Skip to content

ID-90 — Server-ledger cutover: PLAN

{90.4} PLAN artefact — authored against the ratified {90.2} PRODUCT (S322, 62 invariants incl. the amended invariant-14 wording) + {90.3} TECH (S322, incl. OQ-7 Semantics B RATIFIED and the T-1…T-5 decisions). Decomposes the ratified Option A two-phase cutover into implementation Subtasks for the parallel-cmux sub-track.

  • Task: ID-90 “Server-ledger cutover — task-view patch-server replaces ledger-cli (gates + guard port)”
  • Authored: 07/06/2026 (fresh Planner per Q-PLANNER-2 — no carryover from the RESEARCH/PRODUCT/TECH Planners).
  • Predecessors: docs/specs/ID-90-server-ledger-cutover/{RESEARCH,PRODUCT,TECH}.md — all ratified S322.
  • Grounded at: canonical-pipeline-setup HEAD 876c68ac (07/06/2026). Pin facts re-verified at that SHA: TASK_VIEW_TAG: v0.3.1-task-view at ci.yml:1139; lib/ledger/ carries the five modules R2 deletes; lib/validation/ledger-budgets.ts present. Executors re-verify at dispatch.
  • Identity hygiene: public-track artefact. The denylist is referred to generically throughout; zero denylist tokens herein; guard fixtures are synthetic only (AC-I).

0. Ledger reconciliation + decomposition decisions

Section titled “0. Ledger reconciliation + decomposition decisions”
  • Records {90.1}{90.4} are the spec chain (1–3 done; 4 closes with this artefact). New implementation records number 5–23 — 19 records; Task total 23 of the 25-record soft cap. Approaching the cap: any further ID-90 record needs Orchestrator review; spillover is a Task-split signal.
  • Grouping by file-ownership + TECH change-item seams, not micro-slices: U2+U3 share the gate-hook surface (record 7); U5+U6 share the mutation primitives (record 9); U7+U8 are small per-file extensions (record 10); P3 splits into R1–R3 (ordered code chain, record 22) and R4–R6 (tests/docs/evidence, record 23).
  • U11 kept as one record (13): test-only, no production-code risk. A per-suite split was considered and rejected to preserve cap headroom; the Orchestrator may sub-batch within the record if the executor session runs long.
  • Sibling-only dependency discipline verified: every dependencies[] entry below references ids 4–22 within ID-90. Every cross-Task gate ({68.30} Gate-2, {68.27} holdback, OQ-3 private home, OQ-8 referent re-point) is details prose, never deps[]. No cross-Task Subtask dependency was needed; if execution surfaces one, the Executor stops and escalates per the forcing function (§4).

1. Phase map (TECH §Migration plan ↔ subtask ids)

Section titled “1. Phase map (TECH §Migration plan ↔ subtask ids)”
PhaseWhereTECH change items (internal order)Subtask recordsExit gate
P0task-view repo — parallel-cmux sub-track, zero KH impactU0 → U1 → {U2, U3, U4} → {U5, U6, U7, U8} → U9 → U10 → U11 → U125 → 6 → {7 ∥ 8} → {9 ∥ 10} → 11 → 12 → 13 → 14AC-P0 (named in record 14)
P1KH, flag OFFK1 ∥ K6 ∥ {K2 → K3 → K4} → K515 ∥ 16 ∥ {17 → 18 → 19} → 20AC-P1 (named in record 20)
P2KH, flag ON defaultF1 + soak21AC-P2 (named in record 21)
P3KH retirement + S2-iR1 → R2 → R3, then R4 → R5 → R622 → 23AC-P3 + AC-H1(i–iii) + AC-H2 (named in record 23)

Phase-boundary gates AC-P0…AC-P3 are Orchestrator-owned between waves — each boundary record (14, 20, 21, 23) carries the PRODUCT gate text reference in its details; no executor self-certifies a phase exit.

idTitlePhaseSurfaceDeps
5P0-U0 — task-view schema re-vendor + budgets/umbrellas vendorP0task-view repo4
6P0-U1 — conforming serialisation port into patch-server write pathsP0task-view repo5
7P0-U2/U3 — budget + record-set gates ported server-sideP0task-view repo6
8P0-U4 — client-name guard (de-ID gate) with JSON denylist parserP0task-view repo6
9P0-U5/U6 — subtask CRUD + auto-id + create defaults; append opP0task-view repo7, 8
10P0-U7/U8 — promote third leg; umbrellas document kindP0task-view repo7, 8
11P0-U9 — multi-document daemon: slug routing, mutex, lifecycle flagsP0task-view repo9, 10
12P0-U10 — mutation body overrides + response warnings + dryRunP0task-view repo11
13P0-U11 — upstream test ports + relocated guard suite + concurrencyP0task-view repo12
14P0-U12 — cut tag v0.4.0-task-view + AC-P0 exit recordP0task-view repo (orchestrator-direct)13
15P1-K1 — pin bumps: TASK_VIEW_TAG v0.4.0 across ci.yml, vendor-drift, READMEP1KH14
16P1-K6 — umbrellas.json normalisation + serialiseUmbrellas flip (one commit)P1KH14
17P1-K2 — transport client: scripts/ledger-server-client.tsP1KH14
18P1-K3 — lifecycle manager: scripts/ledger-server-lifecycle.tsP1KH17
19P1-K4 — façade flag branch: KH_LEDGER_SERVER + ServerIntent at 12 call sitesP1KH18
20P1-K5 — differential parity harness + CI step (AC-P1 boundary)P1KH15, 16, 19
21P2-F1 — default flip + live-session soak + rollback drill (AC-P2)P2KH (orchestrator-direct, session-spanning)20
22P3-R1/R2/R3 — retirement chain: direct-path removal, deletions, drift shrinkP3KH21
23P3-R4/R5/R6 — test migration, docs pass, cutover journal (AC-P3/H1/H2)P3KH22

3. Wave/dispatch guidance (cmux sub-track)

Section titled “3. Wave/dispatch guidance (cmux sub-track)”

P0 — every record 5–14 executes in the task-view repo. Each P0 details carries the EXECUTION SURFACE contract verbatim: work at the operator’s task-view checkout (github.com/liam-jons/task-view), NOT the KH repo; KH is read-only reference for porting sources; out-of-tree git via --git-dir/--work-tree or cd-subshell; commits stay local — the Orchestrator reviews, pushes and tags. A P0 executor that finds itself editing KH files must STOP and escalate (brief-composition defect per Inv 10).

  • Wave A: record 5 (solo — foundation; everything imports its vendored modules).
  • Wave B: record 6 (solo — the largest single slice; all gates assert on its bytes).
  • Wave C: records 7 ∥ 8 — parallelisable as separate terminals, but both wire into the four mutating handler bodies: record 7 owns the shared gate-chain hook seam; record 8 registers into it. Merge order 7 → 8 (or run sequentially in one terminal).
  • Wave D: records 9 ∥ 10 — small overlap on patch-apply.ts (9 widens FieldPatch; 10 adds the umbrellas walk). Merge order 9 → 10.
  • Waves E–G: 11 → 12 → 13, strictly sequential (routing/mutex pervades patch-server; envelope fields wire the gates; the test ports close the phase).
  • Record 14: orchestrator-direct — review the local commit chain, push, cut v0.4.0-task-view, write the AC-P0 exit record (any P1-deferred gap named explicitly).

P1 — KH records; normal worktree discipline (isolation worktree; first action git fetch origin canonical-pipeline-setup && git reset --hard origin/<branch>; Orchestrator cherry-picks, never merges). All five carry code-intel executor blocks.

  • Wave H: 15 ∥ 16 ∥ 17 (three independent lanes; record 15 is orchestrator-direct-eligible — a 3-file pin bump).
  • Then 18 → 19 (chain on the same transport seam), then Wave I: record 20 (the AC-P1 boundary record).

P2 — record 21 is orchestrator-direct and session-spanning: the F1 flip is one line; the soak evidence accrues across ≥1 full live SDLC session and is journalled into the record as it lands. Cannot be pre-scheduled (§4).

P3 — records 22 → 23 strictly sequential, dispatched only after the AC-P2 evidence set is complete. Single executor each (or one executor running both in order); record 22 is an ordered three-commit chain with full bun run test green after each commit.

#Risk / holdClassHandling
1AC-H1(iv) HOLDS on OQ-3 (post-cutover private home for ledgers + mirrors + parity-gate re-home — Liam + Orchestrator decision). AC-H1 cannot complete before that decision is recorded.HOLDRecord 23’s R6 journal states the hold explicitly; {68.30} stays blocked on AC-H1 meanwhile. Releasing OQ-3 is outside ID-90.
2AC-P2 soak is session-boundary-bound — it rides a live SDLC session and cannot be pre-scheduled.SchedulingRecord 21 stays in_progress across the boundary; evidence journalled incrementally; Orchestrator gates P3 on the complete set.
3Upstream tag v0.4.0 cut (record 14 / U12) gates every P1 record.SequencingEncoded as deps on 14 for all of 15–17; AC-P0 is the Orchestrator’s phase gate.
4Shared-file contention upstream (patch-server.ts handler bodies; patch-apply.ts).Merge§3 merge-order discipline: 7 → 8 and 9 → 10; record 7 owns the gate-chain seam.
5mtime millisecond-granularity residual while flag-OFF and flag-ON writers mix (P1–P2 window).AcceptedEqual to today’s CLI-vs-CLI hazard, never worse (TECH §Risks); the phased flip minimises the window; the U9 mutex closes it intra-daemon.
6Vendored-schema drift (found live: upstream parse helper lacks budget soft-warns).CoveredRepaired by record 5; record 15’s vendor-drift diff verifies at the new tag.
7Identity hygiene across a public-track repo.GateAC-I grep over every ID-90 artefact; synthetic guard fixtures only (records 8, 13, 20); rejection surfaces redacted by design (invariant 32).
825-record soft cap: 23/25 after this PLAN.CapacityNo further ID-90 records without Orchestrator review; spillover signals a Task split.
9Cross-Task referents: {68.30}/{68.27} consume record 23’s R6 evidence; ID-68 records still say “ID-20” (OQ-8).BoundaryProse-only references — never deps[]. OQ-8 re-point is the Orchestrator’s action before {68.30} dispatch. Record 22 must NOT git-rm any ledger JSON/mirror (that is {68.30}‘s move).
10Sibling-only escalation path.Forcing functionNone needed at decomposition. If execution surfaces a cross-Task Subtask dep, the Executor/Orchestrator escalates for a Task split/merge — the constraint is never bent.
PhaseRecordsExecutor effortElapsed shape
P09 executor + 1 orchestrator action~18–26 h (U1, U9, U11 are M–L; others S–M)~2–3 sub-track sessions with Waves C/D parallel
P15 records (1 orchestrator-eligible)~8–12 h~1–2 sessions
P21 record~1 h active≥1 full SDLC session elapsed (soak-bound)
P32 records~5–7 h~1 session
Total19 records~30–45 h agent effort~4–6 elapsed sessions (P2 soak dominates elapsed time)