Skip to content

Testing plan: a contribution has no outer loop, and its arming comment answers its first gate

Derived from the approved bugfix.md and design.md, before tasks.md — each task's _Test:_ names a row below. Authored at test-planning, completed at verification.

This file is executable content. It names commands an agent will run. No credential appears here, by value or by reference: every test runs offline against a fake GitHub integration and a temporary checkout.

Test matrix

#TypeApplies?Scope / what it provesWhere it runs
T1Unityesthe checklist, the parse, the confirmation and the frozen record for a contribution — and unchanged for the outer loopuv run --project cli python -m pytest -q cli/tests/test_graph_contribution.py
T2Integration (scenario)yesa real GraphLink over a real Runtime and a fake GitHub: on_spawn carries an arming comment's goal to phase-selection; no goal parks; a respawn changes nothinguv run --project cli python -m pytest -q cli/tests/test_graph_contribution.py -k spawn
T3Integration (dispatcher)yesthe spawning RoutedEvent reaches on_spawn, on the shared dispatcher both ingresses useuv run --project cli python -m pytest -q cli/tests/test_graph_drive_integration.py
T4Unit (prompt)yes$graph_context names no outer loop for a contribution, and still places one for every other loop; an agent start node is not evaluated at spawnuv run --project cli python -m pytest -q cli/tests/test_graph_drive.py
T5Contract (OpenAPI)n/a — no API request or response shape changes; graph-state.json keeps its fields and surface keeps its type. test_api_contract_parity.py runs as part of T6 and would catch it if that were wrong.
T6Regression (whole suite)yesthe spawn path now runs an exit chain that never ran before; nothing else may movemake test
T7UI / visualn/a — no rendered UI; the two user-visible surfaces are a comment body and a prompt block, both asserted as text in T1/T4.
T8Snapshotn/a — no serialized artifact whose whole shape is asserted; the frozen record's changed field is asserted by name in T1.
T9Performance / loadn/a — one extra exit-chain evaluation per fresh spawn of a human start node, on a path that has just started a tmux session and an LLM; unmeasurable beside it, and zero for every other spawn.
T10Security / abuse caseyesthe three abuse cases in bugfix.md § Security considerations, each as a negative testuv run --project cli python -m pytest -q cli/tests/test_graph_contribution.py -k unauthorized or surface
T11Accessibilityn/a — no rendered UI.
T12Migration / upgradeyesa work item frozen by 9.6.0 with surface: work-item still reads as before; a contribution written by this version carries "", which every reader already treats as the defaultcovered by T1 and by the pre-existing state round-trip tests in T6
T13Manual exploratoryn/a — the reproduction needs a live daemon, a watched repository and credentials; T2 and T3 reproduce both halves deterministically and offline against the same code paths, which is stronger evidence than one manual run.
T14Lint / typecheck / docs parityyesruff, ruff-format, pyright, config validation, markdownlint and test_docs_parity.pymake check

Scenarios & requirement trace

RowRequirement(s)Scenario / case
T1R1.1the contribution checklist carries no outer-loop-on-pull-request row and says where the conversation happens
T1R1.2the work-item loop's checklist still carries it, worded as before
T1R1.3, R1.4a reply ticking the token on a contribution: pointer advances, state.surface == "", frozen surface == "", no phase declared away, confirmation silent about a surface
T2R2.1a spawn whose arming comment states the goal lands the item at phase-selection, checklist posted, binding recorded
T2R2.2a spawn with no goal parks at goal-definition carrying the gate's own reason
T2R2.3a second on_spawn re-records the binding and leaves every node record untouched, even once the goal has become answerable
T3R2.1the dispatcher hands the spawning RoutedEvent to the graph coupling
T4R1.5a contribution's prompt block says "a contribution has no outer loop" and never "the outer loop's artifacts"
T4R1.2a work item's prompt block still places the outer loop on its chosen surface
T4R2.4an agent start node is entered and not evaluated: not parked, no block recorded, one attempt
T10abuse 1an unauthorized goal in the thread leaves the gate waiting (pre-existing coverage, re-run)
T10abuse 2the injected surface token is inert (same case as T1/R1.3)
T10abuse 3an integration outage during the gate leaves the item waiting, never guessing (pre-existing coverage, re-run)
T6R2.5the whole suite: every other spawn path, every other loop, unchanged
T14R3.1docs parity over the changed CLI page and capability docs

Verification environment

A temporary directory per test (tmp_path) holding docs/specs/issue-9/, the shipped graphs from the package, and a fake GitHub integration injected at the_loop.graph.integrations.resolve. No network, no credentials, no tmux; the dispatcher rows use the suite's FakeTmux and StubInteractiveAdapter.

Verification results

Executed at verification — see evidence/.

#ResultEvidence
T1passevidence/unit.md
T2passevidence/unit.md
T3passevidence/integration.md
T4passevidence/unit.md
T6passevidence/check.md
T10passevidence/unit.md
T12passevidence/unit.md
T14passevidence/check.md

Released under the MIT License.