state-hub/docs/retirement-cutover-slice-plan.md
tegwick 613477b4d2
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 2s
docs(STATE-WP-0079): cutover slice plan, close T02
Assign all 425 SHR-INV-0001 items to 19 slices across five waves plus Keep,
each with adapter flag, owner API, and rollback. Coverage computed against
the inventory rather than hand-counted.

Only Wave A (repo-manager, 165 items) is executable; B/D1/D2 are gated on
owner-side contracts still at proposed. Flags two findings for T04/T05: the
9 ops_dependency items cannot be strangled behind a flag, and the
legacy-meter weekly review window is 8h, not a week.

Also corrects the workplan status from proposed to active.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 23:44:27 +02:00

11 KiB
Raw Blame History

State Hub retirement — cutover slice plan

Workplan task: STATE-WP-0079-T02 Inventory: SHR-INV-0001 (prj-state-hub-retirement/inventory/), 425 items, v0.1.1 Created: 2026-08-19

Groups every dispositioned inventory item into an ordered cutover slice. Each slice names its adapter flag, the owner-side API that receives the traffic, and its rollback. Slices are the execution unit for STATE-WP-0079-T04.

Method

Slices are cut on capability, not on route or table, because a capability is the smallest unit with a single owner and a coherent contract. The inventory's capability field yields 51 groups; those are bundled into waves by owner, and ordered within a wave by dependency and blast radius.

Two rules constrain the ordering:

  1. A slice cannot move before its owner can receive it. Owner readiness is the owner repo's own workplan status, not an assertion here.
  2. Read-only projections move before write paths in the same capability, so a failed cutover degrades to stale reads rather than lost writes.

Owner readiness (verified 2026-08-19)

Owner Items Gating workplan Status Can receive?
repo-manager 167 RMGR-WP-0001/0002/0003 finished Yes
hub-core 128 HUB-WP-0004 runtime + extension contract proposed No
state-hub-until-cutover 55 — (keep/retire in place) n/a
activity-core 18 ACTIVITY-WP-0029 hub port alignment active Partial
ops-hub 13 OPS-WP-0003 extension contract alignment proposed No
fin-hub 10 FIN-WP-0003 fabric authority boundary proposed No
archive 30 legacy-meter evidence see Wave E Conditional
ops-bridge 2 — (keep) n/a
the-custodian 2 Yes

Only the repo-manager lane is fully unblocked today. Wave A is the whole of the near-term executable surface; everything else is correctly waiting on an owner-side contract, not on State Hub.

Adapter mechanism

Wave A reuses the dual-run strangler proven in RMGR-WP-0002/0003 rather than introducing a new mechanism:

  • Adapter: api/services/repo_manager_dual_run.py
  • Existing flags: RM_WRITEBACK, RM_WRITEBACK_PUSH, RM_RECONCILE, RM_PILOT_REPOS, RM_METER_PATH, RM_DUAL_RUN_CONFIG
  • Reference: repo-manager/docs/dual-run.md, evidence repo-manager/docs/evidence/wp0002-completion.md

New slices add a slice-scoped flag of the form RM_SLICE_<NAME> with three states — off (hub only), dual (both, hub authoritative, divergence metered), owner (owner authoritative, hub proxies). Rollback for every Wave A slice is therefore the same operation: set the slice flag back one state. No slice advances to owner until it has run a full consistency-sweep cycle at dual with zero divergence.

Waves BD must not invent hub-side adapters ahead of their owner contract. Per the T01 freeze rule, building an adapter for an owner that cannot yet receive establishes new permanent ownership here — the exact thing retirement is removing.


Wave A — repo-manager (167 items, executable now)

A1 · Repository registry — 27 items

repository-registry (24: 16 route, 7 mcp_tool, 1 dataset) · repo-reconciliation (1) · repo-doi (1) · repo-onboarding (1)

Flag RM_SLICE_REGISTRY
Owner API rmgr repo registry + classification spine
Rollback flag → dual, then off; hub tables retain rows throughout

First because every other repo-manager slice keys off repo identity, and because repo-onboarding is already delegated (STATE-WP-0080-T02, rmgr scaffold), so the slice starts partly cut over.

A2 · Work records — 59 items

work-records (20) · work-records-workplan (12) · work-records-intake (9) · work-records-decision (8, move+replace) · work-records-deps (2) · work-records-task (8, repo-manager portion)

Flag RM_SLICE_WORKRECORDS
Owner API rmgr file-backed work-record index + PATCH /tasks writeback
Rollback flag → dual; C-15 writeback already reconciles file↔DB drift

Highest blast radius in the program — this is the surface every agent session touches. Split the flag by record kind if divergence appears; do not cut the whole slice at once.

work-records-task is owner-split: the route/dataset portion is repo-manager, the job portion is activity-core (Wave C1). Cut the repo-manager portion first and leave the job dual-running.

A3 · Registers — 49 items

sbom-inventory (10) · repo-goals (9) · upstream-contributions (9) · register-technical-debt (9) · register-extension-points (6) · register-entries (6)

Flag RM_SLICE_REGISTERS
Owner API rmgr register endpoints
Rollback flag → off; these are append-mostly, so replay is cheap

Low coupling and low write volume — the natural place to prove the RM_SLICE_* pattern before A2's blast radius.

A4 · Work + repo UI — 22 items

work-coordination-ui (14, replace) · repo-ui (8)

Flag RM_SLICE_UI
Owner API owner-side dashboard; hub pages redirect
Rollback remove redirect; hub pages are unchanged behind it

replace, not move: the contract changes. Must follow A1A3, since the pages render what those slices serve.

A5 · Topic spine — 8 items

topic-spine (8, replace)

Flag RM_SLICE_TOPICSPINE
Owner API rmgr topic/classification contract
Rollback flag → off

Last in Wave A: it is a replace under a changed contract, and A1A4 read it.


Wave B — hub-core (128 items) · gated on HUB-WP-0004

HUB-WP-0004 is proposed. No hub-side adapter work until it is at least ready. Slices are listed to fix scope and order, not to start.

Slice Capabilities Items
B1 catalogs capability-catalog (18), cross-domain-registry (16) 34
B2 messaging + interface log agent-messaging (11), interface-change-log (11) 22
B3 telemetry token-telemetry (14), third-party-software-catalog (10), progress-telemetry (8) 32
B4 projections + policy state-projections (9), domain-goals (6), policy-integration (2), write-idempotency (1), event-bus (1), recently-on-scope (1) 20
B5 hub UI hub-projection-ui (14, replace), agent-integration (2), dashboard (1) 17

Order B1 → B4 → B2 → B3 → B5: catalogs and projections are read-mostly and carry the contract; messaging and telemetry are write paths; UI last.

Wave C — activity-core (18 items) · ACTIVITY-WP-0029 active

Slice Capabilities Items
C1 execution workplan-execution-queue (7, replace), task-flow-engine (6, replace) 13
C2 jobs ops-run-projection (1), repo-consistency (3), work-records-task activity-core portion (1) 5

Both are replace — schedulers move to activity-core under a different contract. C2 must follow A2, since the consistency job writes work records.

Wave D — remaining owners (25 items) · all gated

Slice Owner Capabilities Items Gate
D1 ops-hub service-catalog (9), service-catalog-ui (2) 11 OPS-WP-0003 proposed
D2 fin-hub fabric-graph (10) 10 FIN-WP-0003 proposed
D3 the-custodian kaizen-agents (2) 2 none — can go anytime

D3 is two MCP tools with no dependants; take it opportunistically.

Wave E — retire (42 items)

Slice Capability Items Gate
E1 suggestion-backlog → archive 17 caller check; no successor runtime
E2 work-records-workplan-legacy → archive 13 legacy-meter — see caveat below
E3 dashboard-meta 1 none
E4 legacy-meter itself 9 last — it is the instrument for E2

E4 retires only after every other legacy surface is closed; retiring the meter first destroys the evidence for the retirements it gates.

Caveat on E2's evidence

The 2026-08-19 review (docs/evidence/legacy-meter-weekly-review-20260819.json) reports 19 retirement candidates, all replacement_verified: true with zero calls in window. But the window is 06:00Z → 14:00Z8 hours, not the 7 days cadence: weekly implies. Several candidates have very large all-time counts (GET /workstreams/{id} 511 406, GET /workstreams/ 144 086, POST /workstreams/{id}/dependencies/ 255 865).

An 8-hour quiet window is not sufficient evidence to retire an interface at that call volume. Either the window computation is a defect or the cadence label is wrong; either way E2 should not proceed on the current evidence. Resolving this is a prerequisite, and it is worth checking before Wave A rather than after, since the same meter gates T05.

Keep — 43 items

schema-history (43 migrations, keep until cutover) plus ops-automation, connectivity (ops-bridge). Not slices: they persist until the T06 freeze window and are dispositioned by the final dump and archive.

Coverage

Computed against state-hub-disposition.yaml, not hand-counted. Every item is assigned by capability; work-records-task splits on owner.

Wave Slices Items
A repo-manager A1 27 · A2 59 · A3 49 · A4 22 · A5 8 165
B hub-core B1 34 · B2 22 · B3 32 · B4 20 · B5 17 125
C activity-core C1 13 · C2 5 18
D ops-hub / fin-hub / the-custodian D1 11 · D2 10 · D3 2 23
E retire E1 17 · E2 13 · E3 1 · E4 9 40
Keep schema-history 43, ops-automation 1, connectivity 1 45
Ops dependencies see below 9
Total 425

Wave A totals 165 rather than the owner table's 167, and Wave B 125 rather than 128: the difference is ops_dependency items, which carry no capability and so attach to no capability slice.

Ops dependencies (9 items, no capability)

Owner Disposition Items Handling
hub-core move / replace / keep 3 ride with Wave B; confirm at B4
ops-hub replace 2 ride with D1
state-hub-until-cutover retire 2 T06 freeze window
activity-core keep 1 keep to cutover
ops-bridge keep 1 keep — external dependency, survives retirement

These are infrastructure couplings (DB, scheduler, tunnel), not API surface. They cannot be strangled behind a flag and are dispositioned at the freeze window instead. Worth an explicit owner confirmation during T04 so none is discovered live at cutover.

Next actions

  1. Resolve the legacy-meter window discrepancy above — it gates E2 and T05.
  2. Implement RM_SLICE_REGISTERS (A3) first as the pattern proof.
  3. Do not open Wave B until HUB-WP-0004 reaches ready.