From 7ff57f0cb2beadc7c99dc23b65d0e6bd4338fef9 Mon Sep 17 00:00:00 2001 From: chadhouser <119618887+chadhouser@users.noreply.github.com> Date: Sun, 20 Sep 2026 08:45:11 -0500 Subject: [PATCH] test(kanban): pin the review handoff of a card assigned to its own reviewer The suite already covers the shape where assignee != reviewer (test_review_handoff_without_live_run_attributes_run_to_implementer). The mirror case -- a card created already assigned to its reviewer -- was the gap. Asserts the honest provenance (no implementer, NULL run profile) and, more to the point, that request_changes refuses instead of routing the rejection back to the reviewer. Fails on the parent commit with implementer='reviewer-a'. Co-Authored-By: Claude Opus 5 --- .../test_kanban_review_lifecycle.py | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/tests/hermes_cli/test_kanban_review_lifecycle.py b/tests/hermes_cli/test_kanban_review_lifecycle.py index 16f42dafeb..29e1f6a3e7 100644 --- a/tests/hermes_cli/test_kanban_review_lifecycle.py +++ b/tests/hermes_cli/test_kanban_review_lifecycle.py @@ -923,6 +923,37 @@ def test_review_handoff_without_live_run_attributes_run_to_implementer(kanban_ho assert _events(conn, tid, kind="review_requested")[0][1]["implementer"] == "worker" +def test_review_handoff_of_card_assigned_to_its_reviewer_records_no_implementer( + kanban_home: Path, +) -> None: + """A card created already assigned to its reviewer has no implementer to + record. Stamping the assignee made the payload read + ``implementer == reviewer``, and ``request_changes`` routes on that field — + so a rejection went back to the profile that wrote the findings. With no + live run and nothing but the reviewer on the row, the honest provenance is + *none*, and the rejection must refuse rather than misroute.""" + with kbc.connect() as conn: + tid = kb.create_task(conn, title="already applied", assignee="reviewer-a") + assert kb.request_review( + conn, tid, summary="review this", reviewer="reviewer-a", + ) is True + + ev = _events(conn, tid, kind="review_requested")[0][1] + assert ev["reviewer"] == "reviewer-a" + assert ev["implementer"] is None + run = conn.execute( + "SELECT profile, outcome FROM task_runs WHERE task_id = ? " + "ORDER BY id DESC LIMIT 1", (tid,), + ).fetchone() + assert (run["outcome"], run["profile"]) == ("review_requested", None) + + claimed = kb.claim_review_task(conn, tid, claimer="reviewer-a") + assert claimed is not None + ok, reason = kb.request_changes(conn, tid, reason="found 3 issues") + assert ok is False + assert "implementer provenance" in (reason or "") + + def test_synthesized_run_for_unassigned_card_keeps_null_profile(kanban_home: Path) -> None: """A transition that does not name an actor still reads the card: an unassigned card's synthesized run carries ``profile=NULL`` (the actor