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.
§1 Overview
Section titled “§1 Overview”3-PR contract (per OQ-7 RATIFIED-DEFAULT)
Section titled “3-PR contract (per OQ-7 RATIFIED-DEFAULT)”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); rewrittentriage-finding/SKILL.md(Branch B/C under Shape A); rewrittenupdate-roadmap-backlog/SKILL.md(Create / Update / Promote under Shape A); per-task-mirror 20.14 extension (rank-edit + drag-reorder UX intask-viewrepo). 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+RoadmapItemSchemafrom schema; updatesbun run roadmap:renderto emit theme-headings; back-fillscapability_themeon Tasks. Acceptance gate: theme count ≤ 12; every theme has ≥ 1linked_tasks[]orlinked_backlog[]; every theme hastime_horizonset.
Decomposition shape
Section titled “Decomposition shape”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.
| Wave | PR | Subtasks | Effort |
|---|---|---|---|
| Wave 2 | PR-A | 30.5, 30.6, 30.7, 30.8 | 6.5-9.5h |
| Wave 3 | PR-B | 30.9, 30.10 | 3-4h |
| Wave 4 | PR-C | 30.11, 30.12, 30.13 | 6.5-8.5h |
Ordering rationale
Section titled “Ordering rationale”-
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.
- helpers). Both touch
-
Inv 13 OQ-8 ALT — Subtask 30.5 dispatches a sub-agent invoking
/update- skillagainst bothtriage-finding/SKILL.mdandupdate-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 Per-Subtask records
Section titled “§2 Per-Subtask records”§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; addrank,time_horizon,capability_themecopy-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-skillagainst 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-skillagainst.claude/skills/triage- finding/SKILL.mdFIRST (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_sectionwithroadmap_proposed_themecarryingtitle,description,time_horizon(defaultlater),initial_linked_tasks[],initial_linked_backlog[]. - Branch C: trigger unchanged; output gains
priorityANDrankfields (rank defaultnull; 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
rankrow (defaultnull; explicit rank from triage payload’sbacklog_slot.rankif present). - Update mode: add
rankto allowedfield_editsmap (line 271). Auto- shift collision behaviour per P-OQ-3 default (pseudocode in TECH §4.2): inserting atrank: Nin tier T pushes every item in tier T withrank ≥ Ntorank + 1; emit warning naming shift count. Addtime_horizonto allowedfield_editsmap for roadmap path; validationenum(['now','next','later']). - Promote mode: gain
capability_themecopy-through per P-OQ-4 default (pseudocode in TECH §4.2):- Read roadmap.json
themes[]. - Find themes where source_backlog_id in
linked_backlog[]. - If exactly one match: set Task.capability_theme = theme id.
- If zero matches: leave unset.
- If 2+ matches: leave unset AND emit warning naming the matching themes.
- Read roadmap.json
- 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.tsper 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 newBacklogItemSchema(rank field present + nullable), (b) Phase-B provenance round-trips cleanly, (c) therankfield is settable from the triage payload.Verification (CLAUDE.md AST-Dataflow / GitNexus discipline):
- Before dispatching the sub-agent, run
gitnexus_context({name: "triage-finding"})andgitnexus_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.tsand 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)
- 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
-
testStrategy: Smoke test (
bun run test __tests__/skills/curator- rewrites-smoke.test.ts) passes; both rewritten skills load via/update-skillverification 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 betweennotesanddetails~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 —
BacklogItemtype re-derives viaz.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
RoadmapThemeSchemaper 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
RoadmapSchemaroot from requiredsections[]to optionalsections[]+ optionalthemes[], 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"})andgitnexus_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.tslib/validation/task-list-schema.tslib/validation/roadmap-schema.ts
- Before edit:
-
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 mirroringparseTaskListWithWarnings)
-
dependencies: [6]
-
scope: All schema and sort-helper tests per TECH §3.3 + §6.1.
parseRoadmapWithWarningsmirrors the existingparseTaskListWithWarningspattern (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: nullparses; (b)rank: 10parses; (c)rank: -5parses (no positive constraint); (d)rank: "10"fails (non-integer); (e)rank: 1.5fails; (f)rankomitted parses.__tests__/lib/validation/roadmap-schema-shape-a.test.ts(verifies inv 6, 7): 4 cases PR-A — (a) document withthemes[]only parses; (b) document withsections[]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)statusoutside 3-value set fails; (d)id: "x"fails (non-bare-digit); (e) stale ref inlinked_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: nullparses; (b)capability_theme: "1"parses; (c) field absent parses (optional); (d)capability_theme: 123fails.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 parseIntreturn 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).
parseRoadmapWithWarningsinlib/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)
- 4 new test files in
-
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-viewrepo (packages/ui/Backlog index page component) e2e/tests/task-mirror-backlog-rank.spec.ts(NEW Playwright spec in KH repo)
- External
-
dependencies: [6]
-
scope: Per PRODUCT inv 10 + TECH §2 row inv 10. Extend the per-task- mirror Backlog index page (in
task-viewrepo) 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 atpackages/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
rankto 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) topriority → rank (nulls last) → idon the Backlog index specifically (other ledgers unchanged). - UX library: defer to task-view repo conventions (
@dnd-kit/coreorreact-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.tsexists in task-view repo atpackages/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 chromiumif not already present in dev env.Touch zone:
task-viewrepo (coordinated PR — outside KH-side commit scope but referenced in 30.8 brief)e2e/tests/task-mirror-backlog-rank.spec.ts(NEW, KH-side)
- Add
-
testStrategy: Playwright spec passes (
bun run test:e2efiltered 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)”Subtask 30.9 — Migration script + tests
Section titled “Subtask 30.9 — Migration script + tests”-
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 ofdocs/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:- Read
docs/reference/product-backlog.jsonviafs.readFileSync+JSON.parse. - Read fixture payload via
fs.readFileSync. - 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).
- 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
notesline to each member of the cluster citing every other member. - Read
docs/reference/task-list.json; loadTaskListSchema.parse(); iterate new entries; for each, lowercase + tokenise the newdescriptionand every active Tasktitle; assert no 4-word-window overlap (per PRODUCT inv 5 + TECH §2 inv 5 row). - Merge new entries into backlog
items[]; validate viaBacklogSchema.parse(). - 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). - Validate roadmap via
RoadmapSchema.parse(). - 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 innotesfield. 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
trackfield 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
notesfield 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
notesline 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
+54is 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 againstBacklogSchemaif 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)
- Read
-
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:
- Run
bun scripts/migrate-backlog-from-roadmap.tsagainst live JSONs. - Verify backlog item count via
jq '.items | length' docs/reference/ product-backlog.jsonreports 108 (54 → 108 per T-OQ-1 amendment). - Verify roadmap item count via roadmap-render count or section-by-section item count: total = 53.
- Verify all PARTIAL_OVERLAP cluster notes present via grep.
- Verify Phase-B provenance markers present for IDs 78-131 via grep
"Migrated from roadmap §". - Run
bun run test __tests__/docs/backlog-schema-roundtrip.test.ts+__tests__/docs/roadmap-roundtrip.test.ts— both green. - Run
bun run test __tests__/scripts/migrate-backlog-from-roadmap.test. ts— green. - Commit per
commit-commands:commitskill: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.jsondocs/reference/product-roadmap.json
- Run
-
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:
- Read post-PR-B
docs/reference/product-roadmap.json(16 sections, 53 items). - Read post-PR-B
docs/reference/product-backlog.json(108 items including the 54 newly-migrated). - Read
docs/reference/task-list.json(in-flight Tasks). - 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.
- 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 ofnow/next/laterper 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_linksif relevant,notesfree text. - Write document with the new schema shape: drop the
sections[]field; populatethemes[]. TheRoadmapSchemaunion (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 Warningswarning (which 30.7 added). Re-evaluate quarterly.PR-C acceptance gate per PRODUCT inv 12:
- Theme count ≤ 12.
- Every theme has ≥ 1
linked_tasks[]ORlinked_backlog[]entry (no orphan themes). - Every theme has a
time_horizonset.
CLAUDE.md / UK English discipline: every theme
title+descriptionin UK English (colour,organisation,behaviour, DD/MM/YYYY dates).Coordination with WP0 §3 row 5 (curator skill rewrites): the
update-roadmap-backlogCreate-mode contract (from 30.5) IS the contract used here. The author may invoke/update-roadmap-backlog Createonce per theme to populatethemes[]— verifying the rewritten skill’s contract works in practice.Touch zone (Write — full file replacement):
docs/reference/product-roadmap.json
- Read post-PR-B
-
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
sectionsfield fromRoadmapSchema - The
.superRefine()union enforcement from 30.6 (no longer needed)
Keep / require:
RoadmapThemeSchema(already added in 30.6)RoadmapSchemaroot requiresthemes: 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 assertedsections[]-only parses; assert that document withsections[]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
RoadmapSectionSchemaorRoadmapItemSchemapergreppost-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-fillcapability_themeon 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 filesconst 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_idconst 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_listlet updatedCount = 0;for (const task of taskList.tasks) {const themeId = reverseMap.get(task.id);if (themeId && themeId !== '') {task.capability_theme = themeId;updatedCount++;}}// Writefs.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:renderruns 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.
§3 Sibling-only dependency graph
Section titled “§3 Sibling-only dependency graph” 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 donePer-Subtask dependencies[] (sibling-only integer arrays, NEVER cross-
Task — per workflow-orchestration constraint §3.3 / A6):
| Subtask | dependencies | rationale |
|---|---|---|
| 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)”| Wave | Subtasks | Session estimate (per WP0) | Cross-Task gates |
|---|---|---|---|
| Wave 2 | 30.5, 30.6, 30.7, 30.8 | ~S66 | OQ-C2: PR-A merges BEFORE ID-31 §3 schema dispatches |
| Wave 3 | 30.9, 30.10 | ~S67 | PR-A merged (gate Subtask 30.10’s commit) |
| Wave 4 | 30.11, 30.12, 30.13 | ~S67-S68 | PR-B merged (gate Subtask 30.11’s authoring) |
Wave 2 ordering — OQ-B1 ratified
Section titled “Wave 2 ordering — OQ-B1 ratified”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-skillagainst triage-finding first; then/update-skillagainst update-roadmap-backlog). NOT parallel. - Group C —
task-viewexternal 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.
Wave 3 + Wave 4 — strict sequential
Section titled “Wave 3 + Wave 4 — strict sequential”- 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.
OQ-B1 forward-compat hook (Wave 5+)
Section titled “OQ-B1 forward-compat hook (Wave 5+)”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_idparameter 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).
Acknowledged Task-level dependencies
Section titled “Acknowledged Task-level dependencies”- 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:renderMUST still work post-reshape): Subtask 30.13 rewrites the renderer for themes shape sobun run roadmap:rendercontinues working. ID-9 docubot in Wave 7 may eventually replace this legacy renderer; PR-C ensures the bridge holds until then.
Why these stay OUT of Subtask deps
Section titled “Why these stay OUT of Subtask deps”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.
§6 OQs already ratified (traceability)
Section titled “§6 OQs already ratified (traceability)”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.tsexists at task-view repo atpackages/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):
superRefineretained (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
statusenum): 3 values — pending / in_progress / done. - P-OQ-2 (Roadmap serialised shape): flat
themes[]array;sectionsdropped 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.
§7 Risks + mitigations
Section titled “§7 Risks + mitigations”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 HEADa6095553) - 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