Commit Graph

26 Commits

Author SHA1 Message Date
d2ff7f2bb0 Dashboard decisions: list view with MultiSelect filters
- Replace Pending/Made tab + Inputs.table with MultiSelect filters and
  a proper list view
- Filters: Type (pending/made), Status (open/escalated/resolved/superseded),
  title text search — all stable across polls (no data dependency)
- Each decision renders as a compact card: left border coloured by status
  (blue=open, amber=escalated, green=resolved, gray=superseded), type and
  status badges, domain context, deadline (red+overdue warning if past),
  full title, description/rationale snippet, resolved-by attribution
- Decisions sorted: escalated → open → resolved → superseded, then by
  deadline ascending within each group
- Fetch now includes topics alongside decisions for domain name join
- Escalation warning box and velocity chart retained

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-26 00:39:44 +01:00
95fcbba716 Dashboard: reusable MultiSelect dropdown component for workstreams filters
Adds src/components/multiselect.js — a compact dropdown multi-select that is
Observable-compatible (exposes .value, dispatches bubbling input events) so it
works with view(), Inputs.form, and Generators.input without modification.

Component behaviour:
- Closed state: pill button showing "Label: All" (muted) or active selection
  (1-2 items shown by name, 3+ shown as "N of M"); blue border when active
- Open state: dropdown with per-item checkboxes + "Clear selection" link
  (only visible when something is selected); closes on outside click / Escape
- Styles injected once into document.head (STYLE_ID guard prevents duplicates)
- Uses CSS custom properties for light/dark mode compatibility

Workstreams page update:
- Domain and Status filters now use MultiSelect instead of Inputs.checkbox
- Filter bar layout reduced to a tight inline row (0.5rem gap)
- Owner text filter restyled to match trigger button height
- No changes to filter logic or downstream cells (filters.domain / .status
  are still string[] with empty = show all)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-26 00:19:58 +01:00
29f335dc5c Dashboard workstreams: multi-select filters that survive data polls
- Replace single-select Domain/Status dropdowns with checkbox multi-selects
- Use Inputs.form() with a custom template to lay the three filters out
  side by side in a card-style filter bar
- Filter options are now static constants (DOMAINS, STATUSES) — no
  dependency on the polled data, so selections are never reset on refresh
- Empty selection = no filter applied (show all); any checked item = include
- Updated filtered computation and wsWithDeps to use filters.domain /
  filters.status array semantics

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-26 00:05:58 +01:00
a9405829c7 Dashboard: make status cards interactive links
- Active Workstreams → navigates to ./workstreams page
- Blocking Decisions → anchor-scrolls to #blocking-decisions section
- Blocked Tasks → click toggles inline panel showing each blocked task
  with workstream name and blocking reason; label toggles expand/collapse
- Events Today → anchor-scrolls to #recent-activity section
- All cards get hover lift effect (box-shadow + 1px translateY)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-25 23:43:44 +01:00
a5fa4177af 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
e7a14456bd Add State Hub v0.2 workplan and register in hub
roadmap/state-hub-v0.2/PLAN.md covers three stages:
- S0: Design boundary cleanup (observation + 2 write exceptions)
- S1: Workstream dependency graph (schema → API → MCP → dashboard)
- S2: Suggesting Next Steps (derived endpoint → MCP tool → dashboard)
- S3: Integration, seeding known deps, CLAUDE.md rollout

Registered in State Hub:
- Workstream 6585ee66: State Hub v0.2 — Decisions, Suggestions & Dependencies
  (7 tasks, all todo)
- Workstream a2d9919d: Custodian Agent Runtime — Bootstrap
  (2 tasks; bootstrap task marked blocked on markitect/llm-shared-library)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-25 16:55:58 +01:00
312d64a14b Dashboard decisions: stable form inputs + copy to clipboard
Polling fix:
- Blocking decisions now use a Mutable (blockingDecisions) + refreshDecisions()
  instead of deriving from summary.blocking_decisions
- Cards only re-render on initial page load or after a successful resolve,
  not on every 15 s summary poll — so typing in the form is never interrupted
- On successful resolve, refreshDecisions() re-fetches the list; the resolved
  decision no longer matches the open/escalated filter so it disappears cleanly

Copy to clipboard:
- Small "Copy" button in the card header (next to deadline/escalation badges)
- Formats full decision as markdown: title, description, context, status, date
- Shows "✓ Copied" for 1.5 s, reverts to "Copy"; shows "⚠ Failed" on error

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-25 09:47:52 +01:00
1d9d776a23 Add in-dashboard decision resolution with project log write
API:
- DecisionResolve schema (rationale, decided_by, write_log flag)
- POST /decisions/{id}/resolve — marks resolved, emits progress event,
  appends entry to DECISIONS.md in the project's registered directory
  (found via the topic's registration milestone event)

Dashboard:
- Replace Inputs.table for blocking decisions with full-text cards
- Each card shows title, full description (pre-wrap), rationale/context,
  escalation warning if present
- Expandable "Resolve →" section with rationale textarea, decided-by
  input, submit button that calls the resolve endpoint
- On success: collapses form, dims card, confirms log was written

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-25 09:34:35 +01:00
eeb4faeedd Dashboard: show domain on y-axis, workstream title inside bar
- y-axis tick labels now show domain name (only on the first
  workstream in each domain group, blank for subsequent ones)
- Workstream title rendered as text at x=0 inside the bar
- Titles truncated at 36/24 chars to avoid overflow
- marginLeft reduced to 160 (domain names are shorter than titles)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-25 00:58:34 +01:00
e65d530a5e Add per-workstream task counts to state summary and dashboard
API:
- WorkstreamWithTaskCounts schema extends WorkstreamRead with
  tasks_total/todo/in_progress/blocked/done fields
- /state/summary now includes these counts in open_workstreams via
  a single extra GROUP BY query (workstream_id, status)

Dashboard:
- Replace domain workstream-count bar with a horizontal stacked
  progress bar per workstream (done/in-progress/blocked/todo)
- Workstreams with no tasks show "no tasks yet" annotation
- Workstreams with tasks show "X/N done" label after the bar
- Sorted by domain then title so domains group naturally

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-25 00:50:43 +01:00
6aff5a7936 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
b2fb8d3279 Remove hardcoded br from hint, inline the command 2026-02-25 00:16:37 +01:00
ca33d96c43 Tighten hint text to avoid linebreak 2026-02-24 23:59:38 +01:00
1f56facda5 Update getting-started hint: say Hi! to trigger first session 2026-02-24 23:57:12 +01:00
17a75d2726 Make first-message behaviour explicit in CLAUDE.md template
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>
2026-02-24 23:48:28 +01:00
1c052df90b Add First Session Protocol to project CLAUDE.md template
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>
2026-02-24 23:43:39 +01:00
fa2b6ff698 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
cc0f10b031 Live dashboard: replace data loaders with client-side polling
CORS: add CORSMiddleware to FastAPI for localhost:3000 so browser fetch
works across ports without errors.

All four pages now use async generator cells that call the API directly
and re-yield every 15 s — no data loader cache, no manual cache clearing.

Each page shows a live status bar (● green/red · last updated time).
Offline state shows the `make api` hint inline.

index.md: add "Registered Projects" section — polls
  /progress/?event_type=milestone&limit=500 and filters for
  "Project registered with State Hub:" events; shows project name,
  domain, path, and registration timestamp.

workstreams.md: fix broken domain column — now fetches /workstreams/
  and /topics/ in parallel and joins on topic_id client-side.
  Previously the domain column showed "unknown" for all rows because
  WorkstreamRead schema doesn't include domain.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-24 23:19:26 +01:00
2c3687d1c9 Add documentation: root README and state-hub/README
Root README covers: architecture, domain table with topic IDs, quick
start, project registration, Claude Code integration, governance
summary, roadmap, and design principles.

state-hub/README covers: full setup guide, Makefile targets, DB schema
with governance constraints, API summary (incl. /state/summary shape),
MCP server config, custodian CLI reference, dashboard pages, and WSL2
known issues.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-24 23:00:20 +01:00
ae10aaf33f Add custodian CLI — register-project and status subcommands
custodian register-project [--domain DOMAIN] [--path PATH]
  Defaults path to cwd; auto-detects domain from project charter if
  --domain is omitted. Does: API health → topic lookup → MCP check →
  CLAUDE.md from template → progress event.

custodian status
  Prints API health + summary totals + blocking decisions.

Installed via: make install-cli (symlinks .venv/bin/custodian → ~/.local/bin/)
Entry point declared in pyproject.toml [project.scripts].

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-24 22:55:41 +01:00
b93df3aa68 Implement registration UX wishlist W1–W6 (260224)
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>
2026-02-24 22:22:53 +01:00
715a7169ba docs(memory): add 260224-wishlist-custodian — project registration UX
7 items for streamlining project-to-custodian registration. Baseline
~27K tokens; target ~1.5K (18x) after W1+W6+W3+W2 implemented.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-24 21:42:49 +01:00
880de1870a Update .gitignore for state-hub artifacts
Exclude state-hub/.venv, .env, dashboard/node_modules,
dashboard/src/.observablehq/, and dashboard/dist/.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-24 17:48:57 +01:00
05cc29e50b 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
c7046a79e0 initial priming commit 2026-02-24 12:01:37 +01:00
62e743ec9a Initial commit 2026-02-24 10:24:45 +00:00