These docs track main. Latest release: v1.2.0.

antigravity-booster
Guides

Writing plans

Hand-writing plan.json: ticket sizing, scopes and rails, and what edges mean.

agb plan compiles a plan for you, but a plan is just JSON and you can write one by hand. This guide covers the rules agb validate enforces and the judgment calls it cannot make. The full field list is in the plan schema.

A compiled plan is disposable: agb plan refuses to overwrite an existing plan.json unless you pass --force, precisely because a hand-written one may not be (overwrite guard).

Skeleton

{
  "repo": "/abs/path/to/repo",
  "base": "main",
  "gate": { "build": "npm run build", "test": "npm test" },
  "prosecution": { "dryPasses": 1 },
  "tickets": [
    {
      "id": "T1",
      "title": "Short imperative title",
      "body": "Self-contained spec: files to create, behavior, tests to write.",
      "scope": ["src/feature/**", "test/feature.test.mjs"],
      "rails": ["src/shared/types.ts"],
      "edges": [{ "to": "T2" }],
      "tier": "mid",
      "pool_hint": "auto"
    }
  ]
}

Plan-level rules

These are checked by validatePlan, shared by agb validate, agb run and the plan compiler (validatePlan):

  • repo is required; relative paths are resolved against the current directory (loadPlan).
  • gate must declare build, test, or both, and each must match npm test or npm run <script>. Put anything more complex in a package.json script.
  • adlcBin is prohibited; the ADLC binary is resolved and authenticated by the runtime.
  • base defaults to main (base default). agb run refuses to start unless that branch is checked out in repo.

Ticket rules

RuleWhy
id matches ^[A-Za-z0-9][A-Za-z0-9_.-]*$ and is unique case-insensitivelyIt becomes the worktree .worktrees/agb-<id> and branch agb/<id> in lowercase, so T1 and t1 would collide (id rules)
body is a non-empty stringThe builder sees only the body; an empty one renders an empty spec
scope is a non-empty array of globsAn empty scope would disable the out-of-scope check (scope and rails)
rails (optional) are valid pathspecsPaths the ticket must not edit
tier is cheap, mid or frontier (default mid)Selects the candidate models
pool_hint is gemini, claude, claude-gpt, gpt-oss or autoFilters the tier's candidates; the combination must leave at least one (tier/hint check). gpt-oss passes the enum check but no tier has a GPT-OSS candidate, so it is always rejected

Tier and hint combinations

The cheap tier contains only Gemini models, so tier: "cheap" with pool_hint: "claude" is rejected at validation time (tier candidates, tierCandidates). Claude builders are reachable through mid (claude-sonnet-5-5-medium) and frontier (claude-sonnet-5-5-high, claude-opus-5-5-high). No tier lists a GPT-OSS model, so pool_hint: "gpt-oss" fails validation with every tier; GPT-OSS appears only as a prosecutor (PROSECUTORS).

Edges

An edge { "to": "B" } on ticket A means A must merge before B starts. The scheduler turns each edge into a predecessor of its target (predecessors) and starts a ticket only when every predecessor has merged (ready check). There are no waves: independent tickets run as soon as a pool slot is free.

  • Edges must name an existing ticket; self-edges and cycles are rejected (edge checks, cycle check).
  • If a predecessor fails, every ticket downstream of it fails as blocked by failed predecessor without running (blocked).
  • Add an edge whenever one ticket reads code another ticket writes. Two tickets with no edge between them run concurrently against the same base.

Scopes and rails

Scope is what a ticket may change; rails are what it must not. After the build, any change outside scope or inside a rail fails the attempt (scope check).

  • Keep concurrent scopes disjoint. agb preflight vetoes pairwise scope overlap between tickets that can run at the same time (preflight overlap).
  • Rail the foundation. When B depends on A, list A's files in B's rails so B cannot rewrite them.
  • Tests belong in scope. A builder told to write tests needs the test file in its scope.

Sizing

Each ticket gets two strikes: one regeneration with the failure appended, then it fails (two-strike rule). A ticket that cannot be finished in one focused builder session is too big. Practical heuristics:

  • One coherent change per ticket: a module plus its tests, not a feature spread across layers.
  • Put shared types, directory layout and dispatchers in a foundation ticket that everything else depends on.
  • Prefer more, smaller tickets with clean edges over a few large ones; parallelism comes from width, and failures stay cheap.
  • Write the body so a fresh agent with no other context can execute it: name the files, the behavior and the tests.
  • Use cheap for mechanical work, mid by default, frontier for design-heavy or subtle work. See Pools and tiers.

Check before you run

agb validate plan.json    # exit 2 if invalid, prints every error
agb preflight plan.json   # scope overlap + coldstart on each ticket body

Then follow the walkthrough from the run step.

On this page