Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Proposed workflow specification

Status: historical implementation design. The current service implements the workflow using the contracts and routes listed in implementation status; some design-stage names and state shapes below differ from that implementation. This chapter preserves the reasoning beneath the confirmed product choices in PLAN.md. Projects can permit automatic integration or require human authorization, and can delegate binding-rule changes to agents. The service stores bounded logs/reports; source checkpoints remain in Git remotes.

Task outcome and available work

A task represents an outcome. Its kind is code, general, objective, agent_review, human_review, or integration. Agents normally create code or general tasks. An objective groups required children. Review and integration tasks are linked workflow activities, created transactionally from a submission and the applicable project policy, with stable identities preventing duplicates. A revert is a code task that undoes one published integration result on an integrator-owned project; its task view carries a revert target and the original task’s view names it in reverted_by. While the integrator computes its candidate nobody claims or unblocks it, and a review that requests changes on that candidate cancels the revert (see the API contract, “Reverts”).

Persist a task lifecycle of planned, open, done, canceled, or superseded. Expose a derived work status alongside it, so agents do not have to infer readiness from raw records:

Human operators may cancel unowned planned or open tasks, archive tasks for separate browsing, and restore archived tasks to the ordinary task listing. Archiving preserves lifecycle and history. The default task endpoint excludes archived and soft-deleted tasks before pagination; /tasks/archived is a separate project-scoped listing. Deletion is soft and limited to canceled or planned tasks with no attempt, dependency, objective, or workflow history. Canceling a task also retires it from the queue: a task with no attempt, dependency, objective, or workflow history, and no replacement, is soft-deleted; any other canceled task is archived instead, so its history stays browsable. The cancel response reports which with deleted or archived. Active attempts and review/integration workflows block lifecycle changes.

Work statusMeaning and next action
plannedOutcome is recorded but not admitted to the work queue
readyThe task can be claimed; a candidate listing grants no ownership
in_progressA current unexpired attempt owns this task
waiting_reviewA submitted candidate needs one or more linked reviews
waiting_integrationReview requirements are satisfied; the linked integration task is pending
integratingThe linked integration attempt is preparing or publishing a result
validatingThe integrated result is being checked; the deliverable is still incomplete
blockedAn explicit dependency, decision, capability, resource, or verification issue prevents the next action
recovery_requiredAn expired owner or uncertain external effect requires reconciliation
doneThis task kind’s required outcome is accepted
canceledWork was deliberately stopped; this does not satisfy a dependency
supersededA replacement/duplicate relationship closes the record; the replacement is explicit

The response also includes structured blockers, current attempt, submission, linked activities, and exact next actions. It never uses a status string as a substitute for these facts. These statuses describe the selected task: a code task can be waiting for review while its linked review task is in progress.

Task records also carry a read-only processing object that says whether anyone is acting on the status right now, so a list can tell a queued review from a claimed one without opening the task. It is null unless the task is in_progress, waiting_review or, as described below, an integrator-owned waiting_integration. Its stage is in_progress (a live, authorized, unexpired attempt owns the task), in_review (a required review activity is claimed under a live lease), awaiting_reviewer (every pending review is queued and unclaimed) or review_lease_expired (a claimed review’s lease lapsed and needs recovery). active is true only for the first two. holders lists the lease holder’s name, harness, workstation and lease_expires_at; a value the service did not record is null, never a guess. A live lease proves a claim, not that the holder’s process is running. The dashboard animates a status icon only while active is true, labels every stage in text, and shows holders in a tooltip that opens on hover and focus.

On a project whose integration_owner is integrator, a task that is waiting_integration carries processing.kind integration: an additive indicator that leaves work_status and its filters unchanged and creates no owner, lease, claim or policy change (holders is always empty). The service derives it from the current code submission’s newest integration result for its exact candidate_revision; a result for another candidate, a superseded submission or a different revision is ignored, so old evidence never makes the task look active. Its stage is awaiting_checks (a result is pinned and no check was reported), verification_queued (the integrator reported required checks that are queued and none is running), verifying (at least one required check is running), checks_passed (every required check passed and the result awaits publication), checks_failed (a required check’s deciding run did not pass and no newer run is going), verification_unknown (the report of queued or running checks, or the integrator heartbeat, is more than three minutes old), publishing (push authority is outstanding and unexpired) or publication_unconfirmed (push authority expired before the integrator observed the target). active is true only for verifying and publishing. Publication ends, and the indicator disappears, when the integrator’s observation completes the task or returns it to review. The object also names submission_id, candidate_revision, result_id, result_revision, result_created_at, observed_at (the integrator’s last progress report), authority_expires_at, checks (total, passed, failed, running, queued, pending) and up to 25 check_runs (check_name, state, run_id, run_attempt, conclusion, started_at). A task that is blocked, done, ready again or superseded, a legacy agent-owned integration, and a task with no result for its current candidate have processing null; their existing statuses (integrating, validating, recovery_required) are unchanged. The integrator feeds the queued and running state through POST …/integrator/check-progress; completed runs and publication come from receipts and push authority as before.

Status is derived from authoritative records, including server-time lease validity. The database must not rely on a periodic job to change in_progress to recovery_required before refusing a stale update. Transactional projections may speed dashboards but cannot grant authority or hide expired ownership. The API does not accept arbitrary writes to derived status.

An expired current attempt or unresolved external outcome takes precedence over ready. A task waiting for an active linked review/integration displays that phase and retains any blockers as separate fields. No task becomes complete merely because all owners have released their attempts.

Admission and task selection

Task admission requires a title, concrete outcome, acceptance criteria, kind, project, priority, source/provenance, and any required capabilities or resources. A code task also needs its repository/target binding. Use a checklist of explicit criteria; do not require the service to interpret arbitrary prose as executable tests. Planned tasks can hold incomplete drafts.

Admission is also budgeted. Every task records its origin: human or agent from the principal that created it, or service when the service created it (reverts, integrator follow-ups, re-lands and internal review/integration tasks). A task may carry an admission_class (revert, fix_target, deflake or refusal_fix) that marks a fix; fixes are always admitted and do not use the budget. An agent-created task without a class is admitted only while fewer than N agent-originated tasks were admitted in the current ISO week (UTC, Monday 00:00 to the next Monday) in the task’s own project; the budget is per project, and tasks of other projects do not count against it. The 6th such task in a week is still created, but as planned, and the creation response carries an admission object with held: true and the reason; the digest lists it under held_agent_tasks. A human releases it by editing it to planned: false; an agent cannot, even with a task-definition grant. Human tasks, tasks with a class and tasks an agent itself created as planned are never held and do not use a place. N defaults to 14 and is the service setting --agent-task-weekly-budget (COORDINATOR_AGENT_TASK_WEEKLY_BUDGET, 0 through 10000; 0 holds every unclassed agent task). The week rolls over with the clock: the first agent task of a new ISO week is admitted again.

The fix classes (revert, fix_target, deflake, refusal_fix) skip the budget, so an agent cannot grant one to its own task. Who may set each class:

ClassHuman or serviceAgent
revertalwaysadmission_evidence.result_id naming a project integration result that landed (published, already contained, or published after reopen)
fix_targetalwaysresult_id naming a project result with a failed check receipt (optionally narrowed by check_name), or report_id naming a fix_target integrator report of the project
deflakealwaysreport_id naming a flaky integrator report of the project
refusal_fixalwaysno record to verify: only a designated principal
canaryrefusedonly a designated canary principal

An agent the operator names with --fix-class-principals (COORDINATOR_FIX_CLASS_PRINCIPALS; empty by default) may set any fix class without evidence. Otherwise an unbacked class is refused with a 403 and no task is created; the agent can file the task without a class, and the budget counts it.

The end-to-end canary (one task per host and harness per day, seven or more a week) would otherwise use the whole budget and hold genuine agent work, so it has its own route: the request-only admission_class canary. It is accepted only from an agent principal the operator designates with --canary-principals (COORDINATOR_CANARY_PRINCIPALS); any other creator is refused with a 403 and no task. A canary task is always admitted and is not counted against the budget, and the same principal’s tasks without the class are budgeted normally. The canary asks for priority 0 (urgent, the highest the service accepts), so selection hands it out before every task of priority 1 to 3.

Default priorities are urgent, high, normal, and low. Within a project, selection filters eligibility and requested task kinds/capabilities, then orders by priority, oldest-ready time, and stable ID. Ready time resets only when work actually becomes eligible again, not on a heartbeat or cosmetic edit. There is no agent-vendor preference or required scheduling model.

Agents search existing and recently closed tasks before creating new work. An optional stable external source key is unique within its declared source namespace. Similar titles produce suggestions, not automatic task identity. The service can prevent duplicate claims and repeated source imports; it cannot guarantee that separately worded outcomes never overlap.

Normal dependency edges require the prerequisite task to be done. Cancellation and supersession produce an explicit blocker and replacement reference; they do not silently satisfy the old edge. Authorized dependency edits retain history. Objectives cannot complete until required children and their own acceptance criteria are satisfied. Reject parent and dependency cycles, including concurrent edits that would create a cycle only when combined.

Attempts and checkpoints

Each attempt belongs to one task, authenticated session, workstation, and ownership generation. Its state is active, submitted, released, blocked, expired, or canceled. Only an active, current, unexpired attempt can perform ownership-dependent mutations. Historical attempts are retained.

For code work, claim first, then prepare/register the separate worktree and checkpoint the starting repository state before editing. A preparation failure releases or blocks the attempt with a reason; it does not leave an unreported reservation. Lease renewal can continue during preparation.

A checkpoint includes a short summary, current action, progress since the last checkpoint, next step, blockers, and current branch/revision/job references when relevant. Heartbeat requests need not fabricate a new progress summary. Save health time and progress time independently.

Explicit relinquishment records a final checkpoint and an outcome. A request to cancel an active task revokes service authority but retains jobs/resource holds until their actual disposition is known. Operators see the distinction between canceled work and a still-running external job.

Submission, review, and completion

Submitting a code attempt creates an immutable candidate containing the task revision, policy revision, repository/base/candidate revisions, result summary, acceptance evidence, handoff, and linked/new lessons. Artifact references include their accessibility. The submission ends the implementation attempt and admits the required review activities atomically.

Reviews become eligible from this candidate, not from the code task’s done state. This avoids a dependency cycle. Review tasks use their own ownership, candidate binding, and attribution. A completed review task means a decision was recorded; its decision may be approval or changes requested. The code task uses the decision as a guard, not merely the review task’s terminal state.

The review modes are none, agent, human, and both, with agent as the selected default. Propose one required approval of each enabled type initially. Human decisions require human authentication; agent review uses the separation rules in the coordination contract.

A changes-requested decision makes a revision attempt eligible, subject to the project’s retry/escalation rules. It does not reopen the completed review task. A new code submission supersedes the old candidate and creates its own required activities; old approvals never transfer automatically. Pending obsolete activities are canceled, while active ones lose authority and retain history.

After the required approvals, a linked integration task becomes eligible under the selected integration-authorization policy. It reserves the canonical target, records the observed target and candidate, and prepares the intended result. Conflicts, a moved target, incomplete checks, and uncertain publication outcomes have distinct blockers and recovery instructions.

The integration result records its base, resulting commit/tree, publication observation, verification roster, check outcomes, and reporting actor. Required checks must apply to the exact integrated tree and configured environment. Pre-publication testing can count when tree equivalence is verified; checks whose semantics require a published/deployed state must actually run there.

The final transaction verifies the current candidate and required policy, applicable approvals, integration evidence, required checks, and ownership. It completes the integration activity and code task together, records the final handoff, and reevaluates downstream readiness. Publishing code without satisfying these checks leaves visible incomplete work. It does not automatically revert the target or authorize deployment.

General tasks complete from their own acceptance evidence and configured review, without artificial Git requirements. Objectives complete from their required children and criteria. They have no implementation worktree of their own.

Recovery and late information

Recovery is an attempt mode on the affected task, not permission to overwrite the old attempt. Claiming recovery is atomic and uses a new generation. In manual projects, an operator must release the recovery hold first. Inspection can read all retained evidence but cannot bypass reservations held by uncertain jobs.

Record one recovery disposition: resume accessible work, reconcile an already delivered result, restart with an explanation, or remain blocked. Reconciliation must satisfy the same completion guards as normal work. A commit found in Git does not itself establish passed review or verification.

Support append-only late notes and job observations from their authorized reporters after an attempt expires. They are clearly historical/unaccepted and cannot renew ownership, approve the current candidate, release another owner’s resources, or complete the task. A current recovery owner may explicitly adopt applicable evidence after verification.

Changes to requirements or policy during work

Descriptions, acceptance criteria, dependency sets, and project policy use revision checks. Cosmetic changes preserve acceptance applicability when marked as such; substantive changes require explicit reconciliation. An agent cannot erase or weaken acceptance criteria to make its own submission pass.

A project may explicitly authorize agents to change binding project rules without human approval. Each change checks the existing delegation, requires the expected policy revision, and records rationale and actor. Delegation and service credential administration are separate from editable rule text: changing a rule cannot grant its author a new administrative identity or fabricate human approval.

A new policy revision prevents new claims/submissions from silently following the old policy. Existing attempts receive a policy-changed next action and can checkpoint or relinquish safely; they must reconcile before taking a newly restricted action. Historical approvals remain tied to their original policy. The service records the authorized actor’s resolution instead of silently grandfathering or retroactively rewriting every in-progress task.