diff --git a/.claude/scripts/seed-issues.sh b/.claude/scripts/seed-issues.sh index 04eb4c3..d13d103 100755 --- a/.claude/scripts/seed-issues.sh +++ b/.claude/scripts/seed-issues.sh @@ -8,6 +8,19 @@ # Idempotent: existing labels are reused; an issue whose exact title already # exists is skipped, so re-running won't create duplicates. # +# NOTE — this is the anti-drift mechanism for module:* labels: the label block +# below derives label names straight from gates.json.modules[], so the labels +# the /pr-loop ADVANCE step looks for can never drift out of sync with the +# module map (see docs/USAGE.md → "Autonomous loop & the issue queue"). +# +# NOTE — this script uses bare `gh` and runs as the OWNER (fine for a one-time, +# interactive backlog seed you run yourself). Per this project's `gh` rule, +# anything the AGENTS/loop do must go through the bot instead. If you want to +# (re)bootstrap just the module:* labels as the bot — e.g. to hand that step to +# an agent — use bot-gh.sh directly: +# node -e "require('./.claude/gates.json').modules.forEach(m=>console.log(m.name))" | \ +# while read -r m; do bash .claude/scripts/bot-gh.sh label create "module:$m" --force; done +# # Prereq: `gh auth login` completed for this repo, and `node` on PATH. # Usage: bash .claude/scripts/seed-issues.sh set -uo pipefail diff --git a/README.md b/README.md index d5bf9bb..9d34f3f 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,8 @@ config edit, not a rebuild. 1. Click **“Use this template”** on GitHub → create your repo. 2. Open it in Claude Code and follow **[`docs/GETTING_STARTED.md`](docs/GETTING_STARTED.md)** (fill `CLAUDE.md` and `.claude/gates.json` — there are copy-paste prompts in [`docs/PROMPTS.md`](docs/PROMPTS.md) that draft - them for you). + them for you), then work through the **[new-project configuration + checklist](docs/GETTING_STARTED.md#new-project-configuration-checklist)** to wire it into the autonomous loop. 3. Drive it: see **[`docs/USAGE.md`](docs/USAGE.md)**. ## What's in here diff --git a/docs/GETTING_STARTED.md b/docs/GETTING_STARTED.md index 554c79d..b3f10d4 100644 --- a/docs/GETTING_STARTED.md +++ b/docs/GETTING_STARTED.md @@ -129,6 +129,29 @@ adapter-driven — you configure `gates.json`, not the YAML. > still run and are visible on every PR, and `merge-ready.sh` only merges a PR once the owner has approved > it *and* CI is green — so the approval+green gate holds even though GitHub doesn't hard-block the button. +## New-project configuration checklist +A copy-pasteable checklist for wiring a new project into the autonomous loop. See +[`USAGE.md` → "Autonomous loop & the issue queue"](USAGE.md#autonomous-loop--the-issue-queue) for the mental +model (the `module:*` opt-in queue + the owner-approval merge gate) that this checklist wires up. + +1. **`.claude/gates.json`** — the only per-project file that must be filled: `project.{name,language,packageManager}`; + `modules[]` (one entry per independently-ownable area, each with a non-overlapping `path` — these become + both the worker boundaries and the `module:` labels the loop understands; include non-code areas + like `docs` if you want them automatable); `gates.*` (real shell commands, `""` = skip); `coverage_threshold`; + `review.{lenses,consensus}`; `budget.*` (model routing, `max_parallel_workers`); `merge.{policy,baseBranch}`. +2. **`CLAUDE.md`** — project context, conventions, definition of done, merge policy. +3. **Bot machine account** — create it, add as a write collaborator, put `GH_BOT_TOKEN` in `.env` (gitignored). + All agent/loop `gh` calls run as the bot via `bot-gh.sh`; only `git` commits/pushes stay on the owner's + auth, so the owner can approve bot PRs. Setup notes live at the top of `.claude/scripts/bot-gh.sh`. +4. **Create the `module:*` labels** matching your `modules[]` names — see the bootstrap note at the top of + `.claude/scripts/seed-issues.sh`. Without the label, ADVANCE can never queue the issue. +5. **Server-side gates** — confirm `.github/workflows/gates.yml` runs your gate commands (Step 7 above), and + set branch protection / required status checks on `merge.baseBranch` if your plan supports it. +6. **Arm the loop** — run **`/pr-loop`**. It self-adjusts cadence (FAST when there's ≥1 open PR or ≥1 open + `module:*` issue, else IDLE) but the cron is session-scoped, so re-run it at the start of each session. +7. *(optional)* **Hardening** — `/harden` for the bypass + strict-sandbox profile, see + [`HARDENING.md`](HARDENING.md). + ## Verification checklist - [ ] `CLAUDE.md` describes the project and lists modules. - [ ] `.claude/gates.json` has real commands; `gate.sh build|lint|test` behave correctly. diff --git a/docs/PROMPTS.md b/docs/PROMPTS.md index 496631f..e09e8c7 100644 --- a/docs/PROMPTS.md +++ b/docs/PROMPTS.md @@ -5,6 +5,12 @@ Copy-paste these into Claude Code. The first two populate the files you must fil > **Shortcut:** the **`/setup-orchestrator`** command runs an interactive interview that covers prompts 1–2 > (draft `CLAUDE.md`, fill `gates.json`) *and* the rest of onboarding (labels, bot check, CI, arming the loop, > hardening). Use it for a fresh project; reach for the individual prompts below when you want to redo one piece. +> +> **Brand-new project?** Read the **[new-project configuration +> checklist](GETTING_STARTED.md#new-project-configuration-checklist)** and **[USAGE.md → "Autonomous loop & +> the issue queue"](USAGE.md#autonomous-loop--the-issue-queue)** first — they explain what `/setup-orchestrator` +> (and prompts 1–2 below) are actually wiring up, and the one convention that trips people up: only issues +> labelled `module:*` are ever picked up automatically. --- diff --git a/docs/USAGE.md b/docs/USAGE.md index 450c439..9b32ccf 100644 --- a/docs/USAGE.md +++ b/docs/USAGE.md @@ -119,6 +119,30 @@ run unattended (Claude Code `bypassPermissions`), first harden the environment s by always-enforced guardrails — see **[`HARDENING.md`](HARDENING.md)** (deny list + OS sandbox + host isolation). Don't enable bypass without it. +## Autonomous loop & the issue queue +Each `/pr-loop` tick runs, in order: **poll → merge → address-feedback → advance** — this per-tick order, +canonically defined in `.claude/commands/pr-loop.md`, is authoritative; the poll / address-feedback / +merge scripts described above are the mechanism it runs. Two human control points +decide what the loop actually touches: + +- **The `module:*` label is an explicit opt-in work queue.** The ADVANCE step only picks up **open issues + labelled `module:`** — lowest-numbered first, one at a time, and only when there are zero open PRs. + An unlabelled issue is never touched, no matter what its title or body say. Two reasons: + - **Intent gate** — most issues are discussions, questions, or half-scoped bugs; a bot shouldn't + auto-implement them. The label is you saying "this is scoped and ready for an autonomous worker." + - **Mechanism** — the label maps issue → module → the worker's `path` boundary (`gates.json.modules[]`). + No module ⇒ no boundary ⇒ nothing safe to hand a worker. +- **Owner-approval merge gate.** Workers author PRs as the **bot** (`bot-gh.sh`); the MERGE step (above) + only merges PRs the repo **owner** has Approved on GitHub that are CI-green and mergeable. It never + approves on the owner's behalf. + +**Corollary:** non-module (docs/infra) work is not loop-eligible until (a) its area exists as a module in +`gates.json.modules[]`, and (b) the issue carries the matching `module:*` label. Commenting "approved" on an +issue does nothing — nothing watches issue text. + +New project? Wire this up with the **[new-project configuration +checklist](GETTING_STARTED.md#new-project-configuration-checklist)**. + ## Merge discipline - **`pr-per-agent`** (default): each worker → branch → PR. You (or a merge step) integrate; conflicts surface at PR time. Cleanest/auditable.