state-hub/api/schemas/workstream.py

85 lines
2.3 KiB
Python
Raw Normal View History

import uuid
from datetime import date, datetime
2026-05-02 00:21:14 +02:00
from typing import Literal
2026-05-18 01:31:36 +02:00
from pydantic import BaseModel, ConfigDict, field_validator
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
from api.schemas.workstream_dependency import WorkstreamDepStub
2026-05-18 01:31:36 +02:00
from api.workplan_status import normalize_workstream_status
2026-05-18 01:31:36 +02:00
WorkstreamStatus = Literal[
"proposed",
"ready",
"active",
"blocked",
"backlog",
"finished",
"archived",
]
2026-05-02 00:21:14 +02:00
2026-05-18 01:31:36 +02:00
class WorkstreamStatusMixin(BaseModel):
@field_validator("status", mode="before", check_fields=False)
@classmethod
def _normalise_status(cls, value):
return normalize_workstream_status(value)
class WorkstreamCreate(WorkstreamStatusMixin):
topic_id: uuid.UUID
slug: str
title: str
description: str | None = None
2026-05-02 00:21:14 +02:00
status: WorkstreamStatus = "active"
owner: str | None = None
due_date: date | None = None
planning_priority: str | None = None
planning_order: int | None = None
repo_id: uuid.UUID | None = None # GEMS primary: the owning repository
repo_goal_id: uuid.UUID | None = None
2026-05-18 01:31:36 +02:00
class WorkstreamUpdate(WorkstreamStatusMixin):
title: str | None = None
description: str | None = None
status: WorkstreamStatus | None = None
owner: str | None = None
due_date: date | None = None
planning_priority: str | None = None
planning_order: int | None = None
repo_id: uuid.UUID | None = None
repo_goal_id: uuid.UUID | None = None
2026-05-18 01:31:36 +02:00
class WorkstreamRead(WorkstreamStatusMixin):
model_config = ConfigDict(from_attributes=True)
id: uuid.UUID
topic_id: uuid.UUID
repo_id: uuid.UUID | None = None
repo_goal_id: uuid.UUID | None = None
slug: str
title: str
description: str | None = None
status: WorkstreamStatus
owner: str | None = None
due_date: date | None = None
planning_priority: str | None = None
planning_order: int | None = None
created_at: datetime
updated_at: datetime
class WorkstreamWithTaskCounts(WorkstreamRead):
tasks_total: int = 0
tasks_todo: int = 0
tasks_in_progress: int = 0
tasks_blocked: int = 0
tasks_done: int = 0
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
class WorkstreamWithDeps(WorkstreamWithTaskCounts):
"""WorkstreamWithTaskCounts enriched with dependency graph edges."""
depends_on: list[WorkstreamDepStub] = []
blocks: list[WorkstreamDepStub] = []
2026-05-02 00:21:14 +02:00
blocked_reasons: list[dict] = []