Parses go.sum lockfiles for Go projects. Reads go.mod alongside to
mark direct vs indirect dependencies. Deduplicates by (module, version),
skipping go.mod hash lines.
Used to ingest key-cape (netkingdom domain): 23 Go modules.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- parse_task_blocks() now injects the nearest preceding ### heading
text as `title` — tasks no longer stored with bare IDs as their title
- C-11 fix skips creating tasks when workstream is completed/archived
(prevents duplicate task creation on repeated fix-consistency runs)
- C-12 is now fixable: auto-cancels open orphan DB tasks when the
backing workstream is finished (completed/archived)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Root cause analysis: calling create_workstream() before writing the workplan
file creates a ghost workstream with repo_id=null. When fix-consistency later
runs on the file, it creates a second workstream and writes its ID into the
file — leaving the ghost permanently active and showing false partial progress
in the dashboard.
C-14: after checking file-backed workstreams, query active workstreams on the
same topic with repo_id=null. Flag any whose title matches a file-backed
workstream as a probable ghost duplicate.
CLAUDE.md: add explicit "workplan ↔ DB sync rule" prohibiting create_workstream()
for file-backed work. Write file first, then make fix-consistency.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
T01: copy agent-scope-analyst.md to the-custodian/agents/
T02: add scope.template, prepend @SCOPE.md to claude-md.template,
update register_project.sh to write SCOPE.md stub on new registration,
add scope-analyst row to TOOLS.md
T03: SCOPE.md for the-custodian itself
Workplan: CUST-WP-0017 registered in state-hub
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 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>
Replaces the monolithic project_claude_md.template with a directory of
7 focused rule files in scripts/project_rules/. register_project.sh now
generates .claude/rules/*.md + a thin CLAUDE.md index of @-imports,
matching the pattern established in ops-bridge.
Template files:
claude-md.template — 9-line @-import index
repo-identity.template — purpose, domain, slug, topic ID (machine-gen)
session-protocol.template — orient/inbox/workplans/brief/close (machine-gen)
first-session.template — bootstrap flow; delete once past FSP
workplan-convention.template— prefix, location; delegates to global CLAUDE.md
stack-and-commands.template — language/deps/commands (stub, manual)
architecture.template — design overview (stub, manual)
repo-boundary.template — what this repo does NOT own (stub, manual)
register_project.sh changes:
- Generates .claude/rules/ from templates with variable substitution
- Writes thin CLAUDE.md if none exists; appends suggestion comment if one does
- Step 7: auto-registers this machine's local path via POST /repos/{slug}/paths/
- project_claude_md.template deprecated to a redirect notice
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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>
Detects when all DB tasks are done/cancelled but the workstream status
is still 'active' — the pattern where a worker completes tasks via MCP
but forgets to call update_workstream_status(). Auto-fixable via --fix.
Also extends the C-04/C-05 fix path to handle C-13 (same PATCH logic).
Motivated by marki-docx WP-0001/WP-0002 visibility gap (2026-03-16).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Root cause: workplan files use "done" (task vocabulary) but the DB workstream
API only accepts "completed". The PATCH was silently failing with 422.
Fixes:
- Add FILE_TO_DB_WORKSTREAM_STATUS map and normalise_workstream_status()
- Normalise file status before C-04 comparison: done↔completed is no longer
spurious drift
- Normalise file status before PATCHing: always send DB-valid "completed"
- _api_patch now returns {"_error": ...} instead of None on failure, so the
fix loop reports FAILED entries rather than silently dropping them
- 9 new tests in TestNormaliseWorkstreamStatus (42 total)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 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>
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>
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>
- 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>
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>
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>
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>
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>
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>
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>
Add one-line imperative at the top of the Session Protocol:
'On receiving your first message — before writing any response text —
call get_state_summary() immediately.'
Previously Claude would wait for a substantive prompt before acting.
Now any first message (including 'start', 'go', or just Enter) triggers
the tool call immediately, after which the First Session Protocol takes over.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When get_state_summary() shows no workstreams for the domain, Claude
now has explicit instructions: read the canon charter + roadmap, survey
the repo for in-progress work, propose 1-3 workstreams to Bernd, wait
for approval, then create workstreams + tasks and record a milestone.
The "wait for approval before creating anything" gate keeps the human
in control while making the expected first-session behaviour unambiguous.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
W1: Document user-scope MCP config location in ~/.claude/CLAUDE.md —
adds verification and re-registration commands, warns against
settings.json (saves ~12K tokens per registration session).
W2: scripts/register_project.sh + make register-project —
5-step automation: API health → topic lookup → MCP check →
CLAUDE.md from template → progress event.
W3: state-hub/scripts/project_claude_md.template —
parameterised CLAUDE.md with {PROJECT_NAME}/{DOMAIN}/{TOPIC_ID}
placeholders; used by register_project.sh.
W4: Add custodian_topic_id + domain to all 6 canon project charters —
lets agents grep for topic IDs without touching the API.
W5: state-hub/mcp_server/TOOLS.md — compact 30-line tool reference
card; replaces reading the full server.py (~350 lines).
W6: Switch .mcp.json to absolute path + PYTHONPATH env so cwd is not
required; add scripts/patch_mcp_cwd.py for post-registration fix.
Update ~/.claude.json to match (cwd kept for belt-and-suspenders).
W7 (SessionStart hook) deferred: no SessionStart hook type in Claude
Code; PreToolUse with empty matcher fires before every tool call.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>