cc-discipline 2.12.1 → 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.
Files changed (2) hide show
  1. package/init.sh +72 -2
  2. package/package.json +1 -1
package/init.sh CHANGED
@@ -377,14 +377,84 @@ echo -e "${GREEN}Installing skills...${NC}"
377
377
  # v2.12.1. Symptom on an affected machine: a stray .claude/skills/SKILL.md plus
378
378
  # skill dirs frozen at their first-install date. status/doctor could not catch
379
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
+
380
406
  for skill_dir in "$SCRIPT_DIR"/templates/.claude/skills/*/; do
381
407
  [ -d "$skill_dir" ] || continue
382
408
  skill_name=$(basename "$skill_dir")
383
409
  mkdir -p ".claude/skills/$skill_name"
384
- cp -R "$skill_dir"* ".claude/skills/$skill_name/"
385
- echo " ✓ /$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
386
448
  done
387
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
+
388
458
  # Clean up the stray file left behind by the v2.11.0–v2.12.0 bug above. A bare
389
459
  # SKILL.md directly under skills/ is never a valid skill (skills live in
390
460
  # subdirectories), so this only ever removes that debris.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cc-discipline",
3
- "version": "2.12.1",
3
+ "version": "2.12.2",
4
4
  "description": "Discipline framework for Claude Code — rules, hooks, and agents that keep AI on track",
5
5
  "bin": {
6
6
  "cc-discipline": "bin/cli.js"