Files
the-custodian/workplans/CUST-WP-0033-interface-change-registry.md
tegwick f99d77d539 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-01:
  - update .custodian-brief.md for the-custodian
2026-05-01 00:55:53 +02:00

5.9 KiB

id, type, title, domain, repo, status, owner, topic_slug, created, updated, concept, state_hub_workstream_id
id type title domain repo status owner topic_slug created updated concept state_hub_workstream_id
CUST-WP-0033 workplan Interface Change Registry — Coordinated API Evolution custodian the-custodian done custodian custodian 2026-04-26 2026-04-26 canon/projects/custodian/interface_change_registry_v0.1.md 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

id: CUST-WP-0033-T01
status: done
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

id: CUST-WP-0033-T02
status: done
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

id: CUST-WP-0033-T03
status: done
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-scoping/dispatch returns pending_interface_changes list (empty or populated); no regression on existing dispatch tests.

T04: MCP tools

id: CUST-WP-0033-T04
status: done
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

id: CUST-WP-0033-T05
status: done
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

id: CUST-WP-0033-T06
status: done
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.