Skip to content

Testing plan: an opt-in critic review of the locked design

Derived from the approved requirements.md and design.md. Authored at test-planning, completed at verification.

Test matrix

#TypeApplies?Scope / what it provesWhere it runs
T1Unityescompile-time vocabulary (optIn parsed, required×optIn refused, an opt-in skipSets member refused, the implied skippable edge requirement), checklist rendering, reply parsing (ticked / unticked / absent), the runtime default, the not selected provenance line, state round-tripuv run pytest cli/tests/test_graph_skips.py cli/tests/test_graph_model.py cli/tests/test_graph_state.py
T2Integration (scenario)yesa work item walking the miniature loop end to end both ways — selected (the node is entered and gates its section) and not selected (the pointer routes design → test-planning with no hooks run), plus the shipped outer loop's own shapeuv run pytest cli/tests/test_graph_skips.py -k opt_in
T3Contract (OpenAPI / GraphQL SDL)n/a — the control-plane API gains no endpoint and no field; optIns lives in graph-state.json, which the contract does not describe
T4End-to-endn/a — an end-to-end run needs a live GitHub ticket, an authorized human and a configured critic CLI; the seams that stand in for them (the github integration, _authorized_comments, the critic runner) are covered at T2 and already have their own suites
T5UI / visualn/a — no user-facing surface; the only rendered output is a markdown comment, asserted as text at T1
T6Snapshotn/a — the checklist body is asserted by content, not by golden file; a snapshot would lock wording the writing skill expects to evolve
T7Performance / loadn/a — one extra dict comprehension over a ~20-node graph per read
T8Security / abuse caseyesthe three testable abuse cases in design.md §Security design: unauthorized reply ignored, forged optIns on a non-opt-in node inert, a deleted selection reverting to not selected (never pass)uv run pytest cli/tests/test_graph_skips.py -k "forged_opt_in or deleting_a_selection or unauthorized_reply_never_selects_an_opt_in"
T9Accessibilityn/a — no UI
T10Migration / upgradeyesa pre-issue-188 graph-state.json (no optIns key) loads, defaults to no selection, and leaves an in-flight work item unblockeduv run pytest cli/tests/test_graph_state.py -k "opt_ins or without_opt_ins"
T11Manual exploratoryyesthe-loop check on this repository's own docs/specs/issue-188/, reading the new node's line in the reportuv run the-loop check issue-188
T12Parity (docs ↔ graph ↔ templates)yesthe gated Design critic review section exists in the shipped execution-log.md template (P5c) and the phase sequence still matches both configs (P4)uv run pytest cli/tests/test_graph_parity.py cli/tests/test_docs_parity.py cli/tests/test_writing_parity.py
T13Lint / type checkyesruff, pyright, markdownlint over the changed Python and markdownmake lint typecheck

Scenarios & requirement trace

RowRequirement(s)Scenario / case
T1R1.1, R1.2, R1.3optIn compiles, implies skippable; required×optIn and an opt-in skip-set member both raise GraphConfigError
T1R1.4, R1.5an unselected opt-in node reports skip with not selected, in both check modes
T1R2.1, R2.2the checklist renders opt-in rows unticked, under their own heading, with the node's description
T1R2.3, R2.4ticked → selected; unticked → not selected; absent → not selected
T1R2.5, R2.6the confirmation names selected opt-in phases, or says none were; an untouched selection still runs every default-on phase
T2R3.1, R3.2Scenario: a work item that selects the design critic round walks it between design and test-planning
T2R3.2Scenario: a work item that does not select it routes design straight to test-planning, running none of the node's hooks
T2R3.3Scenario: the design critic node blocks until the execution log's Design critic review section is written
T2R3.6the inner PR loop and the contribution loop declare no opt-in node
T2R1.6, R1.8a selection is recorded with provenance and frozen into the graph record carrying optIn per node
T8R1.7, security AC 1–3unauthorized reply ignored; forged/removed optIns inert
T10NFR backward compatibilitya state file without optIns loads and selects nothing
T12R3.3the gated section exists in the template

Verification environment

  • Repositories: this repository only.
  • Services / containers: none. Every test is a filesystem/in-process read; the github integration is stubbed, as it is throughout cli/tests.
  • Fixtures & data: the miniature graph dict already in cli/tests/test_graph_skips.py, extended with one opt-in node; tmp_path spec folders.
  • Credentials: none — no network call is made.
  • Bring-up: uv sync · Tear-down: none.
  • If bring-up fails: record it under Verification results, leave the dependent activities unticked, and escalate.

Evidence plan

RowEvidencePath under evidence/
T1, T2, T8, T10, T12pytest run output and countstests.md
T13lint + type-check outputlint.md
T11the the-loop check report showing the new node's line, both selected and notwalkthrough.md

Verification activities

  • [x] T1 — uv run pytest cli/tests/test_graph_skips.py cli/tests/test_graph_model.py cli/tests/test_graph_state.py
  • [x] T2 — uv run pytest cli/tests/test_graph_skips.py -k opt_in
  • [x] T8 — uv run pytest cli/tests/test_graph_skips.py -k "forged_opt_in or deleting_a_selection or unauthorized_reply_never_selects_an_opt_in"
  • [x] T10 — uv run pytest cli/tests/test_graph_state.py -k "opt_ins or without_opt_ins"
  • [x] T11 — uv run the-loop check issue-188
  • [x] T12 — uv run pytest cli/tests/test_graph_parity.py cli/tests/test_docs_parity.py cli/tests/test_writing_parity.py
  • [x] T13 — make lint typecheck
  • [x] Full suite — uv run pytest cli/tests

Verification results

Authored empty at test-planning, filled at verification. Counts are from the runs recorded in evidence/, not from this plan.

ActivityCommand / procedureOutcomeEvidence
Red→greennew tests run with the production change stashed, then restoredpass — 19 failed → 19 passedevidence/tests.md
T1uv run pytest cli/tests/test_graph_skips.py cli/tests/test_graph_model.py cli/tests/test_graph_state.pypass — 116 passedevidence/tests.md
T2uv run pytest cli/tests/test_graph_skips.py -k opt_inpass — 15 passedevidence/tests.md
T8uv run pytest cli/tests/test_graph_skips.py -k "forged_opt_in or deleting_a_selection or unauthorized_reply_never_selects_an_opt_in"pass — 3 passedevidence/tests.md
T10uv run pytest cli/tests/test_graph_state.py -k "opt_ins or without_opt_ins"pass — 2 passedevidence/tests.md
T11the-loop graph show, the-loop check on a scratch item with and without the selection, and on this work itempass — reported not selected unselected, gated its section once selectedevidence/walkthrough.md
T12uv run pytest cli/tests/test_graph_parity.py cli/tests/test_docs_parity.py cli/tests/test_writing_parity.pypass — 25 passedevidence/tests.md
T13make lint format-check typecheck validatepass — ruff, markdownlint (501 files), pyright, schema validation all cleanevidence/lint.md
Full suiteuv run pytest cli/testspass — 1650 passed, 1 skippedevidence/tests.md

Not executed: T3–T7 and T9 — marked n/a in the matrix above with their reasons; none was replanned or escalated. The one suite skip (test_instructions.py:149, an unreadable-file case that cannot be staged as root) predates this change and is unrelated to it. The fourth abuse case — a critic's output carrying instructions — is a documented rule in reference/reviewing.md with no code path of its own, so it has no test row.

Review comments

Appended by the-loop's record-feedback hook when a human gate approves with comments.

Released under the MIT License.