From 7a87112aa45df42ff01b0d2e89382da016baae1b Mon Sep 17 00:00:00 2001 From: Victor Kzam Date: Wed, 16 Sep 2026 15:42:24 +0100 Subject: [PATCH 01/24] docs(cw-plugin): add design + research artifacts Co-Authored-By: Claude --- .gitattributes | 1 + .../plans/cw-plugin/cw-plugin-design-draft.md | 535 ++++++++++++++++++ .../cw-plugin-research-bestpractices.md | 15 + .../cw-plugin/cw-plugin-research-codebase.md | 131 +++++ .../cw-plugin/cw-plugin-research-docs.md | 101 ++++ docs/plans/cw-plugin/cw-plugin-tasks.md | 141 +++++ 6 files changed, 924 insertions(+) create mode 100644 .gitattributes create mode 100644 docs/plans/cw-plugin/cw-plugin-design-draft.md create mode 100644 docs/plans/cw-plugin/cw-plugin-research-bestpractices.md create mode 100644 docs/plans/cw-plugin/cw-plugin-research-codebase.md create mode 100644 docs/plans/cw-plugin/cw-plugin-research-docs.md create mode 100644 docs/plans/cw-plugin/cw-plugin-tasks.md 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/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..3b6b201 --- /dev/null +++ b/docs/plans/cw-plugin/cw-plugin-design-draft.md @@ -0,0 +1,535 @@ +# 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/