How a run works

A gateline run is one change (a feature, a fix, a piece of maintenance) carried from a one-page brief to a merged branch by a chain of specialized agents, with a named human approving at each phase boundary. Everything the run is, everything it has done, and everything it is waiting on lives in a single directory of files committed to git.

From conversation to artifacts

In the chatbot workflow most engineers know, the developer is the integration point: you hold the plan in your head, feed the model context piece by piece, and validate every output before it touches the repo. It works, but throughput caps at one conversation, and none of the intermediate reasoning survives the session. gateline moves the integration point into durable, typed artifacts committed to git: agents never share a conversation, they share contracts. Each role consumes specific files, produces specific files, and a human approves at phase boundaries. The pipeline's state is the repo.

Three properties fall out of that one decision. Any agent is replaceable mid-flight: if an implementer's work is unusable, you discard its branch and re-run the work item, because the spec and plan it worked from are unchanged on disk. Models and runtimes are swappable independently of roles, because a role spec says what an agent must consume, produce, and refuse to do — never which vendor's model executes it. And the record is free: every decision, review finding, and verification result is a file with git history, so "why did we build it this way?" has a git log answer.

The lifecycle: four gates

At full weight a run passes four gates, each a named human's recorded decision that closes a phase. The Analyst turns the intent brief into a testable spec; at G0 the human answers "is this what we actually want built?" The Architect turns the spec into a technical plan cut into work items; at G1, "is this how we'd want it built, in safe parallel pieces?" Each work item then loops between an Implementer and a Reviewer, and a Verifier exercises the finished change end to end; at G2, "does the evidence support merging?" Finally the Ops role prepares release and rollback plans; at G3, "ship it?"

GateThe human's questionOn the table
G0 — SpecIs this what we actually want built?intent-brief.md, spec.md
G1 — PlanIs this how we'd want it built, cut into safe parallel pieces?plan.md, tasks/*.yaml, ADRs
G2 — ChangeDoes the evidence support merging?diff, review report, verification report
G3 — ReleaseShip it?release plan, rollback plan

Two caps keep the loop safe. Implementer ⇄ Reviewer cycles are capped at three rounds per work item; a fourth round becomes an automatic escalation to the human with both sides' artifacts. Agents arguing past three rounds are almost always stuck on an ambiguity in the spec, which is a G0 or G1 defect. The cap has an exit: resolving that escalation grants the loop one more round, and the engine asks again for each extra round. And each run carries a cost budget whose exhaustion pauses the pipeline rather than letting quality degrade silently.

Reviewer and Verifier are deliberately separate roles. Review is reading: does this code say the right thing? Verification is running: does the system do the right thing? Collapsing them recreates the rubber-stamp reviews seen in human teams.

A full-weight run from intent brief to release. Roles produce artifacts; gates G0–G3 are human decisions over those artifacts; the implement/review loop is capped at three rounds.
Pipeline diagram: six roles, four gates, one run from intent brief to release, with a state file band and human markers at each gate. intent brief human-authored Analyst → spec.md G0 Is this what we actually want built? HUMAN named human approves Architect → plan.md + tasks/*.yaml G1 safe parallel pieces? HUMAN named human approves per work item, in parallel Implementer diff Reviewer request-changes · ≤ 3 rounds round 4 → escalate to human report Verifier → verification-report.md G2 evidence supports merging? HUMAN named human merges Ops → release-plan.md G3 ship it? HUMAN named human approves released runs/<slug>/state.yaml every step commits

The lifecycle has been exercised end to end. runs/dupefind/, a completed human-orchestrated run at full weight (its state file predates the profile field, and an absent profile: means full), shows the shape the lifecycle leaves behind: three work items each verified after two review rounds, a hand-appended budget ledger of sixteen entries totaling $12.15 against a $50 limit, four gates approved by the same named human with the first three noting burden: confirmation in their notes, and zero escalations.

The run directory is the state

A run lives at runs/<slug>/ on its own branch, run/<slug>, and the directory is the pipeline's state; no state lives anywhere else. Artifacts are committed as they are produced, so the git history is the record of what happened, in order. Once a run merges, its directory is a historical record and is never retro-edited.

runs/<slug>/
├── state.yaml               # phase, profile, gates, budget, tasks, escalations
├── intent-brief.md          # human-authored input
├── spec.md                  # Analyst            → gate G0
├── ux-research.md           # UX Researcher                  (design runs only)
├── design/
│   └── <candidate>/         # one Designer each              (design runs only)
├── plan.md                  # Architect           → gate G1
├── tasks/
│   └── NN-name.yaml         # one work item per Implementer
├── review-NN.md             # Reviewer, per task, per round
├── verification-report.md   # Verifier            → gate G2
├── release-plan.md          # Ops                 → gate G3
└── retro.md                 # human observations after the run

At the center is state.yaml, the run's spine. It records the phase and profile, and the budget as an append-only ledger (one entry per model invocation, carrying timestamp, role, task, round, adapter, model, tokens, and cost) from which totals are derived rather than maintained, so concurrent writers and later audits survive. It also holds the gate ledger (one entry per gate with who approved, when, notes, and an optional burden rating of how much work the review took), task statuses and review-round counts, and an append-only escalation list. A human or an engine decides what happens next from this file, the artifacts committed beside it, and the branch order in which they landed.

Two rows of the tree are not roster output. ux-research.md and design/ come from extension positions that design runs such as runs/fleetview-design/ prototyped inside their own records, as DESIGN.md §4.2 allows; they are not roles, and only the eight roster roles have contracts. retro.md is human notes and has no contract either.

Every artifact the roster's roles hand off follows a contract from contracts/: required sections, concision budgets, a parseable ID and heading grammar, and readability rules for the sections a human reads. All of these are equally bounceable. An artifact missing a required section is malformed, and the consuming agent's first duty is to bounce it back to its producer, never to guess. A breach of a readability rule is bounced the same way, with the rule cited. The handoffs therefore fail loudly or not at all.

Profiles: ceremony scaled to the change

Not every change should pay for the full pipeline. A run profile declares, per run, which roles run and which gates exist. There are three profiles, they are fixed sets, and they nest:

ProfileRoles that runGatesPhase sequence
patchImplementer, ReviewerG1, G2plan → implement → integrate → done
standard+ Analyst, Architect, VerifierG0–G2spec → plan → implement → integrate → done
fullall eightG0–G3spec → plan → implement → integrate → release → done

Every sequence ends at done, and every profile can also end at closed, the second terminal phase. A named human ends a run short of done with gateline close <slug> --as <disposition> --reason <text>, where the disposition is one of already-delivered, superseded, obsolete, or abandoned. The engine never closes a run. Closing deletes nothing, and gateline reopen undoes it in a commit of its own.

patch is for bug fixes and small bounded changes: the human authors the intent brief and the single work item at creation (gateline new --task-file <path> stages it as tasks/01-<slug>.yaml), G1 approves both together, and there is no Verifier (wanting independent verification is itself evidence the change is standard-weight). standard is the workhorse for feature-sized changes that ship by merging; it drops Ops and G3 because for most repository work the merge is the release. full is the complete pipeline, for when deployment is a distinct, risky act that needs a release and rollback plan.

The guardrails matter more than the menu. Profiles are fixed sets, not knobs: there is no per-run role or gate toggle, so if a profile doesn't fit you pick the next heavier one. The gate ledger carries exactly the profile's gates; a gate outside the profile is absent, never auto-approved. Upgrades are one-way and human-decided (the human edits profile: to a heavier value and resumes, and the missing work derives as ordinary dispatches), while downgrading mid-run is forbidden, and an engine that observes one escalates.

Two defaults live at different layers and are easy to conflate. A state.yaml with no profile: field is a full run, the heaviest profile, so every pre-profile record keeps its meaning. The gateline new command, one layer up, defaults to --profile standard for runs it stages. The record's default protects history; the tool's default matches the common case.

Records are historical, so older runs show older shapes. The orchestrator-driven runs/creation-seam/ (a standard run) lists a G3 entry that today's contract would omit: present but undecided, a compatibility shim for a parser written before per-profile gate sets. It is harmless because of the rule above: an undecided or absent gate can never masquerade as approved.

The three profiles are fixed, nested sets. Each heavier profile adds roles and gates; a run can only move up the ladder, by human decision.
Three run profiles as nested bars: patch, standard, full. Each adds roles and gates. Upgrades are human-decided; downgrades are forbidden. patch Implementer · Reviewer G1 · G2 standard Implementer · Reviewer · Analyst · Architect · Verifier G1 · G2 · G0 full Implementer · Reviewer · Analyst · Architect · Verifier · all eight roles G1 · G2 · G0 · G3 fixed sets, not knobs — no per-run toggles upgrade: human edit profile: + resume downgrade: forbidden — the engine escalates no profile: field in state.yaml = full

Creating a run: stage, then arm

A run is created in two steps. gateline new stages the record (branch, intent brief, state file) in a paused, inert state (paused_reason: staged) for human review; nothing can dispatch against a staged run. gateline arm is what makes it dispatchable: it starts the run at the profile's first undecided-gate phase and ensures the run's draft pull request exists.

That pull request is generated from the run's own artifacts (the intent brief first, then the spec once it lands), and it refreshes as the run progresses, until a human edits the body. The generated body carries a hidden marker comment, <!-- gateline:draft-pr -->. Once the marker is gone, which a rewrite of the body normally removes, the text belongs to the human, and the framework never touches the title or body again. The PR stays a draft, carrying a do-not-merge banner, until the run reaches done. A closed run's banner names its disposition instead.

The gate-less exception: historian sweeps

One role runs outside the gate lifecycle. The Historian is scheduled: committed policy in the repo-root orchestrator.yaml sets its cadence (in this repository, a sweep every seven days with a $5 pre-flight cost cap). A due sweep is dispatched as a mini-run, runs/historian-<date>/ on branch run/historian-<date>, carrying a one-entry ledger in sweep.yaml and deliberately no state.yaml, so sweeps stay out of the gate machinery entirely. Its approval is not a numbered gate: a human reviews the docs-delta.md and merges the sweep branch. That merge is the approval.

The gates are where the design concentrates its weight: the next page, how gates keep a human in charge, covers who may write them and how that hold survives automation. For field-level detail see the state.yaml reference; for command flags, the CLI reference.