generated from coulomb/repo-seed
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>
This commit is contained in:
67
dashboard/src/workstreams.md
Normal file
67
dashboard/src/workstreams.md
Normal file
@@ -0,0 +1,67 @@
|
||||
---
|
||||
title: Workstreams
|
||||
---
|
||||
|
||||
# Workstreams
|
||||
|
||||
```js
|
||||
const workstreams = await FileAttachment("data/workstreams.json").json();
|
||||
const data = Array.isArray(workstreams) ? workstreams : [];
|
||||
```
|
||||
|
||||
```js
|
||||
const domainFilter = view(Inputs.select(
|
||||
["(all)", ...new Set(data.map(w => w.domain ?? "unknown"))],
|
||||
{ label: "Domain" }
|
||||
));
|
||||
const statusFilter = view(Inputs.select(
|
||||
["(all)", "active", "blocked", "completed", "archived"],
|
||||
{ label: "Status" }
|
||||
));
|
||||
const ownerFilter = view(Inputs.text({ label: "Owner contains" }));
|
||||
```
|
||||
|
||||
```js
|
||||
const filtered = data.filter(w =>
|
||||
(domainFilter === "(all)" || w.domain === domainFilter) &&
|
||||
(statusFilter === "(all)" || w.status === statusFilter) &&
|
||||
(!ownerFilter || (w.owner ?? "").toLowerCase().includes(ownerFilter.toLowerCase()))
|
||||
);
|
||||
|
||||
const STATUS_COLOR = {
|
||||
active: "green",
|
||||
blocked: "orange",
|
||||
completed: "blue",
|
||||
archived: "gray",
|
||||
};
|
||||
|
||||
display(Inputs.table(filtered.map(w => ({
|
||||
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,
|
||||
}));
|
||||
```
|
||||
|
||||
```js
|
||||
import * as Plot from "npm:@observablehq/plot";
|
||||
|
||||
display(Plot.plot({
|
||||
title: "Workstream Status Distribution",
|
||||
marks: [
|
||||
Plot.barX(
|
||||
Object.entries(
|
||||
filtered.reduce((acc, w) => { acc[w.status] = (acc[w.status] ?? 0) + 1; return acc; }, {})
|
||||
).map(([status, count]) => ({ status, count })),
|
||||
{ y: "status", x: "count", fill: "status", tip: true }
|
||||
),
|
||||
Plot.ruleX([0]),
|
||||
],
|
||||
marginLeft: 80,
|
||||
width: 500,
|
||||
}));
|
||||
```
|
||||
Reference in New Issue
Block a user