P9 · Fully automated review mode (adk auto) — progress note (2026-05-21)
Status: SHIPPED as MVP (locally). Core orchestrator + dry-run + report; safety guards deferred.
Commits
<latest> v4/P9: adk auto — headless review orchestrator (MVP)Test pass count
364 passed (+8 new in test_auto_run.py).
Exit-criteria check (plan §8 P9)
| Criterion | Evidence | Status |
|---|---|---|
adk auto --dry-run prints what it would do |
auto_run.main([..., "--dry-run"]) → JSON summary listing would_review URLs. |
✓ |
adk auto runs end-to-end with no input |
Implemented. Spawns <agent> -p "/adk-pr-review <url>" per eligible PR; captures logs; writes report.md. |
✓ |
| Exit-code 0/1/2 semantics | 0 = all succeeded, 1 = some failed, 2 = aborted by guard (today: invalid args). | ✓ |
What got done
skills/adk-cli/scripts/auto_run.py— orchestrator.bin/adk—autowired into dispatch table + USAGE block._eligible_rows(queue_path, exclude=...)— usesready_for_review(P5’s §6.u predicate) + FIFO sort._spawn_review(pr_url, agent, run_dir, log)— captures per-PR stdout to a log file; returns structured summary; handles missing-binary gracefully._write_report(run_dir, results, ...)— writesreport.mdwith per-PR bullets + run metadata.- 8 tests covering eligibility filtering + dry-run + max-reviews cap + report generation.
What got skipped (deferred to a follow-up)
--quiet-hours WW-XX— refuse to spawn during the window. Simple to add (parse args.quiet_hours, check current hour against the local clock, exit 2 if inside).--max-cost-usd N— pre-flight estimate × ready-PR-count. Needs per-agent cost table (could hard-code claude=$X in v1).--report-to-slack #channel— one summary post to that channel at the end. Reusesslack_helpers(P6 deferred Slack work). Once §6.y lands, the post fits naturally.- Per-agent registry / picker — today’s
--agentaccepts any binary name. The plan §8.5 talks about an agent registry (registry.launch(slash_cmd, args)) so the TUI + auto can swap agents (codex / cursor / opencode). Deferred to P8 (TUI) since that’s where the abstraction pays off. - launchd plist example in SETUP.md — a 10-line example to fire
adk autoevery 2h.
How to use
# Preview what would happen (no agent spawned):adk auto --dry-run# Run end-to-end (default: 1 agent at a time, up to 20 PRs, default agent claude):adk auto# Custom parallelism + cap:adk auto --parallel 4 --max-reviews 10# Exclude a specific PR:adk auto --exclude https://github.com/acme/foo/pull/123# Skip the pr-sync pre-flight (e.g. if it just ran):adk auto --no-sync# Use a different agent:adk auto --agent codexadk auto --agent cursorDecisions made this run
- Default
--parallel 1— serial execution by default. Parallelism is opt-in to give predictable runtime for cron schedules. - Default
--max-reviews 20— matches plan §7.4. Conservative cap so a runaway sync doesn’t burn budget. --dry-runis side-effect-free — even pr-sync is skipped under —dry-run.- Missing-binary handling —
_spawn_reviewcatches FileNotFoundError and emits a structured failure dict instead of crashing the run. Other PRs in the same run still get a chance. - Log location —
~/.agents-devkit/skill-setup/auto-runs/<ts>/per plan §7.3. Each PR gets its own.logfile; the run-level summary lands inreport.md.
Open questions for the user
- Worth ironing out
--quiet-hours+--max-cost-usd+--report-to-slackin a focused session — they’re the user-facing knobs that makeadk autoschedulable safely. - The agent-registry abstraction (so
--agent codexworks equally to--agent claude) needs a sketch — today both work via the same spawn pattern, but a clean registry pattern (per-agent argv builder + per-agent cost coefficient) would tighten the contract.
Exact commands to inspect
git show HEAD --statpython3 -m pytest skills/adk-cli/scripts/tests/test_auto_run.py -vadk auto --dry-run