feat(project-bootstrap): v1.3.0 — idempotent CLAUDE.md merge on upgrade

Step 5 was binary on upgrade (append whole template / leave alone), so
projects bootstrapped before v1.2.0 silently missed new canonical triggers
(`check across all projects`, `we're on Windows`) on re-run. Now upgrade
reads existing CLAUDE.md, substring-diffs vs template, preserves a
deliberately-pinned platform line, and appends only missing lines after
explicit confirm. Re-runs are no-ops.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-30 15:06:06 +03:00
parent 0b1b0555d1
commit 68fe9a8c1c
10 changed files with 156 additions and 8 deletions

View File

@@ -1,6 +1,6 @@
---
name: project-bootstrap
version: 1.2.0
version: 1.3.0
description: >
Initializes or upgrades a project in the current folder: git, .gitignore, README.md,
.wiki/ using Karpathy's method, .tasks/ for task tracking, CLAUDE.md with skill triggers.
@@ -219,12 +219,41 @@ If `setup-tasks` is not installed, **stop** and tell the user — same rule as S
## Step 5 — CLAUDE.md
If `CLAUDE.md` already exists — show its contents and ask:
"CLAUDE.md already exists. Append skill triggers to the end, or leave as is?"
Two paths, picked by file presence:
If it does not exist — create from template `assets/CLAUDE.md.template`.
### Init (file does not exist)
Create `CLAUDE.md` from `assets/CLAUDE.md.template`. Substitute the platform line
on non-Windows hosts (`we're on Linux` / `we're on macOS` instead of
`we're on Windows`).
### Upgrade (file exists) — idempotent merge
Treat the template as the canonical trigger set and reconcile the existing file
against it. Re-runs are no-ops once the file is in canon.
1. Read the existing `CLAUDE.md`.
2. For each non-empty, non-comment line in the template, decide whether it's
already present:
- **Trigger lines** (everything except the platform line) — present iff any
existing line, after `trim` + `tolower`, contains the template line's
trigger text. Substring match, not equality — tolerates user rewording or
trailing punctuation.
- **Platform line** (`we're on Windows`) — present iff any existing line
matches `we're on (windows|linux|macos)` case-insensitively. If the user
pinned a different platform on purpose, **leave it alone**. Only append
the host-appropriate platform line when none of the three is present.
3. Collect missing lines. If none → print `CLAUDE.md already canon — no changes`
and skip to Step 5.5.
4. Show the user the diff (N lines, exact text to append) and ask one question:
"Append these N missing canonical triggers to the end of CLAUDE.md?" Wait
for explicit confirmation before writing.
5. On confirm: append a single newline (if the file doesn't end with one) and
then the missing lines, one per line. Don't rewrite the file — only append.
Don't reorder existing lines. Don't dedupe within the existing file.
Template contents (`assets/CLAUDE.md.template` — source of truth):
Template contents:
```markdown
# CLAUDE.md
# Agent instructions. Each line is a trigger for an installed skill.