Commit Graph

88 Commits

Author SHA1 Message Date
b744a0de2c fix(template): replace get_state_summary with get_domain_summary in domain CLAUDE.md template
Avoids ~12.9k token response in domain repo sessions; get_domain_summary
returns the same actionable data scoped to the domain at ~10% of the cost.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 09:09:01 +01:00
05c2b50e3e fix(workplan): mark CUST-WP-0006 T05 as done
CUST-WP-0007 (the three-pass GEMS migration) was completed 2026-03-02.
T05 was left as blocked on the six GEMS decisions; synced to done.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-04 23:33:00 +01:00
b9f5d46428 feat(dashboard): Interventions page improvements and action-confirm modal
- Move Interventions under Workstreams in the navigator
- Add action-confirm.js: shared modal component for actions requiring a
  mandatory comment (survives live-poll re-renders, unlike inline DOM mutation)
- Wire action-confirm into Interventions (Mark done) and Decisions (Resolve)
- Fix Interventions completed section: fetch all tasks and filter client-side
  so resolved interventions (needs_human=false) still appear under Completed
- Add docs/interventions.md help page with ? button on the h1
- Replace all hardcoded "Bernd" with "human" across dashboard src and docs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-04 23:15:06 +01:00
25b4dd07f5 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
44c19c422f 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
8ab6e6c9c5 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
23bf21d40d feat(sbom): add custodian ingest-sbom + fix help button target
custodian_cli.py:
- new ingest-sbom subcommand: auto-detects repo slug from local_path
  registration, runs ingest_sbom.py --scan from the repo root
- --dry-run flag passes through to the underlying script
- --slug override for repos where path lookup fails

repos.md:
- ? button on "⚠ not ingested" now opens /docs/sbom (not /docs/repos)

docs/sbom.md:
- Ingest commands section now leads with `custodian ingest-sbom` (repo-root)
- make ingest-sbom kept as low-level alternative
- Per-ecosystem and gap-type references updated to new command

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 13:31:08 +01:00
a5058dad3c feat(repos): add ? help button to SBOM "not ingested" cells
Each "⚠ not ingested" entry in the Coverage Map now shows a hoverable ?
button linking to /docs/repos (SBOM ingestion section).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 13:14:16 +01:00
7607318a4a docs(onboarding): mention /init to trigger integration in step 3
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 11:16:08 +01:00
d7c4bd5802 feat(onboarding): redesign repo integration journey
custodian_cli.py:
- register-project now writes CLAUDE.custodian.md (suggestion) instead
  of overwriting CLAUDE.md; includes preamble with integration instructions
- registers repo via POST /repos/
- creates a "Repo Integration: {slug}" workstream in the domain's topic
  with 4 onboarding tasks (integrate CLAUDE.md, first workplan, SBOM,
  EPs/TDs); checks for existing workstream to be idempotent
- fixes {REPO_SLUG} template substitution (previously missing)

dashboard:
- repos.md: fetches workstreams; detects active repo-integration-* slugs;
  adds "Integrating" KPI card; shows ⚙ integrating badge per repo in
  coverage map and table; replaces "How to Ingest a Repo" with
  "Onboard a New Repo" 4-step panel with doc help button
- docs/repo-integration.md (new): full collaboration model doc — custodian
  as coach, repo agent as executor; journey, generated tasks, first session
  protocol, ongoing relationship
- docs/repos.md: links to new repo-integration doc; updates "What is a
  managed repo?" section; adds onboarding quick reference
- docs/reference.md: fix latent build error — code examples were in ```js
  fences (executed by OF); changed to ```javascript (display only)
- observablehq.config.js: adds "Repo Integration" to Reference nav

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 08:42:30 +01:00
1efa3ae13a feat(registration): write CLAUDE.custodian.md instead of overwriting CLAUDE.md
Instead of overwriting the target repo's CLAUDE.md, the registration
script now writes CLAUDE.custodian.md — a suggestion file with an
integration header. The repo's Claude agent integrates both files and
deletes the suggestion when done, preserving existing project conventions.

Also fix: `read` prompt now redirects from /dev/tty so the script
doesn't exit with code 1 when run non-interactively via make.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 01:30:28 +01:00
d96ed44c57 feat(maintenance): add stale-task cleanup scheme
- scripts/cleanup_stale_tasks.py: daily script that cancels open tasks
  in completed/archived workstreams; handles 307 redirects; emits a
  cleanup progress event summarising results
- Makefile: add cleanup-stale target (also suitable for cron)
- ADR-001: append Workstream Closure Protocol section — mandatory closure
  review before marking workstream completed, with task classification
  table (done/cancelled/carry-forward) and Closure Review file format
- WP-0002 + WP-0005: append Closure Review sections documenting the
  2026-03-02 cleanup run (26 stale DB rows cancelled — all were legacy
  pre-ADR-001 DB-first records; file status was already done)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 00:32:35 +01:00
412b7e6bf8 fix(dashboard): hide escalation notes on resolved/superseded decisions
- `escalated` filter now excludes decisions with status resolved or
  superseded — a lingering escalation_note on a closed decision no
  longer triggers the warning box or shows the amber note on the card
- Resolves D1 Vault backend appearing to re-surface an escalation alert

Also resolved ADR-001 decision (was made/open, now made/resolved);
overview blocking-decision count is now 0.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-01 23:57:30 +01:00
235355eb58 feat(dashboard): nav restructure, full context-help coverage, 11 new ref docs
Navigation:
- New order: Overview · Todo · Domains · Repos · Workstreams (collapsible,
  open:false, with atomic sub-entries: Decisions, Tasks, Debt, Extends,
  Dependencies) · Contributions · SBOM · Progress · Reference (collapsible)
- Reference section gains path:/reference landing page; all 18 doc pages
  listed in nav (alphabetical) and in reference.md table

New pages:
- todo.md — Internal / Ecosystem / Third-party todo classification
- dependencies.md — dependency edge table derived from state/summary
- reference.md — Reference landing page with full doc index

New reference doc pages (11):
  contributions, debt, dependencies, domains, extensions, overview,
  repos, tasks, todo + reference (meta) already added previously

doc-overlay.js — lazy bubblehelp tooltip:
- _titleCache Map + _fetchDocTitle(docPath): on first hover of any ?
  button, fetches the target doc page, parses <h1>, sets btn.title
- Native browser tooltip appears exactly on the ? circle on subsequent hover

Context-help wired on all 14 dashboard pages:
- h1 withDocHelp added to: index, todo, domains, repos, tasks, techdept,
  extensions, dependencies (contributions/workstreams/decisions/sbom/
  progress/reference were already wired)
- domains.md + repos.md: added missing withDocHelp import and live-data link
- tasks/techdept/extensions: removed duplicate _h1 const that caused
  SyntaxError: Identifier '_h1' has already been declared

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-01 23:46:26 +01:00
894c8b3934 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
b6121fd6d7 chore(dashboard): sort Reference nav pages alphabetically
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-01 21:09:32 +01:00
c2fc672a07 feat(dashboard): collapse Reference nav section by default
Observable Framework 1.13.3 supports collapsible: true on nav sections,
rendering them as <details> elements. Collapsed by default; auto-expands
when any page within the section is active.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-01 21:07:56 +01:00
f5d5fab46e feat(canon): add inter-repo communication standard with todo taxonomy
Establishes the repo boundary rule and a formal vocabulary for classifying
work items by scope:

- Task: neutral state hub data entity
- Todo: a task scoped to the current session's repo/domain
  - Internal todo: addressed within this repo by this agent
  - Ecosystem todo: work for another registered repo → state hub task [repo:<slug>]
  - Third-party todo: work for an upstream repo → contribution artifact (BR/FR/EP/UPR)

New dashboard doc: /docs/inter-repo-communication — defines the boundary rule,
the full terminology, ecosystem and third-party todo workflows, and a decision
table for classifying any piece of work found during a session.

Also:
- sbom.md: replace verbose inter-repo section with a 3-line summary + link
- observablehq.config.js: add "Inter-Repo Communication" to Reference nav
- project_claude_md.template: add "### Repo Boundary Rule" section; fix
  Workplan Convention section (removing incorrect claim that the custodian
  writes workplan files in other repos — that is the target repo's job)

Cross-repo: created state hub task [repo:railiance-bootstrap] for that repo's
agent to apply the boundary rule and workplan convention fix to its own CLAUDE.md
(task 78d43cb0, workstream 59155efb).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-01 20:52:07 +01:00
23ebb9c38f fix(template): use reliable workplan discovery in step 2
Glob with pattern 'workplans/*.md' from repo root fails silently.
Changed instruction to Glob(pattern="**/*.md", path="workplans/")
with Bash ls as fallback.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-01 20:13:31 +01:00
82afb8d316 fix(template): rewrite session protocol to produce concrete orientation output
The previous template only defined a First Session Protocol (triggered when no
workstreams existed). When workstreams did exist, get_state_summary() was called
but no output was defined, causing registered-repo Claude sessions to produce
nothing useful.

New 3-step normal session protocol:
- Step 1: get_state_summary() + get_next_steps()
- Step 2: scan workplans/*.md for active tasks (todo/in_progress)
- Step 3: output orientation brief covering active workstreams, pending tasks
  for this repo (from workplans/ + [repo:<slug>] state hub tasks), suggested
  next action, and SBOM status

Also strengthens First Session Protocol, ADR-001 workplan convention section,
and SBOM ingest section (adds SCAN=1 REPO_PATH= flags).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-01 20:05:16 +01:00
7df0152ca7 docs(sbom): add SBOM reference page + withDocHelp on SBOM dashboard
- docs/sbom.md: what SBOM is, lockfile semantics, 5-level maturity standard,
  gap types A–E, per-ecosystem guidance, Syft OSS tooling, inter-repo task
  communication convention, ingest commands, compliance check commands
- sbom.md: wire withDocHelp(h1, "/docs/sbom") — ? button on page title
- observablehq.config.js: add SBOM entry to Reference nav section

EP-CUST-002 registered: Syft-based comprehensive SBOM generation
Task 5f8cade5 created: [repo:railiance-bootstrap] Add Ansible lockfile

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-01 19:29:20 +01:00
6278c1c265 feat(dashboard): Repos page with coverage map; expose last_sbom_at on RepoRead
- RepoRead schema: add last_sbom_at + sbom_source fields (already in model,
  now surfaced in API response)
- repos.md: new dashboard page — KPI row (total/domains/ingested/gaps),
  domain-grouped coverage map with SBOM/EP/TD chips, per-repo table with
  gap highlighting, domain filter + gap-only toggle, ingest how-to section
- observablehq.config.js: add Repos after Domains in nav

Coverage state: 3 repos registered (custodian×1, railiance×2);
2 ingested (the-custodian + railiance-hosts), 1 gap (railiance-bootstrap
— infra-only, no lockfile, expected)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-01 18:53:25 +01:00
c90c7a7d97 feat(sbom): add Terraform .terraform.lock.hcl parser; ingest railiance repos
- ingest_sbom.py: parse .terraform.lock.hcl provider blocks (name, version);
  ecosystem stored as 'other' until terraform added to DB ENUM
- Registered railiance-bootstrap + railiance-hosts under railiance domain
- railiance-hosts ingested: 2 Terraform providers (hashicorp/template 2.2.0,
  hetznercloud/hcloud 1.52.0)
- railiance-bootstrap: no lockfile (pure Ansible/shell — noted in convention)
- sbom-convention_v0.1.md: add Terraform + Ansible rows to lockfile table;
  update registered repos status table

Total SBOM: 422 packages across 2 repos (custodian + railiance-hosts)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-01 18:07:56 +01:00
1c3c6ef27d feat(sbom): scan mode, domain grouping dashboard, SBOM convention doc
- ingest_sbom.py: add --scan flag (recursive lockfile discovery) +
  --lockfile repeatable for explicit multi-file ingestion; skip
  .venv/node_modules/.git/dist/etc; Makefile gains SCAN= and REPO_PATH= vars
- sbom.md: add /domains/ fetch; domain-level summary table; per-repo
  accordion with details/summary; domain filter on package table; dual-
  licence false-positive note; +1 KPI card (Domains Covered)
- canon/standards/sbom-convention_v0.1.md: authoritative lockfile table,
  ingest workflow (single/scan/explicit), snapshot semantics, direct-vs-
  transitive caveats, licence governance + copyleft escalation, update
  cadence, multi-repo domain pattern, planned enhancements

First ingest: the-custodian — 420 pkgs (88 python + 332 node), 13 licence
groups, 1 copyleft flag (jszip dual-licensed MIT OR GPL-3.0-or-later)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-01 16:15:40 +01:00
e471ed2cd5 feat(state-hub): v0.3 registration workflow + ingest-sbom + CLAUDE.md template update
- scripts/ingest_sbom.py: lockfile parser + API poster for uv.lock, requirements.txt,
  package-lock.json, yarn.lock, Cargo.lock; auto-detects from repo root
- Makefile: make ingest-sbom REPO=<slug> [LOCKFILE=<path>] target
- scripts/register_project.sh: adds {REPO_SLUG} template substitution + optional
  SBOM ingest prompt at end of registration (non-fatal if venv not ready)
- scripts/project_claude_md.template: adds Contribution Tracking + SBOM sections
  documenting register_contribution(), update_contribution_status(), ingest-sbom,
  and the contrib/ directory layout
- workplans/CUST-WP-0002: all 15 tasks → done, status → completed

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28 17:28:49 +01:00
8f34b3547f 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
755e94a2a0 feat(state-hub): v0.3 schema — contributions + sbom_entries migrations, models, schemas, routers
Migrations (chain: b1c2d3e4f5a6 → c2d3e4f5a6b7 → d3e4f5a6b7c8):
- c2d3e4f5a6b7: contributions table (contributiontype BR/FR/EP/UPR enum,
  contributionstatus 7-state lifecycle, FKs to topics/workstreams)
- d3e4f5a6b7c8: sbom_entries table (ecosystem enum, snapshot-based replacement),
  + sbom_source + last_sbom_at columns on managed_repos

New models: Contribution (ContributionType, ContributionStatus), SBOMEntry (Ecosystem)
Modified: ManagedRepo (sbom_source, last_sbom_at columns)

New routers:
- /contributions/ — CRUD + lifecycle-guarded PATCH /status + soft-delete (withdrawn)
- /sbom/ — ingest (replace snapshot), list, per-repo view, licence report

Modified:
- /state/summary now includes contribution_counts and licence_risk_count
- main.py: registers contributions + sbom routers; bumps version to 0.6.0

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28 17:28:27 +01:00
0d978b1417 feat(canon): add contribution-convention v0.1, contrib/ templates, and first UPR artifact
- canon/standards/contribution-convention_v0.1.md: master spec for BR/FR/EP/UPR
  artifact types, directory layout, frontmatter schema, ID schemes (EP-DOMAIN-NNN
  for extension points), status lifecycle, and relationship to State Hub
- canon/standards/contrib-templates/: four template files (br, fr, ep, upr)
- contrib/upstream-prs/2026-02-26--observablehq--framework--toc-sidebar-inject.md:
  first real UPR artifact — proposes injectTocTop() to Observable Framework

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28 17:28:13 +01:00
b949a11f20 fix(cli): auto-create topic when registering a brand-new domain
register-project now creates a topic automatically if the domain has
no active topic yet, instead of exiting with an error. This makes the
"create domain → register project" flow self-contained.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28 15:40:32 +01:00
6730720ce4 fix(cli): replace hardcoded VALID_DOMAINS with live /domains/ API lookup
The custodian CLI had a static VALID_DOMAINS list used as argparse
choices= and for in-process domain validation, preventing any domain
added after v0.5 from being used. Now fetches active domains from the
API at runtime. Also fixes t.get("domain") → t.get("domain_slug")
in two topic lookup sites.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28 15:39:34 +01:00
b6ec7c2ecb fix(dashboard): replace stale t.domain with t.domain_slug across all pages
After the v0.5 migration TopicRead.domain was renamed to domain_slug.
index.md, decisions.md and tasks.md still referenced the old field,
causing every workstream domain to fall back to "unknown". Also
updated tasks.md to load the domain filter list dynamically from
/domains/ instead of the hardcoded 6-slug array.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28 15:31:28 +01:00
9112d11621 fix(state-hub): repair await-in-generator in _derive_next_steps
str.join() is synchronous and cannot consume a generator that uses await.
Build the blocker slugs list with an explicit async for loop instead.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28 15:27:26 +01:00
07a082b7b0 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
fec05dcb5d docs(workplans): write files for 4 pre-ADR-001 orphan workstreams
Resolves all orphan-workstream FAIL findings from validate_repo_adr.
The custodian domain now passes 47/47 checks (0 warn, 0 fail).

Files written:
  CUST-WP-0001  custodian-agent-runtime (2 tasks: 1 done, 1 todo)
  CUST-WP-0002  contribution-tracking-sbom (15 tasks, v0.5 scope
                reductions annotated inline)
  CUST-WP-0003  whi-kpi-card (9 tasks)
  CUST-WP-0004  ep-td-tracking (10 tasks: 4 done, 6 todo)

All files cross-reference state_hub_workstream_id and
state_hub_task_id for future sync reconciliation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28 12:14:47 +01:00
0974285ad9 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
81fd254472 docs(workplans): add CUST-WP-0005 — dynamic domains & multi-repo
First workplan file following ADR-001 convention. Canonical source
for the v0.5 workplan previously recorded DB-first in the state-hub.
Embeds all 11 tasks with state_hub_task_id cross-references for
future sync reconciliation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28 11:47:44 +01:00
3332d2de2f docs(canon): add ADR-001 — workplans are repository artefacts
State-hub is a read/cache layer. Workplans and work items must
originate as Markdown files in their native repository so the hub
can rebuild its full representation from registered repos alone
(the rebuild principle).

Establishes:
- canon/architecture/ directory for ADRs
- Workplan file convention (frontmatter schema, task embedding)
- Rebuild sequence (migrate → seed-domains → sync-workplans)
- Marks DB-first v0.3/v0.5 records as legacy pending sync tooling

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28 11:45:42 +01:00
6f468baa35 feat(dashboard): add entity detail modal and fixed-layout tables
Replace Inputs.table() with buildEntityTable() across workstreams and
tasks pages. Add click-to-detail modal (openEntityModal) on all entity
list views: workstreams, tasks, extension points, and technical debt.

- New component: src/components/entity-modal.js
  - openEntityModal(entity, type) — full-detail overlay (Esc/click-outside to close)
  - buildEntityTable(rows, cols, onRowClick) — table-layout:fixed, overflow-safe wrapper
  - CSS injected lazily; no separate stylesheet required

- Tables: table-layout:fixed keeps content within the content column;
  title col 32%, workstream col 14%, all cells ellipsis + title tooltip
- Cards (EP, TD): onclick → modal; workstream name span gets title tooltip
- Blocked task cards also wired to modal

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 18:28:44 +01:00
f3b782b010 docs(memory): add W8 — first-class extension point entity (EP-CUST-001)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 08:56:16 +01:00
3108094e0a chore: mark llm-shared-library workstream completed
All 9 tasks done (S1.1–S3.2). llm-connect is now a standalone
installable package at /home/worsch/llm-connect, integrated into
state-hub as its first consumer (S3.1, commit 444b35d).

Also tracks workstream-kpi.md spec (previously untracked).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 08:53:43 +01:00
444b35d68c feat(state-hub): integrate llm-connect as dependency (S3.1)
Add llm-connect as an editable local dependency via [tool.uv.sources].
Creates tests/test_llm_connect_integration.py: 7 offline smoke tests
covering public symbol imports, MockLLMAdapter execute/reset, RunConfig
and LLMResponse fields, and ErrorLLMAdapter error propagation.

All 7 tests pass. Satisfies workstream llm-shared-library S3.1.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 08:32:17 +01:00
531f278f73 feat(dashboard): replace title tooltips with <help-tip> web component
New custom element (src/components/help-tip.js):
- Floating card appears on hover/focus, appended to document.body
  (position:fixed) so it escapes overflow:hidden in the TOC sidebar
- Attributes: label (bold), description (body), doc (optional
  "Learn more →" link)
- Mouse-over-card grace period so the link stays reachable
- Correct viewport clamping (horizontal + prefer-above/fallback-below)

workstreams.md:
- WHI metric abbreviations (DD/BR/SPR/PEP/CDDR) now use <help-tip>
  with full name, one-sentence description, and doc link
- Domain breakdown labels show domain-scoped stats (open count,
  blocked%, runnable%) and a doc link
- Cycle ⚠ icon upgraded to <help-tip> with explanation
- Removed dotted underline; cursor:help comes from the element CSS

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 08:11:09 +01:00
5c14fd731d feat(dashboard): add mouseover tooltips to WHI metric abbreviations
DD, BR, SPR, PEP, CDDR now show full name + one-sentence explanation
on hover via title attributes. Metric labels get a dotted underline
and cursor:help to signal they are hoverable.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 08:03:19 +01:00
2bf952321d 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
f1ba69b23a Add Tasks dashboard page
New page with:
- Data fetch: /tasks/ + /workstreams/ + /topics/ in parallel, enriched
  with domain and workstream_title per task
- Task Overview KPI card in TOC sidebar: open / blocked (red if >0) /
  in progress / done with % of total
- Status Distribution chart (horizontal bar, colour-coded by status)
- Blocked Tasks section: cards with priority badge, domain, workstream,
  blocking_reason highlighted in amber
- All Tasks: filterable table (status, priority, domain, assignee
  multiselect + text), sorted blocked→in_progress→todo→done, 25 rows

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 01:04:19 +01:00
efd13b13dd Implement Workstream Health Index (WHI) KPI card
Add a live WHI card to the Workstreams page TOC sidebar. All six base
metrics from the spec (workstream-kpi.md) computed client-side from
existing data — no API or schema changes required.

Computation (workstreams.md):
- DD: dependency edges / open workstreams (normalised at DD_crit=1.0)
- BR: blocked workstreams / open workstreams
- SPR: max inbound deps on one incomplete workstream / open count
- PEP: active workstreams with all deps completed / open count
- CDDR: cross-domain edges / total edges
- CPI: DFS cycle detection (back-edge = 1, halves WHI as hard penalty)
- WHI = 0.30(1-DDnorm) + 0.25(1-BR) + 0.15(1-SPR) + 0.20·PEP + 0.10(1-CDDR)
- Per-domain breakdown using intra-domain edges only

Card UI: global WHI % with green/orange/red health label, sub-metric
rows with per-spec warning thresholds, cycle alert panel, per-domain
breakdown rows with coloured dots.

Also add src/docs/workstream-health-index.md reference page (formula,
thresholds, improvement guidance) and wire ? button on the card.
Add "Workstream Health" to Reference nav.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 00:03:27 +01:00
fc7dfa1b64 Add Decisions and Workstreams reference docs with heading help wiring
- Remove residual constitution footnote from progress page header
- Create src/docs/decisions.md: types, statuses, resolution history chart,
  filter bar, card anatomy, Decision Health KPI, escalation protocol
- Create src/docs/workstreams.md: status distribution chart, filter bar,
  table columns, dependency graph, create/update patterns
- Wire withDocHelp(h1) on Decisions and Workstreams pages pointing to new docs
- Add both pages to Reference nav section in observablehq.config.js

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-26 18:12:12 +01:00
22b4618abd dashboard: add progress log documentation and ? button on page heading
- src/docs/progress-log.md: covers append-only constitution §5 guarantee,
  event structure (all fields), standard + convention event types, session
  protocol, MCP and curl usage, filters, and the 30-day volume chart
- progress.md: withDocHelp applied to #observablehq-main h1 → ? button
  appears on hover over the 'Progress Log' page heading
- observablehq.config.js: Progress Log added to Reference nav section

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-26 18:03:05 +01:00
755a5fcb9a dashboard: move Open Workstreams by Domain chart to top of overview page
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-26 17:49:12 +01:00
7d7cd31244 dashboard: add 'Event Log' subtitle above filtered table on progress page
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-26 17:06:28 +01:00