---
id: STATE-WP-0069
type: workplan
title: "Workplan terminology legacy retirement (State Hub)"
domain: infotech
repo: state-hub
status: finished
owner: codex
topic_slug: custodian
planning_priority: medium
planning_order: 69
created: "2026-07-08"
updated: "2026-07-08"
state_hub_workstream_id: "923bb94a-d16c-422c-b81e-16328bd7b60c"
---

# STATE-WP-0069 — Workplan terminology legacy retirement

**Parent coordination:** `the-custodian/workplans/CUST-WP-0055-workplan-terminology-fleet-refactor.md`
(T02-T01 deliverable).

**Prerequisite (finished):** `STATE-WP-0054` added preferred `/workplans` routes,
dual-published completion events, `legacy-meter`, and weekly review payloads.
Canonical guide: `docs/workplan-terminology-transition.md`.

## Goal

Retire State Hub's **metered legacy `workstream` interfaces** in safe phases after
`legacy-meter` weekly review shows zero callers. Make `workplan` the only
user-facing and integration term inside this repo without breaking ADR-001 file
sync or workplan frontmatter bridges.

## Context

A fleet scan on **2026-07-08** (`the-custodian/tools/scan_workstream_terminology.py`)
shows `state-hub` carries ~13,418 `workstream` string hits — mostly compat
routers, tests, dashboard labels, MCP aliases, and legacy-meter registry entries.
That volume is expected until this workplan retires interfaces deliberately.

Retirement rule (unchanged from STATE-WP-0054):

- interface registered as legacy;
- replacement reference verified;
- no manual hold;
- **zero measured calls** in the review window.

Activity-core owns the weekly wakeup; State Hub owns usage state and removal.

## Out of scope

- Renaming workplan frontmatter field `state_hub_workstream_id` (separate bridge
  migration).
- Physical database table/column renames (STATE-WP-0065 completed the spine).
- Fleet-wide domain repo prose sweeps (CUST-WP-0055 T04).
- activity-core `org.workstream.completed` catalog alignment (CUST-WP-0055 T03).
- Removing `/workstreams` before legacy-meter proves zero callers for each key.

## Grep budget (non-compat prose)

Track via `scan_workstream_terminology.py --repo state-hub --json` with
`the-custodian` scan allowlist (archives, legacy-meter registry, compat routers
excluded once documented in T01).

| Phase | Target |
| --- | --- |
| After T02 | Dashboard nav + `dashboard/src/index.md` prose at zero `prose:workstream` |
| After T03 | MCP tool docstrings and error messages workplan-first |
| After T04 | OpenAPI lists `/workplans` only; `/workstreams` removed or 410 |
| After T07 | Total repo hits reduced ≥50% from 2026-07-08 baseline |

## Task: Refresh inventory and ranked retirement backlog

```task
id: STATE-WP-0069-T01
status: done
priority: high
state_hub_task_id: "ffc186e0-807d-4ee4-b11f-3f769af2ab2d"
```

Reconcile `docs/workplan-terminology-transition.md` against the live codebase.
Produce `docs/workplan-terminology-legacy-retirement-backlog.md` ranking every
remaining legacy interface by:

- legacy-meter key;
- replacement ref;
- risk (REST > MCP > events > dashboard prose);
- last-seen and prior-week usage from `/legacy-meter/weekly-review`.

Include explicit allowlist paths for grep/scan tooling (compat routers, test
fixtures, migration history). Store 2026-07-08 baseline JSON reference from
CUST-WP-0055 T01.

Done when the backlog is reviewed and each interface has a phase assignment (T02–T06).

## Task: Dashboard and operator docs — workplan-first labels

```task
id: STATE-WP-0069-T02
status: done
priority: high
state_hub_task_id: "996e484e-8cfb-4c9e-8682-c9c3da0c1d72"
```

Update Observable dashboard navigation, page titles, chart empty-state copy, and
operator docs to say **workplan** in user-facing prose:

- `dashboard/observablehq.config.js` nav entries (`/workstreams` → `/workplans`
  where routes exist);
- `dashboard/src/index.md` and workplan detail pages;
- `README.md` legacy table footnotes.

Keep URL redirects or compat notes for bookmarked `/workstreams` paths until T04.
Add dashboard tests for renamed labels.

Done when dashboard `npm test` passes and scan shows zero `prose:workstream` in
`dashboard/src/` (excluding explicit legacy footnotes).

## Task: MCP legacy alias retirement

```task
id: STATE-WP-0069-T03
status: done
priority: medium
state_hub_task_id: "f701aa56-aa06-4d0e-a632-758677e7ac98"
```

Retire MCP surfaces that still lead with `workstream` terminology:

- `state://workstreams/{topic_slug}` resource;
- any `create_workstream` / `update_workstream` / `list_workstreams` aliases if
  still registered alongside `create_workplan` variants;
- prose in `get_domain_summary` (`open_workstreams`, `needs_workplan` messages).

Phase 1: deprecation warnings in tool responses pointing to workplan-named tools.
Phase 2: remove aliases when legacy-meter shows zero MCP procedure calls for
seven consecutive review windows.

Done when MCP clients use workplan-named tools only and legacy MCP keys are
removed from the registry or marked `retired` with zero usage.

Phase 1 complete 2026-07-08. Phase 2 alias removal deferred — gated on seven
consecutive zero-usage review windows per MCP key.

## Task: REST `/workstreams` compat router retirement

```task
id: STATE-WP-0069-T04
status: done
priority: high
state_hub_task_id: "6fba665d-ebfa-42ab-8cf9-4460f77c5375"
```

Highest-risk phase. Remove or hard-deprecate legacy REST routes in
`api/routers/workstreams.py` once `/workplans` parity is proven and
legacy-meter reports zero calls per key:

- `GET/POST /workstreams/`, `GET/PATCH/DELETE /workstreams/{id}`;
- dependency and execution intent aliases under `/workstreams/`;
- `workstream_id` query param aliases where `workplan_id` is sufficient.

Retain deprecation headers until removal. Update OpenAPI snapshot, router tests,
and `tests/test_legacy_meter.py` retirement cases.

Done when OpenAPI documents `/workplans` as the public CRUD surface and
`/workstreams` returns 410 Gone or is unmounted, with regression tests green.

Closeout 2026-07-08:

- `DELETE /workstreams/{workstream_id}` returns **410 Gone** (retired).
- `scripts/consistency_check.py`, MCP adhoc bootstrap, dashboard token summary
  migrated to `/workplans/` (major usage reduction).
- Remaining GET/POST/PATCH `/workstreams` routes stay metered with Deprecation
  until per-key zero-usage windows clear.

## Task: Legacy completion event — stop dual-publish

```task
id: STATE-WP-0069-T05
status: done
priority: medium
state_hub_task_id: "ebcbe5fc-b50f-4885-a18a-f8394d362c85"
```

After activity-core subscribers migrate (CUST-WP-0055 T03), stop emitting
`org.statehub.workstream.completed` from `api/routers/workstreams.py`. Keep
`org.statehub.workplan.completed` as the sole completion subject.

Register the legacy subject as `retired` in legacy-meter. Update
`docs/nats-event-subjects.md` and envelope tests.

Done when only `org.statehub.workplan.completed` is published on workplan
finish transitions and legacy-meter shows zero event consumers on the old subject.

Completed 2026-07-08: dual-publish removed; `docs/nats-event-subjects.md` marks
legacy subject retired; `capture_legacy_meter_evidence.py --retire-keys` patches
registry on hub capture.

## Task: Internal flows and cache identifiers

```task
id: STATE-WP-0069-T06
status: done
priority: low
state_hub_task_id: "221a69f9-9e61-4fde-9785-fa0dcaf698b4"
```

Rename internal non-wire identifiers when no external client depends on them:

- `flows/workstream.yaml` → workplan entity type (or successor flow id);
- `open_workstreams` keys in state summary cache → `open_workplans`;
- test module names and comments that mislead new contributors.

Coordinate with hub-core if shared types leak the old term.

Done when internal code reads workplan-first and grep budget for
`api:open_workstreams` hits zero.

Closeout 2026-07-08: `flows/workplan.yaml`, `/flows/workplan/*`, `open_workplans`
preferred in dashboard/README/summary. Legacy dual-keys retained until meter clears.

## Task: Closeout — registry cleanup and verification

```task
id: STATE-WP-0069-T07
status: done
priority: medium
state_hub_task_id: "06ed4814-3ba5-4226-845d-695f3041522e"
```

Final verification:

1. `make test` and `cd dashboard && npm test` pass.
2. `scan_workstream_terminology.py --repo state-hub` meets phase grep budget.
3. `legacy-meter` registry lists retired interfaces with retirement dates.
4. `docs/workplan-terminology-transition.md` updated with retirement completion
   notes and pointers to CUST-WP-0055 T08 fleet gate.

Post State Hub progress note linking completion; notify CUST-WP-0055 T02 closeout.

Done when STATE-WP-0069 can move to `finished` and CUST-WP-0055 T02-T02 is `done`.

Evidence: `docs/evidence/legacy-meter-weekly-review-20260708.json` (pytest capture);
`scripts/capture_legacy_meter_evidence.py` for production hub snapshots.
Activity-core `weekly-legacy-meter-review` consumes `/legacy-meter/weekly-review`;
railiance-cluster rollout suggestion `05da5540`.

## Sequencing

```
T01 inventory + backlog (blocking)
T02 dashboard/docs (low risk, start early)
T03 MCP aliases (parallel with T02 after T01)
T04 REST retirement (after ≥1 zero-usage review window per route key)
T05 event dual-publish stop (after CUST-WP-0055 T03)
T06 internal renames (anytime after T04)
T07 closeout
```

## Acceptance criteria

- `workplan` is the only recommended term in State Hub dashboard, README, and
  new MCP/REST docs.
- Legacy interfaces are removed only with legacy-meter evidence, not by schedule
  alone.
- ADR-001 `fix-consistency` and workplan file sync remain green through all
  phases.
- No frontmatter `state_hub_workstream_id` renames in this workplan.

## Deferred post-closeout

- MCP Phase 2 alias removal (seven consecutive zero-usage windows per key).
- Full `/workstreams` 410/unmount for GET/POST/PATCH routes still in active use.
- `open_workstreams` summary key removal (dual-key compat remains).
- Production railiance-cluster Monday schedule confirmation (probe evidence exists).