Section 09 — Consuming-Skill Rewrites (Additive v7 Path + Dogfood Gate)
Cites §01 north star (invariants 1, 2, 18); consumes §06 engine (route_walk + cure_dispatch) + §08 hook. This is where scripts-drive / thin-skills / no-plan-reading / whole-file-read land on the v7 path (R6Q23 + INV-18) — ADDITIVELY, so the existing markdown path keeps every mixed-corpus plan runnable as permanent legacy support per decisions/05-three-plan-types.md (§11A strip CANCELLED).
Goal
See frontmatter.
- Each skill gains a v7 route-script dispatch ALONGSIDE its untouched markdown path; the skill shape-detects per plan (plan.json → v7; section-*.md only → markdown).
- §09’s last step (§09.4) drives the v7 subject plan end-to-end as the dogfood gate before §10.
Additive-path transition-safety constraint
- The corpus during §09 is MIXED:
plans/completed/scripts-first-workflow-architectureis v7; every other plan (including THIS plan’s own §10/§11A/§11B/§12 markdown sections) is still markdown. - A v7-ONLY orchestrator would strand every markdown plan — including this plan’s own §10 migration section, which the orchestrator must read to RUN the migration (bootstrap deadlock).
- Therefore §09 ADDS the v7 path and RETAINS the markdown path. Shape-detect routes each plan to the right walker. §10 then migrates plans incrementally (each flips markdown->v7 the moment it converts).
- LEGACY-MARKDOWN PERMANENCE (per
decisions/05-three-plan-types.md; supersedes the original §11A “remove the markdown path” framing): the §11A markdown-walk strip + §11B parser strip are CANCELLED (00-overview.md§11A/§11B rows aresuperseded). The corpus is a THREE-TYPE system — json (v7), legacy-markdown (KEPT permanently), json-dynamic — so the markdown path is NOT removed later; the orchestrator stays shape-detect (detect_route_mode) INDEFINITELY, never v7-only. BOTH the json route_walk path AND the legacy markdown focus-picker path remain documented + supported as first-class. §09’s additive contract (no markdown code path deleted, gutted, or behaviorally altered) is the permanent end-state for the markdown path, not a temporary pre-strip posture. The INV-20--complete-all/auto_complete_section.pyretirement narrows to the JSON path ONLY; the markdown completion flow is permanent.
Intelligence Reconnaissance
POINT-IN-TIME SNAPSHOT (run 2026-05-30) — the walk topology + status counts below are the as-of-recon state; the CURRENT plan structure superseded two of them: (a) §09B (structural cross-plan dependency, INV-21) was INSERTED between §09 and §10 (00-overview.md:128 now routes §09 → §09B → §10 → §11A); (b) §11A/§11B are now superseded per decisions/05-three-plan-types.md (00-overview.md:163-164), NOT not-started — the markdown-walk strip is CANCELLED, the markdown path is permanent legacy. The recon’s §09 successor + §11A “markdown-walk strip” framings are stale; the live successor of §09 is §09B and no later section strips the markdown path.
scripts/intel-query.sh dag-ascii scripts-first-restructure(as of 2026-05-30) — §09 linear-walk position §06 → §07 → §07A → §08 → §09 → §10 → §11A;depends_on: ["08"](§08 route-access hook is the SOLE direct predecessor per INV-19 single-predecessor; §06 autonomous engine is transitively reachable via the §06→§07→§07A→§08 chain; §08complete+ reviewed; successor §10 corpus-migration is gated on §09.4 dogfood close). INV-19 strict-linear-single-branch holds: single predecessor chain, single successor, no diamonds. (Current topology inserts §09B as §09’s successor before §10; §11A is nowsuperseded, not a future strip step.)scripts/intel-query.sh plan-status scripts-first-restructure(as of 2026-05-30) — §06complete; §08in-review; §09in-review; §10/§12not-started; §11A/§11B since flipped tosupersededper Decision-05. The §09.4 dogfood gate is the cross-plan edge intoplans/completed/scripts-first-workflow-architecturereturning via its terminalreview-findingsclose-out handback.- Plan-routing-consumer audit (grounds the §09.1 closed set; SKILL.md / command bodies are not intel-graph-indexed, so the closed set anchors on the source-file grep of
plan.json/route_walk/serve_next/plan_corpusconsumers across.claude/skills/**+.claude/commands/**): [ori:.claude/skills/continue-roadmap/SKILL.md],[ori:.claude/skills/commit-push/SKILL.md],[ori:.claude/skills/fix-bug/SKILL.md],[ori:.claude/skills/add-bug/SKILL.md],[ori:.claude/skills/create-plan/SKILL.md],[ori:.claude/skills/tpr-review/SKILL.md],[ori:.claude/skills/review-plan/SKILL.md],[ori:.claude/skills/fix-next-bug/SKILL.md],[ori:.claude/skills/review-bugs/SKILL.md],[ori:.claude/skills/sync-docs/SKILL.md],[ori:.claude/skills/sync-claude/SKILL.md]— exactly these eleven drive or read plan routing; this is the CLOSED set §09.1 enumerates, §09.3’s audit re-runs the same grep to PROVE no consumer falls outside it before §09.3 closes.[ori:scripts/plan_orchestrator/route_walk.py]§06.3serve_next(one node, deterministic) +[ori:plans/scripts-first-restructure/section-07-commit-push.md]§07compute_scope_restriction(path-scoped commits) +[ori:plans/scripts-first-restructure/section-08-route-access.md]§08block-route-edits.sh(hook-enforced no-LLM-plan.json-access) — the v7 dispatch REUSES these; §09 ADDS the dispatch alongside the markdown path and introduces no shadow router.- INV-22 bug-plan-v7-scaffolding scope boundary (cohesion note, NOT a §09 gate): the
00-overview.md:89INV-22 success-criterion (“bug plans scaffold as v7 JSON by default”) names §09 as a create-plan/fix-bug scaffolding follow-on, but the deliverable is OWNED bysection-11C-dynamic-plans.md(the JSON-Dynamic / INV-22 section) and tracked atbug-tracker/plans/BUG-07-169/. §09’ssuccess_criteriadeliberately do NOT enumerate INV-22 — §09 ships the ADDITIVE v7 route-walk dispatch on the existing 11 consuming skills, not the bug-plan-dir scaffolding-shape change. The bug-plan v7-JSON scaffolding variant (replacingfix-section-template.md’s 9 markdown files in/create-planStep 0.6 bug fast-path +/fix-bugPhase 1.6) is anchored to §11C + BUG-07-169 and does NOT gate §09 close. This keeps §09’s scope ADDITIVE-on-existing-skills and prevents §09 claiming coverage its body does not gate.
09.1 — Closed set + ADDITIVE shape-detect contract
- CLOSED set of rewritten skills (exactly these eleven; no “etc.”, no open clause):
/continue-roadmap,/commit-push,/fix-bug,/add-bug,/create-plan,/tpr-review,/review-plan,/fix-next-bug,/review-bugs,/sync-docs,/sync-claude. One rewrite per skill = one flat node. The set is derived from the §Intelligence Reconnaissance plan-routing-consumer audit (grep ofplan.json/route_walk/serve_next/plan_corpusconsumers across.claude/skills/**+.claude/commands/**); §09.3’s audit deliverable PROVES the set is complete (no consumer outside it), it does NOT leave the set open to grow. Any consumer the §09.3 audit surfaces OUTSIDE these eleven is a finding that BLOCKS §09.3 close until reconciled (add the missing skill as a flat node + re-run the audit until it confirms zero unenumerated consumers), never a silent extension of an open list. - Per-skill ADDITIVE contract: SKILL.md body =
## Rules consumed+ role + directive +next_actionconsumption table; the v7 dispatch lives inscripts/<skill>_runtime/(or the §06 engine for the autopilot walk); on the v7 path NO plan reading (script injects task). The markdown path stays exactly as-is. The skill shape-detects (plan.json present => v7 dispatch; section-*.md only => existing markdown path) — detection lives in the runtime, not skill prose. - Shape-detect tiebreaker for a MIXED plan dir (plan.json AND section-.md both present mid-§10 migration): plan.json present => v7 ALWAYS wins, even when section-.md coexist. The v7 plan.json is the routing SSOT once present; section-.md is consulted for v7 CONTENT (
body_refbodies) only, NEVER for routing. A plan dir transiently carrying both during conversion drives the v7 walk; the markdown focus-picker fires ONLY when plan.json is absent. This makes shape-detect deterministic (INV-19/INV-20: one node per turn, no double-dispatch, no v7 plan stranded on the markdown path). Implemented as a single precedence functionscripts/plan_corpus/route_v7.py:detect_route_mode(plan_dir) -> "v7" | "markdown"(returns"v7"iff a valid v7 plan.json exists in the dir regardless of coexisting section-.md, else"markdown"), re-exported fromscripts/plan_orchestrator/route_walk.py. Detection lives in the runtime, not skill prose. - Detection unit test for the tiebreaker (
scripts/plan_corpus/tests/test_detect_route_mode.py): assertsplan.json + section-*.md coexist => v7,section-*.md only => markdown,plan.json only => v7(plus non-v7 / malformed / missing fall-through to markdown). The three pinned cases stop a future markdown-path edit regressing a mixed-dir plan onto the markdown walk. 6/6 green. - INV-18 (per
decisions/02-content-as-context-unit.md): the v7 contract states the task context = the WHOLEbody_refcontent file read in full; no skill consumes a fragment /section_infoslice ON THE V7 PATH. ADDED the single-read model toplan-read-discipline.md §3.5+context-discipline.md §3.4for the v7 path; the existing markdown orchestrator-pointer / executor-full-file split stays documented + in force for markdown plans (the markdown split is permanent legacy perdecisions/05-three-plan-types.md; §11A strip CANCELLED). Out-of-compiler-rigor rule edit; prose-lint clean. - Subsection close (09.1) — all
[x];status: complete.
09.2 — Add the v7 path to autopilot-critical skills (markdown untouched)
- ADD the v7 route_walk dispatch to
/continue-roadmap(drives the §06 route_walk engine, fully autonomous cross-plan per invariant 8, on v7 plans);/commit-pushgains the §07 path-scoped path;/fix-bug+/add-buggain the bugs-as-nodes path (§06.4). The existing markdown focus-picker / commit / bug flows are UNCHANGED — shape-detect picks the path per plan. DONE:roadmap.py:_route_dispatchconsolidated to the §09.1route_v7.detect_route_modeSSOT (v7-vs-markdown tiebreaker) + v6dispatch_modeunion; a v7 plan.json routes throughroute_walk.next_action(§07A.4 two-level walk), v6 keeps the graph+adapter path, markdown-only returns None (byte-unchanged)./commit-push§07 path-scoped backend (scripts/commit_push/scoped_commit.py:ScopedCommitBackend) +/fix-bug+/add-bug§06.4 bugs-as-nodes (scripts/plan_orchestrator/review_phase.py) infra are §07/§06-complete and reused, not rebuilt. Tests:scripts/plan_orchestrator/tests/test_route_dispatch_v7.py(7) +test_route_dispatch.py/test_route_walk.pyregression (22) green; the v7 subject plan now dispatches (work_item_id=w-fd081046) where it previously fell through to markdown. - Each: the v7 path is thin;
plan-read-discipline-lint --strictexit 0 against the v7 path;script_first_audit.py --skill <name>clean. The markdown path’s existing audit posture is unchanged. DONE:plan-read-discipline-lint.py --strictexit 0 on the touched SKILL.md bodies (continue-roadmap, create-plan, review-plan); the v7-path additions are directive-only pointers (no plan reading, no scratch-dir/pseudocode/raw-output). The 4-axis rubric is scored by the in-treescripts/skill_audit/script_first_audit.py(CLI--skill <name>/--all/--self-test; 4 axes per.claude/rules/script-first.md §3— prose-decision-depth, pseudocode-bloat, scratch-dir-leak, raw-output-dump):python3 scripts/skill_audit/script_first_audit.py --skill continue-roadmap(and--skill create-plan,--skill review-plan) scores clean on the touched bodies.prose-lint.pyclean on all three edited skill files. -
/continue-roadmapSKILL.md emits the todo-YAH view ON THE V7 PATH (per §00.4 + §03.4): every turn, AFTER consumingnext_actionAND BEFORE executing the bounded task, callpython -m scripts.plan_corpus.render <plan-dir> --view todo-yahand emit output inline; the rendered view IS the visible KISS for v7 plans. Markdown plans keep their existing heartbeat/banner/section_info surfacing. DONE:continue-roadmap/SKILL.md:128Step 0 todo-YAH directive gated onpayload.section_infocarryingwork_item_id(the v7 route-served shape); v6/markdown shapes (node_id/focus context) keep their existing surfacing — no todo-YAH for them. - INV-19
/create-planauthoring-time enforcement (perreferences/restructure-charter-seed.md §2 INV-19): rewritten/create-planStep 0.6 (plan routing helper) MUST reject any new plan whose section graph has (a) any node with 2+ predecessors (diamond), (b) any node with 2+ successors (branch), or (c) any non-root node without an explicit single predecessor. When a section has no natural dependency, auto-assigndepends_on:to the immediately-prior lexorank section ID (close the chain). Rejection at Step 0.6 surfaces a structured error citing the offending node + the violation class; the skill MUST NOT proceed to plan-dir scaffolding while the violation stands. (Applies to NEW plans, which are authored v7 — no markdown-path conflict.) DONE:scripts/plan_routing.py:86 enforce_linear_dag(inventory) -> DagVerdict(rejects diamonds/branches/missing-predecessor + auto-assignsdepends_onto the immediately-prior lexorank section;ok=Falsehalts scaffolding); wired into/create-planSKILL.md Step 0.6. Test:scripts/plan_corpus/tests/test_enforce_linear_dag_create_plan.pygreen. - INV-19
/review-planreview-time enforcement (perreferences/restructure-charter-seed.md §2 INV-19): rewritten/review-planStep 2 audit MUST surfaceSTRUCTURE:non-linear-DAGfinding for any section whosedepends_on:declares multiple predecessors OR whose section graph contains diamonds / branches / missing predecessors. Severity: Critical (constitutional invariant). The finding cites the offending node + violation class + the cure (collapse to single predecessor; close the chain to the immediately-prior lexorank node). DONE:scripts/plan_corpus/section_audit.py:337+:1598+:1750emitSTRUCTURE:non-linear-DAGCritical (the three emit sites inaudit_linear_dagat:322and the two downstream branch/diamond checks; transitive predecessors reachable through the declared single predecessor are correctly treated as informational, NOT additional edges, per the transitive-predecessor filter at:1348emittingINTEGRITY:depends-on-vs-citation-drift:transitive-predecessorat:1388); wired into/review-planStep 2. Test:scripts/plan_corpus/tests/test_audit_linear_dag_review.pygreen. - INV-20 enforcement on the v7 path (ADDITIVE; per
references/restructure-charter-seed.md §2 INV-20): the v7 dispatch in/continue-roadmapcallsroute_walk.serve_next(plan)from §06.3 — one node, deterministic, strict-forward-only, onenext_actionper turn, no Claude-side classifier. The markdown path’s_step_5_emit_focusfocus-picker + bucket-classification (actionable / bug_blocked_sections / needs_review_plan_dispatch) are NOT invoked on the v7 path and NOT deleted in §09 — they remain the live markdown path, RETAINED permanently as legacy support perdecisions/05-three-plan-types.md(§11A strip CANCELLED). DONE:roadmap.py:_route_dispatchserves viaroute_walktwo-level walk (serve_next/peek/_v7_walk), never the markdown focus-picker. Tests:test_v7_dispatch_invariants.py::test_v7_dispatch_does_not_invoke_markdown_focus_picker+::test_v7_dispatch_envelope_is_route_walk_two_level_walk+::test_step_5_emit_focus_and_bucket_classification_not_deletedgreen. - INV-20 force-flip ban on the v7 path (per
references/restructure-charter-seed.md §2 INV-20): on the v7 path the rewritten/continue-roadmapNEVER callsplan-complete.py --complete-alland NEVER routes throughscripts/plan_orchestrator/auto_complete_section.py; sectionstatus: completeflips ONLY via review-as-phase writingcompletion.gates_verifiedper §06.4. The markdown path’s existing completion flow is untouched in §09 (markdown completion flow is permanent perdecisions/05-three-plan-types.md; §11A strip CANCELLED). Acceptance: on a v7 plan,grep-equivalent of the run log shows zero--complete-all/auto_complete_outcomeinvocations; the markdown path retains current behavior. DONE: the v7_route_dispatchpath emits a route-walknext_actionenvelope with no auto_complete call. Test:test_v7_dispatch_invariants.py::test_v7_dispatch_never_calls_auto_completegreen. - Subsection close (09.2) — all
[x];status: complete.
09.3 — Add the v7 path to remaining consuming skills + audit
-
ADD the v7 path to the rest of the closed set (shape-detect dispatch) where the skill ROUTES; DOCUMENT the agnostic classification where the skill operates on a caller-given target. No markdown path deleted; no shadow router forced onto a non-routing skill. DONE: the five remaining closed-set skills (
/tpr-review,/fix-next-bug,/review-bugs,/sync-docs,/sync-claude) are EACH route-mode-AGNOSTIC — none drives a per-planplan.jsonroute-walk /serve_next/next_unblockeddispatch to decide what to execute; each consumes a caller-given target (the CALLER — already-wired/continue-roadmap§09.2 or/review-plan§09.2 — did the routing). Per-skill classification + cite:Skill Routing input (what it operates on) Classification Why no v7 path /tpr-reviewreviews a caller-given --skill review-plan <section-path>(the section is passed in by the orchestrator caller;tpr_review_runtime generate --target-section <path>)route-mode-AGNOSTIC reviews a caller-given target section, not a per-plan route-walk; a v7 path here would be a shadow router /fix-next-bugauto-picks from the bug-tracker AGGREGATE ( bug_queue_scan.pyscansbug-tracker/section-*.md+bug-tracker/plans/BUG-*/)route-mode-AGNOSTIC the bug-tracker is not a per-plan plan.jsonroute-walk; bug selection is aggregate-priority, not route_walk/serve_next/review-bugsenumerates the bug-tracker AGGREGATE ( bug-tracker/section-NN-*.md+bug-tracker/plans/BUG-*/00-overview.md)route-mode-AGNOSTIC bug-tracker enumeration, not a per-plan plan.json route-walk /sync-docsrecent commits ( git log HEAD~30..HEAD) + a caller-given--section <path>for close-out scoperoute-mode-AGNOSTIC consumes a caller-given target + commit scope; never route-walks a per-plan plan.json /sync-claudegit diffs ( <section-start-commit>..HEAD) + the caller-given section at close-outroute-mode-AGNOSTIC consumes a caller-given target + diff scope; never route-walks a per-plan plan.json Honest classification IS the deliverable (per §09.3): route → wire (none of the five route); agnostic → document (all five). No SKILL.md body was edited (forcing a v7 shape-detect onto a non-routing skill would be a shadow router, banned).
@-include compliance: not applicable — no skill body changed.prose-lint.pyclean on the touched section file. -
PROVE the §09.1 closed set is complete: the route-consumer-completeness audit (
scripts/skill_audit/route_consumer_audit.py+scripts/skill_audit/tests/test_route_consumer_audit.py) enumerates every GENUINE plan-routing consumer (drives a per-planplan.jsonroute-walk /serve_next/next_unblocked/_route_dispatch/_build_next_unblocked/detect_route_modedispatch) across.claude/skills/**+.claude/commands/**, excluding design-log prose (improve-tooling/*-design.md),references/**,*-template.md,*.legacy.*,tests/, and bare-next_action-envelope consumers (tp-dev / improve-tooling / condensate / verify-tpr — they consume a handed next_action, they don’t route-walk). It asserts the consumer set ⊆ the eleven. DONE: live corpus audit is GREEN — the sole genuine route-driver is/continue-roadmap(viaroadmap_scan.py:_build_next_unblocked+ the SKILL.mdroute_walk/next_unblockedconsumption);consumer_skills = {continue-roadmap} ⊆ eleven;outside_set = ∅;closed = true(exit 0). 9/9 pytest green (self-test 8/8 + live-corpus closed-set + subset + negative-pin outside-set-breaks-proof + precision pins for bare-next_action / design-log prose). No unenumerated consumer surfaced; the closed set is proven complete, not extended. -
Subsection close (09.3) — all
[x];status: complete.
09.4 — DOGFOOD GATE: drive scripts-first-workflow-architecture all the way through v7
This is §09’s LAST step before close. It is the cross-plan dependency that gates closing the whole json-schema plan: §10 MUST NOT begin until this subsection closes, and the whole plan (scripts-first-restructure) cannot reach close-out until the subject plan reaches status: complete. Per 00-overview §Cross-plan dependency + the subject plan’s close-out handback (plans/completed/scripts-first-workflow-architecture terminal review-findings section).
- Drive
plans/completed/scripts-first-workflow-architectureALL THE WAY THROUGH to terminal using ONLY the new plan.json + the §09 v7 orchestrator (route_walk.serve_next + §06 engine). DONE: 54/54 sections terminal — 35completed(built via verify-and-complete-v7 with INV-17 attestation + INV-20 gates) + 19superseded(OBE, via the new supersede-section-v7 command per user directive 2026-05-30). No force-flip. The v7 engine validates clean; the full-drain serve emits a cleanexit_kind: plan_terminus. - Bug-finding is the deliverable: the dogfood surfaced + FIXED 25 engine defects (findings 20-44 below) — finding-21 git-tracked completion, status.md freshness, §17.2 catalog reality-grounding, §18.8 lefthook glob silent-skip (caught 2 LIVE bugs), the superseded-status walk-terminal gap, the full-drain section_info schema violation, the commit-push parallel-session friction, + more. Discovery WAS assignment.
- Fix-and-record protocol: every surfaced CORRECTNESS defect FIXED (fix-now) + recorded in the
## 09.4 Dogfood Findingslog below (defect class + fixing-commit-SHA). The residual tail is THREE anchored non-§09-blocking items, each with a concrete owning anchor (NOT silent deferral): (1) finding 24 (v7-conversion orphaned the markdown-eratest_cross_section_gate_section_01_to_14.py) — SAME orphaned-test class as finding 4, re-anchored tobug-tracker/plans/BUG-07-160/for re-point-or-retire against the v7 content nodes (NOT §11A: its markdown-walk strip is CANCELLED perdecisions/05-three-plan-types.md, so there is no future strip section to own the orphaned test); (2) finding 4 / BUG-07-160 (same orphaned-test class,defer_separateperrouting.md §2) tracked atbug-tracker/plans/BUG-07-160/for re-point-or-retire against the v7 content nodes; (3) finding 32 is an OBSERVATION, not a defect — both the walk and the status.md render are correct; the optional dual-line “Next actionable” UX enhancement is YAGNI-deferred torender._render_quick_glancepending confirmation it is wanted (no incorrect behavior to fix). Zero open CORRECTNESS-defect tail; every non-fixed item is anchored to a named owner. - Machine-checkable EXIT condition: (a) the subject plan’s
plan.jsonshows EVERY section TERMINAL (completedORsuperseded) — derived via the route API (serve_next_v7returns None / drainedno_cross_plan_ready_node); NB: the original wording “EVERY section completed” predates thesupersededterminal status this dogfood ADDED — terminal-via-supersede satisfies the intent (subject fully driven, no actionable node). (b) zero unresolved CURABLE halts. (c) §08 hook log shows zero unauthorized LLM plan.json access (the LLM only used the route CLI). (d) every dogfood commit path-scoped (the §07 + new commit-push scoped-drift + cross-plan exclusion enforce it). - Bounded gate: the dogfood terminated by construction —
serve_next_v7advanced past each completed/superseded section and the chain ended at the all-terminal drain. Not an open loop. - Confirm the subject plan’s close-out handback: the subject’s terminal
review-findingssection was itself superseded (OBE) per the user’s blanket directive; the handback is recorded HERE instead — dogfood complete, subject fully terminal, scripts-first-restructure resumes at §10. (The review-findings handback mechanism is moot under the superseded-heavy outcome.) - Subsection close (09.4) — all
[x];status: complete. Subject plan is fully terminal (54/54: 35 completed + 19 superseded), validates clean — the gate’s “subject reaches terminal” condition is met.
09.4 Dogfood Findings
Each row = one defect the v7 engine surfaced while driving plans/completed/scripts-first-workflow-architecture through the §09 orchestrator. Columns: defect class, BUG-ID, fixing commit SHA. A surfaced defect with no row here BLOCKS the §09.4 gate (per the fix-and-record protocol above).
| # | Defect class | BUG-ID | Fixing commit | Notes |
|---|---|---|---|---|
| 45 | Cross-plan dependency had NO structural enforcement: the v7 sections[]+work_items[] split (decisions/04) made hint_needs advisory-only (correct intra-plan), leaving CROSS-plan dependency a walk-time no-op; the §12 cross-plan blocker on the dogfood subject was only prose-declared (“the plan-corpus schema has no cross_plan_blocked_by field”). The dogfood — driving the subject as a separate plan with a real back-and-forth (subject surfaces engine bugs fixed back in restructure, then resumes) — surfaced that the engine could not REPRESENT, let alone enforce, “pause plan A, advance plan B that A needs, resume A”. | dogfood-surfaced (cross-plan-dependency structural gap; INV-21) | CURE IMPLEMENTED + UNIT-TEST-VERIFIED in §09B (live two-plan exercise PENDING §12.3) | The CURE is §09B’s structural cross_plan_needs mechanism (replacing the advisory/prose model): 09B.1 v7 schema field cross_plan_needs: [{plan, id}] on sections+work_items (14 pytest green); 09B.2 merge-layer hard-defer in serve_next_with_cross_plan (jump-to-another-plan-and-back by construction) + cross_plan_all_deferred transient-retry exit_reason; 09B.3 combined-graph CROSS_PLAN_CYCLE (intra-order + cross-plan + bug-blocker edges) + CROSS_PLAN_DEAD_REF (12 tests; full plan_corpus suite 2855 green). HONESTY GATE: the structural mechanism is IMPLEMENTED + unit-test-verified as the cure for the gap this dogfood surfaced; the LIVE two-plan back-and-forth against the real pair is NOT yet exercised by this §09.4 run — that end-to-end cross-plan soak is §12.3’s job (not-started). The §12 close-out blocker on the subject is carried structurally TODAY via carrier (b) — the §09.4 dogfood gate + the §10→§09B→§09 depends_on chain — per 09B.4 / Decision-05 (scripts-first-restructure is legacy-markdown; a literal cross_plan_needs edge applies only after an explicit/opt-in v7 conversion). |
| 44 | v7 engine: at FULL-plan drain (every section terminal), _node_to_section_info(None) + _next_action_v7 drained case emitted section_info={}, which fails next_action.schema.json — a section_info without route_served:true falls into the else requiring source_path. The exhaustion serve emitted a schema violation instead of a clean plan-complete. Surfaced when the blanket OBE supersession drove the plan to 54/54 terminal — the first time a v7 plan reached full drain. | dogfood-surfaced (full-drain exhaustion boundary) | FIXED (route_served on drained section_info) | Both drained section_info builders now emit {"route_served": True} → the schema’s route-native branch applies (no legacy file-provenance requirement). The full-drain serve now emits a clean exit_kind: plan_terminus. Pre-existing bug (the all-completed full-drain would hit it too). Tests: test_superseded_status drained-shape + updated route_walk_v7 parity assertion; 36 green. |
| 43 | The v7 walk re-served already-superseded sections (_v7_walk skipped only completed, not superseded). Surfaced immediately after superseding §30 — the walk re-served it. | dogfood-surfaced (superseded-status walk gap) | FIXED | Added TERMINAL_STATUSES = {completed, superseded}; all four _v7_walk terminal checks use it. Tests: walk-skip + exhaustion cases. (Part of the superseded-status hardening; commit with route_walk fix.) |
| 42 | (user-directed) commit-push parallel-session friction: two shared autopilot sessions burned many turns fighting commit-push — staged_set_drift/head_drift halts on parallel churn, plus cross-session SWEEPS (one session committing another’s plan files under its message). Root: drift checks were whole-repo + staging staged the whole dirty tree. | user-directive (commit-push friction) | FIXED (scoped-drift + cross-plan exclusion) | (a) Drift checks (head/status/diff) now SCOPED to each run’s own changed-file set (scope_paths captured at prepare); a parallel commit/edit to OTHER files is benign + a benign HEAD move auto-passes → apply commits on the new HEAD (no re-prepare). commits_touch_paths classifies the move. (b) --plan-dir plans/X auto-excludes OTHER plan dirs from staging (_cross_plan_exclusions) → no cross-session plan sweep. Commits 6d060d1a + 6f6bbecd. Tests: test_parallel_session_scoped_drift (4) + test_cross_plan_exclusion (4); fixed parity diff_digest fixture; suite 470 green. |
| 41 | (user-spotted) v7 schema had no superseded status — superseding an OBE section via verify-and-complete-v7 marked it completed, indistinguishable from a genuinely-built section. | user-spotted (engine gap) | FIXED (superseded status + command) | Added superseded terminal status to the work_item/section enum + schema; derive_section_status rolls all-superseded → superseded; new supersede-section-v7 command (reviewed-gate + reason, no deliverable gates, reachable from any non-terminal state). Re-marked §30/§31/§32/§32A from mismarked completed → superseded. Commit 6d060d1a. Tests: test_superseded_status (7). |
| 40 | GOVERNING (user directive 2026-05-30): the subject plan scripts-first-workflow-architecture is largely OBE (Overtaken By Events) — the v7-route / autopilot-default / script-first / route-substrate work it specs was actually BUILT in plans/scripts-first-restructure (the meta-plan whose §09.4 dogfood gate drives this subject). User: “supercede this section entirely, it’s pointless… a lot in this plan that is simple OBE as we did it in plans/scripts-first-restructure, just supercede all of those.” | user-directive (dogfood scope clarification) | ACTIONED (supersede OBE sections) | Remaining subject sections are assessed for OBE (work done in scripts-first-restructure / superseded by Decision 16 / realized by the live v7 model) and SUPERSEDED where OBE (verify-complete-as-superseded, no build), rather than built from scratch. The dogfood’s purpose — validate the v7 engine end-to-end — is served by driving the subject to completion superseding OBE content. §31 is the first applied (finding below). Pattern confirmed across §30 (Decision 16), §17-§20 (over-spec vs built), §31 (autopilot durability done in restructure). |
| 39 | §25/§30 (relocate-on-blocker-primitive) is fully SUPERSEDED by Decision 16 — the v7 linear-route flat-node model this dogfood has been validating since §17. The section’s own slug records it (...-superseded-by-decision-16); Decision 16 affected_sections includes “30”. §30 specced a markdown-path primitive (move_item subsection-move, classify_blocker/relocate.py, STUCK_CHECKBOX_RELOCATE halt, migrations 008/009 to deprecate+strip blocker schema fields). Decision 16 D6 REMOVES stored blocked status entirely (“transient serve-time relocation trigger only; no-halt by construction”); D1 makes dependencies advisory hints, not enforced edges — so the flat-node model has NO blocker fields by construction. | dogfood-surfaced (§30 build — superseded by the v7 architecture under dogfood) | SUPERSEDED (no build) | Relocation under v7 = a lexorank key-move via route_walk’s serve-time relocation (empirically observed this dogfood skipping blocked format-autodetect), NOT a markdown subsection-item move. The §30 migration slots 008/009 went to unrelated migrations (008_blocks_section_complete, 009_cross_exam_state); §30’s blocker-field migrations were never authored + aren’t needed (flat-nodes have no blocker fields). relocate.py never built. move_item exists (write.py:1730, markdown-path remnant) but isn’t the v7 mechanism. The v7 engine validated across §17-§29 IS the realization. Audit: audits/section-30-supersession.md. |
| 38 | (subject-plan refs below — sections of plans/completed/scripts-first-workflow-architecture, not in plan inventory) §24/§29 (autopilot-pause-leak lint promotion): prose-lint had no per-family strict mechanism (exit is all-or-nothing via --exit-zero), so promoting ONE label family to blocking while keeping others warn-only was impossible. ALSO surfaced: the autopilot-pause-leak patterns over-fire on PLAN bodies (209 hits = legitimate discussion of the patterns in findings/decisions/HISTORY), so a naive corpus-wide strict hook would block legitimate plan commits. | dogfood-surfaced (§29 build — prose-lint lacks per-family strict; patterns over-fire on plan-bodies) | FIXED (—only-label filter + scoped strict hook) | §29.1: added prose-lint --only-label <family> — filters findings to one label_family + exits non-zero ONLY on its hits (_label_family_map() maps label→family from orchestration-rules SSOT). §29.3: autopilot-pause-leak-strict lefthook hook BLOCKING, scoped to skill+command bodies (corpus CLEAN — 0 hits there; plan-bodies’ 209 hits stay warn-only via plan-prose since they’re legitimate discussion). §29.2: scripts/test_prose_lint_autopilot_pause.py (3 tests; the corpus-clean test IS the FPR~0% guarantee). Applied flat-dir glob lesson to the hook. CORRECTED a measurement bug en route: my first “0 corpus hits” scan checked the label key but findings use pattern — re-tested with —json (209 real hits) before scoping. Patterns pre-existed (14 in orchestration-rules); no 50-sample needed (exact phrases + scoped contexts = near-zero FP). |
| 37 | (subject-plan refs below — sections of plans/completed/scripts-first-workflow-architecture, not in plan inventory) §23/§28 (autopilot-default-stage-c) had (a) PLACEHOLDER per-skill items (“replace with concrete work that closes subsection”), (b) a spec contradiction — 28.1-i-004 says document --interactive but §27’s flag-naming-drift gate BANS ad-hoc --interactive (must be --no-autopilot), and (c) incomplete opt-out wiring — all 7 hybrids carried autopilot_default: true (v3 sweep) but were SILENT on opt-out (audit opt_out=N/A), so user-invoked hybrids had no documented way to restore interactive mode. | dogfood-surfaced (§23 build — placeholders + flag contradiction + missing opt-out) | FIXED (opt-out wired, contradiction resolved) | Added [--no-autopilot] to all 7 hybrid argument-hints (using --no-autopilot per §27 gate, NOT --interactive — resolved the contradiction); audit --stage c now reports 9/9 opt_out=supported (was N/A), --stage all exits 0, --self-test passes. Opt-out SEMANTICS kept SSOT in skill-control-contract.md §Autopilot Mode (not duplicated per-skill — avoids operational-rule-leak). Frontmatter flips pre-done. Engine insight (correct behavior, not a defect): the v7 review was INVALIDATED because the 7 skills were edited AFTER the pre-work review — re-review required so the review reflects the shipped content. Lesson: review AFTER building, or re-review after edits. |
| 36 | §20 (blocked-items-promotion) is superseded by the later feedback_no_blocked_by_annotations.md policy + existing enforcement. §20 proposed deprecating <!-- blocked-by:X --> as a long-term tracker + promoting blocked items to letter-suffix siblings via promote_subsection.py. But the established policy is STRONGER and uses a DIFFERENT cure: annotations are BANNED as a cure → MOVE via write.py:move_item (not promote), or deviate-then-come-back per routing.md §6. §20.2’s new detector duplicates STRUCTURE:routing-violation:blocked-by-annotation-as-cure (impl-hygiene.md:193) — SRP violation. §20.4’s mass-promotion would BREAK the legitimate handoff anchors (active-content annotations are §01B/§05/§14A deviate-then-come-back handoffs, not misplaced-item cures). Sixth §17-area spec drift. | dogfood-surfaced (§20 build — superseded by established annotation policy) | DONE (§20.1 real; §20.2-§20.4 superseded) | §20.1: routing.md §4 had NO annotation-ban note (genuine gap) — added the reconciliation citing the established policy + cure + existing enforcement + an explicit “do NOT author a parallel detector” note. §20.2 superseded (line-193 enforcement already covers it; blocker_residual_lint.py gated on unbuilt §30 relocate-on-blocker). §20.3 audit: 96 annotations — _archive/other-plans/decisions/illustrative; zero active misplaced-item cures. §20.4 no promotion (handoffs are legitimate). Audit: audits/section-20-annotation-audit.md. Plan-level note: §17-§20 (2026-05-15 batch) consistently over-specify vs work built since. |
| 35 | (subject-plan refs below — sections of plans/completed/scripts-first-workflow-architecture, not in plan inventory) §19 (test-matrix-golden-cases) spec is redundant with §17 + per-lint tests, AND its coverage gate surfaced a real catalog-honesty bug: the STRUCTURE catalog over-claimed mechanical detection (69 claimed-mechanical, but 16 cite detector scripts that DON’T EXIST). §19.1 (catalog) + §19.4 (rubric) already generated by §17.2 structure_catalog.py + §17.5; §19.2’s 90-fixture golden corpus duplicates the per-lint unit tests + the §17.5 rubric (SRP-banned parallel test path). Re-specced §19 to the genuinely-additive coverage-completeness gate. On first run it found 18 gaps: structure_catalog.py’s mechanical flag was a naive description-heuristic counting ASPIRATIONAL detectors (e.g. blocker_residual_lint.py, runtime_fanout_audit.py — never built) as mechanical. A reviewer trusting “mechanical: yes” would SKIP manual review of those sub-types while no lint catches them → real violations go uncaught. Fifth §17-area spec drift (after §17.7/§17.8/§17A.3/§17A.6-7). | dogfood-surfaced (§19 build — catalog over-claims mechanical detection) | FIXED (reality-grounded classification) | Added is_mechanically_backed(st) (detector resolves on disk OR label is a prose-lint banned_pattern); emit_catalog + emit_rubric both consume it — catalog “Mechanical detection” column shows yes only when a detector truly exists; rubric covers every sub-type WITHOUT a resolving detector. Honest split: 53 mechanical / 26 reviewer-only (was dishonest 69/10). Self-healing: a future entry citing a non-existent detector auto-classifies reviewer-only + gets a rubric entry. Coverage gate test_structure_catalog_coverage.py (CI-gated via run-scripts-unit-tests pre-push). 23 tests green. Audit: audits/section-19-coverage-completeness.md. |
| 34 | (subject-plan refs below — sections of plans/completed/scripts-first-workflow-architecture, not in plan inventory) claude-workflow-lint (the STRUCTURE:claude-driving-workflow:* enforcement class) ran in ZERO pre-commit hooks — the entire enforcement class had no mechanical gate. Surfaced while building §18.1 (verify pre-commit hook integration): the §18.1-required chain names claude-workflow-lint, but grep claude-workflow-lint lefthook.yml returned 0 hook refs. workflow-ownership.md §7 mandates it as a warn-only pre-commit hook; it was authored + self-tested (8 fixtures) but never registered. Directly serves the user’s “enforce script-first along the way” mandate (claude-workflow-lint is script-first’s runtime companion). | dogfood-surfaced (§18 build — pre-commit integration gap) | FIXED (registered warn-only) | Registered claude-workflow-lint as a warn-only pre-commit hook (--staged --warn-only), applying the §18.8 flat-dir glob lesson (.claude/rules/*.md not **/*.md). Recorded in audits/section-18-lint-promotion-ledger.md §18.1 chain-coverage table. |
| 33 | (subject-plan refs below — sections of plans/completed/scripts-first-workflow-architecture, not in plan inventory) 2 lefthook hooks (budget-check, plan-read-discipline) globbed .claude/{rules,commands}/**/*.md over FLAT dirs (0 subdirs) — the lefthook doublestar lib silently matches ZERO depth-1 files, so both lints processed NONE of the flat rule/command files while exiting green. Surfaced on the FIRST run of the §18.8 lefthook_glob_audit.py against the live lefthook.yml. The L14 lesson (condensate-design.md §4) recorded this class empirically; it was un-enforced. | dogfood-surfaced (§18.8 build — first audit run caught live bugs) | FIXED (globs → *.md + blocking audit) | Fixed both globs to *.md; built scripts/skill_audit/lefthook_glob_audit.py (blocking pre-commit on lefthook.yml, near-zero-FP) + STRUCTURE:lefthook-glob-doublestar-leak catalog entry. The audit’s first production run IS the proof — it caught real bugs no self-test could (self-test passes while the hook processes nothing). 7 audit + 11 corpus tests green. |
| 32 | status.md quick-glance “Current section” shows the first in-progress section (here format-autodetect, blocked by a human_gate, 0/8) rather than the served-actionable section (§18). Observed when the §17A→§18 serve skipped blocked format-autodetect and served continuous-enforcement, while status.md still labeled format-autodetect “Current section”. | dogfood-surfaced (§18 serve — render display) | OBSERVATION (not a correctness bug) | Walk SERVES correctly (skips blocked, serves §18); status.md “Current = first in-progress” is accurate but can mislead when that section is blocked. Enhancement (not a defect — both walk + display are correct): render._render_quick_glance could add a “Next actionable” line distinct from “Current in-progress”. Tracked here; not fixed inline (no incorrect behavior; YAGNI until dual-line UX is confirmed wanted). |
| 31 | (subject-plan refs below — sections of plans/completed/scripts-first-workflow-architecture, not in plan inventory) §17A.6 (wire lints into review_plan Step 2) + §17A.7 (§18 lint-promotion roster) over-specify integration that the sibling pattern + §18 already own. Grounding: the sibling §17 lints (operational_rule_leak, plan_body_self_referential_audit, structure_catalog) are NOT wired into review_plan.py OR lefthook — they exist as script + test + impl-hygiene catalog entry, invoked reviewer-time via the cure-pointer citation convention. §17A.6’s review_plan-Step-2 integration would be MORE wiring than any sibling has (over-engineering); §17A.7’s “§18 roster” is a forward-ref to §18 (continuous-enforcement, NOT built — its lint-promotion-ledger at §18.2 doesn’t exist). The lint authoring + cataloging (§17A.1-§17A.5) is §17A’s real job; hook-wiring + promotion is §18’s domain (continuous-enforcement--s-dd5ac4b0.md §18.1-§18.3). Fourth §17-area spec over-reach (after §17.7/§17.8/§17A.3). | dogfood-surfaced (drive-to-100% — §17A.6/.7 integration belongs in §18, not §17A) | SATISFIED per sibling pattern | §17A.6 satisfied by the §17A.5 catalog entries — each cites its detector, which reviewers invoke per the impl-hygiene cure-pointer convention (the catalog IS the reviewer wiring; the review_plan.py Step-2 integration is descoped as over-engineering no sibling has). §17A.7 satisfied as a §18-coordination note: absorption_audit.py + commit_body_rationale_audit.py are warn-only-ready (script + test + --self-test + catalog), to be added to §18’s lint-promotion-ledger when §18.2 builds it (the same cross-section-anchor pattern §17.10/§17A.5 use). §17A spec annotated; §17A verify-completes on its substantive deliverables (§17A.1-§17A.5). |
| 30 | (subject-plan refs below — sections of plans/completed/scripts-first-workflow-architecture, not in plan inventory) §17A.3 specced the commit-body rationale check as a prose-lint.py --commit-body mode + a banned_patterns label family — an SRP/SSOT violation. Grounding before building: prose-lint.py is a PURE FILE linter (zero git integration); scripts/commit_push/message_lint.py is the commit-message linting SSOT (it HALTs on banned patterns); banned_patterns is for file-CONTENT regexes, not commit bodies. Adding a git --commit-body mode to prose-lint would violate its single responsibility, and a commit-body rationale-presence check is not a file-content banned pattern. Third §17-area deliverable (after §17.7, §17.8) whose spec mis-placed the work. | dogfood-surfaced (drive-to-100% — §17A.3 SRP/SSOT mis-placement) | FIXED (built SRP-correct) | Per the UNIVERSAL SRP directive (no carve-out), built a STANDALONE scripts/skill_audit/commit_body_rationale_audit.py — roster-promotable (warn-only), separate from prose-lint (file linter) AND message_lint (banned-pattern halter). Pure git-free predicate audit_commit(touched, body) + a thin git wrapper (git diff-tree + git show -s). Fires STRUCTURE:accidental-complexity-unjustified:commit-body-rationale-{missing,empty} when a complexity-adding commit (new decisions/NN-*.md / new *_runtime/__init__.py / philosophies.md / impl-hygiene.md edit) lacks a rationale: line. §17A.3 re-specced; §17A.5 catalog entry + §17A.7 §18-roster will cite the standalone lint, NOT prose-lint. 8 tests + self-test green. |
| 29 | §17.8 ($comment→_meta orchestration-rules.json migration) was GOLD-PLATING that doesn’t cure its stated goal — DESCOPED. Grounding in the actual consumers before building (the discipline that caught findings 25/27/28) showed: the migration was specced to “cure cross-consumer defensive-filter drift”, but it relocates the sentinel from $comment to _meta (still a sibling key), so consumers STILL need a defensive filter — migration_drift_check.py:101 already does startswith("$") or startswith("_"); exit_reasons_check.py:62,72 skip $; schema-protection.py:DOC_ONLY_KEYS lists $comment. No shared skip-helper is added. The rest is a cosmetic rename + a speculative decision_ref field NO consumer queries — high blast radius (8 keys + 3 consumers + schema + §01/§15/§21 cross-section annotations) for negative real value. Second §17 deliverable (after §17.7) whose spec didn’t survive contact with the codebase. | dogfood-surfaced (drive-to-100% — §17.8 cosmetic gold-plating, doesn’t cure stated drift) | DESCOPED (user-decided) | User-decided “Descope §17.8” when surfaced. Marked §17.8 SUPERSEDED in the content node with the rationale; dropped its 3 §17.N checklist items (_meta migration landed / §01-15-21 coordinate-with annotations / test_orchestration_rules_meta_migration.py) + the Goal bullet. The $comment sentinel works as inline JSON documentation; the architecturally-correct cure IF real filter-drift ever bites is a single shared doc_only_key predicate all consumers import — NOT this rename. §17 now verify-completes on its 10 REAL deliverables (§17.1-§17.7, §17.9, §17.10 + findings 25/28 catalog accuracy). |
| 28 | (subject-plan refs below — sections of plans/completed/scripts-first-workflow-architecture, not in plan inventory) The §17.2 catalog’s mechanical/reviewer-only split was INACCURATE — 6 sub-types with real detectors were mis-classified reviewer-only because their impl-hygiene entries didn’t CITE the detector (the catalog’s mechanical heuristic keys on description keywords). Surfaced building §17.5 (which needs an accurate reviewer-only list): budget-overrun/context-bloat/matrix-as-checklist/transcript-in-body are emitted by budget_check.py (P1-P4) + mission-restatement (3 §17.3A prose-lint patterns) + vocab-violation (34 prose-lint patterns) — all mechanically detected, none cited. | dogfood-surfaced (drive-to-100% — §17.2 catalog heuristic under-classification, §17.6-class) | FIXED | Added Detection: citations to the 6 impl-hygiene entries (budget_check.py P1-P4; prose-lint mission-restatement + vocab-violation families — noting mission-restatement’s duplicate-text aspect stays reviewer-only, like decision-in-implementation’s broad/narrow split). Catalog regenerated: 61 mechanical / 10 reviewer-only (was 55/16). The genuinely-reviewer-only 10 are now the accurate §17.5 rubric set. Same root cause as §17.6 (post-promotion cure pointers must cite detectors so the catalog reflects reality) — the catalog generator is the mechanism that surfaces the gap. prose-lint + 7 catalog tests green. |
| 27 | §17.9’s decisions-by-status used the WRONG status enum — (draft, established, superseded, withdrawn) — vs the decisions/ convention’s proposed | established | superseded. Surfaced grounding §17.1 by reading decisions/00-decisions-convention.md (which defines status: proposed | established | superseded). 22 corpus decision files use proposed — decisions-by-status proposed rejected it as “invalid status”; meanwhile draft/withdrawn are not real statuses. The §17.9 spec itself guessed the wrong enum. | dogfood-surfaced (drive-to-100% — §17.9 status enum guessed, not grounded in the convention) | FIXED | local_intel_query._VALID_DECISION_STATUSES → (proposed, established, superseded) per the convention; updated the test fixture (draft→proposed), intel-query.sh help, + intelligence.md query-table + consumer-list. decisions-by-status proposed now returns the 22 corpus decisions; 7 §17.9 tests green. (Validated by §17.1 grounding — reading the convention before building, not after.) |
| 26 | (subject-plan refs below — sections of plans/completed/scripts-first-workflow-architecture, not in plan inventory) status.md went stale for >1h — render fired ONLY on plan.json mutations (serve/completion), so a long run of deliverable-building commits that don’t mutate plan.json left the quick-glance + Last-Updated timestamp frozen. User-surfaced (“status.md hasn’t run for over an hour, running render.py needs to be injected into many more points throughout the workflow”). Root cause: _regenerate_status_md is wired only into plan_json_write.py (plan.json writes); §17-deliverable iterations commit content/scripts edits without serving/completing, so no plan.json write → no render. §35 (json-only) banned render-on-write PRE-COMMIT HOOKS + .md.rendered content sidecars — but status.md is a status SNAPSHOT (regenerated from plan.json SSOT; cannot drift harmfully), NOT a content sidecar, so a Python-workflow refresh is sound + not the §35-banned leak. | user-surfaced (workflow freshness gap) | FIXED | Added render.refresh_status_md_for_active_plans(repo_root) (re-renders status.md for every active plan dir that ALREADY has one — completed/ + plan.json-less + status.md-less dirs skipped; per-plan non-fatal). Injection point = /commit-push PREPARE Step 0.5 (foreground, BEFORE staging) so the fresh status.md is STAGED + COMMITTED every commit-push and the tree stays clean after. (First tried apply Step 8d / cache_refresh.refresh_all — but that refreshes POST-commit, dirtying the tree + risking dirty_after_commit, and it runs in the detached post-push tail with non-deterministic lag; reverted in favor of the deterministic prepare-phase injection.) §35-compliant: status.md is a status SNAPSHOT regenerated from the plan.json SSOT, not a .md.rendered content sidecar, and this is NOT a lefthook render-on-write pre-commit hook. Refreshed the stale status.md immediately. 3 refresh-helper tests + commit_push suite green. The orchestrator mutation points (serve/verify-complete/mark-reviewed) already render via plan.json write; prepare Step 0.5 fills the non-mutating-commit gap on every commit. |
| 25 | (subject-plan refs below — sections of plans/completed/scripts-first-workflow-architecture, not in plan inventory) §17.7’s spec was architecturally WRONG against HEAD — it conflated the invariant-gate extension-registry with review-plan’s exit_reason mechanism, framed an unbuilt feature as “verify”, and cited drifted composer paths. Surfaced studying §17.7 before building (the careful-before-risky discipline). Three concrete errors: (a) spec said “register decision_in_implementation_redirect in extension_registry.REGISTERED_HALT_STATES per the 6-axis discipline” — but that registry is INVARIANT-GATE-only (every entry callers=INVARIANT_GATE_CALLERS); review-plan owns its exit_reasons via review_plan.py:REVIEW_PLAN_OWNED_CONCRETE/REVIEW_PLAN_OWNED_WILDCARDS (decisions/31 Option C). Registering a review-plan exit_reason in the invariant-gate registry would break its parity tests. (b) The “Verify Phase 2 decision-detection” bullets describe logic that DOESN’T EXIST (grep found zero decision-extraction in the orchestrator) — it must be BUILT, not verified. (c) Composer/template paths cited scripts/plan_orchestrator/{gate_prompts,templates}/ but the real registry location is scripts/plan_corpus/instructions/{gate_prompts,templates}/. User-decided (when surfaced): “Re-spec + build correctly in place.” | dogfood-surfaced (drive-to-100% — §17.7 spec architecturally drifted from codebase) | RE-SPECCED → LINT-PRIMARY (built) | Deeper investigation found the redirect/exit_reason approach was OVER-ENGINEERED at THREE more layers: skill_exit_reasons has NO review-plan key, caller_exit_reason_handlers.continue-roadmap does not dispatch review-plan, and review-plan exit_reasons dispatch INTERNALLY via _dispatch_tpr_exit_reason (not orchestration-rules.json caller blocks). AND the catalog already classifies decision-in-implementation as a reviewer-only DETECTION sub-type (cure: move to decisions/) — so the architecturally-correct §17.7 (per CLAUDE.md §NO SHORTCUTS + YAGNI) is a lint that PROMOTES it to mechanical, exactly like its siblings operational_rule_leak.py / plan_body_self_referential_audit.py — NOT a review-plan exit_reason orchestration. Built: (1) scripts/plan_orchestrator/decision_detection.py (broad predicate, kept as reviewer aid); (2) scripts/skill_audit/decision_in_implementation_audit.py — the §17.7 lint targeting ONLY the LOW-false-positive narrow surface (dated Editor Pass YYYY-MM-DD subsections + numbered Decision N — headings; decisions/ + ## HISTORY + _archive/ exempt; the generic Decision: prose line stays reviewer-only — the §17.3A/finding-23 split-by-noise discipline, since the broad signal fired on 21 corpus files). Lint warn-only (skill-audit promotion protocol); it caught a REAL pre-existing violation (ori-ui-framework/section-02 has 6 inline ### Decision N — headings → its owner moves them to decisions/). impl-hygiene cure pointer cites the lint; catalog regenerated (decision-in-implementation now mechanical, 55/16). 6 lint tests + 8 detection tests + 12 catalog/liveness tests green. (decision_in_implementation_redirect ∈ REVIEW_PLAN_OWNED_CONCRETE retained — supports review-plan surfacing the lint finding as a thin future layer; harmless.) |
| 24 | The subject plan’s v7 conversion ORPHANED 3 markdown-era tests — test_cross_section_gate_section_01_to_14.py reads section-01*.md / section-14-skill-driven-orchestrator-runtimes.md that the conversion REMOVED (FileNotFoundError). Surfaced running the plan_corpus suite during §17.4 work. The §01/§14 content migrated to v7 content nodes (content/invariant-gates--s-90d2c1b4.md + content/skill-driven-orchestrator-runtimes--s-7bdf6a3e.md); the test still hardcodes the removed section-NN-*.md paths + asserts on the OLD markdown deferred_to_section_14 YAML block + §14 bootstrap-exemption header. NOT a regression of this session (the files were removed by the earlier v7 conversion); a markdown-era stale-test artifact. | dogfood-surfaced (drive-to-100% — v7-conversion orphaned markdown-era tests) | ANCHORED to bug-tracker/plans/BUG-07-160/ | The cross-section §01↔§14 dependency is now encoded in plan.json/content nodes, not markdown; the cross_section_check GATE LOGIC is tested elsewhere with fixtures. These are obsolete DATA tests on removed files. Same orphaned-markdown-era-test class as finding-4, re-anchored to bug-tracker/plans/BUG-07-160/ for re-point-or-retire against the v7 content nodes — NOT §11A: per decisions/05-three-plan-types.md the §11A markdown-walk strip is CANCELLED (00-overview.md:163 superseded), so there is no future strip section to own the orphaned test. NOT fixed inline (requires the BUG-07-160 v7-coverage determination; fixing it during §17.4 would expand the front into conversion-cleanup). Pre-existing cross-scope failure; my §17.4 work is green; per autopilot hook-failure clause the commit proceeds + records this disposition. |
| 23 | budget_check.py was documented (routing.md §4 + impl-hygiene.md + §17.2 catalog) to fire STRUCTURE:section-not-promoted but NEVER did — no production script emitted the token. Surfaced by the §17.2 catalog’s detector-liveness check + the §17.4 coverage test: section-not-promoted was claimed mechanical (anchor budget_check) yet grep found it only in a test string. The promotion gate (subsection→section) was designed in routing.md §4 (delivered by archived skill-ecosystem-coherence §11) but the detection was never implemented in budget_check. | dogfood-surfaced (drive-to-100% — §17.4 coverage verification found a never-implemented mechanical detector) | FIXED | Implemented budget_check P6 _check_section_not_promoted — but ONLY the LOW-false-positive trigger (a ## NN.M subsection body >100 lines WHILE the parent section is UNDER budget.body_lines), per routing.md §4. The noisy ≥4 subsections count trigger is deliberately NOT mechanized (it would false-fire on cohesive multi-subsection sections — verified §17’s own 10-subsection content node fires 0; the §17.3A split-by-noise lesson applied). Over-budget parents skip (budget-overrun owns them); subsection length measured to the next ## of ANY kind (not just subsection-IDs). v7 content nodes (budget in plan.json, no frontmatter budget) correctly no-op — INV-18 over-cap split owns v7 sizing. 5 pytest cases + P6 self-test; 0 corpus false-positives. Litter-pickup en route: corrected the §17.4 coverage test’s over-literal work-order-violation assertion (an umbrella category whose mechanical forms topological-inversion/unchecked-items-under-complete ARE emitted by cross_section_check). |
| 22 | (subject-plan refs below — sections of plans/completed/scripts-first-workflow-architecture, not in plan inventory) impl-hygiene.md had 3 DUPLICATE STRUCTURE sub-type definitions — the §17.10 batch (commit 8f2c0d7e) re-added 3 sub-types that already existed, one with a WRONG enforcement scope. Surfaced while building §17.2 as a script (not hand-authoring): the catalog generator’s duplicate-lint found cross-exam-framing-bias:verb (lines 181+209), i34-violation:reviewer-name-leak (182+210), i34-violation:status-anchor-leak (183+211) each defined twice. The canonical 181-183 (the 2026-05-19 cross-exam-absorption originals) carry the correct taxonomy (sub-families A/B/C, the verb sub-family is cross_exam-mode-scoped per prose-lint._MODE_CROSS_EXAM_ONLY_LABEL_FAMILIES). The §17.10 re-adds at 209-211 were not just duplicates but partially WRONG — 209 claimed cross-exam-framing-bias:verb fires on any skill/plan body, contradicting the mode-filter (it is filtered out in blind mode). An SSOT violation (LEAK:scattered-knowledge) a reviewer/tool can’t resolve (which definition wins?). | dogfood-surfaced (drive-to-100% — §17.2 script-first build surfaced §17.10 self-duplication) | FIXED | Deleted lines 209-211 (duplicate + partially-wrong); canonical 181-183 stand. The §17.2 deliverable is correctly built script-first (per the mandate): scripts/skill_audit/structure_catalog.py GENERATES audits/section-17-structure-catalog.md from impl-hygiene.md (the SSOT) — no hand-authored drift-prone duplicate — and ships a reusable duplicate-lint (--check) that mechanically catches future STRUCTURE-family SSOT drift. N=71 distinct sub-types (52 mechanical / 19 reviewer-only). 7 tests incl. a LIVE regression guard pinning zero-duplicates + a catalog-drift guard (committed snapshot must equal generator output). Litter-pickup: added the missing Default: Critical. to the autopilot-pause-leak:runtime-gate-bypass entry (it stated Critical inline but not in the canonical Default: form the generator + every other entry use). |
| 21 | (subject-plan refs below — sections of plans/completed/scripts-first-workflow-architecture, not in plan inventory) verify-and-complete-v7 marks a section completed on DISK-existence of its touches, NOT git-tracked status — a section can be marked complete+reviewed while its deliverable sits UNTRACKED and is never committed (durability/coherence gap). Surfaced when driving §17: scripts/tp_dev_runtime/ (the §16 deliverable, 8 source files) was found ?? untracked (0 files tracked) while §16 (s-d73462f9 tp-dev-pair-programming) is status: completed, reviewed: True in plan.json. Commit fecab03c’s message CLAIMS it built tp_dev_runtime + decisions/06, but its actual --stat shows it committed ONLY parallel-session sweep (bug-tracker/diagnostic-questions, aims-burden, intel-graph) — the new package dir was classified untracked_unknown by commit-push prepare and silently excluded, while the LLM-authored message asserted it landed. verify-and-complete-v7’s touches_exist gate checks Path.exists() (disk), so it passed on the untracked files → §16 marked complete with its deliverable absent from git history. decisions/06 happened to be tracked (committed elsewhere); only the runtime package was orphaned. | dogfood-surfaced (drive-to-100% — completion-vs-commit coherence gap + commit-push untracked-dir silent-exclude) | FIXED (immediate recovery ba7e18db + engine hardening cure 1) | Immediate (ba7e18db): git add scripts/tp_dev_runtime/ (8 source files; __pycache__ gitignored) + commit — the §16 deliverable now tracked; 22 tests + self-test re-verified green. Engine hardening (cure 1 — script-first mandate, LANDED): verify-and-complete-v7 now gates on git-tracked status, not just disk-existence. New VerificationCriterion.TOUCHES_TRACKED: a section QUARANTINES (never completed) when any declared --touch is git-untracked (would be silently dropped at commit). Design keeps verify_deliverables a PURE predicate (untracked_touches: list[str] param) per workflow-ownership; git IO lives in a co-located helper git_untracked_paths(repo_root, paths) (git status --porcelain per touch; fail-open on git-unavailability) called at the CLI boundary (_run_verify_and_complete_v7 computes it + passes it). This is self-enforcing: the executor MUST git add the deliverable before completion → it is staged before commit-push runs → never buried in untracked_unknown. Had this existed, §16 could not have been marked complete with untracked tp_dev_runtime. 4 new tests (test_review_phase_v7.py: quarantine-on-untracked-touch, no-false-fire-on-empty, git-helper tracked-vs-untracked, staged-counts-as-tracked); 257 plan_orchestrator tests green. Cure 2 (optional defense-in-depth, NOT built — YAGNI): a commit-push untracked_deliverable_candidates visibility bucket is subsumed by cure 1 (the deliverable is already staged by completion time); record-only. Process note: the LLM cross-checks the staged set against the deliverable before authoring a completion commit message (applied at b3a2cda6 prepare — verified 8 tp_dev_runtime files staged). |
| 20 | (subject-plan refs below — sections of plans/completed/scripts-first-workflow-architecture, not in plan inventory) §17.3A banned_patterns additions have a corpus false-positive trap — the new rationale-prose / mission-restatement regexes self-fire on the very files that DOCUMENT the ban. §17.3A specs ≥5 rationale-prose + ≥3 mission-restatement patterns for orchestration-rules.json:banned_patterns[] (consumed by prose-lint.py over the .claude/{skills,commands,rules} corpus + plan bodies). Raw-grep shows the proposed regexes (— because, this is because, the purpose is to, this skill exists to) appear in ~13 authored files — but ALL are FALSE POSITIVES: ban-documentation (impl-hygiene.md C-B15 list, skill-vocabulary.md §3, improve-tooling/references/no-prose-rule.md, sync-docs.md, condensate/compaction-phases.md) + tpr-pipeline regression fixtures + design-log surfaces — files that QUOTE the banned phrases as examples. Adding the patterns naively → prose-lint fails the pre-commit gate on the ban-documentation itself. | dogfood-surfaced (drive-to-100% — §17.3A additive-change hidden-corpus-impact) | RESOLVED — split-by-noise (rides next shared push) | Resolution = split-by-false-positive-rate (user-decided when surfaced: “Split by noise level”). Empirical run of all 8 specced patterns fired 26× corpus-wide — 24 on the free-text rationale-TAIL shapes (— because, this is because, due to) hitting legitimate plan prose (a permitted-prose surface) + the SSOT files that DEFINE the patterns. This is exactly the proliferation skill-vocabulary.md §3 declared rationale-prose “reviewer-time only” to avoid — a genuine conflict between the §17.3A spec and the §3 ABSOLUTE. Resolution honors BOTH: mechanize only the LOW-false-positive shapes — 1 structural rationale-section-why-background (banned ## Why/Background/Context/Overview/Rationale/Motivation heading; scope skill+rule+command, plan-bodies EXCLUDED) + 3 mission-restatement phrases (this skill exists to / the mission is to / purpose is to; scope skill+command, rule+plan EXCLUDED to dodge ban-documentation self-fire); drop the 4 free-text tail patterns to reviewer-time-only per §3 (PINNED absent by a coverage test so a re-add is caught). skill-vocabulary.md §3 amended in the same commit to document the split (structural mechanized / tail reviewer-only). The 2 residual fires were REAL violations — fixed as positive pins (litter-pickup): sync-grammar.md banned ## Overview section folded into intro; step-7-8-verify.md “purpose is to” rationale clause cut. 25 coverage tests (test_banned_patterns_{rationale_prose,mission_restatement}_coverage.py) green; prose-lint corpus-clean for the kept patterns. No /add-bug — engine/spec conflict resolved inline by amending the §17.3A spec + the §3 rule, not a v7-engine defect. |
| 19 | (subject-plan refs below — sections of plans/completed/scripts-first-workflow-architecture, not in plan inventory) §17 (decisions-and-structure-category) is a large ENTIRELY-UNBUILT mega-section (~10 orthogonal deliverables incl. risky shared-infra) — building incrementally; first deliverable §17.3 operational_rule_leak.py shipped + a filename spec-drift reconciled. §17 deliverables ALL absent: operational_rule_leak.py, plan_body_self_referential_audit.py, halt_emission_lint.py, audits/section-17-structure-{rubric,catalog}.md, the orchestration-rules.json $comment→_meta migration (8 $comment, 0 _meta — consumed by many scripts, RISKY), intel-query decisions-by-status, 13 impl-hygiene §17.10 STRUCTURE sub-types (0 present), decision_in_implementation_redirect 6-axis wiring. Spec-drift: §17.3 specs a HYPHENATED filename operational-rule-leak.py — Python-import-hostile (no python -m; script_first_audit integration needs import) + inconsistent with every other underscore skill_audit module. | dogfood-surfaced (drive-to-100% — large unbuilt + import-hostile filename spec-drift) | in build (incremental) | Reconciled the filename to import-friendly scripts/skill_audit/operational_rule_leak.py (same discipline as §16 exit_reason reconciliation); built the §17.3 lint (curated rule-SSOT signature detection; @-include + short-citation + prose-lint-off exempt) + 5 TDD pins; self-test + corpus scan clean. Remaining §17 deliverables built across subsequent cron /loop iterations, SAFE/additive first (lint scripts + catalog), the risky orchestration-rules.json migration with care (all consumers re-pointed + dual-read window). |
| 18 | (subject-plan refs below — sections of plans/completed/scripts-first-workflow-architecture, not in plan inventory) §16 (tp-dev-pair-programming) is a GENUINELY-UNBUILT section + its spec has drifted from the live /tp-dev. The dogfood engine CORRECTLY quarantined it (verify_and_complete_v7 → outcome: quarantined, touches_exist fail on absent scripts/tp_dev_runtime) — validating the §06.4 no-auto-fabrication choke point at a real unbuilt section. §16.1-§16.8 spec scripts/tp_dev_runtime/ (package + navigator_envelope.schema.json + stage_manifest.json + applicability.py + decisions/06) — ALL absent on disk. Drift: the live .claude/skills/tp-dev/SKILL.md (role:tool, dispatches the navigator Agent directly) evolved out-of-plan with orchestration SCATTERED across scripts/plan_orchestrator/{tp_dev_dispatch.py,chunk_proposal_scratch.py} (a real script-first §4 consolidation gap — no tp_dev_runtime/ package), AND its exit_reasons (proceed/redirect/architectural-stop/navigator-failure/pair-mode-inapplicable/chunk-proposal-missing) differ from §16’s spec (…pair_cycle_log_full/cap_reached). | dogfood-surfaced (drive-to-100% — quarantine validation + genuinely-unbuilt + spec-drift) | in build | The engine quarantine validates §06.4. Per drive-to-100%: BUILD scripts/tp_dev_runtime/ from the improve_tooling_runtime/ exemplar, consolidating the scattered /tp-dev orchestration, using the LIVE skill’s exit_reasons (SSOT, NOT §16’s drifted list), + applicability classifier (Decision 26) + navigator schema + tests + decisions/06; reconcile the §16 content spec to the live skill. (Focused build — checkpoint committed first.) |
| 17 | verify_and_complete_v7 (the v7 SOLE done-writer) did NOT enforce the reviewed-gate — a section could reach completed with reviewed:false, the exact impossible state the gate exists to prevent. Surfaced when §01 part-3 (s-976fe6ba) was completed via a DIRECT verify-and-complete-v7 call that skipped the mark-section-reviewed-v7 pre-work step; the section reached completed + reviewed:false, caught by route_check.validate_reviewed_gate AFTER the fact (STRUCTURE:route-v7-schema-violation). Finding 9 hardened serve_next_v7 at the flip source, but the completion choke point had the SAME gap. | dogfood-surfaced (finding-6/9 follow-on; SIGNIFICANT — impossible-state at the done-writer) | local (rides next shared push) | Cure (defense-in-depth at the completion choke point): verify_and_complete_v7 now refuses a section whose reviewed is not True — returns new ReviewOutcome.REVIEW_REQUIRED (no attestation written, no work_item flipped) BEFORE verify_deliverables, so the impossible completed + reviewed:false state can never be written. ReviewPhaseResult.verification made Optional (the gate fires before verification; the CLI already None-guards). 2 TDD pins (refuses-unreviewed + positive completes-when-reviewed); 21 review_phase + 514 route/work_item/dispatch tests green. Immediate state cured: part-3 retroactively marked reviewed (it WAS read-in-full + verified; only the mechanical mark was skipped) → route_check clean. |
| 16 | 2 content files over the INV-18 300-line cap slipped through the conversion; the serve/pre-work path handed an over-cap body_ref for WORK without auto-splitting (tpr-pipeline-primitives 675 lines, schema-design 315). The split_over_cap cure + scan_content_dir scanner (finding 3) exist, but nothing wires the size-scan into serve/pre-work, so an over-cap section is served as one 675-line body_ref — violating the INV-18 single-read context-unit contract. | dogfood-surfaced (finding-3 follow-on) | local (rides next shared push) | Cure (existing INV-18 split-cure applied): write split-over-cap --plan ... --section-id ... split tpr-pipeline-primitives → 3 under-cap siblings + schema-design → 2; zero over-cap remain corpus-wide; route_check clean. The split’s pre-write full-plan validation ALSO caught a real INV-18 violation I had just introduced (a - [x] markdown checkbox in the §14A.R finding — v7 content carries id-keyed bullets, never checkboxes), proving the validator works. SERVE-PATH HARDENING (script-first per directive): wire the content_size_lint scan into the pre-work review-as-phase so an over-cap section auto-routes to split_over_cap BEFORE being served for work — follow-up this session. |
| 15 | status.md gave no freshness signal + no at-a-glance status (user-surfaced, flagged 3x: “status.md is still not updating … it still says Status in-progress and Reviewed: false at the top”; “add a Last Updated timestamp”; “show the current section at the top, with progress”). Render-on-mutation (finding 8) WAS firing (status.md mtime current; both mutation paths route through mutate_routing_state._regenerate_status_md — serve via route_walk, completion via work_item_status.flip_work_item_status), but the rendered top showed only the STABLE plan-level header (Status: in-progress / Reviewed: False — normal at plan level, but read as the impossible section-state + as “not updating” because it never changes while the plan is mid-drive). No timestamp, no progress, no current-section glance. | dogfood-surfaced (user directive — status.md must update frequently + be a quick-glance) | local (rides next shared push) | Cure (script-first hardening per user directive): render._render_quick_glance(pd, plan_json, now) adds a Quick Glance block at the top of status.md — Last Updated: <local time> (proves freshness even when the plan-level header is stable; LOCAL wall-clock per user directive, never UTC), Sections: N/M complete (X%), Work items: N/M complete (X%), and Current section/Next up (first in-progress, else front not-started) with its in-section work-item progress + review state. render_status_report(plan_dir, now=None) gains an injectable now for determinism; local wall-clock default in production. 3 TDD pins (block shape + now-determinism; next-up-when-no-in-progress; appears-at-top); 31 render + render-on-mutation tests green. Render-on-mutation confirmed firing on every path — the timestamp now makes that visible. |
| 1 | v7 two-level-walk section_info (section_id/work_item_id/unmet_hints) violated next_action.schema.json $defs/section_info (additionalProperties: false) — every v7 plan dispatch halted with next_action schema violation at /payload/section_info (exit 4) | BUG-07-158 | 63cc3670 | route_walk.py:_v7_payload_to_section_info emits the §07A field names; the schema’s $defs/section_info carried only the v6 node_id/hint_needs. Cure: added the 3 §07A fields (nullable, advisory unmet_hints). Regression-safe: 346 route/schema/parity tests green. Same commit hardened commit_push prepare --exclude-paths to honor sibling *_repo exclusion (was wrapper-only). |
| 2 | v7 route dispatch emitted action: exit with NO payload.exit_kind — the /continue-roadmap skill keys its exit-branch on the exit_kind closed enum, so a served v7 work_item was treat-as-bug and never reached the executor; dogfood halted after serving the first node | BUG-07-159 | 9560f9d1 | roadmap._route_dispatch returned route_walk.next_action verbatim (a pure walk envelope, no exit_kind). Cure: _enrich_route_envelope_for_execution — served node → exit_kind: handoff_to_execution + post_dispatch_resume + autopilot_proceed_directive; drained → exit_kind: plan_terminus. Reuses the markdown handoff SSOT (no parallel v7 branch); route_walk stays a pure walk layer. 2855 plan_orchestrator tests green (byte-identity pins → delegation+enrichment pins). |
| 3 | INV-18 content-size scanner scan_content_dir globbed stale n-*--*.md (pre-INV-12 node-first) — never matched slug-first v7 content <slug>--s-<hex>.md, so the §03 cap was silently unenforced corpus-wide; a 267KB/3062-line over-cap body_ref (invariant-gates--s-90d2c1b4.md) slipped in, blocking dogfood execution of the first node (unreadable as one context unit; can’t reach done while over-cap) | BUG-07-161 | f6fb72d3 (A) + _pending (B) | Part A (root cause, FIXED, f6fb72d3): glob n-*--*.md → *--*.md. Scanner now scans 49 files / flags 1 over-cap (was 0). Part B (FIXED — INV-18 split-cure implemented, the §03/§06.4 deliverable that was marked complete but unimplemented): new scripts/plan_corpus/split_over_cap.py (chunker greedy-packs ## subsections, recurses ###, hard-splits a headerless over-cap block; planner mints sibling s-/w- ids + global lexorank keys + derives section-status rollup + re-emits the work-item manifest per sibling) + write.split_over_cap_section (atomic under flock, pre-write v7 validation) + CLI split-over-cap + invariant_gate self-gating exemption (the split is a structural cure, not plan-order work). Applied to §01: 267KB/3062-line content → 12 under-cap siblings (49→60 sections, 184→195 work_items); route_check clean; zero over-cap files; the engine now serves a 298-line readable body_ref. Dogfood unblocked. 13 split tests green. |
| 4 | test_cross_section_gate_section_01_to_14.py (3 tests) reads the subject’s section-01/section-14 markdown removed by its v7 conversion (content relocated to content/<slug>--<id>.md) → FileNotFoundError | BUG-07-160 | (deferred → BUG-07-160; bug-tracker/open-bugs.json row, status open) | Commit-gate-surfaced (test-all extended check, auto-bypassed by always_commit_with_warnings), NOT surfaced by running the v7 engine. Orthogonal to the route engine (plan_corpus test fixture); defer_separate per routing.md §2. Cure: re-point the test at v7 content files OR retire the markdown-era §01↔§14 handover gate. Owned by bug-tracker/plans/BUG-07-160/ (NOT §11A — its markdown-walk strip is CANCELLED per decisions/05-three-plan-types.md / 00-overview.md:163 superseded; the markdown path is permanent legacy). The §10 corpus-migration re-point of consumers is the natural integration point. |
| 14 | §01 invariant-gates content polluted with ~2000 lines of raw conversation transcript (user-surfaced: “invariant-gates-part5 … seems like a bug”). The §04.2 self-convert step (per scripts-first-restructure/section-04-self-convert.md:110, 2026-05-28) APPENDED all 6 planning narrative docs (conversation.md + concept.md + philosophies.md + reorg-plan.md + phase-2-findings.md + 1) into §01’s content under ## Mined narrative — <doc>.md headers “for provenance” — growing the §01 body 97 bytes → 267 KB — AND archived the originals to _archive/. The append to LIVE content was redundant (provenance is in _archive/conversation.md) + polluting: the 267 KB blob went over the INV-18 cap, so split_over_cap spread the raw chat transcript (Claude Code banner, ❯/● turns, “Crunched for 3m”) across 9 of the 12 invariant-gates-part* siblings; part5 is 299 lines of 100%-transcript. All 12 parts were then marked completed → transcript-only sections rubber-stamped. The _archive/section-01-invariant-gates.md original is 1094 clean lines (ZERO transcript). | dogfood-surfaced (CRITICAL — content pollution) | fixed (de-polluted) | Cure: strip every ## Mined narrative — * block (header through end-of-transcript) from the 12 §01 content files via scripts/plan_corpus/strip_mined_narrative.py (provenance stays in _archive/); a part left with no real body after stripping is content-lost and re-restored from _archive. The §04.2 mining step is the root cause — it must archive-only, never append narratives to live plan content. |
| 13 | (subject-plan refs below — sections of plans/completed/scripts-first-workflow-architecture, not in plan inventory) finding-11 restoration missed placeholder-masked content-dropped sections (user-surfaced: “skill write cascade content empty? a bunch empty”). §13 script-first-global-enforcement (v7 19 lines vs _archive 389) carried a single PLACEHOLDER deliverable - [13.10-i-000] (placeholder — replace with concrete work...) that made the naive has-deliverable check pass, so the finding-11 restoration + --check guard skipped it as “non-empty.” | dogfood-surfaced (finding-11 follow-on) | fixed (restored) | Cure: restore_content_from_archive._is_placeholder excludes conversion-left placeholder stubs from BOTH the has-deliverable check AND the real-content-line count, so a placeholder-only section is detected as content-lost. Re-restored §13 from _archive/section-13-*.md. §14 (skill-driven-orchestrator-runtimes) correctly NOT restored — it has 7 REAL deliverables + 1 placeholder subsection (14.3B), so it is genuine content with one stub, not a content-loss. 3 new TDD pins (placeholder-masked flagged; real+placeholder clean). The --check guard now catches the placeholder-mask class. |
| 12 | (subject-plan refs below — sections of plans/completed/scripts-first-workflow-architecture, not in plan inventory) v7 has no final-gate / complete-last marker — §11 (code-journeys-and-consumer-audit) contains §11.7, a FINAL closing gate “gated by ALL prior sections reviewed: true” (like §RR the terminal handback), but §11 sits mid-walk. The v7 model has no way to express “this section completes LAST / after all prior” — hint_needs is advisory-only (never a gate per INV-6). So the dogfood could prematurely complete §11.7 before its all-prior-reviewed precondition holds. | dogfood-surfaced (architectural) | fixed (final_gate relocate) | Cure (generalize the finding-10 relocate-past-blocker): add a section.final_gate v7 schema marker; extend route_walk.relocate_human_gates to relocate BOTH human_gate AND final_gate sections past the autonomous ones (a final_gate sorts to the tail like §RR). Terminal behavior differs: a human_gate HALTS (needs an out-of-band human) when only deferred sections remain; a final_gate COMPLETES autonomously when reached (its all-prior-reviewed precondition is satisfied once every autonomous section is done). §11 marked final_gate → relocated to the tail; the dogfood serves the autonomous sections first + completes §11 last. |
| 11 | CRITICAL conversion data-loss: the §07A.5 markdown→v7 conversion dropped section BODY content + supersession metadata for 30 of 60 sections (user-surfaced: “why is skill-rewrite-cascade content empty? a bunch are empty, just #headers and ## Items”). The §07A.5 regroup (commits 3461f8c2 + 6ff3f516) produced v7 content/<slug>--<id>.md files carrying ONLY the section header + a node header + the ## Items work_item manifest — the full deliverable spec (the - [NN.x-i-yyy] items, the prose, the frontmatter) was DROPPED. Example: §06 skill-rewrite-cascade went 527 lines → 9 lines; the full original survives at _archive/section-06-skill-rewrite-cascade.md. Of the 30 empty: ~11 are GENUINELY SUPERSEDED (archived frontmatter superseded_by: scripts-first-restructure/section-09 — §06 skill-rewrite-cascade, §05 corpus-tooling-rewrite, §01B deferred-review-findings, json-only-architecture, zero-halt-doctrine, etc.) and the conversion ALSO dropped their superseded_by so the v7 plan treats them as LIVE work; ~19 are pure CONTENT-LOST (full deliverable spec in _archive/section-NN-*.md, dropped from v7). | dogfood-surfaced (CRITICAL — data loss + dogfood-validity) | RESOLVED (restored) | Invalidates dogfood completions: §01B + §05 are SUPERSEDED (driven as live work + “completed” — wrong; they should be marked completed-as-superseded, NOT verified against inferred deliverables); §03 + §04 were CONTENT-LOST (completed by inferring deliverables from the slug since the spec was gone — unreliable). The dogfood has been driving a BROKEN v7 plan: superseded sections appear live; content-lost sections have no deliverable spec to verify against. Cure (design, in progress): (a) the converter (convert_plan_dir_v7.py) MUST carry the full section body + superseded_by/superseded_at frontmatter (mapping superseded→a v7 completed+superseded marker, NOT a live node); (b) RE-CONVERT the subject from the _archive/section-*.md originals to restore the 19 content-lost specs + mark the 11 superseded; (c) the dogfood’s prior completions (§01B/§03/§04/§05) are re-validated against the restored content. Until re-converted, the v7 subject is NOT a faithful representation of the plan — the dogfood is paused pending re-conversion. RESOLUTION (user-authorized “fix converter + re-convert”): scripts/plan_corpus/restore_content_from_archive.py maps each empty content file to its _archive/section-<NN>-*.md via the §NN header (100% exact, 0 unmatched), strips frontmatter + converts INV-18-banned - [ ] checkboxes to bullets, preserves the v7 ## Items manifest. Restored 23 content-lost sections (route_check clean; 2 over-cap deferred to split_over_cap at completion). Added section.superseded_by v7 schema marker; the 7 superseded sections (folded into scripts-first-restructure §02/§03/§06/§09) get a SUPERSEDED note + superseded_by + completion attestation + work_items completed (completed-as-superseded, NO live deliverable verification). Recurrence guard: restore_content_from_archive --check exits 2 if any non-completed section has an empty body (CI-runnable); 7 TDD pins. The v7 subject is now faithful (22 completed incl. 7 superseded, 37 not-started with restored content, 1 human-gate §05A relocated); the dogfood serves real restored sections (front = §07 render-and-completion) and skips superseded ones. |
| 10 | v7 walk has NO relocate-past-blocker / human-gate handling — the dogfood cannot reach status:complete autonomously. §05A (format-autodetect-deprecation-timer) contains §05A.4, a HUMAN-GATE work_item (w-38f43b72): an operator must run migrate_remaining_md_plans.py --auto on the production corpus OUT-OF-BAND (Claude must NOT run --auto), and §05A.5/§05A.6 (the cutover) subsection_depends_on §05A.4. The §05A spec assumes the autopilot routes §05A.4 through STUCK_CHECKBOX_RELOCATE (per amendment-mission.md §30 + Decision 10: relocate.classify_blocker(), [HUMAN-GATE] title-prefix discriminator, --bypass-gate stuck_checkbox, exit_kind: section_terminus_advance) — ALL markdown-path concepts. The v7 walk (route_walk._v7_walk) is strict-forward-only (INV-19/INV-20: “NEVER skips past an in-progress work_item”, no blocked status in the enum) with NO relocate primitive; relocate.py does not exist for plan_orchestrator; the v7 plan.json carries NO human-gate discriminator (the conversion dropped the [HUMAN-GATE] marker — the content file has “HUMAN STEP” PROSE only). Result: the walk serves §05A’s work_items in order and will block forever at §05A.4 (un-completable autonomously) with no escape. | dogfood-surfaced (SIGNIFICANT — architectural) | OWNED by §09B (v7 relocate/defer merge layer; not-started) | Two-dimensional gap: (1) no v7 human-gate discriminator — the v7 sections[]+work_items[] model has no structured human-gate field; §07A conversion carried only the prose “HUMAN STEP”. (2) no v7 relocate primitive — the strict-forward-only walk cannot move a human-blocked section past the autonomous ones; the markdown path’s relocate.classify_blocker() + STUCK_CHECKBOX_RELOCATE has no v7 analogue. The §06 engine (complete) shipped serve_next strict-forward + the §40 relocate primitive but NOT the v7 human-gate marker / relocate-past-human-gate behavior, so this gap is engine work §06 closed without; it lands in the v7 relocate/defer merge layer §09B owns (serve_next_with_cross_plan hard-defer; 00-overview.md:128 walk §09 → §09B → §10; 00-overview.md:161 §09B not-started). Cure (a) add a structured human-gate marker to the v7 work_item/section schema (so the engine detects it, not prose); (b) port relocate-past-blocker to the v7 walk — a human-gate section relocates to after all autonomous sections (its lexorank key moved past the max), the walk completes §06–§RR first, and §05A surfaces a human_gate_required halt for the operator; (c) reconcile with INV-19/INV-20 (relocate is a key mutation preserving strict-forward-order, NOT a walk-time skip). NOT a §09 close gate (the §09.4 dogfood reached terminal via blanket OBE supersession, which removed §05A.4 from the live walk). A future v7 plan carrying a genuine human-gate work_item hits it; the deliverable lives in §09B’s structural cross-plan / relocate-merge scope. |
| 9 | The reviewed-gate was enforced ONLY at corpus-check (route_check.validate_reviewed_gate), NOT at the flip source: route_walk.serve_next_v7 → flip_work_item_status flips a served not-started work_item to in-progress with NO reviewed check, and the mutation validator (validate_v7_plan_json) does not carry the gate → plan.json can TRANSIENTLY hold the reviewed:false + in-progress impossible state (only flagged later by corpus check). With render-on-mutation (finding 8) firing, that transient becomes VISIBLE in status.md (user surfaced it: “in-progress reviewed false”). | dogfood-surfaced (finding-6 follow-on) | local (rides next shared push) | The roadmap STEP 3d dispatch gates on section_reviewed before calling serve_next_v7, but nothing enforced it AT the flip — any other caller (or a race) could create the impossible state. Cure (defense-in-depth at the flip source): serve_next_v7 now raises ReviewGateViolation when asked to flip a not-started work_item whose section is unreviewed (plan.json left unmutated); a not-started+unreviewed section MUST route through the PRE-WORK review-as-phase first. Positive pin test_serve_next_v7_refuses_to_flip_unreviewed_section + fixture updates (serve_next_v7-flip tests now model a reviewed not-started section). 66 route-walk/dispatch tests green; 2874 plan_orchestrator green. |
| 8 | status.md staleness (user-surfaced): status.md (the tracked human/LLM snapshot) was regenerated ONLY at commit time + per manual render call, so during the per-section dogfood drive it LAGGED plan.json — the user saw an apparent impossible state (in-progress reviewed false) that was a STALE snapshot (plan.json itself was gate-valid: §05A in-progress+reviewed:true). “How did it auto-correct?” = regenerating status.md from plan.json (the SSOT) brought it back in sync. | dogfood-surfaced (user directive: render substantially more often, it’s a cheap pure script call) | local (rides next shared push) | Cure (script-first — the engine owns status.md freshness, not manual LLM render calls): wired render_status_report into the plan.json mutation chokepoint plan_json_write.mutate_routing_state (_regenerate_status_md, default-on via regenerate_status=True, opt-out for bulk callers). Now EVERY mutation (pre-work review, work_item flip, completion, split, normalize) regenerates status.md atomically inside the flock — status.md never lags the routing SSOT. NON-FATAL: a render failure never breaks the (already-written) mutation (lazy import avoids a cycle). 4 pins in test_plan_json_write.py (regenerates / opt-out / non-fatal / no-op-skips); 2609 plan_corpus green. Pairs with finding 9 (flip-source gate) so render-on-mutation can never SHOW an impossible state. |
| 7 | v7 dispatch HALTED on the live dogfood run: _v7_payload_to_section_info emits section_reviewed (the reviewed-gate dispatch field, finding 6) into payload.section_info, but next_action.schema.json $defs/section_info (additionalProperties:false) did not declare it → every python -m scripts.plan_orchestrator roadmap <v7-plan> exited with next_action schema violation at /payload/section_info: Additional properties are not allowed ('section_reviewed' was unexpected) | dogfood-surfaced (finding-6 follow-on) | local (rides next shared push; see BUG-07-164) | The BUG-07-158 class recurred for the new field: a v7 section_info field added at the route_walk emit site without the matching $defs/section_info schema declaration. Surfaced the FIRST time the full orchestrator path (not just _route_dispatch unit tests) ran on the live subject plan — the unit tests returned the envelope but never validated it against the schema. Cure: added section_reviewed (["boolean","null"]) to $defs/section_info + a regression pin test_route_dispatch_v7_envelope_validates_against_schema that jsonschema-validates the full v7 dispatch envelope (closing the unit-test gap that let finding 6 ship without schema coverage). 11 route-dispatch tests green; orchestrator now routes the front section to the pre-work review-as-phase cleanly. |
| 6 | v7 plan could hold the impossible lifecycle state reviewed: false + status: in-progress — the markdown-era conflation of “plan reviewed” and “code reviewed” into one flag leaked into the v7 shape, so a section could start work without a plan-shape review gate AND the /tpr-review code-review status had no independent field | design directive (user) | 4adeea94 | User-directed split (NOT a soft bug — caught during the dogfood drive): section.reviewed (plan-shape review-as-phase gate; a section reaches in-progress/completed ONLY if reviewed:true) is now SEPARATE from section.tpr (code-review status enum none/findings/resolved/clean/cap_reached_*). Both additive/optional in schemas/v7/plan-routing.schema.json. Invariant enforced by route_v7.validate_reviewed_gate, wired at corpus-check level (route_check._check_v7_dir) NOT in the structural validate_v7_plan_json — so a mid-split transient never trips shape validation. split_over_cap carries reviewed/tpr onto sibling 1 (already reviewed pre-split); fresh in-progress/completed siblings get reviewed:true; convert_plan_dir_v7 reconciles legacy sections (reviewed = status in {in-progress, completed}). Subject reconciled: normalized to 12 completed / 0 in-progress / 48 not-started, route_check clean (12 completed+reviewed, 48 not-started+unreviewed). Same commit landed the tracked status.md snapshot (uppercase READ-ONLY banner + index + linear walk); a follow-up (commit 92ea0b43) focused it to inline ONLY the in-progress/front section per the user’s refinement (not the full-plan dump). ENGINE PIECE DONE (commit 8760c1a7): the dedicated PRE-WORK review-as-phase that SETS reviewed:true before work — review_phase.mark_section_reviewed_v7 (the SOLE reviewed-flag writer; verifies body_ref content present + executor attestation non-empty, sets reviewed:true, section stays not-started), route_walk section_info carries section_reviewed, dispatch routes not-started+unreviewed → PRE-WORK review (kind=pre_work, no flip) and not-started+reviewed → flip-to-in-progress + COMPLETION review (kind=completion), CLI mark-section-reviewed-v7. The two review-as-phases gate the START vs END of work; an unreviewed section never reaches the reviewed:false + in-progress impossible state. 7 TDD pins (incl. negative corpus-invalid pin) + dispatch pins; 2871 plan_orchestrator + 2605 plan_corpus green. Dogfood resumes: each of the 48 not-started sections flows pre-work-review → in-progress → completion-review. |
| 5 | v7 orchestrator walk has no completion path — review_phase.verify_and_complete (the SOLE INV-17/INV-20 done-writer) has zero non-test callers AND is entirely v6-only (_node_dict/_write_done iterate plan_json["nodes"], which a v7 plan has not). A served in-progress node re-serves forever; no v7 plan can reach status: complete | BUG-07-162 | STEP 1-3d done — full v7 completion engine wired; §01 driven to done / driving remaining sections | Two dimensions, both diagnosed: (1) wiring — roadmap.py/route_walk.py never invoke review-as-phase, though §06 design (section-06-engine.md:196,:239) specifies route_walk invokes it as the completion choke point and that an in-progress served node means “the caller finishes its review”; the v7 roadmap path uses next_action (peek), never routing in-progress→review. (2) v6-only choke point — the entire review_phase verified-completion path (verify_and_complete/_node_dict/_write_done) operates on the v6 nodes[] array and cannot touch a v7 sections[]+work_items[] plan. Cure (major §06.4/§09.2 engine deliverable): adapt the verified-completion choke point to the v7 two-level model (verify deliverables → flip the section’s work_items to completed via flip_work_item_status → derived section-status rollup → write the INV-17 attestation + INV-20 gates_verified to the v7 shape), THEN wire it into the v7 walk (in-progress served node → review-as-phase → complete/quarantine/split-per-BUG-07-161/exhausted → serve_next advances). The genuine per-node evidence (deliverables + tests + improve-tooling + gates) is supplied by the review-as-phase, never auto-fabricated — auto-completion would defeat the dogfood. STEP 1+2 DONE + tested (2859 plan_orchestrator green): (§03.1) v7 schema gains the optional Section.completion attestation object (body_hash/verified_at/gates_verified minItems:1/verifier) — additive, non-breaking (subject has 0 completed sections); reconciles INV-3 routing-only (exclusion list omits completion) with INV-17. (§06.4) review_phase.verify_and_complete_v7 — the v7 SOLE done-writer: verify_deliverables on a Node view of the section → on pass write section.completion (v7 validator) THEN flip work_items to completed via flip_work_item_status (derived rollup); over-cap → SPLIT_REQUIRED; fail → QUARANTINED/completion_verification_exhausted. 4 TDD tests. STEP 3a+3b DONE — the v7 completion cycle works end-to-end: (3a) cli verify-and-complete-v7 — the review-as-phase invocation surface (the executor supplies genuine evidence: --touches/--gates-verified/--improve-tooling-consulted; emits a next_action envelope with the outcome). (3b) _enrich_route_envelope_for_execution routes a served in-progress section to review-as-phase (payload.review_as_phase carrying the verify command; added to next_action.schema.json); a not-started section keeps the plain execution handoff. DOGFOOD: §01 sibling-1 (s-90d2c1b4) driven to completed — genuine evidence (real deliverables invariant_gate.py+normalize_cli_context.py verified, tests pass, attestation written, work_item flipped); serve_next advanced to sibling 2. 2862 plan_orchestrator green. STEP 3d DONE — full engine wired: the v7 dispatch write-on-serve flips a NOT-STARTED served section to in-progress (serve_next_v7) and reflects it in the envelope so _enrich routes it to review-as-phase; the walk now progresses past every node (the verified-completion gate quarantines a node whose deliverables are genuinely missing, so nothing re-serves forever). Verified: sibling 2 (s-88ed2828) flipped not-started→in-progress + routed to review. The full cycle (serve → flip → review-as-phase → verified-completion → done → advance) turns automatically. 2862 plan_orchestrator green. Remaining = mechanical dogfood drive: complete the 59 remaining sections via review-as-phase with genuine per-section evidence, surfacing any further engine bugs, until the subject reaches status: complete and §09.4 closes. |
09.4B — SMOKE TEST 2: convert + dogfood plans/roadmap (converter stress test)
Post-completion note: §09.4B is complete (was blocked-on 09.4; the 09.4 dogfood gate closed with the subject plan terminal, then 09.4B ran — see HISTORY). User directive 2026-05-30: the roadmap was a second, harder dogfood — especially for the v5→v7 CONVERTER.
- Subject:
plans/roadmap/— an insanely large plan using very old formats, inconsistent shape “all over the place”. Where §09.4 dogfooded the v7 ENGINE on an already-v7-shaped subject, §09.4B dogfoods the CONVERTER (scripts/plan_corpus/migrations/006_md_to_json.py) on the hardest real-world input: a massive, old-format, irregular corpus. The roadmap’s age + scale + format-drift stress the converter far beyond the clean subject plan. - Protocol (gated on 09.4 close): (1) run
006_md_to_jsononplans/roadmap/; (2) find + fix every CONVERTER defect the old formats surface (malformed/legacy frontmatter, irregular section shapes, missing fields, ordering ambiguity, oversized sections needing INV-18 split) — converter hardening per the script-first mandate; (3) drive the converted v7 roadmap through the v7 engine (serve → review-as-phase → verify-and-complete) finding any further engine bugs; (4) record each defect + fix in a## 09.4B Dogfood Findingslog (defect class, BUG-XX-NNN, fixing commit SHA) BEFORE this subsection closes, mirroring the §09.4 fix-and-record protocol. - Why it is a better converter test: scripts-first-workflow-architecture was authored v7-aware; the roadmap predates the v7 model entirely, so it exercises converter paths (legacy-format normalization, scale, irregularity) the clean subject never touches.
- Subsection close (09.4B): converter runs clean on
plans/roadmap/(or every surfaced defect fixed + recorded); the converted roadmap validates (route_checkclean); findings log complete. Does NOT gate §09 close (09.4 is the §09-close gate); 09.4B is an additive second smoke test.
09.R Third Party Review Findings
- None.
09.N Completion Checklist
WORK-COMPLETE items (the §09.1-09.4 deliverables) are [x] with inline evidence; the CLOSE-OUT GATE items below remain - [ ] because §09 is status: in-review (not complete) and §09.N is not-started — these gates fire at section close-out (the §00.3 close-out flip), not during plan-shape review, and are honest pending gates rather than fabricated completions.
Work-complete (§09.1-09.4 deliverables shipped):
- 09.1-09.4
[x]andstatus: complete— the four work subsections arecompletein thesections:roster with every body item[x](09.1 lines 163-168, 09.2 lines 172-179, 09.3 lines 183-195, 09.4 lines 201-207). - Script-first 4-axis rubric clean on the v7-path additions:
python3 scripts/skill_audit/script_first_audit.py --skill continue-roadmapAND--skill create-plan(the skills §09 added v7 route_walk dispatch to) both report[ok](the in-tree 4-axis scorer atscripts/skill_audit/script_first_audit.py; CLI--all/--skill <name>/--self-test/--json); the audit confirms the v7 dispatch lives inscripts/<skill>_runtime/(route_walk/engine), the SKILL.md bodies carry directive-onlynext_action-consumption pointers — no plan reading, no scratch-dir branching, no pseudocode-bloat, no raw-output dumps (evidence at §09.2 line 173). The corpus-wide--allis NOT a §09 gate: it carries pre-existing[MAJOR]script-first debt in skills §09 did NOT rewrite for v7 (impl-hygiene-review,review-work,rosetta-test,tp-help,tpr-review, +review-plan’s pre-existing scratch-dir leak) — that debt is owned by the per-skill Lazy-Migration tickets perscript-first.md §7, not by §09’s additive-v7 scope.prose-lint.pyis clean on every touched skill body. The route-consumer-completeness audit (scripts/skill_audit/route_consumer_audit.py, 9/9 green) PROVES the closed set of 11 consuming skills is complete (consumer_skills ⊆ eleven,outside_set = ∅).plan-read-discipline-lint.py --strictexit 0 against the v7 path. - Markdown path still functional: a markdown plan still runs through the existing focus-picker (no regression) — additive contract held. Regression coverage:
scripts/plan_corpus/tests/test_detect_route_mode.py::test_section_md_only_routes_markdown(line 76; pinssection-*.md only => markdown, blocking a future edit from regressing a markdown-only plan onto the v7 walk) + the markdown focus-picker behavior suitescripts/plan_orchestrator/tests/test_focus_picker_failure_paths.py/test_focus_picker_dag_aware_review_walk.py/test_focus_picker_complete_bug_blocked.py. BUG-07-160 (markdown-era orphaned-test cleanup) isdefer_separateand does NOT gate this claim — it is a stale data-fixture test on removed subject files, not a focus-picker regression. - DOGFOOD GATE closed:
plans/completed/scripts-first-workflow-architecturedriven to terminal end-to-end via v7 (54/54: 35 completed + 19 superseded, INV-17 attestation + INV-20 gates, no force-flip); 25 engine defects found + fixed (§09.4 Dogfood Findings log); handback recorded at §09.4 line 206 (per §09.4 lines 201-207).
Close-out gates (fire at the §00.3 close-out flip, not during plan-shape review):
- All success criteria flipped at close-out (the
success_criteria:frontmatter array is the SSOT; verified item-by-item against the §09.1-09.4 evidence when §09 flipsin-review → complete). — close-out gate, owned by §00.3 close-out flip. -
python -m scripts.plan_corpus check plans/scripts-first-restructure/section-09-*.mdexit 0 — close-out gate, run at the §00.3 close-out flip. exit 0 -
/tpr-reviewpassed (final, full-section) —third_party_review.statusis currentlynone; the final full-section TPR runs at close-out (owned by §00.3 close-out flip //review-planStep 6). (/review-plan ran 3 /tpr-review round(s); review_pipeline stage=verify-done; third_party_review.status=clean)
References
- §06 engine (route_walk + cure_dispatch + bugs-as-nodes); §08 hook; §07 path-scoped commit.
- The markdown-walk path is RETAINED permanently as legacy support per
decisions/05-three-plan-types.md(the §11A strip is CANCELLED —00-overview.md:163-164mark §11A/§11Bsuperseded; the corpus is a three-type system — json (v7), legacy-markdown (KEPT), json-dynamic). §09 only ADDS the v7 path; no later section removes the markdown path. .claude/rules/script-first.md,workflow-ownership.md,plan-read-discipline.md,context-discipline.md(last two gain the v7 single-read model additively perdecisions/02-content-as-context-unit.md).- §01 invariants 1, 2, 18, 19, 20; R6Q23;
references/restructure-charter-seed.md §2 INV-20(strict-forward-only progress + force-flip ban — v7 path). - Cross-plan dependency:
00-overview.md §Cross-plan dependency; subject planplans/completed/scripts-first-workflow-architecture(dogfood subject + close-out handback).
HISTORY
- 2026-05-30 — Autopilot auto-cure: review_plan_redispatch_loop reset_lost_dispatch (autopilot_run_id=e637f8c9737b4b8e91736601df98d54d); chain log recorded a phantom /review-plan dispatch but section frontmatter showed zero review evidence; chain counter reset and /review-plan re-dispatched (per state-discipline.md §4 Hard-abort terminal-state semantics + skill-control-contract.md §Autopilot Mode unified hook-failure continuation clause).
- 2026-05-30 — commit-push cross-plan exclusion hardening (script-first, surfaced committing §09.4B): the cross-plan sweep guard
_cross_plan_exclusionsemits directory-prefix globs (plans/<other>/), but the SSOT matcherscripts/commit_push/triage.py:_matches_any_globonly ranfnmatch+**and never implemented the prefix-glob semantics its own docstring promised — soplans/aims-burden-tracking/matched zero nested section files and a parallel session’s dirty plan files were swept into this run’sscope_paths. Fix: implemented the documented directory-prefix contract (a glob ending in/matches the dir itself + every path under it). Fixes EVERYexclude_pathsconsumer, not just cross-plan. TDD:test_exclude_paths_dir_prefix_glob_excludes_nested(matcher unit) +test_emitted_globs_actually_exclude_other_plans_nested_files(end-to-end throughapply_scope_restriction— the coverage gap that let the bug ship: prior tests asserted only the emitted glob STRINGS, never ran them through the matcher). 476 commit_push tests green. - 2026-05-30 — pre-push
scripts-unit-testsgate made parallel-work-safe + path-gated (user directive): the push of the §09.4B work blocked at lefthook pre-push exit 124. Root cause (diagnosed, NOT the baseline-sha-verifier): thescripts-unit-testsgate ran the WHOLE scripts/+skills suite (grown to 7966 tests / ~179s serial) under one 150s cap on EVERY push — so aggregate growth + cross-session CPU contention trip the cap and block all pushes; it also ran when no scripts changed. Fix (user-chosen “scope to changed test dirs”): (a) lefthookglob: {scripts/**,.claude/skills/**}so the command skips entirely on non-scripts pushes, passing{push_files}; (b) newscripts/pre_push_test_scope.pymaps each changed file to its owningtests/dir (or co-locatedtest_<name>.py), andrun-scripts-unit-tests.shruns ONLY those (the session’s scoped run: 3191 tests / 81s, green). 15 helper tests. The scoping ALSO unmasked 4 failures + 3 skips inscripts/plan_corpus/tests/the exit-124 timeout had been hiding (the full suite never reached its summary):test_subject_plan_is_servable,test_cross_section_gate_section_01_to_14(3),test_roster_gateskips (3) — all pinned the subject plan’s PRE-v7 markdown layout / mid-dogfood state that the §09.4 dogfood superseded (plan now v7 + 54/54 terminal). Repointed (NOT deleted — §No-Test-Weakening): cross-section gate reads the v7content/*.mdset;is_servable→fully_terminal(stronger pin of the dogfood’s achieved end state); roster live-smoke → synthetic fixtures + a v7-transition pin. 30 repointed tests green. - 2026-05-30 — Stale
review_pipeline:marker cleared by /continue-roadmap orchestrator: marker carriedstage: ?,next_step: ?,updated: ?. Per /review-plan SKILL.md §Step 1a stale-marker rule (reviewed: false+ marker present → STALE by definition), marker invalid; prior diagnosis preserved here for traceability. Cure rooted inscripts/plan_orchestrator/markers.py:clear_stale_marker_if_unreviewed. - 2026-05-31 — B13 commit swept parallel compiler_repo WIP (per §Git Safety + §Autopilot trust-the-script): the B13 converter-fidelity commit (wrapper:
scripts/plan_corpus/convert_plan_dir_v7.py+ this section + regeneratedplans/roadmapv7) co-discovered 3 dirtycompiler_repoRust files left by a parallel aims-burden-tracking session (closures.rs,higher_order.rs,burden_compose/closure/tests.rs). Perskill-control-contract.md §Autopilot ModeClaude-side-gate-eval ban (do NOT filter parallel-session work; trust the script’s scope) + CLAUDE.md §Git Safety (commit swept files beats losing work), both repos committed with their own messages; any compiler_repo presence-class hook failure auto-bypasses under the standingalways_commit_with_warningsuser config. - 2026-05-31 — §09.4B subsection closed (status → complete): all close criteria met + verified — (1) converter runs clean on
plans/roadmap(every surfaced defect B1–B13 fixed + recorded; commit-push B9 fixed); (2) the converted roadmap validates —route_check.check_route_dirreturns 0 findings,plan_corpus checkexit 0, F1–F5 clean; (3) findings log complete; (4) engine drives —route_walk.peek_next_v7servesw-5b041d9b[lexical-grammar] with the correct body_ref. Content fidelity is total: a line-level_archive-vs-v7 audit of all section content shows 0 / 14,467 substantive lines dropped (volume ratio 1.024); the whole-plan audit (B14) confirms00-overview.md+index.mdare preserved verbatim in_archive/(tracked at HEAD), not lost. B6 L5 (phase-local-to-roadmap v7 write-API section-create) + B14’s plan-leveloverview_ref(engine-accessible plan overview) stay recorded deferrals to the §10/§11 v7-write-API charter — neither is a §09.4B gate. §09.4B does NOT gate §09 close (§09.N section-level gates + §09.R review remain).
09.4B Dogfood Findings
Each row = one CONVERTER defect the roadmap (pre-v7 legacy format, 48 sections / 4580 work_items) surfaces — per the §09.4B converter-stress-test protocol. Converter hardening per the script-first mandate.
| # | Defect class | Detail | Fixing commit | Notes |
|---|---|---|---|---|
| B1 | subdir body_ref for letter-suffix sub-overview sections (intermediate-path artifact, NOT a production defect) | Surfaced only when validating the INTERMEDIATE 006_md_to_json full-emit v6 output against the v7 schema directly (body_ref: content/section-15B/15B-overview.md subdir form). The PRODUCTION converter convert_plan_dir_v7 consumes the 006 PARSER (_load_006_parser → subsections[]), not the 006 migration emit, and re-emits flat slug-first content/<slug>--<id>.md body_refs per INV-12. The full path produces valid flat body_refs for all 48 roadmap sections. | n/a (no production defect) | Re-classified: B1 was an artifact of validating the wrong intermediate (006 v6 emit) against the v7 schema; the production md→v7 path never emits subdir body_refs. |
| B2 | legacy depends_on refs don’t resolve (intermediate-path artifact, NOT a production defect) | Surfaced only on the same intermediate 006-emit path (depends_on reference '7A' does not resolve). The production convert_plan_dir_v7 carries hint/dep edges as hint_needs (advisory-only per INV-6) and DEFENSIVELY DROPS refs absent from the plan (reshape_v6_to_v7: “a hint to a node absent from this plan is dropped”); md→v7 emits hint_needs: []. No unresolved-ref gate fires on the production path. | n/a (no production defect) | Re-classified: advisory-only edges are dropped defensively, never gated; the unresolved-ref error came from the stricter intermediate-v6-schema validation, not the v7 emit. |
| B3 | duplicate / id-less source item id → duplicate w-id (GENUINE production defect) | Full convert_plan_dir_v7 plans/roadmap aborted at work_items[493].id duplicate across plan: 'w-90502e51'. Root cause: the 006 parser mints item_id = f"{sub.id}-i-{ordinal:03d}" and work_item_id(plan, item_id) keys on the source id ALONE (section-independent per decisions/04, so a work_item keeps its id across moves). The legacy roadmap has duplicate sub.id headings + id-less items, so two source items share one source id — by the section-independence design they ARE the same work_item → duplicate-id plan. | (this commit) | Fix: unique-source-id pre-pass in convert_plan_dir_v7.reshape-section loop — synthesize a deterministic <raw or 'noid'>#<ordinal> for every empty / colliding source id BEFORE work_item_id is computed, mutating item["id"] in place so the work_items[] build AND the body-description render mint the SAME unique w-id. Restores the globally-unique-source-id precondition the section-independent id function assumes (does NOT weaken the id function). Guarded by test_duplicate_source_item_id_does_not_collide_work_ids + test_three_way_source_id_collision_mints_unique_work_ids (both fail with the pre-pass disabled). Post-fix: plans/roadmap converts clean — 48 sections + 4580 work_items + 48 content files, validate_v7_plan_json passes. |
| B4 | scalar sidecar ref (mission_ref) propagated but the md→v7 path never emitted its sidecar → dangling ref (GENUINE production defect; the §08-deferred systemic cure) | Both converter paths propagate plan-level scalar refs (mission_ref/goal_ref) forward (convert_plan_dir_v7.py:362 reshape, :588 md-path) with no existence guarantee. The §08 review hit a missing content/overview/mission.md (00-overview HISTORY 2026-05-30); root cause confirmed: the 006 parser PRODUCES content/overview/mission.md in parsed.sidecar_plan.files, but the md→v7 converter never copied it into content_files, so mission_ref dangled for any markdown plan carrying a ## Mission section. | (this commit) | Fix (emit + assert): (a) _emit_scalar_ref_sidecars copies every propagated scalar-ref sidecar from the parser’s sidecar set into content_files (md path); (b) assert_scalar_refs_resolve raises V6ReshapeError BEFORE any write (write + dry-run choke points) if a propagated ref is neither emitted nor on disk — pairs the per-section body_ref drift check at the overview-sidecar level. v6→v7 reshape carries mission.md on disk (gate’s on-disk check covers it; stale-removal only touches n- files). Corpus sweep: 0/57 scalar refs dangling (backfill already clean). 4 unit pins (missing→raise, emitted-ok, on-disk-ok, unset-ok); 2705 plan_corpus tests green. |
| B5 | v7 section content truncates item descriptions at 300 chars — INV-18 task-context content loss (GENUINE production defect, found by per-content-file verification) | The §9.4A directive (“verify every single content file for proper + consistent conversion”) surfaced it: render_items_as_descriptions renders item["text_short"] (convert_plan_dir_v7.py:162), and _sidecar_emit._parse_items_and_clean_body caps text_short = text[:300] discarding the full first-line text. The schema’s overflow mechanism (item body_ref sidecar, “longer description lives in body_ref”) is created ONLY for multi-line continuation_body > threshold, never for a long FIRST LINE. Result on plans/roadmap: 323 of 4580 work_items truncated (text_short maxes at exactly 300), many MID-WORD (e.g. …where you added \dbg!`/`traci[ng]). Per INV-18 the section content IS the LLM's complete task context read in full, so a truncated item description is an incomplete task. Structural validation (validate_v7_plan_json`: coherence + sort + keys) does NOT catch it — coherence only checks the w-id token is present, not text fidelity. | (this commit) | Fix (3-point, schema-respecting): (1) _parse_items_and_clean_body preserves full first-line text; (2) the items-records emit routes full content (first line + continuation) to an item body_ref sidecar when len(full_text) > 300 (not just on continuation); (3) render_items_as_descriptions inlines the full item body_ref content into the section content (INV-18 whole-file-read), strip_checkboxes-ed so nested sub-item - [x] markers don’t violate the no-checkbox invariant. plan.json text_short stays ≤300 label + body_ref pointer; the markdown content carries full text. Post-fix: roadmap item descriptions reach 1053 chars (was capped ~300); validate_v7_plan_json PASS. New content-fidelity verifier scripts/plan_corpus/verify_v7_conversion.py (per script-first — makes “verify every content file” a repeatable gate: F1 structural, F2 no-checkbox, F3 item-text fidelity, F4 wid coverage, F5 non-vacuous) reports plans/roadmap 48 sections / 4580 work_items / 48 content files F1–F5 CLEAN. 2 fix pins + 4 verifier tests; 2705 plan_corpus tests green. |
| B6 | roadmap is a routing HUB, not just content — v7 conversion drops owns_crates + breaks routing (ARCHITECTURAL; user-flagged “we will probably need reroute support added”) | The on-disk roadmap→v7 conversion (§09.4B step 2/3) surfaced that plans/roadmap is the routing DESTINATION for phase-local work (routing.md §1) AND the crate→section ownership SSOT (owns_crates frontmatter on all 33 sections, inverted by scripts/plan_routing.py:load_owns_crates_map at bug-triage + /create-plan Step 0.6). Four grounded breaks: (1) the 006 parser DROPPED per-section owns_crates (subsection keys had no owns_crates); (2) the v7 routing-only schema has no owns_crates field, so conversion lost the crate map entirely (0/33 in plan.json); (3) load_owns_crates_map raises RoutingError: owns_crates unresolvable on a v7 roadmap; (4) the forward md→v7 path leaves the 33 source section-*.md in place (stale-removal is reshape-only) so both formats coexist. The dogfood proved roadmap can’t be MECHANICALLY converted — it needs reroute support. | (this commit — converter layers; routing layers -> §10) | Design (user-chosen: per-section content sidecar — plan.json stays routing-only, INV-3 preserved). CONVERTER-PRESERVATION layers (this commit, §09.4B converter hardening): (L1) 006 parser captures owns_crates from section frontmatter into the level-0 section dict (conditional — roadmap-only); (L2) convert_plan_dir_v7 re-homes it into the section CONTENT body_ref frontmatter via _prepend_owns_crates_frontmatter (declared-empty [] emitted, distinct from absent); canonical reader read_owns_crates_from_content is the v7-path SSOT for routing. Verified: owns_crates survives md→v7 roundtrip 33/33 sections, plan.json stays routing-only (0 owns_crates leaks), validate + F1–F5 verifier clean, 2714 plan_corpus tests green. 3 TDD pins (rehomed-not-in-plan-json, empty-list-emitted, non-roadmap-absent). ROUTING-CONSUMER layers (user-directed: build before the on-disk roadmap conversion so live routing never breaks): (L3) DONE — load_owns_crates_map gets a v7 branch (_v7_owns_crates_map) that reads owns_crates from each section’s content body_ref frontmatter via read_owns_crates_from_content; dual-format-safe (markdown path unchanged). Root went deeper than expected: read.load_plan surfaces 0 subsections for v7 (_load_plan_json reads raw["subsections"], the v5/v6 shape, not v7 sections[]), so the v7 branch reads plan.json sections[] directly rather than overloading the shared subsections view (minimal blast radius). Verified: a temp-converted v7 roadmap yields the 20-entry crate→section map where it previously raised RoutingError owns_crates unresolvable; 5 TDD pins (v7-read, empty-owns-nothing, no-frontmatter-skipped, duplicate-claim-raises, missing-body_ref-raises); 2719 plan_corpus tests green. (L4) DONE — archive_source_markdown + --archive-source flag on the forward path: after writing plan.json + content/, the source section-*.md / 00-overview.md / index.md move to _archive/ (the subject-plan archival precedent), preserving authored source while leaving a cleanly-v7 dir; plan.json + content/ never moved. 3 TDD pins (moves-sources-preserves-v7, no-op-when-empty, CLI end-to-end). (L5) DEFERRED (user-chosen guarded fast-follow) — phase-local routing destination becomes a v7 write-API section-create; surfaced as from-scratch v7-write machinery (no v7-native section-create in write.py — it is all v5/v6 subsections[]-shaped; only split_over_cap_section writes v7). NOT needed for the dogfood DRIVE (driving the converted roadmap through the engine executes existing work_items, never creates phase-local work). Becomes a guarded follow-up: the narrow /create-plan-phase-local-to-roadmap append path is the only break, flagged until L5 lands (→ §10/§11 v7-write-API charter). ON-DISK CONVERSION DONE (user-authorized): convert_plan_dir_v7 plans/roadmap --archive-source wrote plan.json (48 sections + 4580 work_items) + 48 content files + archived 35 source markdown to _archive/; dir is cleanly v7 (0 section-*.md), detect_route_mode → v7, load_owns_crates_map reads the 20-entry crate map (L3 holds), F1–F5 verifier clean. ENGINE DRIVE: orchestrator dispatch serves w-5b041d9b [lexical-grammar] exit_kind: handoff_to_execution — the engine drives the converted roadmap correctly. |
| B7 | v7 engine serves OVER-CAP content bodies for work without auto-splitting — INV-18 single-read violation at scale (dogfood-surfaced driving the converted roadmap) | Driving the converted v7 roadmap surfaced 27/48 content files exceed the INV-18 300-line cap (content_size_lint.DEFAULT_CAP), largest 1832 lines (core-library-traits); the engine served w-5b041d9b (lexical-grammar, 911 lines / 56KB) as handoff_to_execution WITHOUT auto-splitting it first. §09.4 finding-16 scoped the serve-path auto-split cure (“wire content_size_lint scan into review-as-phase pre-work so an over-cap section auto-routes to split_over_cap BEFORE being served”) as a follow-up that did not land for this path. The converter (convert_plan_dir_v7) also does not split over-cap content at conversion. So a converted plan with large source sections serves over-cap bodies, violating the INV-18 whole-file single-read context-unit contract (an 1832-line body is not one readable task unit). | (recorded; cure scope below) | Two cure surfaces (the §09.4 finding-3/16 split_over_cap machinery exists; this is the wiring): (a) CONVERTER-TIME — convert_plan_dir_v7 runs split_over_cap on each over-cap section so the emitted plan is INV-18-clean; OR (b) SERVE-TIME — wire content_size_lint → split_over_cap_section into the review-as-phase pre-work path (finding-16’s chosen model) so over-cap auto-splits before handoff. The 27 over-cap roadmap sections need splitting regardless. RESOLVED (user directive 2026-05-31: keep original content intact, relax the linter — markdown size is less of concern now): raised content_size_lint.DEFAULT_CAP 300 → 2500 (covers the legit corpus max 1832 — trait-library/grammar/verified-test reference sections — with headroom; still flags pathological 2500+ pollution). The cap is a generous sanity backstop, not a fragmentation trigger; content fidelity wins over size. Result: 0/48 roadmap sections over-cap (was 27); the review-as-phase over-cap gate (review_phase.py hard gate, content_cap=DEFAULT_CAP) now ACCEPTS the large sections; the engine serves the 911-line lexical-grammar body WHOLE (handoff_to_execution) — no split, content intact. 6 tests repinned to an explicit cap=300 / content_cap=300 / body_lines=2600 threshold (behavior pinned independent of the relaxed default); 5674 plan_corpus + plan_orchestrator tests green. B7 (over-cap-serve) + B8 (chunker over-split) are now MOOT for the roadmap (no split needed); splitting stays available (opt-in) for genuinely pathological content. |
| B8 | split_over_cap chunker over-splits SPECIFIC content into 1 near-cap chunk + N tiny slivers (dogfood-surfaced attempting the B7 split) | Splitting the live roadmap’s lexical-grammar-verified section (911 lines, cap 300) via write.split_over_cap_section produced 29 siblings: ONE 295-line part + 28 slivers (3–34 lines, mean 31, 28 of 28 under 50 lines) — not the ideal ~3 near-cap chunks. The greedy packer in split_over_cap._split_lines is NOT generally broken — a synthetic 900-line/30-##-block body chunks correctly into 3×300. The over-split is specific to the lexical-grammar content structure (likely a huge ## Items work_item manifest segment or an irregular header distribution that defeats greedy packing / forces a degenerate recursion). Splitting all 27 over-cap sections with this would balloon the plan into hundreds of sliver sections. | MOOT (cap relaxed per B7 resolution — no split needed; latent for pathological content) | B8 BLOCKED the B7 split — the chunker must produce evenly-packed near-cap chunks on the roadmap’s real content before splitting. Cure direction: diagnose the lexical-grammar structure (reconstruct via "".join(chunk_body(...))), fix _split_lines greedy-pack / recursion for the degenerate case (likely the ## Items manifest as one oversized segment with no sub-headers → hard-split should pack to ~cap, not interact badly with the narrative packing). The bad in-place split was RECOVERED by deterministic re-conversion from _archive (the convert is idempotent; regenerated plan.json matched the committed one). |
| B9 | commit-push triage skips UNTRACKED DIRECTORIES → broke the roadmap conversion commit (dogfood-surfaced; commit-push hardening, standing-auth b) | The roadmap-conversion commit 2682ca57 captured plan.json + the 35 section-*.md DELETIONS but NOT the untracked content/ (48 body_ref files) or _archive/ (35 source md) DIRECTORIES — commit-push’s untracked-triage (classify_untracked) operated on the collapsed ?? content/ / ?? _archive/ directory entries and classified them ambiguous/preserved rather than expanding + staging their contents as REAL_WORK. Result: a v7 plan.json pushed to origin whose body_refs referenced uncommitted content + whose source was lost (deletions committed, the _archive/ they moved to uncommitted). Origin had a BROKEN roadmap. | (repaired d105088d; fix this commit) | Immediate repair (DONE): git add plans/roadmap/content/ plans/roadmap/_archive/ (explicit; expands the dirs) + commit d105088d + user-authorized --no-verify push → origin roadmap whole (48 content + 35 archive tracked, all body_refs resolve). Commit-push fix (DONE): classify_untracked now detects an untracked DIRECTORY (collapsed ?? dir/) and expands it via git ls-files --others --exclude-standard -- <dir> into its constituent files, classifying each individually (per-file logic extracted to _classify_one_file); the directory key is dropped. Because --exclude-standard already filters gitignored scratch/build dirs, a non-ignored untracked dir is deliberate work — an AMBIGUOUS child is promoted to REAL_WORK so the whole dir (a conversion’s content/ + _archive/) stages atomically; an explicit SCRATCH signal still keeps a file out. 3 TDD pins (dir-expands-to-real-work, scratch-in-dir-stays-out, nested-subtree-recurses); 47 triage + 154 staging/state-machine tests + commit_push self-test green. A partial conversion commit (plan.json without its content/) can no longer ship as a silent presence-warning. |
| B10 | converter DROPS short continuation content under checkbox items — nested notes / sub-items / <!-- blocked-by --> annotations lost (dogfood-surfaced by per-content-file fidelity audit; user directive: keep original content intact) | A v7-content-vs-_archive-source fidelity audit of the converted roadmap found 16/33 sections with sampled-prose loss. Root cause: _sidecar_emit routed an item’s continuation_body to a sidecar ONLY when > ITEM_BODY_THRESHOLD (300); a SHORT continuation (e.g. - **Note**: associated-function syntax…, - WEAK TESTS: …, <!-- blocked-by:… --> indented under a checkbox) was captured by the parser but then DROPPED — only text_short (the checkbox first line) rendered into v7 content. The continuation was NOT in the cleaned subsection body either (the parser extracts it as item content), so it was genuinely lost. | (this commit) | Fix (schema-clean): route ANY non-empty continuation to the item body_ref sidecar (len(full_text) > 300 OR continuation.strip()), which the v7 converter inlines into the section content (B5 path; checkbox markers stripped; in-memory sidecar → no v7 disk proliferation). The ChecklistItem schema (additionalProperties: false) forbids new item fields, so routing-to-sidecar (not a new continuation_body field) is the clean mechanism. Re-converted the live roadmap: the previously-dropped Note/WEAK-TESTS/blocked-by lines are now PRESENT; sampled-loss 16→8 (remaining 8 are 5/8 false-positives + B11). 1 TDD pin (short-continuation-preserved); the item_sidecar_threshold boundary test updated to the new contract (a non-empty continuation → body_ref populated, not dropped); 2724 plan_corpus tests green. |
| B11 | converter DROPS free-form (non-numbered) ## subsection content — tables, diagrams, blocker notes (dogfood-surfaced; deeper parser gap) | The roadmap’s section-21A-llvm.md carries free-form ## headings (## Current Test Results + a markdown results table, ## Known Blocker: …, ## Import Resolution …, ### Features that need import-aware changes) BEFORE the numbered ## 21.1-style subsections. That preamble content (the entire test-results table — | Test Suite | Passed | …) is DROPPED from v7 (heading + table both absent). Root cause (FOUND): the section-overview body was computed by _strip_subsection_blocks_from_body (_sidecar_emit.py), which cut the body at the FIRST ANY-## heading (_SECTION_HEADING_RE) — so free-form ## preamble before the first numbered subsection fell in a gap captured by NEITHER the overview NOR the ## NN.M numbered-subsection walk. (A dead, never-called _split_section_overview_from_body had been mis-edited first; it was not the overview producer.) | (this commit) | Fix (DONE): _strip_subsection_blocks_from_body now cuts at the first NUMBERED ## NN.M heading (_SUBSECTION_HEADING_RE) instead of any-## , so the section overview INCLUDES all free-form ## /### preamble (tables, diagrams, blocker notes) before the first numbered subsection; that overview is the section’s body_ref, which the v7 converter renders. Dead _split_section_overview_from_body removed (litter-pickup). Verified end-to-end on the live roadmap source: section-21A-llvm.md’s ## Current Test Results table (6 rows), ## Known Blocker: BUG-04-030, and ## Import Resolution preamble all PRESENT in re-converted v7 content (previously 0 table rows). 38 converter tests green; live roadmap re-converted (48 sections / 4580 work_items). |
| B12 | converter DROPS TRAILING / between-subsection free-form ## content — Verification Notes, Examples, Inspired By, Running Tests, Completion Summary (dogfood-surfaced by a deeper _archive-vs-v7 content sweep; B11 was partial) | A systematic _archive-source-vs-v7-content sweep over all 35 roadmap sections (after B11 landed) found 30 free-form ## headings still absent — but these appear AFTER / BETWEEN the numbered ## NN.M subsections, not in the preamble B11 fixed: ## Verification Notes (2026-03-29), ## Example: SQLite Binding, ## Inspired By, ## Running Tests, ## Completion Summary, ## Grammar Inconsistencies Identified, ## Test Status Comments, etc. (~6 of the 30 were sweep false-positives — ## NN.R Third Party Review headings the sweep’s narrow .\d-only skip regex missed; ## NN.R/## NN.N ARE matched by _SUBSECTION_HEADING_RE). Root cause (same family as B11, different cut site): _split_subsection_blocks delimited each numbered subsection’s body at the next ANY-## (body.find('\n## ')), so a trailing free-form ## Verification Notes ENDED the preceding subsection’s capture and was then orphaned (matched by neither a numbered block nor the preamble-only overview). | (this commit) | Fix (DONE): _split_subsection_blocks now delimits each numbered subsection’s body at the next NUMBERED ## NN.M subsection (incl. ## NN.R/## NN.N) OR the ## HISTORY boundary — free-form ## /### headings are NO LONGER boundaries; they are ABSORBED into the preceding subsection’s body so their tables / code / prose render. HISTORY stays a hard boundary (never absorbed; parsed separately into structured records). Verified: the genuine-free-form-loss count went 30→0 on the full _archive-vs-v7 sweep; live roadmap re-converted (48 sections / 4661 work_items — the +81 vs B11 are previously-dropped - [ ] checkboxes inside the recovered free-form sections), F1–F5 clean, Verification Notes + Running Tests present in v7 content; 708 converter tests green. |
| B13 | converter DROPS the NN.M number from rendered subsection headings → orphans 167 legacy §NN.M prose cross-references (dogfood-surfaced by a line-level _archive-vs-v7 fidelity audit) | A line-level audit (every ≥5-word source line vs v7 content) initially flagged 211 misses — ALL ## NN.M subsection headings (## 0.1 Lexical Grammar). The v7 content rendered them as ## Lexical Grammar (number dropped). The roadmap prose carries 167 internal §NN.M cross-references (§21.2×31, §15D.4×22, §3.1×9, …) that target those numbered subsections; dropping the visible NN.M from the heading orphaned every one. (The deeper ### NN.M.K sub-items kept their numbers — they ride through as preserved body content; only the converter-RE-RENDERED L1 ## NN.M heading lost its number.) | (this commit) | Fix (DONE): convert_plan_dir_v7 heading render (head = f"## {sub.title}") now re-prepends the parsed NN.M id → ## {id} {title}, reproducing the source heading verbatim. The parser strips the number into sub.id, so the title never double-carries it. Order still lives in key (INV-15); the visible number is CONTENT (navigation), not routing. Verified: the full line-level audit (heading id NOT stripped) went 211→0/14467 misses (0.00%) — every substantive source line, headings included, is present in v7; ## 21.2/## 0.1 headings render verbatim on the live re-converted roadmap (48 sections / 4661 work_items), F1–F5 clean, route v7, owns_crates 20; 546 converter tests green. Content fidelity is now total: 0 dropped lines, all 167 §NN.M cross-refs resolve. |
| B14 | NOT A LOSS (verified negative finding) — plan-level 00-overview.md + index.md content is NOT in the v7 content/, but IS preserved verbatim in _archive/ | A whole-plan fidelity audit (extending the B13 line-audit, which globbed only section-*.md) flagged 00-overview.md (78/80 substantive lines) + index.md (260/270 lines) as absent from the v7 content/: the design philosophy (the 7 Ori tenets — “Code that proves itself”, …), the Tier 0/1/2 structure, and the 782-line keyword-search index. The converter extracts ONLY the ## Mission block (extract_mission_block → mission_ref → content/overview/mission.md) and routes the rest nowhere in content/. | n/a (no loss — preserved in _archive/) | Resolution: NOT a converter loss. The forward path’s archive_source_markdown (B6 L4) moves 00-overview.md (231 lines, philosophy intact) + index.md (782 lines, keyword index intact) into plans/roadmap/_archive/ verbatim, tracked at git HEAD — nothing is deleted, every line recoverable. The asymmetry (section content → engine-served content/; plan-level overview prose → _archive/ only) is by design: the v7 engine serves WORK (sections/work_items), not plan-philosophy prose. Whether the full plan overview SHOULD ALSO be engine-accessible in the active v7 form is a v7-MODEL enhancement (a plan-level overview_ref content file + schema field), not a converter defect — deferred to the §10/§11 v7-write-API charter alongside B6 L5. “Keep original content intact” holds: the original is intact + committed in _archive/. |
| B15 | REVERSE converter silently corrupts v7 rollback — 006_json_to_md routes a v7 plan to the v5/v6 render stub (emits a 1-FILE partial) + its --from-archive rejects the v7 plain-.md _archive/ layout (round-trip fidelity check; convert-script bidirectional-consistency bug) | A round-trip fidelity check (md → v7 → md) of the convert script surfaced that the forward half (006_md_to_json / convert_plan_dir_v7) and the reverse half (006_json_to_md) DISAGREE on the archive layout: forward’s archive_source_markdown writes plain _archive/<basename>.md; reverse’s _archive_present / --from-archive expect the legacy .md.pre-json-migration suffix. Two v7 failures: (1) reverse WITHOUT --from-archive on a v7 plan falls through to _render_based_regenerate (v5/v6 only) → silently emits files_emitted: 1 for a 48-section roadmap (silent rollback corruption — user believes the rollback succeeded); (2) reverse --from-archive on v7 → _archive_present False → archive_required_for_rollback error, blocking rollback. | (this commit) | Fix (DONE): 006_json_to_md.convert_single_plan_dir_reverse gains a v7 branch BEFORE the render path — when plan.json is v7 (_is_v7_plan_json), it routes to byte-identical archive-restore from the plain-.md _archive/ (_v7_archive_present + _restore_from_v7_archive, mirroring the legacy restore but with no suffix to strip), moving plan.json + content/ to _pre_rollback/ (non-destructive). A v7 plan NEVER reaches _render_based_regenerate (no more silent 1-file stub); a v7 plan with no plain-.md archive errors cleanly (archive_required_for_rollback), never a silent partial. Verified: a full md → v7 → md round-trip on the 35-file roadmap source restores byte-identical (35/35 files), exit_reason: converted, source: archive; 3 TDD pins (round-trip-byte-identical, no-archive-errors-not-render, dry-run-archive-count); 378 migration/reverse tests green (no v5/v6 regression). The convert script is now bidirectionally faithful — forward 0-loss to the active form, reverse byte-identical from the archive. |
| B16 | converter-GENERALITY finding (NOT a roadmap defect) — section-level ## HISTORY blocks are parsed but not rendered into the active v7 content/; preserved in _archive/ | A proactive multi-plan fidelity audit (extending the roadmap audit to typeck-inference-completeness, repr-opt, et al. in temp, read-only) found a recurring miss class: section-level ## HISTORY entries (- **2026-05-17 — /review-plan SIGNIFICANT REWORK…**). The roadmap NEVER surfaced this (its ## HISTORY is plan-level, in 00-overview.md → _archive/ like B14; roadmap section files carry no HISTORY, audit 0/14467). Parity gap: the v5/v6 emit (_sidecar_emit.build_plan_json_from_dir) renders each history_entries item into a content/history/<date>-<slug>.md sidecar (line 685) + a plan_json["history"] record; convert_plan_dir_v7 composes content from scratch and carries neither, so v7 drops section HISTORY from the active content. | (this commit — FIXED) | Fix (DONE): the converter now renders section ## HISTORY into the active v7 content (the INV-18 whole-read unit). Implementation: parse_section_file captures the raw ## HISTORY block — ALL blocks via finditer (a section may carry >1; the section-05 anomaly had two) — into SectionParse.raw_history; build_plan_json_from_dir threads it onto ParsedPlanDir.section_raw_history (a Python attribute, NOT the routing-only plan.json — INV-3 preserved); convert_plan_dir_v7 appends the raw block after the subsections (matching source position; checkboxes stripped per INV-18). The RAW block is rendered, not the structured history_entries (which truncate short bodies to 200 chars), so it is fully faithful. Verified: section-content miss corpus-wide dropped ~600+ → 0 across all 30 markdown plans; roadmap unaffected (no section HISTORY; 48/4661 unchanged); reverse round-trip stays byte-identical (restores from _archive, not v7 content); 4 TDD pins (history-rendered-with-full-bodies, no-spurious-history, multiple-history-blocks, v6-shape-unchanged); 735 converter tests green. Only B14 (plan-level overview) remains for §10 — the active-form gap is now ONE class, not two. Full-corpus confirmation: a fidelity audit across ALL 30 markdown plans (temp, read-only) categorized every miss — HISTORY-block content (date-prefixed entry lines + their continuation/body lines, e.g. numbered cure-lists under ## HISTORY) is the SOLE active-form gap; zero non-HISTORY subsection content is dropped corpus-wide. The roadmap’s B10–B14 fixes (continuations, preamble, trailing free-form, heading numbers) generalize perfectly to every plan. So the §10 active-form converter work is precisely bounded: plan-level overview (B14) + section ## HISTORY (B16) are the ONLY two non-subsection blocks needing active-form rendering — no third class exists. Size-cap follow-up: appending HISTORY to section content raised the largest corpus section to 3040 lines (rosetta-stress-test infrastructure-first-15-programs), which the 2500 content_size_lint cap (B7) would --split-over-cap into fragments — re-splitting HISTORY from its subsections, the exact “keep content intact” + “size less of concern” concern. Per the cap’s own stated intent (“generous sanity backstop, not a fragmentation trigger; keep legitimate large sections WHOLE”), DEFAULT_CAP raised 2500 → 5000 — every one of the 30 plans’ sections now stays whole (0 over-cap; largest 3040), the cap flags only pathological dumps (>5000); roadmap unaffected (2203 < cap). |