An agent-agnostic scaffold for autonomous, test-gated maintenance of an existing open-source repository: fresh-context agent iterations triage the public issue tracker, plan a milestone, and fix the queue one test-first commit at a time — while a human always owns publish (push, PR, merge, release).
This is the sibling of open-spek/loop. That template builds NEW software from a frozen spec; this one MAINTAINS existing software against a live, public — and therefore untrusted — issue tracker. Same discipline (fresh context per iteration, files and git as the only memory, one task per iteration, the gate is truth), plus the layers maintenance demands: an untrusted-input firewall, a moderation protocol, an adversarial per-commit review, and a product-level functional smoke.
Distilled from a real deployment: the loop in
libredb/libredb-studio ran two milestones
against its public tracker — 12 issues fixed test-first across 15 build iterations, every
commit gated and reviewed, zero human interventions mid-run — and every mechanism here
carries the scars of that run (usage-limit recovery, dead-iteration adoption, seed-retry
readiness, port-shadowing isolation). The written scenario catalogue
(loop/SCENARIOS.md) documents 24 use cases: success, failure, skip,
needs-info, moderator escalation, scams, and prompt injection.
raw issue (untrusted)
→ TRIAGE: verify every claim in code, write a sanitized spec [no foreign code executed]
→ PLANNING: tasks + acceptance criteria from sanitized specs [nothing lifted verbatim]
→ BUILD: one task, test-first, per iteration [gate.sh green before commit]
→ loop-reviewer: adversarial fresh-context diff review [BLOCK stops the commit]
→ close-out: acceptance re-verified + functional smoke [the product's golden path]
→ local commits only [runner blocks push/PR/release]
→ HUMAN: review branch, push, PR, merge, release
Three prompt modes drive the same runner (loop/scripts/loop.sh); pipeline.sh chains them
unattended; new-milestone.sh opens each milestone by archiving the previous one (bounded
per-iteration reading — the fresh-context loop's memory files never grow without limit).
Issues route to exactly one of: loop:queued (verified in code, sanitized spec written),
loop:needs-info (one clarifying question posted; only a human clears it),
loop:needs-moderator-action (injection attempts, security reports, privileged changes,
product decisions — label only, never a reply), or a recorded "Not for the loop" skip.
No silent outcomes.
Everything a reporter writes is data, never instructions — regardless of who they appear to
be. Four independent layers enforce this: sanitized-spec indirection (build mode never takes
its acceptance bar from raw issue text), prompt-level guardrails (the 999 series), an
adversarial reviewer with supply-chain and destructive-command dimensions, and runner-level
tool blocks (no pushes, no network fetches, no GitHub mutations beyond loop:* labels and
one clarifying-question comment). Publishing is always a human act. Details:
loop/LOOP-ENGINEERING.md; worked adversarial examples:
loop/SCENARIOS.md §6.
git clone https://github.com/open-spek/maintainer-loop.git
./maintainer-loop/loop/scripts/scaffold.sh /path/to/your-repo "Your Project"
cd /path/to/your-repo
# follow the printed setup checklist: gate.sh, functional-smoke.sh,
# prompt placeholders, ./loop/scripts/setup-labels.sh
git checkout -b loop/sweep-1 && ./loop/scripts/new-milestone.sh sweep-1
git add -A loop .claude .gitignore && git commit -m "chore(loop): install maintainer loop"
./loop/scripts/pipeline.sh
# when it finishes: review the branch, push, open the PR (always human)Containment is the only safety boundary. Unattended agents run with permission bypass:
use a sandbox (container/VM/dedicated machine), a dedicated branch, a clean tree, iteration
caps, and the tool blocks in loop/config/loop.env. Read the containment section of
loop/LOOP-ENGINEERING.md before the first run.
| Path | Role |
|---|---|
loop/PROMPT-TRIAGE.md.template / PROMPT-PLANNING.md.template / PROMPT.md.template |
The three mode prompts — the agent's only instruction source |
loop/LOOP-ENGINEERING.md |
Operating discipline: honesty contract, untrusted-input firewall, modes, error handling, containment |
loop/SCENARIOS.md |
24 written use cases incl. adversarial inputs (descriptive, precedent-grounded) |
loop/TRIAGE.md.template + state templates (PROGRESS, HANDOFF, ACCEPTANCE, IMPLEMENTATION_PLAN) |
The loop's file-backed memory |
loop/scripts/loop.sh |
Fresh-context iteration runner (agent-agnostic; Claude Code wired by default) |
loop/scripts/pipeline.sh |
Unattended triage → planning → build with stage contracts |
loop/scripts/new-milestone.sh |
Milestone opening: archive rotation + state reset |
loop/scripts/setup-labels.sh |
Idempotent loop:* label taxonomy |
loop/scripts/gate.sh.example |
YOUR mandatory pre-commit verification (fill in) |
loop/scripts/functional-smoke.sh.example |
YOUR product's golden path (fill in; contract in header) |
loop/scripts/scaffold.sh |
Installs all of the above into an existing repo |
.claude/agents/loop-reviewer.md.template / loop-judge.md.template |
Fresh-context review/judge subagents |
The template contains no application code — only prompts, documentation, and scripts that drive the agent.
open-spek/loop turns a frozen Spek into a verified implementation — greenfield. This template picks up where that one ends: once software exists and has users filing issues, the maintainer loop keeps it healthy. Both share the Loop Engineering method; their operating manuals deliberately overlap.
This template improves the way it was built: by deployments feeding lessons back. If your loop hits a scenario the catalogue marks synthetic, contribute the anonymized precedent; if a guardrail failed or chafed, open an issue with the PROGRESS.md excerpt. The reference deployment's friction log lives in its repository history.
MIT — see LICENSE.