fix: clear 55 pre-existing test failures uncovered after Wave A landed

Three classes of failure, all surfaced once Wave A's plan-required gate
and the migration 013 went in. Per project standing rule: pre-existing
errors are not a free pass — fix them.

1. Wave A1 ordering (32 lifecycle parity failures + 1 full-pipe test).
   _pm_sub_tasks_gate fired BEFORE _claim_plan_start_gate, so wrong-state
   PMs got `incomplete_input` (the gate's verdict) when the spec's
   lifecycle gate should have returned `invalid_state` first. Swapped:
   re-entry check → spec lifecycle gate → sub_tasks gate → claim_plan_run.
   Parity test now sees the spec's verdict as expected.

2. E2 enum naming (2 migration_013 failures + ripple).
   _str_enum in roboco/db/tables.py didn't pass name=… to SQLAlchemy
   Enum(...), so Base.metadata.create_all in test setup inferred
   `role` from the Python class `Role` while the alembic migrations
   declare `agentrole`. Tests saw two enums for the same class and
   hit `agentrole = role` operator errors. Fixed: default name to
   lower(class_name) (matches every migration), override `Role` →
   `agentrole`. One dict entry; no class-by-class registration needed.

3. _MockContentActions.note() signature drift.
   Wave 2 G4 added `structured` kwarg to ContentActions.note().
   The integration mock at tests/integration/v2/test_full_pending_to_completed.py
   didn't accept the new kwarg → 1 test failed on the very first call
   from the v2 do/note route. Added `structured: object = None` and
   left it unused (the test asserts lifecycle, not journal rendering).

Plus three ruff E501 line-length fixes in the test files I touched.

Quality: ruff + mypy clean. pytest 6690 passed / 0 failed / 274 skipped.
This commit is contained in:
Renn F
2026-05-12 04:22:03 +02:00
parent f680db34c6
commit ce92829385
5 changed files with 60 additions and 13 deletions
@@ -173,11 +173,16 @@ class _MockContentActions:
text: object,
scope: str = "note",
task_id: object = None,
structured: object = None,
) -> Envelope:
# `structured` mirrors the Wave 2 G4 production signature (panel
# decision/reflect fields). The mock ignores it — the test asserts
# lifecycle transitions, not journal-entry rendering.
_ = agent_id
_ = text
_ = scope
_ = task_id
_ = structured
return Envelope.ok(status="noted", task_id=None, next="continue")
@@ -218,7 +218,9 @@ async def test_i_will_plan_rejects_non_pending_state() -> None:
pm_id = uuid4()
task_id = uuid4()
task_svc = AsyncMock()
task_svc.get.return_value = MagicMock(id=task_id, status="in_progress", assigned_to=uuid4())
task_svc.get.return_value = MagicMock(
id=task_id, status="in_progress", assigned_to=uuid4()
)
task_svc.agent_for.return_value = MagicMock(role="cell_pm", team="backend")
deps = _make_deps(task=task_svc)
c = Choreographer(deps)
@@ -392,8 +394,13 @@ async def test_i_will_plan_idempotent_when_already_in_progress_for_caller() -> N
task_id,
plan="re-entry plan",
rich_plan={
"approach": "Idempotent re-entry: task already in progress, refresh heartbeat.",
"sub_tasks": [{"title": "Re-entry subtask", "description": "Resume work"}],
"approach": (
"Idempotent re-entry: task already in progress, "
"refresh heartbeat."
),
"sub_tasks": [
{"title": "Re-entry subtask", "description": "Resume work"}
],
},
)
@@ -451,8 +458,13 @@ async def test_i_will_plan_recovery_when_already_claimed_for_caller() -> None:
task_id,
plan="re-entry plan",
rich_plan={
"approach": "Recovery re-entry: task claimed but not started; run set_plan + start.",
"sub_tasks": [{"title": "Recovery subtask", "description": "Resume from claimed"}],
"approach": (
"Recovery re-entry: task claimed but not started; "
"run set_plan + start."
),
"sub_tasks": [
{"title": "Recovery subtask", "description": "Resume from claimed"}
],
},
)
+2 -1
View File
@@ -286,7 +286,8 @@ async def test_note_reflect_missing_required_fields_returns_incomplete_input() -
body = env.as_dict()
assert body["error"] == "incomplete_input"
assert {"what_done", "what_learned", "what_struggled"}.issubset(set(body["missing"]))
missing = set(body["missing"])
assert {"what_done", "what_learned", "what_struggled"}.issubset(missing)
journal_svc.write_entry.assert_not_awaited()