Skip to content

Roadmap-Backlog Consolidation + Roadmap Rethink (Linear-style) — PLAN.md

Roadmap-Backlog Consolidation + Roadmap Rethink (Linear-style) — PLAN.md

Section titled “Roadmap-Backlog Consolidation + Roadmap Rethink (Linear-style) — PLAN.md”

Spec slug: roadmap-backlog-consolidation Version: v1.0 (draft for ratification at S65 W1a) Authored by: task-planner (fresh instance per Q-PLANNER-2 — independent review pass against PRODUCT.md + TECH.md) under planning-and-task- breakdown for Subtask ID-30.4. Status: PENDING-RATIFICATION (Liam to ratify; Checker promotes 30.4 → done). Linked PRODUCT: docs/specs/id-30-roadmap-backlog-consolidation/PRODUCT.md (15 invariants × 5 clusters; 4 P-OQs all ratified S62 W3 + S63 W1). Linked TECH: docs/specs/id-30-roadmap-backlog-consolidation/TECH.md (526L; 1-to-1 mapping; 5 T-OQs all ratified S65 W0). Linked WP0: Cross-task dependency map at commit a6095553 (docs/research/cross-task-dependency-map-and-sequencing.md on production- readiness; not yet on origin). Last verified: 22/05/2026 against origin/production-readiness HEAD 3bc4fd34 + worktree worktree-agent-a671792d296a5648c.


The work ships in three sequential PRs against production-readiness. Each PR fully merges + CI-green before the next opens:

  • PR-A — Schema + curator skills + 20.14 UI foundation. Purely additive against existing JSON content. Lands: BacklogItemSchema.rank, TaskSchema.capability_theme, RoadmapThemeSchema + union root (sections OR themes); rewritten triage-finding/SKILL.md (Branch B/C under Shape A); rewritten update-roadmap-backlog/SKILL.md (Create / Update / Promote under Shape A); per-task-mirror 20.14 extension (rank-edit + drag-reorder UX in task-view repo). Acceptance gate: schema tests pass on live (rank-less, section-shape) JSON; curator skills load under new shapes.

  • PR-B — Bulk content migration. Removes 8 REMOVE_REDUNDANT roadmap items; adds 54 net-new Backlog entries IDs 78-131 with full Phase-B provenance. Roadmap structure unchanged at PR-B (still 16-section shape minus 8 removals). Acceptance gate: Backlog count delta = +54 (live 54 → 108, per T-OQ-1 reconciliation in 30.5 detail); Roadmap item count = 53.

  • PR-C — Roadmap reshape to Shape A. Authors ~10-12 capability themes; drops RoadmapSectionSchema + RoadmapItemSchema from schema; updates bun run roadmap:render to emit theme-headings; back-fills capability_theme on Tasks. Acceptance gate: theme count ≤ 12; every theme has ≥ 1 linked_tasks[] or linked_backlog[]; every theme has time_horizon set.

9 implementation Subtasks ID-30.5 through ID-30.13. Bringing Task 30 total to 13 Subtasks (4 spec-chain + 9 implementation) — well under the 25-Subtask soft ceiling. Effort estimate per TECH §8: 16-22h grand total spread across 3 PRs / 3 Waves.

WavePRSubtasksEffort
Wave 2PR-A30.5, 30.6, 30.7, 30.86.5-9.5h
Wave 3PR-B30.9, 30.103-4h
Wave 4PR-C30.11, 30.12, 30.136.5-8.5h
  • OQ-B1 ratified — curator-skill rewrite is the FIRST Subtask of PR-A. ID-30’s Branch B/C semantic rewrite is the biggest change (it changes what the skill does). Per WP0 §3 row 5 + §7 OQ-B1: layering smallest-to-largest backwards causes thrash; largest-first means later edits (ID-31 §6.4, ID-23 Inv 8 amendments) are surgical inserts.

  • OQ-C2 ratified — ID-30 PR-A lands BEFORE ID-31 §3 schema (umbrella schema

    • helpers). Both touch lib/validation/ but PR-A is broader-impact (3 schema files + 2 skill files + UI); ID-31 §3 is additive-only (new files). Sibling-only deps enforced within Task 30; cross-Task coordination on PR-A merge happens at Orchestrator level per WP0 §6 Wave 2 sequencing.
  • Inv 13 OQ-8 ALT — Subtask 30.5 dispatches a sub-agent invoking /update- skill against both triage-finding/SKILL.md and update-roadmap-backlog/ SKILL.md. Per WP0 §3 row 5 + CLAUDE.md gotcha “Sub-agents struggle with multi-skill invocations”: two sequential sub-agent dispatches within Subtask 30.5 (one per file), not parallel.


§2.1 Wave 2 — PR-A foundation (Subtasks 30.5-30.8)

Section titled “§2.1 Wave 2 — PR-A foundation (Subtasks 30.5-30.8)”

Subtask 30.5 — Curator-skill rewrites under Shape A (FIRST per OQ-B1)

Section titled “Subtask 30.5 — Curator-skill rewrites under Shape A (FIRST per OQ-B1)”
  • id: 5

  • title: Curator-skill rewrites under Shape A (triage-finding + update- roadmap-backlog)

  • priority: must

  • effort: 2-3h

  • file-ownership zone:

    • .claude/skills/triage-finding/SKILL.md (rewrite Branch B/C semantics)
    • .claude/skills/update-roadmap-backlog/SKILL.md (rewrite Create / Update / Promote under Shape A; add rank, time_horizon, capability_theme copy-through)
    • __tests__/skills/curator-rewrites-smoke.test.ts (NEW — node-level skill contract smoke test)
  • dependencies: [] (PR-A entry point; deliberately the first sibling to honour OQ-B1 ratification — biggest semantic shift lands first so later cross-Task edits from ID-31 §6.4 and ID-23 Inv 8 are surgical inserts)

  • scope: Sub-agent dispatch invoking /update-skill against each file in turn (sequential, not parallel — per WP0 §3 row 5 / CLAUDE.md gotcha). The rewrite surgery is fully specified in TECH §4.1 (triage-finding) and §4.2 (update-roadmap-backlog) — sub-agents read those sections verbatim.

  • details:

    Dispatch a sub-agent invoking /update-skill against .claude/skills/triage- finding/SKILL.md FIRST (lines 110-134 Branch B + lines 136-165 Branch C + failure-modes section lines 237-245), then a SECOND sequential sub-agent dispatch against .claude/skills/update-roadmap-backlog/SKILL.md (Create flow Steps 1-7 / lines 99-258, Update mode lines 261-308, Promote mode lines 364-415, failure-modes section lines 432-440). Both rewrites follow TECH §4 verbatim.

    Triage-finding rewrites (TECH §4.1):

    • Branch B trigger: rewrite from “strategic / cross-cutting / multi-month / new top-level capability” 5-condition OR-gate to a 2-condition capability-theme-promotion gate — (1) finding describes a capability not covered by any existing theme’s linked_tasks[] / linked_backlog[] chain; (2) capability is multi-month or cross-cutting.
    • Branch B output: replace roadmap_target_section with roadmap_proposed_theme carrying title, description, time_horizon (default later), initial_linked_tasks[], initial_linked_backlog[].
    • Branch C: trigger unchanged; output gains priority AND rank fields (rank default null; curator may set explicitly if evidence carries within-tier ordering signal).
    • Branches A + D: unchanged.
    • Examples: keep existing 4 examples; add a fifth illustrating Branch B routing under Shape A semantics (a finding that surfaces a new theme).
    • Failure-modes addition: “Routing a tactical item to Branch B — it belongs on Backlog. Branch B = new capability theme only; single-feature finding routes to Branch C even if touches a theme’s linked_backlog area.”
    • Total churn: ~80 lines of SKILL.md modification.

    Update-roadmap-backlog rewrites (TECH §4.2):

    • Create mode — Roadmap target: full replacement of Step 3 field table (lines 137-184) per TECH §4.2 11-row table (id / title / description / time_horizon / status / linked_tasks / linked_backlog / session_refs / commit_refs / cross_doc_links / notes). Remove section_id / phase_label / severity (none exist under Shape A).
    • Create mode — Backlog target: existing Step 3 table gains rank row (default null; explicit rank from triage payload’s backlog_slot.rank if present).
    • Update mode: add rank to allowed field_edits map (line 271). Auto- shift collision behaviour per P-OQ-3 default (pseudocode in TECH §4.2): inserting at rank: N in tier T pushes every item in tier T with rank ≥ N to rank + 1; emit warning naming shift count. Add time_horizon to allowed field_edits map for roadmap path; validation enum(['now','next','later']).
    • Promote mode: gain capability_theme copy-through per P-OQ-4 default (pseudocode in TECH §4.2):
      1. Read roadmap.json themes[].
      2. Find themes where source_backlog_id in linked_backlog[].
      3. If exactly one match: set Task.capability_theme = theme id.
      4. If zero matches: leave unset.
      5. If 2+ matches: leave unset AND emit warning naming the matching themes.
    • Failure-modes addition: two new bullets (13th-theme warning; rank-on-Create-when-tier-empty hint).
    • Total churn: ~150 lines of SKILL.md modification.

    Smoke test (TECH §6.1 + TECH §9 T-OQ-5): Author __tests__/skills/ curator-rewrites-smoke.test.ts per the mock-payload + contract-output assertion pattern (T-OQ-5 ratified). Mock payload simulates a Branch C decision from the rewritten triage-finding; assert that invoking Create against backlog under the rewritten update-roadmap-backlog (a) parses to the new BacklogItemSchema (rank field present + nullable), (b) Phase-B provenance round-trips cleanly, (c) the rank field is settable from the triage payload.

    Verification (CLAUDE.md AST-Dataflow / GitNexus discipline):

    • Before dispatching the sub-agent, run gitnexus_context({name: "triage-finding"}) and gitnexus_context({name: "update-roadmap- backlog"}) to surface caller blast radius.
    • After sub-agent commits, run gitnexus_detect_changes() to verify edit scope matches expected file set.
    • Run bun run test __tests__/skills/curator-rewrites-smoke.test.ts and confirm green.

    Forward-compat hook (per WP0 §3 row 5 / §7 OQ-B1): the rewritten skill bodies are read by ID-31 §6.4 (umbrella_id parameter on Promote — Wave 5) and ID-23 Inv 8 (caller-count pre-grep on triage-finding Step 1 — Wave 5). Those later edits are surgical inserts ON TOP of the Shape-A-rewritten bodies, not ground-up rewrites. The smoke test is the seal: after Wave 5 amendments land, the smoke test continues passing if the Shape A contract is preserved.

    Touch zone (Edit / Write):

    • .claude/skills/triage-finding/SKILL.md
    • .claude/skills/update-roadmap-backlog/SKILL.md
    • __tests__/skills/curator-rewrites-smoke.test.ts (NEW)
  • testStrategy: Smoke test (bun run test __tests__/skills/curator- rewrites-smoke.test.ts) passes; both rewritten skills load via /update-skill verification step; manual diff review confirms TECH §4.1 + §4.2 surgery applied verbatim (no scope creep).

Subtask 30.6 — Schema field additions (PR-A additive)

Section titled “Subtask 30.6 — Schema field additions (PR-A additive)”
  • id: 6

  • title: Schema additions — BacklogItemSchema.rank, TaskSchema.capability_ theme, RoadmapThemeSchema + union root

  • priority: must

  • effort: 1-1.5h

  • file-ownership zone:

    • lib/validation/backlog-schema.ts (+1 field: rank)
    • lib/validation/task-list-schema.ts (+1 field: capability_theme)
    • lib/validation/roadmap-schema.ts (+RoadmapThemeSchema export + union root via .superRefine())
  • dependencies: []

  • scope: Three Zod schema additions per TECH §3.1. All purely additive against existing live JSON content — both shapes valid simultaneously in PR-A; PR-C drops the legacy sections shape.

  • details:

    lib/validation/backlog-schema.ts (1-line addition between notes and details ~line 122):

    /**
    * Within-priority deterministic ordering. Lower integer = higher rank.
    * Default null; pre-existing items omit. Schema does NOT enforce
    * uniqueness or contiguity within tier (PRODUCT inv 3). Curator skill
    * maintains discipline (Subtask 30.5 rewrite + P-OQ-3 auto-shift default).
    */
    rank: z.number().int().nullable().optional(),

    No new exports — BacklogItem type re-derives via z.infer<typeof BacklogItemSchema>.

    lib/validation/task-list-schema.ts (1-line addition ~line 130, after the array-fields block, before .strict()):

    /**
    * Optional back-link to a Roadmap theme (OQ-6 ratification). Authoritative
    * direction is theme.linked_tasks[]; capability_theme is convenience
    * back-link the curator skill maintains in sync. Absent = unaffiliated.
    */
    capability_theme: z.string().nullable().optional(),

    lib/validation/roadmap-schema.ts (additive — keep existing RoadmapSectionSchema + RoadmapItemSchema in PR-A; PR-C drops them via Subtask 30.12):

    Add new export RoadmapThemeSchema per TECH §3.1 (10 fields per Phase-B shape: id / title / description / time_horizon enum 3-value / status enum 3-value per P-OQ-1 default / linked_tasks / linked_backlog / session_refs / commit_refs / cross_doc_links / notes). .strict().

    Reshape RoadmapSchema root from required sections[] to optional sections[] + optional themes[], with .superRefine() enforcing “exactly one of”:

    .superRefine((doc, ctx) => {
    const hasSections = doc.sections !== undefined;
    const hasThemes = doc.themes !== undefined;
    if (hasSections === hasThemes) {
    ctx.addIssue({
    code: 'custom',
    path: ['sections', 'themes'],
    message: 'Exactly one of `sections` or `themes` must be present.',
    });
    }
    });

    Per T-OQ-4 ratification: stay with superRefine (not discriminatedUnion) to avoid forcing a discriminator-field content edit on every existing roadmap.json read in PR-A.

    GitNexus verification (CLAUDE.md discipline):

    • Before edit: gitnexus_impact({target: "BacklogItemSchema", direction: "upstream"}) and gitnexus_impact({target: "RoadmapSchema", direction: "upstream"}) to surface caller blast radius (expect: schema-roundtrip tests, curator-skill consumers, task-view vendoring).
    • After edit: gitnexus_detect_changes() to verify edit scope.

    Touch zone (Edit):

    • lib/validation/backlog-schema.ts
    • lib/validation/task-list-schema.ts
    • lib/validation/roadmap-schema.ts
  • testStrategy: Existing schema-roundtrip tests (__tests__/docs/backlog-schema-roundtrip.test.ts + __tests__/docs/roadmap-roundtrip.test.ts) continue to pass against live JSON; bun run test __tests__/lib/validation/ green.

Subtask 30.7 — Schema tests + sort helper

Section titled “Subtask 30.7 — Schema tests + sort helper”
  • id: 7

  • title: Schema tests + sortBacklogItems helper

  • priority: must

  • effort: 1.5-2h

  • file-ownership zone:

    • __tests__/lib/validation/backlog-schema-rank-field.test.ts (NEW)
    • __tests__/lib/validation/roadmap-schema-shape-a.test.ts (NEW)
    • __tests__/lib/validation/roadmap-schema-soft-cap.test.ts (NEW)
    • __tests__/lib/validation/task-list-schema-capability-theme.test.ts (NEW)
    • lib/backlog/sort.ts (NEW — pure deterministic sort helper)
    • __tests__/lib/backlog/sort.test.ts (NEW)
    • lib/validation/roadmap-schema.ts (+ parseRoadmapWithWarnings() helper mirroring parseTaskListWithWarnings)
  • dependencies: [6]

  • scope: All schema and sort-helper tests per TECH §3.3 + §6.1. parseRoadmapWithWarnings mirrors the existing parseTaskListWithWarnings pattern (lib/validation/task-list-schema.ts:235-254) for the 12-theme soft-cap warning.

  • details:

    __tests__/lib/validation/backlog-schema-rank-field.test.ts (verifies inv 3): 6 cases — (a) rank: null parses; (b) rank: 10 parses; (c) rank: -5 parses (no positive constraint); (d) rank: "10" fails (non-integer); (e) rank: 1.5 fails; (f) rank omitted parses.

    __tests__/lib/validation/roadmap-schema-shape-a.test.ts (verifies inv 6, 7): 4 cases PR-A — (a) document with themes[] only parses; (b) document with sections[] only parses (transitional); (c) document with both fails (superRefine union-discriminator error); (d) document with neither fails. Plus 5 RoadmapThemeSchema cases — (a) all required fields present parses; (b) time_horizon: "someday" fails; (c) status outside 3-value set fails; (d) id: "x" fails (non-bare-digit); (e) stale ref in linked_tasks[] parses (no referential integrity at schema level — render- time concern).

    __tests__/lib/validation/roadmap-schema-soft-cap.test.ts (verifies inv 8): 3 cases — (a) 12 themes — no warning; (b) 13 themes — one warning naming count; (c) 30 themes — still ONE warning (per-document, not per- excess-theme). Hard schema parse succeeds for all three.

    __tests__/lib/validation/task-list-schema-capability-theme.test.ts (verifies inv 9): 4 cases — (a) capability_theme: null parses; (b) capability_theme: "1" parses; (c) field absent parses (optional); (d) capability_theme: 123 fails.

    lib/backlog/sort.ts + test (verifies inv 4):

    export function sortBacklogItems(items: BacklogItem[]): BacklogItem[] {
    const priorityOrder: Record<Priority, number> = {
    must: 0, should: 1, could: 2, future: 3,
    high: 4, medium: 5, low: 6, trigger: 7,
    };
    return [...items].sort((a, b) => {
    const pDelta = priorityOrder[a.priority] - priorityOrder[b.priority];
    if (pDelta !== 0) return pDelta;
    const rA = a.rank ?? Number.MAX_SAFE_INTEGER;
    const rB = b.rank ?? Number.MAX_SAFE_INTEGER;
    if (rA !== rB) return rA - rB;
    // bare-digit id lexicographic safe via parseInt
    return parseInt(a.id, 10) - parseInt(b.id, 10);
    });
    }

    Test fixture: 8-case ordering — priority changes, rank null vs set, id tiebreaker on bare-digit comparison (“9” sorts before “10” via parseInt).

    parseRoadmapWithWarnings in lib/validation/roadmap-schema.ts (mirrors task-list pattern):

    export interface RoadmapWarning {
    themeCount?: number;
    message: string;
    }
    export function parseRoadmapWithWarnings(input: unknown): {
    value: Roadmap;
    warnings: RoadmapWarning[];
    } {
    const value = RoadmapSchema.parse(input);
    const warnings: RoadmapWarning[] = [];
    if (value.themes && value.themes.length > 12) {
    warnings.push({
    themeCount: value.themes.length,
    message: `Roadmap has ${value.themes.length} themes (>12). ` +
    `Per PRODUCT inv 8, consider merging.`,
    });
    }
    return { value, warnings };
    }

    Touch zone (Write / Edit):

    • 4 new test files in __tests__/lib/validation/
    • lib/backlog/sort.ts (NEW)
    • __tests__/lib/backlog/sort.test.ts (NEW)
    • lib/validation/roadmap-schema.ts (+ helper function append)
  • testStrategy: All 6 new test files green via bun run test; existing schema-roundtrip tests continue passing; sort helper return values asserted against fixture.

Subtask 30.8 — per-task-mirror 20.14 extension (rank-edit + drag-reorder)

Section titled “Subtask 30.8 — per-task-mirror 20.14 extension (rank-edit + drag-reorder)”
  • id: 8

  • title: per-task-mirror Backlog rank-edit + drag-reorder UX (Subtask 20.14 in task-view repo)

  • priority: must

  • effort: 2-3h

  • file-ownership zone:

    • External task-view repo (packages/ui/ Backlog index page component)
    • e2e/tests/task-mirror-backlog-rank.spec.ts (NEW Playwright spec in KH repo)
  • dependencies: [6]

  • scope: Per PRODUCT inv 10 + TECH §2 row inv 10. Extend the per-task- mirror Backlog index page (in task-view repo) with rank integer-input edit-in-place + drag-and-drop bulk-reorder UX (keyboard-operable). New sort order: priority → rank (nulls last) → id. T-OQ-2 RATIFIED — task- view patch-server.ts confirmed landed at task-view repo at packages/server/patch-server.ts, so the structured-patch path A4 builds on exists.

  • details:

    Task-view repo changes (the per-task-mirror viewer is a sibling repo, not in the KH worktree; the Subtask’s commit ships KH-side changes only — the task-view side may need a coordinated PR but that’s tracked in 20.14’s task-view-side commits, not Task 30’s KH-side commit history):

    • Add rank to the Backlog index page item-row affordances. Edit-in-place via integer input. “(unset)” option clears to null per inv 30 visual treatment from per-task-mirror PRODUCT.
    • Drag handle on each item-row; drag within priority tier re-ranks items via single atomic multi-field patch. Server-side rollback on validation failure.
    • Keyboard operability: arrow keys move focused row up/down within tier; Enter commits. WCAG 2.1 AA.
    • Sort order updates from per-task-mirror inv 20 (track → status → id) to priority → rank (nulls last) → id on the Backlog index specifically (other ledgers unchanged).
    • UX library: defer to task-view repo conventions (@dnd-kit/core or react-dnd). Constraint: keyboard-operable, semantic tokens (Warm Meridian), atomic patch transaction.

    KH-side E2E spec (e2e/tests/task-mirror-backlog-rank.spec.ts):

    • (a) navigate to Backlog index page;
    • (b) click rank affordance on item X; type 5; save;
    • (c) assert item X moves above item Y (with higher rank) within same tier;
    • (d) drag item A above item B; save; assert ranks updated atomically; refresh; assert order persists;
    • (e) axe-core a11y test: keyboard-navigate to drag handle; focus visible; arrow-keys move; Enter commits;
    • (f) Warm Meridian semantic-token regex against rendered DOM (no raw Tailwind colour classes in rank-edit affordance markup);
    • (g) NEGATIVE assertion (verifies inv 11): no element with text “Promote” or data-testid="promote-button" on Backlog index or per- item page.

    Patch-API dependency (T-OQ-2 ratified): patch-server.ts exists in task-view repo at packages/server/patch-server.ts — confirmed pre- flight. A4 builds on this without needing a stub patch-API. The structured-patch path per per-task-mirror PRODUCT inv 33 is operational.

    CLAUDE.md / agent-browser discipline: E2E spec uses Playwright per KH e2e convention (NOT agent-browser, which is for interactive testing). Browser install per CLAUDE.md gotcha: python3 -m playwright install chromium if not already present in dev env.

    Touch zone:

    • task-view repo (coordinated PR — outside KH-side commit scope but referenced in 30.8 brief)
    • e2e/tests/task-mirror-backlog-rank.spec.ts (NEW, KH-side)
  • testStrategy: Playwright spec passes (bun run test:e2e filtered to the new spec); axe-core a11y assertions green; semantic-token regex finds no raw Tailwind colour classes; Promote-button negative assertion green.

§2.2 Wave 3 — PR-B bulk content migration (Subtasks 30.9-30.10)

Section titled “§2.2 Wave 3 — PR-B bulk content migration (Subtasks 30.9-30.10)”
  • id: 9

  • title: Migration script — append 54 net-new backlog entries; remove 8 REMOVE_REDUNDANT roadmap items

  • priority: must

  • effort: 2-3h

  • file-ownership zone:

    • scripts/migrate-backlog-from-roadmap.ts (NEW)
    • scripts/fixtures/backlog-migration-payload.json (NEW — extracted from RESEARCH §3.2 JSON snippet)
    • __tests__/scripts/migrate-backlog-from-roadmap.test.ts (NEW)
  • dependencies: [5, 6, 7]

  • scope: Author the migration script + its idempotency / collision tests per TECH §2 inv 1+2+5+15 and TECH §7 risk row 3 (payload extraction). The Subtask depends on the curator-skill rewrite (30.5) and schema additions (30.6, 30.7) being done so the migration’s Create-mode contract aligns with the rewritten skill body.

  • details:

    Payload fixture (scripts/fixtures/backlog-migration-payload.json): Extract the RESEARCH §3.2 JSON snippet (lines 308-1101 of docs/research/ roadmap-backlog-consolidation-and-roadmap-rethink.md) into a sibling fixture file. The fixture contains 54 net-new entries IDs 78-131 with full Phase-B schema shape per PRODUCT inv 2.

    Migration script (scripts/migrate-backlog-from-roadmap.ts): Node script. Steps:

    1. Read docs/reference/product-backlog.json via fs.readFileSync + JSON.parse.
    2. Read fixture payload via fs.readFileSync.
    3. Build a Set of existing item ids; iterate payload entries; for each entry not already present, append to a new-items[] array (idempotency: re-running skips already-migrated ids).
    4. For each PARTIAL_OVERLAP cluster (per PRODUCT inv 5 + RESEARCH §5.4 — ingest-UI: ID-61+62+79+100, doc-triage: ID-64+82, prompt-suggestion: ID-49+91, portal-automation: ID-53+101): add an adjacency notes line to each member of the cluster citing every other member.
    5. Read docs/reference/task-list.json; load TaskListSchema.parse(); iterate new entries; for each, lowercase + tokenise the new description and every active Task title; assert no 4-word-window overlap (per PRODUCT inv 5 + TECH §2 inv 5 row).
    6. Merge new entries into backlog items[]; validate via BacklogSchema.parse().
    7. Read docs/reference/product-roadmap.json; remove the 8 REMOVE_ REDUNDANT roadmap items (3.2, 3.4, 3.6, 7.2, 7.6, 8.1, 11.17, partial 11.2 per RESEARCH §2 + PRODUCT inv 12 PR-B description).
    8. Validate roadmap via RoadmapSchema.parse().
    9. Write both files atomically via fs.writeFileSync.

    Idempotency contract per PRODUCT inv 15 + TECH §3.2 order 6: running the script twice produces identical final JSON state.

    Phase-B provenance contract per PRODUCT inv 2: every appended entry carries the canonical "Migrated from roadmap §X.Y. ..." marker in notes field. The fixture should already encode this (verified during extraction).

    Idempotency + collision tests (__tests__/scripts/migrate-backlog-from- roadmap.test.ts):

    • (a) Run migration once on a copy of live JSON; assert delta = +54 new entries; all IDs 78-131 present.
    • (b) Run again; assert delta = 0 (idempotent).
    • (c) Mock a fixture with one id deliberately pre-populated; assert the script reports the collision and does NOT write (exit code non-zero or error thrown).
    • (d) Mock a fixture with one entry’s track field corrupted to empty string; assert Zod parse failure aborts write.
    • (e) Mock the task-list with a Task whose title 4-word-window-matches a new backlog entry’s description; assert the script aborts with a clear duplicate-detection error.
    • (f) Assert every new entry’s notes field contains the "Migrated from roadmap §" substring.
    • (g) Assert the 4 PARTIAL_OVERLAP clusters’ id-lists are all present in the post-migration backlog and that each cluster member has a notes line citing every other member.
    • (h) Assert roadmap item count drops from 61 to 53.

    T-OQ-1 reconciliation (live count vs PRODUCT stated count): PRODUCT inv 1 cites “55 → 109” but live count is 54. Update PRODUCT inv 1 + PR-B acceptance gate text to “54 → 108” in a one-line spec amendment committed as part of 30.9. The delta +54 is the load-bearing assertion; absolute count is informational.

    CLAUDE.md ast-dataflow discipline: Before script ships, run bun scripts/ast-dataflow-cli.ts string-literal-uses "Migrated from roadmap §" to verify no existing references collide. Run gitnexus impact against BacklogSchema if any field name added.

    Touch zone (Write):

    • scripts/migrate-backlog-from-roadmap.ts (NEW)
    • scripts/fixtures/backlog-migration-payload.json (NEW)
    • __tests__/scripts/migrate-backlog-from-roadmap.test.ts (NEW)
    • docs/specs/id-30-roadmap-backlog-consolidation/PRODUCT.md (1-line amendment: “55 → 109” becomes “54 → 108” per T-OQ-1)
  • testStrategy: All 8 test cases (a-h) pass via bun run test __tests__/scripts/migrate-backlog-from-roadmap.test.ts; idempotency check verifies second-run produces identical JSON; collision tests verify abort-before-write.

Subtask 30.10 — Bulk content migration execution

Section titled “Subtask 30.10 — Bulk content migration execution”
  • id: 10

  • title: Execute migration script — commit 54 net-new backlog entries + 8 roadmap item removals

  • priority: must

  • effort: 1h

  • file-ownership zone:

    • docs/reference/product-backlog.json (54 entries appended)
    • docs/reference/product-roadmap.json (8 items removed)
  • dependencies: [9]

  • scope: Run the migration script from 30.9 against live JSONs; verify outputs; commit.

  • details:

    Steps:

    1. Run bun scripts/migrate-backlog-from-roadmap.ts against live JSONs.
    2. Verify backlog item count via jq '.items | length' docs/reference/ product-backlog.json reports 108 (54 → 108 per T-OQ-1 amendment).
    3. Verify roadmap item count via roadmap-render count or section-by-section item count: total = 53.
    4. Verify all PARTIAL_OVERLAP cluster notes present via grep.
    5. Verify Phase-B provenance markers present for IDs 78-131 via grep "Migrated from roadmap §".
    6. Run bun run test __tests__/docs/backlog-schema-roundtrip.test.ts + __tests__/docs/roadmap-roundtrip.test.ts — both green.
    7. Run bun run test __tests__/scripts/migrate-backlog-from-roadmap.test. ts — green.
    8. Commit per commit-commands:commit skill: feat(s65-w3-30.10): PR-B bulk content migration — 54 net-new backlog entries + 8 roadmap removals.

    PR-B acceptance gate verification per PRODUCT inv 12:

    • Backlog count delta = +54 (live 54 → 108).
    • Roadmap item count drops from 61 to 53.
    • All notes-field markers present.
    • No schema errors.
    • No item duplicates per inv 5.

    Idempotency probe: Re-run the script after the initial commit; expect zero diff (no new file changes). Confirms PRODUCT inv 15 idempotency in live execution.

    Touch zone (Write — via script execution):

    • docs/reference/product-backlog.json
    • docs/reference/product-roadmap.json
  • testStrategy: Both round-trip tests green post-migration; manual count verification matches expected delta; idempotency probe (re-run script) produces zero diff.

§2.3 Wave 4 — PR-C Roadmap reshape to Shape A (Subtasks 30.11-30.13)

Section titled “§2.3 Wave 4 — PR-C Roadmap reshape to Shape A (Subtasks 30.11-30.13)”

Subtask 30.11 — Content reshape — author 10-12 capability themes

Section titled “Subtask 30.11 — Content reshape — author 10-12 capability themes”
  • id: 11

  • title: Author 10-12 capability themes per Shape A — populate themes[]

    • linked_tasks/linked_backlog
  • priority: must

  • effort: 3-4h

  • file-ownership zone:

    • docs/reference/product-roadmap.json (full reshape to themes[] array)
  • dependencies: [10]

  • scope: Curator-authored content reshape. Replace 53-item / 16-section shape with 10-12 capability themes per PRODUCT inv 6, 7, 8.

  • details:

    Authoring process:

    1. Read post-PR-B docs/reference/product-roadmap.json (16 sections, 53 items).
    2. Read post-PR-B docs/reference/product-backlog.json (108 items including the 54 newly-migrated).
    3. Read docs/reference/task-list.json (in-flight Tasks).
    4. Identify ~10-12 capability themes that cover the strategic surface. RESEARCH §4 named candidate themes (Sales Proposals, MCP server, ingestion-UI, taxonomy-and-vocab, intelligence-refinement, etc.) — re-evaluate against post-PR-B state.
    5. For each theme: author id (bare-digit, “1” onwards under Shape A), title, description (multi-paragraph Markdown; why this capability matters; outcome shape), time_horizon (one of now / next / later per OQ-2 + P-OQ-1 default), status: 'pending' (P-OQ-1 default), linked_tasks[] (Task IDs from task-list contributing), linked_backlog[] (Backlog item IDs from product-backlog contributing), full Phase-B provenance (session_refs: ["kh-prod-readiness-S65"] at minimum), cross_doc_links if relevant, notes free text.
    6. Write document with the new schema shape: drop the sections[] field; populate themes[]. The RoadmapSchema union (from 30.6) accepts this in PR-C transitional state; the schema reshape in 30.12 drops the union.

    Theme cardinality discipline per PRODUCT inv 8: soft cap 12. If the authoring surfaces a 13th theme, consider merging per parseRoadmapWith Warnings warning (which 30.7 added). Re-evaluate quarterly.

    PR-C acceptance gate per PRODUCT inv 12:

    • Theme count ≤ 12.
    • Every theme has ≥ 1 linked_tasks[] OR linked_backlog[] entry (no orphan themes).
    • Every theme has a time_horizon set.

    CLAUDE.md / UK English discipline: every theme title + description in UK English (colour, organisation, behaviour, DD/MM/YYYY dates).

    Coordination with WP0 §3 row 5 (curator skill rewrites): the update-roadmap-backlog Create-mode contract (from 30.5) IS the contract used here. The author may invoke /update-roadmap-backlog Create once per theme to populate themes[] — verifying the rewritten skill’s contract works in practice.

    Touch zone (Write — full file replacement):

    • docs/reference/product-roadmap.json
  • testStrategy: All three PRODUCT inv 12 PR-C acceptance gates verified via manual or scripted check: jq '.themes | length' docs/reference/ product-roadmap.json ≤ 12; jq '.themes[] | select((.linked_tasks | length) == 0 and (.linked_backlog | length) == 0)' returns empty; jq '.themes[] | select(.time_horizon == null)' returns empty.

Subtask 30.12 — Schema final reshape (drop sections / RoadmapSectionSchema)

Section titled “Subtask 30.12 — Schema final reshape (drop sections / RoadmapSectionSchema)”
  • id: 12

  • title: RoadmapSchema final reshape — drop sections[] / RoadmapSection Schema / RoadmapItemSchema; require themes only

  • priority: must

  • effort: 1.5h

  • file-ownership zone:

    • lib/validation/roadmap-schema.ts (breaking reshape — drop legacy)
  • dependencies: [11]

  • scope: Per TECH §3.1 PR-C reshape — drop the union root; drop legacy schema exports. Pre-30.12 ensure all consumers migrated (per TECH §7 risk row 1: enumerate via grep -rn "RoadmapSectionSchema\|RoadmapItem Schema" --include="*.ts" and migrate or delete each).

  • details:

    Pre-edit consumer enumeration:

    Terminal window
    grep -rn "RoadmapSectionSchema\|RoadmapItemSchema" --include="*.ts"

    Expected consumers (verify all migrated or removed in PR-C):

    • scripts/roadmap-from-json.ts — legacy MD renderer; migrates in 30.13.
    • __tests__/docs/roadmap-roundtrip.test.ts — updates in 30.13.
    • Any tests that still import the legacy schemas — update or delete.

    Schema reshape lib/validation/roadmap-schema.ts:

    Remove these exports:

    • RoadmapSectionSchema (lines 186-226)
    • RoadmapItemSchema (lines 106-180)
    • The sections field from RoadmapSchema
    • The .superRefine() union enforcement from 30.6 (no longer needed)

    Keep / require:

    • RoadmapThemeSchema (already added in 30.6)
    • RoadmapSchema root requires themes: z.array(RoadmapThemeSchema) (changes from optional to required)
    • parseRoadmapWithWarnings (already added in 30.7)

    Update test __tests__/lib/validation/roadmap-schema-shape-a.test.ts (the file 30.7 created): drop the PR-A transitional cases that asserted sections[]-only parses; assert that document with sections[] now FAILS schema parse.

    GitNexus discipline (CLAUDE.md):

    • Before edit: gitnexus_impact({target: "RoadmapSectionSchema", direction: "upstream"}) — surfaces all consumers; verify against the grep result.
    • After edit: gitnexus_detect_changes().

    Touch zone (Edit):

    • lib/validation/roadmap-schema.ts
    • __tests__/lib/validation/roadmap-schema-shape-a.test.ts (drop transitional cases)
  • testStrategy: All schema tests green; the legacy-shape document now fails parse (negative assertion); no remaining imports of RoadmapSectionSchema or RoadmapItemSchema per grep post-edit; no cycle introduced.

Subtask 30.13 — Renderer update + capability_theme back-fill

Section titled “Subtask 30.13 — Renderer update + capability_theme back-fill”
  • id: 13

  • title: Renderer update — emit theme-headings; back-fill capability_ theme on Tasks

  • priority: must

  • effort: 2-3h

  • file-ownership zone:

    • scripts/roadmap-from-json.ts (rewrite for themes shape)
    • docs/reference/task-list.json (back-fill capability_theme on Tasks where clear)
    • __tests__/docs/roadmap-roundtrip.test.ts (update to new shape)
    • scripts/backfill-capability-theme.ts (NEW — small reverse-map script)
  • dependencies: [12]

  • scope: Per TECH §2 inv 6 + inv 9 + §3.2 order 8 + §6.2. The renderer is rewritten for themes shape; the back-fill script reverse-maps from theme.linked_tasks[] to set Task.capability_theme per T-OQ-3 ratified default (split if >30 Tasks affected).

  • details:

    Renderer rewrite (scripts/roadmap-from-json.ts):

    Replace the section-traversal logic with theme-traversal. Emit one MD heading per theme:

    # {document_name}
    ## Theme: {title} ({time_horizon} — {status})
    {description}
    **Linked Tasks:** {linked_tasks.map(id => `[ID-${id}](...)`)}
    **Linked Backlog:** {linked_backlog.map(id => `[BID-${id}](...)`)}

    Idempotency probe (per TECH §7 risk row 9): render-twice-assert-equal test added to the round-trip suite.

    Back-fill script (scripts/backfill-capability-theme.ts):

    import { RoadmapSchema } from '@/lib/validation/roadmap-schema';
    import { TaskListSchema } from '@/lib/validation/task-list-schema';
    import fs from 'fs';
    // Read both files
    const roadmap = RoadmapSchema.parse(JSON.parse(
    fs.readFileSync('docs/reference/product-roadmap.json', 'utf-8')));
    const taskList = TaskListSchema.parse(JSON.parse(
    fs.readFileSync('docs/reference/task-list.json', 'utf-8')));
    // Build reverse map: task_id -> theme_id
    const reverseMap = new Map<string, string>();
    for (const theme of roadmap.themes ?? []) {
    for (const taskId of theme.linked_tasks) {
    // If task is linked from multiple themes, leave unset (warn)
    if (reverseMap.has(taskId)) {
    console.warn(`Task ${taskId} linked from multiple themes — leaving capability_theme unset`);
    reverseMap.set(taskId, ''); // sentinel for "ambiguous"
    } else {
    reverseMap.set(taskId, theme.id);
    }
    }
    }
    // Back-fill task_list
    let updatedCount = 0;
    for (const task of taskList.tasks) {
    const themeId = reverseMap.get(task.id);
    if (themeId && themeId !== '') {
    task.capability_theme = themeId;
    updatedCount++;
    }
    }
    // Write
    fs.writeFileSync('docs/reference/task-list.json',
    JSON.stringify(taskList, null, 2) + '\n');
    console.log(`Back-filled capability_theme on ${updatedCount} Tasks`);

    T-OQ-3 cardinality check (ratified): if >30 Tasks affected, escalate to Orchestrator at script-run time (split 30.13 into 30.13a back-fill + 30.13b renderer). With ~36 Tasks in task-list.json today, likely 10-20 Tasks affected by back-fill — under the 30 threshold; no split needed.

    Round-trip test update (__tests__/docs/roadmap-roundtrip.test.ts): Update fixture + assertions to themes shape. Add render-twice-assert- equal probe per TECH §7 risk row 9.

    CLAUDE.md gotcha (Stable empty array/object defaults in hook returns): N/A — this is a script, not a React hook. But the renderer output JSON ordering must be deterministic so the round-trip test is idempotent.

    Touch zone (Write / Edit):

    • scripts/roadmap-from-json.ts (rewrite)
    • scripts/backfill-capability-theme.ts (NEW)
    • docs/reference/task-list.json (back-fill via script)
    • __tests__/docs/roadmap-roundtrip.test.ts (update)
  • testStrategy: bun run roadmap:render runs cleanly; render-twice- produces-identical-output test green; back-fill script reports a non- empty count of Tasks updated; round-trip test green against new shape; bun run test __tests__/docs/ green.


30.5 (curator skills) 30.6 (schema +)
│ │
└──────┬─────────────────────┤
▼ ▼
30.7 (schema tests 30.8 (20.14 task-view
+ sort helper) extension)
│ │
└─────┬───────────────┘
│ (PR-A merges)
30.9 (migration script + tests)
[deps: 5, 6, 7]
30.10 (run migration + commit)
[deps: 9]
│ (PR-B merges)
30.11 (author themes)
[deps: 10]
30.12 (schema final reshape)
[deps: 11]
30.13 (renderer + back-fill)
[deps: 12]
│ (PR-C merges)
Task 30 done

Per-Subtask dependencies[] (sibling-only integer arrays, NEVER cross- Task — per workflow-orchestration constraint §3.3 / A6):

Subtaskdependenciesrationale
30.5[]PR-A entry point; biggest semantic shift FIRST per OQ-B1
30.6[]PR-A schema additions; can run in parallel with 30.5
30.7[6]Tests depend on schemas existing
30.8[6]20.14 UI consumes the rank field
30.9[5, 6, 7]Migration uses rewritten skill contract + new schema + sort helper
30.10[9]Execution depends on script
30.11[10]Author themes after bulk content migration settles
30.12[11]Schema reshape after content reshape
30.13[12]Renderer + back-fill after schema final reshape

Acyclicity verification: Walking the graph depth-first from any leaf (30.13 → 30.12 → 30.11 → 30.10 → 30.9 → {30.5, 30.6, 30.7} where 30.7 → 30.6) — no cycles. Acyclic: YES.

Sibling-only verification: Every dependencies[] integer references another Subtask of Task 30 (5, 6, 7, 9, 10, 11, 12). No integer references a Subtask of any other Task. The TaskSchema.superRefine enforcement at lib/validation/task-list-schema.ts:132-151 will reject any cross-Task reference at JSON validation time.

Cross-Task dependencies (handled at Task level, not Subtask level — see §5):

  • Task 30 → Task 15 (existing, already in Task.dependencies: ["15"])
  • Task 30 → Task 20 patch-API readiness for 30.8 (T-OQ-2 RATIFIED — patch- server.ts confirmed landed; no Task-level dep amendment needed)

§4 Wave alignment (per WP0 §6 sequencing)

Section titled “§4 Wave alignment (per WP0 §6 sequencing)”
WaveSubtasksSession estimate (per WP0)Cross-Task gates
Wave 230.5, 30.6, 30.7, 30.8~S66OQ-C2: PR-A merges BEFORE ID-31 §3 schema dispatches
Wave 330.9, 30.10~S67PR-A merged (gate Subtask 30.10’s commit)
Wave 430.11, 30.12, 30.13~S67-S68PR-B merged (gate Subtask 30.11’s authoring)

Within Wave 2’s parallel-eligible dispatch (per WP0 §6 Wave 2 “4 disjoint file zones”):

  • Group A — lib/validation/: 30.6 + 30.7 dispatch sequentially (30.7 depends on 30.6 schema being in place). Within group A, ID-30 PR-A additions land BEFORE any potential ID-31 §3 dispatch (OQ-C2 strict- sequence).
  • Group B — .claude/skills/: 30.5 dispatches independently. Per CLAUDE.md gotcha “Sub-agents struggle with multi-skill invocations”: the Subtask brief contains TWO sequential sub-agent dispatches (/update-skill against triage-finding first; then /update-skill against update-roadmap-backlog). NOT parallel.
  • Group C — task-view external repo: 30.8 dispatches independently. Sibling file zone (e2e/ in KH repo); no collision with Group A or B.

Parallel-eligible across groups A + B + C; sequential within A.

  • PR-B (30.9 + 30.10) dispatches AFTER PR-A merges (all of 30.5-30.8 done
    • main-branch CI green).
  • PR-C (30.11-30.13) dispatches AFTER PR-B merges (30.10 done + main- branch CI green).
  • The Orchestrator gates Wave-N+1 dispatch on Wave-N PR merge per workflow-orchestration §wave-sequencing.

After Task 30’s curator-skill rewrites (30.5) land, the rewritten skill bodies are read by:

  • ID-31 §6.4 (Subtask 31.9 — umbrella_id parameter on Promote mode). Surgical addition; ~5-line patch on top of the rewritten Create mode.
  • ID-23 Inv 8 (caller-count pre-grep on triage-finding Step 1). Surgical addition; new Step 0 or Step 1 enhancement on top of the rewritten Branch B/C decision tree.

Both later edits build ON TOP of the Shape-A-rewritten bodies, not ground-up rewrites. The curator-rewrites-smoke.test.ts (from 30.5) continues passing if the Shape A contract is preserved — that’s the seal.


§5 Cross-Task dependencies (NOT Subtask dependencies)

Section titled “§5 Cross-Task dependencies (NOT Subtask dependencies)”

Cross-Task coordination happens at the Orchestrator dispatch level via WP0 sequencing, NOT via task-list.json#/tasks/30/subtasks/N/ dependencies (which stays sibling-only per workflow-orchestration §3.3 / A6).

  • Task 30 → Task 15 (existing in Task.dependencies: ["15"] — schema baseline; Task 15 is done).

Cross-Task coordination (Orchestrator-managed, NOT in Subtask deps)

Section titled “Cross-Task coordination (Orchestrator-managed, NOT in Subtask deps)”
  • Task 30 PR-A → Task 31 §3 dispatch (OQ-C2 ratified strict-sequence): PR-A (30.5-30.8) must merge BEFORE ID-31’s umbrella schema work (Subtasks 31.5-31.6) dispatches. WP0 §6 Wave 2 captures this. The Orchestrator surfaces the gate at dispatch time — no Subtask dependencies[] field expresses this.

  • Task 30 PR-A curator-skill rewrites → Task 23 Inv 8 amendments + Task 31 §6.4 Promote extension (OQ-B1 ratified ordering): Subtask 30.5 lands FIRST (biggest semantic shift). ID-23 Wave 5 + ID-31 Wave 5 later surgical edits build on top. The Orchestrator gates Task 23.3 PLAN dispatch’s brief to instruct sub-agent reading the post-30.5 form before editing. No Subtask dep amendment.

  • Task 30 PR-A schema → Task 9 docubot Wave 7 (forward-compat ID-9 field names locked): PR-A schema additions LOCK these field names at merge time, consumed verbatim by ID-9 Wave 7 docubot narrative templates: rank, time_horizon, linked_tasks, linked_backlog, capability_theme. Any field-name change post-PR-A merge requires a coordinated ID-9 brief amendment. The Orchestrator surfaces this in WP0 §5.4.

  • Task 30 PR-C reshape → Task 9 docubot Wave 7 (forward-compat — bun run roadmap:render MUST still work post-reshape): Subtask 30.13 rewrites the renderer for themes shape so bun run roadmap:render continues working. ID-9 docubot in Wave 7 may eventually replace this legacy renderer; PR-C ensures the bridge holds until then.

Per workflow-orchestration §3.3 / A6: implementation Subtasks within a Task may depend on other Subtasks of the same Task only. Cross-Task dependencies live at the Task level (Task.dependencies[]), not the Subtask level. The above cross-Task coordination items would, if encoded as Subtask deps, violate that constraint. The Orchestrator manages them via WP0 §6 sequencing + per-Wave gate enforcement.


S65 W0 ratifications (5 T-OQs from S64 WP3a TECH)

Section titled “S65 W0 ratifications (5 T-OQs from S64 WP3a TECH)”
  • T-OQ-1 (backlog count): sync issue, not a spec amend. Live count 54, PRODUCT cited 55. RESOLVED: amend PRODUCT inv 1 + PR-B gate prose to “54 → 108” in a one-line edit committed as part of 30.9.
  • T-OQ-2 (Task 20 patch-API readiness): CONFIRMED LANDED. patch- server.ts exists at task-view repo at packages/server/patch-server.ts (pre-flight verified). 30.8 builds on this directly; no stub-patch-API alternative needed.
  • T-OQ-3 (PR-C capability_theme back-fill cardinality): reverse-map from theme.linked_tasks[] in Subtask 30.13. With ~36 Tasks in task-list.json today, ~10-20 likely affected — under 30-Task split threshold; no Subtask split needed.
  • T-OQ-4 (RoadmapSchema union vs discriminatedUnion): superRefine retained (lower content-churn for transitional PR-A).
  • T-OQ-5 (test philosophy for skill smoke test): mock-payload + contract- output assertion pattern. Codified in 30.5 details.

S62 W3 ratifications (P-OQs / OQs ratified before PRODUCT)

Section titled “S62 W3 ratifications (P-OQs / OQs ratified before PRODUCT)”
  • OQ-1 (roadmap shape): Shape A — flat capability themes.
  • OQ-2 (time horizon enum): now / next / later.
  • OQ-3 (theme cardinality): soft cap 12 (guidance, not schema-enforced).
  • OQ-4 (rank field location): Backlog only under Shape A.
  • OQ-5 (Promote affordance): defer to v1.1.
  • OQ-6 (capability_theme back-link on TaskSchema): optional, not mandatory.
  • OQ-7 (migration sequencing): 3 sequential PRs.
  • OQ-8 (curator skill amendments): ALT — own Subtask via dedicated /update-skill sub-agent (becomes 30.5 in this PLAN).

S63 W1 ratifications (4 P-OQs from PRODUCT)

Section titled “S63 W1 ratifications (4 P-OQs from PRODUCT)”
  • P-OQ-1 (theme status enum): 3 values — pending / in_progress / done.
  • P-OQ-2 (Roadmap serialised shape): flat themes[] array; sections dropped in PR-C.
  • P-OQ-3 (rank collision policy): auto-shift on insert per curator skill (Subtask 30.5 Update mode Step 4).
  • P-OQ-4 (capability_theme on Promote): single-match auto-set / multi- match warn-and-skip (Subtask 30.5 Promote mode).

WP0 ratifications applied (6 — affect cross-Task sequencing, not

Section titled “WP0 ratifications applied (6 — affect cross-Task sequencing, not”

PLAN content directly but Subtask brief framing)

  • OQ-B1 ordering: Subtask 30.5 curator-skill rewrite FIRST (biggest semantic shift; layering smallest-to-largest backwards causes thrash).
  • OQ-C2 strict-sequence: Task 30 PR-A merges BEFORE Task 31 §3 dispatches. Orchestrator-managed.
  • OQ-D (ID-22 stale criterion): Outside Task 30 scope. Noted for Wave 9.
  • OQ-E (ID-25 cancelled): Outside Task 30 scope. Status quo.
  • OQ-F (ID-23.3 PLAN sub-agent constraint): Outside Task 30 scope. Noted for Wave 5.
  • WP0 §4 helper location: lib/validation/umbrellas-helpers.ts (Task 31’s territory, not Task 30).

Total ratifications absorbed: 5 (T-OQs) + 8 (S62 W3) + 4 (P-OQs) + 6 (WP0) = 23. ZERO new OQs surfaced during PLAN authoring.


Risk 1 — Cross-branch worktree conflicts on PR-A schema

Section titled “Risk 1 — Cross-branch worktree conflicts on PR-A schema”

Description: PR-A touches three schema files (backlog, task-list, roadmap) — high-churn for lib/validation/. The cross-branch ledger merge at S65 pre-sync (commit 3bc4fd34) already showed cross-branch churn risk in this surface. If Task 31 §3 dispatches before Task 30 PR-A merges, both worktrees edit lib/validation/ simultaneously.

Probability: Medium. Impact: Medium — merge conflicts; not data loss.

Mitigation: OQ-C2 ratified strict-sequence — Task 30 PR-A merges BEFORE Task 31 §3 dispatches. Orchestrator enforces at Wave 2 dispatch gate. Sibling-only Subtask deps within Task 30 reduce intra-Task collision risk.

Risk 2 — Curator-skill rewrite collision with ID-23 Wave 5

Section titled “Risk 2 — Curator-skill rewrite collision with ID-23 Wave 5”

Description: Subtask 30.5 rewrites both triage-finding/SKILL.md and update-roadmap-backlog/SKILL.md under Shape A. Task 23 Wave 5 amends the same two skill bodies (Inv 8 caller-count pre-grep on triage-finding Step 1; propagation discipline + cross-references on update-roadmap- backlog). Per WP0 §3 row 5, three observed sub-agent stalls with multi- skill invocations.

Probability: Low. Impact: Low — sequencing already resolves this per OQ-B1.

Mitigation: OQ-B1 ratified — Task 30 PR-A (30.5) lands FIRST. Task 23 Wave 5 sub-agent reads the post-30.5 form and applies surgical inserts (single Step 0 / Step 1 enhancement on triage-finding; ~5-line propagation block on update-roadmap-backlog). The curator- rewrites-smoke.test.ts (from 30.5) seals the contract — Task 23 amendments must keep the smoke test green.

Risk 3 — Migration script payload extraction (TECH §7 risk row 3)

Section titled “Risk 3 — Migration script payload extraction (TECH §7 risk row 3)”

Description: RESEARCH §3.2 contains the 54 net-new backlog payload as a code-fenced JSON snippet inside the research MD file (lines 308-1101). The migration script needs to consume this — either parse the MD file (fragile) or pre-extract to a sibling fixture (cleaner).

Probability: Low. Impact: Low — script-load failure if extraction skipped.

Mitigation: Subtask 30.9 details specify: extract the JSON snippet into scripts/fixtures/backlog-migration-payload.json at script-author time; commit fixture alongside script. Script reads fixture, not MD file. This decouples migration script from RESEARCH doc location/formatting.

Risk 4 — PR-C breaking-change cascades (TECH §7 risk row 1)

Section titled “Risk 4 — PR-C breaking-change cascades (TECH §7 risk row 1)”

Description: When Subtask 30.12 collapses the union shape to themes- only, any consumer of RoadmapSectionSchema / RoadmapItemSchema that wasn’t migrated breaks at runtime.

Probability: Medium. Impact: High — broken render pipeline, broken docs surface.

Mitigation: Subtask 30.12 details mandate a pre-edit grep -rn "RoadmapSectionSchema\|RoadmapItemSchema" --include="*.ts" sweep to enumerate every consumer; migrate or delete each one in 30.12. Subtask 30.13 covers the legacy renderer migration (scripts/roadmap- from-json.ts). The gitnexus_impact upstream blast-radius check before the edit surfaces consumers the grep might miss.

Risk 5 — 20.14 task-view repo coordination

Section titled “Risk 5 — 20.14 task-view repo coordination”

Description: Subtask 30.8 ships task-view repo changes (rank-edit affordance + drag-reorder UX in packages/ui/) AND a KH-side Playwright E2E spec. The task-view repo is a sibling, not a KH-worktree submodule; coordinated PRs across two repos increases failure modes.

Probability: Medium. Impact: Medium — slip in PR-A merge if task- view side stalls.

Mitigation: Subtask 30.8 details split the work:

  • task-view repo: separate PR / commit history (managed by 20.14’s task-view-side brief).
  • KH repo: only e2e/tests/task-mirror-backlog-rank.spec.ts (NEW)
    • any vendor schema bump if Task 30 schema additions in 30.6 require re-vendoring. The KH-side commit is independently CI-green; the task-view-side coord is tracked in 20.14’s KH-side mirror PR description.

End of PLAN.md. Awaits Liam ratification of any deferred surface; on ratification Subtask 30.4 promotes to done (Checker action) and 30.5 dispatch unblocks Wave 2.

Cross-references:

  • PRODUCT.md: docs/specs/id-30-roadmap-backlog-consolidation/PRODUCT.md
  • TECH.md: docs/specs/id-30-roadmap-backlog-consolidation/TECH.md
  • WP0 cross-task map: docs/research/cross-task-dependency-map-and- sequencing.md (on production-readiness HEAD a6095553)
  • RESEARCH: docs/research/roadmap-backlog-consolidation-and-roadmap- rethink.md
  • Task-list schema: lib/validation/task-list-schema.ts (SubtaskSchema + TaskSchema.superRefine)
  • Curator skills: .claude/skills/{triage-finding,update-roadmap- backlog}/SKILL.md