Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a053ff-1d6f-7fe2-ac1c-a6eb40a42a0c
558 lines
30 KiB
Markdown
558 lines
30 KiB
Markdown
---
|
||
id: STATE-WP-0079
|
||
type: workplan
|
||
title: "State Hub retirement strangler and disposition execution"
|
||
domain: infotech
|
||
repo: state-hub
|
||
status: blocked
|
||
owner: codex
|
||
topic_slug: infotech
|
||
created: "2026-08-09"
|
||
updated: "2026-08-31"
|
||
parent_project: prj-state-hub-retirement
|
||
parent_workplan: SHR-WP-0001
|
||
related:
|
||
- STATE-WP-0074
|
||
- SHR-INV-0001
|
||
- RMGR-WP-0001
|
||
- HUB-WP-0004
|
||
state_hub_workstream_id: "ed077b62-7048-5752-bf65-f90471f45854"
|
||
---
|
||
|
||
# State Hub retirement strangler and disposition execution
|
||
|
||
## Goal
|
||
|
||
Execute the **keep/move/replace/retire** dispositions from
|
||
`prj-state-hub-retirement/inventory` via strangler adapters and owner handoffs,
|
||
without adding new permanent authorities here. End state: freeze window with no
|
||
normal traffic, then archive.
|
||
|
||
## Dual-run handoff (RMGR-WP-0002)
|
||
|
||
Repo Manager Stage B dual-run is available:
|
||
|
||
- Flags: `RM_WRITEBACK`, `RM_RECONCILE`, `RM_PILOT_REPOS` (see `repo-manager/docs/dual-run.md`)
|
||
- SH adapter: `api/services/repo_manager_dual_run.py` (PATCH `/tasks` + C-15 writeback + reconcile proxy)
|
||
- Evidence: `repo-manager/docs/evidence/wp0002-completion.md`
|
||
|
||
Expand pilot list here as cutover progresses; do not add new checkout mutators in State Hub.
|
||
|
||
## Freeze policy for new scope
|
||
|
||
```task
|
||
id: STATE-WP-0079-T01
|
||
status: done
|
||
priority: high
|
||
state_hub_task_id: "3e8659a1-54bd-5329-bfee-24fdaca5374d"
|
||
```
|
||
|
||
Document and enforce: changes during retirement must preserve compatibility,
|
||
enable extraction, reduce scope, or fix operational risk — not establish new
|
||
permanent ownership (INTENT retirement status).
|
||
|
||
**Result (2026-08-20):** `policies/retirement-freeze.md`, following the existing
|
||
`policies/` convention. States the four admissible reasons, the inadmissible
|
||
case (new permanent ownership here), and the operative test — *where does this
|
||
live after cutover?* — since most inadmissible changes are otherwise good
|
||
changes. Uses `STATE-WP-0080`'s retarget as the worked example.
|
||
|
||
**Enforced by review, not by new automation.** A freeze-checker built inside
|
||
State Hub would be new permanent automation in the component being retired, so
|
||
the policy would violate itself. Gates attach to points where changes are
|
||
already reviewed: new workplan goal statements, non-trivial task starts, and
|
||
slice execution. New tables, routes, or MCP tools carry a presumption against
|
||
and are the one hard stop.
|
||
|
||
## Capability strangler plan
|
||
|
||
```task
|
||
id: STATE-WP-0079-T02
|
||
status: done
|
||
priority: high
|
||
state_hub_task_id: "fcf280dd-cf42-5c41-bd55-69b4b409db3b"
|
||
```
|
||
|
||
Group SHR-INV-0001 items into cutover slices (repo/work → repo-manager;
|
||
messages/progress/projections → hub-core; catalogs → owners; retire aliases).
|
||
Per slice: adapter flag, owner API, rollback.
|
||
|
||
**Result (2026-08-19):** `docs/retirement-cutover-slice-plan.md`. All 425
|
||
inventory items assigned to 19 slices in five waves plus Keep, computed against
|
||
`state-hub-disposition.yaml` rather than hand-counted. Each slice carries an
|
||
`RM_SLICE_*` flag (off/dual/owner), owner API, and rollback; Wave A reuses the
|
||
RMGR-WP-0002/0003 dual-run adapter rather than adding a mechanism.
|
||
|
||
Owner readiness verified: only **Wave A (repo-manager, 165 items)** is
|
||
executable — RMGR-WP-0001/0002/0003 are `finished`. Wave B is gated on
|
||
HUB-WP-0004 (`proposed`), D1 on OPS-WP-0003 (`proposed`), D2 on FIN-WP-0003
|
||
(`proposed`). Recommended first cut is A3 (registers), lowest blast radius.
|
||
|
||
Two findings for T04/T05: the 9 `ops_dependency` items carry no capability and
|
||
cannot be strangled behind a flag — they resolve at the T06 freeze window; and
|
||
the legacy-meter review window is 8 hours despite `cadence: weekly`, which is
|
||
not sufficient evidence to retire high-volume `/workstreams/` interfaces (E2).
|
||
|
||
## Register CLI and GOAL.md support
|
||
|
||
```task
|
||
id: STATE-WP-0079-T03
|
||
status: done
|
||
priority: medium
|
||
state_hub_task_id: "757bad31-b5d9-5ff7-b33e-d8c1dfb1bcde"
|
||
```
|
||
|
||
Adapt `statehub register` / scaffolding so `prj-` repos with `GOAL.md` and
|
||
`repo_flavor: project` are valid without inventing durable-product `INTENT.md`
|
||
(residual from SHR-WP-0001-T01).
|
||
|
||
**Result (2026-08-19):** Implemented by `STATE-WP-0080-T01/T02`. Project
|
||
flavor is detected from classification, `GOAL.md`, or the `prj-` slug; a repo
|
||
with an existing `GOAL.md` is registered without durable scaffolding, while a
|
||
fresh project delegates scaffolding to `rmgr scaffold`. The focused State Hub
|
||
registration suite passes (`20 passed`).
|
||
|
||
## Execute move/replace slices
|
||
|
||
```task
|
||
id: STATE-WP-0079-T04
|
||
status: wait
|
||
priority: high
|
||
state_hub_task_id: "3a454438-1955-547f-a491-8eab7cd25710"
|
||
```
|
||
|
||
Implement strangler handoffs coordinated with RMGR-WP-0001 and HUB-WP-0004.
|
||
Compatibility tests for each dispositioned route family.
|
||
|
||
**Owner-readiness correction (2026-08-20):** T02's slice plan marked all 167
|
||
repo-manager items receivable because RMGR-WP-0001/0002/0003 are `finished`.
|
||
That reads readiness off workplan status, which is too coarse. Verified against
|
||
`repo-manager/src/repo_manager/`: those workplans delivered work-record
|
||
dual-run, repository observation, and scaffolding. `parse/` holds only
|
||
`workplan.py`, and the source tree has **no** reference to `sbom`, `repo_goal`,
|
||
`contribution`, `technical_debt`, or `extension_point`.
|
||
|
||
So only **A1 (partial) and A2** are receivable — 86 items, not 165. A3
|
||
(registers, 49), A4 (UI, 22) and A5 (topic spine, 8) have no owner-side surface
|
||
at all, and RMGR-WP-0004/0005 do not cover them.
|
||
|
||
**Critical path is now repo-manager-side**, not here: a repo-manager workplan
|
||
must build the register, UI, and topic surfaces before 79 Wave A items can move.
|
||
Building them in State Hub is inadmissible under `policies/retirement-freeze.md`
|
||
— it would be new permanent ownership in the component being retired.
|
||
|
||
**A2 checked the same way (2026-08-20):** the State Hub adapter exposes exactly
|
||
three operations — `rm_update_task_status`, `rm_reconcile`, `rm_scaffold`. There
|
||
is no adapter for workplan CRUD, intake, decision, dependency, or human-flag
|
||
records, and no repo-manager parser for them either. A2 therefore splits into
|
||
**A2a** (task status + reconcile, ~6 items, receivable) and A2b–A2e (~32 items,
|
||
not receivable).
|
||
|
||
**A2a is the only slice in the whole plan executable today.** Its next step is
|
||
operational rather than code: `rmgr dual-run-status` shows dual-run entirely off
|
||
(`config_exists: false`, writeback/reconcile false, no pilot repos; the 23
|
||
metered mutations are RMGR-WP-0002/0003 pilot residue). Moving A2a from `off` to
|
||
`dual` means creating `~/.repo-manager/dual-run.yaml`, enabling `RM_WRITEBACK`
|
||
and `RM_RECONCILE` for one pilot repo, and watching the mutation meter for
|
||
divergence. Reversible by clearing the flags; needs an operator decision because
|
||
it changes how live task writes flow.
|
||
|
||
Net: of 425 inventory items, roughly **6 can move today**. The retirement is
|
||
gated almost entirely on owner-side capability in `repo-manager` and `hub-core`.
|
||
|
||
**Readiness update (2026-08-21):** RMGR-WP-0008 is finished, HUB-WP-0004 is
|
||
finished, and the cutover slice plan now records the corrected receiving/UI
|
||
boundaries. Workplan/register/classification adapters and compatibility tests
|
||
exist; execute them by slice rather than relying on this earlier readiness
|
||
snapshot.
|
||
|
||
**Deterministic-identifier compatibility sub-slice (2026-08-21):** fleet owner
|
||
declared namespace `helixforge`. Repo Manager's sealed plan covers 242 live
|
||
records across 42/42 eligible repositories with zero collisions, but apply is
|
||
not yet authorized. State Hub uses workplan/task UUIDs as primary keys referenced
|
||
by progress, decisions, dependencies, token events, launches, and other tables;
|
||
those foreign keys do not use `ON UPDATE CASCADE`. This task owns the temporary
|
||
transactional projection migration, durable old-id aliases, rollback rehearsal,
|
||
and compatibility evidence needed by RMGR-WP-0005-T04. Do not rewrite repository
|
||
UUID fields until that sub-slice passes in isolated PostgreSQL.
|
||
|
||
**Identifier projection gate implemented and rehearsed (2026-08-22):** Alembic
|
||
revision `b8d4f0a2c6e1` adds durable old→new alias provenance and converts all 20
|
||
foreign keys into `workplans.id` / `tasks.id` to `ON UPDATE CASCADE`, while
|
||
retaining their existing delete behavior. The internal executor verifies the
|
||
Repo Manager plan seal, `helixforge` namespace, UUIDv5 derivation, repository
|
||
membership, source presence, target absence, and alias consistency before a
|
||
repository-atomic apply. Reverse runs task-first/workplan-second and retains the
|
||
aliases as `reversed`; plan entries with `action: assign` are deferred to normal
|
||
file reconciliation because there is no old projection row to rewrite.
|
||
|
||
Isolated PostgreSQL evidence: migration upgrade produced 20/20 update-cascade
|
||
constraints plus the alias table; downgrade restored 20/20 no-action update
|
||
constraints and removed the table. Service tests cover cascades through task
|
||
parentage, progress, token accounting and dependency edges, forward/reverse
|
||
alias state, and all-or-nothing failure (`3 passed`). Full State Hub regression:
|
||
`622 passed`. No live database migration or repository UUID rewrite was run.
|
||
The remaining gate is an operator-approved pilot ordering the central database
|
||
transaction and authoritative file rewrite/reconciliation as one recoverable
|
||
cutover unit.
|
||
|
||
**Repo Manager pilot executed (2026-08-22):** the workstation projection was
|
||
the only instance holding `RMGR-WP-0005`; the production/registrar projection
|
||
had no matching row. A verified 4.4 MiB preapply PostgreSQL dump was retained at
|
||
`/tmp/state-hub-rmgr-wp-0005-pilot-preapply.dump`. The live schema advanced to
|
||
`b8d4f0a2c6e1`, then six workplan/task primary keys migrated in one transaction.
|
||
All 12 child-task links, 12 workplan progress links, one decision link, and
|
||
three task progress links followed. Six aliases are `applied`; all old rows are
|
||
absent and all new rows present. Repo Manager committed the matching file
|
||
rewrite in `5de754a`; two consistency runs produced a fresh, non-stale index and
|
||
the new workplan API lookup returns 200 while the old lookup returns 404.
|
||
|
||
The absent registrar row exposed the final rebuild gap before remote ingestion:
|
||
create schemas did not accept authoritative UUIDs and consistency classified a
|
||
missing derived row as an unfixable stale reference. The projection rebuild path
|
||
now accepts file UUIDs, derives IDs when a live file has none, and registers a
|
||
missing derived workplan/task without rewriting the authoritative identifier.
|
||
Focused rebuild/API tests and the full State Hub suite pass (`624 passed`).
|
||
|
||
**Empty-projection rebuild proof (2026-08-22):** consistency now has an explicit,
|
||
registrar-only `--bootstrap-empty-projection` mode. It is limited to one local
|
||
repository, proves the target has zero projected workplans before mutation, and
|
||
preserves authoritative UUIDs for workplans, tasks, intakes, and decisions.
|
||
Repo Manager's governed wrapper additionally verifies every expected UUID and
|
||
fails on authoritative checkout mutation. A fresh disposable database rebuilt
|
||
all 9 Repo Manager workplans, 62 tasks, and 2 intakes; a second read-only pass
|
||
reported zero issues and 9/9 bindings. State Hub commits `03c7924` and
|
||
`059de93`; evidence is recorded in Repo Manager under
|
||
`docs/evidence/RMGR-WP-0005-isolated-rebuild-2026-08-22.md`. Hub-native history
|
||
remains a separate, unresolved centralization gate and was not copied.
|
||
|
||
**Production registrar pilot completed (2026-08-22):** a verified 4.6 MiB
|
||
custom-format dump was retained at
|
||
`/tmp/state-hub-registrar-rmgr-wp-0005-preapply.dump` (SHA-256
|
||
`01753744bc844b154900ead916f122946c5414e77f888c3e18016cae6d3d8929`). Helm
|
||
revision 10 atomically promoted image `main-697dd49`; the dry-run and live pod
|
||
both confirmed `sweep.enabled: false` with no host or SSH mounts. The production
|
||
schema advanced from `f0a1b2c3d4e5` to `b8d4f0a2c6e1`; health remained green,
|
||
all 20 relevant foreign keys use `ON UPDATE CASCADE`, and the alias table exists.
|
||
|
||
The registrar did not previously contain the logical `repo-manager` repository
|
||
or its workplans. After registering that repository, governed projection repair
|
||
created only deterministic `RMGR-WP-0005` UUID
|
||
`6dcf854e-9229-569d-90f0-2d9df235a61d` and its 12 authoritative task UUIDs.
|
||
File and production task-ID sets match exactly; the new workplan lookup returns
|
||
200, the former random UUID returns 404, and a second read-only consistency pass
|
||
has no `RMGR-WP-0005` issue. The eight other random-ID Repo Manager workplans
|
||
remain explicit non-fixable stale references in this formerly empty projection
|
||
and were not ingested. Production aliases remain empty as expected for a rebuild
|
||
rather than an in-place rewrite. Widening beyond this one-repository pilot still
|
||
requires a separate fleet cutover decision.
|
||
|
||
**Sealed pre-derivation repair interface approved with safeguards
|
||
(2026-08-23):** Repo Manager interface
|
||
`helixforge.identifiers.state-hub-sealed-projection-repair.v1` is accepted as a
|
||
temporary T04 compatibility sub-slice. The owner implementation adds
|
||
`POST /identifier-migrations/sealed-projection-repairs` and keeps ordinary C-03
|
||
refusal unchanged. Repair is limited to one explicitly named workplan and all
|
||
of its sealed `replace` task mappings; it requires the exact plan seal, clean
|
||
synchronized Git revision and source fingerprint, explicit primary
|
||
confirmation, existing repository/topic projection, and complete absence of
|
||
both the old unit and derived targets. Creation is one database transaction;
|
||
an exact retry returns a verified no-op receipt, while partial presence, source
|
||
drift, aliases, target rows, or content mismatch fail closed. Operational and
|
||
removal contract: `docs/sealed-prederivation-projection-repair.md`.
|
||
|
||
Verification: focused identifier-migration coverage passes (`13 passed`), the
|
||
ordinary consistency suite passes (`129 passed`), and the full API plus
|
||
dashboard build passes (`650 passed`). The full run retained one pre-existing
|
||
SQLAlchemy resource warning and one pre-existing dashboard link warning.
|
||
|
||
**A2a executed (2026-08-20) — first live cutover slice.** Dual-run is on for the
|
||
pilot repo:
|
||
|
||
- `~/.repo-manager/dual-run.yaml` installed from
|
||
`repo-manager/config/dual-run.pilot.example.yaml` — `writeback: true`,
|
||
`reconcile: true`, `writeback_push: false`, `pilot_repos: [repo-manager]`
|
||
- State Hub API reloaded via its own `--reload` watcher (no service restart, the
|
||
operator's foreground `make api` was left alone)
|
||
- `statehub fix-consistency --repo repo-manager` reported
|
||
`RM dual-run reconcile ok: index=/home/worsch/repo-manager/.repo-manager/index.json`
|
||
- mutation meter grew 23 → 24 with
|
||
`{"kind": "reconcile", "repo_slug": "repo-manager", "workplan_count": 8, "task_count": 53, "record_count": 61}`
|
||
|
||
**Divergence check:** rmgr's index holds 8 workplans; the hub has
|
||
`rmgr-wp-0001`–`0007` registered. The single-item delta is `RMGR-WP-0008`, whose
|
||
C-06 registration was skipped because this instance is not the identifier
|
||
registrar (ADR-007 interim). That is a known registrar limitation, **not**
|
||
dual-run divergence — rmgr correctly indexed the file that exists on disk.
|
||
|
||
Slice state: **A2a is `dual`, not `owner`** — the hub remains authoritative and
|
||
rmgr executes checkout mutation alongside it. Promotion to `owner` needs a full
|
||
consistency-sweep cycle at `dual` with zero divergence, per this plan's adapter
|
||
rules. Rollback is `rm ~/.repo-manager/dual-run.yaml`.
|
||
|
||
### Registrar bottleneck — status check 2026-08-21
|
||
|
||
**The registrar is reachable, and was all along.** `bridge status` shows all
|
||
seven tunnels `connected` and LIVE, including `state-hub-primary`. It binds
|
||
`[::1]:8000` — IPv6 localhost — while the workstation API listens on
|
||
`127.0.0.1:8000` (IPv4). Same port number, different stacks, so a `127.0.0.1`
|
||
probe silently hits the local hub and looks like the tunnel is down. Anything
|
||
checking registrar reachability must use the bracketed IPv6 form.
|
||
|
||
**But the two databases have diverged badly:**
|
||
|
||
| | workstation (`127.0.0.1:8000`) | registrar (`[::1]:8000`) |
|
||
| --- | --- | --- |
|
||
| workplans | 987 | 649 |
|
||
| tasks | 5 710 | 4 037 |
|
||
| decisions | 119 | 80 |
|
||
|
||
The registrar is **338 workplans and 1 673 tasks behind**. It also runs older
|
||
code — its `/state/summary` still returns `open_workstreams` where the
|
||
workstation returns `open_workplans`, so it predates the terminology rename.
|
||
|
||
This is exactly the `ADR-007` defect `RMGR-WP-0005` describes, at fleet scale:
|
||
two instances over two databases, each minting database-local primary keys into
|
||
shared git artifacts.
|
||
|
||
**A queue has formed.** Ten unread messages to `state-hub`, nine of them
|
||
registrar sync requests from three agents (`agentic-resources`, `glas-harness`,
|
||
`kaizen-agentic`), all dated 2026-08-20 — plus this repo's own `RMGR-WP-0008`.
|
||
Agents fleet-wide are now blocked on identifier registration.
|
||
|
||
**The dependency chain, re-checked:**
|
||
|
||
- `RMGR-WP-0004-T08` (prefix uniqueness enforcement) — **`done`** 2026-08-18
|
||
- `RMGR-WP-0004-T09` (assign shared prefixes) — executed 2026-08-17 as an
|
||
authorized exception, still `wait`, with one stated residual: *"Not yet
|
||
reconciled — the workstation is not the registrar"*
|
||
- `RMGR-WP-0005-T03` (deterministic UUIDv5 derivation) — still `wait`, but its
|
||
stated blocker `RMGR-WP-0004-T08` **has closed**
|
||
|
||
T03 is the permanent fix: derived identifiers make writeback idempotent, so any
|
||
number of hubs write identical bytes and the queue disappears. Its formal gate is
|
||
clear. Its *substantive* gate is not — `ADR-007` § Migration option 2 lets
|
||
historical files keep colliding identifiers (`CUST-WP`, `RAILIANCE-WP`, and
|
||
`PRJ-WP` in `prj-forgejo-org-refactor` all still present in the 2026-08-18 scan),
|
||
and deriving UUIDv5 from a non-unique identifier manufactures collisions rather
|
||
than removing them. That tension needs a ruling before T03 can start.
|
||
|
||
|
||
**Inherited (2026-08-19) from `STATE-WP-0080-T04`:** this slice now also owns
|
||
deletion of the templating path in `statehub_register.py` — `INTENT.md`
|
||
generation, the `AGENTS.md` / `CLAUDE.md` / `.custodian-brief.md` templates,
|
||
`project_rules/`, and bootstrap-workplan generation. The code is dead-but-present:
|
||
project repos are already routed to `rmgr scaffold`. Gate the deletion on
|
||
`RMGR-WP-0004-T06` proving byte-identical durable output and idempotent
|
||
re-scaffolding.
|
||
|
||
**Brief compatibility repair (2026-08-23):** the surviving consistency
|
||
generator degraded `the-custodian` to `Domain: (unknown)` and emitted
|
||
`get_domain_summary("")` even though `GET /repos/the-custodian` correctly
|
||
projected `domain_slug: infotech`. Active workplans can legitimately have no
|
||
topic, so topic inference is not authoritative. The generator now prefers the
|
||
repository projection and retains topic lookup only for legacy API responses
|
||
that omit `domain_slug`. Two regression tests cover both paths; all 131
|
||
consistency-check tests pass. This is a compatibility fix until the generator
|
||
moves or retires, not new permanent State Hub authority.
|
||
|
||
**Ad-hoc identity compatibility repair (2026-08-23):** the surviving project
|
||
instruction templates prescribed fleet-wide `ADHOC-YYYY-MM-DD` identifiers.
|
||
Activity Core and Net Kingdom used that form on the same day, and deterministic
|
||
derivation correctly refused the second record. Templates and the legacy ADR
|
||
validator now accept and prescribe `{WP_PREFIX}-ADHOC-YYYY-MM-DD` while keeping
|
||
the daily filename unchanged. A regression test covers the filename/id pairing.
|
||
This prevents new collisions without making State Hub the long-term convention
|
||
owner.
|
||
|
||
**Owner-gate reconciliation 2026-08-31.** The previously open receiving-side
|
||
gates have advanced materially: RMGR-WP-0005 finished the deterministic
|
||
identifier migration, HUB-WP-0005 put all hub-core route and writer groups into
|
||
production ownership with exercised rollback, and ACTIVITY-WP-0029 finished
|
||
the schedule, consistency-sweep, interaction-event, and execution-boundary
|
||
handoffs. Those are durable owner records and no longer block this task.
|
||
|
||
They establish receiving-side readiness only. They do not, by themselves,
|
||
prove that State Hub callers and route families have switched or that the
|
||
required parity, rollback, and production receipts exist.
|
||
|
||
**D1 receiving contract completed 2026-08-31.** OPS-WP-0003 is finished with
|
||
all three tasks done. Ops Hub now publishes the reviewed
|
||
`capability.operations.ops-hub` and
|
||
`capability.operations.service-catalog` owner package, passes hub-core's
|
||
schemas/catalog and all eight implemented conformance checks, and passes the
|
||
post-cutover public `/api/v2` gate. Framework checks absent from contract 0.1.0
|
||
are live owner residual `HUB-WP-0009` / State Hub UUID
|
||
`0d6e94f3-fd15-5f57-af41-60f0b862da5e`; they do not return D1 ownership here.
|
||
|
||
**D2 receiving contract completed 2026-08-31.** FIN-WP-0003 is finished with
|
||
all three tasks done. `railiance-fabric` revision `113445d` now publishes the
|
||
direct `financial-fabric-v1` authority export, deterministic accepted-snapshot
|
||
revision provenance, graph edge/summary reads, and regression coverage.
|
||
Fin-hub revisions `debe67e` / `5fe943d` publish the consumer contract and
|
||
executable schema/content-hash/count/provenance gate. Retirement-project
|
||
revision `1812170` corrects all ten Fabric items from `fin-hub/move` to
|
||
`railiance-fabric/replace`; hub-core projection is explicitly deferred.
|
||
|
||
The receiving contract is ready, but the production cutover is not. The first
|
||
gate run correctly returned no-go: the authority has 131 nodes / 117 edges,
|
||
while State Hub has 49 / 58, with a different content hash and null source
|
||
revision/path/export time. T04 therefore remains `wait` on selecting and
|
||
refreshing one authority snapshot into the dual-read window, obtaining a green
|
||
`finhub fabric-cutover-check`, recording route-switch/rollback receipts for the
|
||
remaining repo-manager/hub-core/activity-core/ops-hub families, and explicit
|
||
authorization for production writer changes. It must resume from a fresh
|
||
caller scan, not from the obsolete 2026-08-20 snapshot.
|
||
|
||
**D2 dual-read evidence completed 2026-08-31.** The deterministic authority
|
||
snapshot is now the active `railiance01` read model at import
|
||
`47e5358e-d04b-4969-99a2-ca88423ad054`: 131 nodes, 117 edges, 2 actors, 1
|
||
fabric, 0 unresolved, content hash `caae6679…`, snapshot-set revision
|
||
`991bca29…`. `finhub fabric-cutover-check` is green on every schema, content,
|
||
count, and provenance check; exact re-ingest is idempotent. A receiver contract
|
||
drift/column-width defect was fixed in `cf40c7b` and deployed with migration
|
||
`b5e6f7a8c9d0` as Helm revision 56. Immutable-import activation was added in
|
||
`cdff3b7` and deployed as revision 57. Production rollback to retained import
|
||
`f844733d…` (49/58) and roll-forward to `47e5358e…` (131/117) were both
|
||
exercised, followed by another green gate.
|
||
|
||
The fresh named-repo caller scan found no runtime consumers of
|
||
`/fabric/graph*`; only contracts, docs, and retirement inventory matched. The
|
||
owner service is still workstation-local and its accepted-snapshot freshness is
|
||
not automated, so hosted runtime/persistence/auth/freshness and the eventual
|
||
direct route are live owner residual `RAIL-FAB-WP-0028`. Evidence:
|
||
`docs/evidence/STATE-WP-0079-d2-dual-read-20260831.md`. T04 remains `wait` on
|
||
the non-D2 repo-manager/hub-core/activity-core/ops-hub route receipts and the
|
||
explicit writer-change authorization already stated above.
|
||
|
||
## Retire legacy surfaces
|
||
|
||
```task
|
||
id: STATE-WP-0079-T05
|
||
status: wait
|
||
priority: medium
|
||
state_hub_task_id: "f6cf8c01-eb59-5ca8-a541-23928d4a000c"
|
||
```
|
||
|
||
Complete retirement of suggestions, workstream aliases, and other `retire`
|
||
inventory items once meters/callers allow. Keep historical rows archive-readable.
|
||
|
||
**Blocker identified (2026-08-20):** the legacy-meter evidence this task gates
|
||
on was being captured over an 8-hour band, not a week —
|
||
`capture_legacy_meter_evidence.py` fell back to `hours=8` whenever `--days` was
|
||
omitted, so 39 of 40 captures sampled only 06:00Z–14:00Z. Interfaces called
|
||
outside that band read as unused. Three candidates on the 2026-08-19 capture had
|
||
live callers, including `GET /tasks/?workstream_id` (seen 2026-08-18).
|
||
|
||
Script default corrected to `days=7`; corrected capture
|
||
`docs/evidence/legacy-meter-weekly-review-20260820.json`.
|
||
|
||
**Candidate rule tightened (2026-08-20):** `_retirement_state` now requires a
|
||
quiet period scaled to all-time call volume (`RETIREMENT_QUIET_LADDER`: 7d under
|
||
100 calls, 30d under 10 000, 60d above). On the 2026-08-20 capture this makes 15
|
||
of 19 legacy interfaces retirable — all `workstream` MCP tools, the `state://`
|
||
resource, and the low-volume REST aliases — while holding the three six-figure
|
||
read paths (`GET /workstreams/`, `GET /workstreams/{id}`,
|
||
`GET /workstreams/{id}/dependencies/`) and `GET /tasks/?workstream_id`, which
|
||
still has live traffic. Covered by 7 new tests in `tests/test_legacy_meter.py`.
|
||
|
||
**Slice E2 executed (2026-08-20):** the 15 evidenced interfaces are retired in
|
||
the legacy meter — all four `workstream` MCP tools, the `state://` resource, and
|
||
the low-volume REST aliases including `PATCH /workstreams/{id}` (571 calls),
|
||
`POST /workstreams/` (824) and `POST /workstreams/{id}/dependencies/` (4 971).
|
||
Meter now reads 16 retired / 4 legacy, 0 outstanding candidates. Evidence:
|
||
`docs/evidence/legacy-meter-weekly-review-20260820.json`.
|
||
|
||
Retirements are journalled fleet-side at
|
||
`the-custodian/docs/retired-legacy-interfaces.md` — deliberately outside this
|
||
repo, since State Hub is being archived and the record must outlive it.
|
||
|
||
**Remaining work for this task:** the 4 held interfaces
|
||
(`GET /workstreams/`, `GET /workstreams/{id}`,
|
||
`GET /workstreams/{id}/dependencies/`, `GET /tasks/?workstream_id`) clear as
|
||
their quiet counters run; earliest is 18 more silent days. Re-capture before
|
||
deciding — the ladder evaluates at review time. **Slice E1 part-executed (2026-08-20):** `suggestion-backlog` history archived
|
||
to `the-custodian/docs/archived-suggestion-backlog.md` — 10 suggestions, 10
|
||
notes, 5 bumps, all `declined` in the 2026-07-21 intake migration, none
|
||
promoted. Mutations already 410 since `CUST-WP-0061-T06`; reads were open only
|
||
to keep that history reachable, which the archive now replaces.
|
||
|
||
**E1 removal executed the same day:** the 8 read routes 410 with a pointer to
|
||
intake and the archive, the 6 MCP tools are removed outright, the 5
|
||
`/suggestions` write-idempotency rules are dropped, and the dashboard page is
|
||
deleted with nav, `reference.md` and `wsjf-triage.md` updated;
|
||
`dashboard/src/docs/suggestions.md` is now the archive pointer. Tables remain
|
||
for the T06 dump. Two tests that pinned the old read-live behaviour were
|
||
rewritten to pin the retirement contract.
|
||
|
||
Naming trap for cutover: `ui-feedback.md` / `todo.md` "suggestions" are
|
||
Shift+click dashboard feedback backed by `technical_debt`, **not** this
|
||
capability. Untouched.
|
||
|
||
**E3 (`dashboard-meta`) is `/ui-feedback`** — that same feedback surface. Owner
|
||
is `state-hub-until-cutover` and it is still in use, so it retires at the T06
|
||
freeze window, not now.
|
||
|
||
Then `dashboard-meta` (E3, 1); `legacy-meter` itself (E4, 9) retires last,
|
||
being the instrument.
|
||
|
||
**Execution launch-request defect closed (2026-08-23):** the surviving
|
||
`POST /execution/launch-requests` route claimed Activity Core pickup after that
|
||
mapping was explicitly retired by `ACTIVITY-WP-0029-T04`. New submissions now
|
||
return 410 with the repository-file / ActivityDefinition+ops_run replacement;
|
||
`GET /execution/semantics` explicitly says launch requests are not accepted,
|
||
that Activity Core does not consume them, and that legacy `launching` does not
|
||
prove pickup. Historical launch rows remain readable. The two reported
|
||
requests (`7052b20f…`, `5628fe55…`) were cancelled as never consumed and their
|
||
workplans restored from `launching/immediate` to `manual/manual`.
|
||
Focused execution coverage passes (`4 passed`); the combined full regression
|
||
and dashboard build remains green (`650 passed`).
|
||
|
||
**Central meter review 2026-08-31.** The corrected seven-day review found six
|
||
replacement-verified interfaces past their volume-scaled quiet period. They
|
||
were marked retired on the sole `railliance01` primary: the old workstream
|
||
completion event subject, `DELETE /workstreams/{id}`, two low-volume SBOM
|
||
compatibility reads, `GET /workstreams/workplan-index`, and
|
||
`POST /workstreams/{id}/dependencies/`. The recapture now reports 6 retired,
|
||
9 legacy, and zero currently eligible candidates. The remaining nine include
|
||
live SBOM callers, live `GET /tasks/?workstream_id`, the three high-volume
|
||
workstream reads still inside their 60-day quiet window, and two workstream
|
||
mutations still inside 30 days. Evidence:
|
||
`docs/evidence/legacy-meter-weekly-review-20260831.json`. T05 remains
|
||
`wait`; T06 must not start.
|
||
|
||
The nine held interfaces are explicitly owned by this task until the meter
|
||
allows retirement; they are not untracked prose residuals. Three SBOM reads and
|
||
`GET /tasks/?workstream_id` still had calls in the seven-day review window.
|
||
Three high-volume workstream reads have only 9 of 60 required quiet days, while
|
||
the two workstream mutations have 14/30 and 15/30 quiet days. A future review
|
||
must recapture central-primary evidence and apply the existing volume ladder;
|
||
calendar passage alone is not retirement evidence.
|
||
|
||
## Stabilization window and archive prep
|
||
|
||
```task
|
||
id: STATE-WP-0079-T06
|
||
status: wait
|
||
priority: high
|
||
state_hub_task_id: "9230c99b-af58-5794-9291-452e619a30fa"
|
||
```
|
||
|
||
With T06 gates: zero normal read/write window, final dump, backup/restore
|
||
evidence, stop service, archive repo read-only. Residuals → live owners.
|
||
|
||
**Blocked 2026-08-31.** The sole `railiance01` primary is healthy and remains
|
||
the active coordination service, the legacy meter has live callers, and T04
|
||
still has owner-side cutovers. A freeze, final dump/restore rehearsal, service
|
||
stop, or repository archive would therefore interrupt normal work and destroy
|
||
the evidence needed by T05. T06 remains `wait` until T04 and T05 are done and a
|
||
fresh central meter demonstrates the required zero normal read/write window.
|
||
|
||
## Acceptance
|
||
|
||
- [x] Freeze policy documented
|
||
- [x] Strangler plan covers all inventory capabilities
|
||
- [x] prj-/GOAL.md register path works
|
||
- [ ] Move/replace slices evidenced with tests/counts
|
||
- [ ] Retire list closed or residual-owned
|
||
- [ ] Stabilization + archive prep ready for project retirement
|