feat(gateway): restore Gate Set E submit-qa field-level gates

i_am_done now strictly enforces the four pre-gateway field-level gates
restored from roboco/api/routes/tasks.py:903-940 at commit 254cc93:

- NOT_SELF_VERIFIED: task.self_verified must be true.
- NO_COMMITS: task.commits must be non-empty.
- NO_PR: task.pr_number must be set.
- NO_PROGRESS: task.progress_updates must have at least one entry.

Each missing field surfaces as a tracing_gap with the matching pre-
gateway error code in the missing list, and a remediation hint that
tells the dev exactly what to do.

The previous silent-catch-up behavior is preserved as a separate
opt-in verb i_am_done_with_catchup. Existing tests that asserted the
catch-up behavior have been migrated to the new verb.

This fixes the failure mode where a dev could call i_am_done with no
commits and the gateway would silently try to push nothing, open an
empty PR, etc. — now the dev sees an explicit error.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Renn F
2026-05-03 03:34:57 +02:00
co-authored by Claude Opus 4.7
parent 855cd24477
commit 4cb47afdb2
4 changed files with 399 additions and 15 deletions
@@ -73,7 +73,8 @@ async def test_i_am_done_reassigns_task_to_qa_agent() -> None:
acceptance_criteria_status=[
{"criterion": "AC1", "referencing_artifact_id": "c1"}
],
commits=[],
# Gate Set E requires non-empty commits before submit_qa.
commits=[{"sha": "abc"}],
documents=[],
dev_notes="",
)
@@ -124,7 +125,8 @@ async def test_i_am_done_skips_reassign_when_no_qa_agent() -> None:
progress_updates=[{"message": "p"}],
acceptance_criteria=[],
acceptance_criteria_status=[],
commits=[],
# Gate Set E requires non-empty commits before submit_qa.
commits=[{"sha": "abc"}],
documents=[],
dev_notes="",
)