Commit Graph

44 Commits

Author SHA1 Message Date
55e36bdf2d feat: add State Hub bulk status skill 2026-06-07 20:11:07 +02:00
2cad5da0ab fix: harden MCP write tool errors 2026-06-07 19:30:58 +02:00
38835e9e79 feat(tasks): adopt canonical task statuses 2026-05-26 01:32:50 +02:00
d6522a9a40 Complete workplan state model cleanup 2026-05-18 01:31:36 +02:00
5429340f21 Improved workplan dependency management facilities 2026-05-04 11:45:24 +02:00
a8228fc780 railiance-bootstrap to railiance-cluster rename cleanup 2026-05-03 16:30:07 +02:00
a00f1b615b Task flow engine implementation 2026-05-02 00:21:14 +02:00
c9695d51b1 Implemented Ad-Hoc Task handling 2026-05-01 21:27:52 +02:00
548c3efe4a feat(state-hub): Interface Change Registry (CUST-WP-0033 T01-T06)
Adds first-class tracking for API and interface mutations across the
agent ecosystem. Breaking changes are documented, affected repos are
notified via inbox, and agents discover pending changes at session
start via the dispatch endpoint.

- Migration q4l5m6n7o8p9: interface_changes table
- Model/schema: InterfaceChange with draft→published→resolved lifecycle
- Router: POST/GET/PATCH /interface-changes/, /publish, /resolve actions
  (auto-notify affected repo agents on publish; progress event on origin)
- Dispatch: GET /repos/{slug}/dispatch now returns pending_interface_changes
- MCP tools: register_interface_change, list_interface_changes,
  publish_interface_change, resolve_interface_change
- Dashboard: /interface-changes page with type badges, planned calendar,
  published cards, and draft table
- EP-CUST-ICR-001 registered: webhook subscriptions (deliberately deferred)

First record: trailing-slash normalisation (2026-04-26), published,
affecting repo-registry — visible in repo-registry dispatch immediately.

223 tests passing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 15:29:08 +02:00
09bbf62430 feat(capability-registry): CUST-WP-0031 domain capability registry
- Migration p3k4l5m6n7o8: nullable repo_id FK on capability_catalog
- PATCH /capability-catalog/{id} endpoint for back-filling repo attribution
- register_capability MCP tool accepts optional repo_slug
- get_domain_summary now includes compact capabilities list (type+title+repo_slug)
- New get_capability_profile MCP tool: domain → repos → capabilities tree
- 6 repo descriptions populated; 25 catalog entries attributed to repos
- 9 new capabilities registered for personhood, foerster_capabilities, coulomb_social
- TOOLS.md: Capability Catalog & Requests section with full tool reference

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 17:23:45 +02:00
af3fdfde80 feat(token-tracking): introduce token note taxonomy (measured/userbased/workplan/heuristic)
Tier 1 (exact counts) now defaults to note="measured" instead of null,
signalling the counts were read from the Claude Code status bar.
Callers can pass note="userbased" when a human provided the numbers.

  measured  — agent read exact counts from the Claude Code status bar
  userbased — counts provided by a human
  workplan  — prorated from workplan total across task count
  heuristic — server fallback, 1000/500, no agent input

Added token_note field to TaskUpdate schema and exposed note param on
update_task_status and record_interactive_task MCP tools.
TOOLS.md documents the full taxonomy. 185 tests pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-29 18:47:40 +02:00
8c87a9a799 feat(token-tracking): add record_interactive_task MCP tool
New tool for capturing ad-hoc work done outside formal workplans.
Finds or creates a persistent 'interactive-<repo>' workstream for the
repo, creates the task, marks it done, and records a token event using
the three-tier logic — all in a single call.

Seeded two example events on interactive-the-custodian:
  - Three-tier token recording on task done (8000/3500)
  - Add record_interactive_task MCP tool (4500/1800)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-29 18:36:51 +02:00
fdfd4365cd feat(token-tracking): three-tier token recording on task done
Token events are now always created when update_task_status is called
with status="done", using the best available data:

  Tier 1 (best): exact tokens_in + tokens_out passed by agent
  Tier 2:        workplan_tokens_in + workplan_tokens_out prorated
                 across workstream task count (note="workplan")
  Tier 3 (fallback): heuristic 1000 in / 500 out (note="heuristic")

Non-done status changes never create a token event.
MCP tool updated with workplan_tokens_in/out params and tiered docs.
Ralph-workplan skill files updated with the three-tier guidance.
184 tests pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-29 18:28:18 +02:00
58e1bafce9 feat(token-tracking): record AI token consumption per task (CUST-WP-0029)
Introduces end-to-end token consumption tracking so agent work is
visible as a cost/effort metric alongside tasks and workplans.

- Migration o2j3k4l5m6n7: token_events table with FK indexes on
  task_id, workstream_id, repo_id, created_at
- ORM model, Pydantic schemas (TokenEventCreate, TokenEventRead with
  computed tokens_total, TokenSummary)
- Router: POST /token-events/, GET /token-events/ (7 filters),
  GET /token-events/summary/ (task|workstream|repo|commit|release scope)
- MCP tools: record_token_event, get_token_summary (formatted table)
- update_task_status enriched with optional tokens_in/tokens_out
  passthrough — one call creates status update + token event
- Dashboard token-cost.md page: by-repo bar, by-workplan table,
  by-model bar, top-10 tasks by tokens
- ralph-workplan skill updated with token reporting guidance and
  per-task heuristics for estimating counts
- Tests: test_token_events.py + test_token_passthrough.py (182 pass)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-29 17:46:46 +02:00
3f96dc035d feat(mcp): add create_topic tool
POST /topics/ was already implemented in the REST API but had no MCP
wrapper, so agents couldn't create topics (e.g. inter_hub) via MCP.
Tool follows the same pattern as create_domain.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-28 01:32:52 +01:00
c5c8ee52eb fix(state-hub): fix mcp-http startup crash and remove legacy tunnel targets
- Add `Optional` to typing imports in mcp_server/server.py — it was used
  in 13 annotations but never imported, crashing FastMCP v3 at startup
- Remove legacy tunnel/tunnel-daemon/tunnel-loop/tunnel-status/tunnel-stop
  targets from Makefile; ops-bridge (tunnels-up/status/check) supersedes them

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 22:32:51 +01:00
b3a44fb4f3 feat(capability-requests): add routing dispute & reroute workflow (CUST-WP-0027)
Adds a structured dispute mechanism when capability request routing is wrong:
- New `routing_disputed` status with four DB columns (dispute_reason, disputed_by,
  dispute_suggested_domain, disputed_at) via Alembic migration m0h1i2j3k4l5
- POST /capability-requests/{id}/dispute — any party can flag misrouting with a reason
  and optional suggested domain; notifies custodian + current fulfilling domain
- POST /capability-requests/{id}/reroute — custodian re-routes to correct domain via
  catalog_entry_id or direct slug; appends audit trail to routing_note; resets to requested
- Two new MCP tools: dispute_capability_routing and reroute_capability_request
- Dashboard: amber disputed-banner at top of Summary, routing_disputed Kanban column,
  dispute details (reason, suggested domain, raised-by) shown on disputed cards

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 23:58:52 +01:00
62d407cae7 feat(capability-requests): add routing_note, PATCH endpoint, word-boundary fix, and ops-bridge tunnel targets
- Add `routing_note` column (migration l9g0h1i2j3k4) to persist why a request was routed to a given domain
- Fix substring-match bug in `_route_capability`: use `\b` word-boundary regex so 'postgres' no longer matches inside 'postgresql'
- Include `title` in keyword scoring for better routing accuracy
- Return `routing_note` string from `_route_capability` and store it on the request
- Add `PATCH /capability-requests/{id}` endpoint + `CapabilityRequestPatch` schema to correct mutable metadata (catalog_entry_id, priority, blocking_task_id, fulfilling_workstream_id)
- Add `patch_capability_request` MCP tool wrapping the new endpoint
- Add 105 lines of routing tests (word-boundary, title-match, multi-entry scoring, broadcast fallback)
- Add `tunnels-up`, `tunnels-status`, `tunnels-check` Makefile targets for ops-bridge managed tunnels

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 03:47:54 +01:00
5eeeeeb6c4 feat(doi): Repository DoI automated gate and dashboard integration (CUST-WP-0024)
Implements the 14-criterion DoI checklist as a runnable gate with API,
MCP tools, CLI script, and dashboard integration.

Core components:
- api/doi_engine.py — async engine evaluating all 14 criteria (asyncio.to_thread
  for non-blocking HTTP self-calls), shared by API and CLI
- api/schemas/doi.py — DoICriterion, DoIReport, DoISummaryEntry schemas
- api/routers/repos.py — GET /repos/{slug}/doi + GET /repos/doi/summary
- scripts/check_doi.py — CLI: make check-doi REPO=<slug> / check-doi-all
- mcp_server/server.py — check_repo_doi(), get_doi_summary() tools

Dashboard (repos.md):
- DoI tier badge per repo (None/Core/Standard/Full) colour-coded red→green
- Domain block shows lowest DoI tier across its repos
- DoI KPI card in summary row
- DoI filter in All Repos Table
- Link to Repository DoI policy page

Also fixes: TPSC snapshots 500 error (missing nested selectinload for
catalog_entry relationship in list_snapshots endpoint).

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 01:08:18 +01:00
60beb1ff35 feat(tpsc): Third-Party Services Catalog (CUST-WP-0023)
Introduces TPSC for tracking external service dependencies with GDPR
compliance maturity (CNIL/IAPP CMMI scale), pricing model, ToS, and
data retention information across all repos.

Primary data:
- canon/tpsc/{openai,anthropic,gemini,openrouter}-api.yaml — service definitions
- tpsc.yaml in each repo (llm-connect seeded with 4 services)

State-hub additions:
- Migration j7e8f9a0b1c2: tpsc_catalog + tpsc_snapshots + tpsc_entries
- api/models/tpsc.py, api/schemas/tpsc.py, api/routers/tpsc.py
- /tpsc/catalog/, /tpsc/ingest/, /tpsc/snapshots/, /tpsc/report/gdpr endpoints
- 4 MCP tools: register_service, list_services, ingest_tpsc_tool, get_gdpr_report
- scripts/ingest_tpsc.py + make ingest-tpsc[/-all] targets
- Dashboard: tpsc.md page + docs/tpsc.md

GDPR maturity scale: unknown | non_compliant | initial | developing | defined | managed | certified
Warnings triggered at: unknown, non_compliant, initial

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 00:15:26 +01:00
4e28cab297 fix(mcp): resolve repo paths with existence check before trusting hostname match
Stale host_paths entries (wrong username, old machine) were silently overriding
the correct local_path, causing FileNotFoundError on tools like list_kaizen_agents.

Extracts _resolve_repo_path(repo) helper that tries host_paths[hostname] first
but validates the path exists on disk before trusting it, then falls back to
local_path. Both candidates support ~ expansion. Applied to all 4 call sites:
_kaizen_agents_dir, validate_repo_adr, check_repo_consistency, ingest_sbom_tool.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 21:38:35 +01:00
d45234531b feat(capability-requests): add cross-domain capability catalog and request routing
Introduces a capability catalog (CUST-WP-0022) so domains can advertise what
they provide and agents can request capabilities from other domains with
auto-routing, lifecycle tracking, and task-unblocking on completion.

- New models: CapabilityCatalog, CapabilityRequest with full lifecycle
  (requested → accepted → in_progress → ready_for_review → completed/rejected/withdrawn)
- Migration i6d7e8f9a0b1: capability_catalog + capability_requests tables
- Router /capability-catalog and /capability-requests with accept/status endpoints
- 7 new MCP tools: register_capability, list_capabilities, request_capability,
  accept_capability_request, update_capability_request_status,
  list_capability_requests, get_capability_request
- StateSummary gains open_capability_requests count
- Dashboard: capability-requests.md page + docs/capabilities.md + docs/scope.md
- SCOPE.md: three seed capabilities documented (MCP registration, state tracking, SBOM)
- scope.template: Provided Capabilities section with example block
- scripts/ingest_capabilities.py + make ingest-capabilities[/-all] targets

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 21:07:50 +01:00
15b72c6739 feat(mcp): add list_tasks(workstream_id) tool — resolves FR 7074fd47
Agents had no way to look up task UUIDs by workstream; they were stuck
unable to call update_task_status without already knowing the UUID.
list_tasks() wraps GET /tasks with workstream_id filter, returning
[{id, title, status, priority}] for all matching tasks.

FR raised by kaizen-agentic worker on COULOMBCORE while syncing
KAIZEN-WP-0002 task IDs. Marked merged in contributions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-18 23:01:22 +01:00
4feba3e8d2 feat(CUST-WP-0021): multi-host repo path hardening — all 5 tasks complete
- T01 (done prior): registered host_paths for bnt-lap001 (14 repos) and
  COULOMBCORE (6 repos) via POST /repos/{slug}/paths/
- T02: validate_repo_adr now accepts repo_slug (not raw path); resolves
  local path via host_paths[hostname] → local_path; clear error for
  unregistered/missing paths
- T03: ingest_sbom_tool lockfile_path is now optional and relative to
  resolved repo root; absolute paths accepted with deprecation warning
- T04: check_repo_consistency pre-flight guard — fetches repo, resolves
  path, returns clear error before spawning subprocess if path missing
- T05: TOOLS.md — updated validate_repo_adr row (slug not path);
  added Multi-Host & Remote Agent Usage section documenting design
  boundary, remote agent workflow, and update_repo_path usage

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-18 22:53:25 +01:00
2d0ce8f943 feat(api): CUST-WP-0018 — API hardening & code quality
T01: Fix datetime.utcnow() → datetime.now(tz=timezone.utc) in MCP server
T02: Wrap _get/_post/_patch/_delete with try/except; return error dicts
T03: Log warnings when write_log skips missing project path
T04: Add priority + due_date_before filters to GET /tasks/
T05: Add owner + slug filters to GET /workstreams/
T06: Add offset param to GET /progress/ for proper pagination
T07: Low-severity bundle:
  - CORS origins from CORS_ORIGINS env var (TD-017)
  - seed.py upsert domains+topics on re-run (TD-011)
  - normalise filter bar CSS → filter-text-input everywhere (TD-016)
  - add 30.5 avg-days-per-month comment in decisions.md (TD-019)
  - TD-009, TD-018 already resolved by existing code

Closes CUST-WP-0018.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-18 02:17:04 +01:00
cb2c4f9a0c fix(mcp): accept JSON string for add_progress_event detail param
FastMCP validates dict | None strictly, rejecting a JSON string even if
parseable. Broaden to dict | str | None and coerce in the function body
so callers don't need to pre-parse the detail payload.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-18 02:11:35 +01:00
8619cd2218 feat(CUST-WP-0016): kaizen-agentic integration — MCP tools, templates, direct install
- Fix /domains/{slug}/ 500: EP/TD queries now use domain_id FK (not string column)
- Remove dead cascade-slug code in rename_domain (FK handles it)
- MCP: list_kaizen_agents(category?) + get_kaizen_agent(name) via resolve_repo_path()
- TOOLS.md: Kaizen Agents section with discovery/load pattern
- agents.template: new project rule for consumer repos
- claude-md.template + register_project.sh: include agents.md in new-project scaffolding
- agents/: direct install of 6 curated agents for hub sessions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 22:24:30 +01:00
82552b8d59 feat(repos): multi-machine path support via host_paths
Adds a JSONB column `host_paths` to managed_repos mapping
hostname → absolute local path. Fixes the consistency-checker
failure when the same repo lives at different paths on different
machines (e.g. /home/worsch/marki-docx on the workstation vs
/home/tegwick/marki-docx on custodiancore).

Changes:
- Migration g4b5c6d7e8f9: adds host_paths JSONB (default {})
- Model: host_paths Mapped[dict] column
- Schemas: host_paths in RepoRead; new RepoPathRegister schema
- Router: POST /repos/{slug}/paths/ — merges one host entry
- consistency_check.py: resolve_repo_path() prefers host_paths
  [hostname] over local_path; --repo-path CLI override added
- MCP: update_repo_path(slug, path, host?) tool
- Makefile: register-path target; REPO_PATH passthrough on
  check-consistency and fix-consistency targets
- TOOLS.md: documents update_repo_path

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 16:30:55 +01:00
4b3cb1b039 feat(CUST-WP-0015): implement agent inbox for inter-agent coordination
Adds a message-passing layer to state-hub so Claude instances can
coordinate across sessions without polling shared progress events.

- Migration f3a4b5c6d7e8: agent_messages table with thread support
- FastAPI router: POST/GET /messages/, thread view, mark-read, archive, reply
- 4 MCP tools: send_message, get_messages, mark_message_read, reply_to_message
- Observable dashboard: /inbox page with unread/read/archived sections + KPI
- CLAUDE.md updates: global, custodian, marki-docx, activity-core, template
- TOOLS.md: Agent Inbox tools section documented

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 02:55:45 +01:00
5e7a72e144 feat(CUST-WP-0014): repo sync automation & Gitea inventory
- Migration e2f3a4b5c6d7: add last_state_synced_at to managed_repos
- consistency_check.py: PATCH last_state_synced_at after fix run;
  fix ~ treated as non-empty state_hub_task_id (C-03 vs C-11);
  fix _inject_task_id_into_block skipping injection when field exists
  with null value
- install_hooks.sh: idempotent post-commit hook installer for all
  registered repos (make install-hooks REPO= / install-hooks-all)
- gitea_inventory.py: compare coulomb Gitea org against state-hub
  registered repos — registered / unregistered / hub-only sections
- infra/README.md: document systemd user timer + crontab fallback
- systemd user timer: custodian-sync.{service,timer} runs
  fix-consistency-all every 15 min (enabled)
- dashboard/src/repo-sync.md: Repo Sync Health page — sync age table,
  unregistered Gitea repos, hub-only repos
- api/routers/repos.py: GET /repos/{slug}/dispatch endpoint returning
  active goal, pending tasks per workstream, human interventions
- mcp_server/server.py: get_repo_dispatch() MCP tool

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 01:41:16 +01:00
f3fca3088f feat(ops-bridge): add HTTP/SSE MCP transport for remote Claude Code sessions
server.py: MCP_TRANSPORT and MCP_PORT env vars select transport at startup
  (default: stdio — no behaviour change for local use)
Makefile: `make mcp-http` starts SSE server on 127.0.0.1:8001

Remote registration (one-liner on COULOMBCORE after tunnel is up):
  claude mcp add-json -s user state-hub \
    '{"type":"sse","url":"http://127.0.0.1:18001/sse"}'

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 00:13:14 +01:00
651df73e3a feat(goals): add domain/repo goal tracking and update_workstream MCP tool
- Migration c5d6e7f8a9b0: domain_goals and repo_goals tables, repo_goal_id FK on workstreams
- DomainGoal: one active per domain (partial unique index), status active/archived/superseded
- RepoGoal: integer priority, status active/paused/completed/archived, optional domain_goal_id link
- WorkstreamUpdate schema and router extended with repo_goal_id and repo_goal_id filter
- 6 new MCP goal tools: create_domain_goal, get_domain_goals, activate_domain_goal, create_repo_goal, get_repo_goals, update_repo_goal
- update_workstream MCP tool: patch any subset of workstream fields (title, description, owner, due_date, repo_goal_id, status)
- get_domain_summary extended with goal_guidance (needs_workplan, alignment_warnings) signals
- Dashboard goals.md page and docs/goals.md reference page
- CLAUDE.md template updated to act on goal_guidance signals at session start
- CUST-WP-0010 workplan for this feature

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-09 00:15:29 +01:00
c792ab0bc0 feat(tasks): add needs_human intervention flag (CUST-WP-0009)
- Migration b4c5d6e7f8a9: adds needs_human (bool) + intervention_note (text) to tasks
- API: needs_human filter on GET /tasks/; 422 if flagged without note
- 3 MCP tools: flag_for_human, clear_human_flag, list_human_interventions
- Dashboard: interventions.md with amber cards and "Mark done" button
- Policy router + workstream DoD policy (workstream-dod.md)
- Workstream lifecycle docs page + workplan CUST-WP-0010
- CLAUDE.md: add step 4 (run fix-consistency after workplan writes)
- consistency_check.py: promote C-11 unlinked tasks from INFO to WARN

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-04 19:44:14 +01:00
5c1b7e7e1d feat(consistency): implement ADR-001 consistency checking engine (CUST-WP-0008)
Adds state-hub/scripts/consistency_check.py with C-01 through C-12 checks:
bidirectional file↔DB validation, --fix for auto-fixable issues, --all for all
repos, --json output, exit codes 0/1/2.

MCP tool: check_repo_consistency(repo_slug, fix=False)
Makefile: check-consistency, fix-consistency, check-consistency-all, fix-consistency-all

Auto-fixes applied across all repos:
- C-09: activity-core-foundation + activity-core-triggers-ops repo_id → activity-core
- C-04: railiance phase-0-operational-baseline status → completed
- C-05: railiance phase-0 title synced from file
- C-10/C-11: task status drifts resolved; state_hub_task_id injected into
  CUST-WP-0006 and CUST-WP-0007 task blocks

Remaining orphans reported for human review: repo-integration-activity-core,
infospace-s3-closeout, testdrive-jsui-publication, staged-promotion-lifecycle,
three-phoenix-ha-cluster, current-env-safety-net.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-03 08:16:00 +01:00
fc87e26b4b feat(gems): three-pass schema migration aligning state-hub with GEMS
Implements CUST-WP-0007. Resolves inconsistencies I-1, I-2, I-5, I-6
identified in the GEMS audit (GenericEntityModellingSystem.md).

Pass 1 (e1f2a3b4c5d6): domain_id FK on extension_points and
technical_debt (replaces raw string column); repo_id FK on contributions.
Fixes domain-filtering bugs in EP/TD dashboard pages.

Pass 2 (f2a3b4c5d6e7): repo_id nullable FK on workstreams, aligning
the GEMS primary attachment with ADR-001 (repo > topic). Dashboard
pages updated to prefer repo->domain over topic->domain.

Pass 3 (a3b4c5d6e7f8): SBOMSnapshot container entity (GEMS Complex
between Repository and SBOMEntry). Ingest is now additive — each call
creates a new snapshot; history is retained. List/report endpoints
filter to latest snapshot per repo via _latest_snapshot_ids_subquery().
New endpoints: GET /sbom/snapshots/, GET /sbom/snapshots/{id}/.
Dashboard gains a Snapshot History section.

Also adds GEMS analysis artefacts: wiki/GEMS-StateHub-TypeRegistry.md,
wiki/GEMS-StateHub-SWOT.md, workplans/CUST-WP-0006 (analysis),
workplans/CUST-WP-0007 (migration, now completed).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 23:39:17 +01:00
70c8e3cd51 feat(mcp): add get_domain_summary() for low-token domain session orientation
get_state_summary() returns ~10k tokens — too expensive for routine domain
repo sessions that only need their own workstreams and decisions.

New get_domain_summary(domain_slug):
- 5 targeted API calls: topics (filter), workstreams (topic+status), decisions
  (topic+pending), progress (topic, limit 5), repos (domain, slug+SBOM only)
- Returns: topic, active workstreams, blocking decisions, 5 recent events,
  repo SBOM status — all scoped to one domain
- Estimated ~80-90% token reduction vs get_state_summary()

get_state_summary() preserved unchanged for cross-domain / custodian sessions.
Updated its docstring to note the large response and point to get_domain_summary.

Template updated: Step 1 now calls get_domain_summary("{DOMAIN}") instead of
get_state_summary() + get_next_steps(). TOOLS.md updated with usage guidance.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-01 22:05:31 +01:00
afac54ec09 feat(state-hub): v0.3 MCP tools + dashboard pages for contributions and SBOM
MCP server additions (5 tools + 3 resources):
- register_contribution(), update_contribution_status(), get_contributions()
- ingest_sbom_tool(repo_slug, lockfile_path) — shells out to ingest_sbom.py
- get_licence_report()
- state://contributions, state://sbom/aggregated, state://sbom/{repo_slug}

Dashboard pages:
- contributions.md — live-polled Kanban by status (draft→merged), filter bar
  (type/status/repo), KPI grid (total + per type), follow-up banner, full table
- sbom.md — licence distribution bar chart (Plot), copyleft risk section,
  package table with ecosystem/direct/dev filters, repo-slug resolution
- data/contributions.json.py, data/sbom.json.py — Observable data loaders
- index.md — added Contribution & SBOM Health KPI row (total, follow-up count,
  copyleft risk indicator; sourced from state summary fields)
- observablehq.config.js — added Contributions + SBOM to nav

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28 17:28:41 +01:00
fcd0f06536 feat(state-hub): implement v0.5 — dynamic domains & multi-repo
Replaces the hardcoded 6-domain PostgreSQL ENUM with a first-class
`domains` DB table, and adds a `managed_repos` table for multi-repo
support per domain.

P1 — Domain as a DB entity:
- Migration b1c2d3e4f5a6: creates `domains` table, migrates topics.domain
  ENUM column to domain_id FK, drops the domain ENUM type
- Domain ORM model (api/models/domain.py) + Pydantic schemas
- Domain API router: GET/POST /domains/, GET/PATCH /domains/{slug}/,
  rename and archive endpoints with EP/TD cascade on rename
- Topic model updated: domain_id FK + @property domain_slug for
  backwards-compatible JSON serialization (field renamed domain → domain_slug)
- TopicCreate/TopicRead updated; seed.py rewritten to use FK lookup

P2 — Multi-repo support:
- ManagedRepo ORM model (api/models/managed_repo.py) + schemas
- Repo API router: GET/POST /repos/, GET/PATCH /repos/{slug}/, archive
- Makefile: add-domain, rename-domain, add-repo, list-repos targets
- register_project.sh: verify domain via /domains/ API + POST /repos/

P3 — MCP tools & live validation:
- 6 new MCP tools: list_domains, create_domain, rename_domain,
  archive_domain, list_domain_repos, register_repo
- EP/TD routers: replace hardcoded VALID_DOMAINS set with per-request
  DB lookup — returns 422 with list of valid slugs on unknown domain
- State summary: adds domains: list[DomainSummary] (slug, name,
  repo_count, active_workstream_count, ep_count, td_count)
- TOOLS.md updated with domain management section

P4 — Dashboard:
- New domains.md page with KPI row + domain cards + repo lists
- domains.json.py + repos.json.py data loaders
- Domains page added to observablehq.config.js nav
- workstreams.md, extensions.md, techdept.md: domain_slug fix +
  dynamic domain list loaded from /domains/ API (no longer hardcoded)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28 15:20:15 +01:00
c3efb099f1 feat(custodian): add ADR-001 compliance validator
Scripts, Makefile target, and MCP tool for checking a repository
against ADR-001 (workplans as repo artefacts, state-hub as cache).

Checks performed:
  File-side: workplans/ dir exists, valid YAML frontmatter (required
  fields, type, status, id format), filename matches id, embedded
  task blocks have id/status/priority.

  State-hub cross-reference: state_hub_workstream_id references
  resolve to real DB records; orphan detection flags active DB
  workstreams with no backing workplan file.

Usage:
  make validate-adr REPO=<path> [DOMAIN=<slug>]
  validate_repo_adr(repo_path, domain_slug?)  # MCP tool

Running against the-custodian itself correctly surfaces the 4
pre-ADR-001 workstreams that still need workplan files written.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28 12:00:09 +01:00
090a206f3d feat(state-hub): add Extension Points and Technical Debt tracking
New entity types (DB tables, API routers, Pydantic schemas, Alembic
migration a3f1c2d4e5b6):
- extension_points: ep_id, domain, title, ep_type, status, priority,
  location, description, topic_id, workstream_id
- technical_debt: td_id, domain, title, debt_type, severity, status,
  location, description, topic_id, workstream_id

MCP server: 6 new tools — register_extension_point, list_extension_points,
update_ep_status, register_technical_debt, list_technical_debt,
update_td_status (each write emits a progress_event)

Dashboard: two new pages (extensions.md, techdept.md) with KPI sidebar,
charts, urgent-items section, and filterable card lists. Both added to
nav in observablehq.config.js.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 07:29:51 +01:00
f34b49ebde Implement State Hub v0.2: dependency graph, next-steps suggestions, design boundary
S0 — Design boundary formalised across all integration surfaces:
- TOOLS.md restructured with Design Boundary section, Sanctioned Write Tools,
  and Bootstrap-Only Tools (create_workstream, create_task) with explicit note
- project_claude_md.template and railiance CLAUDE.md updated with boundary note
  and get_next_steps() in session start protocol
- Global ~/.claude/CLAUDE.md updated accordingly

S1 — Workstream dependency graph:
- WorkstreamDependency model (directed edge, CASCADE on delete, unique pair constraint)
- Alembic migration 0b547c153153; script.py.mako added (was missing)
- REST API: POST/GET /workstreams/{id}/dependencies/, DELETE …/{dep_id} (hard delete)
- StateSummary open_workstreams enriched with depends_on/blocks lists
- MCP tools: create_dependency(), list_dependencies()
- Dashboard workstreams page: Dependencies section with relationship cards
- Seeded: custodian-agent-runtime → llm-shared-library + phase-0-operational-baseline

S2 — Suggesting Next Steps (sanctioned write use case #2):
- GET /state/next_steps derives suggestions from recently resolved decisions
  (→ first open task in same workstream) and cleared dependencies
  (→ first todo task in now-unblocked workstream)
- StateSummary.next_steps included on every summary call
- MCP tool: get_next_steps()
- Dashboard: "What's next?" card grid above Registered Projects

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-25 23:33:14 +01:00
379a3b1a01 Fix MCP server httpx redirect handling
Add follow_redirects=True to httpx Client so 307 redirects (FastAPI
trailing-slash redirects) are followed transparently. Also add trailing
slash normalisation to _get and _patch to match existing _post behaviour,
so all three helpers hit the correct URLs on first attempt.

Requires Claude Code restart to take effect (MCP server is a subprocess
launched at startup).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-25 00:21:09 +01:00
ebe7369249 Add create-workstream: MCP tool, CLI commands, dashboard hint
MCP server: add create_workstream(topic_id, title, slug?, owner?,
  description?, due_date?) — auto-generates slug from title if omitted;
  emits workstream_created progress event. Now 12 tools total.

CLI: add two new subcommands —
  custodian create-workstream --domain DOMAIN --title TITLE [--slug] [--owner] [--description]
  custodian create-task --workstream ID_OR_SLUG --title TITLE [--priority] [--assignee]
  create-task accepts workstream UUID or slug (resolves via API).

Dashboard: hint box below "Open Workstreams by Domain" chart listing
  registered domains that have zero workstreams, with the exact
  custodian create-workstream command to run.

TOOLS.md: updated tool count (11 → 12) and added create_workstream row.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-24 23:35:54 +01:00
0ea2788943 Add state-hub v0.1 — local-first state service for the Custodian
Implements the first live layer of the Custodian cognitive infrastructure:
PostgreSQL schema, FastAPI REST API, FastMCP stdio server, and Observable
Framework telemetry dashboard.

- state-hub/: full stack (docker-compose, FastAPI, Alembic, MCP server, dashboard)
- 5 DB tables: topics, workstreams, tasks, decisions, progress_events
- 11 MCP tools + 5 resources registered in .mcp.json
- Observable dashboard: Overview, Workstreams, Decisions, Progress pages
- CLAUDE.md: session protocol (get_state_summary / add_progress_event ritual)
- ~/.claude/CLAUDE.md: global cross-project reference to the hub
- scripts/pull_image.py: WSL2 TLS-resilient Docker image downloader

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-24 17:47:49 +01:00