"""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"] PMFlowExecutionRuntimeTarget = Literal["local_bridge", "codex", "github_agent", "manual"] PMFlowExecutionProgressSource = Literal["local_bridge", "codex", "github_agent", "manual"] PMFlowExecutionProgressEventType = Literal[ "branch_created", "commit", "pr_opened", "pr_synced", "test_passed", "test_failed", "checks_passed", "failed", "blocked", "merged", "accepted", "manual_progress", ] PMFlowReleaseGateStatus = Literal["ready", "blocked", "needs_confirmation", "empty"] PMFlowReleaseValidationDecision = Literal["enter_release_candidate", "keep_blocked"] PMFlowExecutionAcceptanceDecision = Literal[ "accept", "request_changes", "reject", "request_technical_review", "approve_technical_review", ] PMFlowExecutionMemoryWritebackResult = Literal["completed", "blocked", "changes_requested"] 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"] PMFlowReviewerRoutingStatus = Literal["empty", "ready", "warning"] PMFlowReviewerRoutingSourceType = Literal["manual", "ai_extraction", "iteration_recommendation", "unknown"] PMFlowReviewerRoutingPriority = Literal["normal", "elevated", "urgent"] PMFlowReviewerConfidence = Literal["low", "medium", "high"] PMFlowFallbackReviewerRole = Literal["OWNER", "REVIEWER", "MEMBER"] PMFlowReviewDecisionAction = Literal["request_review", "approve", "request_changes", "reject"] PMFlowApprovalState = Literal["not_requested", "requested", "approved", "changes_requested", "rejected"] PMFlowAIFeedbackRating = Literal["positive", "negative"] PMFlowAIFeedbackAnswerKind = Literal["chat_answer", "structured_extraction", "copilot_answer"] PMFlowAIFeedbackTargetType = Literal["thread_message", "change_set", "copilot_answer"] ProjectCopilotSurface = Literal[ "command_center", "structured_extraction", "change_review", "project_memory", "work_graph", "execution_bridge", "team_layer", "release_growth", ] ProjectCopilotIntent = Literal["ask", "supplement", "command"] ProjectCopilotAnchorType = Literal["project", "change_set", "change_item", "task", "release", "evidence"] ProjectCopilotAllowedAction = Literal[ "answer", "draft_change", "review_explain", "prepare_execution_handoff", "route_to_surface", ] ProjectCopilotActionLadderLevel = Literal["read_only", "draft_candidate", "human_review", "handoff_prepare"] ProjectCopilotAutomationLevel = Literal["suggest_only", "prepare_only"] PMFlowExecutionCapabilityMode = Literal[ "ai_direct", "ai_with_user_acceptance", "ai_with_technical_review", "needs_human_judgement", "blocked", ] PMFlowExecutionCapabilityStatus = Literal["ready", "partial", "blocked", "unknown"] PMFlowHumanWorkType = Literal["focus", "review", "acceptance", "coordination"] PMFlowCapacityStatus = Literal["normal", "attention", "near_full", "overloaded", "blocked", "manually_extended"] PMFlowCapacityFitStatus = Literal["recommended", "allowed_with_warning", "not_recommended", "blocked"] PMFlowCapacityOverrideType = Literal["extend_minutes", "overtime", "lock_capacity", "work_type_bias", "high_risk_exception"] PMFlowOvertimeType = Literal["general", "focus", "review", "release_guard"] PMFlowHumanTouchSourceType = Literal[ "changeset_confirmation", "review", "acceptance", "release_decision", "context_completion", "ai_failure_recovery", ] PMFlowHumanTouchBindingType = Literal["hard_bound", "role_bound", "ai_shiftable"] 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 PMFlowAIFeedbackCreateRequest(BaseModel): target_type: PMFlowAIFeedbackTargetType target_id: str = Field(min_length=1, max_length=128) answer_kind: PMFlowAIFeedbackAnswerKind = "chat_answer" rating: PMFlowAIFeedbackRating reason_tags: list[str] = Field(default_factory=list) comment: Optional[str] = Field(default=None, max_length=4000) thread_id: Optional[str] = None message_id: Optional[str] = None change_set_id: Optional[str] = None ai_call_log_id: Optional[str] = None scene_key: Optional[str] = Field(default=None, max_length=128) prompt_key: Optional[str] = Field(default=None, max_length=128) prompt_release_id: Optional[int] = None runtime_profile_id: Optional[str] = Field(default=None, max_length=128) model_provider: Optional[str] = Field(default=None, max_length=64) model_name: Optional[str] = Field(default=None, max_length=120) feedback_metadata: dict[str, Any] = Field(default_factory=dict) class PMFlowAIFeedbackResponse(BaseModel): id: str projectId: str threadId: Optional[str] = None messageId: Optional[str] = None changeSetId: Optional[str] = None aiCallLogId: Optional[str] = None targetType: str targetId: str answerKind: str rating: PMFlowAIFeedbackRating reasonTags: list[str] = Field(default_factory=list) comment: Optional[str] = None sceneKey: Optional[str] = None promptKey: Optional[str] = None promptReleaseId: Optional[int] = None runtimeProfileId: Optional[str] = None modelProvider: Optional[str] = None modelName: Optional[str] = None metadata: dict[str, Any] = Field(default_factory=dict) createdAt: str updatedAt: str class ProjectCopilotObjectAnchorRequest(BaseModel): type: ProjectCopilotAnchorType = "project" id: str = Field(default="", max_length=128) title: Optional[str] = Field(default=None, max_length=255) class ProjectCopilotAskRequest(BaseModel): question: str = Field(min_length=1, max_length=8000) surface: ProjectCopilotSurface = "command_center" intent: ProjectCopilotIntent = "ask" object_anchor: Optional[ProjectCopilotObjectAnchorRequest] = None context_packet: dict[str, Any] = Field(default_factory=dict) class ProjectCopilotObjectAnchorPacket(BaseModel): type: ProjectCopilotAnchorType id: str title: str summary: str status_label: str mode: Literal["current", "historical", "committed", "stale"] = "current" source_label: str risk_level: PMFlowRiskLevel = "low" evidence_ids: list[str] = Field(default_factory=list) class ProjectCopilotContextPacket(BaseModel): packet_version: Literal["project_copilot_context_packet.v1"] = "project_copilot_context_packet.v1" project_ref: dict[str, Any] surface: ProjectCopilotSurface object_anchor: ProjectCopilotObjectAnchorPacket truth_projection: dict[str, Any] = Field(default_factory=dict) change_context: dict[str, Any] = Field(default_factory=dict) execution_context: dict[str, Any] = Field(default_factory=dict) release_context: dict[str, Any] = Field(default_factory=dict) allowed_actions: list[ProjectCopilotAllowedAction] = Field(default_factory=list) forbidden_actions: list[dict[str, str]] = Field(default_factory=list) automation_policy: dict[str, Any] = Field(default_factory=dict) proactive_suggestions: list[dict[str, Any]] = Field(default_factory=list) limitations: list[str] = Field(default_factory=list) action_ladder_level: ProjectCopilotActionLadderLevel = "read_only" class ProjectCopilotAnswerCanvas(BaseModel): headline: str direct_answer: str evidence_blocks: list[dict[str, Any]] = Field(default_factory=list) object_refs: list[dict[str, Any]] = Field(default_factory=list) next_actions: list[dict[str, Any]] = Field(default_factory=list) limitations: list[str] = Field(default_factory=list) class ProjectCopilotAskResponse(BaseModel): answer_canvas: ProjectCopilotAnswerCanvas project_copilot_context_packet: ProjectCopilotContextPacket customer_interaction_context_packet: dict[str, Any] = Field(default_factory=dict) answer_process_packet: dict[str, Any] = Field(default_factory=dict) allowed_actions: list[ProjectCopilotAllowedAction] = Field(default_factory=list) blocked_actions: list[dict[str, str]] = Field(default_factory=list) proactive_suggestions: list[dict[str, Any]] = Field(default_factory=list) warnings: list[str] = Field(default_factory=list) 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(default_factory=list) 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 PMFlowExecutionHandoffRequest(BaseModel): task_id: str = Field(min_length=1) repo_binding_id: Optional[str] = None runtime_target: PMFlowExecutionRuntimeTarget = "local_bridge" note: Optional[str] = Field(default=None, max_length=4000) class PMFlowExecutionHandoffConsumeRequest(BaseModel): runtime_target: Optional[PMFlowExecutionRuntimeTarget] = None consumer_label: Optional[str] = Field(default=None, max_length=120) note: Optional[str] = Field(default=None, max_length=4000) class PMFlowDeliveryChangedFile(BaseModel): path: str = Field(min_length=1, max_length=512) change_type: Literal["added", "modified", "deleted", "renamed", "unknown"] = "unknown" summary: Optional[str] = Field(default=None, max_length=1000) risk_level: PMFlowRiskLevel = "medium" class PMFlowDeliveryCommandRun(BaseModel): command: str = Field(min_length=1, max_length=1000) status: Literal["passed", "failed", "skipped", "blocked", "unknown"] = "unknown" summary: Optional[str] = Field(default=None, max_length=2000) duration_ms: Optional[int] = Field(default=None, ge=0, le=86_400_000) class PMFlowDeliveryTestOutput(BaseModel): name: str = Field(min_length=1, max_length=255) status: Literal["passed", "failed", "skipped", "blocked", "unknown"] = "unknown" command: Optional[str] = Field(default=None, max_length=1000) summary: Optional[str] = Field(default=None, max_length=4000) output_ref: Optional[str] = Field(default=None, max_length=512) class PMFlowDeliveryScreenshot(BaseModel): label: str = Field(min_length=1, max_length=255) artifact_ref: Optional[str] = Field(default=None, max_length=512) artifact_url: Optional[str] = Field(default=None, max_length=1024) summary: Optional[str] = Field(default=None, max_length=1000) class PMFlowDeliveryLogSnippet(BaseModel): level: Literal["debug", "info", "warning", "error"] = "info" summary: str = Field(min_length=1, max_length=2000) artifact_ref: Optional[str] = Field(default=None, max_length=512) class PMFlowDeliveryRiskNote(BaseModel): risk: str = Field(min_length=1, max_length=1000) mitigation: Optional[str] = Field(default=None, max_length=1000) severity: PMFlowRiskLevel = "medium" class PMFlowDeliveryReviewChecklistItem(BaseModel): item: str = Field(min_length=1, max_length=255) status: Literal["passed", "failed", "needs_review", "skipped", "unknown"] = "unknown" summary: Optional[str] = Field(default=None, max_length=1000) class PMFlowDeliveryArtifacts(BaseModel): changed_files: list[PMFlowDeliveryChangedFile] = Field(default_factory=list, max_length=100) commands_run: list[PMFlowDeliveryCommandRun] = Field(default_factory=list, max_length=50) test_outputs: list[PMFlowDeliveryTestOutput] = Field(default_factory=list, max_length=50) screenshots: list[PMFlowDeliveryScreenshot] = Field(default_factory=list, max_length=30) logs: list[PMFlowDeliveryLogSnippet] = Field(default_factory=list, max_length=50) risk_notes: list[PMFlowDeliveryRiskNote] = Field(default_factory=list, max_length=30) review_checklist: list[PMFlowDeliveryReviewChecklistItem] = Field(default_factory=list, max_length=50) class PMFlowExecutionProgressEventRequest(BaseModel): task_id: str = Field(min_length=1) event_type: PMFlowExecutionProgressEventType source: PMFlowExecutionProgressSource = "manual" repo_binding_id: Optional[str] = None branch_name: Optional[str] = Field(default=None, max_length=255) commit_sha: Optional[str] = Field(default=None, max_length=255) pr_number: Optional[int] = Field(default=None, ge=1) test_summary: Optional[str] = Field(default=None, max_length=4000) blocker_summary: Optional[str] = Field(default=None, max_length=4000) execution_status: Optional[PMFlowExecutionStatus] = None workflow_state: Optional[str] = Field(default=None, max_length=120) summary: Optional[str] = Field(default=None, max_length=4000) delivery_id: Optional[str] = Field(default=None, max_length=255) event_source_id: Optional[str] = Field(default=None, max_length=255) delivery_artifacts: Optional[PMFlowDeliveryArtifacts] = None occurred_at: Optional[str] = None class PMFlowArtifactReviewActionRequest(BaseModel): task_id: str = Field(min_length=1) action: Literal["request_fix", "record_fix", "mark_recheck_ready"] = "request_fix" review_item_ids: list[str] = Field(default_factory=list, max_length=50) note: Optional[str] = Field(default=None, max_length=4000) class PMFlowArtifactReworkPackageRequest(BaseModel): task_id: str = Field(min_length=1) repo_binding_id: Optional[str] = None runtime_target: PMFlowExecutionRuntimeTarget = "local_bridge" review_item_ids: list[str] = Field(default_factory=list, max_length=50) note: Optional[str] = Field(default=None, max_length=4000) class PMFlowExecutionRuntimeCredentialCreateRequest(BaseModel): runtime_target: Optional[PMFlowExecutionRuntimeTarget] = None allowed_sources: list[PMFlowExecutionProgressSource] = Field(default_factory=list) expires_in_seconds: int = Field(default=86400, ge=300, le=604800) note: Optional[str] = Field(default=None, max_length=4000) class PMFlowExecutionRuntimeCredentialResponse(BaseModel): keyId: str secret: str secretPreview: str projectId: str taskId: str promptPackageId: str repoBindingId: Optional[str] = None runtimeTarget: PMFlowExecutionRuntimeTarget allowedSources: list[str] = Field(default_factory=list) expiresAt: str status: str = "active" packageEndpoint: str = "/api/pmflow-os/runtime/execution-packages" ingestEndpoint: str = "/api/pmflow-os/runtime/execution-results" signingAlgorithm: str = "hmac-sha256" signatureBase: str = "{timestamp}.{raw_body}" exampleHeaders: dict[str, str] = Field(default_factory=dict) examplePackagePayload: dict[str, Any] = Field(default_factory=dict) examplePayload: dict[str, Any] = Field(default_factory=dict) boundary: str = "PMFlow only accepts execution result metadata; command execution stays outside backend runtime." class PMFlowRuntimeExecutionPackageRequest(BaseModel): prompt_package_id: str = Field(min_length=1) task_id: str = Field(min_length=1) source: PMFlowExecutionProgressSource delivery_id: Optional[str] = Field(default=None, max_length=255) event_source_id: Optional[str] = Field(default=None, max_length=255) class PMFlowRuntimeExecutionPackageResponse(BaseModel): package: dict[str, Any] = Field(default_factory=dict) callback: dict[str, Any] = Field(default_factory=dict) audit: dict[str, Any] = Field(default_factory=dict) class PMFlowRuntimeExecutionResultRequest(PMFlowExecutionProgressEventRequest): prompt_package_id: str = Field(min_length=1) class PMFlowExecutionAcceptanceDecisionRequest(BaseModel): task_id: str = Field(min_length=1) decision: PMFlowExecutionAcceptanceDecision note: Optional[str] = Field(default=None, max_length=4000) evidence_event_ids: list[str] = Field(default_factory=list) class PMFlowExecutionMemoryWritebackRequest(BaseModel): task_id: str = Field(min_length=1) progress_event_ids: list[str] = Field(default_factory=list) note: Optional[str] = Field(default=None, max_length=4000) result: PMFlowExecutionMemoryWritebackResult = "completed" class PMFlowReleaseValidationRunCreateRequest(BaseModel): decision: PMFlowReleaseValidationDecision note: Optional[str] = Field(default=None, max_length=4000) class PMFlowReleaseFeedbackIngestRequest(BaseModel): source_type: str = Field(default="manual", min_length=1, max_length=32) title: Optional[str] = Field(default=None, max_length=255) content: str = Field(min_length=1, max_length=12000) charter_id: Optional[str] = None metrics: dict[str, Any] = Field(default_factory=dict) samples: list[dict[str, Any]] = Field(default_factory=list) class PMFlowIterationRecommendationChangeSetDraftRequest(BaseModel): note: Optional[str] = Field(default=None, max_length=4000) class PMFlowIterationRecommendationGroupChangeSetDraftRequest(BaseModel): recommendation_ids: list[str] = Field(default_factory=list) note: Optional[str] = Field(default=None, max_length=4000) class PMFlowReviewDecisionRequest(BaseModel): action: PMFlowReviewDecisionAction reviewer_id: Optional[int] = Field(default=None, ge=1) reason: Optional[str] = Field(default=None, max_length=4000) item_ids: list[str] = Field(default_factory=list) 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 PMFlowReviewerSuggestion(BaseModel): userId: Optional[str] = None displayName: Optional[str] = None role: Optional[str] = None reason: str confidence: PMFlowReviewerConfidence = "low" class PMFlowReviewerRoutingItem(BaseModel): projectId: str changeSetId: str changeSetTitle: str changeSetStatus: str sourceType: PMFlowReviewerRoutingSourceType = "unknown" reviewReason: str riskLevel: PMFlowRiskLevel = "low" priority: PMFlowReviewerRoutingPriority = "normal" changeTypes: list[str] = Field(default_factory=list) itemCount: int = 0 pendingItemCount: int = 0 evidenceCount: int = 0 suggestedReviewer: Optional[PMFlowReviewerSuggestion] = None fallbackReviewerRole: Optional[PMFlowFallbackReviewerRole] = None reviewDecision: Optional[PMFlowReviewDecisionAction] = None approvalState: PMFlowApprovalState = "not_requested" requestedAt: Optional[str] = None decidedAt: Optional[str] = None decisionReason: Optional[str] = None targetUrl: str createdAt: Optional[str] = None updatedAt: Optional[str] = None class PMFlowReviewerRoutingSummary(BaseModel): totalPendingReview: int = 0 highRiskCount: int = 0 missingReviewerCount: int = 0 iterationDraftCount: int = 0 requestedReviewCount: int = 0 approvedCount: int = 0 changesRequestedCount: int = 0 rejectedCount: int = 0 class PMFlowReviewerRoutingProjection(BaseModel): status: PMFlowReviewerRoutingStatus = "empty" warningCode: Optional[str] = None items: list[PMFlowReviewerRoutingItem] = Field(default_factory=list) summary: PMFlowReviewerRoutingSummary = Field(default_factory=PMFlowReviewerRoutingSummary) 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 lastWritebackBy: Optional[str] = None lastWritebackById: 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) aiFeedback: list[PMFlowAIFeedbackResponse] = Field(default_factory=list) feed: list[PMFlowFeedEvent] = Field(default_factory=list) teamInbox: PMFlowTeamInbox = Field(default_factory=PMFlowTeamInbox) reviewerRouting: PMFlowReviewerRoutingProjection = Field(default_factory=PMFlowReviewerRoutingProjection) 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 qualityContract: dict[str, Any] = Field(default_factory=dict) acceptance: dict[str, Any] = Field(default_factory=dict) releaseGate: dict[str, Any] = Field(default_factory=dict) releaseSignals: dict[str, Any] = Field(default_factory=dict) 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) deliveryArtifacts: dict[str, Any] = Field(default_factory=dict) artifactCompleteness: dict[str, Any] = Field(default_factory=dict) artifactReview: dict[str, Any] = Field(default_factory=dict) warnings: list[str] = Field(default_factory=list) class PMFlowExecutionModeCapability(BaseModel): mode: PMFlowExecutionCapabilityMode label: str status: PMFlowExecutionCapabilityStatus = "unknown" reason: str targetHref: Optional[str] = None class PMFlowToolReadinessItem(BaseModel): key: str label: str status: PMFlowExecutionCapabilityStatus = "unknown" summary: str href: Optional[str] = None class PMFlowPersonalExecutionReadiness(BaseModel): status: PMFlowExecutionCapabilityStatus = "unknown" toolReadiness: list[PMFlowToolReadinessItem] = Field(default_factory=list) waitingForUser: dict[str, int] = Field(default_factory=dict) blockers: list[str] = Field(default_factory=list) recommendedNextStep: str = "回到项目主流程查看下一步。" targetHref: str class PMFlowTeamCapacitySignal(BaseModel): status: PMFlowExecutionCapabilityStatus = "unknown" label: str workloadRatio: float = 0.0 pendingReviewCount: int = 0 activeExecutionCount: int = 0 class PMFlowTeamContextSignal(BaseModel): status: PMFlowExecutionCapabilityStatus = "unknown" label: str evidenceCount: int = 0 recentContributionCount: int = 0 class PMFlowTeamToolSignal(BaseModel): status: PMFlowExecutionCapabilityStatus = "unknown" label: str connectedTools: list[str] = Field(default_factory=list) class PMFlowTeamExecutionSignal(BaseModel): userId: str displayName: str role: str judgementResponsibilities: list[str] = Field(default_factory=list) reviewResponsibilities: list[str] = Field(default_factory=list) capacity: PMFlowTeamCapacitySignal context: PMFlowTeamContextSignal toolStatus: PMFlowTeamToolSignal referenceSkills: list[str] = Field(default_factory=list) recommendedModes: list[PMFlowExecutionCapabilityMode] = Field(default_factory=list) warnings: list[str] = Field(default_factory=list) class PMFlowWorkTypeDistribution(BaseModel): focus: float = 0.0 review: float = 0.0 acceptance: float = 0.0 coordination: float = 0.0 class PMFlowWorkTypeMinutes(BaseModel): focus: int = 0 review: int = 0 acceptance: int = 0 coordination: int = 0 total: int = 0 class PMFlowHumanTouchEstimate(BaseModel): sourceType: PMFlowHumanTouchSourceType sourceId: str targetHref: str workType: PMFlowHumanWorkType estimatedMinutes: int riskLevel: PMFlowRiskLevel = "low" urgency: str = "normal" bindingType: PMFlowHumanTouchBindingType = "role_bound" assignedUserId: Optional[str] = None roleBinding: Optional[str] = None contextReadiness: PMFlowExecutionCapabilityStatus = "unknown" aiReductionPotentialMinutes: int = 0 title: str summary: str class PMFlowCapacityFit(BaseModel): workType: PMFlowHumanWorkType label: str status: PMFlowCapacityFitStatus estimatedMinutes: int afterTotalUtilization: float afterTypeShare: float reason: str class PMFlowCapacityOverridePayload(BaseModel): userId: str date: Optional[str] = None overrideType: PMFlowCapacityOverrideType addedMinutes: int = Field(default=0, ge=0, le=720) overtimeType: Optional[PMFlowOvertimeType] = None maxPlannedUtilization: Optional[float] = Field(default=None, ge=0.5, le=1.25) workTypeBias: dict[str, float] = Field(default_factory=dict) highRiskLimit: Optional[int] = Field(default=None, ge=0, le=20) reason: str = Field(..., min_length=2, max_length=500) expiresAt: Optional[str] = None class PMFlowCapacityOverrideRecord(BaseModel): id: str userId: str date: str overrideType: PMFlowCapacityOverrideType addedMinutes: int = 0 overtimeType: Optional[PMFlowOvertimeType] = None maxPlannedUtilization: Optional[float] = None workTypeBias: dict[str, float] = Field(default_factory=dict) highRiskLimit: Optional[int] = None reason: str expiresAt: str createdBy: str createdAt: Optional[str] = None class PMFlowMemberCapacityPlan(BaseModel): userId: str displayName: str role: str baseAvailableMinutes: int = 480 calendarBlockedMinutes: int = 0 effectiveMinutes: int = 480 reservedBufferMinutes: int = 72 maxPlannedUtilization: float = 0.85 suggestedBaseline: PMFlowWorkTypeDistribution = Field(default_factory=PMFlowWorkTypeDistribution) currentMix: PMFlowWorkTypeDistribution = Field(default_factory=PMFlowWorkTypeDistribution) plannedTouchMinutes: PMFlowWorkTypeMinutes = Field(default_factory=PMFlowWorkTypeMinutes) capacityStatus: PMFlowCapacityStatus = "normal" remainingMinutes: int = 0 bottleneckType: Optional[PMFlowHumanWorkType] = None fatigueRisk: dict[str, str] = Field(default_factory=dict) riskDensity: dict[str, int] = Field(default_factory=dict) canTakeMore: list[PMFlowCapacityFit] = Field(default_factory=list) manualOverride: Optional[PMFlowCapacityOverrideRecord] = None explanations: list[str] = Field(default_factory=list) class PMFlowDailyCapacityPlan(BaseModel): projectId: str date: str generatedAt: str teamDemandMix: PMFlowWorkTypeDistribution = Field(default_factory=PMFlowWorkTypeDistribution) teamEffectiveMinutes: int = 0 teamPlannedTouchMinutes: PMFlowWorkTypeMinutes = Field(default_factory=PMFlowWorkTypeMinutes) memberPlans: list[PMFlowMemberCapacityPlan] = Field(default_factory=list) humanTouches: list[PMFlowHumanTouchEstimate] = Field(default_factory=list) warnings: list[str] = Field(default_factory=list) recommendations: list[str] = Field(default_factory=list) class PMFlowCapacityOverrideSimulation(BaseModel): beforePlan: PMFlowMemberCapacityPlan afterPlan: PMFlowMemberCapacityPlan impactSummary: list[str] = Field(default_factory=list) warnings: list[str] = Field(default_factory=list) class PMFlowExecutionCapabilitySnapshot(BaseModel): projectId: str executionModes: list[PMFlowExecutionModeCapability] = Field(default_factory=list) personalReadiness: PMFlowPersonalExecutionReadiness teamSignals: list[PMFlowTeamExecutionSignal] = Field(default_factory=list) adaptiveCapacitySummary: Optional[PMFlowDailyCapacityPlan] = None warnings: list[str] = Field(default_factory=list)