# Workplan Terminology Legacy Retirement Backlog

Date: 2026-07-08  
Owner: `STATE-WP-0069` (child of `CUST-WP-0055`)  
Baseline: `the-custodian/docs/evidence/workstream-terminology-baseline-20260708.json`

This backlog ranks every metered legacy `workstream` interface still present in
State Hub. **Removal requires legacy-meter evidence** — zero measured calls in
the review window, replacement verified, no manual hold.

Authoritative interface matrix: `docs/workplan-terminology-transition.md`.

## Retirement rule (unchanged)

1. Registered in `legacy-meter`
2. Replacement reference verified
3. No manual hold
4. Zero measured calls in the review window

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

## Scan allowlist (grep tooling)

Exclude these paths from non-compat prose counts (see
`the-custodian/tools/scan_workstream_allowlist.yaml`):

| Area | Paths |
| --- | --- |
| Compat REST | `api/routers/workstreams.py`, `api/routers/workstream_dependencies.py` |
| Legacy meter | `api/routers/legacy_meter.py`, `api/services/legacy_meter.py`, `api/models/legacy_meter.py`, `migrations/` |
| MCP aliases | `mcp_server/` |
| Transition docs | `docs/workplan-terminology-transition.md`, this file, `docs/nats-event-subjects.md` |
| Regression tests | `tests/test_legacy_meter.py`, `tests/test_routers_core.py` |
| CLI compat | `custodian_cli.py`, `scripts/consistency_check.py` |

Dashboard prose is **not** allowlisted — `STATE-WP-0069` T02 drives it to zero
`prose:workstream` in `dashboard/src/`.

## Ranked backlog

Risk order: REST > MCP > events > dashboard prose > internal identifiers.

| Phase | Legacy-meter key | Replacement | Risk | Owner task |
| ---: | --- | --- | --- | --- |
| 1 | `rest_api:GET /workstreams/` | `GET /workplans/` | REST | T04 |
| 1 | `rest_api:POST /workstreams/` | `POST /workplans/` | REST | T04 |
| 1 | `rest_api:GET /workstreams/{workstream_id}` | `GET /workplans/{workplan_id}` | REST | T04 |
| 1 | `rest_api:PATCH /workstreams/{workstream_id}` | `PATCH /workplans/{workplan_id}` | REST | T04 |
| 1 | `rest_api:DELETE /workstreams/{workstream_id}` | `DELETE /workplans/{workplan_id}` | REST | T04 |
| 1 | `rest_api:GET /workstreams/workplan-index` | `GET /workplans/index` | REST | T04 |
| 2 | `rest_api:GET /workstreams/{workstream_id}/dependencies/` | `GET /workplans/{workplan_id}/dependencies/` | REST | T04 |
| 2 | `rest_api:POST /workstreams/{workstream_id}/dependencies/` | `POST /workplans/{workplan_id}/dependencies/` | REST | T04 |
| 2 | `rest_api:DELETE /workstreams/{workstream_id}/dependencies/{dep_id}` | `DELETE /workplans/{workplan_id}/dependencies/{dep_id}` | REST | T04 |
| 2 | `rest_api:PATCH /execution/workstreams/{workstream_id}/intent` | `PATCH /execution/workplans/{workplan_id}/intent` | REST | T04 |
| 3 | `mcp:create_workstream` | `create_workplan` | MCP | T03 |
| 3 | `mcp:update_workstream` | `update_workplan` | MCP | T03 |
| 3 | `mcp:update_workstream_status` | `update_workplan_status` | MCP | T03 |
| 3 | `mcp:list_workstreams` | `list_workplans` | MCP | T03 |
| 3 | `state://workstreams/{topic_slug}` | `state://workplans/{topic_slug}` (proposed) | MCP resource | T03 |
| 4 | `event_subject:org.statehub.workstream.completed` | `org.statehub.workplan.completed` | Event | T05 |
| 5 | Dashboard nav label `Workstreams` | `Workplans` (URL compat retained) | Prose | T02 |
| 5 | `dashboard/src/index.md` user-facing copy | workplan-first strings | Prose | T02 |
| 6 | `open_workstreams` summary cache key | `open_workplans` | Internal | T06 |
| 6 | `flows/workstream.yaml` entity id | `flows/workplan.yaml` (`custodian.workplan.v1`) | Internal | T06 (workplan flow shipped; workstream yaml retained) |

### Query-param aliases (metered from 2026-07-09)

These accept `workstream_id` alongside `workplan_id` on preferred routes:

| Legacy-meter key | Route | Replacement |
| --- | --- | --- |
| `rest_api:GET /tasks/?workstream_id` | `GET /tasks/` | `GET /tasks/?workplan_id=` |
| `rest_api:GET /tasks/counts?workstream_id` | `GET /tasks/counts` | `GET /tasks/counts?workplan_id=` |
| `rest_api:GET /decisions/?workstream_id` | `GET /decisions/` | `GET /decisions/?workplan_id=` |
| `rest_api:GET /token-events/?workstream_id` | `GET /token-events/` | `GET /token-events/?workplan_id=` |
| `rest_api:GET /execution/launch-requests?workstream_id` | `GET /execution/launch-requests` | `GET /execution/launch-requests?workplan_id=` |
| `rest_api:GET /progress/?workstream_id` | `GET /progress/` | `GET /progress/?workplan_id=` |

Retire param aliases in T04 after zero-usage windows; callers surface via
`X-StateHub-Component` in weekly review.

## Grep budget by phase

Measured with:

```bash
python ~/the-custodian/tools/scan_workstream_terminology.py --repo state-hub --apply-allowlist --json
python ~/the-custodian/tools/scan_workstream_terminology.py --repo state-hub --check-prose-gate
```

| Phase | Target |
| --- | --- |
| After T02 | Zero `prose:workstream` in `dashboard/src/` |
| After T03 | MCP tool docstrings and error messages workplan-first |
| After T04 | OpenAPI lists `/workplans` only; `/workstreams` returns 410 or unmounted |
| After T07 | Total repo hits reduced ≥50% from 2026-07-08 baseline |

## Sequencing

```
T01 backlog (this document) ──► T02 dashboard prose
                           ├─► T03 MCP deprecation warnings → alias removal
                           ├─► T04 REST retirement (per-key zero usage)
                           ├─► T05 stop dual-publish (after CUST-WP-0055 T03)
                           ├─► T06 internal renames
                           └─► T07 closeout
```

## Related workplans

- `STATE-WP-0054` — compatibility layer and legacy-meter (finished)
- `STATE-WP-0069` — this retirement plan
- `CUST-WP-0055` — fleet coordination; activity-core catalog alignment (T03)