Files
rodin 30fe48d265
CI / test (push) Successful in 18s
CI / review (anthropic--claude-4.6-sonnet, sonnet, SONNET_REVIEW_TOKEN) (push) Has been skipped
CI / review (gpt-5, gpt, GPT_REVIEW_TOKEN) (push) Has been skipped
CI / review (gpt-5, security, ., rodin/security-patterns, SECURITY_REVIEW.md, SECURITY_REVIEW_TOKEN) (push) Has been skipped
docs(#148): add SKILL.md and dev-loop-spec.md for dispatch redesign (#149)
2026-05-15 08:12:02 +00:00

130 lines
5.2 KiB
Markdown

# Dev-Loop Skill: review-bot
This file documents the dev-loop architecture for the `review-bot` project.
It lives in the repo so changes are version-controlled alongside the code.
## Architecture
Dispatch is a **pure shell script** — no model reasoning.
```
Cron (agentTurn, toolsAllow: [exec, sessions_spawn, read])
→ runs dispatch script
→ reads output for SPAWN or HANDOFF lines
→ spawns worker if instructed
Dispatch script (~/.openclaw/workspace/scripts/dev-loop-dispatch.sh)
→ pure bash, all decisions are curl API calls + branches
→ exits after emitting one SPAWN line (at most one worker per run)
→ emits HANDOFF for each qualifying PR (does not exit after HANDOFF)
Workers (Opus, spawned by cron model)
→ receive precise task description
→ do one job: self-review, fix CI, address feedback, or implement
→ remove wip label when done, reply NO_REPLY
```
The cron model's **only** job: run script, read output, spawn worker if told to.
The model **never** assesses project state or makes dispatch decisions.
## Safety Invariants
1. **NEVER MERGE** — no merge API call exists anywhere in the script or worker templates
2. **REQUEST_CHANGES always blocks** — checked first, before CI, before self-review, before handoff
3. **WIP mutex** — one active worker per repo; WIP label gates new issue pickup
4. **One SPAWN per run** — script emits at most one SPAWN line per execution
5. **set -euo pipefail** — any curl failure aborts immediately, no partial actions
6. **Workers reply NO_REPLY** — no dispatch-level side effects (workers may push changes and manage labels as part of their task)
## Dispatch Rules (in order)
| Rule | Condition | Action |
|------|-----------|--------|
| 0 | WIP label > 1hr old | Remove stale WIP, continue |
| 0b | WIP label ≤ 1hr old | Mark ACTIVE_WIP=1, continue (only gates Rule 10) |
| _(1)_ | _(reserved — intentionally unused)_ | — |
| 2 | Any reviewer has REQUEST_CHANGES | SPAWN:findings |
| 3 | PR not mergeable | SPAWN:rebase |
| 4 | CI failure, no fix plan | SPAWN:ci-fix |
| 4b | CI failure, fix plan exists | Skip (worker in progress) |
| 5 | Bot review missing | Wait |
| 6 | CI pending/unknown | Wait |
| 7 | No clean self-review, no fix plan | SPAWN:self-review |
| 7b | Self-review needs attention, no fix plan | SPAWN:sr-fix |
| 8 | Unacknowledged bot review findings | SPAWN:address-feedback |
| 9 | Unresolved inline diff comments | SPAWN:address-feedback |
| 10 | All checks pass | HANDOFF |
| 11 | No open PRs + no ACTIVE_WIP | SPAWN:impl (next issue) |
## Files
| File | Description |
|------|-------------|
| `~/.openclaw/workspace/scripts/dev-loop-dispatch.sh` | Dispatch script — pure bash |
| `~/.openclaw/workspace/scripts/worker-tasks/self-review.md` | Self-review worker template |
| `~/.openclaw/workspace/scripts/worker-tasks/sr-fix.md` | Fix findings from self-review |
| `~/.openclaw/workspace/scripts/worker-tasks/ci-fix.md` | CI fix worker template |
| `~/.openclaw/workspace/scripts/worker-tasks/address-feedback.md` | Address feedback worker template |
| `~/.openclaw/workspace/scripts/worker-tasks/findings.md` | Address REQUEST_CHANGES findings |
| `~/.openclaw/workspace/scripts/worker-tasks/rebase.md` | Rebase worker template |
| `~/.openclaw/workspace/scripts/worker-tasks/impl.md` | Issue implementation worker template |
| `~/.openclaw/workspace/scripts/test/dispatch.bats` | Unit tests (bats) |
| `~/.openclaw/workspace/scripts/test/check-invariants.sh` | Static invariant checks |
| `~/.openclaw/workspace/memory/projects/review-bot.yaml` | Project config |
## Project Config
Config is at `~/.openclaw/workspace/memory/projects/review-bot.yaml`.
Key fields:
- `repo`: `rodin/review-bot`
- `api_base`: `https://gitea.weiker.me/api/v1`
- `user`: `rodin` (bot Gitea username)
- `labels.wip`: WIP label ID
- `labels.ready`: ready label ID
- `review_bots`: list of bot sentinel names
## Cron Config
```yaml
- label: review-bot-dev-loop
schedule: "*/15 * * * *"
prompt: |
Run: bash ~/.openclaw/workspace/scripts/dev-loop-dispatch.sh review-bot
Read the output. If it contains a SPAWN line, load the matching template from
~/.openclaw/workspace/scripts/worker-tasks/<type>.md, substitute {{PROJECT}},
{{PR_NUM}}, and {{HEAD_SHA}}, then spawn with sessions_spawn(mode: "run",
model: "hai-anthropic/anthropic--claude-4.6-opus", thinking: "high").
If no SPAWN line in output, reply NO_REPLY.
See ~/.openclaw/workspace/skills/dev-loop/SKILL.md for full instructions.
(This repo's SKILL.md is deployed to that workspace path.)
model: hai-anthropic/anthropic--claude-4.5-haiku
toolsAllow: [exec, sessions_spawn, read]
```
## Tests
```bash
# Unit tests (no real API calls):
bats ~/.openclaw/workspace/scripts/test/dispatch.bats
# Invariant checks (static analysis):
bash ~/.openclaw/workspace/scripts/test/check-invariants.sh
# Dry-run against real API:
DRY_RUN=1 bash ~/.openclaw/workspace/scripts/dev-loop-dispatch.sh review-bot
```
## Related Issues
- **#144** — autonomous merge: eliminated by removing all merge API calls from dispatch
- **#145** — merged despite REQUEST_CHANGES: eliminated by checking REQUEST_CHANGES first, unconditionally
- **#148** — this redesign
## Spec
Full design spec: `docs/dev-loop-spec.md`