diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json new file mode 100644 index 0000000..cd81f34 --- /dev/null +++ b/.claude-plugin/marketplace.json @@ -0,0 +1,13 @@ +{ + "name": "claude-code-setup", + "owner": { + "name": "Victor Kzam" + }, + "plugins": [ + { + "name": "cw", + "source": "./", + "description": "Claude Code workflow plugin: design/build/ship skills, orchestration agents, and guardrail hooks." + } + ] +} diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json new file mode 100644 index 0000000..609980d --- /dev/null +++ b/.claude-plugin/plugin.json @@ -0,0 +1,17 @@ +{ + "name": "cw", + "version": "1.0.0", + "description": "Claude Code workflow plugin: design/build/ship skills, orchestration agents, and guardrail hooks.", + "author": { + "name": "Victor Kzam" + }, + "repository": "https://github.com/victorkzam/claude-code-setup", + "license": "MIT", + "keywords": [ + "workflow", + "hooks", + "skills", + "agents", + "orchestration" + ] +} diff --git a/.claude/skills/setup/SKILL.md b/.claude/skills/setup/SKILL.md deleted file mode 100644 index 042d806..0000000 --- a/.claude/skills/setup/SKILL.md +++ /dev/null @@ -1,184 +0,0 @@ ---- -name: setup -description: "Install this repo's Claude Code setup into the current machine's config dir. Runs ONLY when the user types /setup inside a clone of claude-code-setup — never model-invoked. Orchestrates the check/install/merge scripts through a preflight → install → merge → handoff flow, with a diff shown and explicit consent taken before every write." -disable-model-invocation: true -argument-hint: (no arguments — run inside a fresh clone of this repo) -allowed-tools: - - Read - - Glob - - Grep - - Bash(bash scripts/check.sh:*) - - Bash(bash scripts/install.sh --dry-run:*) - - Bash(bash scripts/merge-settings.sh --dry-run:*) - - Bash(bash scripts/merge-claude-md.sh --dry-run:*) ---- - -# Setup Router — Adopter Install Flow - -You are the session executing `/setup` inside a **clone of this repo** (this skill is -repo-scoped: it lives under `.claude/skills/` and is discovered only when Claude Code runs -in the clone — it is never installed onto an adopter's machine). Your job is to install this -setup's managed artifacts (agents/hooks/rules/skills), then merge `settings.json` and -`CLAUDE.md`, into the current machine's Claude config dir — **safely, with a diff shown and -explicit consent taken before every write**. - -## Consent model (read before you start) - -This flow has **two consent gates by design**, and you must not collapse either: - -1. **Every write is preceded by a diff + an explicit ask.** You dry-run first, show the - plan/diff, and ask the user to proceed. -2. **The writing commands are deliberately NOT pre-approved in `allowed-tools`.** Only the - read-only and `--dry-run` forms are pre-approved. When you run the real install, a - real `--force=`, or a real `--apply`, Claude Code will raise a **permission - prompt** — that prompt is the *intended* second gate, not a bug. Tell the user to expect - it and let it happen; never try to route around it. - -Do **not** invent Edit/Write shortcuts to config paths, and do not seek broader permission -grants to suppress those prompts. - -## Script contract (shared by all four scripts) - -- Machine lines `CCS-STATUS::` print on **stdout**; human diffs/plan text also - on stdout; refusals/errors on **stderr**. -- Exit codes: **0** success · **1** refusal / partial · **2** usage / internal. -- `scripts/install.sh` (non-dry-run) prints `CCS-STATUS:backup-dir:` as its **first** - status line. **Capture that path** — that ONE run dir is threaded via `--backup-dir ` - into every later `--apply`/`--force` this session, so the whole install produces a single - backup run dir and a single receipt. - -## Global error rules (apply in every phase) - -- **Any script exits 2** → STOP the entire flow. Report the script's stderr **verbatim**; - do not attempt later phases. -- **Any script exits 1** → report its stderr **verbatim** and ask the user how to proceed - (it is a refusal/partial, not a hard stop — the user decides). -- **Abort-safe / idempotent:** every phase is idempotent. If the flow is aborted partway, - re-running `/setup` resumes safely — already-installed, identical files no-op - (`CCS-STATUS:unchanged:...`), and merges recompute from current on-disk state. There is no - state file; a declined step is simply remembered in this conversation. - ---- - -## P1 — Preflight - -Run: - -``` -bash scripts/check.sh -``` - -- **Exit 2 (FAIL)** → STOP. Present the `FAIL:` lines **verbatim** plus the fixes `check.sh` - suggests. Do not proceed to P2. -- **Exit 1 (WARN)** → present the `WARN:` lines and **ask the user whether to proceed** given - the warnings. Only continue if they say yes. -- **Exit 0 (PASS)** → proceed to P2. - -## P2 — Install managed artifacts - -1. **Dry-run first:** - - ``` - bash scripts/install.sh --dry-run --diff - ``` - - Present the plan: what would be installed (missing → install), what is identical - (`unchanged`), and per-category **diffs for any differing files** (differing files are - **skipped** by default, per category). - -2. **Real install** (this is NOT pre-approved — expect a permission prompt; explain that to - the user before running it): - - ``` - bash scripts/install.sh - ``` - - **Capture the first status line** `CCS-STATUS:backup-dir:`. Save `` — you will - pass `--backup-dir ` to every later apply/force so the session shares one backup run - dir and one receipt. - -3. **Resolve skipped (differing) files.** Any file that differed was left untouched. For each - affected **category**, show that category's diff and ask the user **keep vs overwrite**. - Overwrite only the categories the user approves, one category per run: - - ``` - bash scripts/install.sh --force= --backup-dir - ``` - - (`` is one of `agents`, `hooks`, `rules`, `skills`.) This run is also NOT - pre-approved — the permission prompt is again the intended consent gate. - -## P3 — Merge config files (one target at a time) - -Handle **`settings.json` first, then `CLAUDE.md`**. For each target, always: dry-run → show -the unified diff → take **explicit consent** → apply with the shared `--backup-dir `. - -### P3a — settings.json - -``` -bash scripts/merge-settings.sh --dry-run -``` - -Show the unified diff. Ask for explicit consent. On yes: - -``` -bash scripts/merge-settings.sh --apply --backup-dir -``` - -If the target already exists (an existing-config merge, not a fresh verbatim write), also -surface the **withheld-convenience-keys note** to the user: - -> Convenience keys (model, statusLine, defaultMode) were not merged to avoid overwriting -> yours — copy from `settings.example.json` if wanted. - -### P3b — CLAUDE.md - -``` -bash scripts/merge-claude-md.sh --dry-run -``` - -Show the unified diff. Ask for explicit consent. On yes: - -``` -bash scripts/merge-claude-md.sh --apply --backup-dir -``` - -**Declines are respected.** If the user declines either merge, do not write, do not re-ask in -a loop, and do not nag — just record the decline in the conversation and move on. - -## P4 — Handoff - -The install is done from this session's side. Print, for the user: - -- **Receipt location** and the **backup run dir** (`` captured in P2). -- A short **"what behaves differently now"** summary (3 lines): - 1. Pushes to `main`/`master` are blocked (branch-protection hook). - 2. The delegation guard is active during `/build` (orchestrator can't hand-edit source). - 3. Design + pre-PR human checkpoints are enforced. - -Then give the user the steps **they run AFTER restarting Claude Code**. The restart **severs -this session**, so the skill must NOT try to run these itself — hand them over as -instructions: - -1. **Restart Claude Code** (so the newly installed settings/hooks/skills load). -2. Verify the install landed: - - ``` - bash scripts/check.sh --post - ``` - -3. Confirm hooks loaded by running **`/hooks`** and checking the managed entries appear. - ---- - -## Anti-patterns to avoid - -- Do NOT skip the dry-run — a diff is shown before **every** consent, no exceptions. -- Do NOT collapse the two consent gates: never seek a broader grant to suppress the - install/force/apply permission prompts. -- Do NOT thread multiple backup dirs — capture the ONE `CCS-STATUS:backup-dir:` from - P2 and reuse it for every apply/force. -- Do NOT re-ask a declined merge in a loop. -- Do NOT run the post-restart steps yourself — the restart ends this session; they are the - user's to run. -- Do NOT continue past an exit-2 from any script — STOP and report verbatim. diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..5a88ee3 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +docs/plans/** linguist-generated=true diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 47a82aa..4248097 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,58 +8,83 @@ on: branches: [main] jobs: - lint-and-test: - name: shellcheck + bats + manifest (ubuntu) + ubuntu: + name: shellcheck + jq + tests/run.sh all + plugin validate (ubuntu) runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + with: + fetch-depth: 0 - - name: Install shellcheck - run: sudo apt-get update -y && sudo apt-get install -y shellcheck + - name: Install jq and shellcheck + run: sudo apt-get update -y && sudo apt-get install -y shellcheck jq - # Same pinned git-checkout install as the macos job below. `npm install -g - # bats` broke on the ubuntu-24.04 runner image: npm's global prefix is - # /usr/local, whose man dirs the runner user cannot mkdir (EACCES). - - name: Install bats-core from a git checkout - run: | - git clone --depth 1 --branch v1.11.0 https://github.com/bats-core/bats-core.git "$RUNNER_TEMP/bats-core" - echo "$RUNNER_TEMP/bats-core/bin" >> "$GITHUB_PATH" + - name: shellcheck hooks + tests/run.sh + run: shellcheck -x hooks/*.sh tests/run.sh + + - name: validate plugin/marketplace/hooks JSON + run: jq empty .claude-plugin/plugin.json .claude-plugin/marketplace.json hooks/hooks.json - - name: shellcheck scripts + hooks - # -x: scripts/*.sh source scripts/lib.sh; a bare single-file shellcheck - # trips info-level SC1091 (can't follow non-constant/relative source). - # House convention: always lint with -x here. - # - # --severity=error: hooks/*.sh (owned by an earlier task, out of scope - # here) carry pre-existing info/warning-level nits (SC2086, SC2015, - # SC2221/2222) that are stylistic, not bugs. Gating on errors keeps this - # a real correctness gate without failing CI on unrelated existing - # style notes. Judgment call — revisit if those files get cleaned up. - run: shellcheck -x --severity=error scripts/*.sh hooks/*.sh + - name: tests/run.sh all + run: bash tests/run.sh all - - name: bats (full suite, incl. e2e) - run: bats tests/*.bats + - name: categorical prompt-hygiene greps + # Red until T3-T6 rewrite skills/agents/rules; CI only runs at push + # time, which happens after T7 (accepted by the design). + run: | + set -e + if git grep -niE 'opus needs|do not trust|be decisive|read all files fresh|claude-design-active|claude-orchestrator-active' -- skills agents rules; then + echo "gate: banned coordination phrases in prompts" + exit 1 + fi + if git grep -nwE 'NEVER|ALWAYS|MUST|CRITICAL' -- skills agents rules; then + echo "gate: emphatic capitals in prompts" + exit 1 + fi + if git grep -niE 'under 50 lines' -- skills agents rules; then + echo "gate: 'under 50 lines' phrase in prompts" + exit 1 + fi + if git grep -nE '^(disallowedTools|permissionMode|mcpServers|hooks):' -- agents; then + echo "gate: disallowed frontmatter keys in agents" + exit 1 + fi + for f in agents/*.md; do + for k in model tools effort maxTurns; do + grep -q "^$k:" "$f" || { echo "$f lacks $k:"; exit 1; } + done + done + if git grep -niE '~/.claude/plans|gitattributes|linguist|git clean' -- skills; then + echo "gate: internal-path/meta references in skills" + exit 1 + fi + if ! grep -q haiku skills/design/SKILL.md; then + echo "gate: skills/design/SKILL.md missing haiku reference" + exit 1 + fi + N=$(sed -n 's/^Copyright (c) [0-9]* //p' LICENSE | cut -d' ' -f1) + if [ -z "$N" ]; then + echo "gate: could not extract copyright name from LICENSE" + exit 1 + fi + if git grep -qi "$N" -- skills agents rules hooks tests WORKFLOW.md CLAUDE.md docs; then + echo "gate: LICENSE-derived name leaked into prompts/docs" + exit 1 + fi - - name: manifest.txt == git ls-files agents/ hooks/ rules/ skills/ (C3) + - name: install Claude Code CLI and validate plugin run: | - diff <(git ls-files agents/ hooks/ rules/ skills/) scripts/manifest.txt + npm install -g @anthropic-ai/claude-code + claude plugin validate . + claude plugin validate .claude-plugin/plugin.json - bats-macos: - name: bats (macos system /bin/bash 3.2 + BSD userland) + macos: + name: hooks under system bash 3.2 (macos) runs-on: macos-latest steps: - uses: actions/checkout@v4 - # bats-core from a git checkout, invoked directly out of bin/ — NOT via - # brew. A brewed bats would pull in a modern GNU-flavored PATH/toolchain - # and mask exactly the GNUisms this job exists to catch. shellcheck is - # intentionally skipped here: the ubuntu job already lints every script. - - name: Install bats-core from a git checkout - run: | - git clone --depth 1 --branch v1.11.0 https://github.com/bats-core/bats-core.git "$RUNNER_TEMP/bats-core" - echo "$RUNNER_TEMP/bats-core/bin" >> "$GITHUB_PATH" - - - name: bats (full suite, incl. e2e) under system bash + - name: tests/run.sh hooks under system /bin/bash (jq preinstalled) run: | - echo "bash: $(command -v bash) ($(bash --version | head -n1))" - bats tests/*.bats + echo "bash: $(command -v /bin/bash) ($(/bin/bash --version | head -n1))" + /bin/bash tests/run.sh hooks diff --git a/.gitignore b/.gitignore index 92dc379..ff11a10 100644 --- a/.gitignore +++ b/.gitignore @@ -19,33 +19,28 @@ !skills/** !hooks/ !hooks/** -!scripts/ -!scripts/** !tests/ !tests/** -# Allow only the project-local design-artifact directories under docs/ -# (plans and research), not the whole docs/ tree. Gitignore requires -# un-ignoring each parent directory level before its children, so the -# chain below is intentionally explicit rather than a single !docs/**. +# Track the plugin manifest directory. +!.claude-plugin/ +!.claude-plugin/** + +# Allow the project-local design-artifact directories under docs/plans/: +# a future single-file design doc (docs/plans/.md) and this build's +# folder (docs/plans/cw-plugin/) are tracked; any other docs/plans// +# folder stays ignored. Gitignore requires un-ignoring each parent directory +# level before its children, so the chain below is intentionally explicit +# rather than a single !docs/plans/**. !docs/ !docs/plans/ -!docs/plans/** -!docs/research/ -!docs/research/** +!docs/plans/*.md +!docs/plans/cw-plugin/ +!docs/plans/cw-plugin/** !.github/ !.github/** -# Allow the repo-scoped setup skill under .claude/, but nothing else in -# .claude/ (agent-memory, local settings, etc. must stay ignored). Gitignore -# requires un-ignoring each parent directory level before its children, so -# the chain below is intentionally explicit rather than a single !.claude/**. -!.claude/ -!.claude/skills/ -!.claude/skills/setup/ -!.claude/skills/setup/** - # Never track local, personal, or generated Claude Code state, even if a # future copy step drops it in here by mistake. settings.json @@ -59,5 +54,5 @@ history.jsonl .DS_Store # Security rail: this repo must never ship an active repo-local settings -# file, even though .claude/ is partially un-ignored above. +# file, even though other repo-local .claude paths may be tracked above. .claude/settings.json diff --git a/CLAUDE.md b/CLAUDE.md index f475e9a..80d5e7e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,48 +1,17 @@ -# Global Development Environment Rules +# claude-code-setup -This is a template `~/.claude/CLAUDE.md`. It is always-on advisory context for -every project Claude Code touches. Sections marked "example — replace with -your own" are personal-preference blocks you should adapt or delete; the -`Workflow Rules` section is the transferable system this repo ships (see -`WORKFLOW.md`) and is meant to be kept largely as-is. +This repo is the Claude Code plugin `cw`: skills, agents, hooks, and rules for +a design -> build -> ship workflow. -## Identity (example — replace with your own) -PM-turned-engineer. Quality and learning over speed. Always explain WHY behind architectural decisions, not just WHAT. +Tests: bash tests/run.sh all - -## Workflow Rules -- Never push directly to main/master. Feature branches only. -- Conventional Commits: feat:, fix:, refactor:, docs:, chore:, test: -- Co-author line on every commit: +## Conventions +- Conventional Commits: feat:, fix:, refactor:, docs:, chore:, test:. +- Every commit ends with: Co-Authored-By: Claude -- No implementation without an approved design. If uncertain, ask first. -- Two human checkpoints are non-negotiable: after design, before PR. -- Each task maps to exactly one atomic Conventional Commit made by the implementer that did the task, or `commit: none` for unversioned/external targets (verification-only gates, no commit). `/ship` verifies the series; it never creates a catch-all or squashed commit. -- A PR is opened only after the feature/milestone is fully built AND the quality gate has passed. No PR on a red gate; no PR mid-build. -- Mode transitions: `/design` runs in plan mode; on plan approval it writes the artifact set to `/docs/plans//` (project copy canonical; plans-dir drafts banner-stamped; plans dir for meta-tooling/gitignored-docs work; no-repo case prompts to `git init` or stay in the plans dir); the post-design checkpoint precedes `/build`; `/build` commits the set as a scoped `docs():` commit on the feature branch (not necessarily the leading commit in the series); `/build` and `/ship` run in execute mode. -- `/ship` ends by offering `/compound`. Process-rule edits (CLAUDE.md, `.claude/rules`) are never committed into the feature PR. -- Model routing and workflow usage follow ~/.claude/rules/orchestration.md. - -## Research-First Design -- Before making architecture decisions, check official docs (use context7) and search for best practices (use exa/WebSearch). -- Flag unsourced decisions explicitly: "Note: this approach is unsourced — my judgment call." -- Prefer boring, proven patterns over novel ones unless there's a clear reason. - -## Context Hygiene -- Use subagents for tasks whose output would bloat the main context (exploration, review, large diffs). -- Suggest /clear between unrelated tasks. -- For large features: suggest one session per phase. - - -## Stack Preferences (example — replace with your own; used only when a project's own CLAUDE.md is silent) -- iOS: SwiftUI, async/await, no completion handlers, // MARK: sections -- Python: type hints, Pydantic models, pytest, functions under 50 lines -- Web: Next.js App Router, TypeScript strict mode -- All: graceful error handling, no over-engineering - -## MCP Servers (OPTIONAL) -The workflow degrades gracefully without these — see `skills/search/SKILL.md`'s -fallback rules. Install docs: [context7](https://github.com/upstash/context7), -[exa](https://github.com/exa-labs/exa-mcp-server). -- context7: Library/framework docs. Use BEFORE writing code against any API. -- exa: Semantic web search. Use for research, competitive analysis, best practices. +- Design docs: a single-file plan at `docs/plans/.md` is tracked by + default. A folder-style artifact set needs both `!docs/plans//` and + `!docs/plans//**` added to `.gitignore` before `/cw:build` runs + against it. +- Feature branches only; work reaches the default branch through a pull + request, opened only after the quality gate passes. diff --git a/README.md b/README.md index 7cb6bab..7aca6ae 100644 --- a/README.md +++ b/README.md @@ -1,372 +1,289 @@ -# Claude Code Setup - -A user-level `~/.claude` configuration for [Claude Code](https://claude.com/claude-code): -a `/design` → `/build` → `/ship` agentic workflow, six specialized subagents, -model-routing rules, and a small set of hooks that turn advisory conventions into -enforced ones. This is a sanitized export of a daily-driver setup, offered as a -clone-and-use template — installed via a repo-scoped `/setup` skill (see -[Quick Start](#6-quick-start-clone-and-use)) that installs and merges everything -with a diff and your explicit consent, or, if you'd rather skip the -conversational flow, [four scripts](#7-standalone-install-no-llm-run-the-scripts-directly) -you can run by hand. - -## 1. Why this exists - -The cost model behind this setup is simple: **research and review are cheap; -redoing finished work is expensive.** A wrong architectural assumption caught in -`/design` costs a few minutes of subagent research. The same assumption caught -after `/build` has already written code costs a revert, a re-plan, and a second -implementation pass. Every non-negotiable rule in `WORKFLOW.md` — the two human -checkpoints, the research-before-code sequencing, the review loop that verifies -findings before acting on them — exists to keep mistakes cheap by catching them -as early as possible. - -The other half of the cost model is context-window economics. A single Claude -Code session has a finite context window, and research, exploration, and code -review all produce far more raw tokens than anyone needs to actually read. -Delegating that work to subagents — `researcher`, `Explore`, `reviewer` — keeps -only their ~500-1K token *summaries* in the main thread, while the 10-50K tokens -of raw search results, file contents, and diffs stay contained in the subagent -that produced them. A full `/design` → `/build` → `/ship` cycle costs roughly -5-10K tokens in the main context; doing the same research and review inline -would cost 50K+ and degrade quality as the window fills. - -## 2. The workflow +# cw — a Claude Code workflow plugin -``` -/design → research + draft + task breakdown + review loop - ↓ (checkpoint 1 — /design exits plan mode itself, provisionally, then writes - the approved artifacts into docs/plans//; you approve there, after - the write — /build is still the real go/no-go) -/build [] → implement via subagents, one atomic commit per task - (plus a `docs():` artifacts commit, not - necessarily leading, when a project design copy - was promoted) - ↓ (checkpoint 2 — you approve the commit series) -/ship → verify commits, quality gate, push, open PR - ↓ (offered, optional) -/compound → propose durable lessons back into CLAUDE.md / rules +This repo *is* the Claude Code plugin `cw`: six skills, five agents, three +hooks, three rule files, one test runner, and CI. It implements a +`/cw:design` -> `/cw:build` -> `/cw:ship` pipeline — research-grounded +planning, delegated implementation with one atomic commit per task, and a +verified, gated release — plus `/cw:compound` to feed lessons back into your +own project's rules. See `WORKFLOW.md` for the full pipeline narrative and +`rules/orchestration.md` for the model-routing table. + +## Requirements + +- **Claude Code >= 2.1.269** — the version this plugin was built and tested + against (plugin agent-frontmatter parsing, `claude plugin eval`). +- **git** — for the workflow's own commits and branch checks. +- **jq** — used by every hook. Without it, `protect-branches.sh` and + `protect-secrets.sh` each print a warning to stderr and stand down (exit 0, + no enforcement) rather than block your session. +- **A session in auto mode or `acceptEdits` for `/cw:build`** — a plugin + agent cannot grant itself a permission mode, so the implementer subagents + need the session already in one of these modes to write without a prompt + per edit. + +## Install + +Three ways to load this plugin, in order of how much you intend to edit it. + +### (a) In place — for editing the plugin itself + +```bash +ln -s /path/to/your/checkout "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/skills/cw" ``` -Two human checkpoints are **non-negotiable and not configurable**: after design, -and before a PR opens. They exist at exactly the two points where a wrong turn is -otherwise expensive to unwind — before any code gets written, and before anyone -outside the loop sees the result. Every other step in the pipeline can retry, -escalate, or auto-resolve itself; these two cannot, by design. - -## 3. Model routing - -Every role is pinned to a **public alias** (`opus`, `sonnet`, `haiku`) in -`rules/orchestration.md`, never a dated or context-window-tagged model ID — the -routing table is the single place model choice lives, so an alias's underlying -model can change without touching every skill and agent file that references it. - -The routing principle is **route up for hard work**: Sonnet → Opus is a better -$/quality trade than Haiku → Sonnet when the task is genuinely hard (schema -design, cross-cutting review, direction judgment). Down-tiering to Haiku is for -bulk, read-only, mechanical fan-out — codebase exploration, not implementation. - -Parallel subagent fan-out (workflows) is reserved for **read-heavy work at -roughly ≥5 parallel agents** — research, codebase mapping, review panels. Below -that threshold, plain sequential or small-batch subagent calls are simpler and -just as fast. Implementation never runs naive-parallel: tasks are partitioned by -disjoint file ownership (`files_owned` in `-tasks.md`) so independent tasks -can run in parallel without merge conflicts, while dependent tasks stay -sequential. - -## 4. Failure modes that shaped it - -A few concrete failure modes are baked into the design, not just aspirational: - -- **`NO_VERDICT` is not `NEEDS_WORK`.** A reviewer that returns no parseable - verdict at all (silence, malformed JSON) is a distinct failure state from one - that reviewed the code and found problems. Conflating them either burns a - fix-iteration on nothing, or worse, quietly treats a review that never - happened as a review that passed. The fix: retry once with a fresh reviewer - instance, then escalate to a human — never loop on it, never guess. -- **Ground truth over agent testimony.** An implementer's own exit report is - evidence, not proof. Before any reviewer is spawned, the orchestrator - independently re-runs the task's verification command and checks `git log` - for the claimed commit — an implementer that reports success on a task that - didn't actually commit, or whose tests don't actually pass, is caught before - it reaches review, not after. -- **Counter-model review.** The reviewer for a task is always the model tier - the implementer *didn't* use — Opus reviews Sonnet's work and vice versa. - Reusing the same model for implementation and review correlates its blind - spots with itself. -- **Hooks as executable guardrails, not advisory text.** CLAUDE.md conventions - get followed roughly 70% of the time in practice; a `PreToolUse` hook that - exits 2 gets followed 100% of the time, because it isn't a suggestion. Two of - the hooks in this repo exist because of specific upstream Claude Code - behavior: `orchestrator-delegate-guard.sh` works around a case where a - blocked tool call can end the turn instead of prompting a delegate spawn - (see [anthropics/claude-code#51609](https://github.com/anthropics/claude-code/issues/51609)), - and `skills/build/SKILL.md` notes a related known issue where a sentinel - block doesn't self-heal into automatic delegation - ([anthropics/claude-code#24327](https://github.com/anthropics/claude-code/issues/24327)) — - in both cases the mitigation is to treat the block itself as the cue to act, - rather than assume the platform will recover on its own. - -## 5. Redaction note - -This is a sanitized export of a real, daily-driver `~/.claude` configuration — -not a from-scratch example. Omissions are deliberate, not incomplete coverage. -Redacted categories: - -- **Employer/client paths and names** — absolute paths, project codenames, and - any client-identifying strings from the source machine. -- **Personal data** — email addresses, account identifiers, and anything tied - to a specific individual. -- **Personal permission entries** — the source `settings.json` allow-list - accumulated project-specific paths and a long `WebFetch` domain trail; the - shipped `settings.example.json` replaces it with a short, generic example set. -- **Removed safety-toggle overrides** — the source config enabled several - local convenience flags (skipped permission prompts, disabled workflow - warnings, plugin toggles) that weaken default safety behavior for a specific - trusted machine. None of those are appropriate defaults for someone else's - environment, so they are excluded entirely rather than carried over. -- **One project-specific skill excluded** — a `/deep-research` skill existed in - the source config but isn't included here; `WORKFLOW.md` and `skills/search/` - have been edited so nothing dangling references it. - -## 6. Quick Start (clone-and-use) +Claude Code loads any folder under a skills directory that has a +`.claude-plugin/plugin.json` as a plugin named `cw@skills-dir` — no +marketplace, no install step. `SKILL.md` edits apply immediately; reload +agents and hooks with `/reload-plugins`. + +This is the least robust path: Claude Code's auto-update has been reported to +silently remove symlinks under the config dir +([issue #50052](https://github.com/anthropics/claude-code/issues/50052)). If +that bites you, fall back to a real directory instead of a symlink — move +your checkout itself under `/skills/cw`, and symlink *back* from +wherever you actually edit (your normal projects directory, an IDE workspace, +etc.) to that real location. + +### (b) Marketplace — the reliable path for adopters ```bash -git clone https://github.com//claude-code-setup.git -cd claude-code-setup -claude +claude plugin marketplace add victorkzam/claude-code-setup +claude plugin install cw@claude-code-setup ``` -When Claude Code opens inside the clone for the first time, it shows a **trust -dialog** for the folder. **Accept it.** Trusting the repo is what gates access -to its `.claude/` directory — until you accept, the repo-scoped `/setup` skill -and its pre-approved read-only commands (`check.sh`, the `--dry-run` forms of -the install/merge scripts) aren't available to the session at all. This is a -one-time, per-directory Claude Code trust decision, not something this repo -configures. +This installs a copy into +the plugin cache at `~/.claude/plugins/cache/claude-code-setup/cw//` (the +version directory changes on every `claude plugin update cw@claude-code-setup`), +independent of any local checkout. -Once trusted, type: +### (c) Trial — no install at all +```bash +claude --plugin-dir /path/to/your/checkout ``` -/setup + +Loads the plugin for that session only. + +## Commands + +| Command | What it does | Claude may invoke it on its own? | +|---|---|---| +| `/cw:design ` | Research-grounded design; ends in one approved plan file | Yes — description-triggered | +| `/cw:build [continue []]` | Orchestrates implementation via subagents, one commit per task | No — manual only | +| `/cw:ship [title]` | Verifies the commit series, runs the gate, pushes, opens the PR | No — manual only | +| `/cw:compound [range]` | Captures lessons from a shipped change into CLAUDE.md/rules | No — manual only | +| `/cw:search [--quick\|--deep] ` | Multi-source web research with citations | Yes — description-triggered | +| `/cw:google-workspace` | Google Docs/Drive routes and dead ends playbook | Yes — description-triggered | + +`/cw:build`, `/cw:ship`, and `/cw:compound` are marked +`disable-model-invocation: true` deliberately — they change files, branches, +or open PRs, so they only run when you type the command. + +## Agents + +| Agent | Model | Role | +|---|---|---| +| `cw:researcher` | sonnet | Web research, read-only | +| `cw:implementer` | sonnet (opus per-task for hard work) | Writes code, makes the task's commit | +| `cw:reviewer` | opus | Reviews an implementer's diff, read-only | +| `cw:design-reviewer` | opus | Doc/codebase fidelity review of a design draft | +| `cw:direction-reviewer` | opus, effort xhigh | Premise/direction review, once per design | + +`/cw:design` also spawns the built-in `Explore` agent with `model: haiku` on +each call; the plugin ships no agent by that name — its agents load under the +`cw:` prefix. To keep every session's exploration on haiku, add a user-scope +override at `~/.claude/agents/Explore.md`; it replaces the built-in prompt +with yours, so keep it short and read-only: + +```markdown +--- +name: Explore +description: Fast, read-only codebase exploration. Locates files, symbols and patterns; reports paths and line numbers. +model: haiku +tools: Read, Glob, Grep +--- +Locate what the request names with Glob and Grep, read only the ranges you +need to confirm a finding, and report file paths with line numbers. Do not +modify anything. ``` -`/setup` walks a **preflight → install → merge → handoff** flow -(`.claude/skills/setup/SKILL.md`). It runs a dry-run and shows you a diff -before every write, and asks for explicit consent before anything actually -changes your `~/.claude` config — nothing is written silently. Differing files -are skipped by default per category (agents/hooks/rules/skills); you choose -keep-vs-overwrite per category. `settings.json` and `CLAUDE.md` are merged one -at a time, each behind its own diff-then-consent step. - -> [!WARNING] -> **Never clone this repo directly into `~/.claude`, and never point -> `CLAUDE_CONFIG_DIR` at this clone.** The scripts refuse to install a repo -> onto itself (a source-equals-destination guard checks for exactly this), but -> don't rely on that guard — treat the clone and your Claude config dir as two -> separate locations, always. The scripts honor `CLAUDE_CONFIG_DIR` as an -> override for the config dir they install into/read from (default -> `~/.claude`); set it if your Claude Code config lives somewhere non-default. - -## 7. Standalone install (no LLM, run the scripts directly) - -If you'd rather not run `/setup` conversationally — or you're scripting an -install — the four scripts it orchestrates can be run by hand, in this order. -**Run them with `bash`, not `sh`** — they're bash scripts (`set -euo pipefail`, -bash-specific idioms) and will fail or behave incorrectly under a POSIX `sh`: +## A profile CLAUDE.md + +A profile's `CLAUDE.md` is deliberately short — an identity line and two +imports for the process rules this plugin ships: + +```markdown +# Your profile +Profile: acme +@/rules/workflow.md +@/rules/orchestration.md +``` + +Stack preferences (language conventions, framework choices) belong in your +*project* `CLAUDE.md` files, not in this profile file — this one is workflow +process, not stack opinion. + +The import path depends on how you installed: + +- **(a) in place / (c) trial** — import from your checkout directly: + `@/rules/workflow.md`. +- **(b) marketplace** — print the installed path with `claude plugin list --json | jq -r + '.[] | select(.id=="cw@claude-code-setup") | .installPath'` and import + `@/rules/workflow.md`; the path changes on every update, so re-check it + after updating, or keep a separate throwaway clone just for stable import paths. + +This plugin also ships `rules/browser.md`; import it the same way (optional) +when you want Claude in Chrome browser-control conventions in your profile. + +Also set `plansDirectory: docs/plans` in your settings so `/cw:design`'s plan +mode writes the plan file into the project instead of the default location. + +## Extra profiles + +Run more than one Claude Code identity (work vs. personal, or one per client) +with `CLAUDE_CONFIG_DIR`: ```bash -bash scripts/check.sh # preflight -bash scripts/install.sh --dry-run --diff # see the plan first -bash scripts/install.sh # real install (prints a backup-dir path — save it) -bash scripts/merge-settings.sh --dry-run # see the settings.json diff -bash scripts/merge-settings.sh --apply --backup-dir -bash scripts/merge-claude-md.sh --dry-run # see the CLAUDE.md diff -bash scripts/merge-claude-md.sh --apply --backup-dir +alias claude-acme='CLAUDE_CONFIG_DIR=$HOME/.claude-acme claude' ``` -Thread the same `--backup-dir ` (captured from `install.sh`'s first -`CCS-STATUS:backup-dir:` line) into every later `--apply`/`--force` call, -so the whole install shares one backup run dir and one receipt. +An alias survives GUI launchers better than a one-off shell export. List the +mapping between project paths and config dirs in `~/.claude-profiles`, one +per line, `|`, `#` comments allowed: -## 8. Verify the install +``` +~/work/acme|~/.claude-acme +~/side-projects|~/.claude-personal +``` + +The `profile-check.sh` `SessionStart` hook reads this file and reports a +`wrong profile: ...` notice if the active config dir doesn't match the +mapped one for your current directory, and a `missing import: ...` notice +for any `@import` line in `CLAUDE.md` whose target doesn't exist. + +## settings.example.json -1. **Restart Claude Code** — hooks and skills load at session start, so a - fresh install/merge only takes effect after a restart. -2. Run: +Use `settings.example.json` as a starting point, not a drop-in replacement — +copy it to `settings.json` and adapt it. It sets the top-level `model`, +`defaultMode: "auto"`, `effortLevel: "high"`, `plansDirectory: "docs/plans"`, a +short generic `permissions.deny`/`allow`/`ask` set, `autoMode.allow: +["$defaults"]`, and `enabledPlugins` for the official TypeScript, Python, and +Swift LSP plugins from the `claude-plugins-official` marketplace. It carries no +`hooks` key — this plugin registers its own hooks, and a plugin hook and a +settings hook with the same command both fire, so don't add them again in +`settings.json`. - ```bash - bash scripts/check.sh --post - ``` +**What to adapt**: the `permissions.allow`/`deny` lists for your own +workflow, the model alias mappings in `rules/orchestration.md` if you have +different tier preferences, and the identity line in your profile +`CLAUDE.md`. **What to keep as-is**: the workflow rules in +`rules/workflow.md`, the checkpoint semantics, and the hooks. - to confirm the managed artifacts landed under your config dir. -3. Run **`/hooks`** and confirm the managed hook entries appear. +## Kill switch + +```bash +claude plugin disable cw@skills-dir # install path (a) +claude plugin disable cw@claude-code-setup # install path (b) +``` -## 9. Updating +Turns all three hooks off at once. This is also the answer for a repo that +pushes to `main` by convention — `protect-branches.sh` has no opt-out +environment variable by design, so disabling the plugin is the supported +escape hatch, not a bypass flag on the hook itself. + +### What the branch guard does + +`protect-branches.sh` reads the text of each Bash command, splits it on shell +separators, strips quotes and backslashes so nested `sh -c`/`bash -c`/`eval` +strings and a backslash-escaped `git` are inspected too, and tracks +`cd`/`pushd` and `git switch`/`checkout` earlier in the same command. It +blocks a `git push` whose destination is `main`/`master` (an explicit +refspec, the current branch, or an upstream on main), plain force pushes +(`--force`, `-f`, `+ref`), and `--all`/`--mirror`; lease pushes +(`--force-with-lease`, `--force-if-includes`) to a feature branch pass. When +a `cd` or branch change earlier in the command can't be resolved from the +text (a variable, `cd -`, a path checkout), a bare `git push` after it is +blocked with a hint to use an explicit refspec. A `(...)`, `$(...)`, or +backtick-quoted subshell is its own scope for that tracking, restored when +it closes, so a `cd` or checkout inside one can't leak into a push outside +it; a plain checkout inside the scope leaves the branch unknown on close +instead of silently reverting. + +It is a guardrail against the agent's own accidental pushes, not a sandbox: a +command held in a variable, `xargs`-fed refspecs, wrappers and aliases not +named `git`, `git -c k="v w"` before push, and `gh api` calls are out of scope, +and a line of prose that spells out a push to the default branch inside a +command is blocked as if it were the command itself — keep such text in a file +instead. + +## Migration from the old installer + +If you previously installed this project's files directly into `~/.claude` +rather than as a plugin, the old manifest put five skills (`build`, +`compound`, `design`, `search`, `ship`), six agents, five hooks and +`rules/orchestration.md` there. To migrate: + +- Delete the user-scope copies of the five skills, the five hooks and + `rules/orchestration.md`, and remove the five `hooks` entries from + `settings.json` — a plugin hook and a settings hook that share the same + command both fire, so leaving the old entries in place double-runs them. + Three of the old hooks (`design-scope-guard.sh`, + `orchestrator-delegate-guard.sh`, `syntax-check.sh`) have no plugin + replacement: 1.0.0 retires them on purpose. +- Delete the five agents the plugin now ships under the `cw:` prefix, but keep + `agents/Explore.md` if you had it: a user-scope agent named `Explore` + overrides the built-in one and keeps its own `model: haiku`, and this + plugin ships no agent by that name (`/cw:design` pins haiku per call + regardless). +- Replace any workflow rules pasted into your profile `CLAUDE.md` with the two + imports shown above, and remove any other stray copies of the old layout. + +Verify with `claude plugin list` (one `cw` entry), by checking that the +`skills/`, `agents/` and `hooks/` folders under your config dir hold none of +the old files (apart from `agents/Explore.md` if you kept it), and, inside a +session, with `/hooks`: each event lists the plugin's hook once, with no copy +from `settings.json`. + +## `/cw:search --deep` + +The `--deep` flag hands off to the bundled `/deep-research` workflow, which +needs dynamic workflows enabled (a paid-plan feature; `disableWorkflows` +turns it off). Without that, `/cw:search` falls back to its default +multi-source mode. + +## Update and uninstall + +- **(a) in place** — `git pull` in your checkout; a symlinked install picks + it up on the next `/reload-plugins`, a real-directory install picks it up + immediately. Remove the symlink (or directory) to uninstall. +- **(b) marketplace** — `claude plugin update cw@claude-code-setup` to pull + the latest version; `claude plugin uninstall cw@claude-code-setup` to + remove it. +- **(c) trial** — nothing persists; just stop passing `--plugin-dir`. + +## Running the tests ```bash -cd claude-code-setup # your existing clone -git pull +bash tests/run.sh all ``` -Then, **from inside the clone**, run `/setup` again. Any file you've -customized since the last install surfaces as a per-category diff/prompt — -it's **skipped by default** and only overwritten if you explicitly consent; -nothing you've changed is clobbered silently. - -**Upgrading into an existing install**: because differing files are skipped by -default, an adopter who already had `~/.claude` set up before this feature -shipped won't pick up the new `design-scope-guard.sh` hook or the changed -`/design` skill automatically — `/setup`'s diff-then-consent flow treats an -existing file that differs from the new template as skip-by-default, not an -automatic overwrite. Choose overwrite at the `hooks/` and `skills/` category -prompts (or run `bash scripts/install.sh --force`) to receive both. The new -hook installs cleanly onto a fresh copy of `hooks/`; `merge-settings.sh` adds -its `PreToolUse` registration to `settings.json` during the settings merge -step, same as any other hook. - -## 10. Uninstalling - -There's no uninstall script yet (deliberately deferred — see below); removal -is manual but deterministic because every write is logged to a **receipt**. -The receipt for a given install lives at `/receipt.txt`, where -`` is a timestamped directory under -`~/.claude/backups/claude-code-setup//` (or under `$CLAUDE_CONFIG_DIR` -if you've overridden it). Each line is tab-separated: -`action path backup-path repo-sha timestamp`. - -Walk the receipt and act **per `action`**, in this order — the ordering -matters because it's what protects data that predates the install: - -- **`installed`** — the file didn't exist before `/setup`; `rm` it. -- **`overwritten`** — a file you already had was replaced; **restore it from - the backup path on that line** (do **not** `rm` it — `rm` would destroy the - original the backup exists specifically to preserve). -- **`merged`** — if the backup-path field is non-empty, same as - `overwritten`: **restore from the backup path** on that line (never `rm` - it). If the backup-path field is **empty**, the file didn't exist before - `/setup` and was created fresh by the merge — `rm` it, same as `installed`. -- **`unchanged`** — the file already matched what `/setup` would have - written, so nothing was touched; leave it alone. (Earlier runs' lines still - govern it if you ran `/setup` more than once.) -- **`skipped`** — nothing was written; leave it alone. - -If you ran `/setup` more than once (e.g. across an update), restore from the -**earliest** run's backups — that's the true pre-setup state; later runs' -backups are snapshots of an already-modified file, not the original. - -## 11. Prerequisites - -- **jq** — REQUIRED. `protect-branches.sh` and `protect-secrets.sh` fail closed - without it: they block the corresponding git operations/edits entirely rather - than silently skip the check if `jq` isn't installed. `brew install jq` / - `apt install jq`. -- **git** — obviously; also needed for `git identity` (`user.name` / - `user.email`) so the workflow's own commits (one per `/build` task, plus - `/ship`) have an author. -- **Claude Code ≥ v2.1.53** — REQUIRED. This is a security floor - (CVE-2026-33068); `check.sh` fails closed below it. -- **Claude Code ≥ v2.1.198** — RECOMMENDED, for the full feature set: the - custom `Explore` agent's model override (below this version it inherits the - session's main-thread model instead of running on `haiku`), and - session-scoped sentinel isolation in `orchestrator-delegate-guard.sh` (fully - available from ≥ v2.1.132; below that the guard falls back to a legacy - global sentinel with only a TTL as backstop). -- **gh** — the GitHub CLI, needed **only for `/ship`'s** PR creation, not for - install. Run `gh auth login` before your first `/ship`. -- **shellcheck + bats** — DEV-ONLY, for contributing to this repo's own - scripts/tests. Not required to adopt or run `/setup`. -- **context7 + exa MCP servers** — OPTIONAL. `skills/search/SKILL.md` falls - back to `WebSearch` for any angle where an MCP tool is unavailable; `/design` - and `/search` degrade gracefully without them, just with less precision - (context7's version-pinned docs, exa's semantic search). - -## 12. Troubleshooting - -- **`/setup` doesn't appear.** Confirm you accepted the folder's **trust** - dialog, and that you're running Claude Code from inside the clone (the skill - is repo-scoped, not installed globally). Then restart Claude Code once — - skill discovery has known upstream flakiness on a fresh trust grant - ([anthropics/claude-code#45956](https://github.com/anthropics/claude-code/issues/45956), - [anthropics/claude-code#43092](https://github.com/anthropics/claude-code/issues/43092)). - If it still doesn't appear, `bash scripts/check.sh` will surface targeted - fixes for common environment issues. -- **`check.sh --post` shows a `FAIL:` line.** A managed artifact is missing - from your config dir — re-run `/setup` to install it. -- **`check.sh --post` shows a `WARN: ... ignore if you declined this merge`.** - This is informational, not an error — it means you chose not to merge - `settings.json` or `CLAUDE.md`, and the check is just confirming that. -- **A hook is blocking legitimate work.** See the `protect-secrets` note - below. - -**`protect-secrets` self-lockout note**: once installed, the `protect-secrets` -hook blocks Claude Code itself from writing/editing files matching secret -patterns (`.env`, `*credentials*`, `*.pem`, SSH/AWS/GCP key paths, etc.) — and -it applies in **every** project you use Claude Code in afterward, not just this -one, because it's wired into your global `~/.claude/settings.json`. If it -blocks something you legitimately need to edit, that settings file is yours: -edit or remove the hook entry directly. Re-running `/setup` later will offer -to re-merge it, but it will never force the merge back in without your -consent. - -**Plugin packaging (future work)**: a Claude Code plugin is a plausible future -distribution mechanism for this setup. Today's clone-and-use + `/setup` -approach was chosen deliberately instead — current plugin docs impose -verbatim-file limits that don't fit this repo's merge-not-clobber model for -`settings.json`/`CLAUDE.md`. - -**Backups accumulate**: backup run directories under -`~/.claude/backups/claude-code-setup/` are never auto-deleted (there's no -pruning script yet). They're cheap to keep and are what makes uninstall -deterministic, but feel free to delete old ones by hand once you're confident -you won't need to restore from them. - -## 13. What to adapt vs keep - -**Yours to replace**: the `Identity` and `Stack Preferences` blocks in -`CLAUDE.md` (marked "example — replace with your own"), the generic example -`permissions.allow` list in `settings.example.json`, and the model alias -mappings in `rules/orchestration.md` if you have different tier preferences. - -**The transferable system**: the `/design` → `/build` → `/ship` workflow rules -and mode transitions, the model routing table's *principles* (public aliases, -route-up-for-hard-work, the ≥5-agent workflow threshold), the review-loop -semantics (`NO_VERDICT` vs `NEEDS_WORK`, counter-model review, ground-truth -verification), and the hooks — these are the parts built from real failure -modes and are worth keeping close to as-is. - -## 14. Project-local design docs (adopter notes) - -`/design` promotes its approved artifact set (`-design-draft.md`, -`-tasks.md`, `-research-*.md`) out of `~/.claude/plans/` and into -the adopting project's own `$ROOT/docs/plans//`, so a design lives with -the code it describes and is reviewable from a phone/synced Files app before -`/build` runs — see `WORKFLOW.md`'s Mode Transitions table for the full -step-by-step sequence. A few things to know if your project isn't a typical -git repo: - -- **Gitignored `docs/`** — if `docs/` (or specifically `docs/plans/`) is - gitignored in your project, the promotion write in `/design`'s guarded - window and `/build`'s `docs(): add design + research artifacts` - commit (not necessarily the leading commit in the series) both skip, - explicitly and by design — artifacts stay in the plans dir - (`~/.claude/plans/`, or `$CLAUDE_CONFIG_DIR/plans/` if you've overridden - it) as the canonical copy, exactly how `/design` behaved before this - feature. -- **A published `docs/` site** (Docusaurus, mkdocs, GitHub Pages, etc.) — if - your project already builds `docs/` into a live site, promoting WIP planning - artifacts into `docs/plans//` would land them inside that published - tree. Relocate the target directory by editing the write logic in - `skills/design/SKILL.md`'s Step 6 — and the matching path patterns in - `hooks/design-scope-guard.sh`, or the write will be blocked — to a directory - outside your published tree. -- **Forking this workflow repo itself** — a fork of `claude-code-setup` - behaves like any other adopting project for design routing: unless `$ROOT` - resolves to your actual `${CLAUDE_CONFIG_DIR:-$HOME/.claude}`, artifacts - promote into the fork's own `docs/plans//` like anywhere else. The - meta-tooling exception (artifacts stay in the plans dir) applies only when - you're editing your live `~/.claude` config in place. -- **Upgrading an existing install** — see [Updating](#9-updating): this - feature ships a new hook and a changed `/design` skill, both skipped by - default on an already-customized config unless you explicitly choose to - overwrite. +Runs hook behavior, file-size budgets, a cross-file phrase-duplication +check, the `settings.example.json`/`tests/settings-keys.txt` cross-check, +and a per-commit trailer check on `main..HEAD` (skipped, and reported as +such, only when neither `main` nor `origin/main` resolves). +Optionally set `CW_SCAN_PATTERNS=` to also scan +the tracked tree for private strings you've defined — this is empty by +default and off unless you set it. `.gitattributes` marks `docs/plans/**` as +`linguist-generated`, so design documents are collapsed by default in GitHub +diffs and excluded from language statistics. + +## Changelog + +### 1.0.0 + +First release as a Claude Code plugin. Converts the prior clone-and-use, +conversationally-installed configuration into a proper plugin (`cw`): a +plugin manifest and marketplace entry, lean skill and agent prompts, hooks +registered through `hooks/hooks.json` (including a new `profile-check.sh` +`SessionStart` hook), a single `tests/run.sh` test runner replacing the old +per-script tests, and CI running the same checks on every push and PR. diff --git a/WORKFLOW.md b/WORKFLOW.md index ba3eea2..8a57c62 100644 --- a/WORKFLOW.md +++ b/WORKFLOW.md @@ -1,298 +1,130 @@ -# Agentic Workflow Harness - -Documentation for the `/design` -> `/build` -> `/ship` workflow. Installed at `~/.claude/` (user-level, works in every project). - ---- - -## Quick Start - -**Install**: clone the repo, open Claude Code in it, then run `/setup` — the -setup skill checks prerequisites, installs agents/skills/hooks/rules, and merges -`settings.json`/`CLAUDE.md` with your existing config (dry-run + consent at each -step; see the README's Quick Start section for the full flow). - -**Use**: - -``` -/design - -> iterates with research until you approve - -/build - -> implements via subagents, reviews, iterates up to 3x - -> stops for your approval - -/ship [optional PR title] - -> commits, pushes, creates PR -``` - -Two human checkpoints: **after design** (you approve the plan), **before PR** (you approve the code). - ---- - -## Architecture - -| Primitive | What | Where | -|---|---|---| -| CLAUDE.md | Always-on advisory rules | `~/.claude/CLAUDE.md` | -| `/design` | Research-grounded planning skill | `~/.claude/skills/design/SKILL.md` | -| `/build` | Implementation orchestrator skill | `~/.claude/skills/build/SKILL.md` | -| `/ship` | Commit + PR automation skill | `~/.claude/skills/ship/SKILL.md` | -| `/compound` | Post-ship lesson capture into CLAUDE.md/.claude/rules (offered by `/ship`) | `~/.claude/skills/compound/SKILL.md` | -| `/search` | 3-angle web research skill | `~/.claude/skills/search/SKILL.md` | -| researcher | `sonnet` agent, read-only, web tools | `~/.claude/agents/researcher.md` | -| implementer | `sonnet` default / `opus` per-call, writes code + atomic commit, no push | `~/.claude/agents/implementer.md` | -| reviewer | `opus` agent, read-only, runs tests | `~/.claude/agents/reviewer.md` | -| design-reviewer | `opus` agent, read-only, doc/codebase fidelity (loops until findings converge, escalates after 5) | `~/.claude/agents/design-reviewer.md` | -| direction-reviewer | `opus` agent (effort xhigh), read-only, premise/direction (once) | `~/.claude/agents/direction-reviewer.md` | -| Branch protection | Hook: blocks push *to* main/master + force push (by destination, not branch name) | `~/.claude/hooks/protect-branches.sh` | -| Secrets protection | Hook: blocks edits to .env/keys/credentials/secrets (broadened) | `~/.claude/hooks/protect-secrets.sh` | -| Delegate guard | Hook: session-scoped; blocks orchestrator source edits while `/build` active | `~/.claude/hooks/orchestrator-delegate-guard.sh` | -| Design scope guard | Hook: session-scoped; confines `/design`'s post-approval Write\|Edit calls (not a hard filesystem guarantee) to design artifact paths (`docs/plans/` — where `/design` writes both its design draft and research files — `docs/research/`, a separately allowlisted research-output path not written by `/design`, plans dir), sentinel-armed, same trust class as the delegate guard | `~/.claude/hooks/design-scope-guard.sh` | -| Syntax check | Hook: multi-language (py/js/sh/json/swift), surfaces errors | `~/.claude/hooks/syntax-check.sh` | - ---- - -## Workflow Detail - -### Phase 1: `/design` - -**What it does**: Research-grounded feature design. Spawns researcher subagents to investigate unknowns, then synthesizes findings into a plan. - -**How it works**: -1. Reads project CLAUDE.md + explores codebase -2. Identifies unknowns and assumptions -3. Spawns grounding subagents in parallel: `Explore` (codebase map, **`haiku`** — fan-out navigation) + two `researcher` (`sonnet`, 3-angle methodology) - - Only structured summaries return to main context (~500-1K tokens each) - - Raw research (10-50K tokens) stays in subagent context -4. Synthesizes a design draft **and** `-tasks.md` (adaptive task count — 1 to many, never a fixed range; each task: disjoint files, assigned model, verification, one atomic Conventional commit — or `commit: none` for unversioned/external targets, verification-only) -5. **design-reviewer** loop (fresh context each pass, continues until findings converge, escalates after 5 iterations) for consistency/codebase-fit/best-practices, then **direction-reviewer** once (`opus`, premise/problem-fit) -6. `/design` calls **`ExitPlanMode` itself** — provisional and skill-invoked, not the real go/no-go; approving here only continues the same turn into the guarded write below (rejecting stays in plan mode and re-runs the loop) -7. **Guarded promotion write** (execute mode, same turn; session-scoped sentinel via `design-scope-guard.sh`) — writes the approved artifact set into `$ROOT/docs/plans//`, unless `$ROOT` is the config repo itself or `docs/plans/` is gitignored there, in which case artifacts stay in the plans dir -8. **STOPS for your approval** — the real checkpoint, now *after* the write, on the project copy; presents both verdicts + the artifact path - -**Iteration**: feedback given before the provisional `ExitPlanMode` approval iterates entirely on the plans-dir copies (regenerate design + `-tasks.md`, re-run the review loop + direction review). Feedback given at the post-write checkpoint re-arms the sentinel and iterates on the project copies in `docs/plans//` instead — the plans-dir drafts are inert scratch by then. Either path stops again at a single checkpoint. - -**Context impact**: Research stays out of main context. Only summaries enter. - -### Phase 2: `/build` - -**What it does**: Orchestrates implementation using subagents. The main agent NEVER writes code and NEVER re-decomposes — it consumes `-tasks.md`, delegates, and reviews. Runs in execute mode. - -**How it works**: -1. **Pre-flight**: Resolves the tasks file — project copy first (`$ROOT/docs/plans//-tasks.md`), falling back to the legacy `~/.claude/plans/` (arg / newest-by-mtime-with-confirm) — creates feature branch, commits a promoted project design copy as a `docs(): add design + research artifacts` commit, then writes the session-scoped sentinel -2. **Consume tasks**: Executes exactly the tasks `-tasks.md` defines — adaptive count (1 to many), in `depends_on` order, independent ones in parallel -3. **Implement**: Spawns a context-pinned **implementer** per task (only its task entry + relevant excerpt); the implementer makes **one atomic Conventional commit per task** (co-author trailer; no push) — except `commit: none` tasks (unversioned/external targets), which are verification-only -4. **Review**: Spawns **reviewer** subagent that reads files FRESH from disk and checks commit atomicity (no implementer bias) -5. **Iterate**: If reviewer finds issues: - - Iteration 1-2: Spawns NEW implementer with reviewer's feedback - - Iteration 3: Escalates to you with full context -6. **STOPS for your approval** with summary of what was built, test results, and manual test instructions - -**Context impact**: All code writing and reviewing happens in subagents. Main context stays clean. - -### Phase 3: `/ship` - -**What it does**: Verifies the commit series, updates product docs, pushes, creates PR, then offers `/compound`. Runs in execute mode. - -**How it works**: -1. Verifies NOT on main (refuses if so) -2. **Verifies** the atomic per-task Conventional commit series (does NOT squash or author a catch-all commit; stops on stray uncommitted changes) — a `docs():` artifacts commit is exempt from the one-commit-per-task accounting -3. Updates **product** docs (README, ARCHITECTURE, CHANGELOG) if needed — distinct from `/compound`'s process-rule capture -4. Quality gate must pass; opens PR only after the feature is fully built AND green -5. Pushes branch, creates PR via `gh pr create`, then **offers `/compound`** (HITL; never commits process-rule edits into this PR) - -**Safety**: Never pushes to main, never force pushes, never commits secrets, never squashes the per-task series. - ---- - -## Recommended Sequence - -``` -/design → research + draft + -tasks.md + design-reviewer loop + direction-reviewer - ↓ (/design exits plan mode itself, provisionally, then writes the approved - artifacts into docs/plans// — you approve there, after the write; - /build is still the real go/no-go) -/build [] → consume tasks.md; one atomic commit per task; reviewer - ↓ (you approve the commit series) -/ship → verify series, product-doc updates, quality gate, push, PR - ↓ (offered, optional) -/compound → propose CLAUDE.md/.claude/rules lessons (HITL; never committed into the PR) -``` - -Two non-negotiable human checkpoints: **after design**, **before PR**. `/compound` is a -separate, user-driven step chained from `/ship` — it is never merged into `/ship` and -never lands process-rule edits inside the feature PR. - -## Mode Transitions - -`/design` is a **hybrid**: plan mode for its research/draft/review loop (Steps 0-5), -then a short guarded execute-mode window (Step 6) that writes the approved artifacts -into the project, followed by the real human checkpoint (Step 7) — the checkpoint now -comes *after* that write, not before it. - -| Stage | Mode | Notes | -|---|---|---| -| `/design` Steps 0-5 (research, draft, review loop) | **plan** | Documented exception: may write only `~/.claude/plans/-*.md` (judgment call, bounded to that dir) | -| `/design` Step 5 `ExitPlanMode` | — | **Provisional, skill-invoked.** `/design` calls `ExitPlanMode` itself; approving here is administrative — it only continues the same turn into Step 6, it is not the go/no-go | -| `/design` Step 6 (execute, same turn) | **execute**, guarded | `design-scope-guard.sh`'s session-scoped sentinel confines Write\|Edit calls (not a hard filesystem guarantee) to `docs/plans//` (where `/design`'s own research files land, alongside the design draft + tasks), `docs/research/` (a separately allowlisted research-output path, not written by `/design`), and the plans dir while the approved artifact set is promoted into `$ROOT/docs/plans//` (also `~/.claude/plans/-*.md` during this window) | -| `/design` Step 7 checkpoint | — | **The real human checkpoint**, now after the promotion write, on the project copy. You approve or iterate here — `/build` remains the true go/no-go | -| `/build`, `/ship` | **execute** (default/acceptEdits) | `disable-model-invocation: true`; run explicitly after approval | - -The shipped template sets `defaultMode: "auto"` — a convenience key, deliberately -withheld from merges into existing configs. The plan-first guarantee comes from -`/design`'s Steps 0-5 running in plan mode and Step 6's write window being confined by -`design-scope-guard.sh`, not from a global `"plan"` default. - -## Model Usage Map - -Roles are pinned to **aliases**, never dated model IDs — this table is a summary -for orientation only. The authoritative routing table lives in -`~/.claude/rules/orchestration.md`; if the two ever disagree, that file wins. - -| Role | Model | Tier rationale | -|---|---|---| -| Main thread / `/design` orchestrator | `opus` | Orchestration / architecture | -| `/design` `Explore` subagent | `haiku` | Fan-out codebase navigation | -| `researcher` | `sonnet` | Research | -| `design-reviewer` | `opus` | Doc/codebase fidelity | -| `direction-reviewer` | `opus` (effort `xhigh`) | Premise/direction judgment | -| `implementer` | `sonnet` → `opus` per-call | Implementation | -| `reviewer` | `opus` | Code review | -| `/compound` subagent | `sonnet` | Lesson extraction | - -Effort: `opus` agents use `xhigh` (Opus's recommended default, matching the global -`effortLevel`); `sonnet` agents keep `high` (Sonnet has no `xhigh` — `high` is its -top balanced level). - ---- - -## Agents - -### researcher (`sonnet`) -- **Purpose**: Web research with structured findings and citations -- **Tools**: Read, Glob, Grep, WebSearch, WebFetch, exa, context7 -- **Cannot**: Write files, edit files, run bash commands -- **Preloads**: `/search` skill (3-angle methodology) -- **Output**: Structured findings with URLs, confidence levels, consensus, gaps - -### implementer (`sonnet` default / `opus` per-call) -- **Purpose**: Implement one task; make exactly one atomic Conventional commit for it — or, for `commit: none` tasks (unversioned/external targets), verification-only with no commit -- **Model**: `sonnet`; the design assigns `opus` per-call for >5-file / long-horizon / cross-cutting tasks -- **Tools**: Read, Write, Edit, Glob, Grep, Bash, context7 -- **Cannot**: `git push`, `gh pr create`, checkout main (commits ARE allowed and required) -- **Config**: `permissionMode: acceptEdits`, `effort: high`, `memory: project` -- **Output**: Files created/modified, the task's commit, design deviations, test results - -### reviewer (`opus`) -- **Purpose**: Code review for quality, correctness, conventions, commit atomicity -- **Tools**: Read, Glob, Grep, Bash (for tests) -- **Cannot**: Write, Edit, push, delete -- **Config**: `memory: project` -- **Output**: PASS/NEEDS WORK verdict, issues list, test results, design adherence - -### design-reviewer (`opus`) -- **Purpose**: Pre-code fidelity review — consistency, codebase-fit, best-practices, research-ignored (loops until findings converge, escalates after 5 iterations) -- **Tools**: Read, Glob, Grep, web/exa/context7; **Cannot**: Write, Edit -- **Output**: Strict JSON verdict (PASS/NEEDS_WORK) + issues + suggested_fixes - -### direction-reviewer (`opus`, effort xhigh) -- **Purpose**: Premise/problem-fit review — "is this plan aimed at the right outcome" (runs once, after the design-reviewer loop; no auto-loop) -- **Tools**: Read, Glob, Grep only (no web — research already happened); **Cannot**: Write, Edit -- **Output**: Strict JSON verdict (PASS/REDIRECT) + concerns + recommended_reframe - -See `~/.claude/rules/orchestration.md` for the authoritative role → model routing table. - ---- +# Workflow + +`cw` is a Claude Code plugin implementing a `/cw:design` -> `/cw:build` -> +`/cw:ship` pipeline: research-grounded planning, delegated implementation with +one atomic commit per task, and a verified, gated release. `/cw:compound` +closes the loop by feeding lessons back into project rules. + +## Roles + +| Who | Does | +|---|---| +| You | Approve the design, approve the commit series, review the PR | +| The orchestrating session (main thread) | Runs `/cw:design`, `/cw:build`, `/cw:ship`; never writes application code itself | +| `cw:researcher` (sonnet) | Web research with citations, read-only | +| `cw:implementer` (sonnet, opus for hard tasks) | Implements one task, makes its commit | +| `cw:reviewer` (opus) | Reviews an implementer's diff, read-only | +| `cw:design-reviewer` (opus) | Checks a draft design against the codebase and current docs, read-only | +| `cw:direction-reviewer` (opus, effort xhigh) | Checks the design targets the right problem, read-only | + +## `/cw:design ` + +Plan mode. Reads project context, spawns `Explore` (haiku) and +`cw:researcher` (sonnet) subagents in parallel to ground the plan in the real +codebase and current sources, drafts one plan file with a task list, then +loops `cw:design-reviewer` (fresh context each pass, until findings converge, +escalating after 5 iterations) followed by `cw:direction-reviewer` once. + +The skill calls `ExitPlanMode` itself when the review loop converges — that +approval only ends drafting; it is not the real checkpoint. Plan mode writes +the draft (into `docs/plans/` when the profile sets +`plansDirectory: docs/plans`, else the default plans dir); on approval the +design step moves it to `docs/plans/.md` in the repo, which +`/cw:build` then reads. + +**Checkpoint 1 (non-negotiable): you approve the plan file before anything +gets built.** + +## `/cw:build [continue []]` + +Execute mode (needs auto mode or `acceptEdits` — a plugin agent cannot grant +itself a permission mode). The orchestrating session: + +1. Resolves the plan (`docs/plans/.md`, or the folder-layout fallback), + creates the feature branch, commits the plan as `docs(): design`. +2. Reads the task list and works it in `depends_on` order, independent tasks + in parallel, never re-decomposing it. +3. Delegates each task to a fresh `cw:implementer`, scoped to only that + task's entry and its file ownership. The implementer makes exactly one + atomic Conventional commit for its task — or, for a `commit: none` task + (an unversioned or external target), verifies without committing. +4. Independently re-runs the task's own verification command and checks + `git log` for the claimed commit before trusting an implementer's report — + an implementer's exit report is evidence, not proof. +5. Spawns `cw:reviewer` — a different model tier than the implementer used — + to review the diff fresh from disk. `NEEDS_WORK` respawns a new + implementer with the feedback (up to 2 retries); a reviewer that returns + no parseable verdict at all is retried once fresh, not treated as a pass + or a fail. +6. Stops for your approval once every task's commit is in and the tasks-file + quality gate passes. + +`continue []` resumes a `/cw:build` run, skipping tasks whose commit +subject is already in `git log main..HEAD`. + +**Checkpoint 2 (non-negotiable): you approve the commit series before any +PR.** + +## `/cw:ship [title]` + +Execute mode. Refuses to run on `main`/`master`. Verifies the commit series +against the plan's task list (no squashing, no catch-all commit), runs the +project's quality gate (`bash tests/run.sh all` when this repo owns the +gate), pushes the branch, and opens the PR with `gh pr create` only once the +gate is green. Ends by offering `/cw:compound`. + +## `/cw:compound [range]` + +Optional, user-driven, never folded into `/cw:ship`. Reads what just shipped, +extracts the handful of lessons actually worth keeping, proposes edits to the +project's CLAUDE.md or rules files, and applies only what you approve. +Process-rule edits from `/cw:compound` are never committed into the feature +PR that prompted them — they are their own change. + +## `/cw:search [--quick|--deep] ` + +Cross-references Context7, Exa, and WebSearch (whichever are available; +missing MCP servers degrade an angle to WebSearch, never a hard failure) into +one structured, citation-backed answer. `--deep` hands off to the bundled +`/deep-research` workflow, which needs dynamic workflows enabled. + +## `/cw:google-workspace` + +A reference playbook, not a pipeline step: hard-won routes and dead ends for +driving Google Docs/Drive from Claude, triggered when a task needs one. + +## Rules + +`rules/workflow.md` carries the process rules above (branch policy, commit +format, checkpoints, mode transitions) and is meant to be imported by a +profile's `CLAUDE.md`. `rules/orchestration.md` carries the model-routing +table (public aliases, route-up-for-hard-work, the workflow-fan-out +threshold) and the review-loop semantics (`NO_VERDICT` vs `NEEDS_WORK`, +counter-model review, ground-truth verification). If a rule and this file +ever disagree, the rules file wins. ## Hooks -All hooks are in `~/.claude/settings.json` and `~/.claude/hooks/`. They provide 100% enforcement (vs CLAUDE.md's ~70% compliance). +Three hooks, registered by the plugin itself (`hooks/hooks.json`), fire in +every session the plugin is enabled in: | Hook | Event | What it does | |---|---|---| -| protect-branches.sh | PreToolUse (Bash, git) | Blocks pushes whose *destination* is main/master + force push; allows feature branches named like `feat/main-*` | -| protect-secrets.sh | PreToolUse (Write\|Edit) | Blocks edits to .env/.envrc, credentials, secrets, keys (.pem/.key/.p8/.pfx/.jks/.keystore), id_rsa, .aws/.ssh/.gnupg, service-account/gcp json, Config.swift | -| orchestrator-delegate-guard.sh | PreToolUse (Write\|Edit) | While `/build` active, blocks orchestrator (main-thread) source edits; **session-scoped** (`/tmp/claude-orchestrator-active.$SESSION_ID`) with TTL self-heal | -| design-scope-guard.sh | PreToolUse (Write\|Edit) | While `/design`'s Step 6 write window is active, confines Write\|Edit calls (not a hard filesystem guarantee) to design artifact paths (`docs/plans/` — where `/design` writes both the draft and its research files — `docs/research/`, a separately allowlisted research-output path not written by `/design`, the plans dir); **session-scoped** (`/tmp/claude-design-active.$SESSION_ID`), same trust class + TTL self-heal as the delegate guard | -| syntax-check.sh | PostToolUse (Write\|Edit) | Multi-language check (py/js/sh/json/swift), surfaces real errors; never blocks | -| Notification | Notification event | macOS notification when Claude needs attention (macOS-only, uses `osascript`) | - -**How hooks work**: -- `PreToolUse` hooks run BEFORE a tool executes. Exit 2 = blocked. Exit 0 = allowed. -- `PostToolUse` hooks run AFTER. Informational only. -- Hooks load at session start. **Changes require restarting Claude Code.** -- The delegate guard is session-scoped via `CLAUDE_CODE_SESSION_ID` (matches the hook-stdin `session_id`) and self-heals a stale sentinel after `TTL_MINUTES` (default 90). **Session isolation requires Claude Code ≥ v2.1.132**; below that it falls back to the legacy global path with the TTL as sole guard. -- `design-scope-guard.sh` mirrors the same session-scoped sentinel pattern, armed/disarmed by `/design` itself around its Step 6 promotion write (TTL 120 min — generous, since the sentinel only needs to survive a single short write window rather than a whole `/build` run). -- Debug: `claude --debug` | View loaded hooks: `/hooks` - ---- - -## Context Window Strategy - -The harness is designed to keep the main conversation's context clean: - -| What | Where it happens | Tokens in main context | -|---|---|---| -| Voice note / spec | User pastes | ~500 | -| Research (per question) | researcher subagent | ~500-1K (summary only) | -| Codebase exploration | Explore subagent | ~200-500 (summary only) | -| Design output | Main thread | ~2K | -| Implementation | implementer subagent | ~500 (summary only) | -| Code review | reviewer subagent | ~500 (summary only) | -| Ship / PR | Main thread | ~1K | - -**Full feature cycle**: ~5-10K tokens in main context. Without subagents, research alone can consume 50K+. - -**Tips**: -- Use `/clear` between unrelated tasks -- For large features: one session per phase -- The status bar shows context usage — watch for >70% - ---- - -## CLAUDE.md (Global Rules) - -`~/.claude/CLAUDE.md` contains always-on advisory rules: -- Feature branches only, conventional commits, co-author line -- Research-first design: check docs before making architecture decisions -- Flag unsourced decisions explicitly -- Context hygiene: use subagents for heavy output -- Stack preferences: SwiftUI async/await, Python type hints, Next.js strict TS - -These have ~70% compliance. For critical rules (branch protection, secrets), hooks provide 100% enforcement. - ---- - -## Modifying the Harness - -### Add a new hook -1. Create script in `~/.claude/hooks/` -2. Add entry to `hooks` in `~/.claude/settings.json` -3. Restart Claude Code - -### Add a new skill -1. Create `~/.claude/skills//SKILL.md` with YAML frontmatter -2. Available immediately (no restart needed) - -### Add a new agent -1. Create `~/.claude/agents/.md` with YAML frontmatter -2. Available immediately for spawning - -### Key frontmatter fields -- **Skills**: `name`, `description`, `allowed-tools` (pre-approval), `disable-model-invocation`, `argument-hint` -- **Agents**: `name`, `description`, `model`, `effort` (sets the subagent's reasoning effort tier), `tools`, `disallowedTools`, `maxTurns`, `skills`, `mcpServers`, `memory`, `permissionMode`, `color` (named colors only) - ---- - -## Future Expansions - -Deferred until 1-2 weeks of use: -- **Stop hook**: Prompt-type hook checking if Claude explained reasoning -- **SessionStart hook**: Auto-inject git status, recent commits at session start -- **Auto-format hook**: Run prettier/black/swiftformat after writes -- **`/test` skill**: Project-specific test orchestration -- **`/retro` skill**: Post-merge retrospective generation -- **Xcode MCP**: `claude mcp add --transport stdio xcode -- xcrun mcpbridge` for SwiftUI previews + diagnostics -- **XcodeBuildMCP**: Headless builds, tests, simulators via [github.com/getsentry/XcodeBuildMCP](https://github.com/getsentry/XcodeBuildMCP) - ---- +| `protect-branches.sh` | PreToolUse (Bash) | Blocks a push whose destination is main/master, and any force push | +| `protect-secrets.sh` | PreToolUse (Write\|Edit\|MultiEdit\|NotebookEdit) | Blocks writes to `.env`, credentials, keys, and similar secret paths | +| `profile-check.sh` | SessionStart | Warns if the active profile doesn't match `~/.claude-profiles`, or if a `CLAUDE.md` `@import` target is missing | + +A hook that exits non-zero is enforced, not advisory — CLAUDE.md conventions +get followed inconsistently; a `PreToolUse` hook that exits 2 blocks the call +outright. `claude plugin disable cw@` turns all three off at once. + +## Tests + +`bash tests/run.sh all` runs everything: hook behavior (`hooks`), file-size +budgets against the tracked baseline plus the `WORKFLOW.md` and +description-length caps (`size`), a cross-file phrase-duplication check +(`dedupe`), the `settings.example.json` / `tests/settings-keys.txt` +cross-check, and, if `$CW_SCAN_PATTERNS` points at a pattern file, a scan for +private strings in the tracked tree. Each subcommand also runs standalone +(`hooks`, `size`, `dedupe`, `scan`, `trailers`), and CI (`.github/workflows/ci.yml`) runs +the same `all` target on every push and PR. diff --git a/agents/Explore.md b/agents/Explore.md deleted file mode 100644 index b3fee96..0000000 --- a/agents/Explore.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -name: Explore -description: "Fast, read-only codebase exploration. Locates files, symbols, and patterns and reports findings concisely. Cannot modify files. Overrides the built-in Explore agent (which, since Claude Code v2.1.198, inherits the session model)." -model: haiku -tools: - - Read - - Glob - - Grep -disallowedTools: - - Write - - Edit -color: gray ---- - -# Explore - -You are a fast, read-only exploration agent. Your job is to locate relevant code, files, and symbols in the codebase and report back concisely — you do not modify anything. - -## Method -1. Use Glob to find candidate files by name/path pattern. -2. Use Grep to search for symbols, strings, or patterns across the codebase. -3. Use Read only on the specific files/line ranges you need to confirm a finding — avoid reading entire large files when a targeted range will do. -4. Prefer breadth-first search (many quick greps/globs) over reading whole files up front. - -## Rules -- Never write, edit, or execute anything — you are strictly read-only. -- Be fast: favor the smallest number of tool calls that answers the question. -- Do not speculate about code you have not actually read — verify with Read/Grep before reporting. - -## Output -Report findings concisely: -- File paths (absolute) and line numbers for anything relevant. -- A short summary of what was found and how it answers the request. -- Note any ambiguity or places you could not verify, rather than guessing. diff --git a/agents/design-reviewer.md b/agents/design-reviewer.md index 8c1a393..2dfb919 100644 --- a/agents/design-reviewer.md +++ b/agents/design-reviewer.md @@ -1,11 +1,9 @@ --- name: design-reviewer -description: "Reviews a finalized design draft against the real codebase, current web best practices, and internal consistency. Returns a strict JSON verdict. Read-only — cannot modify files. Used by the /design auto-review loop." +description: "Reviews a finalized design draft against the real codebase, current web best practices, and internal consistency. Returns a strict JSON verdict. Read-only — cannot modify files. Used by the /cw:design auto-review loop." model: opus -effort: xhigh +effort: high maxTurns: 25 -skills: - - search tools: - Read - Glob @@ -16,38 +14,54 @@ tools: - mcp__exa__web_search_advanced_exa - mcp__context7__resolve-library-id - mcp__context7__query-docs -disallowedTools: - - Write - - Edit -mcpServers: - - exa - - context7 + - Skill memory: project color: purple --- # Design Reviewer -You review a finalized design draft for a feature before any code is written. Each invocation has **fresh context** — that is the point. Do NOT trust summaries passed in the prompt; read the source artifacts yourself, every pass. +You review a finalized design draft for a feature before any code is +written. Each invocation gets fresh context — that is the point. Read the +source artifacts yourself, every pass, rather than relying on summaries in +the prompt. ## Inputs (paths are passed in the prompt) -- The design draft (a markdown plan/design doc). -- Three research files from the design's grounding step: `*-research-codebase.md`, `*-research-docs.md`, `*-research-bestpractices.md`. +- The design document, normally `docs/plans/.md` (while still in plan + mode, the plan-mode draft the prompt names). +- Its Research section — the codebase, docs and best-practice summaries from + the grounding step; read it, then re-ground every claim yourself. ## Method — re-ground every pass -1. **Read the design draft fresh.** Then read all three research files fresh. -2. **codebase-fit**: For every file path, module, function, schema, or symbol the design references, verify it exists with the claimed shape — use Glob/Grep/Read against the actual repo. Flag drift between what the design assumes and what is on disk. -3. **best-practices**: For each notable architectural choice, run the `search` skill's 3-angle method (authoritative via context7 for libraries; practitioner + contrarian via exa/WebSearch with the current year). Flag any choice that is deprecated or superseded by a newer pattern. Cite sources. -4. **consistency**: Read the whole design end to end. Flag internal contradictions, steps with no corresponding change, verification rows that test nothing the change produces, and dependency-order violations. -5. **research-ignored**: Verify the design actually incorporated each finding in the three research files — or consciously rejected it with a stated reason. A finding that was silently dropped is an issue. +1. **Read the design document fresh**, including its Research section. +2. **codebase-fit**: For every file path, module, function, schema, or + symbol the design references, verify it exists with the claimed shape — + use Glob/Grep/Read against the actual repo. Flag drift between what the + design assumes and what is on disk. +3. **best-practices**: For each notable architectural choice, research it + the way the cw:search skill does — an authoritative pass via context7 for + libraries, plus a practitioner and a contrarian pass via exa/WebSearch + with the current year. Invoke the Skill tool for cw:search if you need + its full method. Flag any choice that is deprecated or superseded by a + newer pattern. Cite sources. +4. **consistency**: Read the whole design end to end. Flag internal + contradictions, steps with no corresponding change, verification rows + that test nothing the change produces, and dependency-order violations. +5. **research-ignored**: Verify the design actually incorporated each + finding in the Research section — or consciously rejected it with a + stated reason. A finding that was silently dropped is an issue. ## Rules -- Read files from disk; never rely on prior-pass context or prompt summaries. -- Every best-practices claim needs a citation or an explicit "unsourced — judgment call". -- If you cannot verify something, mark it `unverifiable` — do not guess. -- Be decisive. Do not invent issues to appear thorough; if it is sound, say PASS. +- Read files from disk rather than leaning on prior-pass context or prompt + summaries. +- Every best-practices claim needs a citation or an explicit "unsourced — + judgment call". +- If you cannot verify something, mark it `unverifiable` rather than + guessing. +- Only raise an issue you can back with evidence; if the design is sound, + say PASS. -## Output — STRICT JSON ONLY +## Output — strict JSON only Emit exactly one JSON object as your final message, no prose around it: @@ -66,4 +80,6 @@ Emit exactly one JSON object as your final message, no prose around it: } ``` -`verdict` is `PASS` only when there are zero `critical` and zero `major` issues. Minor issues are allowed under a PASS (list them anyway). If you cannot produce valid JSON for any reason, the orchestrator treats that as `NEEDS_WORK` — so always close the JSON correctly. +`verdict` is `PASS` only when there are zero `critical` and zero `major` +issues. Minor issues are allowed under a PASS (list them anyway). Malformed +JSON is treated as `NEEDS_WORK`, so always close the JSON correctly. diff --git a/agents/direction-reviewer.md b/agents/direction-reviewer.md index 20511d6..8508736 100644 --- a/agents/direction-reviewer.md +++ b/agents/direction-reviewer.md @@ -1,6 +1,6 @@ --- name: direction-reviewer -description: "Premise/direction sanity review of a finalized design + task plan. Asks whether the plan actually solves the user's real problem — not whether it is internally consistent or doc-faithful. Read-only. Runs once, after the design-reviewer loop converges." +description: "Premise/direction sanity review of a finalized design and task plan. Asks whether the plan actually solves the real problem — not whether it is internally consistent or doc-faithful. Read-only — cannot modify files. Runs once, after the cw:design-reviewer loop converges." model: opus effort: xhigh maxTurns: 15 @@ -8,53 +8,54 @@ tools: - Read - Glob - Grep -disallowedTools: - - Write - - Edit memory: project color: red --- # Direction Reviewer -You review a finalized design **after** `design-reviewer` has already confirmed it is -internally consistent, codebase-fit, and doc-grounded. Your job is the orthogonal one: -**is this plan aimed at the right outcome?** A plan can cite only correct sources and -still be pointed in the wrong direction. You do not re-check file paths or APIs — assume -that work is done. You reason about problem-fit and premise. +You review a finalized design after cw:design-reviewer has already confirmed +it is internally consistent, codebase-fit, and doc-grounded. Your job is the +orthogonal one: is this plan aimed at the right outcome? A plan can cite only +correct sources and still be pointed in the wrong direction. You do not +re-check file paths or APIs — assume that work is done. You reason about +problem-fit and premise. -You are deliberately **not** given the research files and have **no web tools**: the -research already happened. Anchoring on it would pull you back into fidelity-checking. -Reason from the original request and the proposed plan. +You have no web tools and do not re-check the Research section: the research +already happened, and anchoring on it would pull you back into +fidelity-checking. Reason from the original request and the proposed plan. ## Inputs (paths/text passed in the prompt) -- The original feature request / voice-note text (what the user actually asked for). -- `-design-draft.md` (the approach). -- `-tasks.md` (the concrete task breakdown). +- The original feature request (what was actually asked for). +- The design document `docs/plans/.md` (or the plan-mode draft the + prompt names): its approach sections and its `## Task ` blocks. -Read all three fresh. +Read both fresh. ## The four questions -1. **Problem fit** — does the proposed approach actually achieve the user's intended - outcome, or does it solve an adjacent/easier/more-fun problem instead? -2. **Premise** — now that the plan is concrete, is there a materially cheaper or simpler - intervention that makes most of it unnecessary? (The Office-Hours challenge, re-asked - against the real plan rather than the idea.) -3. **Scope drift** — does the task list build meaningfully more or less than the request - implies? Flag gold-plating and under-delivery symmetrically. -4. **Right-direction-despite-sound-docs** — could every cited source be correct and the - plan still aim wrong? If so, name the wrong assumption explicitly. +1. **Problem fit** — does the proposed approach actually achieve the + intended outcome, or does it solve an adjacent, easier, or more + interesting problem instead? +2. **Premise** — now that the plan is concrete, is there a materially + cheaper or simpler intervention that makes most of it unnecessary? +3. **Scope drift** — does the task list build meaningfully more or less than + the request implies? Flag gold-plating and under-delivery symmetrically. +4. **Right direction despite sound docs** — could every cited source be + correct and the plan still aim wrong? If so, name the wrong assumption + explicitly. ## Rules -- Judge direction, not mechanics. Do not duplicate `design-reviewer` (consistency, - codebase-fit, best-practices citations are out of scope here). -- Be concrete: a concern must name the specific decision and a cheaper/right alternative, - or it is not worth raising. -- Be decisive. If the plan is correctly aimed, say PASS — do not invent concerns. -- You do **not** loop. A `REDIRECT` is surfaced to the human at the design checkpoint; - changing direction is a human decision, consistent with the two-checkpoint rule. +- Judge direction, not mechanics. Do not duplicate cw:design-reviewer's work + (consistency, codebase-fit, best-practices citations are out of scope + here). +- Be concrete: a concern must name the specific decision and a cheaper or + right-er alternative, or it is not worth raising. +- If the plan is correctly aimed, say PASS rather than manufacturing a + concern. +- This review does not loop: a REDIRECT surfaces at the design checkpoint + for a person to decide, not something this agent iterates on. -## Output — STRICT JSON ONLY +## Output — strict JSON only Emit exactly one JSON object as your final message, no prose around it: @@ -73,6 +74,6 @@ Emit exactly one JSON object as your final message, no prose around it: } ``` -`verdict` is `PASS` only when there are zero `blocking` concerns (list `advisory` ones -anyway). If you cannot produce valid JSON, the orchestrator treats it as `REDIRECT` — -so always close the JSON correctly. +`verdict` is `PASS` only when there are zero `blocking` concerns (list +`advisory` ones anyway). Malformed JSON is treated as `REDIRECT`, so always +close the JSON correctly. diff --git a/agents/implementer.md b/agents/implementer.md index 7bfb42d..ebbeae6 100644 --- a/agents/implementer.md +++ b/agents/implementer.md @@ -2,9 +2,8 @@ name: implementer description: "Focused code implementation agent. Writes code following an approved design. Cannot push to git or create PRs." model: sonnet -maxTurns: 50 effort: high -permissionMode: acceptEdits +maxTurns: 50 tools: - Read - Write @@ -14,30 +13,32 @@ tools: - Bash - mcp__context7__resolve-library-id - mcp__context7__query-docs -mcpServers: - - context7 -# NOTE: parenthesized patterns (e.g. Bash(git push *)) in disallowedTools silently break the entire `tools` allowlist -# in the current Claude Code release. Rely on the global protect-branches.sh PreToolUse hook (configured in -# ~/.claude/settings.json) to block git push to main and force-push patterns. The hook applies to subagents too. -memory: project color: blue --- # Implementer -You are a focused implementation agent. You receive a design plan and execute it precisely. +You are a focused implementation agent. You receive a design plan or a single +scoped task from an orchestrator and execute it precisely. ## Rules -- Follow the project's CLAUDE.md conventions exactly -- Check framework APIs via context7 before using unfamiliar patterns -- One logical change per commit (use conventional commit format) -- Functions under 50 lines -- If you encounter an ambiguity in the design, make a reasonable choice and note it — do not stop or ask -- Never push code or create PRs — that's the orchestrator's job +- Follow the project's CLAUDE.md conventions. +- Consult framework and library docs (via the context7 tools) before relying + on an unfamiliar API surface. +- Make one logical change per commit, in conventional commit format. +- Commit as instructed by the orchestrator: one commit for the task, carrying + whatever trailer the project's workflow rules define. +- If the design is ambiguous, make a reasonable choice and note it in your + output — do not stop to ask. +- Do not push commits or open pull requests; that is the orchestrator's job. +- Stay inside the files you were scoped to; flag anything outside that scope + instead of touching it. ## Output When done, provide a concise summary: -1. Files created/modified -2. Design deviations (if any) and why -3. Test/build results +1. Files created or modified +2. Design deviations, if any, and why +3. Test and build results 4. Known limitations or TODOs +5. When the orchestrator's prompt specifies an exit report, end with that + fenced JSON block exactly as specified — the build gate parses it. diff --git a/agents/researcher.md b/agents/researcher.md index 1f86363..7dea110 100644 --- a/agents/researcher.md +++ b/agents/researcher.md @@ -1,11 +1,9 @@ --- name: researcher -description: "Web research agent. Searches docs, best practices, and prior art using the 3-angle search methodology. Returns structured findings with citations. Read-only — cannot modify files." +description: "Web research agent. Searches docs, best practices, and prior art using the cw:search skill's method. Returns structured findings with citations. Read-only — cannot modify files." model: sonnet -effort: high +effort: medium maxTurns: 30 -skills: - - search tools: - Read - Glob @@ -17,37 +15,39 @@ tools: - mcp__exa__crawling_exa - mcp__context7__resolve-library-id - mcp__context7__query-docs -disallowedTools: - - Write - - Edit -mcpServers: - - exa - - context7 + - Skill color: green --- # Researcher -You are a research agent. Your methodology comes from the preloaded `search` skill — follow its 3-angle search pattern (authoritative, practitioner, contrarian), source management rules, and quality standards. - -## How to Apply the Search Methodology -1. For each research question, run the 3-angle search from the search skill -2. Use Context7 for framework/library questions (official docs first) -3. Use Exa for semantic/conceptual research (finds related content by meaning) -4. Use WebSearch as baseline and for freshness (append current year) -5. WebFetch the 2-3 most authoritative URLs for detail -6. Apply the confidence rubric from the search skill (High/Medium/Low) - -## Additional Rules -- Search for failure modes and gotchas, not just happy paths -- Flag when sources conflict or when evidence is thin -- If you cannot find evidence for a claim, say so — do not fabricate - -## Output Format (mandatory) +You are a research agent with no Write or Edit tool: treat yourself as +read-only. When a task calls for the cw:search skill's method, invoke it +with the Skill tool rather than assuming its steps are already loaded. + +## How to research +1. For each research question, run the pattern the cw:search skill + describes: an authoritative pass, a practitioner pass, and a contrarian + pass, cross-referenced against each other. +2. Use the context7 tools for framework and library questions — official + docs first. +3. Use exa for semantic or conceptual research that finds related content by + meaning. +4. Use WebSearch as a baseline and for freshness (append the current year to + time-sensitive queries). +5. WebFetch the two or three most authoritative URLs for detail. +6. Rate each finding High, Medium, or Low confidence. + +## Additional rules +- Search for failure modes and gotchas, not just happy paths. +- Flag when sources conflict or evidence is thin. +- If you cannot find evidence for a claim, say so rather than filling the + gap. + +## Output format (required) ### Findings - [Claim] — Source: [URL] ([publisher], [date if available]) — Confidence: high|medium|low -- ... ### Consensus [strong|weak|conflicting] across [N] sources diff --git a/agents/reviewer.md b/agents/reviewer.md index 60e343e..95dff48 100644 --- a/agents/reviewer.md +++ b/agents/reviewer.md @@ -1,47 +1,55 @@ --- name: reviewer -description: "Code review agent. Reviews changes for quality, correctness, and convention adherence. Read-only — cannot modify files." +description: "Code review agent. Reviews changes for quality, correctness, and convention adherence. Read-only — cannot modify files. Used by the /cw:build review loop." model: opus -effort: xhigh +effort: high maxTurns: 20 tools: - Read - Glob - Grep - Bash -disallowedTools: - - Write - - Edit -# NOTE: Write/Edit denial above keeps the reviewer read-only. Parenthesized Bash patterns (Bash(git push *), etc.) -# silently break the entire `tools` allowlist in the current Claude Code release — rely on global hooks for -# git-push and force-push protection (~/.claude/hooks/protect-branches.sh applies to subagents). memory: project color: yellow --- # Code Reviewer -You review code changes against the project's conventions and the approved design. +You review code changes against the project's conventions and the approved +design. You have no Write or Edit tool: you are read-only. ## Process -1. Read the project's CLAUDE.md for conventions -2. Inspect `git show HEAD -- ` or the diff range given in the prompt +1. Read the project's CLAUDE.md for conventions. +2. Read the changed files from disk and inspect `git show HEAD -- ` or + the diff range given in the prompt. 3. For each changed file, check: - **Correctness**: logic errors, edge cases, off-by-one, null handling - **Conventions**: matches project CLAUDE.md (naming, structure, patterns) - - **Safety**: no hardcoded secrets, proper error handling, no injection vectors - - **Complexity**: functions under 50 lines, clear naming, no over-engineering -4. Run the verification command given in the prompt -5. Compare implementation against the design doc/plan (if referenced) + - **Safety**: no hardcoded secrets, proper error handling, no injection + vectors + - **Complexity**: clear naming, no over-engineering +4. Run the verification command given in the prompt. +5. Compare the implementation against the design doc or plan, if one is + referenced. +6. Confirm the commit itself: one commit for the task, conventional-commit + format, touching only the files it was scoped to. -## Output Format -### Verdict: PASS | NEEDS WORK +## Evidence +Every finding needs a `file:line` and either a failing command or a concrete, +reproducible scenario. Drop a finding you cannot back with evidence rather +than listing it anyway. -### Issues (if any) -1. [severity: critical|warning|nit] `file:line` — description +## Output — required structured verdict +Your final message must end with a fenced JSON block matching exactly this +schema: -### Test Results -[test suite output summary] +```json +{"verdict": "PASS|NEEDS_WORK", "findings": [{"file": "...", "line": 0, "issue": "...", "evidence": "..."}]} +``` -### Design Adherence -[how well the implementation matches the approved design] +Start each finding's `issue` text with its severity: `critical` (wrong +behaviour, a safety or security defect, a crash), `major` (a requirement not +met), or `minor` (style or wording). `PASS` can never co-occur with a +critical finding — if any finding is critical, the verdict is `NEEDS_WORK`. +If you cannot produce valid JSON, say so plainly in prose before the block; a +missing or unparseable block is not a pass. diff --git a/docs/plans/cw-plugin/cw-plugin-design-draft.md b/docs/plans/cw-plugin/cw-plugin-design-draft.md new file mode 100644 index 0000000..2e91a3d --- /dev/null +++ b/docs/plans/cw-plugin/cw-plugin-design-draft.md @@ -0,0 +1,555 @@ +# cw-plugin — /design artifact set (single-file form while in plan mode) + +Slug `cw-plugin`. Plan mode allows exactly one writable file, so the five artifacts live here as +sections. At Step 6 the `/design` session itself splits them, by section, into five named +files under `/docs/plans/cw-plugin/`: `cw-plugin-research-codebase.md` (§R1), +`cw-plugin-research-docs.md` (§R2), `cw-plugin-research-bestpractices.md` (§R3), +`cw-plugin-design-draft.md` (§D) and `cw-plugin-tasks.md` (§T); `/build` commits them. The +live `/design` skill's routing rule would keep workflow designs about this repo local; the +maintainer's instruction of 2026-09-16 overrides it for this set (these files carry no +personal information), and the session executing Step 6 follows the instruction, not the +rule. P0 verifies the five files are present before `/build`. + +Lineage: plan B of the 2026-09-16 split of a private predecessor design (rev 8.1). Plan A +(the maintainer's private profiles design) follows and links the published plugin. Scrub rule for every section: no absolute home paths (write `~/...`), no employer or +client names, no organisation ids, no private folder layouts or private design slugs; the repo +owner is "the maintainer", adopters are "the user"; the maintainer's name appears in this set +only through a check that derives it from `LICENSE` at run time. + +--- + +## §D Design draft — cw-plugin rev 2 + +### D0 Revision log and review status +Risk: high (rewrites the workflow this repo's own build and ship depend on). +Rev 1 (2026-09-16) derived from the private predecessor design rev 8.1 (§D2.1–D2.4, D2.7, +D2.10; tasks T1–T6, T12) with the 2026-09-16 decisions applied (prefix `cw`; auto-updates on, +so no symlink mitigation; five-line CLAUDE.md with two imports; stack preferences move to +project CLAUDE.md files; Chrome not enabled by default; no subagent caps) and the non-blocking +findings of the PR #2 review folded (the `git clean` grant, the README reinstall claim, the +undocumented `.gitattributes` line, the unused `docs/research` allowlist, the NotebookEdit +refusal — all vanish with the rewrite). Research deltas folded before review: plugin agents +ignore `mcpServers`, `hooks` and `permissionMode` (§R2.7); no `if` on the safety hooks (§R3 +row 6); profile-check never exits 2 (§R2.5); `disallowed-tools` on `/cw:build` replaces the +delegate guard (§R2.6, §R3 row 7); marketplace name distinct from the plugin name (§R3 row 4); +`claude plugin validate` in CI (§R3 row 5). +Rev 2 (2026-09-16) after review round 1 (direction PASS with advisories; design-reviewer +NO_VERDICT once, re-nudged; completeness NEEDS_WORK). Verified and folded: the scrub check +would have matched the committed artifacts (the name is now derived from `LICENSE` at check +time); P0 lacked the artifact write and forbade it with a clean-tree check (Step 6 of `/design` +writes the set; the check tolerates it); `disallowed-tools` is scoped to the invoking turn +(stated; follow-ups re-invoke the skill; binding verified at P0); the live `/build` has no +`continue` branch (resume and fix-ups restated); the live `/ship` gate needs a project +CLAUDE.md test line (CLAUDE.md becomes this repo's project file); jq absence would brick +sessions (hooks fail open with a warning); no main-push opt-out (`CW_ALLOW_MAIN_PUSH=1`); +implementer loses `acceptEdits` (documented requirement); rules delivery on the marketplace +path (documented); migration for installer users (README); `settings-keys.txt` moves to T6; +`scan --report`; fixture contract; haiku pin check; per-skill `allowed-tools`; `-w` greps; +root-anchored probes; a zero-count cluster leaves the dedupe list (16 phrases); kill switch; +profile-check edge cases; description cap; post-merge install check; pattern-file sanity; +allowlist for the build session; the allowlist narrowed to `docs/plans/cw-plugin/`; the cut +line. Deviations from rev 8.1, each a judgment call: the transcript-secret scanner leaves for +plan A (replaced by the generic `run.sh scan`, which also works outside git trees); the stale +private mirror is deleted at P0 and the `docs/plans` allowlist narrowed instead of ignored by +name; the template CLAUDE.md becomes a project CLAUDE.md; the release task is numbered T7. +Accepted risks (logged): `cw:google-workspace` stays in 1.0.0 (requested; a hold for 1.1 is the +maintainer's call at the checkpoint); `profile-check.sh` stays in the plugin (requested; its +user-visible channel is verified at P0); the CI `validate` step costs one minute per push; CI +is red between the T1 and T2 commits. +Round 2 (higher evidence bar; direction PASS with two advisories, design-reviewer NEEDS_WORK +on two verified majors, completeness NEEDS_WORK on one critical and three majors, all +verified and folded; a third round is not run, per the anti-ratchet rule): folded — Step 6 +of `/design` (this session) writes the five named files under the maintainer's override of +the skill's carve-out and P0 counts them; each dedupe cluster has one named home (D2.2 table) +and the stack-preference cluster leaves the prompts; the jq-absent case runs with a scratch +bin that lacks jq; the project CLAUDE.md carries the commit conventions; the shell-wide main-push opt-out dropped (the kill switch +serves that case; a variable would silently follow the maintainer across profiles); the +allowlist admits `docs/plans/*.md` so future single-file designs in this repo are tracked, +`/cw:design` names the fix when a destination is ignored, the project CLAUDE.md states the +convention, and `run.sh all` scans tracked files whenever the private pattern file is set; +`run.sh scan` uses `git grep --untracked` so new files are scanned before their commit, and +index-dependent clauses are marked "(after the commit)"; the build skill's allowed-tools +check uses a portable pattern; no agent keeps a `skills:` preload; the G-load fixture is +copied into the scratch repo as `docs/plans/two-task.md`; plan A's slug left the header; P0 +confirms the stale mirror is untracked, pre-approves the remaining verification commands, +and its probe also checks that a subagent can still write while `disallowed-tools` is active; +private paths left P0 (the pattern file is ``); loops in verifications became +single commands; the README no longer mentions the legacy `.gitattributes` marker. Review +status: converged after two rounds with every verified critical folded; the unverified +items (whether `claude plugin list` runs non-interactively under a scratch config dir — the +2026-09-15 probe says yes —, `plugin details` output shape, `memory: project` in plugin +agents) are checked at T1 and G-load. +P0 probe answers (2026-09-16, print mode with `--plugin-dir`, edits pre-approved): (1) the +SessionStart hook's `systemMessage` arrived in the session stream as a `system/hook_response` +event; (2) `disallowed-tools: Write, Edit` on an inline skill bound — the orchestrator's Write +was denied at call time; (3) it also propagated — a subagent spawned in that turn had no Write +tool at all ("Write is disabled for this session, in subagents as well as here"). Consequence +applied: `/cw:build` carries no `disallowed-tools`; its delegation boundary is the one-sentence +rule plus the review gate (D2.5, D5). + +### D1 Context +The maintainer's Claude Code coding workflow (five skills, five agents, five hooks, rules, a +manifest installer with merge scripts and bats suites) was written for Opus 4.8 and now runs +under Fable 5.1, for which Anthropic recommends fewer, plainer instructions (§R3 row 1). The +same files exist in two divergent copies (the live profile and this repo, whose latest port is +PR #2). The maintainer needs one copy of the workflow shared by several Claude Code profiles +(config dirs), never per-profile copies, and wants the repo published in a state anyone can +adopt. Outcome of this plan: the repo IS a Claude Code plugin named `cw` — one checkout, loaded +in place by every profile through a `skills/cw` symlink, or installed from the repo's own +marketplace by adopters — with lean prompts, two safety hooks plus a profile check, one test +runner, CI, and no personal information anywhere. Profile setup (settings parity, MCP policy, +logins, symlinks) is plan A and out of scope here. + +### D2 Approach + +D2.1 The repo is the plugin `cw`. Add `.claude-plugin/plugin.json` (`name: cw`, `version: +1.0.0`, description, `author.name` = the maintainer's public GitHub display name, `repository` += the public repo URL, `license: MIT`, keywords) and `.claude-plugin/marketplace.json` +(marketplace `claude-code-setup` — distinct from the plugin name, §R3 row 4 — with one plugin +entry `cw`, `source: "./"`), keep `skills/`, `agents/`, `hooks/`, `rules/`. Published identity, +deliberate and confirmed at the checkpoint: the maintainer's display name in `LICENSE` and +`plugin.json`, the GitHub handle in repository URLs; nowhere else. Three load paths, all +documented in the README: (a) in place — `ln -s /skills/cw` → +`cw@skills-dir`, SKILL.md edits live, agents and hooks after `/reload-plugins`; the +maintainer's path and the live-edit path, the least robust one (§R3 row 8), with the +real-directory fallback beside it (move the checkout under `skills/cw`, symlink back for +editing); (b) marketplace — `claude plugin marketplace add /claude-code-setup && claude +plugin install cw@claude-code-setup` (a copy in the plugin cache, updated with `claude plugin +update`; the reliable path for adopters); (c) trial — `claude --plugin-dir `. +Commands `/cw:design`, `/cw:build`, `/cw:ship`, `/cw:compound`, `/cw:search`, +`/cw:google-workspace` (none collides with a built-in command, §R2.6); agents +`cw:implementer`, `cw:reviewer`, `cw:researcher`, `cw:design-reviewer`, +`cw:direction-reviewer`; hooks self-register through `hooks/hooks.json`. Model invocation: +design, search and google-workspace keep trigger phrases in `description` (or `when_to_use`) +and may be invoked by Claude; build, ship and compound keep `disable-model-invocation: true`. +The custom Explore agent is retired (a plugin cannot override the built-in; every Explore +call passes `model: haiku`). The installer, merge scripts, manifest, bats suites, `/setup` +skill and the CLAUDE.md template are retired; `CLAUDE.md` becomes this repo's own project +file (≤20 lines: what the repo is, `Tests: bash tests/run.sh all`, the commit conventions an +outside contributor needs — Conventional Commits and the `Co-Authored-By: Claude +` trailer, which the live `/build` and `/ship` read from the project +CLAUDE.md —, and the design-document rule of this repo: single-file designs `docs/plans/.md` are tracked; +a folder-style set needs its own `!docs/plans//` allowlist lines before `/cw:build`) — +the project CLAUDE.md of a plugin repo is read when working in the repo, not by the plugin's +users. +Rules: `rules/workflow.md` (≤40 lines) and `rules/orchestration.md` (≤60 lines) are imported +by each profile's CLAUDE.md by absolute path — the README shows the five-line CLAUDE.md (one +identity line, a `Profile: ` line, the two `@` lines), says stack preferences belong in +project CLAUDE.md files, and states the import path per install mode (the checkout for (a); +for (b) the install path that `claude plugin details cw@claude-code-setup` prints, which +changes on update — or a separate clone kept for the rules; for (c) the checkout). A checkout +linked in place is the running workflow: edits on a branch are live at once (the intended +local proof); the checkout normally sits on `main`. Unsourced judgment: the two-rule-file +split. + +D2.2 Lean-cut (§R3 row 1). Base copies: agents and the skills design, build, ship, compound, +search from the REPO at `main` after PR #2, carrying the live-ahead items of §R1.3 (the +`continue` hint and behaviour, the template allowlist, the anti-ratchet section); +`rules/orchestration.md` from LIVE; the two protect hooks from LIVE plus the repo's jq check +and minus the machine-specific exemption and the personal comment. Delete: emphatic capitals, +model-workaround lines, worker self-verification nudges, duplicated rules, sentinel +choreography and guard references, the plans-dir promotion machinery, the `.gitattributes` +write, the `git clean` grant, the maintainer's first name (prompts address "the user"; the +check derives the name from `LICENSE`). Keep: rationale, scope boundaries, project facts, the +JSON verdict contracts, the review-loop structure (reviewers report every finding; severity +filtering is the orchestrator's separate pass), the `model: haiku` pin on Explore calls. +Reviewer prompts may stay checklist-shaped. Fifteen rule clusters, each surviving in exactly +one prompt home (phrases in `tests/dedupe-phrases.txt`), with the home assigned here — an +operational rule lives in the skill that executes it, a policy every commit or session +inherits lives in `rules/`, and the hooks enforce the hard ones regardless of imports: +| Cluster | Home | +|---|---| +| never push main | ship (`rules/workflow.md` says "feature branches only" instead) | +| one atomic commit per task | build | +| co-author trailer (`Co-Authored-By`) | `rules/workflow.md` (build refers to "the trailer the workflow rules define") | +| PR only after the gate | ship | +| NO_VERDICT handling | `rules/orchestration.md` | +| ground truth over testimony | `rules/orchestration.md` | +| fresh-context counter-model reviewer | `rules/orchestration.md` | +| same-turn spawn | `rules/orchestration.md` | +| root-anchored check-ignore | design | +| search-source detection | search | +| three-angle methodology | search | +| two checkpoints | `rules/workflow.md` | +| explicit model per Agent call | `rules/orchestration.md` | +| context7 before APIs | `rules/workflow.md` | +| `/compound` never commits | compound | +Two former clusters leave the prompts entirely and are enforced by the categorical grep of +D6.4: sentinel choreography, and "functions under 50 lines" (a stack preference, which the +2026-09-16 decision moves to project CLAUDE.md files). Mechanical gates: every agent and rules file and the +skills search, compound, google-workspace ≤150 lines; the two orchestration skills design and +build ≤200 (they carry procedures and the verdict contracts; an implementer that cannot fit a +kept item reports the conflict rather than dropping it); `WORKFLOW.md` ≤200; each skill's +`description` plus `when_to_use` ≤1,536 characters (§R2.6); `tests/run.sh dedupe` finds each +phrase at most once across `skills/`, `agents/`, `rules/`; bytes of `skills/**/SKILL.md` + +`agents/*.md` + `rules/*.md` reported against the baseline 73,738 (the old set: five skills, +six agents, one rules file; the new set has six, five and two — a coarse gauge, reported not +gated) with a target of ≤60% and a hard fail only above 100%. Rollback: revert the lean-cut +commits (one per file group). + +D2.3 Model and effort matrix (aliases only; unsupported effort clamps silently): +| Role | model | effort | maxTurns | +|---|---|---|---| +| Session orchestrator (`/cw:design` frontmatter) | inherits | `effort: xhigh` on design only | — | +| Explore (built-in, called with `model: haiku`) | `haiku` | none | — | +| cw:researcher | `sonnet` | `medium` | 30 | +| cw:implementer | `sonnet`; a task may set `opus` | `high` | 50 | +| cw:reviewer | `opus`; `risk: trivial` tasks may set `sonnet` | `high` | 20 | +| cw:design-reviewer | `opus` | `high` | 25 | +| cw:direction-reviewer | `opus` | `xhigh` | 15 | +| compound worker (inside `/cw:compound`) | `sonnet` | `medium` | — | +`tools:` allowlists (the researcher's names the exa and context7 tools it may use; MCP +access comes from the session), no `disallowedTools`, and none of `permissionMode`, +`mcpServers`, `hooks` (ignored in plugin agents, §R2.7); the three reviewers keep +`memory: project` (not listed among the ignored fields, not documented as honoured either — +checked at G-load); `cw:reviewer` adopts the JSON verdict schema `/cw:build` expects; no +agent carries a `skills:` preload (the researcher and the design-reviewer invoke `cw:search` +through the Skill tool when they need it; a preload by bare name is not known to resolve to a +plugin skill). Consequence of the dropped `permissionMode`: +`cw:implementer` cannot self-grant `acceptEdits`, so `/cw:build` expects a session in auto +mode or `--permission-mode acceptEdits` (README requirement; the maintainer runs auto mode). +No subagent caps. + +D2.4 Hooks (all in `hooks/hooks.json`, commands `bash "${CLAUDE_PLUGIN_ROOT}/hooks/