|
|
scheduler (#129)
Adds the contract lifecycle layer on top of the unified-contracts
backbone (#128). State machine:
draft → queued → active → shipped → archived
At most one contract per directive sits in `active` at any time —
the queue is serialised because each directive owns a single shared
worktree. Repository helpers handle the transition checks AND
auto-promote the next-up `queued` contract whenever the active slot
frees (pause / complete / unlock-from-active / archive-from-active).
Endpoints (all under /api/v1/contracts/{id}):
POST /start draft → queued | active (depending on slot)
POST /pause active → queued; promotes next queued
POST /complete active → shipped; optional pr_url + pr_branch
POST /unlock queued | active → draft; promotes if was active
Frontend wiring:
* `DirectiveContractStatus` now includes `queued`.
* Migration adds `queued` to the CHECK constraint on
directive_documents.status.
* `ContractHeader` component renders breadcrumb + status pill +
status-driven action buttons + a merge-mode (shared / own_pr)
radio. Merge mode is editable only while draft / queued so a
running flow's branch target can't change mid-stream.
* RepositoryError gains a `Validation(String)` arm; the three
existing exhaustive matches (files, mesh, versions) get a
400 BAD_REQUEST response for it.
Drag-to-reorder UI deferred to a small follow-up — the backend
endpoint already exists from the backbone PR.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|