100%

Goal

R11 — promote the v7 Section.intel_package field + add a plan-root rollup ref, ALIGN the already-struct v2 validator’s canonical path, and forward-migrate the ref-populated plans’ plan.json REF struct:

  • v7 PROMOTION: Section.intel_package is a bare string (plan-routing.schema.json:428 — confirmed {type: string} on disk); promote to {path, generated_at_sha} so the execution gate can detect a stale sidecar. Add a plan-root intel_package field for the rollup (content/intel/plan.intel.md).
  • v2 ALIGNMENT (not migration): PlanSectionSchema.intel_package is ALREADY the {path, generated_at_sha} struct (schemas.py:456 dict | None + working validator _validate_intel_package at schema.py:1330). The v2 work is canonical-path ALIGNMENT only — re-point the validator’s documented canonical path + recommended_fix strings from the retired nested intel/<section-slug>-package.md to the flat content/intel/<slug>--<id>.intel.md layout the predecessor storage-layout writes.
  • Migration: forward-only backfill of every ref-populated plan’s plan.json REF struct, keyed to the ref-populated set (every plan whose plan.json carries a populated intel_package ref). The prior “9” figure is stale; the count is kept count-free here so a wrong number cannot break the probe (corpus footprint reasoning lives in the predecessor storage-layout §Work Items).
  • Field stays schema-optional; presence is orchestrator-enforced per R13, not schema-required.

Implementation Sketch

  • scripts/plan_corpus/schemas/v7/plan-routing.schema.json: change Section.intel_package (line 428, currently {type: string}) to {path, generated_at_sha}; add a plan-root intel_package object. The plan-root object carries additionalProperties: false (line 8) — the new key MUST be added to the plan-root properties map, not merely referenced; a bare new key under the closed object fails schema validation. Update the Section.intel_package description (line 429), which still documents the RETIRED nested content/section-<sid>/intel/<name>.md location, to the flat content/intel/<slug>--<id>.intel.md pattern the predecessor storage-layout (s-983a8a1b) writes.
  • scripts/plan_corpus/schemas.py: the v2 PlanSectionSchema.intel_package is already the {path, generated_at_sha} dict (line 456) with validator _validate_intel_package (schema.py:1330). The v2 work is path-canonical ALIGNMENT only: re-point the canonical-path docstring (schema.py:1336 + schemas.py:451) and the recommended_fix strings (schema.py:1349 / schema.py:1361 / schema.py:1376 / schema.py:1387) from the nested intel/<section-slug>-package.md to the flat content/intel/<slug>--<id>.intel.md layout so the v2 validator messages do not drift from the new on-disk layout.
  • scripts/plan_corpus/migrations/<NN>_intel_package_struct.py: forward-backfill every ref-populated plan (bare-string -> {path, generated_at_sha: null}; null => regenerate-on-first-read). The migration is keyed to the ref-populated set, not a fixed count — no hardcoded plan-count probe.
  • Do NOT add a duplicate field; do NOT add to Section.required.

Spec References

  • scripts/plan_corpus/schemas/v7/plan-routing.schema.json (Section.intel_package {type: string} at line 428; description at line 429; plan-root additionalProperties: false at line 8)
  • scripts/plan_corpus/schemas.py (PlanSectionSchema.intel_package dict | None at line 456 — already a struct) + scripts/plan_corpus/schema.py (_validate_intel_package at line 1330; canonical-path docstring at line 1336; recommended_fix path strings at lines 1349/1361/1376/1387)
  • plans/intel-package-dossier-rebuild/content/storage-layout--s-983a8a1b.md (predecessor — owns the flat content/intel/<slug>--<id>.intel.md FILE layout this section’s REFs point at)
  • intel-package-rebuild-notes.md R11, R12

Work Items

  • v7 Section.intel_package (plan-routing.schema.json:428, currently {type: string}) -> {path, generated_at_sha} struct + new plan-root intel_package field added to the plan-root properties map (under additionalProperties: false at line 8 — extend properties, never a bare key) + the Section.intel_package description (line 429) re-pointed from the retired nested content/section-<sid>/intel/<name>.md to the flat content/intel/<slug>--<id>.intel.md pattern.
  • v2 PlanSectionSchema.intel_package is ALREADY the {path, generated_at_sha} dict (schemas.py:456); this item is canonical-path ALIGNMENT, NOT a string->struct migration: re-point the _validate_intel_package canonical-path docstring (schema.py:1336 + schemas.py:451) and its recommended_fix strings from intel/<section-slug>-package.md to content/intel/<slug>--<id>.intel.md so v2 validator messages match the flat layout.
  • Forward-only migration backfilling every ref-populated plan’s plan.json intel_package REF struct ({path, generated_at_sha}) — keyed to the ref-populated set, no hardcoded count.

Ownership boundary vs predecessor storage-layout (s-983a8a1b) — WBS, no overlap

  • This section owns the plan.json SCHEMA + REF layer ONLY.
  • The on-disk FILE relocation (moving content/section-<sid>/intel/package.md into the flat content/intel/ layout, writing content/intel/plan.intel.md + sibling .intel.json envelopes) is owned by the lexorank PREDECESSOR storage-layout (s-983a8a1b) per its §Section ownership boundary.
  • w-d7213728 here backfills the plan.json REF struct that POINTS at the files storage-layout writes; it never writes or moves a .intel.md/.intel.json FILE.
  • The migration target is the ref-populated set — every plan whose plan.json carries a populated intel_package ref; keyed to that set, not a fixed plan-count (the prior “9 populated plans” figure is stale; corpus footprint reasoning lives in the predecessor storage-layout §Work Items).
  • Predecessor moves the files; successor backfills the refs — disjoint deliverables.

Verification

Execution is not complete until ALL hold; each work item is pinned by a NAMED test, not a generic suite bucket:

  • w-dfdcea34 (v7 struct round-trip): a pytest pin in scripts/intel_package_runtime/tests/ asserts (a) a v7 Section.intel_package round-trips through the {path, generated_at_sha} struct (parse -> serialize -> parse byte-identical), (b) the plan-root intel_package key validates against the extended properties map under additionalProperties: false (a plan-root intel_package is accepted; an unrelated bare key is still rejected), (c) a flat content/intel/<slug>--<id>.intel.md path is accepted and the retired nested content/section-<sid>/intel/<name>.md no longer appears in the schema description.
  • w-c42a79bf (v2 path-canonical alignment): a pytest pin asserts _validate_intel_package accepts a flat content/intel/<slug>--<id>.intel.md path and its recommended_fix strings emit the flat layout (NOT the nested intel/<section-slug>-package.md); a negative pin asserts an absolute / /tmp-rooted path is still rejected (the existing struct-validator behavior is preserved, only the documented canonical path moves).
  • w-d7213728 (migration backfill): a pytest pin asserts the migration backfills a bare-string intel_package to {path, generated_at_sha: null} for the ref-populated set and is idempotent on an already-struct ref; the pin is keyed to the ref-populated set, with NO hardcoded plan-count assertion.

FLAGGED FOR EXECUTION PHASE (plan.json edit — out of editor scope per route-access ban): success_criterion sc-0007 currently probes a generic pytest scripts/intel_package_runtime/tests/ (schema-integration) bucket. During execution, tighten sc-0007 to name the three per-work-item tests above (struct round-trip for w-dfdcea34, path-canonical alignment for w-c42a79bf, migration backfill for w-d7213728) via the sanctioned write API (scripts/plan_corpus/write.py:success_criterion_append / criterion edit), so the criterion’s probe asserts each work item, not a single bucket.