Skip to content

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

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

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

Spec slug: roadmap-backlog-consolidation Version: v1.0 (draft for ratification at S63) Authored by: task-planner under write-product-spec for Subtask ID-30.2. Status: PENDING-RATIFICATION (Liam to ratify; Checker promotes 30.2 → done). Inputs: docs/research/roadmap-backlog-consolidation-and-roadmap-rethink.md (1648 lines), docs/reference/task-list.json Task ID-30 (description + 30.1 journal with all 8 S62 W3 ratifications).


Three coupled surfaces are reshaped so Knowledge Hub’s product-management ledgers match user-intent Linear-style semantics rather than the inverted shape latent since S40. The work is scoped across four concerns, each of which yields its own invariant cluster below:

  1. Consolidated Backlog — the canonical prioritised work list. Today’s 54 items grow to 108 by absorbing 53 KEEP + PARTIAL Roadmap items per RESEARCH §3 migration (54 net-new entries minus 0 already-promoted), plus a new rank field that gives within-priority deterministic ordering. (T-OQ-1 reconciled at S67 W1a per Subtask 30.9 — original “55 → 109” reflected a stale count; live baseline measured 54.)
  2. Shape A Roadmap — a thin strategic surface of ~10-12 capability themes with now / next / later horizons, forward-linking to Tasks and Backlog. Replaces the 16-section / 61-item shape that 55/61 items mis-fit as tactical work.
  3. Task-view (ID-20.14) extension — the per-task-mirror Backlog edit surface gains rank editing and a bulk-reorder UX so the new field is operable. Promote affordance stays deferred to v1.1 per OQ-5.
  4. Curator skill rewritestriage-finding Branch B/C semantics and update-roadmap-backlog CRUD modes both rewrite under Shape A so future intake routes to the right surface. Per OQ-8 ALT, this is a load-bearing, standalone Subtask in PLAN.md authored via dedicated sub-agent invoking /update-skill.

Net effect: one canonical prioritised work list (Backlog), one slowly-changing strategic surface (Roadmap), one canonical active-sequencing surface (task-list.json), all consistent with Linear / Aha! conventions. Schema, content, and skill changes ship in 3 sequential PRs per OQ-7.


The 8 OQs ratified at S62 W3 (verbatim from task-list.json Subtask ID-30.1 <info added on 2026-05-21T21:15:00.000Z> journal) map one-to-one onto the invariants below. The Checker uses this table to verify spec compliance per-ratification.

Ratification (S62 W3 verbatim)DecisionInvariant(s) carrying it
OQ-1 Roadmap shapeRATIFIED-DEFAULT — Shape A (flat capability themes)inv 6, 7, 8
OQ-2 Time horizon enumRATIFIED-DEFAULT — now / next / later (Aha! convention)inv 7
OQ-3 Theme cardinalityRATIFIED-DEFAULT — soft cap 12 (guidance, not schema-enforced)inv 8
OQ-4 Rank field locationRATIFIED-DEFAULT — Backlog only under Shape Ainv 3, 4
OQ-5 Promote affordance in task-viewRATIFIED-DEFAULT — defer to v1.1inv 11
OQ-6 capability_theme back-link on TaskSchemaRATIFIED-DEFAULT — optional, not mandatoryinv 9
OQ-7 Migration sequencingRATIFIED-DEFAULT — 3 sequential PRs (PR-A schema/skills → PR-B bulk → PR-C reshape)inv 12
OQ-8 Curator skill amendmentsRATIFIED-ALT — own dedicated Subtask via /update-skill sub-agentinv 13 (load-bearing)

In scope (covered by invariants 1-13):

  • docs/reference/product-backlog.json content + schema changes (Backlog growth from 55 → 109 items + new rank field).
  • docs/reference/product-roadmap.json reshape to Shape A capability themes + schema extension (time_horizon, linked_tasks, linked_backlog).
  • docs/reference/task-list.json schema extension (capability_theme optional back-link).
  • lib/validation/backlog-schema.ts + lib/validation/roadmap-schema.ts + Task schema additions.
  • Per-task-mirror (ID-20) extension Subtask 20.14 — rank integer-input edit + bulk-reorder UX on Backlog index page.
  • .claude/skills/triage-finding/SKILL.md Branch B/C rewrite.
  • .claude/skills/update-roadmap-backlog/SKILL.md Create / Update / Delete / Promote mode rewrites under Shape A.
  • 3-PR migration sequencing per OQ-7.

Out of scope (explicitly):

  • Promote affordance in task-view (deferred to v1.1 per OQ-5; inv 11 records the deferral).
  • Roadmap MD-render pipeline rewrite — the bun run roadmap:render step adapts but doesn’t restructure.
  • Cross-branch task-list ID coordination — that’s Task ID-31’s territory (canonical-pipeline → task-list migration); inv 12 only sequences the 3 PRs for this Task.
  • Astro docs site rendering of Roadmap themes — covered by Task ID-9; this Task only owns the JSON surface.
  • Re-ranking the existing 55 pre-migration Backlog items — rank defaults null (inv 4); curator skill (per inv 13 rewrite) may rank items over time, but the migration does not force a back-fill.

Cluster A — Consolidated Backlog (invariants 1-5)

Section titled “Cluster A — Consolidated Backlog (invariants 1-5)”
  1. Backlog as canonical prioritised work list. docs/reference/product-backlog.json is the single canonical surface for active, scoped-but-not-yet-sequenced work items. Items appear on the Backlog when they are scoped enough to act on but not yet picked up onto task-list.json. The Backlog’s audience is internal (Liam + agents); its purpose is to answer “what should we pick up next?” deterministically. After migration its item count grows from 55 to 109 (54 net-new entries IDs 87-140 per RESEARCH §3.2 minus 0 already-promoted; the migration adds 54 and removes 0 from the existing Backlog).

  2. Migration absorbs 53 KEEP + PARTIAL Roadmap items as net-new Backlog entries with full provenance. Every net-new Backlog entry (IDs 87-140) carries the canonical Phase-B schema shape: id (bare-digit string), description, type (BacklogItemType enum: feature / research / tech_debt / infrastructure / testing / ux / documentation / bug), status (BacklogStatus enum: spec_needed / needs_research / parked / ready / blocked), effort_estimate (nullable string), priority (Priority enum), track (free-string domain label), dependencies (string array of other backlog IDs), session_refs (string array — at minimum ["kh-prod-readiness-S62"] for migration provenance), commit_refs (string array), cross_doc_links (DocLinkSchema array), notes (nullable string; carries the "Migrated from roadmap §X.Y. ..." marker so the migration source is queryable). New optional fields details + testStrategy may be populated for promotion-ready items but are not required at migration time. No EXACT_DUPs are created — the RESEARCH §1 audit found 0 EXACT_DUPs; the 6 PARTIAL_OVERLAP clusters (RESEARCH §5.4) reconcile via thematic adjacency notes in the notes field rather than merges.

  3. rank is a new optional integer-or-null field on BacklogItemSchema. The field encodes within-priority ordering. Lower integer = higher rank within its priority tier. Default value at insert is null. The field is nullable AND optional on the Zod schema — pre-existing items omit the field; new items may set it explicitly. There is no schema-level constraint that ranks within a priority tier are unique or contiguous; the curator skill (per inv 13 rewrite) maintains rank discipline but the schema does not enforce it.

  4. Sort order on the Backlog is priority-then-rank-then-id, with null rank sorting last within its tier. When two items share priority, the one with a non-null lower rank appears first; items with rank: null appear after all ranked items in their tier, sorted by id as a stable tiebreaker. This deterministic sort applies wherever the Backlog is listed — the per-task-mirror Backlog index page (per inv 10), MD renderers, curator skill listings. The sort is implementable purely from the schema fields; no derived state lives outside the JSON.

  5. No item on the consolidated Backlog duplicates an in-flight or scheduled Task on task-list.json. Per RESEARCH §5.2 the existing Backlog has 0 conflicts with the 16 active Tasks (ID-6 through ID-27); the migration must preserve this property. Before commit, the migration verifies that no net-new Backlog entry’s description, track, or scope semantically duplicates an existing Task entry. PARTIAL_OVERLAP cases per RESEARCH §5.4 (ingest-UI family ID-61 + ID-62 + ID-79 + ID-100; doc-triage ID-64 + ID-82; prompt-suggestion ID-49 + ID-91; portal-automation ID-53 + ID-101) are documented in each item’s notes field as thematic adjacency rather than merged.

Cluster B — Shape A Roadmap (invariants 6-9)

Section titled “Cluster B — Shape A Roadmap (invariants 6-9)”
  1. The Roadmap is a thin strategic surface naming capability themes, not tactical work. docs/reference/product-roadmap.json reshapes from 16 sections / 61 items to a flat list of ~10-12 capability theme entries. Sections disappear; the document’s sections[] array becomes a flat themes[] array (or the section structure is preserved only as a single root with all themes inside — see TECH for the exact serialised shape). The Roadmap’s audience is Liam-as-product-owner; its purpose is to answer “what capabilities are we building this quarter / next quarter / eventually?” without enumerating individual Tasks or Backlog items. Per RESEARCH §4.4, no surveyed PM source — Linear, GitHub, Aha!, ProductPlan, Pichler, ProdPad — treats a roadmap as a place for hours-to-days tactical items, and the rethink resolves that mis-classification (55/61 items pre-rethink were tactical).

  2. Each capability theme carries time_horizon ∈ {now, next, later} and forward-links to Tasks and Backlog items. Per OQ-2 ratification the time horizon enum is exactly the three values now / next / later, matching Aha! best practice. No hard dates are stored — the surface is deliberately fuzzy on dates per Aha!‘s “loose time horizons over hard release dates and deadlines.” The required theme fields are: id (bare-digit string), title (short UK-English capability name), description (Markdown — why this capability matters; outcome shape), time_horizon (one of now / next / later), status (theme-level only; granular status lives on Tasks), linked_tasks (string array of task-list.json Task IDs that deliver this capability), linked_backlog (string array of Backlog item IDs that contribute), session_refs, commit_refs, cross_doc_links (DocLinkSchema array), notes (free-text). Linked-id rendering: when a theme renders (e.g. in the per-task-mirror viewer or in a future Astro docs site page), linked_tasks[] and linked_backlog[] resolve to inline links to the per-record pages; broken links (referenced ID not present) render with the same missing-target marker the per-task-mirror viewer uses for broken dependencies[] (per docs/specs/id-20-per-task-mirror/PRODUCT.md inv 12).

  3. Theme cardinality has a soft cap of 12. Per OQ-3 ratification, the schema does NOT enforce a hard cap — themes are added freely — but the curator skill (per inv 13 rewrite) treats 12+ themes as a signal that two themes should merge (multi-month capabilities should still be coherent at the headline level). The cap is guidance, surfaced in the rewritten skill’s failure-modes-to-avoid section, not in RoadmapSchema.superRefine. Re-evaluation cadence is quarterly per RESEARCH §4.5.

  4. capability_theme is an optional back-link field on TaskSchema. Per OQ-6 ratification the field is capability_theme: string | null | undefined (optional and nullable on the Zod schema). When set, it names the id of the Roadmap theme this Task contributes to. When absent or null, the Task is unaffiliated — typical for cross-cutting hardening Tasks like ID-19 worktree isolation that don’t fit a product-capability narrative. Mandatory back-linking is rejected because it would force every Task to claim a theme even when the relationship is fuzzy. The forward-link from theme to Task (linked_tasks[] per inv 7) is the authoritative direction; capability_theme is a convenience back-link that the curator skill maintains in sync but is not the source of truth.

Cluster C — Task-view (ID-20.14) extension (invariants 10-11)

Section titled “Cluster C — Task-view (ID-20.14) extension (invariants 10-11)”
  1. The per-task-mirror Backlog index page exposes rank as an editable integer field per item. Extending docs/specs/id-20-per-task-mirror/PRODUCT.md inv 20-25 and inv 30: the Backlog per-item page surfaces rank in the frontmatter table next to priority. The field is editable in place via the same affordance pattern as other structured fields (inv 30) — click a small affordance, integer input replaces the rendered value, Save commits via the structured-patch path (inv 33), null is selectable via an explicit “(unset)” option, schema validation rejects non-integer input server-side. The new field appears in the Backlog index page’s sort order per inv 4 above; the existing sort (track, then status, then id per per-task-mirror inv 20) becomes priority, then rank (nulls last), then id to match inv 4 on this surface specifically. Bulk-reorder UX: the Backlog index page exposes a drag-and-drop affordance that re-ranks all items in a given priority tier in a single multi-field patch transaction (the server applies the new ranks atomically; mid-flight failures roll back to the prior order). The drag handle is keyboard-operable (arrow keys move the focused row up/down within its tier; Enter commits) so the affordance meets WCAG 2.1 AA.

  2. Promote-to-task-list affordance remains explicitly out-of-scope for v1. Per OQ-5 ratification, the per-task-mirror Backlog index page does NOT expose a Promote button. The existing “Promotion-ready” badge (per-task-mirror inv 24) remains purely informational. Promote stays a curator-skill / orchestrator responsibility (update-roadmap-backlog Promote mode) for v1. Re-evaluation is explicitly scheduled for v1.1 once the editor is in real use and the friction is measurable — the schedule is recorded here so the deferral is auditable, not silent. If v1.1 lands the affordance, this invariant updates; this PRODUCT.md edits in the same PR per write-product-spec “keep the spec current” guidance.

Cluster D — Curator skill rewrites (invariant 12-13)

Section titled “Cluster D — Curator skill rewrites (invariant 12-13)”
  1. The 3-PR migration sequencing is the contract for landing this work. Per OQ-7 ratification the three PRs execute strictly in order, with each PR fully merged and CI-green before the next opens:

    • PR-A — Schema + skill foundation. Extends lib/validation/roadmap-schema.ts with time_horizon / linked_tasks / linked_backlog (or whatever serialised shape TECH ratifies). Adds rank to lib/validation/backlog-schema.ts. Adds optional capability_theme to TaskSchema. Lands the rewritten .claude/skills/triage-finding/SKILL.md and .claude/skills/update-roadmap-backlog/SKILL.md (per inv 13). Lands the per-task-mirror 20.14 extension (rank edit + drag-reorder per inv 10). PR-A is purely additive — no JSON content reshape — so existing roadmap.json and backlog.json continue validating against the extended schemas with all new fields optional / nullable. Acceptance gate: schema tests pass on the current pre-migration JSON content; curator skills load under their new shapes.
    • PR-B — Bulk content migration. Removes the 8 REMOVE_REDUNDANT roadmap items (3.2, 3.4, 3.6, 7.2, 7.6, 8.1, 11.17, and the rename-gated 11.2 partition). Adds the 54 net-new Backlog entries IDs 87-140 per RESEARCH §3.2 with full Phase-B provenance per inv 2. Roadmap structure unchanged in PR-B — still 16-section shape minus the 8 removals; the reshape happens in PR-C. Acceptance gate: Backlog item count goes from 54 to 108 (T-OQ-1 reconciled at S67 W1a — original “55 → 109” reflected a stale count; live baseline measured 54); Roadmap item count drops from 61 to 53; no schema errors; no item duplicates per inv 5; all migration notes fields carry the canonical "Migrated from roadmap §X.Y. ..." marker.
    • PR-C — Roadmap reshape to Shape A. Reshapes docs/reference/product-roadmap.json from the 16-section / 53-item shape into ~10-12 capability themes per inv 6, 7, 8. Section structure collapses; remaining roadmap items either (a) are subsumed into a parent theme as notes context, (b) migrate to the Backlog if they were in fact tactical (handled via additional KEEP items), or (c) drop because they’re already covered by an existing theme. Sets capability_theme back-links on Tasks per inv 9 where the relationship is clear. Acceptance gate: theme count ≤ 12; every theme has at least one linked_tasks[] or linked_backlog[] entry (no orphan themes); every theme has a time_horizon set.
    • PR boundaries are reviewable independently because each PR’s acceptance gate is verifiable in isolation. Cross-PR dependencies are encoded as PR-B blocked-on PR-A merge, PR-C blocked-on PR-B merge.
  2. Curator skill rewrites are a load-bearing, standalone Subtask of PLAN.md, authored via /update-skill sub-agent. Per OQ-8 RATIFIED-ALT, the rewrites of .claude/skills/triage-finding/SKILL.md and .claude/skills/update-roadmap-backlog/SKILL.md are NOT folded into a broader implementation Subtask. They get their own Subtask in PLAN.md, dispatched to a sub-agent that invokes the /update-skill skill directly. The rewrite covers, at minimum: (a) triage-finding Branch B rewrites to mean “capability theme promotion” — a finding that surfaces a new capability theme not already on the Roadmap. (b) triage-finding Branch C rewrites to mean “active work item promotion” — add to prioritised Backlog with priority + rank. Branch A (in-Subtask scope) and Branch D (no-action) semantics are unchanged. (c) update-roadmap-backlog Create mode for Roadmap targets the new Shape A field set (time_horizon, linked_tasks, linked_backlog); Create for Backlog supports the optional rank field. Update mode supports rank edits and time_horizon edits. Promote mode (backlog → task-list) gains an optional capability_theme copy-through from the source Backlog item’s parent theme (resolved via Roadmap linked_backlog[] lookup) onto the destination Task. Delete mode unchanged. (d) Both skills’ failure-modes-to-avoid sections gain the new ratifications: triage-finding warns against routing a tactical item to Branch B (it belongs on Backlog); update-roadmap-backlog warns against creating a 13th theme without first checking whether two existing themes should merge per inv 8 soft cap. (e) Ordering: skill rewrites land in PR-A per inv 12 (foundation PR), BEFORE PR-B bulk migration uses the rewritten Create-mode contract to write the 54 net-new Backlog entries. The Subtask is sized for 1 sub-agent dispatch (~2-3h estimated) and is independently testable: the rewritten skills load, their decision-tree examples cover the new branch semantics, and a smoke test invokes Create against both ledgers under the new field sets without schema errors.

Cluster E — Cross-cutting hygiene (invariants 14-15)

Section titled “Cluster E — Cross-cutting hygiene (invariants 14-15)”
  1. UK English + Warm Meridian discipline applies throughout. All authored prose in PRODUCT.md, TECH.md, PLAN.md, and the rewritten skills uses UK English (colour, organisation, behaviour, DD/MM/YYYY dates). All UI changes in the per-task-mirror 20.14 extension use semantic tokens per docs/design/warm-meridian-implementation-spec.md; no raw Tailwind colour classes; the drag-handle affordance + the integer-input affordance meet WCAG 2.1 AA (keyboard-operable, never colour alone for meaning). The new “(unset)” rank option uses the same visual treatment as the “(unset)” Roadmap status / priority options in per-task-mirror inv 30 — consistency carries across surfaces.

  2. All migration writes pass through validated schemas; no silent failures. Per the project-wide silent-failure-prevention discipline (docs/specs/silent-failure-prevention-spec.md): the migration script and the rewritten curator skills use sb() / tryQuery() from @/lib/supabase/safe for any Supabase interaction (though most migration writes are filesystem-only JSON edits). Composite responses use warningsEnvelope(). After every migration write, the JSON is re-read and re-validated through the canonical Zod schema; a validation failure rolls back the write rather than committing partial state. The migration is idempotent: running PR-B’s migration script twice produces the same final JSON state as running it once (the script detects already-migrated items by id and skips them rather than duplicating). Idempotency is verified by a TECH-side test.


Open questions (P-OQ-1 through P-OQ-4) — for Liam ratification at S63

Section titled “Open questions (P-OQ-1 through P-OQ-4) — for Liam ratification at S63”

These are NEW open questions raised during PRODUCT authoring (post-S62 W3 ratifications). Each carries a default proposal and an alternative. None block 30.3 TECH dispatch — defaults apply unless Liam ratifies otherwise.

Question. Inv 7 specifies that each capability theme carries status (“theme-level only; granular status lives on Tasks”) but does not fix the enum. Which values does it accept?

Default proposal. Three values: pending (theme scoped, no linked work has started), in_progress (at least one linked Task is in_progress), done (all linked Tasks done; no remaining linked Backlog items). Derivable from linked_tasks[] + linked_backlog[] states, but stored explicitly so the curator skill can override (e.g. mark a theme done when the residual Backlog items get re-scoped to a different theme).

Alternative. Match task-list.json’s richer TaskListStatus enum (8 values including blocked, deferred, cancelled) so themes can carry the same operational state as Tasks. Rejected by default because theme-level state is intentionally coarse (per RESEARCH §4.5 Shape A “slowly-changing strategic surface”); finer-grained operational state belongs on the linked Tasks.

P-OQ-2. Serialised shape of the Roadmap document under Shape A

Section titled “P-OQ-2. Serialised shape of the Roadmap document under Shape A”

Question. Today RoadmapSchema has sections: RoadmapSectionSchema[] with items nested inside. Under Shape A the section structure collapses. Does the document become (a) a flat themes: RoadmapThemeSchema[] array with sections dropped, OR (b) a single root section containing all themes as items (preserving the sections/items nesting for backwards-compat with the existing renderer)?

Default proposal. Option (a) — flat themes[] array; sections field dropped from RoadmapSchema. The MD renderer adapts to emit one heading-per-theme without section grouping. Cleaner schema; cleaner mental model; matches the RESEARCH §4.5 Shape A description (“flat list of themes”).

Alternative. Option (b) — single root section as a transitional shape that keeps sections intact, with sections.length === 1 and all themes as items inside. Lower MD-renderer change cost. Rejected by default because the residual sections field becomes confusing dead structure once the cardinality is fixed at 1.

Question. Inv 3 says the schema does NOT enforce that ranks within a priority tier are unique. The curator skill (per inv 13 rewrite) maintains discipline. What does the curator do when adding an item with a rank value that collides with an existing item in the same priority tier?

Default proposal. The curator skill auto-shifts the existing items: inserting at rank: N in tier T pushes every item in tier T with rank ≥ N to rank: rank + 1. This is the simplest “insert into a sorted list” semantic. Recorded in the rewritten update-roadmap-backlog skill’s Update-mode section (per inv 13 c).

Alternative. Reject the write with a “rank collision” error and require the curator to pass an explicit shift policy. Higher ceremony; more predictable for batch operations.

Section titled “P-OQ-4. capability_theme back-link consistency on Promote”

Question. Inv 13 (d) says Promote-mode gains an optional capability_theme copy-through from the source Backlog item’s parent theme onto the destination Task. The parent theme is resolved via Roadmap linked_backlog[] lookup — but a Backlog item may be linked from multiple themes. What does the curator do?

Default proposal. If exactly one Roadmap theme lists the source Backlog item in its linked_backlog[], set capability_theme on the destination Task to that theme’s id. If zero themes link the item, leave capability_theme unset (null / absent). If two or more themes link the item, leave capability_theme unset AND emit a warning so the curator (or Liam) sets it explicitly. Inv 13 (d) phrasing “optional copy-through” already permits this; default makes the ambiguity-handling concrete.

Alternative. Always set capability_theme to the first matching theme alphabetically. Rejected because it hides multi-theme membership signal.


Validation pointers (for TECH.md to plan against)

Section titled “Validation pointers (for TECH.md to plan against)”

The Behavior invariants above are the source of truth. TECH.md (Subtask 30.3) authors a one-to-one mapping of proposed changes against each invariant. Validation hooks the TECH spec should plan against:

  • Schema-roundtrip tests against RoadmapSchema post-Shape-A extension (covers inv 6, 7, 9 forward link shape).
  • Schema-roundtrip test against BacklogSchema post-rank-addition (covers inv 3, 4).
  • Backlog sort-order test that asserts inv 4 ordering against a fixture set.
  • Migration-idempotency test per inv 15 — run the PR-B migration script twice, assert equal final state.
  • Per-task-mirror E2E test for the rank-edit affordance (inv 10) — render the Backlog index page, click the integer-input affordance, save, re-render, assert the sort order updated.
  • Skill smoke test per inv 13 (e) — invoke Create against both ledgers under the new field sets, assert no schema error and that Phase-B provenance fields round-trip cleanly.
  • PR-by-PR acceptance-gate tests per inv 12 — each PR’s acceptance gate is independently verifiable.

Test philosophy: behaviour-verifying, not implementation-coupled per docs/reference/test-philosophy.md. The integration tests above assert observable schema, file, and UI behaviour; they do not lock in implementation choices.


End of PRODUCT.md. Awaits Liam ratification of P-OQ-1 through P-OQ-4. On ratification, Subtask 30.2 promotes to done (Checker action) and 30.3 TECH dispatch unblocks.