Section 06 — Autonomous-Execution Engine
Cites §01 north star (invariants 1, 6, 7, 8, 14, 16, 18); grounded in Pass 1D + Pass 2 (consolidation map + 7 risks). One group, flat capability nodes (refinement 6 — avoids the second-system monolith while honoring “one engine designed once”).
Intelligence Reconnaissance
Run 2026-05-28:
scripts/intel-query.sh dag-ascii scripts-first-restructure— §06 linear-walk position: §05 → §06 → §07. Per INV-19 (Strict-Linear-Single-Branch DAG — every node has exactly ONE predecessor;references/restructure-charter-seed.md §2 INV-19), §06’sdepends_onis narrowed to the SOLE DIRECT predecessor["05"]; §03 + §03A are TRANSITIVE predecessors (they precede §05 in the linear chain — §03/§03A → §04 → §05 → §06 per [ori:plans/scripts-first-restructure/00-overview.md:110]) and are reachable through §05, never listed as direct edges (a multi-entrydepends_onwould declare a non-single-predecessor shape INV-19 rejects). §03/§03A/§05 are allstatus: complete(§05 alsoreviewed: true) per their frontmatter SSOTs, so the transitive chain is satisfied. §03A is the substrate-verification close-out gate §06.4 leans on (it verified the §03.1completion.gates_verifiedschema); that dependency is honored transitively through §05 (a §05-complete state implies §03A-complete by the linear chain), NOT via a direct03Aedge.scripts/intel-query.sh plan-status scripts-first-restructure— §03/§03A/§05status: complete; §06in-review; §07-§12not-started(§06 feeds §12 soak, never gates on it) per [ori:plans/scripts-first-restructure/index.md].rules.HaltReasonenum (direct file citation — wrapper Python is not reliably indexed in the intel graph, so this bullet anchors on the source file, not afile-symbolsquery) is the SSOT §06.1halt_reasons.pyre-exports + partitions (no duplicate enum) atscripts/plan_orchestrator/rules.py(theHaltReasonenum definition).CANONICAL_EXIT_REASONS+EXIT_REASON_ROUTINGclosed-enum SSOT (direct file citation) §06.3 route_walk anchors exit_reason→next_action parity on atscripts/plan_corpus/exit_reasons.py; thegate_internal_errorrouting row reconciled by §06.1 lives atscripts/plan_corpus/exit_reasons.py:604.- target-self + redispatch cure shapes §06.2 consolidates (direct file citation):
scripts/plan_orchestrator/autopilot_auto_cure.pydefines the cure shapes; the_compose_resume_bashargv splitters to collapse live there + in thelinear_execution/review_blockeddispatch siblings underscripts/plan_orchestrator/. STRUCTURE:invariant-acceptance-hook-missingdetector §06.4 CONSUMES (never re-authors) (direct file citation) atscripts/plan_corpus/cross_section_check.py.scripts/intel-query.sh bugs-for plans/scripts-first-restructure— no open blockers; 12 BUG-07-NNN absorbed-via-§06 entries closedobepointing here per [ori:bug-tracker/closed-bugs.json].
Results summary: §06 sits at the §05 → §06 → §07 boundary with all three predecessors (§03, §03A, §05) at status: complete per their frontmatter SSOTs (§05 also reviewed: true); rules.HaltReason + CANONICAL_EXIT_REASONS are the two closed-enum SSOTs the engine re-exports and partitions (never duplicates); the §03/§03A substrate parser SSOT (migrations/006_md_to_json.py:build_plan_json_from_dir) is the parse surface route_walk REUSES (never re-implements); the cure argv-splitter duplication spans autopilot_auto_cure + linear_execution + review_blocked dispatch (all collapse into §06.2’s single compose_resume_bash); cross_section_check.py already exists and is consumed (not authored) by §06.4 and §12.1.
Node-grouping — five capability nodes in one section (size-cap reconciliation)
plan-audit.py SIZE_VIOLATION flags §06 at 40 top-level items (cap 20). This packing is DELIBERATE and is NOT promoted to sibling sections, per the following reconciliation:
- The mission demands ONE autonomous-execution engine GROUP “designed once” (refinement 6 + Mission Success Criteria §06 row). Promoting 06.1/06.2/06.3 to sibling sections would fracture the single-group framing into the second-system multi-section sprawl the refinement explicitly guards against.
- The five capability nodes FAIL the
routing.md §4independence test: they do NOT have independent deliverables completable cold.cure_dispatch.py(06.2) imports thehalt_reasons.py(06.1) partition;route_walk.py(06.3) is the SOLE caller of both gates + serve_next + cure_dispatch; review-as-phase (06.4) is invoked by route_walk as the completion choke point; path-scoped-commit + soak (06.5) consume route_walk’s exit states. They share ONE locked module boundary (scripts/plan_orchestrator/engine surface) and ONE composite deliverable (the zero-halt autonomous engine). A session cannot pick up 06.2 without 06.1’s enum landed first. - The flat-node model groups these as ONE
group: architecturalengine node-cluster (perrouting.md §1flat-node group-label projection); thegrouplabel NEVER determines section boundaries — the engine is one cohesive unit whose subsections are sequencing steps, not independently-workable siblings. - Size discipline is honored by the per-capability acceptance-test table (§06.N) which caps each node’s verification surface; the body density is the cohesion the “one engine” mission requires, not unmanaged sprawl.
Goal
See frontmatter goal.
§26/27/28/31/32/34/36= cross-plan refs to the SUBJECT plan’s on-disksection-26-*.md…section-36-*.md, NOT same-plan subsections of this restructure plan.- Zero-halt:
cure_dispatchresolves every curable halt inline; only genuine + user-decision halts survive. - Status SSOT: this section’s frontmatter
status: in-reviewis canonical. The orchestrator API view (audit_api_view.md) may resolve a staleapi_status: in-progressfrom a prior routing-layer projection; the.mdfrontmatter wins per state-discipline.md §1, and the routing layer re-syncs from frontmatter on the next plan-corpus pass. Thein-reviewstate is the legitimate §03/§05-satisfied re-entry recorded in 00-overview HISTORY (2026-05-28), not in-progress execution work.
06.1 — halt_reasons.py
- Author
scripts/plan_orchestrator/halt_reasons.py(ABSENT today per Pass 1D/Pass 2). Re-exportrules.HaltReason(no duplication). Categorize:CURABLE= {PLAN_SCOPE_DEADLOCK, SCHEMA_INVALID, AUTOPILOT_BLOCKED, TARGET_SELF_DRIFT, PIVOT_CHAIN_TARGET_SELF, REVIEW_PLAN_REDISPATCH_LOOP, LINEAR_EXECUTION_BLOCKED, REVIEW_BLOCKED_NO_BUG_POINTER} (each a distinctrules.HaltReasonmember — no conflation;LINEAR_EXECUTION_BLOCKEDandREVIEW_BLOCKED_NO_BUG_POINTERare CURABLE because both have LIVE auto-cure dispatchers inscripts/plan_orchestrator/today —linear_execution_cure_dispatchandreview_blocked_cure_dispatchrespectively, consolidated into §06.2’s single registry — so a member with a live auto-cure dispatcher MUST land in CURABLE, never GENUINE);GENUINE= the remaining halt-only members (derived asset(rules.HaltReason) - CURABLE - USER_DECISION - {RESIDUAL_AUTO_ACKNOWLEDGED}, NOT a hard-coded count);USER_DECISION= {drift_cure_required_user_decision}. - Enum-vs-string partition authority (cc-user-decision-enum-vs-string —
drift_cure_required_user_decisionis a string-keyed halt atscripts/plan_orchestrator/auto_cure_loop.py:73, NOT arules.HaltReasonenum member, yet it sits in this same 06.1 categorization block as the enum-derived sets): the CURABLE/GENUINE/USER_DECISION/QUARANTINE partition declared in this subsection applies torules.HaltReasonENUM MEMBERS ONLY. String-keyed halts that never become enum members (drift_cure_required_user_decision, the commit_push halt strings, the non-enum orchestrator halt stringsgate_internal_error/drift_cure_residual_auto_acknowledged) are partitioned by the SEPARATEHALT_STRING_SOURCESproducer-SSOT mechanism (next checkbox below) —test_halt_reason_partition_exhaustiveiterates ONLYrules.HaltReason(enum) andtest_halt_string_partition_exhaustiveiterates ONLY theHALT_STRING_SOURCESstrings; the two tests are disjoint and jointly exhaustive.drift_cure_required_user_decisionis therefore authoritatively categorized byHALT_STRING_SOURCES(USER_DECISION disposition) — it is referenced in the USER_DECISION set above for readability but its partition membership is OWNED by the string mechanism, never the enum iteration. Acceptance:test_user_decision_string_partition_owner(intests/test_halt_reasons.py) assertsdrift_cure_required_user_decisionis enumerated byHALT_STRING_SOURCES(not byset(rules.HaltReason)) and lands in USER_DECISION via the string mechanism, so the two partition surfaces never both claim it. - Each GENUINE member declares an
autopilot_disposition∈ {log_and_continue,quarantine,structured_exit} (per skill-control-contract.md §Autopilot Mode); the registry rejects a GENUINE member with no disposition. Acceptance:test_halt_reason_partition_exhaustive(inscripts/plan_orchestrator/tests/test_halt_reasons.py) iteratesrules.HaltReasonand asserts every member is in exactly one of CURABLE/GENUINE/USER_DECISION/QUARANTINE or is the documented RESIDUAL_AUTO_ACKNOWLEDGED continuation, and that every GENUINE member has a disposition — so a new HaltReason member breaks the test until categorized. - Non-enum halt-string partition coverage (codex+opencode CONVERGENT —
enum-iteration alone leaves the string-keyed halts untested): the categorization inhalt_reasons.pyMUST cover BOTH therules.HaltReasonenum members AND the string-keyed halts that never become enum members — the commit_push halt strings (test_all_fail,extended_check_fail,messages_invalid,diff_digest_mismatch,push_rejected_non_ff,push_network_failure,authorized_writes_violation,banned_commit_msg,dirty_after_commit,auth_requiredperscripts/commit_push/rules.py/.claude/rules/commit-push-rules.json) and the non-enum orchestrator halt strings (drift_cure_required_user_decision,gate_internal_error,drift_cure_residual_auto_acknowledged).halt_reasons.pyexposes aHALT_STRING_SOURCESproducer-SSOT tuple naming each string source so the test enumerates from the source, never a hard-coded list. Each named producer MUST expose a concrete programmatic enumeration API the test iterates (no string literals copied into the test): (1) the commit-push halt SSOT.claude/rules/commit-push-rules.json(loaded viascripts/commit_push/rules.py) exposesCOMMIT_PUSH_HALT_STRINGS: frozenset[str]derived from the JSONhalt_reasonskeys, NOT a re-typed literal set; (2)scripts/plan_orchestrator/auto_cure_loop.pyexposesAUTO_CURE_LOOP_HALT_STRINGS: frozenset[str]coveringdrift_cure_required_user_decision(today an inline string atauto_cure_loop.py:73); (3)scripts/plan_corpus/invariant_gate.pyexposesINVARIANT_GATE_HALT_STRINGS: frozenset[str]coveringgate_internal_error;drift_cure_residual_auto_acknowledgedis derived fromLoopExitReason.RESIDUAL_AUTO_ACKNOWLEDGED.value(scripts/plan_orchestrator/auto_cure_loop.py), never a copied literal.HALT_STRING_SOURCES = (COMMIT_PUSH_HALT_STRINGS, AUTO_CURE_LOOP_HALT_STRINGS, INVARIANT_GATE_HALT_STRINGS, ...)is the union the test walks. Partition coverage extends to EVERY halt-class exit reason inscripts/plan_corpus/exit_reasons.py CANONICAL_EXIT_REASONSwhoseEXIT_REASON_ROUTINGrow is a halt-class disposition, so an un-categorized external-skill halt string cannot bypass the partition test. Acceptance:test_halt_string_partition_exhaustive(inscripts/plan_orchestrator/tests/test_halt_reasons.py) enumerates EVERY string from eachHALT_STRING_SOURCESproducer API + EVERY halt-classCANONICAL_EXIT_REASONSmember and asserts each lands in exactly ONEhalt_reasons.pydisposition set (CURABLE / GENUINE / USER_DECISION / QUARANTINE) or the documented RESIDUAL_AUTO_ACKNOWLEDGED continuation — a newly-added commit_push halt string, orchestrator halt string, or halt-class exit reason fails the test until categorized; the paired NEGATIVEtest_halt_string_sources_are_programmaticasserts each producer API is sourced (afrozensetderived from its producer module), never a hard-coded literal copied intohalt_reasons.py, closing the gap wheretest_halt_reason_partition_exhaustive(enum-only) silently skips string-keyed halts. - Document
RESIDUAL_AUTO_ACKNOWLEDGEDas a CONTINUATION signal, NOT a halt (Pass 2 risk 7.7) — exclude from CURABLE/GENUINE. -
gate_internal_errorcarve-out (reconciles GENUINE with zero-halt INV-7):gate_internal_error(perscripts/plan_corpus/invariant_gate.py—CLINormalizationError→ exit 3 /halt_reason: gate_internal_error) is a GENUINE halt and IS the documented zero-halt carve-out. Zero-halt (INV-7) bans halts for ROUTABLE conditions (a blocked node, a curable drift, a completion-claim discrepancy) — every such condition becomes a cure or a quarantine.gate_internal_erroris NOT a routable plan-state condition: it signals the gate harness itself malfunctioned (a normalization crash, a corrupt invariant spec), so the engine has no trustworthy route to compute. It carriesautopilot_disposition: structured_exit— the engine emits exit state for the caller orchestrator (never an interactive prompt, neveraction: haltmid-walk for a plan-state reason), and the malfunction is recorded to active-plan HISTORY. Acceptance:test_gate_internal_error_is_genuine_carveoutassertsgate_internal_error ∈ GENUINE, carriesautopilot_disposition: structured_exit, and is the ONLY GENUINE member whose trigger is harness-malfunction rather than plan-state; the test documents that this is the single zero-halt carve-out so INV-7 stays “zero halts for routable plan-state conditions” exactly. -
gate_internal_errorproducer-vs-engine routing reconciliation (ar-gate-internal-error-conflict —scripts/plan_corpus/exit_reasons.py:604routesgate_internal_errorwithcaller_action: halt_and_report, a CONCRETE contradiction with this section’sautopilot_disposition: structured_exit): updatescripts/plan_corpus/exit_reasons.pyso thegate_internal_errorEXIT_REASON_ROUTINGrow carriescaller_action: structured_exit(the disposition the engine requires for autopilot zero-halt), replacinghalt_and_report— the routing table is the SSOT and MUST agree withhalt_reasons.py, never diverge.halt_and_reportwas the interactive-mode shape;structured_exitsubsumes it (the caller orchestrator decides whether to report-to-user in interactive mode or log-and-route in autopilot, per skill-control-contract.md §Autopilot Mode). The engine does NOT override the routing table at runtime — both surfaces are reconciled tostructured_exitat the source so there is ONE authority. Acceptance:test_gate_internal_error_routing_reconciled(inscripts/plan_corpus/tests/test_exit_reasons.py) assertsEXIT_REASON_ROUTING["gate_internal_error"]["caller_action"] == "structured_exit"AND a cross-checktest_gate_internal_error_disposition_matches_routing(intests/test_halt_reasons.py) assertshalt_reasons.py’sgate_internal_errorautopilot_dispositionequals theexit_reasons.pycaller_action— so a future edit to either surface that re-diverges them fails the test. - INV-17 (per
decisions/01-completion-integrity-invariants.md): add a NEVER-CURABLE membercompletion_claim_unverifiedtorules.HaltReasonatscripts/plan_orchestrator/rules.py(mirroring thecompletion_verification_exhausted/soak_nonconvergenceenum additions below —test_halt_reason_partition_exhaustiveiteratesrules.HaltReasonand asserts QUARANTINE coverage, so the class MUST be an enum member) — a node derivingdonewhose deliverable-existence verification fails. Make it a FOURTH partition setQUARANTINE(alongside CURABLE / GENUINE / USER_DECISION) so the exhaustive partition is closed over it: it is NOT in CURABLE (never auto_script/llm_bounded-acknowledged) and NOT a GENUINE halt;QUARANTINEmembers route to the §06.4 relocate-back-to-not-done path (NOTaction: halt), reconciling zero-halt with verification.test_halt_reason_partition_exhaustive(line above) asserts every member lands in exactly one of CURABLE/GENUINE/USER_DECISION/QUARANTINE (or RESIDUAL_AUTO_ACKNOWLEDGED continuation) —completion_claim_unverifiedis the QUARANTINE member, so it can no longer sit outside the declared partition.cure_dispatchMUST NOT have ANY handler that resolves a QUARANTINE member by refreshing a hash, acknowledging the claim, or any auto_script/llm_bounded path. Acceptance:test_completion_claim_unverified_is_quarantine_never_cured(intests/test_halt_reasons.py) assertscompletion_claim_unverified ∈ QUARANTINE, is in NO other set, and thatcure_dispatch.dispatch("completion_claim_unverified", ctx)returns arelocate/quarantineCureResultwith NO hash-refresh or claim-acknowledgment action (paired with §06.2test_cure_dispatch_no_completion_claim_handler). - Fold the commit_push halt strings (test_all_fail, extended_check_fail, …) into the categorization.
- Add the GENUINE member
completion_verification_exhaustedtorules.HaltReason(the §06.4 quarantine-retry-cap escalation target) withautopilot_disposition: log_and_continue; it is the only halt that the §06.4 choke point may escalate to, and it is in GENUINE (never CURABLE — a node that fails verification N times is not auto-cured). Because route_walk emits it as an exit_reason, it is ALSO registered inscripts/plan_corpus/exit_reasons.pyCANONICAL_EXIT_REASONS+ anEXIT_REASON_ROUTINGrow (mirroring theno_cross_plan_ready_noderegistration) so the §06.3test_route_walk_exit_reason_paritysubset check passes; acceptancetest_completion_verification_exhausted_registered(scripts/plan_corpus/tests/test_exit_reasons.py) asserts the member is inCANONICAL_EXIT_REASONSwith its routing row. - Add the GENUINE member
soak_nonconvergencetorules.HaltReason(the §06.5 soak-node true-non-convergence target) withautopilot_disposition: structured_exit; it is in GENUINE (never CURABLE — a genuinely non-converging route has no trustworthy auto-cure), and its disposition isstructured_exitso the engine emits exit state for the caller orchestrator + records the non-convergence fingerprint to active-plan HISTORY, never an interactive prompt in autopilot. Itsautopilot_dispositionparity is asserted bytest_soak_nonconvergence_autopilot_disposition(§06.5) and by the §06.1test_halt_reason_partition_exhaustive(every GENUINE member carries a disposition). Because route_walk emits it as an exit_reason, it is ALSO registered inscripts/plan_corpus/exit_reasons.pyCANONICAL_EXIT_REASONS+ anEXIT_REASON_ROUTINGrow (mirroring theno_cross_plan_ready_noderegistration) so the §06.3test_route_walk_exit_reason_paritysubset check passes; acceptancetest_soak_nonconvergence_registered(scripts/plan_corpus/tests/test_exit_reasons.py) asserts the member is inCANONICAL_EXIT_REASONSwith its routing row. - Subsection close (06.1) — all
[x];status: complete.
06.2 — cure_dispatch.py (consolidation)
- Author
scripts/plan_orchestrator/cure_dispatch.py(ABSENT today). Single registry:dispatch(halt_reason, ctx) -> CureResult. Consolidate per the Pass 2 §6 map:deadlock_cure_dispatch,schema_cure_dispatch,autopilot_auto_cure(target-self + redispatch shapes),auto_cure.execute_cures(drift SCRIPT_AUTO),auto_cure_loopLLM path, materiality,linear_execution_cure_dispatch,review_blocked_cure_dispatch. The consolidation MUST be EXHAUSTIVE:linear_execution_cure_dispatch+review_blocked_cure_dispatchcarry an identical_compose_resume_bashargv-splitter to the three already named — leaving any of them on disk after this node closes isLEAK:algorithmic-duplication(the single-registry design is violated by a surviving sibling splitter). Acceptance:test_cure_dispatch_no_residual_splitterasserts that after consolidation NO module underscripts/plan_orchestrator/defines a_compose_resume_bash/compose_resume_bashother than the one shared util incure_dispatch.py(grep-equivalent AST scan over the engine surface), so a re-introduced duplicate fails the test. - Extract ONE shared
compose_resume_bash(argv, inject_flags, strip_flags)util (Pass 2 risk 7.1/7.8 — three divergent argv-splitters today). Test matrix: no prior flags / one prior flag / stacked duplicates. - Preserve per-cure acknowledgment paths as first-class registry fields (Pass 2 risk 7.2 — drift-hash vs prior_schema_blocking.json vs cure_applied.json are NOT uniform). Carry
cap_exceeded+ fullaudit_resultin the cure context (risks 7.3/7.4). ConsumeDRIFT_CLASSESby reference, never re-register (risk 7.6). - Pin
halt_history.pyowner (cross-cutting cc-compose-resume-bash-shared-util / Pass 2 risk 7.5 — placement was undecided):halt_history.pylives atscripts/plan_orchestrator/halt_history.py(the orchestrator engine surface — it is cross-session halt-convergence state the §06.5 soak node consumes, NOT a commit_push-domain concern). It exposes a READ-ONLY query interface (query_recent_halts(node_id, window),convergence_signal(node_id)) and is written ONLY by the route_walk halt-recording path. It MUST NOT import fromscripts/commit_push/or fromscripts/plan_orchestrator/shared/commit-domain modules (avoids the cross-domain coupling risk 7.5). Acceptance:test_halt_history_import_boundary(tests/test_halt_history.py) — AST/import scan assertshalt_history.pyimports NOscripts.commit_push.*symbol and exposes the query interface; a re-introduced commit_push coupling fails the test (LEAK:scattered-knowledge). - Engine NEVER emits
action: haltfor a CURABLE reason; GENUINE → surface via the member’sautopilot_disposition; USER_DECISION → AskUserQuestion in INTERACTIVE mode ONLY. In AUTOPILOT mode (per skill-control-contract.md §Autopilot Mode), a USER_DECISION member NEVER reaches anAskUserQuestion— the engine routes it throughstructured_exit(emit exit state for the caller orchestrator to route) and records the disposition to active-plan HISTORY, never an interactive prompt. Each USER_DECISION member therefore declares BOTH aninteractive_disposition: ask_userAND anautopilot_disposition ∈ {structured_exit, log_and_continue}; the engine selects by execution mode. Acceptance:test_user_decision_no_autopilot_askuser(intests/test_cure_dispatch.py) drives every USER_DECISION member throughdispatch(reason, ctx)withctx.mode == "autopilot"and asserts the returnedCureResultcarries NOAskUserQuestionaction — onlystructured_exitorlog_and_continue— proving zero-halt INV-7 holds in autopilot (a USER_DECISION never blocks the walk on a prompt the autopilot user is not present to answer). - Subsection close (06.2) — all
[x];status: complete.
06.3 — route-walk node
- Author
scripts/plan_orchestrator/route_walk.py: singlenext_actionentry consuming §05 cross-plan merge; sole caller of gates + serve_next + cure_dispatch. Subsumes roadmap.py’s internal step chain. Locked boundary: no other module orchestrates the walk. - roadmap.py → route_walk migration boundary (ar-roadmap-route-walk-migration — route_walk subsumes
scripts/plan_orchestrator/roadmap.py’s step chain but the ~106 import references acrossscripts/plan_orchestrator/cli.py,scripts/review_plan_runtime/review_plan.py, the commit_push dispatch path, and 30+ tests must be re-pointed before roadmap.py can be deleted): §06.3 AUTHORSroute_walk.pyand makes it the SOLE walk orchestrator, but does NOT deleteroadmap.pyat §06 close. A backward-compat SHIM WINDOW precedes deletion: at §06.3 close,roadmap.py’s public entry points (roadmap, the Step-1 resume-pointer +_build_next_unblockedsurface) become THIN DELEGATES that forward toroute_walk.py(no second walk implementation survives —roadmap.pyholds zero orchestration logic, only the delegating signature so existing imports keep resolving). The shim is the SSOT-preserving bridge: one walk implementation (route_walk.py), one set of import names (roadmap.pydelegates) during the migration. Full deletion ofroadmap.py+ re-pointing all ~106 import references toroute_walk.pyis DEFERRED to §11A strip-skills, which owns the orchestrator markdown-walk + dead-import removal sweep (roadmap.pyisscripts/plan_orchestrator/, the CONSUMER/skill side — removed when the skills go v7-only, before §11B strips the plan_corpus parsers); §11A’s deliverable list addsroadmap.pydeletion + import re-point (forward reference — §11A tracks it; §06 close-out does not gate on §11A). Acceptance (§06.3 scope):test_roadmap_delegates_to_route_walk(tests/test_route_walk.py) assertsroadmap.py’s entry point invokesroute_walk.serve_next/the route_walk walk surface and defines NO independent serve_next/step-chain of its own (AST scan — a surviving second walk impl fails the test, LEAK:algorithmic-duplication). §11A-scope deletion is verified by §11A’s dead-import sweep, not a §06 gate. - INV-18 (per
decisions/02-content-as-context-unit.md): thenext_actionpayload hands the LLM the WHOLEbody_refcontent file (inlined content OR its path for a full Read) as the bounded task — NOsection_info-style fragment, summary, or structural slice in the payload. The whole content file is the node’s sole context unit. - exit_reason→next_action parity: route_walk maps EVERY exit_reason it can emit (CURABLE → cure_dispatch re-engage; GENUINE → the member’s
autopilot_dispositionfrom §06.1; USER_DECISION →interactive_disposition: ask_userin interactive mode,autopilot_dispositionfrom §06.2 in autopilot mode — NEVER an AskUserQuestion in autopilot) to a concretenext_action. Acceptance:test_route_walk_exit_reason_parity(inscripts/plan_orchestrator/tests/test_route_walk.py) anchors on the existing closed-enum SSOT —CANONICAL_EXIT_REASONS+EXIT_REASON_ROUTINGinscripts/plan_corpus/exit_reasons.py— and asserts the set of exit_reasons route_walk emits is a subset ofCANONICAL_EXIT_REASONS, with each routed via itsEXIT_REASON_ROUTINGrow, so no exit_reason can reach a caller without a declared next_action (cures the §06.3-re-owns-caller→exit_reason-routing claim covering BUG-07-112). halt_reasons.py (§06.1) adds ONLY cure/disposition metadata ATOP this canonical set — never a duplicate exit_reason authority (avoids LEAK:scattered-knowledge). - INV-19 single-ready-node assertion (per
references/restructure-charter-seed.md §2 INV-19):route_walk.serve_next(plan)MUST return at most ONE ready node per call (the deterministic next-in-lexorank-order unblocked node). Add a runtime assertion + a regression test:assert len(ready_nodes) <= 1, 'INV-19 violation: strict-linear-single-branch DAG cannot have multiple ready nodes'. Multiple-ready-node case is structurally impossible IF the §03.1 schema rejects branch fields; the assertion is defense-in-depth. Acceptance:test_route_walk_single_ready_node(inscripts/plan_orchestrator/tests/test_route_walk.py) constructs a fixture plan and assertsserve_nextnever emits >1 ready node; a synthetic branch-fixture (constructed bypassing the schema) trips the assertion deterministically.serve_nextis deterministic by construction — never a routing choice. - INV-20 serve_next semantics (per
references/restructure-charter-seed.md §2 INV-20):route_walk.serve_next(plan)performs a linear scan in lexorank order; returns the FIRSTnot-startednode whose predecessors are ALLdone(verified viacompletion.gates_verifiednon-empty per §03.1). A predecessor is BLOCKING unless it isdone-with-attestation — bothin-progressANDin-reviewcount as not-yet-done (anin-reviewpredecessor has NOT written itscompletion.gates_verifiedvia the §06.4 choke point, so a successor reaching it would crawl forward past unverified work — the exact INV-20 violation). If the scan encounters a NON-donepredecessor (in-progressORin-review), return THAT node (caller resumes / finishes its review) — NEVER skips past it as an alternative. The §40 relocate primitive handles cases where a section blocks; the engine NEVER uses skip-past-non-done as a substitute. Runtime assertion:assert not (returned_node.status == "not-started" and any(p.status in ("in-progress", "in-review") for p in predecessors(plan, returned_node))). Regression testtest_serve_next_never_skips_in_progress(inscripts/plan_orchestrator/tests/test_route_walk.py) constructs THREE fixtures: (1) predecessorin-progress, successornot-started→serve_nextreturns the predecessor; (2) predecessorin-review, successornot-started→serve_nextreturns the predecessor (in-review is blocking, not skippable); (3) predecessordonewith non-emptygates_verified, successornot-started→serve_nextreturns the successor. - Parser-SSOT reuse: route_walk + serve_next consume the §03/§03A substrate parser SSOT (
scripts/plan_corpus/migrations/006_md_to_json.py:build_plan_json_from_dir+ the §03per_plan_routesurface) for any plan.json/content parse; the engine defines NO second md→dict parser or frontmatter parser. Acceptance:test_route_walk_reuses_parser_ssot(tests/test_route_walk.py) — AST scan overscripts/plan_orchestrator/asserts no siblingbuild_plan_json_from_dir/frontmatter parser; a re-implementation fails (LEAK:algorithmic-duplication). - Output determinism:
route_walk.serve_next+ the emittednext_actionenvelope are byte-identical across repeated runs on unchanged plan.json + git HEAD; inputs are corpus + HEAD only (notime.time()/uuid/random/session-state), mirroringresume_manifestperstate-discipline.md §6.5. Acceptance:test_route_walk_output_determinism(tests/test_route_walk.py) — asserts byte-identical next_action JSON across repeated in-process, in-process-vs-CLI, and fresh-process-vs-continuous-process calls. - Malformed-plan.json error path (fail-loud, never silent-skip): a plan.json failing schema validation raises the typed
schema_invalidhalt_reason (CURABLE → §06.2 schema_cure_dispatch); the engine NEVER silent-skips the malformed plan and NEVER returns a ready node from the corrupt corpus. Acceptance:test_route_walk_malformed_plan_json_raises(tests/test_route_walk.py) — feeds a malformed plan.json fixture; asserts the typed error /schema_invalidcure route, never a ready node. - Engine bootstrap + empty-route / all-blocked exit_reason (architectural-risk ar-no-cross-plan-ready-node-registration + cc-engine-bootstrap-empty-corpus — the §05→§06 handoff yields no ready node when every cross-plan node is blocked/deferred OR the corpus is fully done; route_walk must cold-start, merge, and resolve these terminal states via a canonical exit_reason, never crash or emit a spurious ready node): route_walk’s cold-start path performs (1) first-route discovery (locate the first route plan with a
plan.json), (2) cold-start cross-plan merge (merge all per-plan nodes by the §05(key, plan, id)comparator with no prior session/cache state — determinism pertest_route_walk_output_determinism), and (3) all-nodes-doneterminal resolution. Registerno_cross_plan_ready_nodeinscripts/plan_corpus/exit_reasons.pyCANONICAL_EXIT_REASONS+ add itsEXIT_REASON_ROUTINGrow withcaller_action: log_and_skip,exit_code: 0(a clean terminal state — an empty unblocked frontier is NOT an error, NOT a halt).route_walk.serve_nextemitsno_cross_plan_ready_nodewhen the lexorank scan finds zeronot-startednodes with all-donepredecessors AND no NON-doneblocking predecessor to return (i.e. the corpus is fullydone/abandoned, freshly empty, or every remaining node is cross-plan-deferred). Acceptance:test_no_cross_plan_ready_node_registered(scripts/plan_corpus/tests/test_exit_reasons.py) asserts the reason is inCANONICAL_EXIT_REASONSwith thelog_and_skip/exit_code 0routing row;test_route_walk_empty_corpus_emits_no_ready_node+test_route_walk_all_deferred_emits_no_ready_node(tests/test_route_walk.py) feed (a) an empty corpus (cold-start bootstrap with no nodes) and (b) an all-cross-plan-deferred corpus and assertserve_nextemitsno_cross_plan_ready_node(exit_code 0) and returns NO ready node — never raising, never anaction: halt;test_route_walk_cold_start_first_route_discoveryasserts a cold-start (no cache) discovers the first route plan and merges cross-plan nodes deterministically. - INV-15 separation on resolve: route_walk CONSUMES the §05.3 flat-node
grouplabels (proposal/architectural/phase-local/bug) for filtering/grouping ONLY; ordering comes fromkey, identity fromid, never fromgroup. The engine is a CONSUMER of the §05 route model’s group labels, never an owner of routing status. Acceptance:test_route_walk_preserves_inv15_separation(tests/test_route_walk.py) — asserts serve_next ordering is invariant undergroup-label permutation and no engine path writes agroupvalue as a routing-status field. Perreferences/restructure-charter-seed.md §2 INV-15+ §05.3. - Subsection close (06.3) — all
[x];status: complete.
06.4 — review-as-phase + bugs-as-nodes
- review-as-phase: a node isn’t
doneuntil its review node passes; auto-dispatch reviewers, auto-triage, cure-and-re-engage on findings; review state = routing fields on the node; no human halt (refinement / R6Q22). - INV-17 single verified-completion choke point (per
decisions/01-completion-integrity-invariants.md): review-as-phase is the SOLE writer ofdone. Before flipping a node todoneit runs deliverable-existence verification (declared body_ref/touch paths exist on disk, declared tests pass, nopending-bearing tracking rows) and writes the §03completionattestation (body-bound hash). Verification FAILS CLOSED: on any missing deliverable the node does NOT complete and does NOT halt — it routes toquarantine(relocate back to not-done) + records which criterion failed. No other engine path may writedone. Acceptance:test_verified_completion_choke_point(tests/test_review_phase.py) — asserts only one path writesdone, only post-verification, and a deliverable-absent node routes toquarantinenotdone/halt. - INV-20 sole writer of
completion.gates_verified(perreferences/restructure-charter-seed.md §2 INV-20): review-as-phase is the SOLE writer of thecompletion.gates_verified: [str]array introduced by §03.1. It populates the list with the named-skill gates that ran toexit_reason: cleanfor this section’s code surface (e.g.,tpr-review-code-side,pytest-<suite-name>,plan-corpus-check). Empty list → §03.1 schema rejectsstatus: done(force-flip via legacy paths impossible at write-time). The gate-name set is declared per-section by the section’sgates_required: [str]frontmatter (see §06.4 deliverable-existence verification —gates_requiredis one of the declared criteria); the choke point assertsset(gates_required) ⊆ set(completion.gates_verified)before flippingdone. No cure path, route-walk, or serve_next may writecompletion.gates_verifieddirectly. Acceptance:test_gates_verified_sole_writer(tests/test_review_phase.py) — asserts review-as-phase is the SOLE writer ofcompletion.gates_verifiedand thatgates_required ⊆ gates_verifiedis enforced beforedone. - INV-20
gates_requiredschema owner (blind-spot bs-gates-required-owner — the subset checkgates_required ⊆ gates_verifiedhas no schema-backed owner today): addgates_required: list[str]toscripts/plan_corpus/schemas.py PlanSectionSchema(optional, default[]) as the SOLE schema owner of the per-section required-gate declaration; the field validates as a list of known gate names drawn from the same gate-name vocabularycompletion.gates_verifiedis populated from (tpr-review-code-side,pytest-<suite>,plan-corpus-check, …). An unknown gate name ingates_requiredfails schema validation (schema_invalid→ §06.2 schema_cure_dispatch). The §06.4 choke point readsgates_requiredfrom this validated field — NEVER an ad-hoc inline list. Acceptance:test_gates_required_schema_owner(inscripts/plan_corpus/tests/test_schemas.py) asserts (a) a validgates_requiredlist passes validation, and the NEGATIVE casetest_gates_required_rejects_unknown_gateasserts agates_requiredentry naming an unknown gate raises a schema-validation error — so a typo’d or invented gate name cannot silently weaken the subset check before §06.4 enforcesgates_required ⊆ gates_verified. - Quarantine retry cap (prevents the pick → verify-fail → quarantine → re-pick livelock): the choke point records a
verification_fail_counton the node (in the node’s content tracking, NOT a plan.json field per INV-3). After N consecutive failed verifications of the SAME node (default N=3, declared in the engine config), the node escalates fromquarantine(re-routable) to the GENUINE haltcompletion_verification_exhaustedwithautopilot_disposition: log_and_continue— the node is set aside (route relocates past it per the plan-scoped linear walk, so one stuck node never deadlocks the corpus) and the exhaustion is recorded to active-plan HISTORY. The reset trigger is a CHANGE to the node’s declared deliverable set — NOT merely a markdown-content edit (a content-only edit would miss the CODE deliverables a code-bearing node fails verification on). The choke point computes adeliverable_fingerprint= hash over the (path, mtime) pairs of EVERY declaredtouches:/body_refdeliverable (code files AND content files) EXCLUDING the node’s ownverification_fail_countcontent-tracking file — that file is the engine’s retry-budget bookkeeping, not a deliverable; including it would make every failed-verification write (which bumpsverification_fail_count, changing that file’s mtime) flip the fingerprint and reset the budget to 0 on the very next attempt, a livelock where the retry cap never accumulates. The fingerprint set isset(touches: ∪ body_ref) - {verification_fail_count_tracking_path}.verification_fail_countresets to 0 ONLY when the current fingerprint (over the excluded set) differs from the one stored at the last failed verification. This way editing the CODE that failed verification (not just the tracking markdown, and never the budget file itself) is what re-arms the retry budget. Acceptance:test_quarantine_retry_capasserts the (N+1)th verify-fail escalates and that route_walk relocates past the exhausted node without halting (proving the cap actually accumulates across attempts — the budget file’s own mtime churn does NOT reset it);test_quarantine_reset_on_deliverable_changeasserts that touching a declared CODE deliverable (changing its mtime) resetsverification_fail_countwhile a no-op re-verify with an unchanged fingerprint does NOT reset (so a content-only edit that leaves the failing code untouched does not falsely re-arm); the NEGATIVEtest_quarantine_fingerprint_excludes_budget_fileasserts theverification_fail_counttracking file is NOT in the fingerprint set, so writing it cannot reset the budget. - Invariant-acceptance-hook gate (delivers §01.1 success_criterion #3): as part of the deliverable-existence verification above, the choke point invokes the existing
scripts/plan_corpus/cross_section_check.pySTRUCTURE:invariant-acceptance-hook-missingdetector for the completing node’s owning invariants (per §01.1’s invariant→section(s) table); an unproven acceptance hook FAILS CLOSED identically — node routes toquarantine, neverdone, neveraction: halt(INV-7). This is the mechanized contradiction-check that replaces the human ‘reviewers flag’ backstop. Dependency note: the detector module ALREADY EXISTS atscripts/plan_corpus/cross_section_check.py; §06.4 CONSUMES it (and extends it for any §06.4-specific detector additions per the checkbox below) — it does NOT author a new module. §12.1 soak also CONSUMES the same detector as a corpus-wide invariant-coverage assertion. No backward dependency on §12; the detector exists by the time §06 closes (§06 depends_on [05]; §03 reachable transitively via §05 → §04 → §03A → §03). - Detector authoring-vs-consuming boundary (explicit): §06.4 is the SOLE AUTHOR of any §06.4-specific detector additions to
scripts/plan_corpus/cross_section_check.py(route-node owning-invariant lookups against §01.1’s invariant→section table). §06.4 AUTHORS + REGISTERS these additions BEFORE its choke-point gate CONSUMES them — authoring precedes consumption within this node, no forward dependency. §12.1 soak is AGGREGATE-ONLY: it CONSUMES the detector (already authored + registered by §06.4) as a corpus-wide invariant-coverage assertion and AUTHORS no detector logic of its own. There is NO backward dependency from §06.4 onto §12 (§12depends_on: [..., 06]; a predecessor never consumes a successor’s output). The detector exists by the time §06 closes because §06.4 authored it; §12 only reads it. Acceptance covered bycross_section_check.pyself-test (tests/test_cross_section_check.py); a §12-side aggregate assertion that tried to ADD detector logic would be a §12 scope violation, not a §06.4 gap. - bugs-as-nodes: bug plans (JSON-first via §10) merge into the cross-plan route;
/add-bugmints a node + key; a bug blocking work is ahint_needs;/fix-bugis the walker serving the bug node (R6Q21). - subsumption relationship (per
decisions/03-plan-bug-subsumption-absorption.md, absorbsplan-bug-subsumption): a bug whose fix is a CONSEQUENCE of an umbrella node carries ahint_needson the umbrella and relocates to serve AFTER it (consequence, NOT prerequisite — the inverse of a blocker). When the umbrella reaches the §06.4 verified-completion choke point, deliverable verification runs the bug’sverification_test(reuse INV-17 deliverable-existence machinery): PASS → the bug node completes by construction (its non-reproduction IS its deliverable); FAIL → un-subsume = route the bug node toquarantine(relocate back to active route), never auto-completed, neveraction: halt(zero-halt INV-7). Un-subsume is NOT triggered by umbrellaquarantinealone: an umbrella that quarantines (re-routable, may still re-cure and complete) RETAINS its subsumed bugs’hint_needs— dropping the hint on a transient quarantine would relocate the bug node back to the active route and execute it as an INDEPENDENT incomplete node before the umbrella (its consequence-source) has completed, the premature-execution failure mode. Thehint_needs(serve-after relationship) is removed ONLY on EXPLICIT umbrella ABANDONMENT (the umbrella node is marked abandoned/superseded, never to complete) OR on the bug’s OWN verification-fail at the umbrella’s verified-completion choke point. A quarantined-but-still-live umbrella keeps its subsumed bugs parked behind it. The subsumption claim + 3-signal evidence (replaced_subsystem/root_cause_pointer/verification_test_pointer) are authored in the umbrella node’s content (INV-18) and re-validated at review-as-phase sign-off — never mechanically inferred, never aplan.jsonfield (INV-3). - Subsumed-bug
gates_verifiedexemption (bs-subsumed-bug-gates-verified — INV-20 requires non-emptycompletion.gates_verifiedforstatus: done, but a subsumed bug node completes BY CONSTRUCTION at the umbrella’s choke point where non-reproduction IS the deliverable, so it runs no named-skill gates of its own and would have an emptygates_verifiedthat §03.1 rejects): when the §06.4 choke point completes a subsumed bug node by construction (the umbrella’s deliverable-verification confirmed the bug’sverification_testpasses), it AUTO-POPULATES that bug node’scompletion.gates_verifiedwith the single canonical gate namesubsumption-verified-by-umbrella:<umbrella-id>— a real, schema-known gate-name token (added to thegates_required/gates_verifiedvocabulary in §03.1) recording that the bug’s verification ran AS PART OF the umbrella’s choke point, not as an independent gate run. This keepsgates_verifiednon-empty (INV-20 schema holds — no exemption carve-out that would weaken the impossible-state) while truthfully attributing the verification to the umbrella. review-as-phase remains the SOLE writer of the field (the umbrella’s choke point IS review-as-phase). A subsumed bug node NEVER reachesdonewith an emptygates_verifiedand NEVER reachesdonevia any path other than the umbrella’s choke point. Acceptance:test_subsumed_bug_gates_verified_autopopulated(intests/test_review_phase.py) asserts a completed-by-construction subsumed bug node carriescompletion.gates_verified == ["subsumption-verified-by-umbrella:<umbrella-id>"](non-empty, schema-valid) and that the §06.4 choke point — not serve_next or cure_dispatch — wrote it. - Review-as-phase node loads the relevant /improve-tooling design-log §4 Lessons + §6 Improvement Log (+
list-locked-designsfor touched paths) as a mandatory grounding input before a section’s review can sign off (INV-16); the consultation is recorded on the node, and review cannot reachdonewithout it. - INV-18 content-size gate (per
decisions/02-content-as-context-unit.md): review-as-phase runs the §03 content-size lint; an over-capcontent/<id>--*.mdblocksdoneand routes to a SPLIT cure. The split has TWO separated responsibilities that never blur: (1) the engine/route-API mints sibling flat nodes (new ids + lexorank keys between neighbors) and writesplan.jsonrouting — purely mechanical, no content awareness; (2) the LLM (a bounded route node the engine serves) partitions the over-cap body across the minted siblings at semantic boundaries (never splitting a checklist row or a fenced code block mid-block) and writes ONLY markdown content files — neverplan.json. The engine never mechanically text-splits the body (a byte-offset split would break checklist/code-block boundaries); the LLM never mints nodes or writes routing. Never compaction-into-denser-prose. The split is a routing op handled through §06.2 cure_dispatch (quarantine-adjacent: the node does not reachdonewhile over-cap; the cure is “split,” not “acknowledge”). Acceptance:test_split_cure_responsibility_separationasserts the node-mint path touches onlyplan.jsonand the content-partition task injects only markdown content paths, with no path that both mints a node and authors content. - Subsection close (06.4) — all
[x];status: complete.
06.5 — path-scoped-commit + soak
- path-scoped-commit node: §06.5 owns ONLY the route-side capability interface — the engine’s call contract (
invoke_commit(touches, scope) -> CommitResult) plus an acceptance test that exercises it against a MOCKED commit backend (test_commit_capability_interfaceasserts the engine routes to the commit capability with the node’stouches:scope and consumes the result, with the backend stubbed). The actualcompute_scope_restrictionwiring lives in §07 (whichdepends_on: [06]); §06.5 reachesdoneagainst the mock and MUST NOT depend on §07’s wiring to close (a successor cannot gate a predecessor’s completion — INV topological invariant). §07 wires the real backend behind the same interface. - Pin the
invoke_commit/CommitResultcontract shape (blind-spot bs-commitresult-contract-shape — §07 wires the real backend behind the same interface and must not guess the boundary):invoke_commit(touches: list[str], scope: CommitScope) -> CommitResultwhereCommitResultis a typed dataclass inscripts/plan_orchestrator/commit_capability.pycarrying{ok: bool, commit_sha: str | None, halt_reason: str | None, error_payload: dict | None}—ok=True⇒commit_shapopulated +halt_reason/error_payloadNone;ok=False⇒commit_shaNone+halt_reasonset to a categorized commit_push halt string (per §06.1 non-enum partition) +error_payloadcarrying the/commit-pushenvelope’shalt_reason/failing_repo/scopefields. The mock backend intest_commit_capability_interfacereturns BOTH anok=Trueand anok=FalseCommitResultso the engine’s consume-path is exercised on both; §07’s real backend (scripts/commit_push/wiring) implements the SAMECommitResultshape with no field additions. Acceptance:test_commit_result_contract_shape(tests/test_commit_capability.py) asserts theCommitResultdataclass fields + the ok/not-ok field-population invariants above, so §07 wires the real backend against a pinned contract. - Commit-failure zero-halt disposition (blind-spot bs-commit-failure-disposition + bs-commit-failure-quarantine-not-continue / INV-7 — an unhandled
CommitResult.ok=Falsecould autopilot-halt on a routable condition, AND alog_and_continuedisposition would advance to a SUCCESSOR node while THIS node’s cures sit uncommitted in the working tree, breaking change isolation and cascading the dirty tree into the next node’s commit scope): the engine NEVER emitsaction: halton a commit failure AND NEVER advances the route past a node whose cures are uncommitted. ACommitResultwithok=Falsecarries a categorizedhalt_reason(a commit_push halt string per §06.1); §06.2cure_dispatchroutes it toquarantine— the node relocates back to not-done (per the plan-scoped linear walk so one stuck node never deadlocks the corpus) and stays the route’s responsibility until its cures commit cleanly, NEVER tolog_and_continue(which would crawl forward past the uncommitted tree). The commit_push halt strings are therefore GENUINE-with-dispositionquarantine(re-routable), NEVER CURABLE (the engine does not silently re-attempt a commit a hook rejected) and NEVERlog_and_continue(advancing past an uncommitted node is the change-isolation break this blind-spot names). When the §06.4 quarantine retry cap is hit (the same node’s commit fails N consecutive times), the node escalates to the GENUINEcompletion_verification_exhausted(autopilot_disposition: log_and_continue) — at THAT escalation point the working tree’s uncommitted cures are recorded to active-plan HISTORY and the route relocates past the exhausted node, never before. The disposition is recorded to active-plan HISTORY on every quarantine, never an interactive prompt in autopilot. Acceptance:test_commit_failure_zero_halt_disposition(tests/test_commit_capability.py) drives a mockedok=FalseCommitResultthrough the engine consume-path withctx.mode == "autopilot"and asserts the engine routes toquarantine(relocates the node back to not-done, does NOT advance to a successor) and emits NOaction: haltand NOAskUserQuestion; the pairedtest_commit_failure_does_not_advance_routeassertsserve_nextdoes NOT return a SUCCESSOR node while the committing node’s cures are uncommitted (the quarantined node or its predecessor is returned, never the next-in-key successor) — closing the INV-7 zero-halt gap AND the change-isolation gap for the commit capability. - soak node: cross-invocation convergence monitor (consolidate redispatch_loop_detector + halt_history cross-session + acknowledgment); emits the named GENUINE halt
soak_nonconvergenceonly on true non-convergence (a node whose halt-historyconvergence_signalshows the same halt fingerprint recurring past the soak window with no forward progress — distinct from transient redispatch, which is NOT a halt); feeds §12 soak verification. Thesoak_nonconvergencehalt_reason is added torules.HaltReasonin §06.1 withautopilot_disposition: structured_exit(a genuinely non-converging route has no trustworthy auto-cure — the engine emits exit state for the caller orchestrator and records the non-convergence fingerprint to active-plan HISTORY, never anaction: haltmid-walk, never an interactive prompt in autopilot). Acceptance:test_soak_convergence_monitorasserts a true non-convergence emitssoak_nonconvergencewhile transient redispatch does NOT; the pairedtest_soak_nonconvergence_autopilot_dispositionassertssoak_nonconvergence ∈ GENUINEcarriesautopilot_disposition: structured_exitand that driving it throughcure_dispatch.dispatch("soak_nonconvergence", ctx)withctx.mode == "autopilot"returns astructured_exitCureResultwith NOAskUserQuestionand NOaction: halt. - Low-confidence-absorb falsifiable-reopen fallback (soak-fed; the EXECUTABLE reproduction assertion is IMPLEMENTED + OWNED by §12 where the soak tests live, NOT a §06 close-out gate — §06 ships only the soak DATA feed, not the local verification, so §06 close-out never depends on the not-started §12): §06.5’s deliverable here is the soak-node convergence-monitor feed (above) that EMITS the per-absorb non-reproduction signal §12 consumes; the executable falsifiable-reopen assertion belongs to §12. §12 soak (
tests/test_soak.pyin §12 scope) asserts each low-confidence absorb’s original symptom does NOT reproduce on a concrete trigger — BUG-07-095: drive a nodecompletethen run a doc_sync pass; assert no co-flip back toin-progress(cure_dispatch terminal-state coherence §06.2 holds). BUG-07-108: drive a section through/review-planclose-out then a follow-up scan; assertreviewed: truesurvives (review-as-routing-field §06.4 holds). If EITHER symptom reproduces, the absorb is FALSE: §12 soak reopens that bug as a separate route node (/add-bugmints it per §06.4 bugs-as-nodes) with the reproduction trigger as itsverification_test, and §06’s absorbed-defects table does not claim it resolved. §06 closes on its own local acceptance tests (§06.N) and the soak-feed deliverable; the §12 reproduction assertion is a §12 success criterion (a predecessor never gates on a successor — §12depends_on: [..., 06]). - Subsection close (06.5) — all
[x];status: complete.
Absorbed defects (bug-tracker triage 2026-05-26)
These standalone tracker bugs are subsumed by §06’s zero-halt route-walk + cure_dispatch.py + review-as-phase + bugs-as-nodes (the halting machinery — roadmap.py / pivot.py / markers.py / plan-complete.py focus-picker — is deleted/replaced). This section’s deliverable MUST resolve each; the tracker entries are closed obe-via-absorb pointing here.
| Bug | Symptom subsumed |
|---|---|
| BUG-07-077 | autopilot fixed-point loop on NN.R findings (PLAN_SCOPE_DEADLOCK → cured node §06.1) |
| BUG-07-082 | autopilot halts on stale review_pipeline markers (marker concept retired §05.2; route_walk reader) |
| BUG-07-093 | routing cycles when in-progress + all checkboxes flipped (status derived from id-scan §03.2) |
| BUG-07-095 | doc_sync_drift co-flip complete→in-progress (cure_dispatch terminal-state coherence §06.2) — low-confidence absorb |
| BUG-07-101 | pivot self-loop deadlock (TARGET_SELF_DRIFT / REDISPATCH_LOOP → CURABLE §06.1) |
| BUG-07-102 | next_action schema rejects chain_diagnosis.exclusion_attempt (route_walk single next_action) |
| BUG-07-103 | unreviewed_plan auto-picker re-loops (auto-picker replaced by route_walk §06.3) |
| BUG-07-107 | misroutes positional plan dir + picks blocked subsection (serve_next §05.1) |
| BUG-07-108 | /review-plan close-out reviewed:true reverts (review = routing field §06.4) — low-confidence absorb |
| BUG-07-122 | focus_picker_internal halt on complete + reviewed:false (review-as-phase §06.4) |
| BUG-07-124 | focus-picker halts on complete + reviewed:false + blocked_by:[BUG] (bugs-as-nodes §06.4) |
| BUG-07-112 | tp-help caller_exit_reason_handlers are flat exit_reason lists with no per-reason action/autopilot routing — route_walk re-owns caller→exit_reason routing (§06.3) |
Low-confidence absorb fallback (falsifiable)
- The two low-confidence absorbs (BUG-07-095, BUG-07-108) are subsumed by the cure_dispatch terminal-state-coherence redesign (§06.2) and the review-as-routing-field redesign (§06.4).
- §06.5 ships the soak-node convergence-monitor DATA FEED that emits each absorb’s non-reproduction signal; the EXECUTABLE falsifiable-reopen assertion is implemented + owned by §12 (
tests/test_soak.py, §12 scope), which checks BUG-07-095 / BUG-07-108 non-reproduction and reopens each via/add-bugon reproduction. - §06 close-out does NOT gate on §12 — a predecessor never gates on a successor (§12
depends_onincludes §06).
06.R Third Party Review Findings
- None.
06.N Completion Checklist
- 06.1-06.5
[x]andstatus: complete. - All success criteria have
[x]checkboxes. -
test_cure_dispatch_registrygreen (every halt_reason categorized; no unregistered cure);halt_emission_lintclean (no newaction: haltfor CURABLE). - Per-capability acceptance tests green (one named test + the invariant it proves per node):
| Node | Acceptance test (file) | Invariant proven |
|---|---|---|
| 06.1 halt_reasons.py | test_halt_reason_partition_exhaustive + test_gate_internal_error_is_genuine_carveout (tests/test_halt_reasons.py) | every rules.HaltReason member is categorized exactly once + every GENUINE member has an autopilot_disposition (INV-6 zero-halt categorization complete); gate_internal_error is the single GENUINE harness-malfunction carve-out reconciling GENUINE with zero-halt INV-7 (autopilot_disposition: structured_exit) |
| 06.2 cure_dispatch.py | test_cure_dispatch_registry + test_compose_resume_bash_matrix + test_cure_dispatch_no_residual_splitter + test_user_decision_no_autopilot_askuser (tests/test_cure_dispatch.py) | every CURABLE halt_reason has a registered cure; no action: halt for CURABLE; shared resume-bash util handles no/one/stacked prior flags (INV-6, Pass 2 risk 7.1/7.8); NO surviving _compose_resume_bash sibling on disk after consolidating linear_execution/review_blocked (LEAK:algorithmic-duplication closed); every USER_DECISION member routes through structured_exit/log_and_continue in autopilot with NO AskUserQuestion (zero-halt INV-7) |
| 06.3 route_walk.py | test_route_walk_exit_reason_parity + test_serve_next_never_skips_in_progress + test_route_walk_reuses_parser_ssot + test_route_walk_output_determinism + test_route_walk_malformed_plan_json_raises + test_route_walk_preserves_inv15_separation + test_no_cross_plan_ready_node_registered + test_route_walk_empty_corpus_emits_no_ready_node + test_route_walk_all_deferred_emits_no_ready_node + test_route_walk_cold_start_first_route_discovery + test_roadmap_delegates_to_route_walk (tests/test_route_walk.py) | every emitted exit_reason maps to a concrete next_action; whole-body_ref injection carries no fragment (INV-18 + caller→exit_reason routing, BUG-07-112); strict-forward serve_next never skips past an in-progress OR in-review predecessor (both blocking — INV-20); engine reuses the §03 parser SSOT (no 2nd parser); next_action output is byte-deterministic; a malformed plan.json fails loud via schema_invalid (never silent-skip); INV-15 separation preserved — ordering from key, identity from id, group non-ordering; engine bootstrap + empty/all-deferred corpus emits no_cross_plan_ready_node (exit_code 0, never a halt) and cold-start discovers the first route plan deterministically; roadmap.py is a thin delegate to route_walk (no second walk impl survives — §11A owns full deletion) |
| 06.4 review-as-phase | test_verified_completion_choke_point + test_quarantine_retry_cap + test_quarantine_reset_on_deliverable_change + test_split_cure_responsibility_separation + test_gates_verified_sole_writer (tests/test_review_phase.py) | only one path writes done and only post-verification; verify-fail routes to quarantine not done/halt; N-fail escalation relocates past the node; verification_fail_count resets ONLY on a declared-deliverable mtime-fingerprint change (CODE not just markdown), never on a no-op re-verify; split-cure keeps node-mint (engine/plan.json) and content-partition (LLM/markdown) separate; review-as-phase is the SOLE writer of completion.gates_verified and asserts gates_required ⊆ gates_verified before flipping done (INV-17 + INV-18 + INV-20) |
| 06.4 bugs-as-nodes / subsumption | test_subsumption_completes_by_construction + test_unsubsume_on_verification_fail + test_subsumed_bug_retains_hint_on_quarantine (tests/test_review_phase.py) | a subsumed bug completes ONLY when the umbrella’s choke point confirms its verification_test; verification-fail un-subsumes via quarantine; a transient umbrella quarantine RETAINS the bug’s hint_needs (no premature execution) — the hint drops ONLY on explicit umbrella abandonment or the bug’s own verification-fail (INV-14) |
| 06.4 invariant-acceptance-hook | cross_section_check.py self-test (tests/test_cross_section_check.py) | an owning-invariant node with no acceptance hook FAILS CLOSED → quarantine (INV-7; existing scripts/plan_corpus/cross_section_check.py consumed + extended at §06.4, also consumed by §12.1) |
| 06.5 path-scoped-commit | test_commit_capability_interface + test_commit_result_contract_shape + test_commit_failure_zero_halt_disposition + test_commit_failure_does_not_advance_route (tests/test_commit_capability.py) | the engine routes to the commit capability with the node’s touches: scope against a mocked backend (closes against the mock, not §07’s wiring); the CommitResult dataclass field + ok/not-ok population invariants are pinned so §07 wires the real backend against a fixed contract; a commit failure routes to quarantine (NOT log_and_continue) emitting no action: halt/AskUserQuestion, and serve_next never advances to a successor while the node’s cures are uncommitted (INV-7 zero-halt + change-isolation) |
| 06.5 soak | test_soak_convergence_monitor + test_soak_nonconvergence_autopilot_disposition (tests/test_soak.py) | a true non-convergence emits the named GENUINE halt soak_nonconvergence; transient redispatch does not (feeds §12); soak_nonconvergence carries autopilot_disposition: structured_exit and routes through cure_dispatch with NO AskUserQuestion/action: halt in autopilot (zero-halt INV-7) |
-
python -m scripts.plan_corpus check plans/scripts-first-restructure/section-06-*.mdexit 0. exit 0 -
/tpr-reviewpassed (final, full-section). /review-plan ran 3 /tpr-review rounds, verdict MINOR FIXES APPLIED reviewed:true (review_pipeline stage=verify-done)
References
- Pass 1D (plan_orchestrator surface; cure_dispatch/halt_reasons absent; 7-node decomposition) + Pass 2 (§6 consolidation map + §7 seven risks).
- §01 invariants 1, 6, 7, 8, 14, 16, 18, 20; refinement 6 (engine decomposition);
decisions/02-content-as-context-unit.md(whole-file task injection + size gate + split cure);decisions/03-plan-bug-subsumption-absorption.md(subsumption = consequence-relationship + verification-gated done + un-subsume-via-quarantine);references/restructure-charter-seed.md §2 INV-20(strict-forward-only progress). - Code surfaces the section depends on (consumed, not re-authored):
scripts/plan_orchestrator/rules.py(HaltReasonenum SSOT §06.1 re-exports/partitions);scripts/plan_corpus/exit_reasons.py(CANONICAL_EXIT_REASONS+EXIT_REASON_ROUTINGparity SSOT §06.3 anchors on);scripts/commit_push/rules.py+.claude/rules/commit-push-rules.json(commit-push halt-string SSOT §06.1COMMIT_PUSH_HALT_STRINGSderives from);scripts/plan_orchestrator/auto_cure_loop.py(LoopExitReasonorchestrator halt/continuation strings §06.1 enumerates);scripts/plan_corpus/invariant_gate.py(gate_internal_errorsource);scripts/plan_corpus/cross_section_check.py(STRUCTURE:invariant-acceptance-hook-missingdetector §06.4 consumes);scripts/plan_corpus/migrations/006_md_to_json.py:build_plan_json_from_dir(substrate parser SSOT route_walk reuses).
HISTORY
- 2026-05-29 — §07A v7 route schema supersedes the v6 flat-node engine contract: the route schema v7 two-level
plan.json(sections[]+ flatwork_items[], per §07A +decisions/04-sections-work-items-split.md) supersedes §06’s v6 flat-nodenodes[]model; §06’s v6 engine stayscompletebutroute_walk.serve_nextis reshaped to walksections[]thenwork_items[], return the current work_item, and own the work_item status lifecycle (write-on-serve + read-onlypeek_next) per §07A.4.