SKILL.md · git:20260910.8a1f5e2 · 2026-09-10 · sha256 1f39962cafc0f87b
SKILL.md git:20260910.8a1f5e2C
Immutable. This exact content is served forever at /api/v1/blob/1f39962cafc0f87b.
# Agent Loop Skill — Claude Code Native Mode
This skill lets you run the `coding-review-agent-loop` orchestration directly inside
an interactive Claude Code session, without calling `claude -p` for Claude turns.
Claude (you, the host) performs coder/plan turns using your active session context.
External agents (Codex, Gemini) are invoked via their local CLIs as subprocesses.
GitHub operations go through `gh`.
**Skill vs the `agent-loop` CLI (when to use which):** use the skill when you want to
participate/oversee, want Claude turns on your **session model** (e.g. Opus, no
`--claude-model` needed), want conversational setup, or want the host to investigate an
unexpected failure interactively. The skill still requires the `claude` executable to
start Claude Code; it avoids launching a new `claude -p` process for each host turn, so
an on-disk binary update does not affect the already-running session. Use the CLI for
lower-overhead orchestration in typical runs: its round control and state transitions are
mechanical Python code, while skill mode also spends host-session context and output tokens
interpreting and executing the orchestration workflow. Actual quota use varies. The CLI also
supports hands-off automation and externally scheduled resume after quota reset — optionally a
`--test-command` gate and, with
`--auto-merge`, CI-wait + merge, or explicit `--managed-ci` exact-head qualification
with a printed head-guarded manual merge command (all are configuration-dependent;
without `--test-command`, `--auto-merge`, or `--managed-ci`, the CLI runs no gate
and does not poll or merge). The skill never auto-merges (merge stays a human
decision), cannot continue or schedule its own restart after the host session exhausts
quota, and may still encounter Claude Code tool-approval prompts. Keeping the skill also
reduces reliance on
`claude -p` for Claude turns if it is ever billed/restricted differently (announced once,
then reversed) — whether interactive-session usage is treated differently depends on
Anthropic's current terms and product behavior (see the "Billing and terms note" below),
so this is about reducing the dependency, not a guaranteed billing outcome. See
[`Claude Code Skill Mode`](README.md#claude-code-skill-mode) in `README.md` for a summary.
## Prerequisites
- `gh` authenticated and configured.
- `codex` CLI installed (for Codex reviewer turns).
- `gemini` CLI installed (for Gemini reviewer turns).
- The `coding-review-agent-loop` package importable from `src/` (run from repo root).
## Process-tree containment
External agents and `--test-command` gates are mechanically contained when the
host supports systemd 253+, a user manager, delegated unified cgroup v2, and
the requested controllers. They share a per-user `agent-loop.slice`, with a
conservative aggregate that reserves OS headroom and child profiles for
`coder`, `reviewer`, `repair`, and `test-gate`. The foreground launcher is
`systemd-run --user --scope --quiet`; it intentionally has no `--wait`,
`--service`, or `--pipe`. A scope-internal shim records target start or target
exec failure, so the report—not a launcher exit number—decides whether a
numeric status belongs to the target.
Run `agent-loop containment-preflight` to inspect resolved limits and
capability-aware telemetry. `auto` visibly falls back to process-group
TERM/KILL, which is deterministic but has no memory ceiling; `required` fails
closed. OOM, hard memory/swap, and task-limit events are `resource-exhausted`;
`MemoryHigh` and PSI are pressure diagnostics. Missing optional counters are
`not collected on this host`, not evidence loss. The managed test wrapper
rejects a same-lane duplicate before spawn and does not learn its runtime.
Unwrapped commands cannot be deduplicated from free-form logs without a
structured hook. In-session Claude and arbitrary descendants remain part of
the host session; use the managed wrapper for test gates and external agents
for the mechanical containment boundary.
Skill-mode test gates select this policy with
`AGENT_LOOP_CONTAINMENT_MODE=auto|required|off`; the default is `auto`.
## How to invoke this skill
Open a Claude Code session **in the `coding-review-agent-loop` repo root** (or
any directory where `helpers/` is on the Python path). Then tell Claude what
you want in natural language, for example:
```
Run the agent-loop skill for issue #123 in myorg/myrepo with gemini as reviewer.
```
```
Plan and implement issue #42 in myorg/myrepo, reviewers: codex and gemini.
```
```
Run agent-loop on PR #99 in myorg/myrepo.
```
```
Resume the agent-loop skill for issue #123 in myorg/myrepo.
```
Claude will read this file, pick a mode, and follow the procedure below. You do
not need to type any slash command; natural-language requests are enough.
---
## Choosing a mode
This is one skill with three modes; pick the procedure from what you're given:
- A **PR number** to review → **PR mode** (run the PR-loop).
- An **issue number**, or you want a plan first → **issue mode** (plan-loop, then
*optionally* implement + PR-loop). Confirm whether to stop at an approved plan
or continue into implementation.
- A **free-form task** with no issue yet → **task mode** (create a scratch issue,
then proceed as issue mode).
All modes share the sub-procedures below, the same primitives, the same session/
resume model, and the same posture: **merge is always a human decision.** For any
mode, you need `OWNER/REPO` and the reviewer set (`codex`, `gemini`, and/or
`antigravity` — the `agy` CLI, the migration path for Gemini CLI consumer access
that Google retires on 2026-06-18). `antigravity` works wherever an external
coder/reviewer does (`--coder antigravity` / `--reviewers antigravity ...`); `agy` is
accepted as an alias (e.g. `--coder agy` / `--reviewers agy`), normalized to `antigravity`.
With no override, it uses the ordered fallback chain `Gemini 3.7 Flash (High)` →
`Gemini 3.6 Flash (High)` → `Gemini 3.1 Pro (High)`. Use `--model MODEL` for the legacy single-model
override or `--antigravity-models MODEL [MODEL ...]` for a custom ordered chain;
the two model options are mutually exclusive. Customize fallback detection with
`--antigravity-quota-signatures SIGNATURE [SIGNATURE ...]`. Each `agy --print`
call passes `--print-timeout` from `--antigravity-print-timeout-seconds`
(default `600`, i.e. ten minutes, matching the `agent-loop` CLI), overriding
`agy`'s own five-minute print-mode default so long turns are not cut short.
For a required local test that may run up to 1,800 seconds, configure this
whole-invocation deadline above that cap with additional budget for analysis,
edits, reporting, and other turn work; the default cannot accommodate it.
Provider capacity failures retry the active model before fallback; the
`--max-retries` allowance is shared across the chain, capping calls at
`models + retries`. Custom quota signatures control eligibility, while settings,
model, timeout, and schema failures remain deterministic.
These options are available on every skill command that can invoke an
external agent.
---
## Sub-procedures
These are the building blocks; the modes sequence them.
### Plan-loop (for issue N)
1. Write the implementation plan to
`/tmp/agent-loop-skill/{session-id}/plan-r{N}.md`, ending with:
```
<!-- AGENT_PLAN_STATE: approved -->
-- Anthropic Claude
```
2. Run one round. `skill_runner` handles resume, plan validation, attaching
`AGENT_LOOP_META`, posting to GitHub, running each reviewer, rendering/
validating responses, and writing session state:
```bash
python -m helpers.skill_runner run-plan-round \
--issue ISSUE --repo OWNER/REPO \
--plan-file /tmp/agent-loop-skill/{session-id}/plan-r{N}.md \
--reviewers codex gemini \
[--workdir-codex /path/to/checkout] [--workdir-gemini /path/to/checkout] [--workdir-antigravity /path/to/checkout]
```
It prints a JSON result:
```json
{ "state": "approved" | "blocking", "round_number": N,
"blocking_items": [...], "approved_reviewers": [...] }
```
3. Decide:
- `"blocking"` → address `blocking_items`, post a change-summary comment
(template below), write a revised plan, and re-run. The round number
increments automatically.
- `"approved"` with empty `blocking_items` → **planning is complete.**
- Clarification needed → post an `<!-- AGENT_CLARIFY -->` comment and stop.
Change-summary template (`EOF` must be flush-left when run in a shell):
```bash
gh issue comment ISSUE --repo OWNER/REPO --body "$(cat <<'EOF'
Addressed round-N feedback:
- **item-X**: <what was changed>
- **item-Y**: <what was changed>
-- <Your Name>
EOF
)"
```
### Implement step (after an approved plan)
Run this only when the user asked to implement (see **issue mode**):
1. If a PR for this issue already exists (e.g. you were interrupted), resume it —
do **not** open a second one.
2. Implement the approved plan in your working tree on a feature branch and commit.
3. Open a PR that references the issue, and note the PR number. Hand off to the
PR-loop.
### Answer-mode discussion summaries
When the CLI is used for `discuss --discuss-result-mode answer`, the public
issue comments lead with a concise state rather than the raw transcript. Each
completed interim round may expose cumulative consensus, active disagreements,
changes, missing facts, and next-round focus; a final comment exposes the fixed
mechanical outcome, agreed conclusions, remaining decisions, and next action.
The configured `--discuss-analyzer` is the only eligible synthesis agent.
Enriched agendas cost no additional round call; a legacy agenda permits one
bounded analyzer fallback, and exact/semantic/debater-confirmed final artifacts
are adapted without a redundant synthesis call. Missing analyzers, invalid or
unsupported claims, and transport failures retain the existing fail-closed
rendering. Partial rounds are labeled as covering responding debaters only and
cannot become final consensus. The latest validated snapshot is persisted for
resume, while full per-agent responses remain the audit record and synthesis
text/excerpts are bounded and spillable.
### External by-phase implementation (after an approved plan)
Use this when the user asks for skill-mode parity with
`plan_execution_mode="implement-by-phase"` and an external coder should perform
the first automated phase:
```bash
python -m helpers.skill_runner run-implement-by-phase \
--issue ISSUE --repo OWNER/REPO \
--coder codex \
--plan-file /tmp/agent-loop-skill/{session-id}/approved-plan.md \
--workdir /path/to/push-capable/clone \
[--base main]
```
Live runs require a push-capable `--workdir` (or `--workdir-codex` /
`--workdir-gemini` / `--workdir-antigravity`). The command decomposes the
approved parent plan using an
`implement-by-phase` decomposition marker, creates or reuses child phase issues,
and then inspects phase 1:
- If phase 1 is `agent-pr`, it records a phase handoff marker on the parent and
runs the external coder against the child issue, using that phase's
`parent_context` as the approved implementation plan. It does not write the
one-shot implementation marker used by `run-implement`.
- If phase 1 is `human-action` or `manual-close`, it prints JSON identifying the
child issue and stops without posting a phase handoff or running the coder.
- If a matching phase handoff marker already exists, it prints a resume hint for
the child issue and does not invoke the coder again.
`--dry-run` parses the decomposition and runs the implementation dry-run stub,
but it does not create child issues, post markers, push branches, or open a real
PR. Dry-run child issue numbers may be absent, so the JSON is a preview of the
phase that would be implemented.
### PR-loop (for PR N)
1. Run one round. The PR diff is fetched automatically — there is no plan-file
step:
```bash
python -m helpers.skill_runner run-pr-round \
--pr PR_NUMBER --repo OWNER/REPO --reviewers codex gemini \
[--head-sha SHA] [--workdir-codex /path/to/checkout] [--workdir-gemini /path/to/checkout] [--workdir-antigravity /path/to/checkout] \
[--test-command "pytest -q"] [--test-workdir .] \
[--approved-followups summarize|issue]
```
The result shape matches plan rounds, plus the optional `tests` and
`approved_followups` fields (see **Gates & guardrails**).
2. Decide:
- `"blocking"` with a host-owned PR → fix the code, push, post a
change-summary comment (template below), and re-run. A new head SHA starts
a new round automatically.
- `"blocking"` with an external-coder PR → have that coder address the
settled blocking review and push to the same PR branch:
```bash
python -m helpers.skill_runner run-pr-fix \
--pr PR_NUMBER --repo OWNER/REPO \
--coder codex \
--reviewers claude gemini \
--workdir /path/to/push-capable/pr-clone
```
The PR must be open, `--reviewers` must exactly match the reviewer set used
by the previous `run-pr-round`, and `--workdir` must be a clean,
push-capable clone where the PR head branch can be checked out by name.
Re-run `run-pr-round` after the coder follow-up posts.
- `"approved"` → check the test gate, then **stop at "ready to merge — human
decision."** The skill never merges.
Change-summary template:
```bash
gh pr comment PR --repo OWNER/REPO --body "$(cat <<'EOF'
Addressed round-N feedback:
- **item-X**: <what was changed>
- **item-Y**: <what was changed>
-- <Your Name>
EOF
)"
```
---
## Modes
### PR mode
Run the **PR-loop** on the given PR. Done when it approves (ready to merge —
human decision).
### Issue mode
1. **Plan-loop** on the issue until approved.
2. Then, based on the user's intent:
- **"plan and implement"** → **Implement step** → **PR-loop** → ready to merge.
- **"just plan"** (the default) → report the approved plan and stop.
This is the skill's equivalent of the CLI's `issue --plan-first
[--implement-after-approval]`. Because the host **is** the coder, "implement after
approval" is your stated intent, not a code flag.
### Task mode
For a free-form task with no issue yet:
```bash
python -m helpers.skill_runner run-task-round \
--task "Add a --verbose flag to the CLI" \
--repo OWNER/REPO \
--plan-file /tmp/agent-loop-skill/{session-id}/plan-r{N}.md \
--reviewers codex gemini
```
This creates (or idempotently reuses) a scratch issue from the task text, then
runs the first plan round on it. Use `--task-file PATH` (or `--task-file -` for
stdin) for longer descriptions; `--dry-run` previews the issue it would create
without creating it. From there, continue **exactly as issue mode** from the
Plan-loop onward (including the optional Implement step + PR-loop).
Task mode accepts the same coder roles as issue mode. The host coder remains the
default and requires `--plan-file`. To have an external coder produce the plan,
pass `--coder codex|gemini|antigravity` (or `agy`) and omit `--plan-file`:
```bash
python -m helpers.skill_runner run-task-round \
--task "Add a --verbose flag to the CLI" \
--repo OWNER/REPO \
--coder codex \
--reviewers gemini
```
---
## Gates & guardrails
- **Test gate** (PR-loop): `--test-command` runs after the reviewer turns in
`--test-workdir` (default: the current directory, where you as the host coder
have the PR branch checked out). The outcome is reported under `tests`:
```json
"tests": { "command": "pytest -q", "passed": true, "exit_code": 0, "output_tail": "..." }
```
A setup failure (empty/bad command, missing executable, or missing
`--test-workdir`) is reported as
`{"passed": false, "exit_code": null, "error": ...}` rather than crashing the
round. **"Ready to merge" = `state == "approved"` AND `tests.passed`.** Treat a
failing or errored gate as a hard stop, even when reviewers approved.
- **Approved-followups** (PR-loop): `--approved-followups summarize|issue`
publishes reviewers' future follow-ups when (and only when) a round is
**approved**. `summarize` posts one PR comment of the reconciled follow-ups;
`issue` files up to three follow-up issues; `ignore` (default) discards them.
The mode is also threaded into the reviewer prompt, so reviewers only surface
future follow-ups when a non-`ignore` mode is set. Publishing is idempotent
(one publish per PR head SHA + mode) and reported under `approved_followups`:
```json
"approved_followups": { "mode": "summarize", "published": true, "count": 2 }
```
- **Agent memory** (plan-loop and PR-loop): repo-scoped orientation context
(repo summary, architecture map, module index, test profile, toolchain,
changed-file summaries) is generated deterministically (git + static analysis,
no LLM) and included in the reviewer prompts so Codex/Gemini get the same
context the CLI gives them. On by default; `--no-agent-memory` disables it,
`--refresh-agent-memory` forces regeneration. The cache lives under the skill
session dir and is incremental. Generation is advisory — if it fails, the round
continues without memory.
- **Usage/cost** (plan-loop and PR-loop): the round result includes a `usage`
field with token totals for the external reviewers (Codex/Gemini), aggregated
per agent. It is **external-agents-only** — the host's Claude coder/plan turns
run in the interactive session and have no programmatic token count, so the
numbers are *not* a session total (the field's `scope`/`note` say so). Usage is
persisted in `AGENT_LOOP_META`, so resumed rounds aggregate the full
external-agent cost.
```json
"usage": { "scope": "external-agents-only", "note": "...host turns not counted...",
"totals": { "call_count": 2, "total_tokens": 250, ... },
"per_agent": { "codex": {...}, "gemini": {...} } }
```
- **Reviewer resilience** (plan-loop and PR-loop): if an external reviewer's CLI
fails to produce a usable review (an agent/tooling failure — e.g. an empty or
malformed-tool-call response — *not* a fixable malformed review), the skill does
**not** abort the round. It marks that reviewer **unavailable**, continues with
the remaining reviewers, and lists it under `unavailable_reviewers`; the reviewer
is re-attempted on the next run (or drop it from `--reviewers` to proceed). A
round with an unavailable reviewer is never reported `approved`: its `state` is
`incomplete` (or `blocking`/`pending` if those apply first). A genuinely
malformed-but-content-bearing structured output is first recovered automatically
when possible. The skill applies its safe reviewer normalizers, envelope cleanup,
known-ledger unknown-disposition stripping, plan-revision human-requirements
acknowledgement reconstruction, and finally a Gemini format-repair pass. Only
genuinely unrecoverable output falls back to `retry-validate`.
- **Round states.** `approved` (all configured reviewers signed off) · `blocking`
(a reviewer reported must-fix items) · `pending` (a host `claude` review handoff
is outstanding — complete it with `complete-host-review`) · `incomplete` (a
configured reviewer was unavailable; rerun). Precedence when several apply:
`pending` > `blocking` > `incomplete` > `approved`.
- **Merge is always a human decision.** The skill never runs CI-wait or
auto-merge; every mode stops at "ready to merge."
- **Merge conflicts route to the coder, not CI-wait.** The `coding_review_agent_loop`
CLI orchestrator checks GitHub's own mergeability (`mergeStateStatus`/`mergeable`)
before each review round and again before CI checks/auto-merge; a confirmed
`dirty`/`CONFLICTING` state skips reviewers and any CI wait or merge attempt
and routes the PR to the assigned coder to sync, resolve, and push instead
(see [Merge conflicts](docs/local_agent_loop.md#merge-conflicts)). In
skill-mode, if you find `gh pr view` reporting `mergeable: false` /
`mergeStateStatus: DIRTY`, treat that the same way: resolve the conflict as
the host coder before continuing review, rather than waiting on CI for the
current head.
- **No unbounded CI waits.** Never run `gh run watch`, `gh pr checks --watch`,
or any other unbounded wait on a GitHub Actions check or workflow run —
including when fixing a reviewer-reported check failure as the host coder.
If you need to confirm CI status, take at most 3 status snapshots (`gh run
view <run-id> --json status,conclusion,startedAt` or `gh pr checks`), spaced
at least 30 seconds apart, for at most 120 seconds of total CI observation.
If a run is still `queued` past that bound, or was cancelled before any job
started (a GitHub-hosted-runner capacity outage), stop observing it and
report the round's result immediately, naming the affected check/run and
noting that work should resume once GitHub Actions runners recover — do not
treat this as a code defect. This does not apply to a check that is
actively running or that fails due to a real repository test failure; those
remain real work to fix. The `coding_review_agent_loop` CLI orchestrator
applies the equivalent bound and stall classification automatically (see
[External CI infrastructure stalls](docs/local_agent_loop.md#external-ci-infrastructure-stalls));
this bullet covers the skill-mode host-coder path, which drives its own
shell commands directly.
- **Focused, bounded local tests.** Select tests proportionate to the files
actually changed and the reviewer item being addressed; prefer the
repository's verified focused test command over a broad suite when one
covers the change, and give a one-line rationale tying each selected test
module to a changed file or reviewer item. Do not run the whole `tests/`
suite, an `--ignore` list that amounts to the whole suite, or broad
server/database/integration/end-to-end suites unless the change actually
touches those surfaces, focused tests demonstrably do not cover it, or a
human or the issue explicitly asked for full-suite verification. Run
required completion tests in the foreground with visible output under an
explicit bounded timeout no greater than the configured finite run-level
ceiling (1,800 seconds by default). That maximum allowance requires an
individually justified command; it is not a reason to choose a broad suite. Never launch pytest (or any required test)
in the background, and never spawn a shell loop that polls a process ID,
`ps`/`kill -0`/`wait`, or a task-output file to learn whether it finished. If
a required test exceeds its bound, terminate it and report the blocker
immediately, naming the exact command and the timeout, rather than waiting
silently or retrying with a broader selection. The `coding_review_agent_loop`
CLI orchestrator's coder prompts carry the same policy; this bullet covers
the skill-mode host-coder path, which drives its own shell commands and
chooses its own test scope directly.
---
## Resuming
Every phase is re-runnable; if a session ends mid-arc, just re-invoke:
- **Plan-loop / PR-loop**: re-run the same round command. `build-resume` reads the
GitHub comment history and skips reviewer turns already completed this round.
- **Task mode**: re-running with the same task text reuses the same scratch issue
(tracked in a local task index), then resumes its plan-loop.
- **Implement step**: before implementing, check whether a PR already exists for
the issue and resume it instead of opening a duplicate.
---
## Reversed roles (external coder, #307)
`run-plan-round` and `run-task-round` can run with an **external coder** (Codex,
Gemini, or Antigravity writes the plan) instead of the host. Pass
`--coder codex|gemini|antigravity` (or `agy`) and **omit** `--plan-file` — the
skill generates the plan via `run_external --role coder`, validates it, attaches
the coder role and agent metadata, and posts it, then runs the configured
reviewers:
```bash
python -m helpers.skill_runner run-plan-round \
--issue N --repo OWNER/REPO \
--coder codex \
--reviewers gemini
```
The skill drives the rounds from the posted ledger (no `--plan-file` to
discriminate them): you just re-run the command until it returns
`{"state": "approved"}`. Each invocation:
- **no coder record yet** → runs the coder for round 1 (`plan_state`);
- **plan posted, reviewers pending** → runs the remaining reviewers;
- **round complete, blocking/same-plan** → runs the coder for round N+1, which
emits a structured `plan_revision` (rendered to a public comment; the canonical
plan is carried forward for reviewers);
- **round complete, all approved** → returns `approved`.
Structured reviewer responses, round-N `plan_revision` responses, and
`run-pr-fix` `coder_followup` responses use the same automatic recovery order:
safe deterministic normalization, envelope normalization, known-ledger
disposition cleanup, context-specific acknowledgement reconstruction, then a
Gemini format-repair pass. Pass `--gemini-cmd PATH` to the round/fix command to
select the Gemini executable used both for Gemini agent turns and repair. The
skill runner requests the recovery evidence sidecar from `run_external` with
`--response-evidence-output PATH`, alongside the existing `--usage-output PATH`
sidecar. The agent's original output is saved before recovery. If every recovery
stage fails, fix the preserved repair-dir `raw.md` with
`retry-validate --repair-dir <dir>` (or inspect the PR-fix debug directory), then
re-run the parent command.
### Host-as-reviewer (Claude reviews the plan or PR)
Put `claude` in `--reviewers` to have **you (the host) review** — for both
`run-plan-round` (review the posted plan) and `run-pr-round` (review the PR diff):
```bash
python -m helpers.skill_runner run-plan-round \
--issue N --repo OWNER/REPO --coder codex --reviewers claude gemini
python -m helpers.skill_runner run-pr-round \
--pr N --repo OWNER/REPO --reviewers claude codex
```
External reviewers always run first. The host can only review *after* reading the
posted plan/PR, so a configured `claude` reviewer becomes a **pending handoff**:
the round returns `{"state": "pending", "pending_reviewers": ["Claude"], ...}`
(never `approved`/`blocking` while it's outstanding) and prints a review-request
dir. Read the material there (`{dir}/plan.md` for a plan, `{dir}/pr-diff.diff` for
a PR). For a PR handoff, also read `{dir}/approved-plan.md`, the
`{dir}/approved-plan-reconciliation.md` guidance artifact, and the labeled issue
artifacts when present. If `{dir}/signed-human-requirements.md` exists, it is the
rendered signed-requirement contract: verify every stable ID and follow its
approval-marker instructions. Then write your `plan_review`/`pr_review` JSON to
`{dir}/host-review.md` and run:
```bash
python -m helpers.skill_runner complete-host-review --dir <dir>
```
That validates, renders, attaches `--agent Claude --role reviewer`, and posts your
review. Re-run the same round command to recompute the round (it advances to
`approved`, or — for a plan — revises via the coder when there are blocking /
same-plan findings).
When an approved-plan reconciliation artifact is present, classify every review
concern as one of three things: implementation noncompliance or an ordinary
defect to fix within the approved contract; an evidence-backed correctness,
security, compatibility, or test defect in an approved decision that may block
and proposes a plan correction; or a discretionary scope/policy request that
names the incompatible approved decision, evidence, and proposed change. Plan
conformance never defeats a real defect, signed human instruction, original
issue authority, or safety constraint. A direct PR or an unavailable/mismatched
plan handoff supplies no approved decision to invent. If canonical plan text is
omitted for provider budget, fetch and verify it through the source locator
before enforcing or challenging a decision; otherwise review ordinary defects
but do not enforce or dispute an unverified decision.
### Reverse implementation (external coder opens the PR)
`run-implement` has an **external coder** implement an approved plan and open a PR,
which you then review with `run-pr-round` (`claude` reviewer optional):
```bash
python -m helpers.skill_runner run-implement \
--issue N --repo OWNER/REPO \
--coder codex \
--plan-file <approved-plan.md> \
--workdir <push-capable-clone> [--base main]
# → prints {"pr": N, ...}; then:
python -m helpers.skill_runner run-pr-round --pr N --repo OWNER/REPO --reviewers claude gemini
# If that review blocks, let the same external coder push fixes:
python -m helpers.skill_runner run-pr-fix \
--pr N --repo OWNER/REPO --coder codex --reviewers claude gemini \
--workdir <push-capable-clone>
# Then re-review the new head:
python -m helpers.skill_runner run-pr-round --pr N --repo OWNER/REPO --reviewers claude gemini
```
This is **side-effecting**: the coder commits, pushes a branch, and opens a real
PR, so it needs a **push-capable** `--workdir`. The response is validated like the
CLI's implement path — a real PR marker, the signed-human-requirements
acknowledgement, in-workdir test reports, an advanced checkout HEAD, and that the
PR is open and references the issue — before a `role: coder` PR comment is posted.
It is **idempotent per plan** (the one-shot handoff marker): re-running returns the
existing PR instead of opening another one. For PR-review fixes, use
`run-pr-fix`; it is gated on a complete, current-head blocking `run-pr-round`
and posts a `role: coder` follow-up for the new PR head after validating that
the PR head and assigned checkout HEAD advanced.
A response that fails validation is non-retryable — fix the cause and re-run.
`--dry-run` does no pushes/PRs.
### Decompose an approved plan into phase issues
`run-decompose` has an **external coder** turn an untyped approved plan into
structured phase child issues. When the plan contains typed `child_stages`, the
helper adapts those stages directly and does not invoke the coder a second
time:
```bash
python -m helpers.skill_runner run-decompose \
--issue N --repo OWNER/REPO \
--coder codex \
--plan-file <approved-plan.md> \
[--workdir <checkout>]
```
Live runs are **side-effecting**: they create real GitHub child issues and post a
parent summary marker. The command is idempotent by parent issue + approved-plan
hash + mode; re-running the same plan returns the recorded child issues instead
of creating duplicates. Both phase commands accept `--flat-child-limit` (15 by
default), preflight every title/body before a checkpoint or create, never
truncate, and recover from checkpoints plus exact child identities. An
over-limit result exits 2 with structured guidance to consolidate or use the
hierarchical design tracked in #720. `--dry-run` parses, searches, adopts, and
validates the full preview without posting state or creating issues.
---
## Billing and terms note
This skill runs Claude turns inside your active interactive Claude Code session.
Whether that counts as interactive or programmatic usage depends on Anthropic's
current terms and product behavior at the time you run it.
Do not use this skill to proxy one user's session to other users, to build
unattended 24/7 automation, or in any way that violates Anthropic's usage policies.
---
## Session state location
Session state is stored in:
```
~/.local/state/coding-review-agent-loop/skill-sessions/{owner-repo}/{issue}.json
```
This location is outside git checkouts, so it never dirties any working tree.
---
## Limitations
- If Claude Code's session ends mid-loop, resume by running `skill_runner` again
with the same plan file — it reads GitHub comment history automatically via
`build-resume` and skips already-completed reviewer turns.
- Long-running Codex/Gemini subprocess progress is not streamed; check the log
file in `/tmp/coding-review-agent-loop/skill-logs/` if a reviewer hangs.
- The structured protocol uses `AGENT_LOOP_META` markers with a `v1_` zlib-
compressed URL-safe base64 payload (while accepting legacy plain-base64
markers). Oversized metadata is carried in `AGENT_LOOP_SIDECAR` comments that
precede the anchor. Keep those sidecars: if resume reports one missing or
corrupt, restore it or remove the incomplete anchor and rerun. Structured JSON
responses must match the versions expected by the existing library in `src/`.
---
## Runtime-aware local test timeouts
Local testing has three separate limits: framework per-test timeout, the
whole-command watchdog, and the backend whole-turn timeout. The run-level
watchdog ceiling defaults to 1,800 seconds and can be overridden with
`--coder-test-command-timeout-seconds SECONDS`; it remains finite. Skill gates
use the ceiling in the foreground. The optional `agent-loop run-tests
[--timeout-seconds N] -- COMMAND...` wrapper measures the complete command,
inherits `AGENT_LOOP_CODER_TEST_TIMEOUT_CEILING_SECONDS` from agent-loop, and
falls back to 1,800 seconds standalone. An explicit positive finite watchdog
may be smaller but never larger than the ceiling; malformed or over-policy
requests fail before spawning. Use learned recommendations when rendered and
omit the option for unknown commands. The backend whole-turn limit must exceed
the selected command watchdog with headroom; for Antigravity, use at least
`max(300s, 20%)` beyond it. Split or shard healthy browser/integration matrices
when that reduces diagnosis and retry cost.
## Demo
Run a minimal dry-run demo (no live GitHub or agent calls):
```bash
python -m helpers.demo_loop --issue 123 --repo demo/repo
```
Expected output includes:
```
validation passed: plan_state
validation passed: plan_review
demo_loop: all steps completed successfully
```