Files
claude-skills/.tasks/bootstrap-claude-md-merge.md
vitya 68fe9a8c1c 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>
2026-04-30 15:06:06 +03:00

54 lines
3.2 KiB
Markdown

# bootstrap-claude-md-merge
## Goal
project-bootstrap upgrade mode currently treats `CLAUDE.md` as binary: either append
the entire template (causing duplicate trigger lines) or leave it untouched. Result:
projects bootstrapped before v1.2.0 silently miss new canonical triggers like
`check across all projects` (→ `using-projects-meta`) and `we're on Windows`
(→ `active-platform`) when re-run on the upgrade path. Fix: turn Step 5 into an
idempotent merge — read existing CLAUDE.md, diff against the template, append only
missing canonical lines after user confirm. Re-runs become no-ops.
## Key files
- `skills/project-bootstrap/SKILL.md:220-249` — Step 5 (the broken binary choice)
- `skills/project-bootstrap/assets/CLAUDE.md.template` — canonical trigger set
- `skills/project-bootstrap/README.md` — public surface, mention idempotency
- `dist/project-bootstrap.skill` — rebuild after install
- `~/.claude/skills/project-bootstrap/` — reinstall target
## Decisions log
- 2026-04-30: Diff strategy — substring match per template line against existing file
(trim + lowercase). A trigger is "present" if any existing line contains the template
trigger text. Avoids false-positive duplicates when user has rephrased a trigger but
preserves canonical wording for missing ones. Rejected: full line-equality match
(too brittle — user comments / case differences would re-add).
- 2026-04-30: Confirmation gate stays — show user the diff (N lines to append) before
touching the file. Idempotent run with no missing lines = silent no-op.
- 2026-04-30: Version bump 1.2.0 → 1.3.0. Behavior change visible to users on every
upgrade — minor bump fits semver intent.
## Open questions
- [ ] Should the platform line (`we're on Windows`) be substituted to match the host
during merge, the same way init does it? Decision: yes — if existing file has no
`we're on (Windows|Linux|macOS)` line, append the host-appropriate one. If it has
any of the three, leave it (user may have intentionally pinned a different platform).
## Completed steps
- [x] open task
- [x] patch Step 5 in SKILL.md (read → diff → confirm → append) — split Init / Upgrade-merge
- [x] bump version 1.2.0 → 1.3.0 in SKILL.md frontmatter
- [x] update `skills/project-bootstrap/README.md` `CLAUDE.md` row to note idempotent merge
- [x] update root `README.md` + `README.ru.md` upgrade-mode paragraph
- [x] reinstall + rebuild dist (`bash scripts/install.sh project-bootstrap && bash scripts/build.sh project-bootstrap`); verified `version: 1.3.0` on disk + Step 5 split
- [x] wiki: concept page `.wiki/concepts/bootstrap-claude-md-merge.md`, index entry, log entry
- [x] commit
- [x] STATUS.md: 🔴 → 🟢
- [x] decision on platform line — preserve if user pinned non-host one (case-insensitive `we're on (windows|linux|macos)` match)
## Notes
Existing related task `[bootstrap-recommend-projects-meta]` (Step 5.7) is **machine-level**
detection (recommend `setup-projects-meta` if MCP server not registered). This task is
**project-level** merge of the trigger line into the project's CLAUDE.md. They compose
cleanly: 5.7 makes the trigger functional on the host, this task ensures the trigger
is actually present in the file.