PMFlow/backend/app/schemas/pmflow_os.py

258 lines
8.0 KiB
Python

"""PMFlow OS read-side projection schemas."""
from __future__ import annotations
from typing import Any, Literal, Optional
from pydantic import BaseModel, Field
PMFlowStage = Literal["idea", "validation", "planning", "development", "testing", "release", "growth"]
PMFlowObjectStatus = Literal["draft", "confirmed", "in_progress", "blocked", "done", "released"]
PMFlowRiskLevel = Literal["low", "medium", "high"]
PMFlowExecutionStatus = Literal["queued", "pushed", "coding", "pr_open", "testing", "synced", "failed"]
PMFlowReleaseStatus = Literal["check_pending", "ready", "shipping", "live", "watch"]
ProjectLoopStage = Literal["command_idle", "ai_extracting", "extraction_ready", "review_open", "writeback_success"]
PMFlowChangeGroup = Literal["new_object", "field_update", "risk", "decision"]
PMFlowChangeStatus = Literal["pending_review", "accepted", "edited", "deferred", "committed", "skipped"]
PMFlowObjectType = Literal[
"Requirement",
"Decision",
"Task",
"Risk",
"ModelDecision",
"TestRun",
"Release",
"MetricSignal",
]
class PMFlowThreadMessageCreateRequest(BaseModel):
content: str = Field(min_length=1, max_length=12000)
source: str = "web"
attachments: list[dict[str, Any]] = Field(default_factory=list)
class PMFlowThreadMessageResponse(BaseModel):
id: str
threadId: str
projectId: str
role: str
author: str
content: str
createdAt: str
status: str = "sent"
source: str = "web"
metadata: dict[str, Any] = Field(default_factory=dict)
class PMFlowProposedChangeItem(BaseModel):
group: PMFlowChangeGroup
object_type: PMFlowObjectType
object_id: Optional[str] = None
title: str = Field(min_length=1, max_length=255)
summary: str = Field(min_length=1)
diff: str = Field(default="")
payload: dict[str, Any] = Field(default_factory=dict)
confidence: float = Field(default=0.0, ge=0.0, le=1.0)
risk_level: PMFlowRiskLevel = "medium"
class PMFlowExtractionCreateRequest(BaseModel):
thread_id: str
message_id: str
scope: str = "latest_message"
summary: Optional[str] = None
headline: Optional[str] = None
routing_meta: dict[str, Any] = Field(default_factory=dict)
llm_call_id: Optional[str] = None
proposed_items: list[PMFlowProposedChangeItem] = Field(min_length=1)
class PMFlowChangeItemEditRequest(BaseModel):
summary: Optional[str] = None
diff: Optional[str] = None
payload_patch: dict[str, Any] = Field(default_factory=dict)
reason: Optional[str] = None
class PMFlowChangeItemDeferRequest(BaseModel):
reason: Optional[str] = None
class PMFlowChangeSetCommitRequest(BaseModel):
item_ids: list[str] = Field(default_factory=list)
mode: Literal["atomic"] = "atomic"
note: Optional[str] = None
class PMFlowChangeSetDetailResponse(BaseModel):
changeSet: dict[str, Any]
items: list[dict[str, Any]] = Field(default_factory=list)
evidence: list[dict[str, Any]] = Field(default_factory=list)
approvals: list[dict[str, Any]] = Field(default_factory=list)
class PMFlowThread(BaseModel):
id: str
title: str
projectId: str
objective: str
extractionStatus: Literal["idle", "loading", "ready"] = "idle"
messageIds: list[str] = Field(default_factory=list)
class PMFlowProjectSummary(BaseModel):
id: str
name: str
goal: str
stage: PMFlowStage
threadId: str
class PMFlowRequirement(BaseModel):
id: str
title: str
summary: str
stage: PMFlowStage = "planning"
status: PMFlowObjectStatus
linkedTaskIds: list[str] = Field(default_factory=list)
class PMFlowDecision(BaseModel):
id: str
title: str
summary: str
stage: PMFlowStage = "planning"
status: PMFlowObjectStatus
owner: str = "未分配"
class PMFlowTask(BaseModel):
id: str
title: str
summary: str
stage: PMFlowStage = "development"
status: PMFlowObjectStatus
assignee: str = "未分配"
acceptanceCriteria: list[str] = Field(default_factory=list)
requirementId: Optional[str] = None
class PMFlowRisk(BaseModel):
id: str
title: str
summary: str
stage: PMFlowStage = "planning"
status: PMFlowObjectStatus
level: PMFlowRiskLevel = "medium"
mitigation: str = "待补充缓解策略"
class PMFlowModelDecision(BaseModel):
id: str
title: str
summary: str
stage: PMFlowStage = "planning"
status: PMFlowObjectStatus
rationale: str = ""
class PMFlowTestRun(BaseModel):
id: str
title: str
summary: str
stage: PMFlowStage = "testing"
status: PMFlowObjectStatus
result: Literal["passed", "failed"]
linkedTaskId: Optional[str] = None
class PMFlowRelease(BaseModel):
id: str
title: str
summary: str
status: PMFlowReleaseStatus
stage: PMFlowStage = "release"
gateItems: list[dict[str, Any]] = Field(default_factory=list)
class PMFlowMetricSignal(BaseModel):
id: str
title: str
summary: str
stage: PMFlowStage = "growth"
status: PMFlowObjectStatus = "confirmed"
value: str
direction: Literal["up", "down", "flat"] = "flat"
class PMFlowFeedEvent(BaseModel):
id: str
kind: Literal["extraction", "review", "execution", "test", "release", "growth", "agent"]
title: str
summary: str
timestamp: str
class PMFlowExecutionContext(BaseModel):
taskId: Optional[str] = None
status: PMFlowExecutionStatus = "queued"
prompt: str = ""
commitLog: list[str] = Field(default_factory=list)
prStatus: str = "pending"
testSummary: str = "pending"
writebackStatus: str = "pending"
class PMFlowTeamInbox(BaseModel):
product: list[str] = Field(default_factory=list)
engineering: list[str] = Field(default_factory=list)
qa: list[str] = Field(default_factory=list)
growth: list[str] = Field(default_factory=list)
class PMFlowProjectMemory(BaseModel):
truthNodeFacts: list[dict[str, Any]] = Field(default_factory=list)
semanticFacts: list[dict[str, Any]] = Field(default_factory=list)
sourceSummary: dict[str, int] = Field(default_factory=dict)
class ProjectTruthStateProjection(BaseModel):
loopStage: ProjectLoopStage = "command_idle"
lastWritebackAt: Optional[str] = None
project: PMFlowProjectSummary
thread: PMFlowThread
messages: list[dict[str, Any]] = Field(default_factory=list)
changeSets: list[dict[str, Any]] = Field(default_factory=list)
changeItems: list[dict[str, Any]] = Field(default_factory=list)
evidence: list[dict[str, Any]] = Field(default_factory=list)
requirements: list[PMFlowRequirement] = Field(default_factory=list)
decisions: list[PMFlowDecision] = Field(default_factory=list)
tasks: list[PMFlowTask] = Field(default_factory=list)
risks: list[PMFlowRisk] = Field(default_factory=list)
modelDecisions: list[PMFlowModelDecision] = Field(default_factory=list)
testRuns: list[PMFlowTestRun] = Field(default_factory=list)
releases: list[PMFlowRelease] = Field(default_factory=list)
metricSignals: list[PMFlowMetricSignal] = Field(default_factory=list)
approvals: list[dict[str, Any]] = Field(default_factory=list)
feed: list[PMFlowFeedEvent] = Field(default_factory=list)
teamInbox: PMFlowTeamInbox = Field(default_factory=PMFlowTeamInbox)
activeChangeSetId: Optional[str] = None
selectedTaskId: Optional[str] = None
execution: PMFlowExecutionContext = Field(default_factory=PMFlowExecutionContext)
projectMemory: PMFlowProjectMemory = Field(default_factory=PMFlowProjectMemory)
projectionWarnings: list[str] = Field(default_factory=list)
class ExecutionSummaryProjection(BaseModel):
projectId: str
execution: PMFlowExecutionContext
devSync: dict[str, Any] = Field(default_factory=dict)
promptPackage: Optional[dict[str, Any]] = None
repoBindings: list[dict[str, Any]] = Field(default_factory=list)
activeDevTasks: list[dict[str, Any]] = Field(default_factory=list)
recentProgressEvents: list[dict[str, Any]] = Field(default_factory=list)
recentDeliveries: list[dict[str, Any]] = Field(default_factory=list)
warnings: list[str] = Field(default_factory=list)