mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
fix(api): require substantive audit notes on human task-decision endpoints
Audit/tracing rule: every human decision must record its rationale. These panel-facing routes accepted empty/absent notes, leaving no trail: - docs-complete: now requires notes (>=20) — what was documented - submit-pm-review: now requires notes (>=20) — what is ready for review - complete: now requires justification (>=20) — why the task is done Mirrors the existing pass-qa / ceo-approve notes gates (checked after the 404/403 so not-found and forbidden still take precedence). submit-qa is left as-is: it already gates on commits + PR + progress_updates + self_verified, and the panel collects no extra note there to drop. Tests updated to send notes; added complete-without-justification reject.
This commit is contained in:
@@ -2209,6 +2209,7 @@ async def test_submit_pm_review_service_returns_none(task_client: dict) -> None:
|
||||
mock_factory.return_value = instance
|
||||
response = await task_client["client"].post(
|
||||
f"/api/tasks/{task.id}/submit-pm-review",
|
||||
json={"notes": "Ready for PM review — all criteria met."},
|
||||
headers=_HDR,
|
||||
)
|
||||
assert response.status_code == HTTPStatus.BAD_REQUEST
|
||||
@@ -2230,12 +2231,29 @@ async def test_complete_task_success(task_client: dict) -> None:
|
||||
mock_factory.return_value = instance
|
||||
response = await task_client["client"].post(
|
||||
f"/api/tasks/{task.id}/complete",
|
||||
json={"force_with_cancelled": False},
|
||||
json={
|
||||
"force_with_cancelled": False,
|
||||
"justification": "All acceptance criteria met; merging.",
|
||||
},
|
||||
headers=_HDR,
|
||||
)
|
||||
assert response.status_code == HTTPStatus.OK
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_complete_without_justification_rejected(task_client: dict) -> None:
|
||||
"""Audit: completing a task must carry its rationale (>= 20 chars)."""
|
||||
task = _seed_task(task_client)
|
||||
await task_client["db"].flush()
|
||||
response = await task_client["client"].post(
|
||||
f"/api/tasks/{task.id}/complete",
|
||||
json={"force_with_cancelled": False},
|
||||
headers=_HDR,
|
||||
)
|
||||
assert response.status_code == HTTPStatus.BAD_REQUEST
|
||||
assert "JUSTIFICATION_REQUIRED" in response.json()["detail"]
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# cancel: service returns None branch (1162-1167)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user