# 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 effective routing for function - Response data: - `function_name` - `provider` - `model` - `api_env` - `tier` - `source: "default" | "override"` ### PUT `/model-routing/functions/{function_name}` - Auth: manager/admin only - Request body: - `provider`, `model`, `api_env`, `tier` - Side effects: - persist override into `integrations(type='model_routing')` - append audit to `operation_logs` ## 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