diff --git a/.claude/commands/efficient-opus.md b/.claude/commands/efficient-orchestration.md similarity index 55% rename from .claude/commands/efficient-opus.md rename to .claude/commands/efficient-orchestration.md index 1da506a..3729fd3 100644 --- a/.claude/commands/efficient-opus.md +++ b/.claude/commands/efficient-orchestration.md @@ -1,17 +1,23 @@ -# Efficient Opus +# Efficient Orchestration -Orchestrate this task with Opus; delegate token-heavy work to cheaper, faster subagents (Sonnet/Haiku via the Task tool). Spend Opus on complexity and judgment; delegate bounded, routine, and high-volume work. +Orchestrate this task on your current model; delegate token-heavy work to cheaper, faster subagents via the Task tool. Spend your model on complexity and judgment; delegate bounded, routine, and high-volume work. + +## Model tiers (reference, cheapest to most capable) + +`Haiku < Sonnet < Opus < Fable` + +You are the orchestrator, running on one of these tiers. Delegate *down* the ladder: when you spawn a subagent, pass the model id for the tier the work needs, and never spend a higher tier than the task justifies. If a model appears that isn't listed here, slot it by its cost and capability relative to the others. This is the only place model names are pinned; everything below is written relative to "your tier." ## Your own token discipline - Search and size-check before reading; read by range or signature, never dump whole files or logs. - Use Bash (`grep`/`sed`/`awk`/`jq`/`head`) for inspection, large files, and mechanical transforms instead of loading them into context; keep Read+Edit for code changes that need review. -- Batch independent searches in parallel — one message, multiple tool calls. +- Batch independent searches in parallel: one message, multiple tool calls. - Report findings as summaries with `file:line` refs, not raw dumps. -## Keep on Opus +## Keep on your model -Decomposition, architecture/risk tradeoffs, complex implementation (intricate refactors, multi-file features, subtle bugs), resolving conflicting reports, integrating results, final review and synthesis — and any blocker your next step depends on. +Decomposition, architecture/risk tradeoffs, complex implementation (intricate refactors, multi-file features, subtle bugs), resolving conflicting reports, integrating results, final review and synthesis, and any blocker your next step depends on. ## Delegate @@ -19,31 +25,33 @@ Repo scans, inventory, search; docs/prior-art extraction; browser/test passes, s ## Model per subagent -- **Haiku** — mechanical, high-volume, low-judgment: search sweeps, inventory, log reduction, simple edits. -- **Sonnet** (default) — low-to-medium complexity: focused research, routine or narrow patches, test runs, straightforward debugging. -- **Opus** — high complexity worth parallelizing or isolating from your context, not for cost savings: intricate refactors, multi-file features, subtle bugs, design exploration, high-stakes reasoning. +Pick the tier by task difficulty, not task type, and don't exceed your own tier for cost savings: + +- **Cheapest tier** (bottom of the ladder): mechanical, high-volume, low-judgment work such as search sweeps, inventory, log reduction, simple edits. +- **A mid tier** (a good default): low-to-medium complexity such as focused research, routine or narrow patches, test runs, straightforward debugging. +- **Your own tier** (or an equal-tier isolated subagent), worth parallelizing or isolating from your context rather than for cost savings: intricate refactors, multi-file features, subtle bugs, design exploration, high-stakes reasoning. -Match the tier to task difficulty, not task type — don't push complex implementation down to Sonnet just because it's "implementation." +Match the tier to task difficulty, not task type: don't push complex implementation down to a mid tier just because it's "implementation." ## Pattern 1. Name the token risk: big search, long logs, broad docs, or repetitive edits. 2. Split independent slices into parallel subagents before reading everything yourself; keep coupled or blocking work local. 3. Give each subagent clear ownership, bounded scope, and verification gates. -4. Require compact returns: findings, `file:line` refs, commands run, diffs, residual risk, stop conditions hit, and what Opus must decide. -5. Decide at the Opus layer: compare, resolve conflicts, choose the path, review the final diff. +4. Require compact returns: findings, `file:line` refs, commands run, diffs, residual risk, stop conditions hit, and what you must decide. +5. Decide at the orchestration layer: compare, resolve conflicts, choose the path, review the final diff. ## Stay within usage limits -- Delegate in bounded waves — cap parallel subagents (~3 by default), let each wave finish before launching the next, and check usage between waves, not continuously. +- Delegate in bounded waves: cap parallel subagents (~3 by default), let each wave finish before launching the next, and check usage between waves, not continuously. - Check real usage with `npx -y ccusage@latest blocks --active --json`; stop launching new work once the 5-hour or weekly window nears ~95% of its cap. -- Don't kill in-flight subagents to claw back marginal budget — let running work finish. +- Don't kill in-flight subagents to claw back marginal budget; let running work finish. ## Pause & resume across windows For long unattended runs, auto-pause at the cap and resume when it clears: -- When either window hits ~95%, finish the current wave, then schedule a wakeup for `min(3600, secondsUntilWindowClears)` seconds. If the window clears further out than 3600s, chain wakeups — re-schedule on each wake until it clears. +- When either window hits ~95%, finish the current wave, then schedule a wakeup for `min(3600, secondsUntilWindowClears)` seconds. If the window clears further out than 3600s, chain wakeups: re-schedule on each wake until it clears. - On resume, re-verify live usage with `ccusage`; don't trust elapsed wall-clock. A fresh `blocks` timestamp (vs. the previous block id) is the real signal the window rolled over. - Make the wake prompt self-contained: remaining work plan, the 95% rule, the exact usage command, the previous block id, the check-then-reschedule logic, and handoff packets for any subagents that resume. - Tell the user which window tripped, the observed %, the next check time, and the outstanding work. @@ -58,11 +66,11 @@ Stop and report instead of improvising when: live code contradicts the handoff; ## Vet results -Reports are leads, not facts. Before acting on a high-impact finding, opening a PR, or claiming done: reopen key cited files, confirm line refs and failures, and review the final diff. Resolve subagent disagreements at the Opus layer. +Reports are leads, not facts. Before acting on a high-impact finding, opening a PR, or claiming done: reopen key cited files, confirm line refs and failures, and review the final diff. Resolve subagent disagreements at the orchestration layer. ## Guardrails - Don't delegate a blocker your next step needs. - Don't let two subagents edit the same files at once. -- Don't trust high-risk conclusions blindly — check the evidence yourself. -- The pattern pays off only when work parallelizes; if a task is tiny or validation needs delicate judgment, keep it on Opus. +- Don't trust high-risk conclusions blindly; check the evidence yourself. +- The pattern pays off only when work parallelizes; if a task is tiny or validation needs delicate judgment, keep it on your own model. diff --git a/README.md b/README.md index 29c082c..e39b9c7 100644 --- a/README.md +++ b/README.md @@ -80,15 +80,15 @@ Run a standalone code review on staged changes. Writes findings to `agent-code-r - Copilot CLI: `/code-review` - Antigravity CLI: `/code-review` -### /efficient-opus +### /efficient-orchestration -Run a task with Claude Opus as the orchestrator and reviewer while cheaper, faster subagents do the token-heavy research, coding, and testing. It matches model tier to task difficulty (Opus for complex work, Sonnet for low/medium, Haiku for mechanical), keeps Opus's own reading and searching lean, runs delegation in bounded waves to respect your usage caps, and — for long unattended runs — auto-pauses and resumes across the 5-hour and weekly usage windows. +Run a task with your current model as the orchestrator and reviewer while cheaper, faster subagents do the token-heavy research, coding, and testing. It matches model tier to task difficulty (your own tier for complex work, a mid tier for low/medium, the cheapest tier for mechanical), keeps the orchestrator's own reading and searching lean, runs delegation in bounded waves to respect your usage caps, and for long unattended runs auto-pauses and resumes across the 5-hour and weekly usage windows. Model names are pinned in one reference ladder inside the command; the rest is written relative to whatever tier you are on, so it reads correctly whether you run Fable, Opus, or Sonnet. -Opus-specific, so it's installed for Claude Code only. +Relies on Task-tool subagent delegation, a Claude Code feature, so it's installed for Claude Code only. **Usage:** -- Claude Code: `/efficient-opus` +- Claude Code: `/efficient-orchestration` ## Review Loops @@ -167,6 +167,7 @@ Both loops are driven by agent-agnostic prompts in [prompts/](prompts/), not int - The `setup` script copies selected commands to the appropriate user-level directory for each tool. - Shared prompts are installed to `~/.local/share/ai-coding-setup/prompts/` and referenced by the review loop scripts. - Installed commands are tagged with a source marker so the script can safely update them later without overwriting your custom commands that happen to share the same name. +- On each run the script also offers to prune stale installs: any command it previously installed (identified by that same marker) that no longer exists in the repo can be removed, so renamed or deleted commands clean themselves up. It asks before each removal (default No, so nothing is dropped without your say-so), or pass `--force` to prune without prompting. Your own unmarked commands are never touched. ## MCP Server Configuration diff --git a/setup b/setup index 76585e0..995f5e9 100755 --- a/setup +++ b/setup @@ -383,7 +383,7 @@ install_commands() { echo -e "${BOLD}── ${display_name} ──${NC}" mkdir -p "$dest_dir" - local installed=0 updated=0 skipped=0 current=0 + local installed=0 updated=0 skipped=0 current=0 pruned=0 for entry in "${entries[@]}"; do local cmd_name src_file dest_file dest_entry @@ -467,7 +467,54 @@ install_commands() { fi done - echo -e " ${BOLD}${display_name}:${NC} $installed installed, $updated updated, $current up to date, $skipped skipped" + # Prune our stale orphans: dest entries that carry our marker but no longer + # have a matching source (a command renamed or removed in the repo). The + # marker guarantees these were installed by us, but removal still asks first + # (default No) so an update run can't silently drop a command the user meant + # to keep, e.g. when they declined the renamed replacement's install prompt; + # --force prunes without asking. Unmarked (custom) files are never touched, + # and the early return above on an empty source dir keeps this from wiping a + # whole category. + local d f fname name found s pext + if [[ "$mode" == skill ]]; then + while IFS= read -r -d '' d; do + [[ -f "$d/SKILL.md" ]] || continue + name=$(basename "$d"); found=false + for s in "${entries[@]}"; do + [[ "$(basename "$s")" == "$name" ]] && { found=true; break; } + done + $found && continue + has_marker "$marker" "$d/SKILL.md" || continue + if ! $FORCE && ! prompt_yes_no " Remove stale ${prefix}${name} (no longer in repo)?" n; then + print_info "Kept ${prefix}${name}" + continue + fi + rm -rf "$d" + print_success "Removed stale ${prefix}${name}" + ((++pruned)) + done < <(find "$dest_dir" -mindepth 1 -maxdepth 1 -type d -print0) + else + pext="${mode#file:}" + while IFS= read -r -d '' f; do + fname=$(basename "$f"); name="${fname%."$pext"}"; found=false + for s in "${entries[@]}"; do + [[ "$(basename "$s")" == "$fname" ]] && { found=true; break; } + done + $found && continue + has_marker "$marker" "$f" || continue + if ! $FORCE && ! prompt_yes_no " Remove stale ${prefix}${name} (no longer in repo)?" n; then + print_info "Kept ${prefix}${name}" + continue + fi + rm -f "$f" + print_success "Removed stale ${prefix}${name}" + ((++pruned)) + done < <(find "$dest_dir" -maxdepth 1 -name "*.$pext" -print0) + fi + + local prune_note="" + [[ $pruned -gt 0 ]] && prune_note=", $pruned removed" + echo -e " ${BOLD}${display_name}:${NC} $installed installed, $updated updated, $current up to date, $skipped skipped${prune_note}" } # ---- Claude Code settings configuration ------------------------------------ @@ -889,7 +936,7 @@ while [[ $# -gt 0 ]]; do -f|--force) FORCE=true; shift ;; -h|--help) echo "Usage: setup [-f|--force]" - echo " -f, --force Overwrite custom (non-managed) files" + echo " -f, --force Overwrite custom (non-managed) files and prune stale ones without prompting" exit 0 ;; *) echo "Unknown option: $1"; exit 1 ;; esac @@ -1023,15 +1070,11 @@ for tool in "${selected_tools[@]}"; do antigravity) echo "" echo -e "${BOLD}── Antigravity CLI ──${NC}" - if prompt_yes_no " Setup Antigravity CLI?"; then - if agy plugin install "$PWD/.antigravity"; then - print_success "Installed Antigravity CLI plugin" - configure_mcp "antigravity" "Antigravity CLI" "agy" - else - print_error "agy plugin install failed — see output above" - fi + if agy plugin install "$PWD/.antigravity"; then + print_success "Installed Antigravity CLI plugin" + configure_mcp "antigravity" "Antigravity CLI" "agy" else - print_info "Skipped Antigravity CLI plugin" + print_error "agy plugin install failed; see output above" fi ;; esac