Opt-in task workflow API (FLOW-02)¶
Status: local server implementation; not deployed. Bridge automation and native presentation remain FLOW-03/FLOW-04. Integration tests use actual MCP, HTTP and PostgreSQL with synthetic provider sessions and Git references. They do not prove that a real provider can produce or verify a candidate.
Dispatch and identity¶
Call workflow_dispatch(spec, write_context) with tasks:write and active
owner/admin membership. The actor must also control the selected Bridge's anchor
project. All writes use the same resource/instance/project binding as existing
MCP writes. spec is a discoverable, closed typed schema in tools/list:
task_id, currentexpected_task_version, enrolledbridge_id, uniqueidempotency_key(1–128 alphanumeric, underscore, dot or hyphen characters).- Explicit absolute
workspace, 40-character lowercase Gitbase_commit,branch, and bounded nonempty workprompt. profile(worker) andverifier: versioned operator-authored profile snapshots. Each containsprofile_id,version,runtime,instructions, optionalsoul, pinnedskills(id,version,content), and provideraccount_idand explicitmodel. Runtime issynthetic,codex_cliorclaude_code_cli. Synthetic fixtures omit the account. Provider accounts must be node-allowed. Worker and verifier profile IDs differ; verifierallow_workspace_writesmust be false. These are snapshots, not automatic Agent Catalog resolution.criteria: 1–32 entries with uniqueid, nonemptydescriptionandmethod.document_refs: up to 32 repository-relative references pinned through the contract's repository/base commit.max_work_attempts: 1 or 2, default 2. Every verification is a distinct attempt.
The server freezes the task goal, input version, repository, assignment and profiles into an immutable revision and SHA-256 contract digest. Dispatch and its first offer are atomic. A matching idempotency replay returns the same revision; a changed request with that key fails. A new revision is allowed only after cancellation or blocking and with the current task version. Old revisions, attempts, evidence references and phase history remain available in storage. A node allows at most one offered/running execution, including legacy work.
Claim, preparation and completion¶
Bridge uses the existing /bridge/v1/executions HTTP offer/claim/renew/event
routes. The plan additionally contains workflow: revision ID, purpose
(work/verify), contract digest, criteria, document references, candidate,
worker attempt ID and any correction feedback. The execution ID is the attempt
ID; plan.session_id is fresh for every attempt. Node-side workspace/runtime
opt-in and actual profile/tool preparation must be implemented in FLOW-03.
The execution's legacy state=running denotes a held lease. The authoritative
workflow phase distinguishes claimed, preparing, running and verifying.
A claim alone never reports that the provider session is ready.
Send ordered events under lease_id, fencing_token, sequence:
state=preparingafter claim.state=runningwith a fresh, nonemptyprovider_session_idafter preparation.state=completed,exit_code=0, the same provider session ID,result_commit, repository-relativeevidence_path,clean_workspace=true. A failed/interrupted event can instead give a boundedreason.
Leases expire after 90 seconds, can be renewed, and have an absolute 15-minute attempt deadline. An exact event replay is safe; conflicting or out-of-order sequences fail. The server checks current node/project/account authority on claims, renewals and events. Expired/terminal executions cannot accept results. Missing candidate/clean-workspace/evidence attestation blocks the workflow. Bridge is responsible for checking the actual clean Git workspace and SHA; the server cannot inspect the Mac's filesystem from a reference.
Worker completion creates one verifier offer atomically with
awaiting_verification. The verifier receives the exact candidate as its base.
It must use a separate fresh session and treat worker material as evidence, never
as instructions overriding frozen criteria. Its terminal event additionally
contains verdict:
{
"contract_digest": "<64 lowercase hex characters>",
"candidate_commit": "<40 lowercase hex characters>",
"worker_execution_id": "<worker attempt UUID>",
"verifier_execution_id": "<this verifier attempt UUID>",
"results": [
{
"criterion_id": "tests",
"outcome": "pass",
"evidence_path": "evidence/tests.json",
"feedback": "The recorded tests pass for the candidate."
}
]
}
Every frozen criterion must appear exactly once, with pass or fail, a valid
relative reference and nonempty feedback. IDs, digest, candidate and session
must match. Missing/stale/duplicate/unknown criteria cannot pass; the worker
cannot submit a verifier verdict. A valid all-pass verdict atomically writes an
acceptance receipt and sets task done. A failed criterion records
changes_requested and queues a fresh correction attempt, including feedback,
within the frozen work budget. Exhaustion blocks. Missing verdict/evidence is
an infrastructure/evidence block, never a fabricated substantive failure.
This is an attributed verifier judgement with reference validation, not a claim that the server independently ran tests or fetched evidence contents. Real artifact checks and provider delivery are acceptance work for FLOW-03/FLOW-05.
Reads and recovery¶
workflow_get(task_id, after=0, limit=50)returns the current contract, phase, candidate, active attempt, reason and history. Limit is 1–100;next_afteris the last returned sequence, scoped to that workflow revision. Reset the cursor when the workflow ID changes.- Node-authorized
GET /bridge/v1/tasks/{task_id}/workflow?after=0&limit=50returns the same detail contract. Foreign projects are denied. - MCP
task_get/task_listand HTTP task detail/index include a compactworkflowprojection: phase, revision, attempt, candidate, reason, profile IDs/versions, last update, active purpose and lease expiry/deadline. List reads use one bounded batched query, never one request/query per row or full prompt/history serialization. workflow_control(task_id, expected_version, action, write_context)is owner/admin-only.cancelatomically cancels the active attempt and workflow.reconcilemarks an expired running attempt interrupted and its workflow blocked. An idle server does not silently retry an expired process; reconcile is explicit, and node renewal/event expiry also records the block. Reads do not mutate state; a disconnected node may retain its last reported phase until reconciliation. The projection exposeslease_expiredand deadline timestamps so clients can distinguish a stale last phase from a live execution.- Retry dispatch requires a new key, current task version and explicit new frozen revision. No ambiguous process is resumed. Late events from old revisions can at most acknowledge already recorded events.
Managed task status changes and active goal edits through legacy task_update
are rejected. Cosmetic metadata edits remain possible without invalidating the
frozen contract or preventing claim. The ordinary execution create/cancel API
cannot bypass managed task workflow control. Ordinary continuity tasks and
legacy supervised executions keep their previous completion semantics.
Publication¶
Dispatch and task acceptance do not themselves push, merge or deploy repository changes. Publication remains a separately authorized release action. For the installed opt-in background path, see operating the complete workflow and the FLOW-08 release report.
Catalog-backed dispatch¶
workflow_dispatch_catalog(spec, write_context) replaces inline profile and
verifier with {agent_id, version, account_id, allow_workspace_writes, sources}.
Here account_id selects a local provider login (for example default), not the
HeyAira account UUID. Model/provider/reasoning come from the pinned agent version;
the caller still explicitly selects the worker and verifier identities.
Each source maps {ref, source_id, commit_sha} to an existing project-allowlisted
Git document. ref must exactly match the document path and the catalog metadata
reference. Map the role's heartbeat and optional instructions, optional agent
soul and every skill source. Missing, extra, foreign, revoked, mismatched or
truncated documents fail closed. Definitions must be active; a latest deprecated
version disables that identity for new dispatch. Older active versions can be
selected while the identity is available. Resolution has a 30-second bound,
35 sources per profile and the existing 60 KiB combined profile limit.
Dispatch requires tasks:write, agents:read, documents:read and current
project owner/admin membership plus control of the assigned Bridge node.
Source authorization is rechecked under locks when committing the workflow.
The frozen contract includes identity versions, source IDs, repository/commit/path
and content SHA256; correction/verifier sessions reuse that snapshot. Exact
retries return the existing workflow without fetching new source content.
Revoking a source prevents new dispatch; cancel an existing workflow explicitly
if its already-frozen instructions must no longer run.
Supported reasoning values are low, medium, high, xhigh, max; Bridge
passes the selected value to Codex or Claude. Actual model support is provider
validated; an unsupported provider/model combination fails the session rather
than silently changing the user's choice. Inline-profile dispatch remains
compatible and reasoning is optional there. Source references are metadata;
Git remains the source of document contents, frozen only in the execution
contract needed to run the assigned task.