| name | agent-loop |
| description | Autonomous issue implementation loop with strict issue allowlisting, one linked worktree per issue, draft-PR-first local critique review hooks, inline finding traceability, bounded convergence, and fresh-base validation. Use when Antigravity or Gemini CLI should implement a bounded GitHub issue queue without hosted AI reviewers. |
Agent Loop
Run isolated issue workers and open one draft pull request per issue before
local review starts. The wrapper owns selection, claiming, worktrees, base
integration, initial publication, review-head attestation, and readiness. A
worker only implements, validates, refactors, and commits locally.
Usage
.agents/skills/agent-loop/scripts/agent-loop.sh \
--issues 5105,5106 --iterations 2
.agents/skills/agent-loop/scripts/agent-loop.sh \
--issues 5105,5106 --dry-run
Options:
| Option | Behavior |
|---|
--issues N,N,... | Restrict selection to exactly these issue numbers. Never fall through to unrelated ready work. |
--iterations N | Process at most N issues. A legacy numeric first argument remains accepted. |
--include-assigned | Include an eligible issue assigned only to the current user. The deprecated --resume spelling remains an alias. |
--resume-run FILE | Resume review/finalization from a private contract-v3 run-state file after re-attesting its issue, worktree, branch, PR, base, and head. |
--resume-batch FILE | Resume an ordered contract-v3 allowlist from its private batch-state file. It cannot be combined with --resume-run, --issues, or --dry-run. |
--dry-run | Show selections, dependency decisions, worktree/branch paths, hooks, and publication without claiming, fetching, creating worktrees, running hooks, pushing, or creating PRs. |
Omitting --issues retains the ready-queue behavior for backward compatibility.
Use an allowlist for every scoped or retrospective-driven run.
Collection branches and worker-side publication are removed. Every selected
issue gets a unique agent-loop/issue-<N>-<run> branch and linked worktree.
Required Consumer Files
agent-loop-instructions.md: repository conventions and worker safety rules.
.agents/skills/agent-loop/prompt.txt: prompt containing {ISSUE_ID}. Require
a local commit and forbid push/PR creation.
.agents/skills/agent-loop/agent-loop.config: hook and base configuration.
.agents/skills/issues/scripts/ready.py: ready-queue provider.
The config, instructions, and prompt are bootstrapped with
create_if_missing: true; merge template changes manually into existing
consumers. ready.py is upstream-owned and overwritten by sync.
Config Interface
The config is parsed as literal key = value lines and is never sourced.
Unknown or duplicate keys fail closed. Hook values are shell commands executed
with the issue worktree as the current directory.
| Key | Purpose |
|---|
base_branch | Integration branch; env AGENT_LOOP_BASE_BRANCH overrides it. |
setup_hook | Isolated bootstrap, such as pnpm install --frozen-lockfile. It must not change HEAD or leave Git-visible worktree changes. |
validation_hook | Required non-mutating validation after the worker, every review pass, and fresh-base integration. |
claude_review_hook | Required fresh local Claude review on the draft PR. It must post confirmed findings inline before fixes, publish through $AGENT_LOOP_REVIEW_PUSH_HELPER, reply, resolve, and fail on undisposed findings. |
gemini_review_hook | Required fresh local Gemini deepcritique on the draft PR against $AGENT_LOOP_REVIEW_BASE_SHA, with the same thread contract. |
review_contract_version | Required hook contract. New and migrated consumers use 3; version 2 remains accepted temporarily for staged sync compatibility. |
config_doctor | Run the non-mutating consumer compatibility doctor before selection or claim. Current contract-v3 consumers set true. |
claude_effort_policy | Optional literal Claude effort policy checked by the doctor, such as low. |
review_max_rounds | Positive cap on review rounds. Default 4; cap exhaustion preserves the worktree and blocks publication. |
worker_hook | Optional worker command override (e.g. agy, gemini, or custom CLI invocation). |
worker_model, worker_fallback_model | Primary and capacity-fallback models for the default worker. |
worker_retries | Retries after clean capacity/timeout failures. Default 1. |
worker_timeout_seconds, hook_timeout_seconds |
Hooks receive AGENT_LOOP_ISSUE_ID, AGENT_LOOP_ISSUE_TITLE,
AGENT_LOOP_ISSUE_BODY, AGENT_LOOP_BASE_BRANCH, AGENT_LOOP_BRANCH,
AGENT_LOOP_WORKTREE, AGENT_LOOP_LOG_DIR, and AGENT_LOOP_PROMPT. Because
ordinary gh commands are masked inside hooks, the worker reads its issue from
AGENT_LOOP_ISSUE_TITLE and AGENT_LOOP_ISSUE_BODY rather than the API. Both
are byte-exact copies of the issue text, including trailing whitespace; the
pre-publication re-attestation compares them against the live issue, so a hook
that rewrites them in place will fail that check. Review
hooks also receive AGENT_LOOP_PR_NUMBER, AGENT_LOOP_PR_URL,
AGENT_LOOP_PR_HEAD_SHA, AGENT_LOOP_REVIEW_BASE, the fully qualified fetched remote
ref, the immutable AGENT_LOOP_REVIEW_BASE_SHA captured after the round's fresh
fetch, AGENT_LOOP_REVIEW_ROUND, AGENT_LOOP_REVIEW_ENGINE, and
AGENT_LOOP_REVIEW_RESULT_FILE and AGENT_LOOP_REVIEW_PUSH_HELPER for
contract v3. Both hooks must scope against the SHA so a
mid-round remote update cannot give the engines different bases.
Every successfully completed clean or changed v3 review hook calls
review-ledger.js write-result; the helper derives the complete
same-engine/same-round fingerprint set, including fixed, deferred, and
dismissed dispositions, and atomically writes the structured result. A blocked
hook instead uses review-ledger.js write-blocked-result with an owner-only
blocker file and
must not claim a clean or changed pass. The wrapper validates the engine, round, pinned base, observed
before/after SHAs, classification, finding fingerprints, and final-lane status;
verifies changed fingerprints against resolved v3 dispositions; and posts the
canonical pass/completion marker itself. Material means any substantive
behavior, correctness, security/privacy, data-safety, compatibility,
deployment/sync, or review-integrity change; it is not inferred from file type.
Minor means low-risk, non-behavioral cleanup, clarity, or test/docs polish. Only
material fixes restart at Gemini. A missing, invalid, or blocked result stops
clearly even if the hook process exits zero. Accepted result bytes remain
unchanged through final validation.
The wrapper pins GH_REPO from the current checkout before any
repository-scoped GitHub operation. Setup, worker, and validation hooks cannot
push or call ordinary gh; review hooks run only after draft PR creation and
may mutate that PR and publish a committed fix only through
$AGENT_LOOP_REVIEW_PUSH_HELPER. The helper owns the exact fully qualified
destination and rejects arguments, force, stale remote heads, rewritten
history, and the wrong branch. After each review hook, the wrapper
requires exit 0, a clean attached issue branch, append-only ancestry, unchanged
origin identity, and identical local, remote, and PR head SHAs. At convergence
it queries GitHub review threads and fails if any local-review thread lacks a
disposition reply or remains unresolved.
Existing Consumer Migration
The wrapper is upstream-owned, but config, worker instructions, and the prompt
are create_if_missing consumer files. Existing consumers must therefore merge
the current templates manually before the synced wrapper can run. State protocol
2 deliberately rejects old Codex-shaped run and batch checkpoints; finish or
discard those runs under their original wrapper before migrating.
- Replace
codex_review_hook with the dedicated gemini_review_hook, and set
both review hooks to the exact $AGENT_LOOP_AGY_REVIEW_LAUNCHER commands in
the current config template. The trusted launcher selects each local engine,
pins the upstream review surface, and scopes the pass to
$AGENT_LOOP_REVIEW_BASE_SHA.
The wrapper rejects either review hook naming a retired grill-family skill
or path during startup, before it claims an issue. The check applies to
every accepted contract version, including an existing version 3 config.
- Leave
worker_hook empty so the default Agy worker launcher consumes
worker_model and worker_fallback_model; a hard-coded nonempty hook cannot
change models during a capacity retry.
- Configure a non-mutating
validation_hook, add
review_contract_version = 3, enable config_doctor = true, and optionally
override review_max_rounds = 4 with another positive cap.
- Merge the current local-only wording from the instruction and prompt
templates, including the local bail-record/operator-handoff contract. Sync
will not overwrite those consumer-owned files.
For a non-mutating consumer smoke test from an upstream development worktree,
set AGENT_LOOP_PROJECT_DIR=/path/to/consumer and pass --dry-run. Do not use
that override for a mutating run; execute the consumer's synced script instead.
Do not put secrets, credentials, PHI, customer identifiers, or user data in
config values or hook output. The wrapper deliberately uses a generic PR body
and never copies issue bodies, model logs, or findings into GitHub.
Deterministic Phase Order
- Select and dependency-gate an eligible issue.
- Claim it, refetch title/body/eligibility, rerun ready/dependency gates, and
detect assignment races. If eligibility changes, roll back only the
assignment added by this run; a rollback failure stops before worktree
creation for operator recovery.
- Create a unique worktree and branch from
origin/<base>.
- Run the isolated setup hook.
- Run the worker and require a clean local commit.
- Integrate the fresh base, validate, push, and open a draft PR.
- Run a fresh Gemini
deepcritique followed by a fresh Claude review on that PR,
validating and attesting the PR head after each pass.
- If either reviewer commits a material fix, restart at Gemini. Minor-only fixes
are validated and retained without restarting. Convergence requires one
entire Gemini-then-Claude round with no material fixes. Exhausting
review_max_rounds blocks publication and preserves the worktree.
- If the base advances, integrate and push it on the draft PR before restarting
at Gemini. A non-fast-forward base move stops the loop.
- Re-attest unchanged issue requirements/readiness while excluding only the
wrapper-captured PR from the open-PR addressed check, require every marked
review thread to contain a reply and be resolved, then mark the PR ready.
For an ordered contract-v3 allowlist, the wrapper also writes a private batch
checkpoint containing the allowlist, cursor, per-issue status, and child run
state path. Resume with agent-loop.sh --resume-batch <batch-state.json>. It
will not advance to the next issue until the current issue is safely finalized
or an operator explicitly records it as bailed; uncertain push, PR, or ledger
state always stops recovery.
Do not invoke hosted Gemini, Copilot, reviewit, or any other GitHub-hosted AI
reviewer. The configured local Agy Gemini and Claude hooks are the review
path.
Dependency Gate
With dependency_gate = merged-to-base, parse Blocked by #N,
Depends on #N, Blocked by PR #N, and Depends on PR #N. A PR dependency
passes only when GitHub reports it merged to the configured base and its merge
commit is an ancestor of the current origin/<base>. An issue dependency passes
only when one of its closing PRs meets the same condition. Closed issues alone
do not pass.
Failure and Recovery
On any non-zero worker exit, inspect whether the worktree is dirty or contains
new commits. Preserve all changed or committed work and stop with recovery
commands. A worker that bails writes the consumer-defined local classification
record there; the operator applies any required GitHub labels/comments after
the guarded run exits. Retry capacity/timeouts only when the worktree is
unchanged. Review, setup, integration, validation mutation,
detached/wrong-branch state, review-thread failures, and review
non-convergence failures also preserve the worktree and draft PR. Never reset,
reuse, clean, or delete a dirty recovery worktree.
Contract v3 creates an owner-only atomic run-state.json after draft PR
publication and checkpoints every review round plus convergence. On a review or
finalization interruption, use the exact --resume-run <state-file> command
printed by the wrapper. Recovery re-attests repository identity, issue
assignment and original requirement digests, worktree ancestry, branch, PR
identity, base, and head before it continues. The original run and every resume
hold one exclusive run-scoped lock through finalization; recovery never re-runs
the worker or blindly recreates a remote branch.
If a newly added claim cannot be rolled back before worktree creation, stop and
manually inspect/unassign it. Publication is not atomic: after a push succeeds,
an attestation, upstream-setting, or PR-creation failure can leave the captured
SHA on the remote issue branch, and a failed post-create attestation can leave
an open PR when automatic close also fails. Preserve the worktree, inspect both
remote branch and PR state, and retry or clean up only after explicit SHA
verification; a blind rerun will reject the existing remote branch.
Successful publication removes the clean linked worktree but retains the local
branch. Interrupted runs preserve the active worktree.
Test Guidance
Use focused commands and bounded output. For Vitest 4, target a test with:
pnpm --filter frontend test:run TestName
Do not insert -- before TestName; that can run the full suite.
Source of Truth
This directory is upstream-owned and synced to consumers. Change reusable
mechanics here, not in a consumer's synced copy.