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
|
|
|
import enum
|
|
|
|
|
import uuid
|
|
|
|
|
from datetime import date
|
|
|
|
|
|
2026-03-04 19:44:14 +01:00
|
|
|
from sqlalchemy import Boolean, Date, Enum, ForeignKey, String, Text
|
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
|
|
|
from sqlalchemy.dialects.postgresql import UUID
|
|
|
|
|
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
|
|
|
|
|
|
|
|
|
from api.models.base import Base, TimestampMixin, new_uuid
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TaskStatus(str, enum.Enum):
|
2026-05-26 01:32:50 +02:00
|
|
|
wait = "wait"
|
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
|
|
|
todo = "todo"
|
2026-05-26 01:32:50 +02:00
|
|
|
progress = "progress"
|
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
|
|
|
done = "done"
|
2026-05-26 01:32:50 +02:00
|
|
|
cancel = "cancel"
|
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
|
|
|
|
|
|
|
|
|
|
|
|
|
class TaskPriority(str, enum.Enum):
|
|
|
|
|
low = "low"
|
|
|
|
|
medium = "medium"
|
|
|
|
|
high = "high"
|
|
|
|
|
critical = "critical"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Task(Base, TimestampMixin):
|
|
|
|
|
__tablename__ = "tasks"
|
|
|
|
|
|
|
|
|
|
id: Mapped[uuid.UUID] = mapped_column(
|
|
|
|
|
UUID(as_uuid=True), primary_key=True, default=new_uuid
|
|
|
|
|
)
|
2026-06-22 13:52:13 +02:00
|
|
|
workplan_id: Mapped[uuid.UUID] = mapped_column(
|
2026-08-22 00:27:48 +02:00
|
|
|
UUID(as_uuid=True),
|
|
|
|
|
ForeignKey("workplans.id", ondelete="RESTRICT", onupdate="CASCADE"),
|
|
|
|
|
nullable=False,
|
|
|
|
|
index=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
|
|
|
)
|
2026-08-26 02:05:51 +02:00
|
|
|
# Canonical work-record identifier, e.g. "CUST-WP-0067-T01" (ADR-007).
|
|
|
|
|
# Nullable because rows created before STATE-WP-0083-T06 have none; only the
|
|
|
|
|
# repository files know the mapping. Without it a task can be matched only by
|
|
|
|
|
# title, so renaming a heading looks like one task vanishing and another
|
|
|
|
|
# appearing.
|
|
|
|
|
record_id: Mapped[str | None] = mapped_column(String(120), nullable=True, index=True)
|
2026-09-14 15:28:58 +02:00
|
|
|
flavor: Mapped[str | None] = mapped_column(String(32), nullable=True, index=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
|
|
|
title: Mapped[str] = mapped_column(String(255), nullable=False)
|
|
|
|
|
description: Mapped[str | None] = mapped_column(Text, nullable=True)
|
|
|
|
|
status: Mapped[TaskStatus] = mapped_column(
|
|
|
|
|
Enum(TaskStatus), nullable=False, default=TaskStatus.todo
|
|
|
|
|
)
|
|
|
|
|
priority: Mapped[TaskPriority] = mapped_column(
|
|
|
|
|
Enum(TaskPriority), nullable=False, default=TaskPriority.medium
|
|
|
|
|
)
|
|
|
|
|
assignee: Mapped[str | None] = mapped_column(String(100), nullable=True)
|
|
|
|
|
due_date: Mapped[date | None] = mapped_column(Date, nullable=True)
|
|
|
|
|
blocking_reason: Mapped[str | None] = mapped_column(Text, nullable=True)
|
2026-03-04 19:44:14 +01:00
|
|
|
needs_human: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False, index=True)
|
|
|
|
|
intervention_note: Mapped[str | None] = mapped_column(Text, nullable=True)
|
CUST-WP-0074-T02: task wait qualifiers in the hub read model
Adds tasks.decision_id and workplan_dependencies.from_task_id (migration
e8f9a0b1c2d3). A from_task_id column is needed rather than
from_workplan_id plus description: the partial unique indexes key on
(from_workplan_id, target, relationship_type), so two tasks in one
workplan waiting on the same target could not both be indexed, and the
derived wait_kind needs per-task attribution. The two existing unique
indexes are narrowed to frontmatter edges (from_task_id IS NULL) and two
task-origin counterparts are added; downgrade deletes task-origin rows
before restoring the old indexes.
POST /workplans/{id}/dependencies/ accepts from_task_id (must belong to
the from workplan; a task cannot depend on itself). TaskCreate/Update/Read
carry decision_id.
Derived read-model fields, no new write routes (rule 5):
- TaskRead.wait_kind: external | human | both | unqualified, null unless
status is wait (dependency rows from this task / needs_human).
- WorkplanRead.blocked_kind: human | external | none, null unless status
is blocked. Human wins over external.
Both come from api/services/wait_kind.py, applied on GET /tasks/,
GET /tasks/{id}, GET /workplans/ and GET /workplans/{id}.
The identifier-migration reference-count proof now includes from_task_id
(FK count guard 22 -> 23).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Assistant: claude-code
Assistant-Model: sonnet
Assistant-Process: 237582@bnt-lap001
Assistant-Session: f2b3d9f1-8fb9-4b9c-bc2b-837ec5dfc826
2026-09-28 22:39:18 +02:00
|
|
|
# Record id of the tracked decision a human-gated wait hangs on, e.g.
|
|
|
|
|
# "CCR-2026-0004" (CUST-WP-0074 Case B). Free text: the decision may live
|
|
|
|
|
# in another repo and may not be indexed in the hub yet.
|
|
|
|
|
decision_id: Mapped[str | None] = mapped_column(String(120), nullable=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
|
|
|
parent_task_id: Mapped[uuid.UUID | None] = mapped_column(
|
2026-08-22 00:27:48 +02:00
|
|
|
UUID(as_uuid=True),
|
|
|
|
|
ForeignKey("tasks.id", ondelete="SET NULL", onupdate="CASCADE"),
|
|
|
|
|
nullable=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
|
|
|
)
|
|
|
|
|
|
2026-06-22 13:52:13 +02:00
|
|
|
workplan: Mapped["Workplan"] = relationship("Workplan", back_populates="tasks") # noqa: F821
|
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
|
|
|
subtasks: Mapped[list["Task"]] = relationship(
|
|
|
|
|
"Task", foreign_keys=[parent_task_id], lazy="selectin"
|
|
|
|
|
)
|
|
|
|
|
progress_events: Mapped[list["ProgressEvent"]] = relationship( # noqa: F821
|
|
|
|
|
"ProgressEvent", back_populates="task", lazy="selectin"
|
|
|
|
|
)
|