STATE-WP-0072: remediate remaining workstream HTTP callers
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 5s

Research sweep captured in research/20260709-workstream-caller-sweep.md.
Migrate dashboard detail tasks query, custodian_cli POST bodies, and
onboarding curl to workplan-first paths; re-capture 8h legacy-meter evidence.
This commit is contained in:
tegwick 2026-07-09 01:48:53 +02:00
parent 3f1eac7bab
commit ef51b99ff5
7 changed files with 228 additions and 12 deletions

View file

@ -293,7 +293,7 @@ def cmd_register(args: argparse.Namespace) -> None:
] ]
for title, priority, description in tasks: for title, priority, description in tasks:
_api_post("/tasks/", { _api_post("/tasks/", {
"workstream_id": ws_id, "workplan_id": ws_id,
"title": title, "title": title,
"priority": priority, "priority": priority,
"description": description, "description": description,
@ -446,9 +446,9 @@ def cmd_create_workstream(args: argparse.Namespace) -> None:
}) })
_api_post("/progress/", { _api_post("/progress/", {
"topic_id": topic_id, "topic_id": topic_id,
"workstream_id": ws["id"], "workplan_id": ws["id"],
"event_type": "workstream_created", "event_type": "workplan_created",
"summary": f"Workstream created: {args.title}", "summary": f"Workplan created: {args.title}",
"author": "custodian", "author": "custodian",
"detail": {"owner": args.owner, "slug": slug}, "detail": {"owner": args.owner, "slug": slug},
}) })
@ -475,14 +475,14 @@ def cmd_create_task(args: argparse.Namespace) -> None:
workstream_id = match["id"] workstream_id = match["id"]
task = _api_post("/tasks/", { task = _api_post("/tasks/", {
"workstream_id": workstream_id, "workplan_id": workstream_id,
"title": args.title, "title": args.title,
"priority": args.priority, "priority": args.priority,
"description": args.description, "description": args.description,
"assignee": args.assignee, "assignee": args.assignee,
}) })
_api_post("/progress/", { _api_post("/progress/", {
"workstream_id": workstream_id, "workplan_id": workstream_id,
"task_id": task["id"], "task_id": task["id"],
"event_type": "task_created", "event_type": "task_created",
"summary": f"Task created: {args.title}", "summary": f"Task created: {args.title}",

View file

@ -14,7 +14,7 @@ const [raw, taskRows, workplanIndex] = await Promise.all([
fetch(`${API}/workplans/${wsId}`) fetch(`${API}/workplans/${wsId}`)
.then(r => r.ok ? r.json() : r.json().then(e => ({error: e.detail ?? `HTTP ${r.status}`}))) .then(r => r.ok ? r.json() : r.json().then(e => ({error: e.detail ?? `HTTP ${r.status}`})))
.catch(e => ({error: String(e)})), .catch(e => ({error: String(e)})),
fetch(`${API}/tasks/?workstream_id=${wsId}&limit=1000`) fetch(`${API}/tasks/?workplan_id=${wsId}&limit=1000`)
.then(r => r.ok ? r.json() : []) .then(r => r.ok ? r.json() : [])
.catch(() => []), .catch(() => []),
fetch(`${API}/workplans/index`) fetch(`${API}/workplans/index`)

View file

@ -1,12 +1,12 @@
{ {
"captured_at": "2026-07-08T23:35:18.486286+00:00", "captured_at": "2026-07-08T23:48:41.675130+00:00",
"api_base": "http://127.0.0.1:8000", "api_base": "http://127.0.0.1:8000",
"workplan": "STATE-WP-0070", "workplan": "STATE-WP-0070",
"retired_interfaces": [], "retired_interfaces": [],
"weekly_review": { "weekly_review": {
"generated_at": "2026-07-08T23:35:18.459774Z", "generated_at": "2026-07-08T23:48:41.652056Z",
"window_start": "2026-07-08T15:35:18.219148Z", "window_start": "2026-07-08T15:48:41.473474Z",
"window_end": "2026-07-08T23:35:18.219148Z", "window_end": "2026-07-08T23:48:41.473474Z",
"cadence": "weekly", "cadence": "weekly",
"activity_core_handoff": { "activity_core_handoff": {
"activity_id": "statehub-legacy-interface-review", "activity_id": "statehub-legacy-interface-review",

View file

@ -0,0 +1,78 @@
# Workstream caller inventory — 2026-07-09 (second sweep)
Follow-up after `STATE-WP-0071` railiance01 deploy. Eight-hour legacy-meter window
(2026-07-09) still shows heavy `GET /workstreams/*` traffic (~1.7k in 8h for
`GET /workstreams/` alone); attribution remains mostly `unknown`.
## Newly found — actionable HTTP callers
| Caller | Repo | Legacy usage | Fix |
| --- | --- | --- | --- |
| `dashboard/src/workstreams/[id].md` | state-hub | `GET /tasks/?workstream_id=` | → `?workplan_id=` |
| `custodian_cli.py` | state-hub | `POST /tasks/` body `workstream_id` (onboarding, add-task) | → `workplan_id` |
| `runtime/prompts/daily_statehub_wsgi_triage.md` | the-custodian | Instructs `GET /workstreams/workplan-index` (**410**) and `?workstream_id=` enrichment | → `/workplans/index`, `?workplan_id=` |
| `k8s/railiance/21-custodian-runtime.yaml` | activity-core | Same stale prompt text projected to cluster | Roll after prompt fix |
| `wise-validator/reporter.py` | wise-validator | `POST /progress/` body `workstream_id` | → `workplan_id` |
| `session_memory/curate/decisions.py` | agentic-resources | Dual-write `workplan_id` + `workstream_id` on decisions | Drop `workstream_id` key |
## Newly found — response / field aliases (no extra REST path)
| Caller | Repo | Notes |
| --- | --- | --- |
| `context_resolvers/state_hub.py` `_safe_next_step` | activity-core | Dual-keys `workplan_*` + `workstream_*` in digest JSON (downstream prose only) |
| `k8s/railiance/20-runtime.yaml` sink configs | activity-core | `workstream_id:` in YAML sink scope — read bridge in `state_hub_write.py` |
| `schedule_health.py` | activity-core | Accepts legacy param; prefers `workplan_id` |
| `dashboard/src/components/field-help.js` | state-hub | Nav links `/workstreams/{id}` (UI route compat, not API) |
| `api/routers/state.py` | state-hub | Response fields `workstream_id`, `open_workstreams` in `/state/summary` |
| `runtime/context.py` | the-custodian | Reads `open_workstreams` from summary (response field, not REST caller) |
## Confirmed migrated (no change since 2026-07-08 inventory)
- `scripts/consistency_check.py`, `cleanup_stale_tasks.py`, `validate_repo_adr.py``/workplans/`
- `custodian_cli.py` list/CRUD paths → `/workplans/` (body fields still legacy — see above)
- Dashboard list pages (`workstreams.md`, `extensions.md`, `tasks.md`, …) → `apiFetch("/workplans/")`
- Dashboard data loaders → `GET /workplans`
- `mcp_server/server.py` REST calls → `/workplans` (tool/param aliases remain by design)
- `activity-core/context_resolvers` index/detail/tasks fetches → `/workplans/*`
- `can-you-assist/shell_session.py` orientation → `GET /workplans/?`
## Intentional legacy (meter-gated — STATE-WP-0070)
| Surface | Notes |
| --- | --- |
| `api/routers/workstreams.py` | Compat router; `workplan-index` + `DELETE` already **410** |
| `api/routers/workstream_dependencies.py` | Legacy dependency aliases |
| `api/routers/execution.py` | `PATCH /execution/workstreams/{id}/intent` |
| Query/body aliases on `/tasks/`, `/progress/`, `/decisions/` | Metered per-key |
| MCP tools `create_workstream`, `list_workstreams`, … | Aliases; internal REST uses `/workplans/` |
| `state://workstreams/{topic_slug}` resource | Deprecated wrapper |
| DB columns / JSON response fields `workstream_id` | STATE-WP-0070 T04 |
| Frontmatter `state_hub_workstream_id` | Fleet bridge — separate migration |
| `tests/test_legacy_meter.py`, `test_routers_core.py` | Regression coverage |
## Likely sources of remaining `GET /workstreams/*` volume
1. **Remote fix-consistency hosts** not yet on `state-hub``14b7d84` (coulombcore runners, cron sweep nodes).
2. **Dashboard detail page** task poll via `?workstream_id=` (every workplan detail view).
3. **Agent prompts** still telling models to call retired `workplan-index` legacy path (410 but metered).
4. **External REST clients** (bookmarks, old scripts, Claude settings curl examples in `activity-core/.claude/settings.local.json`).
5. **Legacy query aliases** elsewhere in dashboard/docs (`docs/onboarding.md` curl example).
## Remediation (STATE-WP-0072 — 2026-07-09)
- [x] `dashboard/src/workstreams/[id].md``?workplan_id=`
- [x] `custodian_cli.py` POST bodies → `workplan_id`
- [x] `docs/onboarding.md` curl → `/workplans/`
- [x] `the-custodian/runtime/prompts/daily_statehub_wsgi_triage.md`
- [x] `activity-core/k8s/railiance/21-custodian-runtime.yaml`
- [x] `wise-validator/reporter.py`, `agentic-resources/curate/decisions.py`
- [x] 8h meter re-capture (`legacy-meter-weekly-review-20260709.json`)
Outstanding: remote fix-consistency hosts; activity-core k8s rollout of prompt projection; meter decline over subsequent 8h windows.
## Verification
```bash
python scripts/capture_legacy_meter_evidence.py # 8h window
rg '/workstreams|workstream_id' --glob '!**/workplans/**' --glob '!**/tests/**' <repo>
```

View file

@ -103,7 +103,7 @@ Restart Claude Code after MCP registration.
```bash ```bash
cat .custodian-brief.md cat .custodian-brief.md
curl -s "http://127.0.0.1:8000/workstreams/?status=active" | python3 -m json.tool curl -s "http://127.0.0.1:8000/workplans/?status=active" | python3 -m json.tool
``` ```
## Domain Collaborator: New Person ## Domain Collaborator: New Person

View file

@ -0,0 +1,57 @@
# Workstream caller sweep — 2026-07-09
**Parent:** `STATE-WP-0070` T01 follow-up after `STATE-WP-0071` railiance01 deploy.
**Evidence:** `docs/evidence/workstream-caller-inventory-20260709.md`
**Meter context:** 8-hour capture (`legacy-meter-weekly-review-20260709.json`) — `GET /workstreams/` ~1,752 calls/window; attribution mostly `unknown`.
## Method
1. Targeted `rg` across `state-hub`, `activity-core`, `the-custodian`, fleet repos (Python/JS/YAML).
2. Fleet terminology scan: `the-custodian/tools/scan_workstream_terminology.py --json` (82 repos).
3. Cross-check against `docs/evidence/workstream-caller-inventory-20260708.md`.
## Fleet scan summary (82 repos)
| Repo | Occurrences | Notable runtime patterns |
| --- | ---: | --- |
| state-hub | 13,562 | `path:workstreams/` 171; `api:workstream_id` 603; python 800 |
| activity-core | 176 | `context_resolvers/state_hub.py`, k8s prompt YAML |
| the-custodian | 1,220 | `runtime/prompts/daily_statehub_wsgi_triage.md` |
| wise-validator | (small) | `reporter.py` progress POST |
| agentic-resources | 11 py | `curate/decisions.py` dual-write |
Most fleet hits are workplans, agent-guidance, or session_memory blobs — not live REST callers.
## Actionable HTTP callers (fix in STATE-WP-0072)
| Caller | Repo | Legacy | Fix |
| --- | --- | --- | --- |
| `dashboard/src/workstreams/[id].md` | state-hub | `GET /tasks/?workstream_id=` | `?workplan_id=` |
| `custodian_cli.py` | state-hub | `POST /tasks/`, `/progress/` body `workstream_id` | `workplan_id` |
| `docs/onboarding.md` | state-hub | curl `GET /workstreams/?status=active` | `/workplans/` |
| `runtime/prompts/daily_statehub_wsgi_triage.md` | the-custodian | `/workstreams/workplan-index` (410), `?workstream_id=` | `/workplans/index`, `?workplan_id=` |
| `k8s/railiance/21-custodian-runtime.yaml` | activity-core | Same prompt projection | Sync with custodian prompt |
| `wise-validator/reporter.py` | wise-validator | progress body `workstream_id` | `workplan_id` |
| `session_memory/curate/decisions.py` | agentic-resources | dual-write both scope keys | `workplan_id` only |
## Confirmed migrated (no regression)
- `consistency_check.py`, `cleanup_stale_tasks.py`, `validate_repo_adr.py``/workplans/`
- Dashboard list pages + data loaders → `/workplans/`
- MCP server REST → `/workplans/` (legacy tool names remain)
- activity-core resolver fetches → `/workplans/*`
- can-you-assist `shell_session.py``/workplans/?`
## Intentional legacy (STATE-WP-0070 — meter-gated)
- `api/routers/workstreams.py`, `workstream_dependencies.py`, execution intent alias
- Query/body aliases on tasks/progress/decisions (until T04)
- MCP aliases, `state://workstreams/` resource
- DB/response fields, `state_hub_workstream_id` frontmatter
## Verification
```bash
python scripts/capture_legacy_meter_evidence.py # 8h default
rg '/workstreams|workstream_id' --glob '!**/workplans/**' --glob '!**/tests/**' <repo>
```

View file

@ -0,0 +1,81 @@
---
id: STATE-WP-0072
type: workplan
title: "Workstream caller remediation (second sweep)"
domain: infotech
repo: state-hub
status: finished
owner: codex
topic_slug: custodian
planning_priority: high
planning_order: 72
created: "2026-07-09"
updated: "2026-07-09"
---
# STATE-WP-0072 — Workstream caller remediation
**Parent:** `STATE-WP-0070` (phase-2 legacy retirement).
**Research:** `research/20260709-workstream-caller-sweep.md`
## Goal
Eliminate remaining production HTTP callers that hit legacy `workstream_id`
query/body params or `/workstreams/*` paths, so 8-hour legacy-meter windows
show declining `GET /workstreams/*` counts.
## Task: state-hub dashboard and CLI
```task
id: STATE-WP-0072-T01
status: done
priority: high
```
- `dashboard/src/workstreams/[id].md` — tasks fetch uses `?workplan_id=`
- `custodian_cli.py` — task/progress POST bodies use `workplan_id`
- `docs/onboarding.md` — curl example uses `/workplans/`
Done when no state-hub runtime file POSTs or GETs legacy workstream paths/params.
## Task: Daily triage prompt (the-custodian + activity-core projection)
```task
id: STATE-WP-0072-T02
status: done
priority: high
```
- `the-custodian/runtime/prompts/daily_statehub_wsgi_triage.md``/workplans/index`, `?workplan_id=`
- `activity-core/k8s/railiance/21-custodian-runtime.yaml` — matching prompt text
Done when prompt no longer references `/workstreams/workplan-index`.
## Task: Cross-repo progress/decision POST bodies
```task
id: STATE-WP-0072-T03
status: done
priority: medium
```
- `wise-validator/src/wisevalidator/reporter.py``workplan_id` on progress POST
- `agentic-resources/session_memory/curate/decisions.py` — drop `workstream_id` dual-write
- Update tests in both repos
Done when tests pass and POST bodies use `workplan_id` only.
## Task: Verify and capture meter evidence
```task
id: STATE-WP-0072-T04
status: done
priority: high
```
1. `rg` confirm no missed runtime callers in fixed repos.
2. `python scripts/capture_legacy_meter_evidence.py` (8h window).
3. Update `docs/evidence/workstream-caller-inventory-20260709.md` checklist.
4. Archive workplan when evidence captured.
Done when 8h capture committed and STATE-WP-0072 `finished`.