Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .claude/agents/implementer.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ isolation: worktree

You own ONE sub-task end-to-end, on your own branch, in your own worktree.

## GitHub identity (hard rule)
Never call bare `gh`. EVERY `gh` invocation (PR create/update, comments, `gh api`, any query) MUST go through `.claude/scripts/bot-gh.sh` so it runs as the bot. Only `git` commits/pushes use the owner's auth. If `GH_BOT_TOKEN` is missing, stop and report it — do not fall back to owner `gh`.

## Read first
- `.claude/gates.json` — for the exact gate commands (`build`, `lint`, `typecheck`, `test_affected`, `coverage`) and your module boundary.
- `CLAUDE.md` — conventions, style, definition of done.
Expand Down
3 changes: 3 additions & 0 deletions .claude/agents/orchestrator.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ Before anything else, read these and treat them as ground truth:
- `CLAUDE.md` — project context and conventions.
If `.claude/gates.json` has empty `gates`, STOP and tell the user the project hasn't been adapted yet (point them at `docs/GETTING_STARTED.md`).

## GitHub identity (hard rule)
EVERY `gh` invocation — by you and by every agent you spawn — MUST go through the bot account via `.claude/scripts/bot-gh.sh`; never call bare `gh`. This covers reads and writes alike: issue creation, issue/PR comments, PR creation, PR merging, and all queries (`gh pr list`, `gh issue view`, `gh api`, …). Only `git` commits and pushes stay on the owner's auth, so the owner can formally review and approve (GitHub blocks a PR's author from approving it). If `GH_BOT_TOKEN` is missing, STOP and point the user at the setup notes in `.claude/scripts/bot-gh.sh` rather than falling back to owner `gh`. When you delegate, tell each worker this same rule.

## Your loop
1. **Scope.** Decompose the task into sub-tasks that are *independent* and *non-overlapping at the file level*. Use the `modules` map in `gates.json` to assign each sub-task to exactly one module/path. If two sub-tasks would touch the same files, either merge them into one sub-task or sequence them (declare the dependency). Scale effort to complexity: a trivial task gets ONE worker and no parallelism — do not fan out for its own sake.
2. **Present the plan and WAIT.** Output the plan: each sub-task's title, target module/path, owner boundary, dependencies, and which reviewers will gate it. Enter plan mode and wait for human approval before any code is written. This is the planning checkpoint.
Expand Down
3 changes: 3 additions & 0 deletions .claude/agents/reviewer.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ model: opus

You are an ADVERSARIAL reviewer. Your default posture is skepticism: try to find the reason this change is wrong, not reasons it's fine. A change you cannot refute is one you approve.

## GitHub identity (hard rule)
If you touch GitHub at all (e.g. `gh pr diff`, `gh pr view`, `gh api`), route it through `.claude/scripts/bot-gh.sh` — never bare `gh`. You remain read-only; this only changes the identity the query runs under.

## Read first
- `.claude/gates.json` — review lenses and any project review skills.
- `CLAUDE.md` — the project's definition of done and conventions.
Expand Down
3 changes: 3 additions & 0 deletions .claude/agents/test-runner.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ model: haiku

You run the project's gates and report results. You do not fix code — you report what's red so others can.

## GitHub identity (hard rule)
If any gate or check needs `gh` (e.g. fetching CI status via `gh api`/`gh run`), call it through `.claude/scripts/bot-gh.sh`, never bare `gh`, so it runs as the bot.

## What to run
Read `.claude/gates.json` and run the requested gates (or all configured ones) using `.claude/scripts/gate.sh <name>` when available, else the raw command from the file. Typical order: `install` (if needed) → `build` → `lint` → `typecheck` → `test` (or `test_affected`) → `coverage` → `e2e` → `security`.

Expand Down
103 changes: 103 additions & 0 deletions .claude/commands/setup-orchestrator.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
---
description: Interactive full onboarding — interview the user, then write .claude/gates.json + CLAUDE.md, fix gitignore, create module:* labels, verify the bot, confirm CI gates, and offer to arm the PR loop and hardening. Brings a fresh project to a working autonomous state.
---

You are running **first-time setup** for this orchestrator template in the user's project. Goal: take a fresh
clone from placeholder to a fully working autonomous state — the same configuration a mature project here has:
a filled adapter, module labels, a working bot identity, server-side gates, the PR loop armed, and (optionally)
hardened hands-off mode. You *interview* the user, then materialize the files and GitHub state the loop depends on.

`docs/GETTING_STARTED.md`, `docs/USAGE.md`, and `docs/HARDENING.md` are the sources of truth — read them first
and defer to them on any detail.

Be conversational but efficient. Use the `AskUserQuestion` tool for discrete choices; ask for free-text
(names, paths, shell commands) in plain prose. **Never invent values** — if you don't know a command or path,
ask. **Propose the final files and get an explicit "yes" before writing.** All `gh` runs through
`bash .claude/scripts/bot-gh.sh`, never bare `gh`.

Do these in order. Stop and report if a step genuinely can't proceed.

## 1. Preconditions & orientation
- Read `docs/GETTING_STARTED.md`, `docs/USAGE.md`, `docs/HARDENING.md`, the current `.claude/gates.json`, and `CLAUDE.md`.
- **Redundant-setup check (warn, then ask — don't hard-abort).** If `gates.json.gates` already has non-empty
commands, the project looks already configured. **Warn clearly**: show the current `project`/`modules`/`gates`,
and say that continuing will re-interview and, on your confirmation, overwrite the adapter files and reconcile
labels. Then **ask the user whether to continue or stop** (use `AskUserQuestion`). If they choose stop, end the
command cleanly with no changes. If they continue, proceed with the flow. (You still confirm before each file
write in later steps, so a re-run can't clobber silently.)
- Resolve the repo: `bash .claude/scripts/bot-gh.sh repo view --json nameWithOwner -q .nameWithOwner`.

## 2. Explain the model up front (so answers are informed)
Briefly tell the user how the loop decides what to build:
- The loop only builds issues **labelled `module:<name>`**, one at a time, when no PRs are open — an explicit opt-in queue.
- Each `module` maps to exactly one filesystem `path`, the **hard boundary** a worker may edit within. So the
module list you define here is both the isolation boundary and the set of labels the loop understands. Include
any non-code area you want automatable (e.g. `docs`, `.claude`, `examples`).
- Nothing merges until the **owner approves the bot's PR** on GitHub.

## 3. Interview
Collect, confirming back as you go:
1. **Project basics** — `project.name`, `language`, `packageManager`.
2. **Modules** (the important one) — for each ownable area: `name` (label-safe: lowercase/kebab), `path`
(repo-relative, **non-overlapping / non-nested** with siblings), one-line `description`, optional `owner`.
Push back on overlapping or nested paths — the isolation guarantee needs disjoint paths. Offer to include
`docs`/infra modules if relevant.
3. **Gates** — exact shell commands (run from repo root) for `install`, `build`, `lint`, `typecheck`, `test`,
`test_affected`, `coverage`, `e2e`, `security`. Empty = "skip" (fine, and the right default when a gate
doesn't exist yet). Warn that a gate pointed at a command that can't pass will block the Stop hook. Ask
`coverage_threshold` (default 80). If unsure on `test_affected`, default it to the full `test` command.
4. **Review** — `review.lenses` (default `["correctness","tests","security","performance"]`) and
`review.consensus` (`all`, or an integer).
5. **Budget/routing** — `orchestrator_model`/`worker_model`/`explorer_model`/`reviewer_model`
(defaults opus/sonnet/haiku/opus) and `max_parallel_workers` (default 3; advise 2–4).
6. **Merge** — `merge.policy` (`pr-per-agent` | `orchestrated-sequential-merge`) and `merge.baseBranch`
(default the repo's default branch).

## 4. Write the adapter (after confirmation)
- Produce the complete `.claude/gates.json`, show it, and on approval write it. It MUST be valid JSON —
validate with `node -e "require('./.claude/gates.json')"`; fix and re-validate if it throws.
- Fill `CLAUDE.md` from its template sections (What this project is / Stack & layout mirroring the module map /
Conventions / Merge policy mirroring `gates.json` / Don'ts). Keep it lean — project-WIDE context only.
- Do **not** touch `.claude/settings.json` or any generic agent/script — only the adapter.

## 5. Gitignore hygiene
Ensure these are gitignored (append if missing, don't duplicate): `.env` (holds `GH_BOT_TOKEN`),
`.claude/settings.local.json` (per-machine hardening/bypass — must never be inherited by a clone), and
`.claude/state/` (the notify-poll cursor). Verify with `git check-ignore <path>`.

## 6. Create the module labels
For every module `name`: `bash .claude/scripts/bot-gh.sh label create "module:<name>" --description "<desc>" --force`.
Report created vs already-existing. Remind: **an issue is only loop-eligible once it carries a `module:*` label.**

## 7. Verify the bot account
- Confirm `.env` has `GH_BOT_TOKEN` and the bot can see the repo:
`bash .claude/scripts/bot-gh.sh api user --jq .login` and a `repo view` on the resolved repo.
- If missing/no access, DON'T fail the whole setup — point at the one-time setup notes in
`.claude/scripts/bot-gh.sh` (create machine account → add as **write** collaborator → classic `repo`-scope
token → `.env`) and mark this step "action needed".

## 8. Server-side gates (CI)
- Confirm `.github/workflows/gates.yml` exists and its jobs match the gate commands just configured (see #8).
If the commands differ, tell the user which to reconcile. Note that **branch protection / required checks**
(making CI a hard merge gate) is an owner action in repo Settings — flag it as a manual step.

## 9. Arm the PR loop
- Explain `/pr-loop` (session-scoped cron; adaptive cadence). **Offer to run it now** (ask; don't auto-run).
If they decline, note they can run `/pr-loop` anytime — and must re-arm it each session.

## 10. Hardening (offer LAST — order matters)
- Explain `/harden`: it writes `bypassPermissions` + a strict OS sandbox into `.claude/settings.local.json` for
hands-off autonomous runs (`docs/HARDENING.md` is the source of truth). **Offer to run `/harden` now** (ask).
- Sequencing the user must know: hardening only takes effect after a **restart**, once hardened the agent can no
longer edit `.claude/settings*.json` (by design), and the restart drops the in-session PR-loop cron. So the
correct order is: finish setup → `/harden` → restart Claude Code → **re-run `/pr-loop`** in the hardened
session. Do not harden before the rest of setup is done.

## 11. Hand off
Summarize what changed (files written, gitignore entries, labels created, bot status, CI status, loop armed?,
hardened?). Restate the two control points in one line each: **label an issue `module:*` to queue it; approve
the bot's PR to ship it.** Finish with an ordered checklist of everything only the human can complete, e.g.:
- add `GH_BOT_TOKEN` to `.env` / add the bot as a write collaborator (if step 7 flagged it),
- set branch protection / required status checks (if wanted),
- OS-level isolation from `docs/HARDENING.md` Step 2 (sudo / VM / WSL interop) if hardening,
- restart, then re-run `/pr-loop`.
5 changes: 4 additions & 1 deletion .claude/scripts/bot-gh.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@
# reliably target repos owned by ANOTHER personal account.)
# 4. Put it in the project's .env (gitignored) as GH_BOT_TOKEN=...
#
# Only PR creation needs the bot; commits and pushes stay on the owner's auth.
# Policy: ALL agent `gh` interaction (issue/PR creation, comments, merging, and
# even reads/queries) goes through this wrapper so it runs as the bot. Only `git`
# commits and pushes stay on the owner's auth — that keeps the owner eligible to
# formally approve bot-authored PRs (GitHub blocks a PR author from approving it).
#
# Usage: .claude/scripts/bot-gh.sh pr create --title "..." --body "..."
set -euo pipefail
Expand Down
10 changes: 7 additions & 3 deletions .claude/scripts/merge-ready.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,20 @@
# - every CI check is green (none failing, none still pending)
# Anything else is SKIPPED with a reason. Output is JSON lines a cron summarizes.
#
# Auth: uses ambient `gh` auth (the owner's `gh auth login`), same as
# notify-poll.sh — merging is an owner action. Only PR *creation* uses the bot
# (bot-gh.sh). Repo is derived from the git remote; override with $1 (owner/repo).
# Auth: ALL `gh` calls (listing, viewing, and the merge itself) run as the bot via
# bot-gh.sh — the bot is a write collaborator, so it can merge. The merge GATE is
# still the human OWNER's APPROVED review (detected below); running the merge as the
# bot does not change who authorized it. Repo is derived from the git remote;
# override with $1 (owner/repo).
# The approver defaults to the repo owner; override with $MERGE_APPROVER.
# Pre-approve `bash .claude/scripts/merge-ready.sh` in .claude/settings.json.

set -euo pipefail
export PATH="$HOME/.local/bin:$PATH"

root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
# Route EVERY gh call (list/view/merge) through the bot identity (see bot-gh.sh).
gh() { bash "$root/.claude/scripts/bot-gh.sh" "$@"; }
repo="${1:-$(gh repo view --json nameWithOwner -q .nameWithOwner)}"
owner="${MERGE_APPROVER:-${repo%%/*}}" # the approver whose APPROVED review authorizes a merge
gates="$root/.claude/gates.json"
Expand Down
3 changes: 3 additions & 0 deletions .claude/scripts/notify-poll.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
set -euo pipefail

root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
# Route EVERY gh call through the bot identity (see bot-gh.sh). Defined before the
# first gh use below so the repo-derivation call already runs as the bot.
gh() { bash "$root/.claude/scripts/bot-gh.sh" "$@"; }
repo="${1:-$(gh repo view --json nameWithOwner -q .nameWithOwner)}"
owner="${MERGE_APPROVER:-${repo%%/*}}" # the human whose APPROVED review gates a merge
state_dir="$root/.claude/state" # add .claude/state/ to .gitignore
Expand Down
3 changes: 3 additions & 0 deletions .claude/scripts/pr-feedback.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
# Invoke as `bash .claude/scripts/pr-feedback.sh` (pre-approve that exact command).
set -euo pipefail

root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
# Route EVERY gh call through the bot identity (see bot-gh.sh).
gh() { bash "$root/.claude/scripts/bot-gh.sh" "$@"; }
repo="${1:-$(gh repo view --json nameWithOwner -q .nameWithOwner)}"
bot="${BOT_LOGIN:-robercano-ghbot}"
marker="<!-- claude-addressed -->"
Expand Down
Loading