Section 07A — Route Schema v7 (Sections + Work_items Split)
Cites §01 north star (invariants 3, 10, 12, 15 — JSON-routing-only + single-update-point + content-keyed + flat-nodes): the v7 two-level schema realizes those invariants in the per-plan plan.json shape.
- Supersedes the v6 flat-node
nodes[]model for every per-planplan.json. - Full design SSOT:
decisions/04-sections-work-items-split.md(schema shape, resolved decisions, blocker-move illustration, invariant deltas, reshape footprint). - Inserted after §07, before §08 (linear chain §06 -> §07 -> §07A -> §08); the rest of the plan builds on the v7 shape.
Intelligence Reconnaissance
Run 2026-05-29:
scripts/intel-query.sh dag-ascii scripts-first-restructure— §07A linear-walk position §07 -> §07A -> §08;depends_on: ["07"](sole direct predecessor per INV-19; §08 re-pointed to [“07A”]).- Remaining bullets are direct file citations (wrapper Python + JSON not reliably intel-indexed):
[ori:plans/scripts-first-restructure/decisions/04-sections-work-items-split.md]— the v7 schema SSOT this section delivers.[ori:scripts/plan_corpus/migrations/006_md_to_json.py]— the §02 converter that must emitsections[]+work_items[]instead ofnodes[].[ori:scripts/plan_orchestrator/route_walk.py]— §06 engineserve_nextto reshape (walk sections, return current work_item, own work_item status lifecycle).[ori:plans/completed/scripts-first-workflow-architecture/plan.json]— the existing 184-node v6 plan.json to re-convert to v7 (engine-only per §08; user-typed unlock required to read).[ori:plans/scripts-first-restructure/section-01-principles.md]— INV-10/12/15/19/20 definitions to update per decisions/04.
07A.1 — Schema v7 definition + validators
- Confirm
decisions/04-sections-work-items-split.mdcaptures the final schema v7 (sections[] + work_items[]), the resolved decisions, the blocker-move illustration, and the invariant deltas (it is the SSOT for the rest of this section). - Define schema v7 in
scripts/plan_corpus/(the v6 schema validator +plan_json_writeAPI):schema: scripts-first-restructure/plan-routing/v7;sections[]{id: s-, slug, key, status, hint_needs, body_ref}; work_items[]{id: w-, section_id, key, status, hint_needs}. No nodes[]. No body text in JSON (INV-3 preserved). Delivered:scripts/plan_corpus/schemas/v7/plan-routing.schema.json+scripts/plan_corpus/schema_loader.py:load_plan_routing_v7_schema. - Author the
array==sorted(key)validator (scripts/plan_corpus/v7 validator module, per decisions/04 resolved-decision 3 + 11):work_items[]physical order MUST equalsorted(work_items, key=lexorank), andsections[]likewise; AND lexorank keys MUST be strictly unique within each array (pairwise-distinct — duplicate keys rejected as a hard precondition, per decisions/04 resolved-decision 11). Reject (validation error) any out-of-order OR duplicate-key array. Pytest: out-of-order array rejected; in-order accepted; a between-key insert keeps it sorted;test_duplicate_lexorank_key_rejected(two work_items sharing a key -> rejected; two sections sharing a key -> rejected). Delivered:scripts/plan_corpus/route_v7.py:validate_array_sorted_and_unique+scripts/plan_corpus/tests/test_route_v7.py. - Author the JSON<->md item-coherence validator: every
work_items[].idappears as an id-reference in itssection_id’sbody_refmd; every id-reference in a section md has awork_items[]entry. Reject orphans either side. Pytest: orphan-in-json rejected; orphan-in-md rejected; matched set accepted. Delivered:scripts/plan_corpus/route_v7.py:validate_md_item_coherence+scripts/plan_corpus/tests/test_route_v7_coherence.py. - Subsection close (07A.1) — all
[x];status: complete.
07A.2 — §02 converter reshape
- Emit
sections[]+work_items[]from the source markdown: one section per source markdown section (slug-firstcontent/<slug>--s-<hex>.md), one work_item per checkbox item hoisted intowork_items[]with a stablew-<hex>id +section_idpointer + lexorank key + status derived from the source checkbox state. Delivered ADDITIVE inscripts/plan_corpus/convert_plan_dir_v7.py(reuses the006_md_to_json.build_plan_json_from_dirparser SSOT; the v6nodes[]emitterconvert_plan_dir.pystays intact for its live consumersroute_check.py+plan_json_write.py— v7 additive until §07A.5 re-converts the subject, per decisions/04). - The converter strips checkboxes from the emitted content md (items live in
work_items[]); the md retains the item DESCRIPTION lines keyed by the stablew-<hex>id (greppable, no- [ ]). - Acceptance (pytest): converting a fixture markdown plan yields a v7 plan.json whose
array==sorted(key)+ JSON<->md coherence validators (imported from §07A.1route_v7.py) pass; item count inwork_items[]equals source checkbox count; section count equals source section count. Delivered:scripts/plan_corpus/tests/test_convert_plan_dir_v7.py(16 tests). - Subsection close (07A.2) — all
[x];status: complete.
07A.3 — §03 substrate reshape
- DEPRECATE the id-keyed checkbox scanner (the v6 INV-10 status-derivation path) — status is now
work_items[].status, not a markdown checkbox scan. Deprecation marker added toscripts/plan_corpus/checkbox_scan.pyciting §11B as the hard-deletion owner; deletion DEFERRED to §11B (the dedicated strip-parsers section) per decisions/04 additive-until-§07A.5 discipline (the still-v6 subject plan.json relies on the v6 status contract until §07A.5 re-converts). Zero live production consumers confirmed by caller-grep. - ADD the work_item status write API (atomic, fcntl.flock, mirrors the existing plan_json_write CAS discipline): flip a
work_items[].status(not-started -> in-progress -> completed) + the move primitive (reassignsection_id+ re-key + re-splice the array to sorted position). The API is the SOLE status-write path; the LLM never edits plan.json (§08). Delivered:scripts/plan_corpus/work_item_status.py(flip_work_item_statusforward-only + section-rollup recompute,move_work_item) reusingplan_json_write.mutate_routing_stateCAS+flock (no new lock regime). - Wire both validators (07A.1) into
plan_corpus checkso v7 plans are validated at write-time + pre-commit. Delivered:route_check.check_route_dirdispatches byis_v7_plan_json→validate_v7_plan_json(array==sorted+unique + JSON<->md coherence),STRUCTURE:route-v7-schema-violationfinding; v6 path unchanged (additive gating). Fixed an in-scope validation-bypass gap (is_route_migrated_dircheck-branch widened to recognize v7). - Acceptance (pytest): status flip persists + array stays sorted; a move keeps hint_needs refs resolving + array sorted; coherence validator runs in
plan_corpus check. Delivered:scripts/plan_corpus/tests/test_work_item_status.py(16 tests); CLI end-to-end verified (clean v7 exit 0; orphan-in-md exit 1 with v7 finding). - Subsection close (07A.3) — all
[x];status: complete.
07A.4 — §05 route model + §06 serve_next
- Reshape the §05 route model to two levels: sections carry the linear chain (lexorank key), work_items are the flat movable units;
hint_needs(both levels) is ADVISORY-ONLY per INV-6 + decisions/04 resolved-decision 8 — it informs authoring-time lexorank placement, never walk-time filtering. - Reshape
scripts/plan_orchestrator/route_walk.py:serve_next: walksections[]in array order (= key order) to the first non-completed section; within it walkwork_items[](by section_id) in array order to the first NON-COMPLETED work_item — NO hint_needs filtering at walk time. In-progress precedence (work_item-level INV-20, per decisions/04 resolved-decision 10): if that first non-completed work_item isin-progress, serve_next returns it AS-IS and NEVER walks past it to a laternot-startedwork_item — at most one work_item per section is in-progress at a time (mirrors the INV-20 section-level “in-progress predecessor returned as-is, never skipped” clause at the work_item level).hint_needsis ADVISORY per INV-6 + decisions/04 resolved-decision 8: serve_next does NOT skip a work_item with unmethint_needs; it serves the first non-completed work_item in array order and surfaces any unmet hints as advisory metadata, returning{section, body_ref, work_item_id, unmet_hints: ["w-<hex>"]}. Array order (lexorankkey) is the sole walk-time ordering authority; the blocker-move pattern (re-key the blocker physically before the work it unblocks) keeps array order sufficient without a hard hint-gate (per decisions/04 resolved-decision 8). - serve_next is WRITE-ON-SERVE per decisions/04 resolved-decision 10: it routes (reads the next work_item) AND flips its status
not-started -> in-progressas an atomic side effect, and flipsin-progress -> completedonly when INV-20 gates pass — it is the single status-transition entry point. Add a read-onlypeek_nextvariant that returns the identical routing payload ({section, body_ref, work_item_id, unmet_hints}) WITHOUT any status write, for dry-run / lookup callers (dag-ascii, resume-manifest builders) that must never mutate plan state. The query (read) and the transition (write) are separated by which function is called, never folded into one ambiguous call. - section.status is a DERIVED rollup of its work_items (never independently written): all completed -> completed; any in-progress/mixed -> in-progress; all not-started -> not-started; ZERO work_items -> completed (decisions/04 resolved-decision 9 — vacuous-truth so an empty section never deadlocks the walk). serve_next + the status API compute it.
- Acceptance (pytest): serve_next returns the section + current work_item verbatim with
unmet_hintsadvisory metadata (never skips on unmet hints); never runtime-sorts (trusts array order); engine flips work_item status (LLM never does);peek_nextreturns the same payload with zero status mutation; an in-progress work_item is returned verbatim, never skipped past to a later not-started one;test_serve_next_returns_whole_section_body+test_work_item_status_engine_only+test_serve_next_does_not_filter_on_hint_needs+test_peek_next_is_read_only+test_serve_next_returns_in_progress_work_item_as_is(work_item-level INV-20 precedence: a section with one in-progress + later not-started work_items serves the in-progress one, never the not-started one). - Acceptance (pytest) —
section.statusrollup matrix inscripts/plan_orchestrator/tests/covering every rollup branch from decisions/04 resolved-decision 4+9:test_section_status_rollup_all_not_started(all work_items not-started -> section not-started);test_section_status_rollup_mixed_in_progress(any in-progress or mixed not-started/completed -> in-progress);test_section_status_rollup_all_completed(all work_items completed -> completed);test_section_status_rollup_empty_section_is_completed(zero work_items -> completed, walk advances past it);test_section_status_rejects_independent_write(a direct write tosection.statusbypassing the work_item rollup is rejected — status is derived, never independently written). - Acceptance (pytest) — preserve
test_route_walk_exit_reason_parity(the v6 exit_reason contract inscripts/plan_orchestrator/tests/) under v7 by adding fixtures: a v7 plan whose serve_next yields a current work_item; a v7 plan with nonot-startedwork_item left (no-ready / queue-drained exit_reason); a v7 plan whose served work_item lacks its deliverable (INV-17 quarantine exit_reason). Each fixture asserts the same exit_reason key the v6 walk produced for the equivalent node-level state, so the v7 sections/work_items walk is exit_reason-compatible with the v6 nodes walk. - Subsection close (07A.4) — all
[x];status: complete.
07A.5 — Re-convert subject plan.json + invariant-doc updates
- Re-convert the existing scripts-first-workflow-architecture
plan.jsonto v7 (sections[] + work_items[] + slug-firstcontent/<slug>--<id>.mdfilenames); both validators green. Result on disk: 49 coarsesections[]+ 184work_items[]. Mechanism: the coarse shape was produced by the one-offscripts/plan_corpus/regroup_v7_coarse.py(v7->v7 coarsening; commit 3461f8c2), NOT by re-running the md->v7 converter — the subject’s v6 source markdown is archived under_archive/and no longer available to feed the md path. SEPARATELY, the converter source was corrected so future md->v7 conversions emit coarse output:convert_plan_dir_v7.convert_plan_dir_v7now groups subsections by parent section (commit 093c214e; verified — scripts-first-restructure md->v7 yields 15 coarse sections, not 93). The legacy v6-nodes pathreshape_v6_to_v7strips checkboxes but remains 1:1 (N nodes -> N sections); it is superseded byregroup_v7_coarse(v7->v7) and the fixed md path for coarse output. Engine-only access per §08 — the LLM never raw-editedplan.json. The INV-18 content-no-checkbox validator gate (route_v7.validate_content_no_checkbox, commit 6dff58e1) prevents any checkbox regression in the emitted content md. - Update
section-01-principles.md+references/restructure-charter-seed.md §2invariant text: INV-6 (hint_needs ADVISORY — never a serve_next gate, per decisions/04 resolved-decision 8), INV-10 (status = work_items[].status field, not md checkbox), INV-12 (id-SUFFIX globcontent/*--<id>.md), INV-15 (two levels: sections + work_items), INV-19 (single-branch over sections; hint_needs advisory; empty-section rolls up completed), INV-20 (serve_next over sections + engine owns work_item lifecycle; write-on-serve with read-only peek_next) — each citingdecisions/04. - Update
00-overview.md(umbrella) for the v7 contract: reword the Mission Success Criteria bullets + North-star INV-2/INV-3 summary + data-flow description that currently describe the v6 flat-nodenodes[]model so they state the v7 two-levelsections[]+work_items[]contract (sections = one md each / status DERIVED rollup; work_items = stable section-independent ids / engine-written status; slug-firstcontent/<slug>--<id>.md), citingdecisions/04-sections-work-items-split.md. The umbrella description must match the v7 shape the rest of the plan now builds on, not the superseded v6 flat-node description. - Confirm §08
depends_on: ["07A"](linear chain §06 -> §07 -> §07A -> §08); the v6 design of §02/§03/§05/§06 stayscomplete(superseded by this section, not reopened) — note the supersession in each of their HISTORY blocks. - Acceptance:
python -m scripts.plan_corpus check plans/completed/scripts-first-workflow-architecture/exit 0 on the v7 plan.json; slug-first content filenames resolve via id-suffix glob. - Subsection close (07A.5) — all
[x];status: complete.
07A.R Third Party Review Findings
- None.
07A.N Completion Checklist
- 07A.1-07A.5
[x]andstatus: complete. - All success criteria have
[x]checkboxes. - schema v7 validators (array==sorted(key) + JSON<->md coherence) green; converter + substrate + serve_next pytest green. TPR final passed: 3 rounds (2 with cures), 9/9 findings resolved+committed a8d24505+06e0ab3b pushed origin/main; route_v7+route_walk_v7 81-test suite PASS; plan_corpus check section-07A + subject scripts-first-workflow-architecture exit 0; reviewed:true verdict SIGNIFICANT REWORK APPLIED 2026-05-29
- subject plan.json re-converted to v7;
python -m scripts.plan_corpus check plans/completed/scripts-first-workflow-architecture/exit 0. TPR final passed: 3 rounds (2 with cures), 9/9 findings resolved+committed a8d24505+06e0ab3b pushed origin/main; route_v7+route_walk_v7 81-test suite PASS; plan_corpus check section-07A + subject scripts-first-workflow-architecture exit 0; reviewed:true verdict SIGNIFICANT REWORK APPLIED 2026-05-29 - invariant docs (section-01 + charter-seed §2) carry the v7 deltas (INV-6/10/12/15/19/20); 00-overview.md Mission Success Criteria + North-star + data-flow re-stated for the v7 sections/work_items contract; §08 depends_on re-pointed to 07A.
-
python -m scripts.plan_corpus check plans/scripts-first-restructure/section-07A-*.mdexit 0. TPR final passed: 3 rounds (2 with cures), 9/9 findings resolved+committed a8d24505+06e0ab3b pushed origin/main; route_v7+route_walk_v7 81-test suite PASS; plan_corpus check section-07A + subject scripts-first-workflow-architecture exit 0; reviewed:true verdict SIGNIFICANT REWORK APPLIED 2026-05-29 -
/tpr-reviewpassed (final, full-section). TPR final passed: 3 rounds (2 with cures), 9/9 findings resolved+committed a8d24505+06e0ab3b pushed origin/main; route_v7+route_walk_v7 81-test suite PASS; plan_corpus check section-07A + subject scripts-first-workflow-architecture exit 0; reviewed:true verdict SIGNIFICANT REWORK APPLIED 2026-05-29
References
decisions/04-sections-work-items-split.md— schema v7 SSOT (this section’s design record).- Pass: §02 converter
scripts/plan_corpus/migrations/006_md_to_json.py; §03 substratescripts/plan_corpus/write API + validators; §06 enginescripts/plan_orchestrator/route_walk.py. - INV-6 (hint_needs advisory) + INV-19 (single-branch) reconciliation; INV-4 (cross-plan lexorank merge); INV-18 (whole-content-unit to LLM).