Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
d03a30a
feat(hooks): add design-scope guard confining /design writes to artif…
victorkzam Jul 24, 2026
ddaa289
feat(hooks): allow project docs and gitattributes writes in the deleg…
victorkzam Jul 24, 2026
139eed5
chore(gitignore): allow docs/plans and .gitattributes through the def…
victorkzam Jul 24, 2026
3c74c99
feat(design-skill): write the approved artifact set into the project …
victorkzam Jul 24, 2026
607512f
chore(setup): register the design-scope guard in example settings
victorkzam Jul 24, 2026
a96dbf0
test(hooks): cover the design-scope guard and the widened delegate-gu…
victorkzam Jul 24, 2026
586d3ac
feat(build-skill): consume project design artifacts and commit them a…
victorkzam Jul 24, 2026
a5363d0
feat(claude-md): document project-local design artifacts in the workf…
victorkzam Jul 24, 2026
cf2c89e
docs(skills): reference project design artifacts in ship and compound
victorkzam Jul 24, 2026
7cf8452
fix(check): verify the design-scope guard in the post-install doctor …
victorkzam Jul 24, 2026
847dbba
docs: document project-local design artifacts in README and WORKFLOW
victorkzam Jul 24, 2026
b54216c
fix(hooks): reject path traversal and fail closed in design + delegat…
victorkzam Jul 24, 2026
8a7a177
fix(skills): reconcile promotion completeness and clean up partial pr…
victorkzam Jul 24, 2026
6456c81
docs(claude-md): correct the design-artifacts commit description
victorkzam Jul 24, 2026
7f032aa
docs: refresh workflow summaries for the project-local-docs flow
victorkzam Jul 24, 2026
26e3023
fix(hooks): anchor project-relative guard allowances to the session p…
victorkzam Jul 25, 2026
11054d3
fix(design-skill): align body commands with the allowed-tools grants
victorkzam Jul 25, 2026
48cc0ae
fix(gitignore): scope the docs un-ignore to docs/plans and docs/research
victorkzam Jul 25, 2026
53b6bb9
docs: reconcile commit-position, commit-none, and non-repo language
victorkzam Jul 25, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

# Explicitly allow tracked template files and directories.
!.gitignore
!.gitattributes
!README.md
!LICENSE
!CLAUDE.md
Expand All @@ -22,6 +23,17 @@
!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/**.
!docs/
!docs/plans/
!docs/plans/**
!docs/research/
!docs/research/**

!.github/
!.github/**

Expand All @@ -40,7 +52,7 @@ settings.json
settings.local.json
.claude.json
.mcp.json
plans/
/plans/
projects/
history.jsonl
*.log
Expand Down
4 changes: 2 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ PM-turned-engineer. Quality and learning over speed. Always explain WHY behind a
Co-Authored-By: Claude <noreply@anthropic.com>
- 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. `/ship` verifies the series; it never creates a catch-all or squashed commit.
- 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 (may write only `~/.claude/plans/<slug>-*.md`); the post-design checkpoint is the exit-plan-mode point; `/build` and `/ship` run in execute mode.
- Mode transitions: `/design` runs in plan mode; on plan approval it writes the artifact set to `<project>/docs/plans/<slug>/` (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(<slug>):` 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.

Expand Down
54 changes: 53 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,13 @@ would cost 50K+ and degrade quality as the window fills.

```
/design <feature description> → research + draft + task breakdown + review loop
↓ (checkpoint 1 — you approve, then exit plan mode)
↓ (checkpoint 1 — /design exits plan mode itself, provisionally, then writes
the approved artifacts into docs/plans/<slug>/; you approve there, after
the write — /build is still the real go/no-go)
/build [<slug>] → implement via subagents, one atomic commit per task
(plus a `docs(<slug>):` 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)
Expand Down Expand Up @@ -209,6 +214,17 @@ 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
Expand Down Expand Up @@ -318,3 +334,39 @@ 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 (`<slug>-design-draft.md`,
`<slug>-tasks.md`, `<slug>-research-*.md`) out of `~/.claude/plans/` and into
the adopting project's own `$ROOT/docs/plans/<slug>/`, 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(<slug>): 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/<slug>/` 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/<slug>/` 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.
38 changes: 26 additions & 12 deletions WORKFLOW.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ Two human checkpoints: **after design** (you approve the plan), **before PR** (y
| 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` |

---
Expand All @@ -63,11 +64,13 @@ Two human checkpoints: **after design** (you approve the plan), **before PR** (y
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** `<slug>-tasks.md` (adaptive task count — 1 to many, never a fixed range; each task: disjoint files, assigned model, verification, one atomic Conventional commit)
4. Synthesizes a design draft **and** `<slug>-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. **STOPS for your approval** — presents both verdicts + tasks path; this is the exit-plan-mode boundary
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/<slug>/`, 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 regenerates the design *and* `<slug>-tasks.md`, re-runs the review loop + direction review, and stops again at a single checkpoint.
**Iteration**: feedback given before the provisional `ExitPlanMode` approval iterates entirely on the plans-dir copies (regenerate design + `<slug>-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/<slug>/` 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.

Expand All @@ -76,9 +79,9 @@ Two human checkpoints: **after design** (you approve the plan), **before PR** (y
**What it does**: Orchestrates implementation using subagents. The main agent NEVER writes code and NEVER re-decomposes — it consumes `<slug>-tasks.md`, delegates, and reviews. Runs in execute mode.

**How it works**:
1. **Pre-flight**: Resolves the tasks file (arg / newest-by-mtime-with-confirm), creates feature branch, writes the session-scoped sentinel
1. **Pre-flight**: Resolves the tasks file — project copy first (`$ROOT/docs/plans/<slug>/<slug>-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(<slug>): add design + research artifacts` commit, then writes the session-scoped sentinel
2. **Consume tasks**: Executes exactly the tasks `<slug>-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)
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
Expand All @@ -93,7 +96,7 @@ Two human checkpoints: **after design** (you approve the plan), **before PR** (y

**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)
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(<slug>):` 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)
Expand All @@ -106,7 +109,9 @@ Two human checkpoints: **after design** (you approve the plan), **before PR** (y

```
/design <spec> → research + draft + <slug>-tasks.md + design-reviewer loop + direction-reviewer
↓ (you approve — exit plan mode here)
↓ (/design exits plan mode itself, provisionally, then writes the approved
artifacts into docs/plans/<slug>/ — you approve there, after the write;
/build is still the real go/no-go)
/build [<slug>] → consume tasks.md; one atomic commit per task; reviewer
↓ (you approve the commit series)
/ship → verify series, product-doc updates, quality gate, push, PR
Expand All @@ -120,16 +125,23 @@ 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` | **plan** | Documented exception: may write only `~/.claude/plans/<slug>-*.md` (judgment call, bounded to that dir) |
| post-design checkpoint | — | **The exit-plan-mode boundary.** You approve, then leave plan mode |
| `/design` Steps 0-5 (research, draft, review loop) | **plan** | Documented exception: may write only `~/.claude/plans/<slug>-*.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/<slug>/` (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/<slug>/` (also `~/.claude/plans/<slug>-*.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` running in plan mode and the post-design checkpoint being the exit-plan-mode
boundary, not from a global `"plan"` default.
`/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

Expand Down Expand Up @@ -164,7 +176,7 @@ top balanced level).
- **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
- **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)
Expand Down Expand Up @@ -201,6 +213,7 @@ All hooks are in `~/.claude/settings.json` and `~/.claude/hooks/`. They provide
| 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`) |

Expand All @@ -209,6 +222,7 @@ All hooks are in `~/.claude/settings.json` and `~/.claude/hooks/`. They provide
- `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`

---
Expand Down
Loading
Loading