Run lifecycle
What agb run does to one ticket: worktree, build, gates, prosecution, then an integration worktree and a compare-and-swap ref update.
agb run executes a compiled plan with runPlan in lib/scheduler.mjs. This page follows one ticket from dispatch to merge. The short version:
Before any ticket runs
runPlan refuses a plan whose ticket DAG has a cycle, checks the agy binary, verifies the rails enforcement gate, snapshots run integrity, and refuses a dirty checkout unless AGB_ALLOW_DIRTY=1 (lib/scheduler.mjs). It then takes the per-repo run lock (.booster/run.lock.d/), reconciles any integration journal left by a crashed run, reaps stale integration worktrees, reconciles quota leases and refreshes quota telemetry (lib/scheduler.mjs).
Known issue (T-CODE-FIXES-AUDIT item 7)
The AGB_ALLOW_DIRTY error and warning text (lib/scheduler.mjs) says a failed merge or gate will hard-reset the repository and discard uncommitted changes. At v1.0.0 that does not happen to your checkout: hard resets run only inside the ticket worktree and the integration worktree, and the base branch moves by compare-and-swap update-ref. Uncommitted changes are left alone, but they are not part of the run's base. The message will be corrected.
One ticket, step by step
Route and create the worktree
The ticket's tier and pool_hint pick a model from the quota pools. The scheduler creates a worktree at .worktrees/agb-<lowercased ticket id> on branch agb/<lowercased ticket id>, branched from the base (C5). A leftover worktree or branch with the same name from an earlier run is removed first. Ticket ids must match ^[A-Za-z0-9][A-Za-z0-9_.-]*$, and plan validation rejects two ids that lowercase to the same worktree.
Build (up to two strikes)
Each attempt gets an isolated per-attempt Git database and a generated AGENTS.md describing the ticket, then the builder runs through agy (lib/scheduler.mjs). A ticket has two strikes. From the second attempt on, adlc flail-detector can end the ticket early if the builder is repeating itself.
Verify what the builder did
The host fetches the candidate commit out of the worktree (the builder never writes the main repository's refs), checks that the root repository's Git state was not tampered with, and runs the authoritative scope and anti-no-op check: every changed file must match the ticket's scope, and the diff must not be empty (lib/scheduler.mjs). When the ticket declares rails, adlc rails-guard runs too; a rail violation uses up every strike at once. A rail or scope strike resets the ticket worktree to the base so the bad commit does not carry into the next attempt.
Gates in a sandbox
The plan's gate.build / gate.test commands run inside the worktree under the platform sandbox, because the builder could have rewritten the scripts they call. Before that, verifyGateScriptIntegrity compares the candidate's package.json scripts and lifecycle hooks against the base (lib/scheduler.mjs). See Gates and sandboxing.
Prosecution until dry
A prosecutor from a different model family reviews the branch diff in a scratch directory. The ticket needs plan.prosecution.dryPasses consecutive clean passes (default 1) (lib/scheduler.mjs). Blocking findings first go to adlc consensus-fix; a fix candidate is re-verified (scope, rails, gates, prosecution) before it is accepted. Otherwise the strike counts and the builder retries with the findings added to its prompt. See Prosecution.
Rebase under the merge lock
Merges are serialized. Under the lock the scheduler re-verifies run integrity, checks the checkout is still on the base branch, rebases the ticket branch onto the current base tip inside the ticket worktree, and fetches the result into the repository. A rebase conflict quarantines the candidate at refs/quarantine/agb-<id>-failed-conflict and fails the ticket. An empty result fails the anti-no-op gate (lib/scheduler.mjs).
Post-merge gates in an integration worktree
A disposable integration worktree is created at .worktrees/agb-integration-<first 8 chars of the transaction token> (C5) and set to the rebased candidate. The journal is written as PREPARED. Two gate passes run there, both sandboxed (lib/scheduler.mjs):
- Pass 1, baseline regression: the base commit's
test/directory is checked out over the candidate andgate.testruns, so a candidate cannot pass by weakening the existing tests. - Pass 2, candidate gates: the candidate's own build and test. If the ticket changed files under
test/,adlc hollow-testmust also pass.
Advance the base with compare-and-swap
The journal moves to GATES_PASSED, a marker ref is written, and the base branch advances with git update-ref refs/heads/<base> <candidate> <preMergeSha> (C24). Git applies that only if the base still points at preMergeSha, so a concurrent change to the branch makes the update fail instead of being overwritten. The journal then records REF_ADVANCED and FINALIZED, and the marker, integration worktree, ticket worktree and journal are cleaned up.
Sync your checkout, if it is safe
If your checkout was clean, on the base branch and at preMergeSha when the merge began (and still is), its files are moved forward with git read-tree -u -m. Otherwise agb leaves it untouched and prints a notice to run git checkout <base> && git merge --ff-only yourself (lib/scheduler.mjs).
What a failure leaves behind
There is no automatic hard reset or clean of your checkout. All rollback happens through refs and disposable worktrees (C24):
- If a post-merge gate fails before the CAS, the base branch was never touched. The candidate is kept at
refs/quarantine/agb-<id>-failed-post-merge, the marker andagb/<id>branch are deleted, the journal is unlinked and the integration worktree removed. - If something fails after the CAS succeeded, the merge stands. The error is reported as
integration_finalization_failurewithbaseRefAdvanced: true, and the next run's journal reconciliation finishes cleanup. - The worktree-level hard reset (
resetToBase) runs only in the ticket worktree after a rail or scope strike (lib/worktrees.mjs). It excludesAGENTS.md,.adlcand.agb_homefrom cleaning.
Tickets whose predecessors failed are marked blocked and never start. The run report lists merged, failed (with reasons) and whether the run was flagged compromised by the final integrity check (lib/scheduler.mjs).