Skip to content

feat: project-local design artifacts (docs/plans/<slug>/) - #2

Merged
victorkzam merged 19 commits into
mainfrom
feat/project-local-docs
Sep 16, 2026
Merged

victorkzam merged 19 commits into
mainfrom
feat/project-local-docs

Conversation

@victorkzam

@victorkzam victorkzam commented Jul 24, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • /design now writes the approved artifact set (design draft, research files, tasks) into the project's docs/plans/<slug>/ folder, making the project copy canonical; plans-dir drafts are banner-stamped as non-canonical, and the plans dir remains the home for meta-tooling work (the no-repo case prompts to git init or stay in the plans dir).
  • New design-scope-guard.sh hook confines /design-phase writes to artifact paths only; the orchestrator delegate guard allowlist is widened to permit project docs and .gitattributes writes. Both guards reject .. traversal, fail closed on malformed input, and anchor their project-relative allowances (docs/plans/, docs/research/, .gitattributes) to the session's project root — out-of-project writes are denied.
  • /build consumes the project design artifacts and commits the set as a scoped docs(<slug>): commit on the feature branch (typically first on a fresh branch, but not guaranteed leading — refreshes on continue can land later); /ship and /compound reference the project copy.
  • .gitignore default-deny now lets exactly docs/plans/**, docs/research/**, and .gitattributes through — the rest of docs/ stays ignored. The guard is registered in settings.example.json and verified by the post-install doctor (check.sh).
  • /design's allowed-tools grants now cover every command its body instructs: the promote-routing probe uses the absolute-path git check-ignore form, and the all-or-nothing partial-copy cleanup uses git clean -fd (cannot touch tracked files) instead of an ungrantable rm -rf.
  • README, WORKFLOW, and the template CLAUDE.md document the artifact flow consistently, including the commit: none (verification-only) task exception.
  • Pre-PR 3-lens review panel (correctness / security / conventions) ran on the branch; all 7 evidence-verified findings were fixed in the final four commits.

Test Plan

  • bats tests/ — 113/113 pass (includes 12 new guard-anchoring tests)
  • shellcheck -x on all changed shell scripts — clean
  • Manual guard verification: previously-demonstrated bypass payloads (out-of-project docs/plans/ write, $HOME/.gitattributes write, missing-cwd payload) now exit 2 in both guards; in-project writes still exit 0
  • Manual gitignore verification: docs/scratch-*/note.md ignored, docs/plans/** and docs/research/** stageable
  • Manual: run /design on a sample feature and confirm the artifact set lands in <project>/docs/plans/<slug>/ with the guard active

Design Reference

~/.claude/plans/project-local-docs-design-draft.md (legacy plans-dir copy — this branch is the feature that introduces project-local design docs, so no project copy predates it)

🤖 Generated with Claude Code

https://claude.ai/code/session_01JcxamSt8aYA4qLQuXADCby

victorkzam and others added 19 commits July 24, 2026 12:05
…act paths

Co-Authored-By: Claude <noreply@anthropic.com>
…ate guard

Widens the orchestrator delegate-guard allowlist so promoted design
docs, docs/research/, and .gitattributes stay orchestrator-editable
while the /build sentinel is armed.

Co-Authored-By: Claude <noreply@anthropic.com>
…ault-deny ignore

Co-Authored-By: Claude <noreply@anthropic.com>
…docs folder

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
…ard allowlist

Co-Authored-By: Claude <noreply@anthropic.com>
…t build start

Co-Authored-By: Claude <noreply@anthropic.com>
…low rules

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
…and merge tests

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
…e guards

Co-Authored-By: Claude <noreply@anthropic.com>
…oject copies

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
…roject root

The docs/plans/, docs/research/, and .gitattributes arms in both guards were
bare */... globs, so they matched those path shapes in any repo on disk (e.g.
another repo's docs/plans/ or $HOME/.gitattributes) during a guarded window.
Anchor each arm to the session project root (git toplevel of the payload cwd,
falling back to cwd), skipping the arm entirely when cwd is empty/non-absolute/
../-tainted so it never collapses to a bare /... glob. .gitattributes is now
limited to the project-root file, the only one skills/build writes.

Co-Authored-By: Claude <noreply@anthropic.com>
Step 6's git -C "$ROOT" check-ignore probe didn't match the literal-prefix
Bash(git check-ignore:*) grant; rewritten to git check-ignore -q "$ROOT/..."
(absolute path is root-anchored either way). The partial-copy cleanup
switched from rm -rf (uncovered) to git clean -fd + a new Bash(git clean:*)
grant, since the partial copy is untracked at design time and git clean
cannot touch tracked files.

Co-Authored-By: Claude <noreply@anthropic.com>
The broad !docs/ + !docs/** pair un-ignored the entire docs/ tree, voiding
the file's default-deny promise for any new content dropped under docs/
outside the design-artifact directories. Scope the un-ignore chain to only
docs/plans/ and docs/research/, matching the explicit parent-then-children
chaining already used for .claude/.

Co-Authored-By: Claude <noreply@anthropic.com>
Reword build/SKILL.md's Phase 0 step 4 heading so it no longer asserts
"leading docs commit" as an invariant (refreshes on continue can land later).

Add the commit: none (verification-only) exception to WORKFLOW.md's and
CLAUDE.md's unconditional one-atomic-commit-per-task language.

Fix CLAUDE.md's mode-transitions bullet so the no-repo case is described as
a user prompt (git init vs plans dir), not an automatic plans-dir outcome.

Co-Authored-By: Claude <noreply@anthropic.com>
@victorkzam
victorkzam merged commit 4299a74 into main Sep 16, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant