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
|
|
|
---
|
|
|
|
|
title: Workstreams
|
|
|
|
|
---
|
|
|
|
|
|
2026-02-24 23:19:26 +01:00
|
|
|
```js
|
|
|
|
|
const API = "http://127.0.0.1:8000";
|
|
|
|
|
const POLL = 15_000;
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
// Fetch workstreams + topics in parallel, join on topic_id → domain/title
|
|
|
|
|
const wsState = (async function*() {
|
|
|
|
|
while (true) {
|
|
|
|
|
let data = [], ok = false;
|
|
|
|
|
try {
|
|
|
|
|
const [rw, rt] = await Promise.all([
|
|
|
|
|
fetch(`${API}/workstreams/`),
|
|
|
|
|
fetch(`${API}/topics/`),
|
|
|
|
|
]);
|
|
|
|
|
ok = rw.ok && rt.ok;
|
|
|
|
|
if (ok) {
|
|
|
|
|
const [wsList, topicList] = await Promise.all([rw.json(), rt.json()]);
|
|
|
|
|
const topicMap = Object.fromEntries(topicList.map(t => [t.id, t]));
|
|
|
|
|
data = wsList.map(w => ({
|
|
|
|
|
...w,
|
|
|
|
|
domain: topicMap[w.topic_id]?.domain ?? "unknown",
|
|
|
|
|
topic_title: topicMap[w.topic_id]?.title ?? "—",
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
} catch {}
|
|
|
|
|
yield {data, ok, ts: new Date()};
|
|
|
|
|
await new Promise(res => setTimeout(res, POLL));
|
|
|
|
|
}
|
|
|
|
|
})();
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
const data = wsState.data ?? [];
|
|
|
|
|
const _ok = wsState.ok ?? false;
|
|
|
|
|
const _ts = wsState.ts;
|
|
|
|
|
```
|
|
|
|
|
|
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
|
|
|
# Workstreams
|
|
|
|
|
|
|
|
|
|
```js
|
2026-02-24 23:19:26 +01:00
|
|
|
display(html`<div class="live-bar">
|
|
|
|
|
<span style="color:${_ok ? 'var(--theme-foreground-focus)' : 'red'}">●</span>
|
|
|
|
|
${_ok
|
|
|
|
|
? `Live · updated ${_ts?.toLocaleTimeString()}`
|
|
|
|
|
: `<span style="color:red">Offline — run: <code>make api</code></span>`}
|
|
|
|
|
</div>`);
|
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
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```js
|
2026-02-24 23:19:26 +01:00
|
|
|
const domainOpts = ["(all)", ...new Set(data.map(w => w.domain))].sort();
|
|
|
|
|
const statusOpts = ["(all)", "active", "blocked", "completed", "archived"];
|
|
|
|
|
|
|
|
|
|
const domainFilter = view(Inputs.select(domainOpts, {label: "Domain"}));
|
|
|
|
|
const statusFilter = view(Inputs.select(statusOpts, {label: "Status"}));
|
|
|
|
|
const ownerFilter = view(Inputs.text({label: "Owner contains"}));
|
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
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
const filtered = data.filter(w =>
|
|
|
|
|
(domainFilter === "(all)" || w.domain === domainFilter) &&
|
|
|
|
|
(statusFilter === "(all)" || w.status === statusFilter) &&
|
|
|
|
|
(!ownerFilter || (w.owner ?? "").toLowerCase().includes(ownerFilter.toLowerCase()))
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
display(Inputs.table(filtered.map(w => ({
|
2026-02-24 23:19:26 +01:00
|
|
|
Title: w.title,
|
|
|
|
|
Domain: w.domain,
|
|
|
|
|
Status: w.status,
|
|
|
|
|
Owner: w.owner ?? "—",
|
|
|
|
|
Due: w.due_date ?? "—",
|
|
|
|
|
Updated: new Date(w.updated_at).toLocaleDateString(),
|
|
|
|
|
})), {rows: 20}));
|
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
|
|
|
```
|
|
|
|
|
|
2026-02-24 23:19:26 +01:00
|
|
|
## Status Distribution
|
|
|
|
|
|
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
|
|
|
```js
|
|
|
|
|
import * as Plot from "npm:@observablehq/plot";
|
|
|
|
|
|
2026-02-24 23:19:26 +01:00
|
|
|
const byStatus = Object.entries(
|
|
|
|
|
filtered.reduce((acc, w) => { acc[w.status] = (acc[w.status] ?? 0) + 1; return acc; }, {})
|
|
|
|
|
).map(([status, count]) => ({status, count}));
|
|
|
|
|
|
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
|
|
|
display(Plot.plot({
|
|
|
|
|
marks: [
|
2026-02-24 23:19:26 +01:00
|
|
|
Plot.barX(byStatus, {y: "status", x: "count", fill: "status", tip: true}),
|
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
|
|
|
Plot.ruleX([0]),
|
|
|
|
|
],
|
|
|
|
|
marginLeft: 80,
|
|
|
|
|
width: 500,
|
|
|
|
|
}));
|
|
|
|
|
```
|
2026-02-24 23:19:26 +01:00
|
|
|
|
|
|
|
|
<style>
|
|
|
|
|
.live-bar { font-size: 0.8rem; color: gray; text-align: right; margin-bottom: 0.5rem; }
|
|
|
|
|
</style>
|