Skip to content

<!-- Authored per the the-loop:writing skill. -->

Testing plan: the stop gate blocks on a node the work item never entered ​

Derived from bugfix.md and design.md. Planned at test-planning, results recorded at verification. See evidence/verification.md.

What "proved" means here ​

The defect is a wrong block, so both directions have to be pinned.

  • The gate lets a parked item's turn end.
  • It still blocks an item that is at the unmet node, and on a broken node behind a moved pointer.

The ticket's reproduction must be run as the harness runs it: the gate script in a subprocess, invoking the real CLI. It must fail on the unfixed tree (negative control).

Test matrix ​

#TypeApplies?Scope / what it provesWhere it runs
T1Unit (blocking_node)yespointer behind the derived position → no block; pointer at it → block; pointer ahead of a broken node → blocks on that node; wait before the pointer → no block; empty/None/unknown pointer → inconclusive; currentNode ""/None/unknown → inconclusive with and without a pointer; issue-238's position-unknown answer → inconclusive (R1, R2)tests/test_harness_gate.py
T2Unit (old CLI)yesa report with no pointer key keeps the pre-change behaviour: every existing blocking_node/main test unchanged and green (R2.3)tests/test_harness_gate.py
T3Integration (report)yesa real checkout: pointer in both modes, "" with no state file, derived currentNode unchanged; issue-238's answer keeps six keys; the key pin moves by one (R3.1, R3.2, R3.4)tests/test_gate_pointer_integration.py, tests/test_core_graphs.py
T4Integration (gate on a real report)yesthe ticket's state on the shipped graph → no block; the same item at design → block naming design.md; pointer at implementation → blocks on design (R1)tests/test_gate_pointer_integration.py
T5Integration (CLI table)yescheck --recompute names the pointer when it differs; not when it agrees; nothing changes without --recompute (R3.3)tests/test_gate_pointer_integration.py
T6End-to-end (stop hook)yesthe gate script as a subprocess against the real CLI on PATH, service routing off: the ticket's state exits 0; the item at design exits 2 with design.md in stderrtests/test_gate_pointer_integration.py
T7Negative controlyesT1, T3–T6 on the unfixed source (tests kept, source stashed): the new cases fail, T6's reproduction among themthe three modules
T8Manual reproductionyesthe bugfix's console session before and after the fixa scratch checkout
T9Regression (full suite)yesgreen from cli/, CI's commandmake test
T10Static (lint, format, types, markdown, config)yesgreenmake lint format-check typecheck validate
T11Contract (OpenAPI)yesthe served surface still equals the authored contract; only a description changedtests/test_api_contract_parity.py (inside T9)
T12Performancen/a: one list comprehension over ~20 nodes per stop
T13UI / visualn/a: nothing rendered by the UI changes

Scenarios & requirement trace ​

RequirementRows
R1.1–R1.3T1, T4, T6
R2.1–R2.3T1, T2
R3.1–R3.4T3, T5, T11

Verification environment ​

  • Python 3.11, uv 0.12, dependencies from uv sync against the committed uv.lock.
  • THE_LOOP_SERVICE_LOCAL=1 for every CLI invocation under test (the suite's autouse fixture; set explicitly for T6's subprocess), so no control-plane service starts.

Activities ​

  • [x] T8 — reproduce on the unfixed tree
  • [x] T7 — negative control
  • [x] T1–T6 — targeted modules
  • [x] T9 — full suite from cli/
  • [x] T10 — static checks
  • [x] T8 — reproduction after the fix

Released under the MIT License.