cc-discipline 2.12.0 → 2.12.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/init.sh +92 -2
- package/package.json +1 -1
package/init.sh
CHANGED
|
@@ -367,12 +367,102 @@ cp "$SCRIPT_DIR/templates/.claude/agents/investigator.md" .claude/agents/
|
|
|
367
367
|
echo -e "${GREEN}Installing skills...${NC}"
|
|
368
368
|
# Install every skill directory under templates/ — no per-skill enumeration,
|
|
369
369
|
# so adding a new skill needs zero changes here.
|
|
370
|
+
#
|
|
371
|
+
# Copy into an EXPLICIT destination directory. Do not use `cp -r "$skill_dir"
|
|
372
|
+
# .claude/skills/` here: the `*/` glob gives $skill_dir a trailing slash, and
|
|
373
|
+
# GNU and BSD cp disagree about what that means. GNU copies the directory;
|
|
374
|
+
# BSD (macOS) copies its *contents*, so every skill's SKILL.md landed on top of
|
|
375
|
+
# the previous one at .claude/skills/SKILL.md and no skill was ever updated.
|
|
376
|
+
# Shipped broken in v2.11.0 (the "directory-driven install" change) and fixed in
|
|
377
|
+
# v2.12.1. Symptom on an affected machine: a stray .claude/skills/SKILL.md plus
|
|
378
|
+
# skill dirs frozen at their first-install date. status/doctor could not catch
|
|
379
|
+
# it because they glob `skills/*/` and a bare file is not a directory.
|
|
380
|
+
# Skills are NOT force-overwritten. Users legitimately tune them per repo
|
|
381
|
+
# (/self-check's "Project-specific Checks" section exists precisely to be filled
|
|
382
|
+
# in), and until v2.12.2 every upgrade silently replaced those edits — a 73KB
|
|
383
|
+
# hand-written self-check was wiped twice in one day before this was fixed.
|
|
384
|
+
#
|
|
385
|
+
# The dpkg-conffile approach: remember the hash of the template WE installed. On
|
|
386
|
+
# the next upgrade, if the file on disk still matches that hash the user never
|
|
387
|
+
# touched it and we can update freely; if it differs the user owns it, so we keep
|
|
388
|
+
# their file and drop the new template beside it as SKILL.md.new.
|
|
389
|
+
#
|
|
390
|
+
# The manifest hash is always set to the template we shipped this run, including
|
|
391
|
+
# in the preserved case. That is what makes adoption self-healing: if the user
|
|
392
|
+
# later replaces their file with the .new one, the next run sees disk == manifest
|
|
393
|
+
# and resumes silent updates.
|
|
394
|
+
SKILLS_MANIFEST=".claude/.cc-discipline-skills.manifest"
|
|
395
|
+
NEW_MANIFEST=$(mktemp 2>/dev/null || echo ".claude/.skills-manifest.tmp")
|
|
396
|
+
PRESERVED_SKILLS=""
|
|
397
|
+
|
|
398
|
+
_cc_hash() {
|
|
399
|
+
if command -v sha256sum >/dev/null 2>&1; then sha256sum "$1" | cut -d' ' -f1
|
|
400
|
+
elif command -v shasum >/dev/null 2>&1; then shasum -a 256 "$1" | cut -d' ' -f1
|
|
401
|
+
elif command -v md5sum >/dev/null 2>&1; then md5sum "$1" | cut -d' ' -f1
|
|
402
|
+
elif command -v md5 >/dev/null 2>&1; then md5 -q "$1"
|
|
403
|
+
else cksum "$1" | cut -d' ' -f1; fi
|
|
404
|
+
}
|
|
405
|
+
|
|
370
406
|
for skill_dir in "$SCRIPT_DIR"/templates/.claude/skills/*/; do
|
|
371
407
|
[ -d "$skill_dir" ] || continue
|
|
372
|
-
|
|
373
|
-
|
|
408
|
+
skill_name=$(basename "$skill_dir")
|
|
409
|
+
mkdir -p ".claude/skills/$skill_name"
|
|
410
|
+
skill_status="updated"
|
|
411
|
+
|
|
412
|
+
for src in "$skill_dir"*; do
|
|
413
|
+
[ -f "$src" ] || continue
|
|
414
|
+
base=$(basename "$src")
|
|
415
|
+
rel="$skill_name/$base"
|
|
416
|
+
dst=".claude/skills/$rel"
|
|
417
|
+
tpl_hash=$(_cc_hash "$src")
|
|
418
|
+
|
|
419
|
+
if [ ! -f "$dst" ]; then
|
|
420
|
+
cp "$src" "$dst" # new file — nothing to protect
|
|
421
|
+
else
|
|
422
|
+
disk_hash=$(_cc_hash "$dst")
|
|
423
|
+
recorded=$(grep "^$rel " "$SKILLS_MANIFEST" 2>/dev/null | head -1 | cut -d' ' -f2)
|
|
424
|
+
if [ "$disk_hash" = "$tpl_hash" ]; then
|
|
425
|
+
: # already current
|
|
426
|
+
elif [ -n "$recorded" ] && [ "$disk_hash" = "$recorded" ]; then
|
|
427
|
+
cp "$src" "$dst" # pristine older version — safe
|
|
428
|
+
elif [ -z "$recorded" ]; then
|
|
429
|
+
# No manifest yet (first run on an existing install) and the file
|
|
430
|
+
# differs from the template. Cannot tell "older version" from
|
|
431
|
+
# "user edited", so assume the user's work matters.
|
|
432
|
+
cp "$src" "$dst.new"
|
|
433
|
+
skill_status="preserved"
|
|
434
|
+
else
|
|
435
|
+
cp "$src" "$dst.new" # user-modified — keep theirs
|
|
436
|
+
skill_status="preserved"
|
|
437
|
+
fi
|
|
438
|
+
fi
|
|
439
|
+
echo "$rel $tpl_hash" >> "$NEW_MANIFEST"
|
|
440
|
+
done
|
|
441
|
+
|
|
442
|
+
if [ "$skill_status" = "preserved" ]; then
|
|
443
|
+
PRESERVED_SKILLS="$PRESERVED_SKILLS $skill_name"
|
|
444
|
+
echo -e " ${YELLOW}~ /$skill_name (your version kept; new template at SKILL.md.new)${NC}"
|
|
445
|
+
else
|
|
446
|
+
echo " ✓ /$skill_name"
|
|
447
|
+
fi
|
|
374
448
|
done
|
|
375
449
|
|
|
450
|
+
[ -f "$NEW_MANIFEST" ] && mv "$NEW_MANIFEST" "$SKILLS_MANIFEST"
|
|
451
|
+
|
|
452
|
+
if [ -n "$PRESERVED_SKILLS" ]; then
|
|
453
|
+
echo -e " ${YELLOW}Locally modified skills were not overwritten:${PRESERVED_SKILLS}${NC}"
|
|
454
|
+
echo -e " ${YELLOW}Compare with: diff .claude/skills/<name>/SKILL.md{,.new}${NC}"
|
|
455
|
+
echo -e " ${YELLOW}Take the new one with: mv .claude/skills/<name>/SKILL.md{.new,}${NC}"
|
|
456
|
+
fi
|
|
457
|
+
|
|
458
|
+
# Clean up the stray file left behind by the v2.11.0–v2.12.0 bug above. A bare
|
|
459
|
+
# SKILL.md directly under skills/ is never a valid skill (skills live in
|
|
460
|
+
# subdirectories), so this only ever removes that debris.
|
|
461
|
+
if [ -f ".claude/skills/SKILL.md" ]; then
|
|
462
|
+
rm -f ".claude/skills/SKILL.md"
|
|
463
|
+
echo -e " ${YELLOW}✓ removed stray .claude/skills/SKILL.md (v2.11.0 macOS install bug)${NC}"
|
|
464
|
+
fi
|
|
465
|
+
|
|
376
466
|
# ─── Handle CLAUDE.md ───
|
|
377
467
|
if [ ! -f "CLAUDE.md" ]; then
|
|
378
468
|
# No CLAUDE.md exists — generate from template
|