# API CONTRACTS ## PMFlow OS ### POST `/pmflow-os/change-sets/{change_set_id}/commit` - Purpose: commit reviewed ChangeSet items into the official project truth layer. - Auth: project member, `OWNER`, or `REVIEWER`; tenant comes from JWT. - Request body: - `item_ids?: string[]` optional; default commits all `accepted / edited` items. - `mode: "atomic"` required for C2 V1. - `note?: string` audit note only. - Behavior: - Processes only `accepted / edited` ChangeItems. - C2 V1 is atomic: any eligible item write failure rolls back the whole commit. - Required C2 objectType support: `Requirement / Decision / Task / Risk`. - Optional C2 objectType support: `Release`. - Unsupported for C2 V1: `ModelDecision / MetricSignal`, which must fail with `422 unsupported_object_type`. - `Requirement / Decision / Risk / Release` write to `truth_nodes`. - `Task` writes `truth_nodes(node_type='task')` plus `tasks.truth_node_id`. - High-risk items require item-level approval with `decision in ('approved','edited')` and `after_status in ('accepted','edited')`. - Response data: - `changeSet`: `{ id, status, rawStatus, committedAt, committedItemIds, skippedItemIds, failedItemIds }` - `committedItems[]`: `{ changeItemId, objectType, targetType, targetId, status, evidenceIds, semanticFactStatus }` - `skippedItems[]`: `{ changeItemId, objectType, status, reason }` - `failedItems[]`: `{ changeItemId, objectType, code, message }` - `projectTruthState?`: optional backend projection after commit. - Failure semantics: - `404 changeset_not_found` - `409 changeset_not_reviewed` - `409 changeset_already_committed` - `409 no_accepted_items` - `409 high_risk_approval_required` - `422 invalid_commit_item_ids` - `422 unsupported_object_type` - `422 invalid_change_payload` - `500 commit_failed` ## Signal & SSTC ### GET `/projects/{project_id}/signals` - Response data: - `items[]` includes planner fields: - `planner_status: "pending" | "completed" | "failed"` - `planner_analyzed_at: string | null` - `planner_assignee_user_id: string | null` - `strategic_analysis: object` ## Model Routing ### GET `/model-routing/functions/{function_name}` - Purpose: query function-level advanced routing override. This is an admin/advanced entry, not the default product UI for members or team leads. - Response data: - `function_name` - `tier` - `source: "default" | "override"` ### PUT `/model-routing/functions/{function_name}` - Auth: manager/admin only - Request body: - `tier` - Side effects: - persist override into `integrations(type='model_routing')` - append audit to `operation_logs` ## AI Routing & Providers - UI placement: these endpoints power the team-level AI 运营中心 under `/ai-config`; they are not project-scoped and must not be presented as per-project provider/model settings. ### GET `/ai-routing/overview` - Purpose: productized AI routing overview for team leads and AI operators. - Auth: `OWNER` or `REVIEWER` via `can_view_ai_policy`. - Response data: - `control_plane`: `{ version, source, updated_at, baseline_note }` - `slots[]`: low/high slot summaries with Chinese labels, provider/model display summary, connection state, and masked key status. - `metrics`: recent 24h/7d calls, failures, failure rate, escalation rate, structured failure rate, average latency, and cost estimate. - `diagnostics[]`: risk cards such as env key override, high slot unavailable, same runtime for low/high, protected downgrade, structured failure spike, or local Ollama scope risk. - Boundary: no cleartext key, `api_env`, prompt, raw provider secret, raw error, or raw routing meta. ### GET `/ai-routing/team-policy` - Purpose: team-lead-facing business policy view for project launch, requirement structuring, task breakdown, assignee matching, internal QA, external query, Feishu understanding, and Feishu reply. - Auth: `OWNER` or `REVIEWER`. - Response data: - `strategy`: `quality_first | balanced | speed_first` - `scenes[]`: Chinese business scene policies, preferred mode, escalation rule, fallback behavior, and editable business note. - `automation_boundary`, `budget_guard`, `quality_targets`, `updated_at`, `updated_by` - Boundary: team policy is saved product governance state only; it does not rewrite `llm_service` runtime routing in v1. ### PUT `/ai-routing/team-policy` - Purpose: save team AI policy display/governance state. - Auth: `OWNER` only via `can_approve_ai_routing_change`. - Request body: - `strategy?: "quality_first" | "balanced" | "speed_first"` - `scenes?: [{ key, policy, mode?, human_confirmation?, protected? }]` - `automation_boundary?: string` - `budget_guard?: { enabled?: boolean, monthly_budget_cny?: number | null, alert_threshold_ratio?: number }` - `quality_targets?: string[]` - Side effects: - persist into `integrations(type='ai_team_policy')` - append `operation_logs(entity_type='ai_routing_policy')` - Boundary: never writes `backend/.control_plane/pmflow-routing-rules.json`, provider secrets, or model-routing overrides. ### GET `/ai-routing/admin-console` - Purpose: AI admin/operator console aggregating provider connection summaries, low/high slots, business-scene routes, recent failure samples, protected scenes, and env override diagnostics. - Auth: `OWNER` or `REVIEWER`. - Response data: - `providers[]`: display-only provider health and masked key state. - `slots[]`: fast/deep slot summaries. - `scene_routes[]`: scene label, mode, contract, protection state; raw `function_name` may only be present in admin data and must be hidden by default in UI advanced details. - `recent_failures[]`: sanitized failure samples without raw error or prompt. - `protected_scenes[]`, `environment_overrides[]`, `diagnostics[]` ### POST `/ai-routing/diagnostics/run` - Purpose: run read-only diagnostics for routing/provider health. - Auth: `OWNER` or `REVIEWER` via `can_operate_ai_routing`. - Side effects: none; does not modify provider, slot, team policy, or runtime routing. ## PMFlow OS Adaptive Capacity All endpoints return `{ code, message, data }`. Project members may read. Override simulate/apply requires `OWNER` or `REVIEWER`; write endpoints only persist capacity override audit records and must not assign tasks, request review, write ChangeSet, or mutate Project Memory. ### GET `/pmflow-os/projects/{project_id}/capacity-plan?date=YYYY-MM-DD` - Purpose: compute the daily adaptive human capacity plan from current truth-state, reviewer routing, execution summary, workspace bindings, user projects, legacy workload reference, and active overrides. - Response data: - `projectId`, `date`, `generatedAt` - `teamDemandMix` - `teamEffectiveMinutes`, `teamPlannedTouchMinutes` - `memberPlans[]`: base/effective minutes, dynamic `suggestedBaseline`, current mix, planned touch minutes, status, remaining minutes, bottleneck, fatigue risk, risk density, `canTakeMore`, manual override, explanations - `humanTouches[]`: source, target href, work type, estimated minutes, risk, urgency, binding, assigned user, context readiness, AI reduction potential - `warnings`, `recommendations` - Boundary: daily plan is computed at read time. Do not persist fixed baselines or daily snapshots. ### POST `/pmflow-os/projects/{project_id}/capacity-overrides/simulate` - Purpose: simulate a manager capacity override before applying it. - Request body: `PMFlowCapacityOverridePayload` - Response data: `{ beforePlan, afterPlan, impactSummary, warnings }` - Boundary: no database write and no assignment side effect. ### POST `/pmflow-os/projects/{project_id}/capacity-overrides` - Purpose: apply a manager override and persist audit in `human_capacity_overrides`. - Request body: `PMFlowCapacityOverridePayload` - Response data: `PMFlowCapacityOverrideRecord` - Side effects: insert one override audit row only. - Boundary: `reason` is required; default expiry is same day 23:59 if omitted. Overtime increases time budget but must not clear fatigue or quality risk. ### GET `/pmflow-os/projects/{project_id}/capacity-overrides?date=YYYY-MM-DD` - Purpose: list override audit records for the given day. - Response data: `PMFlowCapacityOverrideRecord[]` ### GET `/pmflow-os/projects/{project_id}/execution-capabilities` - Addition: response data may include `adaptiveCapacitySummary: DailyCapacityPlan`. ## Task Briefs ### GET `/task-briefs/center` - Purpose: list generated brief cards ### GET `/task-briefs/templates` - Purpose: list templates ### POST `/task-briefs/templates` - Purpose: create template ### PUT `/task-briefs/templates/{template_id}` - Purpose: update template ### GET `/task-briefs/runs` - Purpose: list generation runs ### POST `/task-briefs/generate` - Purpose: generate one task brief run ### GET `/task-briefs/contract-sync` - Purpose: expose docs/contract sync status snapshot