Skip to content

ID-148 TECH — Initiatives-ledger CLI support (Option C: repurpose roadmap server arm)

ID-148 TECH — Initiatives-ledger CLI support + repurpose roadmap→initiatives (server-side)

Section titled “ID-148 TECH — Initiatives-ledger CLI support + repurpose roadmap→initiatives (server-side)”

Spec-tier note. TECH+PLAN by design — no PRODUCT.md. The S472 structural audit is the research substrate; this TECH.md carries its own numbered Behaviour contract (§2).


Revision note — Option B → C (S-current)

Section titled “Revision note — Option B → C (S-current)”

Why this third revision exists. Liam ratified the Option-B open questions and overrode OQ1: the initiatives WRITE path must be server-side, not a KH-native in-process writer.

The architecture fact both prior revisions mishandled (now verified — §1.1). Since the ID-90.22 R1b cutover, ledger WRITES are owned by the task-view patch-server; the in-process direct-write path was deleted (scripts/ledger-cli.ts line ~1767; every mutating call site supplies a ServerIntentbuildTransportRequestserverCommitMutationtransportCommit). Option A/B’s Decision 1 (a scoped atomic+advisory-locked in-process writer for initiatives.json) re-introduces exactly what R1b removed — it is wrong. Liam: “writes were moved server-side previously; not doing this properly undoes the original work.”

Option C — repurpose, don’t retire-and-rebuild. product-roadmap.json was manually repurposed into initiatives.json; the roadmap ledger is the pre-repurpose initiatives ledger. So repurpose the roadmap SERVER ARM into an initiatives server arm rather than retiring it KH-side and rebuilding a KH-native writer:

  • Upstream (task-view): adapt packages/schemas/src/roadmap-schema.tsinitiatives-schema.ts; repurpose the server write/mutate arm (detect-schema kind:'initiatives', patch-apply, record-mutate, id-minting, record-set gate) for the nested initiatives shape; repurpose the roadmap mirror generator → server-side initiatives mirror (and add the retros mirror arm, currently excluded); repurpose the roadmap UI view → an initiatives view plus editing (OQ2). Relocate DocLinkSchema. Retire the umbrella surface. Cut v0.10.0-task-view (Executor, OQ3).
  • Canonical: re-vendor lib/ledger/{detect-schema,patch-apply,record-mutate}.ts so the oracle registers kind:'initiatives' (imports InitiativesSchema); the CLI WRITE verbs (create/update/delete-project, link/unlink task+backlog, move-task/move-backlog) build ServerIntents routed through the transportNO in-process writer. Read verbs stay local file reads ({148.6}, DONE).
  • Retire fully (no initiatives analog): the umbrella surface (both repos incl. tests) and roadmap-only concepts with no initiatives mapping — themes[], the capability_theme write back-link, product-roadmap.json consumption, detect-roadmap-shipped-framings.ts, and the update-roadmap/create-theme verb names (replaced by the initiatives verbs).

Ratified OQ outcomes (from the Option-B report): OQ1 → server-side (this revision); OQ2 → add an initiatives view + editing upstream; OQ3 → Executor cuts + tags + uploads v0.10.0-task-view; OQ4 → umbrellas.json physical deletion stays DEFERRED to the data-quality task.

Disposition of the already-landed {148.5} / {148.6} / {148.9} (on canonical main, pushed this session) — see §8 for the load-bearing detail; in brief: {148.6} read verbs KEEP; {148.5} schema re-homes upstream + is vendored + REGISTERED in detect-schema.ts (its KH-native “not referenced from detect-schema” constraint reverses); {148.9} KH-native mirror generators are SUPERSEDED by server-side generation (revert the scripts + rewire regen-mirrors.sh; the committed mirror OUTPUT stays as valid data — only the mechanism changes). Nothing is lost — it re-bases onto the server architecture.

Delta at a glance — INV-8 inverts (server-side write, no in-process writer); INV-9 inverts (server-side mirror regen); INV-12 changes (roadmap arm REPURPOSED not retired, + upstream initiatives UI view/editing); INV-3 strict-write enforcement moves server-side; new INV-13 (nested project addressing). Subtasks: {148.7} rewritten (ServerIntents), {148.10} rewritten (upstream repurpose + UI), {148.12} rewritten (re-vendor+register+supersede-.9); {148.8} narrows (umbrella + roadmap-verb-name retirement + DocLinkSchema relocation only).


1.1 Code-intelligence orientation (verbatim tool output)

Section titled “1.1 Code-intelligence orientation (verbatim tool output)”

Run against repo: /Users/liamj/Documents/development/canonical.

gitnexus_query({query: 'roadmap umbrella schema retire'})no processes; definitions incl. Function:scripts/ledger-cli.ts:run (2595–4158), …:updateUmbrella (4405–4596), Function:lib/ledger/patch-apply.ts:applyRoadmapPatch (188–236), Function:lib/validation/umbrellas-helpers.ts:formatRetrospectiveJournalBlock (102–162, dead export).

gitnexus_context({name: 'DocLinkSchema'})Const:lib/validation/roadmap-schema.ts:DocLinkSchema (88–103), empty edges (Zod const). gitnexus_impact({target:'roadmap-schema.ts',direction:'upstream', summaryOnly:true})impactedCount:9, risk:"MEDIUM", direct:7, byDepthCounts:{"1":7,"2":2}.

Server-side write-path grounding (verifies the Option-C correction — direct read):

  • scripts/ledger-cli.ts:155type LedgerSlug = 'task-list' | 'roadmap' | 'backlog' | 'umbrellas' | 'retro'; :157 LEDGER_NAME_TO_SLUG; :212 type LedgerName = 'task' | 'roadmap' | 'backlog' | 'retro'; :214 LEDGER_FILES. (Roadmap→initiatives swap targets.)
  • scripts/ledger-cli.ts:174–208type ServerIntent union: field-patch / record-create / subtask-create / subtask-delete / record-delete (all {slug: LedgerSlug, …}) / umbrella-patch / transaction. :1790 commitMutation:1791 “delegates unconditionally to serverCommitMutation”; :1803 buildTransportRequest builds ${base}/${intent.slug}/record/… URLs; :1889 serverCommitMutationtransportCommitensureServer (spawns the pinned task-view clone). Confirms: every write is an HTTP call to the patch-server; there is no in-process writer.
  • lib/ledger/detect-schema.ts:68–98detectSchema routes by document_name literal → kindschema.parse. Known kinds: task-list | roadmap | backlog | retro (canonical oracle; note it does not import umbrellas — umbrella handling is ledger-cli-only). Adding kind:'initiatives' = one arm routing "Canonical Platform - Initiatives"InitiativesSchema.
  • Nested-topology mismatch finding (load-bearing). The roadmap server arm assumes a flat themes[] collection — verified in task-view packages/server/: record-mutate.ts:90–93 collectionKeyFor('roadmap')→'themes', :102–103 idsForDetected('roadmap')→themes.map(t=>t.id), insertRecord/removeRecord operate on the flat rawClone[collectionKey] array; patch-apply.ts applyRoadmapPatch addresses ['themes', themeId, field] (single level, no nesting); mirror-generator.ts:381 planRoadmapMirrors maps roadmap.themes one-per-theme; patch-server.ts:263 kind:'roadmap' → recordKind:'roadmap-theme'. The initiatives ledger is nested + recursive (initiatives[]projects[] + recursive sub-initiatives[]; projects are globally-unique kebab slugs — audit A9). So the repurpose reuses the roadmap arm’s id-minting / record-set-gate / budget-gate / patch-validation scaffolding but replaces the flat-array addressing with a tree walk (INV-13). mirror-generator.ts:89–94 currently EXCLUDES retro from mirrors — the retros arm is added here ({148.9} superseded, §8).

1.2 How the ledger CLI writes today (the load-bearing constraint — Option C’s foundation)

Section titled “1.2 How the ledger CLI writes today (the load-bearing constraint — Option C’s foundation)”

Since ID-90.22 R1b there is exactly one write path and it is server-side: every mutation routes through the task-view patch-server via serverCommitMutationtransportCommitensureServer, which spawns the pinned clone .cache/task-view-<TASK_VIEW_TAG>/apps/server/index.ts. The server owns serialisation, the record-set + budget gates, the discipline sweep and mirror regen. The CLI keeps a client-side validation oracle (lib/ledger/{detect-schema,patch-apply,record-mutate}.ts, vendored from task-view packages/server/*) that fails a malformed mutation fast client-side before the server re-validates authoritatively. Option C makes initiatives a first-class server kind in exactly this model — identical to how task-list/backlog/retro already work.

1.3 Why every roadmap/umbrella verb is currently broken

Section titled “1.3 Why every roadmap/umbrella verb is currently broken”

(Unchanged from prior revisions.) product-roadmap.json renamed → initiatives.json; LEDGER_FILES. roadmap ENOENTs; detectSchema returns unknown for the new document_name; RoadmapSchema requires themes[]; umbrellas.json is malformed/truncated.

1.4 The real initiatives.json shape (verified — schema MUST match this)

Section titled “1.4 The real initiatives.json shape (verified — schema MUST match this)”

ledgers/initiatives.json (43.5 KB; 10 initiatives). Top-level document_name `“Canonical Platform

  • Initiatives”. initiatives[]: id(bare-digit string),title, description, substrate_doc, status, projects[], originating_session[](array),sub-initiatives[](recursive; second-level nesting under initiative4; substrate_docoptional on sub-initiatives).projects[]: id(kebab slug — **globally unique**, audit A9),title, summary, description, substrate_doc, status, blocked_by[], blocking[], linked_tasks[], linked_backlog[], originating_session[]. **Transitional (audit A3):** initiative 4carrieslinked_tasks/linked_backlogat the **initiative** level — the schema MUST read this (INV-2); the data-quality task redistributes it via{148.7}'s CLI verbs (INV-5 preamble). Statuses: project ∈ {idea,proposal,backlog,discovery, accepted,ready,paused,in-progress,maintenance,completed,cancelled}; initiative/sub-initiative ∈ {proposed,planned,active,completed,cancelled}`.

ledgers/initiatives/{1..16}.md = stale theme mirror (the DONE {148.9} regenerated the current topology — that OUTPUT is valid data and stays; the generation MECHANISM re-bases server-side under Option C, §8). TASK_VIEW_TAG is v0.9.0-task-view (ci.yml:282/290). task-view-vendor-drift.yml is non-blocking; watch/download name roadmap-schema.ts.


2. Behaviour contract (numbered invariants — Checker verifies against these)

Section titled “2. Behaviour contract (numbered invariants — Checker verifies against these)”

Project-model requirement (load-bearing, new-dev-workflow-concepts.md). Only projects hold linked_tasks/linked_backlog; a project contains multiple tasks; the data-quality task must (a) redistribute initiative-4’s links to projects and (b) consolidate the current 1:1 project→task records into fewer multi-task projects (Liam ratified: sub-init 2’s 3 projects→one, sub-init 4’s 2→one, next session) — as CLI operations, never hand-edited JSON. INV-5 supplies the full verb set.

  • INV-1 — Read the file as-is. show/list/get parse the current dirty initiatives.json with no clean-data precondition. (DONE — {148.5}/{148.6}.)
  • INV-2 — Schema matches the real shape (§1.4). Optional substrate_doc on sub-initiatives; recursive sub-initiatives[]; initiative-4 off-project links tolerated; gitignored-dir substrate_doc → non-fatal warning (D2). (DONE — now re-homed upstream, §8.)
  • INV-3 — Lenient read / strict write on status. Read accepts any string. A mutation that SETS status rejects an out-of-enum value for that node kind with an actionable invalid-status envelope. Under Option C the strict-write enum check is enforced server-side (the patch-server initiatives arm), with the client-side oracle able to surface it early; existing dirty values elsewhere are preserved.
  • INV-4 — Read verbs. show/list initiatives|projects + --status/--initiative/--recent/--limit/ --fields/--ids-only. (DONE — local reads.)
  • INV-5 — Project CRUD (via ServerIntents). create-project <initiativePath> …; update-project <slug> <field> <value> (incl status); delete-project <slug> (rejects project-not-empty if it still holds linked_tasks/linked_backlog); link-tasks/unlink-tasks/ link-backlog/unlink-backlog <slug> <ids…>; move-task <taskId> --from <slug> --to <slug> and move-backlog <backlogId> --from <slug> --to <slug> (atomic re-parent). Each verb builds a ServerIntent routed through the transport (no in-process write). Bare-digit id validation on task/backlog ids; slug validation on projects.
  • INV-6 — Links are project-only. Link/unlink/move operate ONLY at project level; targeting an initiative/sub-initiative rejects links-project-only.
  • INV-7 — Retired verbs fail cleanly. The roadmap/umbrella verb namesshow/list/update- roadmap, create-theme, show/list umbrellas, update-umbrella, promote --capability-theme — return retired-verb/retired-flag (never ENOENT/parse/stack). Note: the roadmap server arm is repurposed, not retired; only the CLI verb names retire (initiatives verbs replace them). The roadmap/umbrellas <ledger> argument is rejected by ledger-name validation.
  • INV-8 — Safe write is SERVER-SIDE (INVERTED from Option A/B). Initiatives writes route through the task-view patch-server via a ServerIntent (field-patch/record-create/record-delete on slug:'initiatives', plus an atomic move op — INV-13). The server owns atomicity, the record-set gate (post-write id-set delta ∅/+1/−1; move ops are ∅), the budget gate, serialisation and mirror regen — identical to task-list/backlog/retro. There is NO in-process writer; the R1b single-write-path invariant is preserved. --dry-run is honoured server-side; --force downgrades the budget gate to a warning (server flag).
  • INV-9 — Mirror regen is SERVER-SIDE (INVERTED from Option A/B). The task-view mirror generator gains an initiatives arm (one mirror per top-level initiative, rendering the nested sub-initiative→project→links tree) and a retros arm (currently excluded). Mirrors regenerate on every server write and via regen-mirrors.sh (rewired to request initiatives + retros from task-view). The DONE KH-native generators are reverted (§8).
  • INV-10 — Envelope + argv parity. Standard envelope ({ok:true} exit 0 / {ok:false,error, detail} exit 1; --pretty, --dry-run).
  • INV-11 — stdout purity. Initiatives verbs keep stdout pure JSON.
  • INV-12 — Repurpose + relocation + retire (Option C). After ID-148: (a) the roadmap server arm (schema, detect-schema kind, patch-apply/record-mutate arm, mirror generator, UI view) is REPURPOSED to initiatives upstream — including an initiatives UI view + editing (OQ2) — and re-vendored so the canonical oracle registers kind:'initiatives'; (b) the umbrella surface is fully retired in both repos incl. tests (umbrellas.json file-delete DEFERRED — OQ4); (c) DocLinkSchema is relocated to a neutral doc-link.ts (both repos) and its live consumers (backlog/task-list/retro + curator-smoke test) repointed; (d) roadmap-only concepts with no initiatives analog (themes[], capability_theme write, product-roadmap.json, detect-roadmap-shipped-framings.ts) are removed; (e) TASK_VIEW_TAG bumped consistently.
  • INV-13 — Nested project addressing (NEW). The server initiatives arm addresses records across the nesting: a project by its globally-unique slug (server tree-walks initiatives[] + recursive sub-initiatives[] to locate it); an initiative/sub-initiative by its path (e.g. 4, 4.2). create-project’s record-create intent carries the parent initiativePath so the server inserts under the addressed parent. move-task/move-backlog are a single atomic server op touching source + target project records (record-set delta ∅). The record-set gate and id-minting walk the whole tree (not a flat array).

3.1 Upstream (task-view repo) — the repurpose + retire ({148.10})

Section titled “3.1 Upstream (task-view repo) — the repurpose + retire ({148.10})”

Work in /Users/liamj/Documents/development/task-view (branch main; separate repo we own).

(a) Schema. Adapt packages/schemas/src/roadmap-schema.tsinitiatives-schema.ts — port the lenient-read/strict-write initiatives shape (matching the DONE {148.5} canonical schema: status z.string() read, recursive z.lazy sub-initiatives, optional substrate_doc, originating_session array, initiative-4 tolerance) + INITIATIVE_STATUSES/PROJECT_STATUSES for the server strict-write gate. Relocate DocLinkSchemapackages/schemas/src/doc-link.ts; repoint task-list/backlog/retro schemas. Retire umbrellas-schema.ts (+ test) and the ledger-budgets.ts theme entry.

(b) Server write/mutate arm. packages/server/: detect-schema.ts — replace the roadmap document_name/kind arm with kind:'initiatives' ("Canonical Platform - Initiatives"InitiativesSchema); remove the umbrellas kind. record-mutate.ts — replace the flat collectionKeyFor('roadmap')→'themes' + flat insertRecord/removeRecord/idsForDetected with the nested initiatives model (INV-13): tree-walk to locate a project by slug / a parent by path; create-project inserts under the addressed parent; id-minting for new projects (slug uniqueness guard across the whole tree); record-set gate walks initiatives+sub-initiatives+projects. patch-apply.ts — replace applyRoadmapPatch’s ['themes', themeId, field] addressing with initiatives addressing (project fields by slug; initiative/sub-initiative fields by path); add an atomic move op (source+target project linked_* edit in one gate cycle). patch-server.ts — swap the roadmap/roadmap-theme recordKind for initiatives record kinds; remove the umbrellas arm. Repurpose mirror-generator.ts roadmap arm → initiatives (nested render) and add the retros arm (remove retro from the mirror-exclusion set).

(c) UI view + editing (OQ2). Repurpose packages/ui/record-view roadmap/theme views (roadmap-index-view, roadmap-theme-view, roadmap-sort, theme-*, inverse-theme-index) → an initiatives view with editing (render the nested tree; edit project fields, link/unlink, create/ delete/move via the server write arm). Update ledger-switcher/index-search/types initiatives arms. Delete umbrella UI. Update all corresponding .test.*.

(d) Retire umbrella + release. Remove the umbrella surface across packages/{schemas,server,ui}

  • tests. Run the task-view suite green. Cut release v0.10.0-task-view with the schema assets the drift workflow downloads (OQ3 — Executor cuts + tags + uploads).

3.2 Canonical re-vendor + register + supersede-.9 ({148.12})

Section titled “3.2 Canonical re-vendor + register + supersede-.9 ({148.12})”

Dep {148.10} (release) + {148.8} (DocLinkSchema relocated). Bump TASK_VIEW_TAGv0.10.0- task-view in ci.yml + task-view-vendor-drift.yml + lib/ledger/README.md. Re-vendor lib/ledger/{detect-schema,patch-apply,record-mutate}.ts from the new tag: detect-schema.ts now imports InitiativesSchema and registers kind:'initiatives' (drops roadmap); the mutate/patch arms carry the nested initiatives logic. Reconcile lib/validation/initiatives-schema.ts (the DONE {148.5} artifact) as the vendored twin of the upstream schema (same symbols; import-specifier convention) — the read verbs ({148.6}) keep importing it from this path. Update the drift-yml watch/download lists (drop roadmap-schema.ts/umbrellas-schema.ts; add initiatives-schema.ts + doc-link.ts). Delete the now-unreferenced lib/validation/roadmap-schema.ts shell (DocLinkSchema relocated in {148.8}, oracle no longer imports RoadmapSchema) + the ledger-budgets.ts theme entry. Supersede {148.9}: delete scripts/generate-initiatives-mirror.ts + generate-retros-mirror.ts; rewire regen-mirrors.sh to request initiatives + retros mirrors from task-view (whose generator now emits them). The already-committed mirror OUTPUT stays valid.

3.3 Canonical write verbs as ServerIntents ({148.7})

Section titled “3.3 Canonical write verbs as ServerIntents ({148.7})”

Dep {148.12} (the re-vendored oracle must register kind:'initiatives', and the bumped tag must spawn the initiatives-capable server). Add initiatives to LedgerSlug + LedgerName + LEDGER_NAME_TO_SLUG + LEDGER_FILES (initiatives.json). Each write verb builds a ServerIntent: create-projectrecord-create (slug:'initiatives', record carries the project + parent initiativePath); update-project/link/unlink → field-patch (slug:'initiatives', recordId: <projectSlug>, patches); delete-projectrecord-delete (recordId:<projectSlug>, non-empty guard client-side + server); move-task/move-backlog → the atomic move op (INV-13). The CLI-side oracle (loadLedgerdetectSchema→initiatives, fieldPatchMutationapplyPatches, insertRecord/removeRecord) runs at the call site for the fast local envelope; the server re-validates + gates authoritatively. --dry-run/--force threaded as transport flags (INV-8/10). links-project-only (INV-6) enforced at the CLI before building the intent.

3.4 Canonical retire ({148.8}) — umbrella + roadmap-verb-names + DocLinkSchema relocation

Section titled “3.4 Canonical retire ({148.8}) — umbrella + roadmap-verb-names + DocLinkSchema relocation”

Dep {148.6}. Runs before {148.12}/{148.7} in ledger-cli.ts. Remove the umbrella verbs (show umbrellas read 2783; update-umbrella write 4405–4596 + umbrella-patch ServerIntent leg + buildTransportRequest case + registry/USAGE/op-flag) and the roadmap verb names (show/list/update-roadmap, create-theme, promote --capability-theme); intercept all via RETIRED_VERBSretired-verb/retired-flag (INV-7). Delete lib/validation/umbrellas-schema.ts

  • its 3 test dependents + umbrellas-helpers.ts (+ test, after confirming the dead export). Delete scripts/detect-roadmap-shipped-framings.ts. Strip scripts/ledger-differential-parity.ts roadmap legs. Relocate DocLinkSchemalib/validation/doc-link.ts; repoint backlog-schema.ts:22, task-list-schema.ts:26, retro-schema.ts:31, __tests__/skills/curator-rewrites-smoke.test.ts:54. Leave roadmap-schema.ts a RoadmapSchema shell (still imported by the not-yet-revendored oracle; {148.12} deletes it).

N/A — no new external-library symbols. zod already pinned; server transport already exercised. The repurpose is internal symbol/arm movement, verified by both repos’ bun run test + the drift-workflow byte compare, not import-and-call.


4. Ratification gate — Liam signs off (each PROPOSED with a recommendation)

Section titled “4. Ratification gate — Liam signs off (each PROPOSED with a recommendation)”

Decision 1 — Initiatives WRITE path = SERVER-SIDE (Option C; supersedes A/B Option A). Repurpose the roadmap server arm into an initiatives arm; writes route through the patch-server via ServerIntents; no in-process writer. Grounded in §1.1/§1.2 (R1b single-write-path).

Decision 2 — mirror-as-SoT (unchanged): generated initiatives/{id}.md is the readable SoT; substrate_doc demoted. Now server-generated (INV-9).

Decision 3 — originating_session = z.array(z.string()) (unchanged).

Decision 4a — retire umbrella CODE now (both repos), DEFER umbrellas.json file deletion (ratified OQ4): deletion gated on the data-quality task reconciling 49+ orphaned task_ids.

Decision 4b — task-view repo repurpose + re-vendor + TASK_VIEW_TAG bump = IN scope (ratified): {148.10} + {148.12}. Executor cuts the release (OQ3).

Decision 5 (NEW) — nested addressing (INV-13). PROPOSED: address a project by its globally-unique slug (server tree-walk), reusing the generic field-patch/record-delete ServerIntents; create-project carries the parent initiativePath; move-* is a dedicated atomic op. See Open Question 1 (slug vs path addressing) + Open Question 2 (atomic-move mechanism).

Design ruling — repurpose over rebuild. The ledger file, the server kind slot, the mirror generator and the UI view are repurposed (honouring “repurpose/rename, don’t retire-and-rebuild”); the flat themes[] addressing is replaced by a nested tree walk (INV-13). DocLinkSchema is relocated, not deleted.


  • Upstream (task-view, {148.10}) — the task-view suite green after the repurpose: detect-schema routes initiatives; the mutate arm inserts/deletes/patches nested projects + mints slugs + gates the record set; the atomic move op moves a task with delta ∅; the mirror generator emits initiatives
    • retros mirrors; the initiatives UI view renders + edits. Umbrella removed.
  • Canonical re-vendor ({148.12}) — full bun run test green; the re-vendored lib/ledger/* diff vs prior pin shows only the roadmap→initiatives arm swap + import-specifier; no unresolved roadmap-schema imports; drift-yml parses without roadmap-schema.ts.
  • Canonical write verbs ({148.7}, server-backed)ledger-cli-initiatives.test.ts: create/update/delete-project (non-empty guard); link/unlink; move-task/move-backlog re-parent (delta ∅); invalid-status (server-enforced, surfaced client-side); links-project-only; --dry-run writes nothing; --force budget downgrade. Behaviour-first per reference/test-philosophy.md; the permitted mock is the process/spawn seam (server transport) — tests run against a tmp-dir fixture with a real (or stubbed-transport) server, matching the existing ledger-server-*.test.ts pattern.
  • Retire ({148.8}) — retired-verb coverage (roadmap/umbrella verb names → retired-verb/ retired-flag, no ENOENT/parse/stack); DocLinkSchema imports resolve from doc-link.ts; backlog/task-list/retro + curator-smoke tests pass.
  • Regressionledger-server-*.test.ts extended for the initiatives slug; task-list/backlog/retro write contracts unaffected.
  • “Repurpose” understates the nested-arm work. The roadmap arm is flat; initiatives is nested + recursive (INV-13). Mitigation: {148.10} reuses the scaffolding (gates, id-mint, patch validation) but treats the tree-walk addressing as new; sized L/XL with an internal slice order in details.
  • Long server-first critical path. {148.10}{148.12}{148.7} serialises (upstream release → re-vendor → CLI verbs) — longer than the (rejected) in-process shortcut, but architecturally correct. Mitigation: {148.8} (retire/relocate) and the read path (DONE) run off the critical path.
  • Re-vendor drift. {148.12} diffs the re-vendored primitives vs the prior pin; asserts only the arm-swap + import-specifier; gates on full bun run test.
  • .5/.9 re-base churn. Already-landed KH-native work re-homes/reverts. Mitigation: §8 states each disposition explicitly; the committed mirror OUTPUT is preserved (only the mechanism changes).
  • Atomic move (INV-13). Two-record edit needs a dedicated server op. Mitigation: Decision 5 / Open Question 2 — dedicated atomic op recommended.
  • umbrellas.json value loss / docs drift — Decision 4a defers the file delete; {148.11} propagates the vocabulary.

7. Ordered migration plan (seeds {148.4} PLAN.md)

Section titled “7. Ordered migration plan (seeds {148.4} PLAN.md)”

D = DONE this session; U = unstarted.

  1. [D] {148.5} Schema — re-homes upstream + vendored + registered (§8).
  2. [D] {148.6} Read verbs — KEEP (local reads).
  3. [D] {148.9} KH-native mirrors — SUPERSEDED; reverted in {148.12} (§8).
  4. [U] {148.8} Canonical retire + DocLinkSchema relocation — umbrella verbs/schema, roadmap verb names (RETIRED_VERBS), relocate DocLinkSchema, strip parity/detect-roadmap. Dep 2.
  5. [U] {148.10} task-view repurpose + UI + release — roadmap→initiatives server arm (nested), schema, mirror (+retros arm), UI view+editing (OQ2), retire umbrella, relocate DocLinkSchema upstream, cut v0.10.0-task-view. Dep: none (separate repo). Critical-path head.
  6. [U] {148.12} Canonical re-vendor + register + supersede-.9 — bump tag; re-vendor oracle (kind:‘initiatives’); vendor+register schema; drift-yml; delete roadmap-schema shell + ledger-budgets theme; revert .9 generators + rewire regen-mirrors.sh. Dep 4 + 5.
  7. [U] {148.7} Write verbs as ServerIntents — create/update/delete-project, link/unlink, move-task/move-backlog; add initiatives slug/name/file. Dep 6.
  8. [U] {148.11} propagate-workflow-change sweep — canonical .claude/{skills,agents} + root CLAUDE.md + docs-site references. Dep 4,5,6,7 (last).

Critical path: {148.10}{148.12}{148.7}{148.11}. {148.8} parallelises (dep the DONE read path). Compound invariants + two-repo + release-gated server-first chain → PLAN warranted.

8. Follow-ups / deferred + explicit .5/.6/.9 disposition

Section titled “8. Follow-ups / deferred + explicit .5/.6/.9 disposition”

Already-landed work (canonical main, this session) — Option C disposition:

  • {148.6} read verbsKEEP. Local file reads, unaffected by the server write path. Verify the lib/validation/initiatives-schema.ts import still resolves after .5 re-homes (same path, now vendored).
  • {148.5} lib/validation/initiatives-schema.tsRE-HOME + VENDOR + REGISTER. The schema LOGIC is reused, but under Option C it is authored upstream ({148.10}, adapted from roadmap-schema.ts) and vendored into canonical (the existing file becomes the vendored twin, same symbols + import-specifier convention) and REGISTERED in the re-vendored lib/ledger/detect-schema.ts (kind:'initiatives'). Its DONE checker constraint “must NOT be referenced from detect-schema.ts / stay KH-native” REVERSES. Strict-write enum enforcement moves to the server-side write gate.
  • {148.9} KH-native generators (scripts/generate-initiatives-mirror.ts, generate-retros-mirror.ts, regen-mirrors.sh KH wiring) — SUPERSEDED / REVERT. Server-side generation (task-view mirror-generator.ts initiatives + retros arms, {148.10}) replaces them; {148.12} deletes the two scripts and rewires regen-mirrors.sh to request initiatives + retros mirrors from task-view. The committed mirror OUTPUT (initiatives/{id}.md, retros/{session}.md) is valid DATA and stays — only the mechanism changes; the next server regen reproduces it.

Deferred (NOT in ID-148):

  • initiatives-ledger-data-quality task (ID-148 gates it): initiative-4 redistribution + 1:1→multi-task project consolidation (via {148.7} verbs), status normalisation, dead linked_backlog refs, population gaps, substrate_doc cleanup, umbrellas.json physical deletion after task_id reconciliation (Decision 4a / OQ4).
  • {68.30} dissolved into ID-148 — the repurpose + re-vendor land here.
  • ledger-workflow-quality-of-life task: [branding] stdout fix (INV-11), journal date-range search/export, task-level blocked_by/blocking.
  • Task capability_theme field dormant-cleanup (vendored task-list-schema + live data).