Skip to content

RESEARCH — Canonical-pipeline → task-list migration approach

RESEARCH — Canonical-pipeline → task-list migration approach

Section titled “RESEARCH — Canonical-pipeline → task-list migration approach”

Date: 21/05/2026 (Session kh-prod-readiness-S62) Subtask: ID-30.1 RESEARCH (feeds Task ID-30 opening post-return) Author: research agent dispatched from production-readiness orchestrator Mode: Read-only investigation + single research doc Status: [DRAFT — pending Liam ratification]

Purpose: decide HOW the existing docs/specs/id-31-canonical-pipeline-implementation-plan/PLAN.md (T1-T14, ~700L, last verified S244+S246+S247+S248+S249+S250+S251+S252) gets represented in docs/reference/task-list.json given (a) most of T1-T6 has already shipped retrospectively without a Task entry; (b) the user wants PLAN.md to remain the rendered substrate while task-list.json hosts the Task entries that reference it; (c) the “tag” / umbrella concept needs codifying for cross-Task initiatives like canonical-pipeline itself.

Why this exists: ratified by docs/plans/phase-0-investigation/s48-feedback.md general comments (line 200): “Items on KH backlog and roadmap are essentially ‘tasks’, which when moved to the task-list, will be decomposed to subtasks.” The user’s session-start framing (cited in dispatch brief): “We have a project plan that relates to architectural work across the platform and within that the canonical pipeline is one plan. And because that pipeline work has lots of different facets, it also has items within it which have their own dedicated specs, plans and research. And it’s therefore at that level that I would expect the items to be a task on the task list broken into subtasks where the default is that we use either a spec or a plan to structure the subtasks unless an item doesn’t have a spec because of the type of work that it is.” And: “Considerable actions have already taken place from T1 to T6, I think, and any pre-phase work. So we should look at how we retrospectively update the task list for the relevant tasks for this item.”


§1 Linear’s Project / Issue / Sub-issue / Label / Milestone / Initiative model

Section titled “§1 Linear’s Project / Issue / Sub-issue / Label / Milestone / Initiative model”

Source: Linear conceptual model, Linear Initiatives docs, Linear Labels docs, Linear Project Labels docs.

Linear’s data model has six first-class entities with mixed cardinality:

EntityWhat it representsCardinality with neighbours
WorkspaceTenant / org root1-to-many → Teams
TeamFunctional group with its own backlog1-to-many → Issues
IssueAtomic unit of work, owned by ONE team, unique ID like ENG-1231-to-many → Sub-issues; many-to-many ← Projects, Cycles, Labels
Sub-issueHierarchical child within a single Issue (decomposition)1-to-many → its own Sub-issues (nested)
ProjectTime-bound deliverable grouping Issues across teamsMany-to-many ↔ Issues; many-to-many ← Initiatives, Project Labels; 1-to-many → Milestones
InitiativeWorkspace-level umbrella tying multiple Projects to a strategic goalMany-to-many ↔ Projects
CycleRecurring time-boxed sprint container (automated)Many-to-many ↔ Issues
MilestoneWithin-project completion stage1-to-many ← Issues (an Issue can be in 0 or 1 Milestone per Project)
LabelWorkspace- or team-scoped tag on an Issue (free or grouped)Many-to-many ↔ Issues
Project LabelWorkspace-scoped tag on a ProjectMany-to-many ↔ Projects

Empirical key relationships from the conceptual-model doc:

Workspace 1 ──── * Team (hierarchy)
Team 1 ──── * Issue (hierarchy — issue ownership)
Issue 1 ──── * Sub-issue (hierarchy — task decomposition)
Project * ──── * Issue (grouping — an Issue belongs to 0 or 1 Project)
Cycle * ──── * Issue (grouping — sprint membership)
Project 1 ──── * Milestone (hierarchy — within-Project stages)
Milestone 1 ──── * Issue (Issue can be in 0 or 1 Milestone per Project)
Initiative * ──── * Project (grouping — many-to-many)
Label * ──── * Issue (grouping — many-to-many)
ProjLabel * ──── * Project (grouping — many-to-many)

Linear distinguishes two umbrella patterns:

  1. Hierarchical umbrellas (Initiative) — manually curated lists of Projects. Workspace-level. Designed for strategic goals like “Canonical pipeline implementation” or “Sales proposals expansion”. Each Initiative carries its own document body.

  2. Cross-cutting tag umbrellas (Project Label and Label) — flexible, multi-applicable tags. Used for theming work that crosses Initiative boundaries — e.g. “data-migration”, “RLS-touching”, “requires-staging-apply”.

Critical structural facts:

  • An Issue belongs to exactly one Project (one-to-many from Project to Issue). It cannot belong to multiple Projects simultaneously. The way to model an Issue that conceptually spans multiple umbrellas is via Labels — many-to-many.
  • A Project belongs to zero or more Initiatives (many-to-many). This is how Linear handles “this Project is part of canonical-pipeline AND part of sales-proposals” — you list the Project under both Initiatives’ curated lists.
  • Labels apply at two levels: Issue Labels (many-to-many with Issues) and Project Labels (many-to-many with Projects). Issue Labels can be grouped with the syntax Type/Bug, creating one level of nesting. Within a label group, labels are mutually exclusive on a single Issue (one bug-type per issue, one priority per issue) — but across groups, multi-labelling is unconstrained.

§1.3 The “tag” system the user referenced

Section titled “§1.3 The “tag” system the user referenced”

The user said “the tag system” and the closest Linear analogue is Project Labels combined with Initiatives:

  • For strategic umbrellas (“canonical-pipeline”, “sales-proposals”, “production-readiness”) — Linear uses Initiatives. These are curated lists, document-backed, surfacing in the workspace navigation as top-level entities.
  • For cross-cutting work attributes (“RLS-touching”, “requires-migration”, “blocks-T7”) — Linear uses Labels (Issue-level) or Project Labels (Project-level). These are flat tags, can be grouped, multi-applicable.

The Morgen guide (Linear setup best practices) and the Aleni Wright article (backlog-management blog) both confirm the conventional split: Initiative for “what business outcome are we chasing”; Label for “what category of work is this”.

§1.4 What Linear does that the KH task-list.json does NOT

Section titled “§1.4 What Linear does that the KH task-list.json does NOT”

KH’s task-list.json (production-readiness branch, 16 tasks) is currently:

  • Flat array of Tasks with two-level nesting (Task → Subtasks).
  • No umbrella/initiative entity — no umbrella, no initiative_id, no project_id.
  • No tag/label field — no tags, no labels.
  • Subtask dependencies are sibling-only (matches Taskmaster — see §2).

So “canonical-pipeline” as a concept has nowhere to live in the current schema. The Tasks T1-T14 from PLAN.md, when migrated to task-list.json, will look like a flat list with no signal that they all belong to the canonical-pipeline initiative.


§2 GitHub Projects + Aha + Taskmaster comparison

Section titled “§2 GitHub Projects + Aha + Taskmaster comparison”

Source: GitHub Issues sub-issues docs, GitHub Projects hierarchy view 2026, GitHub Issues evolution discussion, Aha! data model, Aha! initiatives vs epics, docs/reference/taskmaster-schema-reference.md.

GitHub Projects (v2, GA January 2025) supports a parent-child Issue hierarchy:

  • Issue → Sub-issue — up to 8 levels of nesting, replacing the deprecated tasklist blocks (retired April 2025). This is strictly hierarchical (parent-child), not many-to-many.
  • Labels — many-to-many between Issues and Labels. Workspace-scoped or repo-scoped.
  • Milestones — many-to-one (an Issue belongs to 0 or 1 Milestone).
  • Projects — many-to-many (an Issue can be in 0+ Projects).

GitHub does NOT have a first-class “Initiative” entity. The closest analogue is Projects themselves (which can be cross-repo and act as umbrellas) or Labels (for cross-cutting themes).

The Hierarchy View (Jan 2026 changelog) lets Project tables render the full Issue → Sub-issue tree inline — strictly hierarchical, not many-to-many umbrella display.

Aha!‘s data model (Aha data model blog) has the richest hierarchy of the three tools:

  • Strategy (Goals/Initiatives) at workspace level — cross-Release, cross-Feature.
  • Releases time-bound deliverables.
  • Epics parents of Features (additional level between Initiatives and Features).
  • Features stories / requirements.
  • Ideas unrefined backlog.

Aha allows linking workspace-level Initiatives downward to Releases / Features / Ideas to show strategy → execution traceability. Aha supports both:

  • Hierarchical Initiative → Epic → Feature (umbrella as container).
  • Cross-linking Goals ↔ Initiatives ↔ Features (umbrella as cross-cut).

Aha is the closest commercial parallel to what KH needs: a two-axis model where Initiatives are containers AND can cross-reference work items by ID. Aha’s “Initiatives can cross multiple releases or sprints” framing aligns precisely with the user’s session-start framing of canonical-pipeline as one of several plans within a broader project plan.

§2.3 Taskmaster (canonical reference in this repo)

Section titled “§2.3 Taskmaster (canonical reference in this repo)”

Per the empirical reference in docs/reference/taskmaster-schema-reference.md (§5 + §6):

  • master.tasks[] is a flat array of Tasks. No initiative_id, no parent_task, no first-class umbrella.
  • Tasks → Subtasks — strict 2-level nesting (depth 1; no sub-subtasks observed across 151 subtasks in the empirical sample).
  • master.metadata.tags is a top-level array of strings (currently ["architectural-refactor"] in the sample). This is the tag attached to the tag-set itself, not per-Task — a single global label for the whole master PRD.
  • Multi-tag support — Taskmaster supports MULTIPLE named tag-sets at the top level (the outer key under master is the tag name). But each Task lives in exactly ONE tag-set; it cannot be cross-tagged.
  • No first-class umbrella / initiative / parent-Task / cross-Task-dep concept. Per the empirical analysis §5.2: “The hand-decomp uses dependency expressivity that TM cannot represent.”

So Taskmaster has no native way to express “Task T1 belongs to canonical-pipeline AND production-readiness umbrellas” — you’d either:

  • (a) Pick one umbrella and put T1 there (loss of multi-membership), or
  • (b) Use master.metadata.tags to label the WHOLE tag-set (so all Tasks in the file share the same umbrella label), or
  • (c) Use multiple tag-sets (one per umbrella) and accept Tasks live in exactly one (no multi-membership), or
  • (d) Encode umbrella membership in prose inside description / details and live without queryability.

§2.4 JSON shape options for grouping Tasks under an umbrella

Section titled “§2.4 JSON shape options for grouping Tasks under an umbrella”

Given KH’s current task-list.json uses a custom (non-pure-TM) shape with these top-level keys:

document_name | document_purpose | last_updated | related_documents | tasks: [Task]

…and Task fields like id, title, description, status, priority, dependencies, subtasks, updatedAt, effort_estimate, owner, priority_note, status_note, cross_doc_links, session_refs, commit_refs

Four umbrella-encoding options are viable in this shape (analysed in §7 with a recommendation):

  1. umbrella field (single string, many-to-one) — each Task has one umbrella; cross-cutting requires duplication.
  2. umbrellas field (array of strings, many-to-many) — Task can belong to multiple umbrellas.
  3. Separate umbrellas document with curated Task ID lists — most Linear-like, normalised.
  4. No umbrella field; rely on title/description prefix or naming convention — implicit only.

§3 T1-T14 inventory + Task mapping proposal

Section titled “§3 T1-T14 inventory + Task mapping proposal”

Source: docs/specs/id-31-canonical-pipeline-implementation-plan/PLAN.md §2 (top-level task list) + §4 (per-task detail) + §8 (implementation ordering).

For each Tn from PLAN.md §2, I extracted: title, family, status as of S252 close, sub-spec docs referenced, backlog/task-list refs, retrospective evidence.

TnTitleFamilyEffort (units)Status (S252)Sub-specs referencedExisting task-list refRetrospective evidence
T1Gating spec drafting — Q-EX2 + cocoindex ledger + Q1.3-Q1.N invariantsSpec drafting2.5DONE-S242docs/specs/id-36-cocoindex-extraction-contract/{PRODUCT,TECH}.md (drafted S242); docs/specs/id-36-cocoindex-ledger-api/TECH.md (DEFERRED-v1.1 per Item 11); docs/specs/id-56-content-model-invariants/PRODUCT.md (drafted S242)NoneCommits 2f142936 + ddebada1 + f324fe93 + a89440f1 + c8fd217b (S242); PLAN.md §5 spec table notes status
T2Q-OQR1-16 combined PR migration drafting (10 canonical + 5 reserved seats)Database migration3DONE-S246/S247 (staging+prod) + WP2a DONE-S245T2 has 11 sub-task migrations; ratifies docs/specs/intelligence-workspaces/TECH.md; depends on docs/specs/reserved-workspace-seats/TECH.mdNoneWP2a commits f6a13f4e + c8cf4e8f; T2 SQL commit 38242fef (S246); prod-apply commit 2f98c8cf (S247); types regen byte-identical
T3RLS-pattern combined migration apply + observability validationDatabase migration1.5DONE-S239 (verified S243)docs/specs/rls-pattern/{PRODUCT,TECH}.md (ratified S239)NoneMigration 20260514150238_enable_rls_auto_event_trigger_and_grants_pattern.sql applied at/before S239; verified S243 per docs/specs/phase-1-kickoff-scoping-s243.md §3
T4Procurement umbrella rename (44-file sweep + lib/bid → lib/procurement + state machine)Code refactor2SHIPPED-S248docs/specs/procurement-workspaces/{PRODUCT,TECH}.md (drafted S242 commits 2f142936 + ddebada1); ID-23 follow-up shipped S249None10 commits dc1d7850..776d3a73 S248 (158-path A + 260-symbol B + 57-file C project_id→workspace_id + 48-file D test alignment + 110-file E prettier); ID-23 closeout commit 95b660ef S249
T5digestschange_reports rename (code)Code refactor1SHIPPED-S248 + closed S251 W1BCode-side only (no new spec)None (PLAN.md §4.5 “SHIPPED” header)S248 commit 44ff65c7 (initial pass); S251 W1B (commits af216dc4 + 31fbff30 + f74eb3cc + d9d42c86 + e15febb3 + 61ea6dd9 + 2cb8064a + 45317dc6) — URL/column/enum residual + DB column rename + notifications enum + ThemeCluster elimination; full scope discovery doc at docs/research/s251-w1b-digest-to-change-reports-scope-discovery.md
T6Q&A two-tier model: q_a_pairs + q_a_extractions + q_a_pair_history migration + RPCsDatabase + RPC2.5DONE-S249/S250 (staging+prod) + WP1b PUBLIC-EXECUTE fix S2500.9-spike-S16-qa-schema-design.md §6 + 05-qa-flow.md §2-§3 (no new spec; design ratified)NoneMigrations 20260520225456_t6_q_a_pairs_full_schema.sql (commit 2f3428c7) + 20260520231524_t6_q_a_search_rpcs.sql (commit 6614d8c3) + 20260521095209_t6_followup_revoke_public_execute_anon_inherit_fix.sql (commit b3a4f792); integration test 275bc9e5
T7Phew Q&A first-ingest via cocoindex (markdown source files → q_a_extractions → promote to q_a_pairs)Pipeline re-ingest2PENDING (gated on T8)None new (consumes T1.1+T1.2 cocoindex-extraction-contract)NoneT7 has not started; depends on T8
T8Cocoindex flow scaffolding — source-binding + extraction + Cloud Run sidecar deployPipeline implementation3IN-PROGRESS (Task ID-28 on content-items-investigation: 4 subtasks, 28.1 RESEARCH done S252)Spec chain at task-list.json ID-28 (RESEARCH/PRODUCT/TECH/PLAN)ID-28 on origin/content-items-investigation (NOT on production-readiness)Commits 40e5cceb (open Task), 58162181 (RESEARCH), d20aa7cc (Liam ratification) — S252
T9Per-UC write-back (UC1/UC4/UC6 user-direct + UC3 + UC5 + UC8) + Diff-UI sidecar re-pointFeature implementation3PENDINGdocs/specs/id-59-concurrent-edit-intent-arbitration/TECH.md (ratified S244 commit 12a20963)NoneNot started
T10question_matches table + retrieval substrate + scoring columnsDatabase + retrieval1.5PENDINGNone new (consumes T6 q_a_pairs)NoneNot started; ID-25/26 backlog items relate (ts_rank tunability, integration test hardening)
T11Citations polymorphic enum + version-on-citeDatabase + integration1PENDINGNone new (N8 resolved S234)NoneNot started
T12Mempalace KG integration — Shape A temporal + Shape B provenanceKG integration2PENDINGNone new (direct pattern ratified S240); Spike #4 PENDINGNoneNot started; ID-24 backlog (q_a_pair_history snapshot completeness) is sibling-dependency
T13Pre-launch operational pre-decisions + observability gates (Theme F follow-through + prompt-cache spike + tracked-changes DOCX regression test)Operational1.5PENDINGdocs/specs/mcp-tooling-audit/{PRODUCT,TECH}.md (NEW required per S241 WP2)NoneNot started
T14Cocoindex absorption cleanup — delete retired pipeline code + dependencies post-T8 stableCode retirement1PENDING (gated on T8 stable + T7 complete)None new (07-collapse-list.md §5 authoritative)NoneNot started

Current ID space across branches:

  • origin/main uses IDs 6, 7, 8, 9, 10, 16, 15, 18, 19, 20, 22, 23 (12 Tasks).
  • origin/production-readiness adds 24, 25, 26, 27 (16 Tasks total).
  • origin/content-items-investigation adds 28, 29 (14 Tasks total).
  • Highest occupied ID across all branches: 29.

To avoid collisions on next merge cycle:

  • ID-28 already in use for T8 (Cocoindex flow scaffolding) — on content-items-investigation only.
  • ID-29 already in use for the TanStack workspace-types migration — on content-items-investigation only.
  • Safe ID range for new Task entries: ID-30 onwards.

Proposed mapping (preserves the T8 = ID-28 already-in-use anchor; sequential numbering elsewhere):

TnProposed Task IDRationale
T1ID-30Retrospective DONE (no Task yet); T1 = first canonical-pipeline Task in numbering order
T2ID-31Retrospective DONE
T3ID-32Retrospective DONE
T4ID-33Retrospective DONE
T5ID-34Retrospective DONE
T6ID-35Retrospective DONE
T7ID-36Pending; gated on T8
T8ID-28 (already open)Keep the in-flight ID-28 — RESEARCH done S252; PRODUCT/TECH/PLAN pending
T9ID-37Pending
T10ID-38Pending
T11ID-39Pending
T12ID-40Pending
T13ID-41Pending
T14ID-42Pending

Rationale for keeping T8 = ID-28 anchored: the canonical-pipeline initiative is already mid-flight on content-items-investigation. Renumbering ID-28 to ID-37 (or wherever T8 would land sequentially) would break the spec chain references already authored in docs/research/id-28.1-... (research doc from S252 commit 58162181). Anchoring T8 = ID-28 keeps continuity at the cost of non-sequential T-number → ID-number mapping, which is acceptable because the umbrella tag (§7 below) carries the canonical-pipeline grouping anyway.

Per the user’s preferred model (session-start framing): “the default is that we use either a spec or a plan to structure the subtasks unless an item doesn’t have a spec because of the type of work that it is.”

Two subtask-shape patterns emerge:

Pattern A — Forward (full spec chain) shape, for Tasks not yet shipped:

{N.1} RESEARCH — research substrate, OQs, recommendation
{N.2} PRODUCT — PRODUCT.md (skip if pure refactor; mark deferred with reason)
{N.3} TECH — TECH.md
{N.4} PLAN — PLAN.md decomposing TECH into TM-shape Subtasks
{N.5+} — implementation subtasks per PLAN.md (variable count)

This is the shape T8 = ID-28 uses (4 subtasks currently; 28.5+ will be appended after 28.4 PLAN ratifies).

Pattern B — Retrospective shape, for Tasks already shipped:

{N.1+} <implementation subtasks reflecting what already shipped>

…with <info added on ...> journal blocks per the empirical TM convention (cited in §3.5 of docs/reference/taskmaster-schema-reference.md).

Per the user’s clarification at S250 (cited in S251 prompt rule 5): “items physically MOVE from backlog → task-list, then retain a done status on task-list once complete.” This means retrospective Tasks should be opened in done status with retrospective Subtask records capturing what shipped, citing commit SHAs and session references.

§3.4 Subtask shapes per Task (proposed JSON snippet table ready for orchestrator-direct splice)

Section titled “§3.4 Subtask shapes per Task (proposed JSON snippet table ready for orchestrator-direct splice)”

For each Task, the proposed Subtask list is below. Statuses use the empirical TM vocabulary (done, pending, deferred, in_progress).

ID-30 (T1) — RETROSPECTIVE shape, status done:

30.1 — Draft cocoindex-extraction-contract PRODUCT.md (DONE-S242)
30.2 — Draft cocoindex-extraction-contract TECH.md (DONE-S242)
30.3 — Draft cocoindex-ledger-api TECH.md (DEFERRED-v1.1; retained as v1.1 substrate)
30.4 — Draft Q1.3-Q1.N content-model invariants PRODUCT.md (DONE-S242 as content-model-invariants spec)

ID-31 (T2) — RETROSPECTIVE shape, status done:

31.0 — WP2a pre-T2 helper + 23-site code sweep (DONE-S245, commits f6a13f4e + c8cf4e8f)
31.1 — Migration SQL draft: application_types + workspaces FK swap + kb_section retire + procurement rename (DONE-S246, commit 38242fef)
31.2 — Form templates rename DDL (DONE-S246)
31.3 — digests → change_reports DDL (DONE-S246)
31.4 — Provenance enum cascade + entity_aliases.category rename (DONE-S246)
31.5 — source_documents.workspace_id NULLABLE (DONE-S246)
31.6 — q_a_pairs schema sketch (DONE-S246; full schema in T6)
31.7 — 5 reserved satellite seats (DONE-S246 per RWS spec)
31.8 — intelligence_workspaces Shape B promotion (DONE-S246, 3 typed cols)
31.9 — form_type 3-tier split + procurement_vehicles + procurement_vehicle_instances (DONE-S246)
31.10 — Apply migration to staging (DONE-S246)
31.11 — Apply migration to production (DONE-S247, commit 2f98c8cf; sync_bid_status trigger drop pulled forward)

ID-32 (T3) — RETROSPECTIVE shape, status done:

32.1 — RLS-pattern PRODUCT.md + TECH.md ratification (DONE-S239)
32.2 — Apply migration 20260514150238_enable_rls_auto_event_trigger_and_grants_pattern.sql to staging (DONE-S239)
32.3 — Apply to production (DONE-S239)
32.4 — Validation gates per RLS-PATTERN T-1..T-3 (DONE-S239; verified S243 per phase-1-kickoff-scoping-s243.md §3)
32.5 — Negative-case validation (grants helper required) (DONE-S239 or before)
32.6 — Update SCHEMA-QUICK-REFERENCE.md §32 + drop skip-doc-freshness marker (DONE-S239)

ID-33 (T4) — RETROSPECTIVE shape, status done:

33.1 — Pre-rename gitnexus_impact + gitnexus_rename pass (DONE-S248)
33.2 — Path A: 158 file paths renamed (DONE-S248, commit 2105404f)
33.3 — Path B: 260 symbol renames + DB strings + URL paths + MCP tools (DONE-S248, commit 99dfc5fd)
33.4 — Path C: 57-file project_id → workspace_id sweep + dead-code + CI guard (DONE-S248, commit 51b6cc8c)
33.5 — Path D: 48-file test alignment (DONE-S248, commit f9261904)
33.6 — Path E: 110-file prettier sweep (DONE-S248, commit 776d3a73)
33.7 — ID-23 follow-up: bid → procurement closeout in formatters + AI skill (DONE-S249, commit 95b660ef)
33.8 — knip un-export 4 internal procurement types (DONE-S251 WP2, commit 76e548db)

ID-34 (T5) — RETROSPECTIVE shape, status done:

34.1 — Initial pass: lib/digest → lib/change-reports + lib/ai/digest.ts → lib/ai/change-reports.ts + queryKeys + hook internals (DONE-S248, commit 44ff65c7)
34.2 — Phase A scope-discovery research doc (DONE-S251 W1B, commit c84631f8)
34.3 — Phases B+C: symbol renames + URL string-literal sweep (DONE-S251 W1B, commits af216dc4 + 03fcfa8f)
34.4 — Phase D: DB column digest_type → frequency + notifications enum (DONE-S251 W1B, commit 31fbff30)
34.5 — Phase E: migration apply staging + prod + types regen (DONE-S251 W1B, commits f74eb3cc + d9d42c86)
34.6 — Phase F: CLAUDE.md + SCHEMA-QUICK-REFERENCE.md + reference/product-functionality/ast-dataflow cascade (DONE-S251 W1B, commits e15febb3 + 61ea6dd9)
34.7 — Phase G: verification fixes + stats regen + ThemeCluster elimination + plugin marketplace /kb:change-report (DONE-S251 W1B, commit 45317dc6)

ID-35 (T6) — RETROSPECTIVE shape, status done:

35.1 — WP1 migration: q_a_pairs full schema + q_a_extractions + q_a_pair_history (DONE-S249, commit 2f3428c7)
35.2 — q_a_pair_history trigger function (DONE-S249, commit 2f3428c7)
35.3 — GIN indexes on scope_tag fields (DONE-S249, commit 2f3428c7)
35.4 — WP2: q_a_search + q_a_get_verbatim RPCs (DONE-S249, commit 6614d8c3)
35.5 — Apply staging + prod + types regen (staging DONE-S249; prod channel-undetermined likely MCP S249; CLI verified S250)
35.6 — WP3 integration test: two-step-retrieval (DONE-S249, commit 275bc9e5)
35.7 — WP1b PUBLIC-EXECUTE anon-inherit fix (DONE-S250, commit b3a4f792)
35.8 — Docs cascade: SCHEMA-QUICK-REF §34 + PLAN.md §4.6 close + ontology 32-q-a-pair (DONE-S249, commit fa0f4710)

ID-28 (T8) — IN-PROGRESS, status in_progress (already open on content-items-investigation):

28.1 — RESEARCH (done S252)
28.2 — PRODUCT (pending)
28.3 — TECH (pending)
28.4 — PLAN (pending)
28.5+ — implementation subtasks per PLAN (deferred until 28.4 ratifies)

ID-36 (T7), ID-37 (T9), ID-38 (T10), ID-39 (T11), ID-40 (T12), ID-41 (T13), ID-42 (T14) — FORWARD shape, status pending: Each follows {N.1 RESEARCH → N.2 PRODUCT → N.3 TECH → N.4 PLAN → N.5+ impl} per Pattern A. Forward Tasks are opened only when ready to commence — to avoid filling the ledger with empty pending entries before they’re actionable.

Per the empirical Taskmaster reference (§5.2 of docs/reference/taskmaster-schema-reference.md): “25 is a soft ceiling — five of seven Tasks hit it exactly and none exceed it. … When a Task needs more than 25, the workaround appears to be splitting into multiple Tasks.”

The retrospective Tasks above range from 4 (T1) to 12 (T2) subtasks — all well under the 25 ceiling. Forward Tasks should follow the same constraint; if a PLAN.md decomposition would exceed 25 impl Subtasks, split into separate Tasks (e.g. T9 might split UC1/UC4/UC6 user-direct from UC3 sweep from UC8 cross-record).


§4 Retrospective Task population for T1-T6 + pre-phase work

Section titled “§4 Retrospective Task population for T1-T6 + pre-phase work”

For each shipped Task, here is the proposed retrospective record. Sources for evidence: PLAN.md DONE-S2NN annotations, S243-S251 main-track continuation prompts, git log on origin/content-items-investigation, and the spec docs themselves.

S238-S241 — Phase 0.9 investigation + architecture sub-doc cascade + drift audit + implementation-readiness audit:

This is the largest single retrospective chunk, spanning roughly S180-S241 (the entire 0.9 phase). It includes:

  • Architecture sub-docs 02-data-flow.md, 04-workspace-types.md, 05-qa-flow.md, 06-mcp-tooling.md, 08-new-features.md (S239-S240).
  • Canonical-pipeline PRODUCT/TECH at docs/specs/id-31-0.9-canonical-pipeline/ (S238 reconciliation, S237 NEW spec authoring).
  • Reserved-workspace-seats spec pair (S240).
  • RLS-pattern spec pair (S239 — this is T3’s spec; could be folded into T3 retro or kept separate).
  • Drift audit + implementation-readiness audit (S240) + STILL-OPEN consolidation (S239).

Recommendation: treat as out-of-task-list-scope (i.e. do NOT create retrospective Tasks for pre-T1 architecture work). Rationale: these were ratification work-packages, not implementable Tasks per the user’s framing. They preceded the task-list / Tn structure entirely; encoding them retrospectively would mean opening ~15 retrospective Tasks for sessions S180-S237, which adds ledger noise without operational value. Instead, add a single umbrella document (proposed §7 Option C) for “canonical-pipeline” that references these as prior-art docs.

If Liam wants pre-phase encoded: open one umbrella Task ID-30 titled “T0 — Phase 0.9 investigation + architecture sub-docs + drift audit (substrate)” with Subtasks 30.1..30.5 corresponding to the major doc landings. Status done; journal blocks cite session refs S180-S241.

Retrospective Task ID-30. Status done.

Description: “Drafted three independent gating specs to gate Phase 1 implementation. (i) docs/specs/id-36-cocoindex-extraction-contract/{PRODUCT,TECH}.md for Q-EX2 Pydantic discriminated union with ExtractByLlm. (ii) docs/specs/id-36-cocoindex-ledger-api/TECH.md for TS-facing API over cocoindex per-flow-run ledger (subsequently DEFERRED-v1.1 per S243 Item 11). (iii) docs/specs/id-56-content-model-invariants/PRODUCT.md for Q1.3-Q1.N content-model invariants. Plus a NEW spec for docs/specs/procurement-workspaces/{PRODUCT,TECH}.md (T4.7 gating spec). Drafting work used /write-product-spec + /write-tech-spec skills (feature-spec pattern per S241 critical-rule 5).”

Journal block (proposed):

<info added on 2026-05-22T10:00:00.000Z>
RETROSPECTIVE OPENING — Task opened in `done` status after Subtask ID-30.1 RESEARCH
identified gap. Original work happened S242 main-track per
`docs/continuation-prompts/continuation-prompt-kh-s242-main-t1-specs-and-phase-0-close.md`.
Commits (S242, content-items-investigation branch):
- 2f142936 — docs(spec): procurement-workspaces PRODUCT + TECH — S242 W3 fix-pass per verifier findings
- ddebada1 — docs(spec): procurement-workspaces PRODUCT + TECH (absorbs EP8 v5) — S242 T4.7
- f324fe93 — docs(spec): content-model-invariants PRODUCT — S242 W3 fix-pass per verifier findings
- a89440f1 — docs(verify): content-model-invariants verifier report — S242 WP1.3
- c8fd217b — docs(verify): procurement-workspaces verifier report — S242 WP1.4
Three of the four specs ratified S242. Cocoindex-ledger-api subsequently DEFERRED-v1.1
per RATIFIED-S243 Item 11 (see PLAN.md §5 row 2). Procurement-workspaces ratified
S242 W3 fix-pass and is consumed by T4 (ID-33) for state-machine + 6-column scope.
PLAN.md §4.1 acceptance criteria all met. T1 closes the Wave 0 spec gate; Wave 1 (T3)
already shipped S239; Wave 2 (T2) dispatched S244+.
</info added on 2026-05-22T10:00:00.000Z>

§4.3 T2 — Q-OQR1-16 combined PR migration (S244-S247)

Section titled “§4.3 T2 — Q-OQR1-16 combined PR migration (S244-S247)”

Retrospective Task ID-31. Status done.

Description: “Single combined-PR migration landing all 10 Q-OQR1-16 items plus 5 reserved satellite seats per docs/specs/reserved-workspace-seats/TECH.md T-1. WP2a (pre-T2 helper + 23-site code sweep) ratified S245. WP2b (T2 SQL drafting + helper swap JSONB → typed-col JOIN) ratified S246. Staging-apply S246; prod-apply S247 (failed first via sync_bid_status trigger dropping NEW.type post-column-drop; fixed inline with trigger drop pulled forward from T4 scope).”

Journal block (proposed):

<info added on 2026-05-22T10:00:00.000Z>
RETROSPECTIVE OPENING — Task opened in `done` status post-implementation.
Commits (S244-S247, content-items-investigation branch):
- WP2a (S245): f6a13f4e + c8cf4e8f — lib/intelligence/workspace-context.ts helper + 23-site sweep
- WP2b (S246): 38242fef — feat(s246-wp2b): T2 migration + intel helper/route swap to satellite
- WP1 prod-apply (S247): 2f98c8cf — fix(s247-wp1): drop sync_bid_status trigger inline in T2 migration
- S247 docs cascade: a689ea49 — docs(s247-freshness): couple migration apply-log header w/ SCHEMA-QUICK-REF bump
Migration filename (post-rename to match staging-server timestamp):
- 20260520... (T2 combined PR; verify exact filename via `ls supabase/migrations/ | grep t2`)
Acceptance audit (S247 prod-apply): env-agnostic invariants 4/3/2/0 + 96/96 crosswalk +
24/24 entity_aliases + 6/6 reserved seats + 8 form_types + 3 procurement_vehicles +
2 vehicle_instances. types regen from prod = byte-identical to staging-generated types.
PLAN.md §4.2 sub-tasks 0-11 all marked DONE. WP2a's deferred `scripts/batch-rescore-articles.ts:157-158`
TODO carried forward to T4 (ID-33).
S250 W1b followup: T6 anon-EXECUTE-via-PUBLIC leak fix surfaced same gotcha that applies
to T2-installed functions; PLAN.md §4.6 carries S250 W1b note.
</info added on 2026-05-22T10:00:00.000Z>

§4.4 T3 — RLS-pattern combined migration apply (S239)

Section titled “§4.4 T3 — RLS-pattern combined migration apply (S239)”

Retrospective Task ID-32. Status done.

Description: “Applied supabase/migrations/20260514150238_enable_rls_auto_event_trigger_and_grants_pattern.sql (RLS-PATTERN auto-enable event trigger + grant_standard_public_table_access(regclass) helper) to staging then production. Validated per RLS-PATTERN P-1..P-5 invariants. Confirmed P-5 observability via RAISE LOG shipping per S240 ratification (option c).”

Journal block (proposed):

<info added on 2026-05-22T10:00:00.000Z>
RETROSPECTIVE OPENING — Task opened in `done` status post-implementation.
Migration applied at/before S239 close on both staging + prod. Verified S243 per
`docs/specs/phase-1-kickoff-scoping-s243.md` §3 — functions live, event trigger enabled,
RLS-PATTERN P-1..P-5 invariants satisfied.
PLAN.md §4.3 acceptance criteria all met:
- pg_event_trigger shows `ensure_rls`.
- Test table CREATE TABLE public.test_rls_autoenable (id int) immediately has
pg_class.relrowsecurity = true.
- grant_standard_public_table_access(regclass) helper callable from staging psql.
- SCHEMA-QUICK-REFERENCE.md §32 updated per T-3 post-apply checklist.
- Negative-case validation: CREATE table WITHOUT calling grants helper; PostgREST returns
42501 permission denied per implementation-readiness audit P4 fix.
P-5 observability v1.1 upgrades (audit_log insertion or fan-out helper) DEFERRED-v1.1
per S240 ratification.
</info added on 2026-05-22T10:00:00.000Z>

§4.5 T4 — Procurement umbrella rename (S248)

Section titled “§4.5 T4 — Procurement umbrella rename (S248)”

Retrospective Task ID-33. Status done.

Description: “Code-side execution of P-42 procurement rename — lib/bid/lib/procurement/; BID_STATESPROCUREMENT_WORKFLOW_STATES; components/bid/components/procurement/; MCP tool name updates; 44-file project_idworkspace_id sweep; app/api/items/[id]/workspaces dead-code cleanup; lib/workspace-types.ts minimal compile fix (full retire-to-application_types-TanStack-Query carried forward to ID-21 → ID-29). 158-path + 260-symbol + 57-file + 48-file + 110-file across stages A-E.”

Journal block (proposed):

<info added on 2026-05-22T10:00:00.000Z>
RETROSPECTIVE OPENING — Task opened in `done` status post-implementation.
Commits (S248, content-items-investigation branch):
- 2105404f — refactor(s248-wp2-t4): rename lib/bid → lib/procurement (paths + imports)
- 99dfc5fd — refactor(s248-wp2-t4): rename Bid* symbols + DB strings + URL paths + MCP tools
- 51b6cc8c — refactor(s248-wp2-t4): project_id → workspace_id sweep + dead-code + CI guard
- f9261904 — test(s248-wp2-t4): fix test expectations + UI strings post-rename
- 8ee36b27 — docs(s248-wp2-followups): add ID-21/22/23 to backlog + bump freshness headers
- 776d3a73 — docs(s248): update SoTP + product-functionality + stats for T4/T5 close
Follow-ups (NOT in T4 scope; tracked as separate items):
- ID-23 closeout (S249, commit 95b660ef) — bid → procurement rename in formatters + AI skill
- ID-22 broken-body fix (S250, commit d2896cb7) — get_bid_question_stats_batch return-field
rename + body rewrite (RPC fully BROKEN on prod since T2 prod-apply; callers silently
failing via per-bid fallback). DROP + CREATE pattern used (CREATE OR REPLACE cannot
change return shape). 4 caller surfaces updated. Backlog ID-22 removed.
- ID-29 (TanStack workspace-types) — lib/workspace-types.ts retire to application_types
TanStack Query; reframed S249 to Path (c) hybrid metadata; ratified S251
PLAN.md §4.4 acceptance criteria all met.
</info added on 2026-05-22T10:00:00.000Z>

§4.6 T5 — digestschange_reports code rename (S248 + S251 W1B)

Section titled “§4.6 T5 — digests → change_reports code rename (S248 + S251 W1B)”

Retrospective Task ID-34. Status done.

Description: “Code-side execution of P-41 — lib/digest/lib/change-reports/; lib/ai/digest.tslib/ai/change-reports.ts; queryKeys + hook internals + cron entry rename. Initial pass S248 ratified incomplete; S251 W1B (7 phases A-G) closed URL/column/enum residual — URL paths, page paths, type file, component dir, hook file, ~14 test files, ~40 symbol renames, 49 URL literals, DB column digest_type → frequency, notifications enum digest_ready → change_report_ready, ThemeCluster + theme_clusters elimination, plugin marketplace /kb:digest → /kb:change-report. CLAUDE.md gotcha + CI guard subsequently DELETED per Liam ratification (single-dev repo).”

Journal block (proposed):

<info added on 2026-05-22T10:00:00.000Z>
RETROSPECTIVE OPENING — Task opened in `done` status post-implementation.
Initial pass (S248 commit 44ff65c7) was incomplete per S251 scope-discovery research at
`docs/research/s251-w1b-digest-to-change-reports-scope-discovery.md`.
S251 W1B closed full scope across 8 commits:
- c84631f8 — docs(s251-w1b): persist digest→change-reports scope discovery report
- af216dc4 — chore(s251-w1b-a): phases B+C — symbol renames + URL string-literal sweep (partial)
- 03fcfa8f — chore(s251-w1b-a-fix): complete Phase B/C residual sweep + ast-dataflow doc-string updates
- 31fbff30 — chore(s251-w1b-d): phase D — digest_type→frequency + digest_ready→change_report_ready + theme_clusters elimination
- f74eb3cc — chore(s251-w1b-e): phase E — migration file authored (NOT applied; orchestrator applies CLI staging then prod)
- d9d42c86 — chore(s251-w1b-e): regen database.types.ts post-migration apply (staging + prod green)
- e15febb3 — docs(s251-w1b-f): Phase F batch 1 — CLAUDE.md + SCHEMA-QUICK-REFERENCE.md cascade
- 61ea6dd9 — docs(s251-w1b-f): Phase F batch 2 — cascade digest→change-reports across reference + product-functionality + ast-dataflow docs
- 2cb8064a — docs(s251-w1b-f+g): final residual sweep — ontology, PLAN.md T5 closure, ast-dataflow CLI, misc
- 45317dc6 — chore(s251-w1b-g): Phase G verification fixes + stats regen
CLAUDE.md "Change Reports not Digest" gotcha + `__tests__/validation/no-digest-import-regression.test.ts`
CI guard DELETED per Liam ratification (single-dev repo).
PLAN.md §4.5 has `SHIPPED:` header in place documenting both passes.
</info added on 2026-05-22T10:00:00.000Z>

§4.7 T6 — Q&A two-tier model migration + RPCs (S249-S250)

Section titled “§4.7 T6 — Q&A two-tier model migration + RPCs (S249-S250)”

Retrospective Task ID-35. Status done.

Description: “Created q_a_pairs corpus-level shape (P-20) + q_a_extractions derived cache + q_a_pair_history trigger-driven version table. RPC signatures for two-step q_a_search (list/preview) + q_a_get_verbatim (get/verbatim) per S16 §6.1. WP1 schema S249; WP2 RPCs S249; WP3 integration test S249; WP4 docs cascade S249. Prod-apply channel-undetermined (likely MCP apply_migration S249; CLI-verified S250). WP1b PUBLIC-EXECUTE anon-inherit fix landed S250.”

Journal block (proposed):

<info added on 2026-05-22T10:00:00.000Z>
RETROSPECTIVE OPENING — Task opened in `done` status post-implementation.
Commits (S249-S250, content-items-investigation branch):
- 2f3428c7 — feat(s249-wp1): q_a_pairs full schema + extractions + history trigger (T6.1-3)
Migration: supabase/migrations/20260520225456_t6_q_a_pairs_full_schema.sql (289 lines)
- f7ce9754 — chore(s249-wp1): regen database.types.ts post T6 WP1 staging apply
- 6614d8c3 — feat(s249-wp2): q_a_search + q_a_get_verbatim RPCs (T6.4)
Migration: supabase/migrations/20260520231524_t6_q_a_search_rpcs.sql
- a20786f5 — chore(s249-wp2): regen database.types.ts post T6 WP2 staging apply
- 275bc9e5 — test(s249-wp3): integration test for q_a_pairs two-step retrieval + history trigger (T6.7)
- fa0f4710 — docs(s249-wp4): T6 docs cascade — SCHEMA-QUICK-REF §34 + PLAN §4.6 close + ontology 32-q-a-pair (T6.5-7)
- 5d309f09 — docs(s249-wp4-fix): address Checker nits — PLAN §4.6 subtask 7 + ontology rollup + frontmatter note
- b3a4f792 — fix(s250-wp1b): T6 anon EXECUTE leak via PUBLIC inheritance + CLAUDE.md gotcha refinement
Followup migration: supabase/migrations/20260521095209_t6_followup_revoke_public_execute_anon_inherit_fix.sql
Prod-apply forensic (S250 W1): T6 migrations already on prod (channel undetermined; likely
MCP `apply_migration` during S249 — `supabase_migrations.schema_migrations` records
byte-identical to staging including comment headers). Schema correct; tables/RPCs/trigger
all present.
S250 W1b PUBLIC-inheritance fix: addresses anon EXECUTE leak via PUBLIC grant on
SECURITY DEFINER functions. Pattern (both REVOKEs required):
REVOKE EXECUTE ON FUNCTION ... FROM PUBLIC;
REVOKE EXECUTE ON FUNCTION ... FROM anon;
GRANT EXECUTE ON FUNCTION ... TO authenticated, service_role;
CLAUDE.md gotcha "Supabase auto-grants anon EXECUTE on every new public.* PL/pgSQL
function" updated S250 with full pattern (both REVOKEs + GRANT).
Sibling backlog rows opened during T6 close:
- ID-24 (q_a_pair_history snapshot completeness — superseded_by + source_workspace_id columns)
- ID-25 (T6 WP3 integration test hardening — 3 checker nits)
- ID-26 (T6 ts_rank normalisation flag — corpus measurement deferred to post-T7/T8)
PLAN.md §4.6 acceptance criteria all met.
</info added on 2026-05-22T10:00:00.000Z>

§4.8 Summary — retrospective Task count

Section titled “§4.8 Summary — retrospective Task count”

6 retrospective Tasks to open in done status: ID-30 (T1) + ID-31 (T2) + ID-32 (T3) + ID-33 (T4) + ID-34 (T5) + ID-35 (T6).

Pre-phase (S180-S241) — treated as out-of-task-list-scope per §4.1 recommendation. Liam can override; if so, open one umbrella retrospective Task ID-30 covering pre-phase substrate (would shift T1 to ID-31 and cascade).


How does a new Tn (T7-T14, not yet shipped) enter task-list?

Per the user’s session-start framing (cited in dispatch brief):

“the items to be a task on the task list broken into subtasks where the default is that we use either a spec or a plan to structure the subtasks unless an item doesn’t have a spec because of the type of work that it is.”

Translated to the orchestrator-direct + task-planner-agent workflow per docs/reference/skill-routing-map.md + S243 ratification of fresh-per-Subtask task-planner discipline:

Step 1 — Orchestrator opens Task entry in task-list.json referencing the relevant PLAN.md section. Empty subtasks (or pre-seeded {N.1 RESEARCH → N.2 PRODUCT → N.3 TECH → N.4 PLAN} chain per Pattern A).

Step 2 — Dispatch Subtask N.1 RESEARCH to a task-planner agent. The RESEARCH brief cites PLAN.md §4.N as the substrate to research. RESEARCH ratification surfaces OQs and may recommend changes to PLAN.md (e.g. T8 RESEARCH might recommend splitting T8 into T8a/T8b/T8c).

Step 3 — PLAN.md edited if RESEARCH recommends restructure. This keeps PLAN.md as the canonical substrate (matching the user’s preference for Option 2 from prior question, cited in dispatch brief: “PLAN.md stays as substrate, top-level Tasks reference it (auto-synced to Astro docs site)”).

Step 4 — Dispatch N.2 PRODUCT (fresh task-planner) → N.3 TECH (fresh task-planner) → N.4 PLAN (fresh task-planner). Each subtask appends <info added on ...> block to its details on completion per implement-subtask convention.

Step 5 — N.4 PLAN’s output becomes the implementation Subtask list (N.5+). Orchestrator splices the proposed implementation Subtasks into the Task; dispatches them per parallelism analysis in N.4 PLAN’s body.

Step 6 — Implementation Subtasks land per the implement-subtask skill (Executor + Checker per workflow-orchestration). Each commits separately (commit-commands skill per S48 B9 ratification).

Step 7 — Task closed when all impl Subtasks done and Checker validates Task-level acceptance criteria. Only an Orchestrator can move Task in_progress → done per S48 B12 ratification.

Three sync patterns are viable:

Option α — PLAN.md is the canonical substrate; Task descriptions reference it (current implicit pattern, no automation). Each Task’s description field starts with: “Implementation of PLAN.md §4.N. See PLAN.md for canonical scope/acceptance/risk.” The Astro docs site renders PLAN.md verbatim; task-list.json Tasks deep-link to PLAN.md sections.

Option β — Auto-sync PLAN.md sections → Task descriptions on commit. A sync script reads PLAN.md, finds ### §4.N Tn — headers, extracts the section body, and updates the corresponding Task’s description field. Requires a CI guard or pre-commit hook. Risk: drift if Task.description is edited independently.

Option γ — Auto-generate PLAN.md sections FROM Task entries (reverse direction). Task.description is canonical; PLAN.md is generated. Risk: loses PLAN.md’s ratification annotations and Wave-N narrative structure (Wave 0 / Wave 1 / etc.).

Recommendation: Option α. PLAN.md is the substrate; Task descriptions reference PLAN.md sections via cross-doc-links field (already in Task schema per §3.1 Task fields). The Astro docs site (ID-9) renders BOTH:

  • docs/reference/task-list.json (as a flat list of Tasks, sortable + filterable by status/priority/umbrella).
  • docs/specs/id-31-canonical-pipeline-implementation-plan/PLAN.md (as the rendered substrate, prose + diagrams + tables).

Cross-doc links surface in both directions — Task page links to PLAN.md §4.N; PLAN.md §4.N has a “see Task ID-NN” backlink (manually added per task-opening, or auto-generated by a sync script at build time).

§5.3 Astro docs site implications (ID-9 dependency)

Section titled “§5.3 Astro docs site implications (ID-9 dependency)”

Per docs/reference/task-list.json ID-9 (Astro+Starlight docs site, in_progress with 21 Subtasks):

  • ID-9 will render docs/reference/, docs/specs/, docs/runbooks/, docs/research/ as canonical sources.
  • docs/specs/id-31-canonical-pipeline-implementation-plan/PLAN.md will render verbatim.
  • task-list.json rendering is a TBD item — could be a custom Astro component that loads the JSON and renders Tasks as a sortable table, or could be a per-Task .md mirror (per ID-20: “Per-Task .md mirror generator + render surface”, in_progress with 13 Subtasks).

ID-20’s per-Task .md mirror is the right primary render surface for Tasks. PLAN.md’s auto-sync to docs site is independent (already happens by virtue of PLAN.md being a markdown file in docs/specs/).

The “umbrella” concept (§7) needs its own render decision:

  • If §7 Option C (separate umbrellas document) is chosen, that document renders alongside PLAN.md as a curated Project-level view.
  • If §7 Option B (tags field on Task) is chosen, the Astro docs site renders a “filter by tag” pill set above the Task list.

§6 Task-list cross-branch divergence diagnosis

Section titled “§6 Task-list cross-branch divergence diagnosis”

Source: git show origin/main:docs/reference/task-list.json + git show origin/content-items-investigation:docs/reference/task-list.json + production-readiness HEAD task-list.json (read inline).

BranchTask countIDs presentSchema variant
origin/main126, 7, 8, 9, 10, 16, 15, 18, 19, 20, 22, 23Custom (KH-extended, not pure-TM)
origin/content-items-investigation (CII)146, 7, 8, 9, 10, 16, 15, 18, 19, 20, 22, 23, 28, 29Custom (KH-extended)
origin/production-readiness (PR)166, 7, 8, 9, 10, 16, 15, 18, 19, 20, 22, 23, 24, 25, 26, 27Custom (KH-extended)

Overlap on the first 12 IDs (6-23) — identical content, identical schema.

Divergence:

  • CII adds ID-28 (T8 Cocoindex flow scaffolding) and ID-29 (TanStack workspace-types migration — backlog ID-21 promotion).
  • PR adds ID-24 (Worktree collapse + track migration), ID-25 (Roadmap §3 restructure — phases become top-level Tasks), ID-26 (fix-errors skill KH-adaptation — TS + Python parity), ID-27 (session-driver-cmux maintenance — done).
  • No ID collisions across branches (28/29 only on CII; 24-27 only on PR).

All three branches use the SAME custom KH-extended TM shape:

  • Top-level keys: document_name | document_purpose | last_updated | related_documents | tasks.
  • Task fields: id, title, description, status, priority, dependencies, subtasks, updatedAt, effort_estimate, owner, priority_note, status_note, cross_doc_links, session_refs, commit_refs.

So the divergence is purely additive — each branch has added new Tasks. No structural conflicts.

This is a stale-merge issue, NOT structural duplication. The branches will reconcile on the next inter-branch merge. Specifically:

  • When CII merges to main → main gains ID-28 + ID-29.
  • When PR merges to main → main gains ID-24 + ID-25 + ID-26 + ID-27.
  • After both merges, main has IDs 6-29 minus any IDs Liam has deliberately retired.

Risk: NEW Task IDs assigned in parallel (e.g. if main-track opens ID-30 while production-readiness opens ID-30 simultaneously, collision). Mitigation:

  • Single canonical source of truth = main branch’s task-list.json. All NEW Task ID assignments happen ON main first (or via a coordination message in the orchestrator-of-orchestrators session) before being added to feature branches.
  • OR — adopt a per-track ID prefix (e.g. main-track uses ID-100+, production-readiness uses ID-200+) to make collisions structurally impossible. But this conflicts with S48 B2 ratification (single ID-N scheme across roadmap + backlog + task-list). Not recommended.
  • OR — implement a CI guard that fails task-list.json updates if a Task ID has been claimed on another branch (would require querying remote refs, complex).

Recommendation: pre-merge ID assignment. When opening a NEW Task that will land on a non-main branch, the orchestrator:

  1. Checks git show origin/main:docs/reference/task-list.json AND git show origin/<other-active-branch>:docs/reference/task-list.json to find the highest ID.
  2. Assigns NEW ID = MAX(highest_id_across_all_branches) + 1.
  3. Records the assignment in the orchestrator session log.

This is a lightweight discipline, doesn’t need automation, and avoids the collision risk.

One canonical task-list.json — on main. All Task openings ultimately land on main (via merge from feature branches). Sequential merges per CLAUDE.md “Worktree isolation rules” — cherry-pick from CII / production-readiness to main one merge at a time, resolving any task-list.json conflicts inline (they will be additive, not conflicting, given §6.3).

Cross-branch merge sequence (when triggered):

  1. CII → main: Tasks ID-28 + ID-29 added to main. Main reaches IDs 6-29 (minus retired).
  2. Production-readiness → main: Tasks ID-24 + ID-25 + ID-26 + ID-27 added to main. Main reaches full IDs 6-29.
  3. Post-merge, on main, the orchestrator-of-orchestrators session can open new Tasks 30+ for retrospective canonical-pipeline T1-T6 entries per §4.

Order matters only insofar as the merge that brings ID-28 (T8) needs to land before any retrospective Task references T8 in dependencies. Since retrospective Tasks ID-30..ID-35 are T1-T6 (predecessor work), they don’t depend on T8 — so the merge order is unconstrained.

§6 headline (single sentence): Stale-merge — branches reconcile additively on next merge cycle; no structural duplication, no ID collisions, no schema conflict.


The user’s framing of “the tag system” + the multi-umbrella reality (canonical-pipeline is ONE of several plans; production-readiness is another; sales-proposals is a Phase 3 plan) requires a representation for cross-Task umbrella membership.

Option A — umbrella field on Task (single string, many-to-one).

{
"id": "30",
"title": "T1 — Gating spec drafting",
"umbrella": "canonical-pipeline",
...
}

Pros: simple; one field; explicit ownership. Cons: a Task that belongs to multiple umbrellas (e.g. T2 is both canonical-pipeline AND prod-readiness because it touched RLS-grants pattern) cannot be expressed. Forces a choice that loses information.

Option B — tags field on Task (array of strings, many-to-many).

{
"id": "30",
"title": "T1 — Gating spec drafting",
"tags": ["canonical-pipeline", "spec-authoring"],
...
}

Pros: many-to-many; multi-umbrella; multi-category. Cons: free-form strings invite drift (“canonical-pipeline” vs “canonical_pipeline” vs “Canonical Pipeline”). Requires either a controlled vocabulary (separate doc listing valid tags) or convention-enforced via lint/CI.

Option C — Separate umbrellas document with Task ID lists (most Linear-like).

docs/reference/umbrellas.json
{
"umbrellas": [
{
"id": "canonical-pipeline",
"title": "Canonical Pipeline Implementation",
"substrate_doc": "docs/specs/id-31-canonical-pipeline-implementation-plan/PLAN.md",
"task_ids": ["28", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42"],
"status": "in_progress",
"phase": "Phase 1"
},
{
"id": "production-readiness",
"title": "Production Readiness",
"substrate_doc": "docs/tracks/production-readiness.md",
"task_ids": ["6", "7", "8", "9", "10", "16", "15", "18", "19", "20", "22", "24", "25", "26", "27"],
"status": "in_progress",
"phase": "Phase 1"
},
...
]
}

Pros: cleanest separation of concerns; normalised; matches Linear’s Initiative model (curated list of Project IDs + a substrate document); easy to render as a top-level navigation in the Astro docs site; multi-umbrella supported (a Task can be referenced from multiple umbrellas[].task_ids[] arrays). Cons: requires the orchestrator to update TWO files (task-list.json AND umbrellas.json) when opening a Task; introduces a new ledger surface to maintain.

Option D — Do nothing (implicit via title/description prefix).

"title": "[canonical-pipeline] T1 — Gating spec drafting"

Pros: zero schema change; backward-compatible. Cons: no queryability (“show me all canonical-pipeline Tasks” requires a regex match against titles); no formal umbrella concept; doesn’t surface in the Astro docs site as a first-class entity; risk of inconsistent prefixing.

CriterionOption A (umbrella)Option B (tags)Option C (separate doc)Option D (no field)
Multi-umbrella supportNoYesYesYes (prose only)
Queryability (filter by umbrella)YesYesYesRegex on title
Substrate doc linkingNoNoYes (first-class)No
Astro docs site as Initiative pageHard (need extra doc)Hard (need extra doc)Easy (umbrellas.json drives nav)None
Backward compatibilitySchema changeSchema changeNew ledger; no Task schema changeNo change
Orchestrator overheadSet one field on openSet one field on openEdit two files on openNone
Drift riskLow (single source)Medium (free-form strings)Low (curated list)High (prose drift)
Linear-model fidelityLow (single membership)Medium (label-only)High (Initiative + curated lists)None

Option C — separate umbrellas document with Task ID lists.

Justifications:

  1. Multi-umbrella is the user’s real model. Per session-start framing: “We have a project plan that relates to architectural work across the platform and within that the canonical pipeline is one plan.” Canonical-pipeline is one of several umbrellas (project-plan, production-readiness, canonical-pipeline, sales-proposals, etc.). Option A fails this; Option B works but invites drift.
  2. Substrate-doc linking is load-bearing. Each umbrella has a PLAN.md or equivalent. Option C makes the link first-class (umbrellas[].substrate_doc). Options A and B don’t capture this.
  3. Astro docs site renderability. With Option C, the docs site has a clean top-level navigation: /umbrellas/canonical-pipeline/ renders PLAN.md + a Task list curated from task_ids[]. This matches the Linear “Initiative page” model exactly.
  4. Backward compatibility on Task schema. No fields added to Task. Existing tooling (per-Task .md mirror generator, knip, doc-freshness guards) continues to work.
  5. Convergence with roadmap restructure ID-25. Task ID-25 (Roadmap §3 restructure — phases become top-level Tasks) creates the same need at the roadmap level. Option C can extend to umbrellas-for-roadmap by adding a roadmap_section_ids[] field to each umbrella entry.

Trade-off accepted: the orchestrator updates two files when opening a Task. This is a discipline cost, mitigated by:

  • Making it a step in the update-roadmap-backlog skill or its successor (per S48 N7 ratification).
  • Adding a doc-test that verifies every task_ids[] entry in umbrellas.json corresponds to a real Task in task-list.json (and vice versa for any Task that should be assigned to at least one umbrella).

Initial umbrellas to define (proposed):

Umbrella IDTitleSubstrate doc
canonical-pipelineCanonical Pipeline Implementationdocs/specs/id-31-canonical-pipeline-implementation-plan/PLAN.md
production-readinessProduction Readinessdocs/tracks/production-readiness.md
sales-proposalsSales Proposals Phase 3docs/specs/sales-proposal-workspaces/PRODUCT.md (substrate placeholder)
intelligence-workspacesIntelligence Workspaces (typed Shape B)docs/specs/intelligence-workspaces/TECH.md
docs-foundationAstro+Starlight Docs Foundationdocs/specs/id-9-astro-starlight-docs-foundation/ (likely PRODUCT.md once authored)

A Task may belong to multiple umbrellas (e.g. T2 ID-31 = canonical-pipeline + intelligence-workspaces both, since T2 ratified intelligence-workspaces Shape B Wave 0.5).


Open questions for Liam ratification with proposed defaults.

OQ-1 — Retrospective scope: pre-phase (S180-S241)?

Section titled “OQ-1 — Retrospective scope: pre-phase (S180-S241)?”

Question: Do we open a retrospective Task ID-30 (T0) for the pre-phase architecture / spec / drift-audit work (S180-S241), or treat it as out-of-task-list-scope?

Proposed default: Out-of-task-list-scope. The Phase 0.9 investigation arc preceded the task-list / Tn structure; encoding it retrospectively means ~15 retrospective Tasks (one per major doc landing across ~60 sessions) which adds ledger noise without operational value. Instead, the canonical-pipeline umbrella entry’s substrate_doc link to PLAN.md provides full retrospective context via PLAN.md’s “Provenance pointers” §10.

Alternative if Liam wants pre-phase encoded: open ONE umbrella retro Task ID-30 titled “T0 — Phase 0.9 investigation substrate” with Subtasks 30.1..30.6 capturing the major doc landings (PRODUCT/TECH, architecture sub-docs 02/04/05/06/08, RLS-pattern, reserved-workspace-seats, drift audit + implementation-readiness audit). All other T1-T6 retrospective IDs cascade by +1 (T1 → ID-31, etc.).

OQ-2 — Task ID anchor for T8 (currently ID-28)

Section titled “OQ-2 — Task ID anchor for T8 (currently ID-28)”

Question: Keep T8 = ID-28 (already in flight on content-items-investigation) and accept non-sequential T-number → ID-number mapping for the canonical-pipeline series (T1=30, T2=31, …, T6=35, T8=28, T7=36, T9=37, …)? Or renumber T8 to fit the sequence (T1=30, T2=31, …, T6=35, T7=36, T8=37, T9=38, …)?

Proposed default: Keep T8 = ID-28. Renumbering ID-28 would invalidate the existing research doc at docs/research/id-28.1-cocoindex-1-0-3-cloud-run-sidecar-op-id-spike-status-single-spec-recommendation.md (commit 58162181 S252) and break continuity with the S252 dispatch + ratification flow. The umbrella tag (§7) carries the canonical-pipeline grouping anyway, so the T-number → ID-number mapping doesn’t need to be sequential for queryability.

OQ-3 — Forward shape: open all T7-T14 Tasks now in pending, or open them just-in-time?

Section titled “OQ-3 — Forward shape: open all T7-T14 Tasks now in pending, or open them just-in-time?”

Question: Should the orchestrator (or follow-up session) open Task entries for T7 + T9 + T10 + T11 + T12 + T13 + T14 NOW in pending status (so the ledger reflects the full canonical-pipeline plan), or only open them as each becomes the next-up Task to dispatch?

Proposed default: Just-in-time. Per the user’s S250 clarification (S251 prompt rule 5): items physically MOVE backlog → task-list when ready to work on. Opening 7 pending Tasks fills the ledger with non-actionable entries. The PLAN.md + umbrella substrate already captures the full plan; task-list.json should reflect what’s actionable (pending = ready to dispatch; in_progress = actively being worked; done = shipped).

Alternative if Liam wants full upfront visibility: open all Tasks now. Pro: complete ledger snapshot of the canonical-pipeline plan. Con: 7 pending Tasks with empty subtasks (since subtasks are seeded only at dispatch time per fresh-task-planner-per-Subtask discipline).

Question: §7 recommends Option C (separate umbrellas document with task_ids[] arrays). Does Liam ratify Option C? Alternative options A (single-string umbrella field) and B (tags array field) on Task are simpler but less expressive.

Proposed default: Option C. Justifications per §7.3 — multi-umbrella reality + substrate-doc linking + Astro docs site renderability + Linear-model fidelity. Trade-off: orchestrator updates two files on Task open.

Implementation followup: If Option C ratified, open a NEW Task ID-43 (or wherever it lands sequentially) titled “Implement umbrellas.json + Astro Initiative pages” with Subtasks for (a) ratify schema; (b) author initial umbrellas.json with 5 entries from §7.3 table; (c) Astro nav + Initiative page template; (d) doc-test for umbrellas.task_ids[]task-list.tasks[].id consistency; (e) update update-roadmap-backlog skill (or successor) to write to both files on Task open.

OQ-5 — Cross-branch Task ID coordination

Section titled “OQ-5 — Cross-branch Task ID coordination”

Question: §6.3 recommends pre-merge ID assignment discipline (orchestrator queries git show origin/<each-branch>:docs/reference/task-list.json before assigning NEW ID). Acceptable as a manual discipline, or does Liam want automated CI guard?

Proposed default: Manual discipline for now. Add a step to the workflow-orchestration skill body that documents “Before opening a NEW Task, check origin/main + origin/content-items-investigation + origin/production-readiness for highest ID; assign MAX+1.” Automation (CI guard that queries remote refs) is heavyweight relative to the risk; revisit if collisions occur.

OQ-6 — Retrospective Subtask granularity

Section titled “OQ-6 — Retrospective Subtask granularity”

Question: The proposed retrospective Subtasks (§4.2-§4.7) range from 4 (T1) to 12 (T2). Some Tasks (e.g. T6) have natural WP groupings (WP1 schema / WP2 RPCs / WP3 test / WP4 docs); others (e.g. T5) ran through multi-session passes (S248 initial + S251 W1B Phases A-G). What granularity does Liam want for retrospective Subtasks?

Proposed default: Match the actual shipping cadence. Subtasks correspond to commit groupings or session-WP packages, with citation of the commit SHA in the title or description. This preserves the audit trail at the right resolution — finer than “T2 shipped” but coarser than per-commit-per-Subtask.

Alternative if Liam prefers coarse-grained: consolidate to one Subtask per session (e.g. T6 ID-35 collapses to 2 Subtasks: 35.1 “S249 WP1+WP2+WP3+WP4 shipping” + 35.2 “S250 W1b PUBLIC-EXECUTE followup”). Less ledger noise; less audit detail.

OQ-7 — PLAN.md as substrate vs Task description sync

Section titled “OQ-7 — PLAN.md as substrate vs Task description sync”

Question: §5.2 recommends Option α (PLAN.md is canonical; Task descriptions reference it via cross_doc_links). Does Liam want auto-sync Options β (PLAN→Task) or γ (Task→PLAN) instead?

Proposed default: Option α (manual / cross-doc-links only). PLAN.md stays as the rendered substrate per the user’s preference (cited in dispatch brief). Task descriptions are short and link to PLAN.md §4.N for canonical scope. Astro docs site renders both surfaces; readers navigate cross-doc links. Auto-sync (β or γ) adds tooling complexity for marginal benefit — drift risk is low if Task descriptions stay short and PLAN.md is the only place that changes for canonical scope.


  • PLAN.md (canonical substrate): docs/specs/id-31-canonical-pipeline-implementation-plan/PLAN.md (S241-S252 cumulative).
  • Taskmaster empirical schema: docs/reference/taskmaster-schema-reference.md (S48, 444 lines).
  • S48 feedback (user-intent anchor): docs/plans/phase-0-investigation/s48-feedback.md lines 30-46 (A6/A7/A8 TM-shape ratifications), lines 116-119 (B12 status-transition rules), lines 195-205 (general comments on backlog→task-list flow).
  • Main-track continuation prompts (retrospective evidence):
    • S242 prompt: docs/continuation-prompts/continuation-prompt-kh-s242-main-t1-specs-and-phase-0-close.md (T1 spec authoring).
    • S243-S247 prompts: T2 combined-PR migration arc.
    • S248 prompt: docs/continuation-prompts/continuation-prompt-kh-s248-main-t4-procurement-rename-and-t5-digest-code.md (T4 + T5 initial).
    • S249-S250 prompts: T6 q_a_pairs migration arc.
    • S251 prompt: docs/continuation-prompts/continuation-prompt-kh-s251-main-baseline-cleanup-before-pipeline-impl.md (T5 W1B residual closeout).
    • S252 prompt: docs/continuation-prompts/continuation-prompt-kh-s252-main-t8-spec-cycle-and-id21-plan.md (T8 Task ID-28 opened).
  • Task-list branches (cross-branch read):
    • git show origin/main:docs/reference/task-list.json (12 tasks, IDs 6-23).
    • git show origin/content-items-investigation:docs/reference/task-list.json (14 tasks, +ID-28 +ID-29).
    • docs/reference/task-list.json on production-readiness HEAD (16 tasks, +ID-24..27).
  • Backlog + Roadmap (cross-reference dedup awareness): docs/reference/product-backlog.json (55 items; canonical-pipeline-related rows: ID-25/26 T6/T10 substrate, ID-74/75/76 q_a_pair/T6, ID-37/38/39 digest-comparison consumer items); docs/reference/product-roadmap.json (16 sections; canonical-pipeline-related items: §13.1 Q&A copy tracking only).
  • Linear research:
  • GitHub Projects research:
  • Aha! research:

End of research doc. Ratification of §8 OQs gates Task ID-30 opening (or ID-30 + cascade depending on OQ-1 outcome).