Running more than one loop in a repo is normal. Running them without boundaries is how loops fight each other.
- One owner per branch — at most one loop may mutate a branch per hour.
- Separate state files —
STATE.mdfor triage; pattern-specific files for action loops. - Triage reports, action loops execute — Daily Triage at L1 never competes with CI Sweeper fixes.
- Shared denylist — copy the same path denylist into every LOOP.md.
- Aggregate token budget — see
templates/loop-budget.md.template.
STATE.md # Daily Triage (priorities, human inbox)
pr-babysitter-state.md # PR watcher
ci-sweeper-state.md # Active CI failures + attempt counts
dependency-sweeper-state.md # In-flight package updates
post-merge-state.md # Cleanup backlog
loop-run-log.md # Append-only observability
| Priority | Loop | Reason |
|---|---|---|
| 1 | CI Sweeper | Red main blocks everything |
| 2 | PR Babysitter | Active PRs are time-sensitive |
| 3 | Dependency Sweeper | Pause while CI red |
| 4 | Post-Merge Cleanup | Off-peak, lowest urgency |
| 5 | Daily Triage | Reports only at L1; schedules others |
Document in root LOOP.md:
## Multi-loop schedule
- CI Sweeper: /loop 15m (active hours)
- PR Babysitter: /loop 10m (active hours, skip if CI Sweeper acting on same PR)
- Daily Triage: /loop 1d 08:00
- Dependency Sweeper: /loop 6h (skip if main CI red)
- Post-Merge: /loop 1d 22:00Each action loop should write acting_on: branch-or-pr-id in its state file. Before spawning a fix:
- Read all other pattern state files
- If another loop
acting_onmatches → skip and log toloop-run-log.md
Use a shared section in STATE.md:
## Human Inbox (ambiguous / cross-loop)
- [ ] PR #42: CI Sweeper and PR Babysitter both flagged — human pick owner| Loop | Level | Cadence |
|---|---|---|
| Daily Triage | L1 | 1d |
| PR Babysitter | L2 | 10m |
| Post-Merge Cleanup | L1 → L2 | 1d off-peak |
Add CI Sweeper only after PR Babysitter attempt limits and verifier are proven for two weeks.
See stories/multi-loop-collision.md for a real collision story.