STATE-WP-0070 T03: remove legacy workstream MCP aliases

Meter-gated removal (7 consecutive zero-usage windows reached). Deletes:
- MCP tools: create_workstream, list_workstreams, update_workstream,
  update_workstream_status
- MCP resource: state://workstreams/{topic_slug}
- Dead helpers: _LEGACY_MCP_* maps, _legacy_mcp_deprecation,
  _meter_legacy_mcp, _attach_legacy_deprecation, _update_workplan_legacy_impl

TOOLS.md keeps a retired→preferred migration map (per backlog). Removed the
now-dead STATEHUB_MCP_LEGACY_METER guard in conftest. Retargeted the
create_workplan error-skip test to the preferred tool; dropped alias-only tests.

Staged on branch state-wp-0070-legacy-retirement — do not merge until the 7th
documented zero-usage window is captured.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
tegwick 2026-07-13 09:29:12 +02:00
parent 1acad4c02c
commit ef62cb3872
5 changed files with 28 additions and 328 deletions

View file

@ -25,18 +25,25 @@ Do not use them as a substitute for formal work definition inside the domain rep
**Preferred terms:** workplan, `workplan_id`, `/workplans/…`
**Legacy compatibility:** `workstream`, `workstream_id`, `/workstreams/…`, and
`create_workstream` / `update_workstream` MCP tools remain available as aliases.
They call the same implementation as the workplan-named tools and endpoints.
**Legacy compatibility:** the `workstream_id` query/body field is still accepted
as an alias on preferred routes. The `/workstreams/…` REST routes and the
`create_workstream` / `update_workstream` / `update_workstream_status` /
`list_workstreams` MCP tools and the `state://workstreams/{topic_slug}` resource
were **retired** by STATE-WP-0070 (phase-2 legacy retirement) after the
legacy-meter showed seven consecutive zero-usage windows. Use the workplan-named
tools below.
| Preferred (workplan) | Legacy alias (workstream) |
Migration map (retired → preferred):
| Retired legacy alias | Preferred (workplan) |
|---|---|
| `create_workplan(repo_id, …)` | `create_workstream(repo_id, …)` |
| `update_workplan` / `update_workplan_status` | `update_workstream` / `update_workstream_status` |
| `list_workplans` | `list_workstreams` |
| `create_workplan_dependency` | `create_dependency` |
| `POST /workplans/` | `POST /workstreams/` (deprecated headers) |
| `workplan_id` query/body field | `workstream_id` (accepted alias) |
| `create_workstream(repo_id, …)` | `create_workplan(repo_id, …)` |
| `update_workstream` / `update_workstream_status` | `update_workplan` / `update_workplan_status` |
| `list_workstreams` | `list_workplans` |
| `create_dependency` | `create_workplan_dependency` |
| `POST /workstreams/` (410 Gone) | `POST /workplans/` |
| `state://workstreams/{topic_slug}` (removed) | `state://workplans/{topic_slug}` |
| `workstream_id` (still-accepted field alias) | `workplan_id` query/body field |
Repo classification filters: `list_repos_by_classification(category?, domain?,
capability_tag?, business_stake?)` and extended `list_domain_repos(...)` query
@ -56,7 +63,6 @@ endpoint they wrap:
| `list_workplans(...)` | `GET /workplans/` |
| `update_workplan_status(...)` | `PATCH /workplans/{workplan_id}` |
| `list_repos_by_classification(...)` | `GET /repos/?category=…` |
| `create_workstream(...)` | `POST /workstreams/` |
| `create_task(...)` | `POST /tasks/` |
| `update_task_status(...)` | `PATCH /tasks/{task_id}` |
| `bulk_update_task_statuses(...)` | `POST /tasks/bulk-status-sync` |
@ -126,12 +132,12 @@ and replay with statehub outbox status and statehub outbox replay.
| Tool | Key Args | Notes |
|------|----------|-------|
| `create_workplan(topic_id, title, ...)` | `slug?`; `owner?`; `description?`; `due_date?` | **Preferred.** Creates workplan under a topic. Legacy alias: `create_workstream`. |
| `create_workplan(topic_id, title, ...)` | `slug?`; `owner?`; `description?`; `due_date?` | **Preferred.** Creates workplan under a topic. |
| `create_task(workplan_id, title, ...)` | `priority`: low/medium/high/critical; `assignee?`; `due_date?` | Creates task under a workplan (`workstream_id` alias accepted). |
| `update_task_status(task_id, status, ...)` | `status`: wait/todo/progress/done/cancel; `blocking_reason?` describes wait conditions | Legacy aliases `blocked`, `in_progress`, `cancelled`, and `canceled` are accepted during migration. |
| `bulk_update_task_statuses(updates, author?, session_id?)` | `updates`: list of `{task_id, status, blocking_reason?}` | Updates many task statuses in one REST call and emits one `task_status_changed` progress event per task. Prefer this at session checkpoints instead of many single-task calls. |
| `update_workstream_status(workstream_id, status)` | `status`: proposed/ready/active/blocked/backlog/finished/archived | Thin shortcut — use `update_workstream` for full field control. |
| `update_workstream(workstream_id, ...)` | `title?`; `description?`; `owner?`; `due_date?`; `repo_goal_id?`; `status?` | Patch any subset of workstream fields. Pass empty string for `repo_goal_id` to clear the link. |
| `update_workplan_status(workplan_id, status)` | `status`: proposed/ready/active/blocked/backlog/finished/archived | Thin shortcut — use `update_workplan` for full field control. |
| `update_workplan(workplan_id, ...)` | `title?`; `description?`; `owner?`; `due_date?`; `repo_goal_id?`; `status?` | Patch any subset of workplan fields. Pass empty string for `repo_goal_id` to clear the link. |
---
@ -186,8 +192,7 @@ Agents should call `record_token_event` (or pass `tokens_in`/`tokens_out` via
|-----|---------|
| `state://summary` | Full StateSummary JSON |
| `state://topics` | Active topics list |
| `state://workplans/{topic_slug}` | Workplans for a topic (by slug) — preferred |
| `state://workstreams/{topic_slug}` | Legacy resource alias (deprecated; same payload + `_deprecation`) |
| `state://workplans/{topic_slug}` | Workplans for a topic (by slug) |
| `state://decisions/blocking` | All pending decisions |
| `state://tasks/blocked` | Legacy resource name; returns all `wait` tasks |
@ -371,6 +376,6 @@ add_progress_event(
)
# First Session Protocol only — bootstrap a new project:
create_workstream(topic_id="<uuid>", title="My Workstream", owner="me")
create_task(workstream_id="<uuid>", title="Do the thing", priority="high")
create_workplan(topic_id="<uuid>", title="My Workplan", owner="me")
create_task(workplan_id="<uuid>", title="Do the thing", priority="high")
```