From 1374aae06382b62025073a9f0bce1a06fec76ecd Mon Sep 17 00:00:00 2001 From: Roberto Cano <3525807+robercano@users.noreply.github.com> Date: Sun, 5 Jul 2026 12:52:08 +0200 Subject: [PATCH 1/3] feat(harness): add plugin marketplace.json + consumer enablement docs Adds .claude/.claude-plugin/marketplace.json listing the orchestrator plugin (mirrors plugin.json's name/version/description/author), and documents the extraKnownMarketplaces + enabledPlugins settings.json snippet a consuming project adds to install it. Notes the known limitation that Claude Code's GitHub marketplace source resolves marketplace.json at repo root, not a subdirectory, given this repo's plugin-root-is-.claude/ layout. Part of issue #39 (packaging phase 4). --- .claude/.claude-plugin/README.md | 40 +++++++++++++++++++++++++ .claude/.claude-plugin/marketplace.json | 19 ++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 .claude/.claude-plugin/marketplace.json diff --git a/.claude/.claude-plugin/README.md b/.claude/.claude-plugin/README.md index e4bcd78..208f780 100644 --- a/.claude/.claude-plugin/README.md +++ b/.claude/.claude-plugin/README.md @@ -29,3 +29,43 @@ Not distributed by this plugin (repo-scaffolded, project-specific): - `.claude/workflows/*.js` — deterministic fan-out workflows, not plugin-portable. - `.claude/self/*` — this repo's OWN self-hosting adapter (gates, checks), not for downstream projects; downstream adopters get the placeholder `.claude/gates.json` instead. + +## Enabling in a consuming project + +`marketplace.json` lives alongside `plugin.json`, at `.claude/.claude-plugin/marketplace.json` — +so its "marketplace root" is `.claude/`, the same directory the plugin itself is rooted at. It +lists a single plugin entry, `orchestrator`, with `"source": "./"` (relative to that marketplace +root, i.e. the plugin payload is the marketplace root itself). + +A consuming project registers this repo as a marketplace source and enables the plugin from it in +its own `.claude/settings.json`: + +```json +{ + "extraKnownMarketplaces": { + "ai-project-orchestrator": { + "source": { + "source": "github", + "repo": "robercano/ai-project-orchestrator" + } + } + }, + "enabledPlugins": { + "orchestrator@ai-project-orchestrator": true + } +} +``` + +`extraKnownMarketplaces` registers `robercano/ai-project-orchestrator` (a GitHub repo) as a +marketplace named `ai-project-orchestrator`; `enabledPlugins` then enables the `orchestrator` +plugin from it, addressed as `@`. + +**Known limitation:** Claude Code's documented `"source": "github"` marketplace source resolves +`marketplace.json` at the repo **root** (`.claude-plugin/marketplace.json`), with no documented +field to point it at a subdirectory. This repo's `marketplace.json` instead lives at +`.claude/.claude-plugin/marketplace.json`, matching the plugin-root-is-`.claude/` layout described +above. Until Claude Code supports a subdirectory marketplace source (or this repo additionally +publishes a repo-root alias), the snippet above is the intended shape but may require consumers to +add the marketplace from a local clone instead (e.g. `/plugin marketplace add +/.claude`) rather than the bare GitHub shorthand. Revisit this note if/when +subdirectory marketplace sources land upstream. diff --git a/.claude/.claude-plugin/marketplace.json b/.claude/.claude-plugin/marketplace.json new file mode 100644 index 0000000..8888dfc --- /dev/null +++ b/.claude/.claude-plugin/marketplace.json @@ -0,0 +1,19 @@ +{ + "name": "orchestrator", + "owner": { + "name": "Roberto Cano" + }, + "description": "Multi-agent orchestration harness: fan out sub-tasks to isolated worktree implementers, gate them, and route results through reviewers.", + "version": "0.1.0", + "plugins": [ + { + "name": "orchestrator", + "source": "./", + "description": "Multi-agent orchestration harness: fan out sub-tasks to isolated worktree implementers, gate them, and route results through reviewers.", + "version": "0.1.0", + "author": { + "name": "Roberto Cano" + } + } + ] +} From dac268d857caa991b1a783dad0e291f5e0b260e3 Mon Sep 17 00:00:00 2001 From: Roberto Cano <3525807+robercano@users.noreply.github.com> Date: Sun, 5 Jul 2026 12:56:21 +0200 Subject: [PATCH 2/3] fix(harness): align marketplace.json name with README enablement docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The marketplace top-level name must equal the marketplace part of `@` addressing. Rename it from `orchestrator` to `ai-project-orchestrator` (the repo/marketplace), keeping the plugin entry's own `name` as `orchestrator` (the plugin id) — this now agrees with the README's extraKnownMarketplaces key and enabledPlugins entry. Also add marketplace.json to the self build gate's JSON-parse loop so a malformed marketplace.json is caught by gates going forward. --- .claude/.claude-plugin/marketplace.json | 2 +- .claude/self/checks.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.claude/.claude-plugin/marketplace.json b/.claude/.claude-plugin/marketplace.json index 8888dfc..c2c7ca7 100644 --- a/.claude/.claude-plugin/marketplace.json +++ b/.claude/.claude-plugin/marketplace.json @@ -1,5 +1,5 @@ { - "name": "orchestrator", + "name": "ai-project-orchestrator", "owner": { "name": "Roberto Cano" }, diff --git a/.claude/self/checks.sh b/.claude/self/checks.sh index bb74a6e..62a6469 100644 --- a/.claude/self/checks.sh +++ b/.claude/self/checks.sh @@ -16,7 +16,7 @@ json_parse() { node -e "JSON.parse(require('fs').readFileSync(process.argv[1],'u do_build() { local rc=0 - for f in .claude/gates.json .claude/self/gates.json .claude/settings.json .claude/.claude-plugin/plugin.json .claude/hooks/hooks.json; do + for f in .claude/gates.json .claude/self/gates.json .claude/settings.json .claude/.claude-plugin/plugin.json .claude/.claude-plugin/marketplace.json .claude/hooks/hooks.json; do if [ ! -f "$f" ]; then echo "build: missing $f"; rc=1; continue; fi if ! json_parse "$f" 2>/dev/null; then echo "build: invalid JSON — $f"; rc=1; fi done From 92151016ee003700d6a00d7fe96cbe3f8dea03ff Mon Sep 17 00:00:00 2001 From: Roberto Cano <3525807+robercano@users.noreply.github.com> Date: Sun, 5 Jul 2026 13:07:33 +0200 Subject: [PATCH 3/3] docs: rewrite GETTING_STARTED/USAGE for the plugin flow, add MIGRATION guide Reframes onboarding around installing the `orchestrator` Claude Code plugin (marketplace + enable) and running /orchestrator:setup, instead of cloning this repo as a template. Leads with the working local-clone install method, presents the settings.json github-source snippet as the target flow, and documents the known marketplace.json-at-repo-root discovery gap. Renames command references to their namespaced /orchestrator:* form, adds an "Updating the plugin" section (marketplace update + /orchestrator:sync, clearly marked forthcoming per issue #38). Adds MIGRATION.md for existing hand-copied adopters: what to delete (harness now carried by the plugin), what to keep (adapter/CLAUDE.md/workflow/CI files), how to enable the plugin, and a verification checklist. Part of issue #39 (packaging phase 4). --- docs/GETTING_STARTED.md | 174 +++++++++++++++++++++++++--------------- docs/MIGRATION.md | 65 +++++++++++++++ docs/USAGE.md | 39 +++++++-- 3 files changed, 207 insertions(+), 71 deletions(-) create mode 100644 docs/MIGRATION.md diff --git a/docs/GETTING_STARTED.md b/docs/GETTING_STARTED.md index b3f10d4..52d5324 100644 --- a/docs/GETTING_STARTED.md +++ b/docs/GETTING_STARTED.md @@ -1,52 +1,96 @@ # Getting Started -From a fresh repo created off this template to a working orchestrator, in 6 steps. Budget ~20 minutes. +From an existing project to a working orchestrator, installed as a **Claude Code plugin**, in 6 steps. +Budget ~20 minutes. -> **Prefer to be guided?** Run **`/setup-orchestrator`** in Claude Code. It interviews you (project basics, -> module boundaries, gate commands, review/merge config), then does the steps below for you — writes -> `gates.json` + `CLAUDE.md`, fixes `.gitignore`, creates the `module:*` labels, verifies the bot, checks the -> CI gates, and offers to arm the PR loop and (last) `/harden`. This page is the manual reference behind that -> command — read it to understand what the command is doing, or to configure by hand. +> **Prefer to be guided?** Once the plugin is enabled (Step 1), run **`/orchestrator:setup`** in Claude Code. +> It interviews you (project basics, module boundaries, gate commands, review/merge config), then scaffolds +> the files a plugin can't carry into your repo — `.claude/gates.json` + `CLAUDE.md` + the fan-out workflow + +> the CI gate workflow — fixes `.gitignore`, creates the `module:*` labels, verifies the bot, checks the CI +> gates, and offers to arm the PR loop and (last) `/orchestrator:harden`. This page is the manual reference +> behind that command — read it to understand what it's doing, or to configure by hand. ## Prerequisites - Claude Code installed and authenticated (`claude` runs). - `node` and `git` on PATH (the gate script uses `node` to read `gates.json`). - Your project's actual build/test tooling installed (so the gate commands work). -## Step 1 — Create your repo -On GitHub, **Use this template → Create a new repository**. Clone it and open it in Claude Code. -(The template ships agents and config under `.claude/`; Claude Code picks them up automatically.) - -## Step 2 — Fill in `CLAUDE.md` -This is project-wide context every agent reads. Either edit it by hand, or paste the **"Draft CLAUDE.md"** -prompt from [`PROMPTS.md`](PROMPTS.md) into Claude Code and let it propose a draft from your codebase, then -trim. Keep it lean — project-wide only. - -## Step 3 — Fill in `.claude/gates.json` (the adapter — the important one) -This is the *only* file that makes the generic agents work on YOUR stack. Set: -- **`project`** — name, language, package manager. -- **`modules`** — the map of independent areas + their paths. This is what the orchestrator uses to give each - worker a non-overlapping boundary. Get this right and clashes mostly disappear. -- **`gates`** — the exact shell commands for `build`, `lint`, `typecheck`, `test`, `test_affected`, - `coverage`, `e2e`, `security`. Leave any you don't have as `""` (it's skipped, not failed). -- **`coverage_threshold`**, **`review.lenses`**, **`budget`** (model routing + `max_parallel_workers`), - **`merge.policy`**. - -Use the **"Fill gates.json"** prompt in [`PROMPTS.md`](PROMPTS.md) to have Claude infer most of this from your -`package.json` / `Makefile` / CI config, then verify each command runs. - -**Sanity-check the gates manually:** +## Step 1 — Install the `orchestrator` plugin +This template ships as a Claude Code plugin named `orchestrator` (plugin root `.claude/`), with a +`marketplace.json` alongside it. Two ways to add it — lead with the one that works today: + +**The reliable method today — a local clone.** Claude Code's `/plugin marketplace add` accepts a plain +filesystem path, and this repo's marketplace root is `.claude/`: +```bash +git clone https://github.com/robercano/ai-project-orchestrator.git ../ai-project-orchestrator +``` +Then, in Claude Code, inside **your own project**: +``` +/plugin marketplace add ../ai-project-orchestrator/.claude +/plugin install orchestrator@ai-project-orchestrator +``` +(`/plugin` alone opens an interactive picker if you'd rather browse marketplaces/plugins than type the +commands above.) + +**The target flow — a GitHub source (has a known gap today).** The eventual "no local clone" install is to +declare the marketplace straight from GitHub in your project's `.claude/settings.json`: +```json +{ + "extraKnownMarketplaces": { + "ai-project-orchestrator": { + "source": { "source": "github", "repo": "robercano/ai-project-orchestrator" } + } + }, + "enabledPlugins": { "orchestrator@ai-project-orchestrator": true } +} +``` +> **Known limitation.** Claude Code's `"source": "github"` marketplace source resolves `marketplace.json` at +> the repo **root** (`.claude-plugin/marketplace.json`). This repo's manifest instead lives at +> `.claude/.claude-plugin/marketplace.json`, because the plugin root is `.claude/`, not the repo root — so the +> bare GitHub shorthand above may not resolve for you yet. Use the local-clone method until this repo ships a +> dedicated, standalone marketplace repo at its root (a deferred follow-up — it can't be created from inside +> this repo). See `.claude/.claude-plugin/README.md` (once cloned) for the up-to-date detail on this gap. + +## Step 2 — Onboard: run `/orchestrator:setup` +With the plugin enabled, run: +``` +/orchestrator:setup +``` +It interviews you, then writes the files a plugin **cannot** carry into your repo — agents, commands, hooks, +and scripts ship *with* the plugin, so there's nothing to copy or wire by hand for those. What the interview +collects and scaffolds: + +- **`.claude/gates.json`** (the adapter — the *only* file that makes the generic agents work on YOUR stack). Set: + - **`project`** — name, language, package manager. + - **`modules`** — the map of independent areas + their paths. This is what the orchestrator uses to give each + worker a non-overlapping boundary. Get this right and clashes mostly disappear. + - **`gates`** — the exact shell commands for `build`, `lint`, `typecheck`, `test`, `test_affected`, + `coverage`, `e2e`, `security`. Leave any you don't have as `""` (it's skipped, not failed). + - **`coverage_threshold`**, **`review.lenses`**, **`budget`** (model routing + `max_parallel_workers`), + **`merge.policy`**. +- **`CLAUDE.md`** — project-wide context every agent reads (what the project is, stack & layout, conventions, + definition of done, merge policy). Kept lean by design. +- **`.claude/workflows/feature-fanout.js`** — the deterministic fan-out workflow (managed; re-stamped on + updates, see [`USAGE.md` → "Updating the plugin"](USAGE.md#updating-the-plugin)). +- **`.github/workflows/gates.yml`** + **`.github/actions/setup/action.yml`** — the CI gate workflow (Step 4 + below). +- **`module:*` GitHub labels**, a **bot-account check** (`GH_BOT_TOKEN`), and offers to arm **`/orchestrator:pr-loop`** + and, last, **`/orchestrator:harden`**. + +**Sanity-check the gates once it's written** (ask Claude Code to run these, so `${CLAUDE_PLUGIN_ROOT}` +resolves correctly whether the plugin is installed or you're dogfooding this repo directly): ```bash -bash .claude/scripts/gate.sh build -bash .claude/scripts/gate.sh lint -bash .claude/scripts/gate.sh test +bash ${CLAUDE_PLUGIN_ROOT:-.claude}/scripts/gate.sh build +bash ${CLAUDE_PLUGIN_ROOT:-.claude}/scripts/gate.sh lint +bash ${CLAUDE_PLUGIN_ROOT:-.claude}/scripts/gate.sh test ``` Each should run the right command (or say "not configured — skipping"). -> **Bootstrap first.** On a brand-new repo there's usually no build system yet, so *real* gate commands will -> **fail** (not skip) — e.g. `pnpm -r build` with no workspace, `forge test` with no `foundry.toml`. Pick one: +> **Bootstrap first.** On a brand-new project there's usually no build system yet, so *real* gate commands +> will **fail** (not skip) — e.g. `pnpm -r build` with no workspace, `forge test` with no `foundry.toml`. Pick +> one: > - **Scaffold a minimal buildable skeleton first** (workspace manifest + empty buildable packages/stubs that -> build and pass a trivial test), *then* wire the real gate commands. This makes the pilot run (Step 6) work +> build and pass a trivial test), *then* wire the real gate commands. This makes the pilot run (Step 3) work > immediately and gives parallel workers a green baseline to branch from. Recommended. > - **Or keep the gates empty** (`""` = skipped) until your first task is an explicit "bootstrap the workspace" > ticket, and only fill in real gate commands once that lands. @@ -55,8 +99,9 @@ Each should run the right command (or say "not configured — skipping"). > `Stop` hook and every agent's "done". ### Choosing `test_affected` per stack -`test_affected` runs on the `Stop` hook after every change, so it should be *fast* — ideally only the tests -touched by the diff. But "test only what changed" isn't free in every stack. Sensible options: +`test_affected` runs on the `Stop` hook (shipped by the plugin's `hooks/hooks.json`, no `settings.json` edits +needed) after every change, so it should be *fast* — ideally only the tests touched by the diff. But "test +only what changed" isn't free in every stack. Sensible options: | Stack | Cheap `test_affected` | Notes | |---|---|---| @@ -73,21 +118,12 @@ reach for affected-filtering when the full run is too slow to gate on every `Sto gotcha: any filter that diffs against `origin/main` needs that ref present in the worktree, so `git fetch origin main` first (or fall back to the full suite) — the per-worktree setup hook in #9 is the place for that. -## Step 4 — Review the agents (usually no change needed) -Skim `.claude/agents/*.md`. They're generic and read `gates.json`, so they typically need no edits. Adjust -`model:` per agent if your routing differs, or add project review skills (e.g. a security/audit skill) and -reference them in `gates.json` → `review.skills`. Run `/agents` in Claude Code to confirm they're detected. - -## Step 5 — Decide on hooks -`.claude/settings.json` wires two gates as hooks: -- **PostToolUse (Edit|Write)** → `gate.sh lint` after every edit. -- **Stop** → `gate.sh test_affected` when an agent tries to finish — a **red test blocks completion**, forcing - iteration. +Agents (`/agents` in Claude Code lists orchestrator, implementer, reviewer, test-runner) and hooks ship +generic and read `gates.json`, so they typically need no edits. Adjust `model:` per agent if your routing +differs, or add project review skills (e.g. a security/audit skill) and reference them in `gates.json` → +`review.skills`. -These are inert until you configure the matching commands in `gates.json`. Disable/adjust if you don't want a -hard test gate yet. (The `update-config` skill can help edit settings safely.) - -## Step 6 — Pilot run +## Step 3 — Pilot run Don't unleash the whole army first. Run ONE real task end-to-end: ``` @@ -98,9 +134,9 @@ Scope it, show me the plan, and wait for my approval before writing code. Approve the plan, let one implementer run in its worktree, watch the reviewers gate it, review the PR. Then read [`USAGE.md`](USAGE.md) to scale up, and [`TOKEN_BUDGET.md`](TOKEN_BUDGET.md) before you go parallel. -## Step 7 — Enforce gates in CI (server-side) +## Step 4 — Enforce gates in CI (server-side) The hooks and `gate.sh` enforce gates *locally*, and the orchestrator runs them before opening a PR — but -nothing stops a human (or a bot) merging a PR whose gates never ran. The template ships +nothing stops a human (or a bot) merging a PR whose gates never ran. `/orchestrator:setup` scaffolds [`.github/workflows/gates.yml`](../.github/workflows/gates.yml) + a `.github/actions/setup` composite action that run **the same `gate.sh` gates** on every `pull_request`, reading commands from `gates.json`. It's adapter-driven — you configure `gates.json`, not the YAML. @@ -134,28 +170,40 @@ A copy-pasteable checklist for wiring a new project into the autonomous loop. Se [`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}`; +1. **Install the plugin and run `/orchestrator:setup`** (Steps 1–2 above) — it writes everything below except + the two GitHub-side actions (4, 6). +2. **`.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). +3. **`CLAUDE.md`** — project context, conventions, definition of done, merge policy. +4. **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 +5. **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 +6. **Server-side gates** — confirm `.github/workflows/gates.yml` runs your gate commands (Step 4 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 +7. **Arm the loop** — run **`/orchestrator: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. +8. *(optional)* **Hardening** — `/orchestrator:harden` for the bypass + strict-sandbox profile, see [`HARDENING.md`](HARDENING.md). +## Step 5 — Keep the plugin up to date +When a new version of `orchestrator` ships, update it and re-stamp the files it scaffolded into your repo — +see [`USAGE.md` → "Updating the plugin"](USAGE.md#updating-the-plugin). + ## Verification checklist +- [ ] The `orchestrator` plugin shows as enabled (`/plugin`). - [ ] `CLAUDE.md` describes the project and lists modules. - [ ] `.claude/gates.json` has real commands; `gate.sh build|lint|test` behave correctly. -- [ ] `/agents` lists orchestrator, implementer, reviewer, test-runner. +- [ ] `/agents` lists orchestrator, implementer, reviewer, test-runner; `/orchestrator:*` commands resolve. - [ ] A pilot task produced a branch/PR that passed gates + review. -- [ ] CI gates run on PRs and are set as **required** status checks on the base branch (Step 7). +- [ ] CI gates run on PRs and are set as **required** status checks on the base branch (Step 4). - [ ] You've checked spend with `/cost` or `npx ccusage`. + +## Migrating an existing hand-copied install +Already have `.claude/` copied wholesale into a repo from before this was packaged as a plugin? See +[`MIGRATION.md`](MIGRATION.md) — it covers what to delete (now carried by the plugin), what to keep +(your adapter/`CLAUDE.md`/workflow/CI files), and how to switch to the plugin install above. diff --git a/docs/MIGRATION.md b/docs/MIGRATION.md new file mode 100644 index 0000000..4f62aff --- /dev/null +++ b/docs/MIGRATION.md @@ -0,0 +1,65 @@ +# Migrating a hand-copied install to the plugin + +If you adopted this template *before* it was packaged as a Claude Code plugin, you likely copied the whole +`.claude/` directory (agents, commands, hooks, scripts, and all) straight into your repo. This guide moves +that repo onto the plugin install, so the generic harness is maintained upstream instead of frozen in your +own git history. + +If you haven't installed the plugin yet, do that first — see [`GETTING_STARTED.md` → Step 1 — Install the +`orchestrator` plugin](GETTING_STARTED.md#step-1--install-the-orchestrator-plugin). + +## What to delete +Remove the copied harness that the plugin now carries — it's generic, not project-specific, and staying on a +frozen copy means you never get fixes/improvements: +- `.claude/agents/` — orchestrator, implementer, reviewer, test-runner. +- `.claude/commands/` — `pr-loop.md`, `pr-loop-self.md`, `harden.md`, `setup-orchestrator.md`, `test-pr.md`, + etc. (they resolve as namespaced `/orchestrator:*` commands once the plugin is enabled). +- `.claude/skills/` — e.g. the `setup` skill. +- `.claude/hooks/` — `hooks.json` (the lint/test-affected wiring is now shipped by the plugin and resolves via + `${CLAUDE_PLUGIN_ROOT}` automatically). +- `.claude/scripts/` — the generic ones (`gate.sh`, `bot-gh.sh`, `notify-poll.sh`, `pr-feedback.sh`, + `merge-ready.sh`, `seed-issues.sh`, `worktree.sh`, `prepare-pr.sh`, etc.). If you added project-specific + scripts of your own alongside these, keep only those. +- `.claude/.claude-plugin/` — if you'd copied this too (it's this repo's own plugin manifest, not something a + consumer needs locally). + +## What to keep +These are repo-specific — a plugin, by design, cannot carry them, so they stay yours regardless of the +install method: +- **`.claude/gates.json`** — your adapter (module map, gate commands, model routing, merge policy). +- **`CLAUDE.md`** — your project's context, conventions, and definition of done. +- **`.claude/workflows/feature-fanout.js`** — the deterministic fan-out workflow, tuned for your repo. This + one is *managed*: `/orchestrator:setup` re-stamps it on future updates if its version marker is behind (see + "Re-stamping managed files" below) — don't hand-edit it into something unrecognizable if you want that to + keep working, or accept that you'll reconcile by hand. +- **Your CI gate workflow** under `.github/` (`.github/workflows/gates.yml` + + `.github/actions/setup/action.yml`) — scaffolded once for your stack, and adapter-driven from there. + +## How to enable the plugin +Follow [`GETTING_STARTED.md` → Step 1](GETTING_STARTED.md#step-1--install-the-orchestrator-plugin): add the +`ai-project-orchestrator` marketplace (local clone today; the GitHub-source snippet is the target flow, with +a documented resolution gap — see that section) and enable the `orchestrator` plugin. Do this **before** +deleting the copied files above, so you're never without a working `/agents` list or hooks mid-migration. + +## Re-stamping managed files after an update +Once installed, updating the plugin and re-stamping managed files (`.claude/workflows/feature-fanout.js`, +mainly) is the **`/orchestrator:sync`** command — see [`USAGE.md` → "Updating the +plugin"](USAGE.md#updating-the-plugin). + +> **`/orchestrator:sync` is forthcoming** (packaging phase 3, issue #38), not available yet. In the meantime, +> `/orchestrator:setup`'s scaffold step does the same job: re-run it and it will re-stamp +> `feature-fanout.js` if its managed-version marker is behind, while leaving your `gates.json` and `CLAUDE.md` +> untouched (they're created once, never overwritten by re-runs). + +## Verification checklist +- [ ] The `orchestrator` plugin shows as **enabled** (`/plugin`). +- [ ] `/agents` lists orchestrator, implementer, reviewer, test-runner, and `/orchestrator:*` commands resolve + (e.g. `/orchestrator:pr-loop`, `/orchestrator:harden`). +- [ ] The old `.claude/agents/`, `.claude/commands/`, `.claude/skills/`, `.claude/hooks/`, and generic + `.claude/scripts/` are gone from your repo (only your own project-specific scripts remain, if any). +- [ ] Gates still run: `bash ${CLAUDE_PLUGIN_ROOT:-.claude}/scripts/gate.sh build|lint|test` behave the same + as before. +- [ ] `.claude/gates.json` and `CLAUDE.md` are intact and unchanged (they're yours; the migration shouldn't + have touched them). +- [ ] A pilot task still runs end-to-end (orchestrator → implementer → reviewers → PR) — see + [`GETTING_STARTED.md` Step 3](GETTING_STARTED.md#step-3--pilot-run). diff --git a/docs/USAGE.md b/docs/USAGE.md index 00a7ab4..53f6258 100644 --- a/docs/USAGE.md +++ b/docs/USAGE.md @@ -1,5 +1,11 @@ # Using the Orchestrator (after setup) +> **Assumes:** you've installed the `orchestrator` Claude Code plugin and run `/orchestrator:setup` in your +> project — see [`GETTING_STARTED.md`](GETTING_STARTED.md) if you haven't. Agents, commands, hooks, and +> scripts ship *with* the plugin; `/orchestrator:setup` scaffolds the repo-specific residue the plugin can't +> carry (`.claude/gates.json`, `CLAUDE.md`, the fan-out workflow, the CI gate workflow). Everything below is +> what you do once that's in place — day-to-day driving, the human checkpoints, and the autonomous loop. + Two ways to drive it: **conversational** (the orchestrator subagent — flexible) or **workflow** (deterministic fan-out). Plus the human checkpoints that keep you in the loop. @@ -118,7 +124,7 @@ With all three wired, the loop runs hands-off: **add issues → review → appro A natural step 4 is to start the next `module:*` issue only when **no PRs are open**, so work stays serialized (one issue in flight) and bounded. Caveats: cron jobs fire only while Claude Code is running, auto-expire after 7 days, and may be session-scoped on some versions — re-arm at session start (the -**`/pr-loop`** command does exactly that: arms or re-arms the cron and runs one tick immediately). +**`/orchestrator:pr-loop`** command does exactly that: arms or re-arms the cron and runs one tick immediately). **Running it fully hands-off?** Polling still leaves a human approving each tool call. To let the loop run unattended (Claude Code `bypassPermissions`), first harden the environment so the prompt is replaced @@ -126,8 +132,8 @@ by always-enforced guardrails — see **[`HARDENING.md`](HARDENING.md)** (deny l 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 / +Each `/orchestrator: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: @@ -146,7 +152,7 @@ decide what the loop actually touches: `gates.json.modules[]`, and (b) the issue carries the matching `module:*` label. Commenting "approved" on an issue does nothing — nothing watches issue text. -**Self-hosting this repo's own backlog?** **`/pr-loop-self`** (`.claude/commands/pr-loop-self.md`) runs the +**Self-hosting this repo's own backlog?** **`/orchestrator:pr-loop-self`** (`.claude/commands/pr-loop-self.md`) runs the same loop mechanics self-hosted, against this repo's own `.claude`/`docs`/`examples`/`.github` backlog, using **`.claude/self/gates.json`** as the adapter (module map, gates, review lenses) instead of the placeholder `.claude/gates.json` above. See `.claude/self/README.md` for the self-adapter contract. @@ -154,6 +160,23 @@ same loop mechanics self-hosted, against this repo's own `.claude`/`docs`/`examp New project? Wire this up with the **[new-project configuration checklist](GETTING_STARTED.md#new-project-configuration-checklist)**. +## Updating the plugin +When a new version of the `orchestrator` plugin ships (new agents, commands, gate fixes, etc.), refresh the +marketplace listing and let Claude Code update the installed plugin: +``` +/plugin marketplace update ai-project-orchestrator +``` +Then re-stamp the files `/orchestrator:setup` scaffolded into **your** repo (`gates.json`, `CLAUDE.md`, the +fan-out workflow, the CI gate workflow) so they pick up any changes shipped in the update: +``` +/orchestrator:sync +``` +> **Not shipped yet.** `/orchestrator:sync` is planned for packaging phase 3 (issue #38) — it will re-run the +> scaffold's re-stamping logic non-interactively, so an update also refreshes managed files without +> re-running the whole interview. Until it lands, re-run `/orchestrator:setup` instead: it safely re-stamps +> only the *managed* `feature-fanout.js` when its version marker is behind, and never overwrites your own +> `gates.json`/`CLAUDE.md` (those are created once and left alone on every re-run). + ## Merge discipline - **`pr-per-agent`** (default): each worker → branch → PR. You (or a merge step) integrate; conflicts surface at PR time. Cleanest/auditable. @@ -174,11 +197,11 @@ If workers stall or collide, the fix is almost always a sharper **module map** i Trivial or single-file changes: just do them directly. The 15× token multiplier isn't worth it. The orchestrator itself is told to use one worker and no parallelism for small tasks — hold it to that. -## Testing a PR locally (`/test-pr `) +## Testing a PR locally (`/orchestrator:test-pr `) The owner reviews bot PRs by actually running the change. Doing that by hand is error-prone — the classic failure is testing from the main working tree (which does NOT contain the unmerged PR), concluding "the fix doesn't work", -and bouncing the PR back. `/test-pr ` removes that footgun: +and bouncing the PR back. `/orchestrator:test-pr ` removes that footgun: 1. Resolves the PR's head branch and fetches the latest pushed commit. 2. Creates a **detached** git worktree at `humanTest.worktreeDir/pr-` (default `.worktrees/pr-`) — isolated @@ -195,5 +218,5 @@ Configure the commands once in `.claude/gates.json`: } ``` -Add `humanTest.worktreeDir` to `.gitignore`. Re-running `/test-pr` on the same PR fast-forwards the worktree to the -latest commit (idempotent). Tear down with `git worktree remove `. +Add `humanTest.worktreeDir` to `.gitignore`. Re-running `/orchestrator:test-pr` on the same PR fast-forwards the +worktree to the latest commit (idempotent). Tear down with `git worktree remove `.