Share
Specification

Tasks

Task Lifecycle

A Task is the unit of work that flows through an Assembly Line. It is created when a user (or an external trigger) submits a Task Card. The Task then progresses through each Station until it is completed or failed.


Task Card

A Task Card is what a user fills in to create a Task. It has two required fields:

FieldTypeRequiredDescription
titlestringyesShort name for the work (e.g. "Vibecheck: my-org/backend")
descriptionstringyesFull context for the Agent, in markdown

The description field carries all the structured inputs the Agent needs. Assembly Line designers document the expected description format for their pipeline. For example, the Vibecheck Assembly Line expects the description to contain a repository URL, branch, and optionally a stack description and areas of concern.

There are no typed input fields in v1. The Agent reads the description and acts on its content.

Optional task fields:

FieldTypeDescription
priority"low" | "medium" | "high"Scheduling priority (default: "medium")
labelsstring[]Custom labels for tracking (not used for routing — Station labels handle routing)

Task Lifecycle

A Task moves through the following states as it flows through an Assembly Line:

[Submit Task Card]
        │
        ▼
     queued          ← waiting for a Runner to claim the Job at the current Station
        │
        ▼
     claimed         ← a Runner has taken the Job and is starting the Operator
        │
        ▼
    in_progress      ← the Operator has started the Agent, work is underway
        │
   ┌────┴────┐
   │         │
   ▼         ▼
success    failure
   │         │
   │         └──────────────────────► failed  (pipeline stops)
   │
   ├── [not last Station] ──────────► queued  (at next Station)
   │
   ├── [last Station] ──────────────► completed
   │
   └── [Transition Rule: gate] ────► awaiting_review
                                          │
                                    ┌─────┴─────┐
                                    │           │
                                  approve     reject
                                    │           │
                                    ▼           ▼
                                 queued       failed
                              (next Station)

State Descriptions

StateDescription
queuedWaiting for a matching Runner to poll and claim the Job
claimedA Runner has claimed the Job; Operator is starting
in_progressOperator has started the Agent; work is underway
awaiting_reviewTask has reached a Human Review Gate and is paused pending approval
held(v1.1) A fan-out parent's dispatch is held because not all of its Child Tasks have Settled. A sibling of awaiting_review: the Task is paused before queued, released by the join (or by force release) instead of by a human approval. Reference implementation flag: joinHeld. See 12-fan-out-join.md
completedAll Stations finished successfully
failedA Station failed with no applicable retry or recovery rule

Settled (v1.1)

Alongside the states above, v1.1 defines Settled — a resting predicate rather than a queue state: the Task's work reached a final outcome (success or failure) and no further dispatch was chained. Fan-out joins wait on Settled. Every dispatch clears it. The full settle rules (including how Child Tasks settle by arriving at their parent's Join Station) are normative in 12-fan-out-join.md.


Task Data

The full Task object maintained by the Server:

interface TaskData {
  id: string;
  owner: string;
  projectId: string;
  stageId: string;            // Assembly Line ID
  title: string;
  description?: string;
  columnId: string;           // Current Station ID
  order: number;              // Position within the Station's queue
  priority?: 'low' | 'medium' | 'high';
  labels?: string[];
  pendingGateId?: string;     // Set when task is in awaiting_review state
  assemblyLineRepo?: AssemblyLineRepo;  // Provisioned when createAssemblyLineRepo fires

  // ── Fan-Out / Join (v1.1 — see 12-fan-out-join.md) ──
  parentTask?: string;        // Set on a Child Task: id of the spawning (join) Task.
                              // Reference implementation: `parentTaskId`
  blockedBy?: string[];       // On a fan-out parent: the Child Task ids the join waits on.
                              // Reference implementation: `blockedByTaskIds`
  joinStation?: string;       // On a fan-out parent: Station where children collect and
                              // settle instead of dispatching.
                              // Reference implementation: `joinColumnId`
  settled?: Settled;          // Resting outcome of this Task's work. Cleared on every dispatch.
  childResults?: Record<string, ChildResult>; // On a fan-out parent: aggregated at Join Release,
                              // keyed by Child Task id. Feeds {{children.results}}

  createdAt: number;          // Unix ms
  updatedAt: number;          // Unix ms
}

interface Settled {
  conclusion: 'success' | 'failure';
  at: number;       // Unix ms
  jobId?: string;   // Job that settled the Task (idempotency guard)
  actor?: string;   // e.g. 'runner_job', 'join_arrival', 'manual'
  result?: string;  // Station output captured at settle time
}

interface ChildResult {
  title: string;
  conclusion: string; // 'success' | 'failure' | 'missing' | 'unresolved'
  result: string;     // the child's final Station output summary
}

interface AssemblyLineRepo {
  repoId: string;
  url: string;    // https://server/api/git/owner/project/repoId.git
  branch: string; // main
  createdAt: number;
}

Task Submission API

POST /api/owners/{owner}/projects/{project}/stages/{assemblyLineId}/tasks
Authorization: Bearer {token}

{
  "title": "Vibecheck: my-org/backend",
  "description": "Repository: https://github.com/my-org/backend\nBranch: main\nConcerns: auth implementation",
  "columnId": "intake",
  "priority": "high"
}

Response: The created TaskData object.

If the first Station is configured with type: "dispatch_worker", the Server automatically creates a Job and queues it for dispatch after creating the Task.


Per-Station Progress

A Task at Station 3 of 6 shows progress via columnId (the current Station ID). The Server maintains the history of which Stations the Task has already passed through, enabling the UI to display a progress indicator.