feat(canon): add Interface Change Registry concept and workplan
Concept doc captures the design for coordinated API evolution in agent ecosystems: InterfaceChange entity, draft→published→resolved lifecycle, TPSC-derived dependency routing, inbox-based notifications, pre-change coordination via planned_for, and deliberate deferral of webhooks. CUST-WP-0033 workplan: 6 tasks (model, API, dispatch integration, MCP tools, dashboard, webhook EP). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
170
workplans/CUST-WP-0033-interface-change-registry.md
Normal file
170
workplans/CUST-WP-0033-interface-change-registry.md
Normal file
@@ -0,0 +1,170 @@
|
||||
---
|
||||
id: CUST-WP-0033
|
||||
type: workplan
|
||||
title: "Interface Change Registry — Coordinated API Evolution"
|
||||
domain: custodian
|
||||
repo: the-custodian
|
||||
status: active
|
||||
owner: custodian
|
||||
topic_slug: custodian
|
||||
created: "2026-04-26"
|
||||
updated: "2026-04-26"
|
||||
concept: canon/projects/custodian/interface_change_registry_v0.1.md
|
||||
state_hub_workstream_id: "420a3981-abf5-4a8e-a94b-455964f1a0e5"
|
||||
---
|
||||
|
||||
# CUST-WP-0033 — Interface Change Registry
|
||||
|
||||
## Goal
|
||||
|
||||
Add a first-class `InterfaceChange` entity to the state-hub. Agents producing
|
||||
breaking changes can document them; agents consuming interfaces discover pending
|
||||
changes at session start via dispatch, and receive inbox notifications on publish.
|
||||
Webhook delivery is deferred and registered as an extension point.
|
||||
|
||||
Reference concept: `canon/projects/custodian/interface_change_registry_v0.1.md`
|
||||
|
||||
## T01: Data model and migration
|
||||
|
||||
```task
|
||||
id: CUST-WP-0033-T01
|
||||
status: todo
|
||||
priority: high
|
||||
state_hub_task_id: "6bc77d3c-78e0-485a-a3bc-b5987c4ccc53"
|
||||
```
|
||||
|
||||
New table `interface_changes`. Fields: `id` (UUID PK), `repo_id` (FK
|
||||
managed_repos), `interface_type` (String: rest_api / mcp_tool / cli / schema /
|
||||
capability), `change_type` (String: breaking / additive / deprecation / removal),
|
||||
`title` (String), `description` (Text), `affected_paths` (JSONB list of strings),
|
||||
`affected_repo_slugs` (JSONB list of slugs), `status` (String: draft / published /
|
||||
resolved), `planned_for` (Date nullable), `published_at` (DateTime nullable),
|
||||
`resolved_at` (DateTime nullable), `author` (String), `created_at`, `updated_at`.
|
||||
|
||||
Index on `(repo_id, status)` and `(status)` for dispatch queries.
|
||||
|
||||
Acceptance: Alembic migration runs cleanly, model importable, no regressions in
|
||||
existing test suite.
|
||||
|
||||
## T02: API endpoints
|
||||
|
||||
```task
|
||||
id: CUST-WP-0033-T02
|
||||
status: todo
|
||||
priority: high
|
||||
state_hub_task_id: "7664551e-0871-4e82-a9ba-b59be515c47c"
|
||||
```
|
||||
|
||||
Router at `/interface-changes/` (prefix). Endpoints:
|
||||
|
||||
- `POST /interface-changes/` — create (status always `draft` on creation)
|
||||
- `GET /interface-changes/` — list; filter params: `repo_slug`, `status`,
|
||||
`change_type`, `affected_repo` (returns changes that affect the given slug)
|
||||
- `GET /interface-changes/{change_id}` — single record
|
||||
- `PATCH /interface-changes/{change_id}` — update mutable fields (title,
|
||||
description, affected_paths, affected_repo_slugs, planned_for); only valid in
|
||||
`draft` status
|
||||
- `POST /interface-changes/{change_id}/publish` — transition draft → published;
|
||||
sets `published_at`; fires inbox messages to agents of all `affected_repo_slugs`;
|
||||
appends a progress event on the originating repo
|
||||
- `POST /interface-changes/{change_id}/resolve` — transition published → resolved;
|
||||
sets `resolved_at`
|
||||
|
||||
Acceptance: all endpoints return correct status codes; publish transitions send
|
||||
inbox messages; 409 on invalid status transitions; tests cover happy path and
|
||||
invalid transitions.
|
||||
|
||||
## T03: Dispatch integration
|
||||
|
||||
```task
|
||||
id: CUST-WP-0033-T03
|
||||
status: todo
|
||||
priority: medium
|
||||
state_hub_task_id: "8f8403a2-4444-4196-9845-ea9c66b674eb"
|
||||
```
|
||||
|
||||
Extend `GET /repos/{slug}/dispatch` to include a `pending_interface_changes` field:
|
||||
published `InterfaceChange` records where `affected_repo_slugs` contains `slug` and
|
||||
status is not `resolved`. Each entry: `id`, `title`, `change_type`,
|
||||
`interface_type`, `repo_slug` (origin), `affected_paths`, `planned_for`,
|
||||
`published_at`.
|
||||
|
||||
Extend `DispatchWorkstream` schema with the new field. Update `RepoDispatch` schema.
|
||||
Update the `get_repo_dispatch` endpoint accordingly.
|
||||
|
||||
Acceptance: `GET /repos/repo-registry/dispatch` returns `pending_interface_changes`
|
||||
list (empty or populated); no regression on existing dispatch tests.
|
||||
|
||||
## T04: MCP tools
|
||||
|
||||
```task
|
||||
id: CUST-WP-0033-T04
|
||||
status: todo
|
||||
priority: medium
|
||||
state_hub_task_id: "d9135829-954e-41de-af9f-607768916478"
|
||||
```
|
||||
|
||||
Four tools in `mcp_server/server.py`:
|
||||
|
||||
- `register_interface_change(repo_slug, interface_type, change_type, title,
|
||||
description, affected_paths=None, affected_repo_slugs=None, planned_for=None)`
|
||||
— creates a draft record
|
||||
- `list_interface_changes(repo_slug=None, status=None, change_type=None,
|
||||
affected_repo=None)` — returns formatted summary
|
||||
- `publish_interface_change(change_id)` — publishes and triggers notifications
|
||||
- `resolve_interface_change(change_id)` — marks resolved
|
||||
|
||||
Acceptance: tools callable from Claude Code; publish tool returns confirmation
|
||||
of how many inbox messages were sent.
|
||||
|
||||
## T05: Dashboard page
|
||||
|
||||
```task
|
||||
id: CUST-WP-0033-T05
|
||||
status: todo
|
||||
priority: low
|
||||
state_hub_task_id: "d2fcbe83-c5a7-400c-a53b-ff1950795814"
|
||||
```
|
||||
|
||||
New page `dashboard/src/interface-changes.md`. Shows:
|
||||
|
||||
- Table of published/draft changes grouped by repo, sorted by `published_at` desc
|
||||
- Change type badge (breaking = red, deprecation = amber, additive = green)
|
||||
- Affected repos column with count
|
||||
- Filter by repo slug and change_type
|
||||
- A "planned" section for changes with future `planned_for` dates, sorted
|
||||
chronologically — effectively a migration calendar
|
||||
|
||||
Add to `observablehq.config.js` nav.
|
||||
|
||||
Acceptance: page renders; data loads from `GET /interface-changes/?status=published`
|
||||
and `GET /interface-changes/?status=draft`.
|
||||
|
||||
## T06: Register webhook extension point
|
||||
|
||||
```task
|
||||
id: CUST-WP-0033-T06
|
||||
status: todo
|
||||
priority: low
|
||||
state_hub_task_id: "47d7bea8-b5fb-4fc4-9ec5-9ed5e0cdef72"
|
||||
```
|
||||
|
||||
Register EP-CUST-ICR-001 in the state-hub:
|
||||
|
||||
```
|
||||
interface_type: future_capability
|
||||
ep_type: architecture
|
||||
title: Webhook subscriptions for interface change notifications
|
||||
description: |
|
||||
Inbox messages cover polling agents. Real-time push to CI pipelines,
|
||||
external webhooks, and non-Custodian agents requires a subscription table
|
||||
(repo_slug → webhook_url) and delivery infrastructure (retry, dead-letter).
|
||||
Defer until inbox-first approach proves insufficient for ≥1 real case.
|
||||
status: open
|
||||
priority: low
|
||||
```
|
||||
|
||||
No implementation. Documents the deliberate deferral and records the design
|
||||
direction so it is not re-invented later.
|
||||
|
||||
Acceptance: EP registered, retrievable via `GET /extension-points/?domain=custodian`.
|
||||
Reference in New Issue
Block a user