@tyhld/conductor 0.12.9 → 0.12.10

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tyhld/conductor",
3
- "version": "0.12.9",
3
+ "version": "0.12.10",
4
4
  "description": "采配くん管制の見守りアプリ(conductor-agent)。各PCで常駐し、中央(devlog-tracker)へ定期的に生存報告(heartbeat)を送る常駐CLI。",
5
5
  "type": "module",
6
6
  "bin": {
@@ -972,6 +972,15 @@ check('職人の鉄則は同期モードでも配る',
972
972
  _ug.index('①-d 職人の鉄則スキル') < _ug.index('①-b・①-c・①-d2 は省略(同期モード)'), True)
973
973
  check('配り損ねたら成功と偽らず管制へ知らせる',
974
974
  'craftsman_notify_failure' in _ug and 'skill_sync_notify.py' in _ug, True)
975
+ # ★上書きの前に日時つきの控えを取る(えふさん確定 2026-09-16・便 bf030fee)。
976
+ # 中身の検査は test/craftsman-skill-sync.test.ts。ここでは決まりが消えていないことだけ見る。
977
+ check('上書きの前に控えを取る', 'craftsman_backup()' in _ug, True)
978
+ check('控えは鉄則の置き場(~/.claude)の外に置く',
979
+ 'CRAFTSMAN_BACKUP_DIR="$HOME/.tyhld/skill-backups"' in _ug, True)
980
+ check('控えの名前は settings.json と同じ流儀(.bak.<日時>)',
981
+ '.bak.$(date' in _ug, True)
982
+ check('控えを取れなければ上書きしない',
983
+ 'if ! craftsman_backup; then' in _ug and 'craftsman_record failed backup-failed' in _ug, True)
975
984
  check('同期モードは権限ルールの整理より前で終わる',
976
985
  _ug.index('同期のみ完了しました') < _ug.index('④ 各現場の権限ルール'), True)
977
986
  # ★同期モードは「現場の二重登録を外す」(=番人の配線)までは行う(ADR-013)。
@@ -307,6 +307,21 @@ CRAFTSMAN_STATE="$GUARD_HOME/craftsman-skill.state" # 最後に【成功した
307
307
  CRAFTSMAN_LAST="$GUARD_HOME/craftsman-skill.last" # 直近の【試み】の結果
308
308
  CRAFTSMAN_NOTIFY="$SCRIPT_DIR/hooks/skill_sync_notify.py"
309
309
 
310
+ # ★上書きする前の控えの置き場(えふさん確定 2026-09-16・便 bf030fee = 29612ff1 の乙)。
311
+ # 【なぜ要るか】鉄則の配布は、中身が違えば無条件に上書きしていた。人が機体の鉄則を手で
312
+ # 直していた場合、その内容は何も残らずに消える。同じ update-guard.sh は、お客さまの
313
+ # settings.json を書き換えるときは必ず日時つきの控えを残す(4か所)。鉄則だけが
314
+ # 控えを残さない、という食い違いをここで揃える。
315
+ # 【★なぜ ~/.claude/skills の中に置かないか】
316
+ # 職人の鉄則は ~/.claude/skills/<名前>/SKILL.md として読み込まれる。控えを同じ所へ置くと、
317
+ # ★中身の違う鉄則が2つ並ぶ形になり、読み込まれる恐れが出る(鉄則は1台に1つが約束)。
318
+ # だから ~/.claude の外へ出す。置き場は番人の控えと同じ ~/.tyhld の下にする=
319
+ # 職人はそこへ書けない(番人が止める)ので、控えを後から書き換えられない。
320
+ # 【名前の流儀】settings.json の控えと同じ「<元の名前>.bak.<日時>」に揃える。
321
+ CRAFTSMAN_BACKUP_DIR="$HOME/.tyhld/skill-backups"
322
+ #: この回の控えの場所(記録に載せる)。作らなかったときは none のまま。
323
+ CRAFTSMAN_BACKUP="none"
324
+
310
325
  # 版=この正本が入っている配布物の版(package.json)。無ければ unknown。
311
326
  craftsman_skill_version() {
312
327
  local pj="$DIST_ROOT/package.json"
@@ -328,7 +343,7 @@ craftsman_skill_sha() {
328
343
  craftsman_record() {
329
344
  local status="$1" reason="$2" ver="$3" sha="$4"
330
345
  local line
331
- line="$(date '+%Y-%m-%dT%H:%M:%S%z') status=${status} reason=${reason} version=${ver} sha=${sha} src=${CRAFTSMAN_SKILL_SRC} dst=${CRAFTSMAN_SKILL_DST}"
346
+ line="$(date '+%Y-%m-%dT%H:%M:%S%z') status=${status} reason=${reason} version=${ver} sha=${sha} backup=${CRAFTSMAN_BACKUP} src=${CRAFTSMAN_SKILL_SRC} dst=${CRAFTSMAN_SKILL_DST}"
332
347
  mkdir -p "$GUARD_HOME" 2>/dev/null || true
333
348
  printf '%s\n' "$line" > "$CRAFTSMAN_LAST" 2>/dev/null || true
334
349
  if [[ "$status" == "ok" ]]; then
@@ -336,6 +351,24 @@ craftsman_record() {
336
351
  fi
337
352
  }
338
353
 
354
+ # 上書きする前に、いま機体に在る鉄則の控えを取る。
355
+ # 返り 0 … 控えは要らなかった(初めて配る)/控えを取れた
356
+ # 返り 1 … ★控えを取れなかった(=上書きしてはいけない)
357
+ # ★控えを取れたときだけ CRAFTSMAN_BACKUP に場所が入る。
358
+ craftsman_backup() {
359
+ CRAFTSMAN_BACKUP="none"
360
+ # 初めて配るとき(機体に鉄則が無い)は、消える物が無いので控えも作らない。
361
+ [[ -f "$CRAFTSMAN_SKILL_DST" ]] || return 0
362
+ local dst
363
+ dst="$CRAFTSMAN_BACKUP_DIR/conductor-craftsman-SKILL.md.bak.$(date '+%Y%m%d-%H%M%S')"
364
+ mkdir -p "$CRAFTSMAN_BACKUP_DIR" 2>/dev/null || return 1
365
+ cp -p "$CRAFTSMAN_SKILL_DST" "$dst" 2>/dev/null || return 1
366
+ # ★取れたと言い切る前に、中身が同じことを確かめる(空の控えを成功と呼ばない)。
367
+ cmp -s "$CRAFTSMAN_SKILL_DST" "$dst" 2>/dev/null || return 1
368
+ CRAFTSMAN_BACKUP="$dst"
369
+ return 0
370
+ }
371
+
339
372
  # 配り損ねを管制へ知らせる(★届かなくても同期は止めない)。
340
373
  craftsman_notify_failure() {
341
374
  [[ -f "$CRAFTSMAN_NOTIFY" ]] || return 0
@@ -357,9 +390,17 @@ elif cmp -s "$CRAFTSMAN_SKILL_SRC" "$CRAFTSMAN_SKILL_DST" 2>/dev/null; then
357
390
  info " 最新です(版 ${CRAFTSMAN_VER} / 中身 ${CRAFTSMAN_SHA})"
358
391
  craftsman_record ok already-current "$CRAFTSMAN_VER" "$CRAFTSMAN_SHA"
359
392
  elif [[ "$APPLY" == "1" ]]; then
360
- if mkdir -p "$(dirname "$CRAFTSMAN_SKILL_DST")" 2>/dev/null \
393
+ # ★消える物が在るなら、上書きの【前】に控えを取る。取れなければ上書きしない。
394
+ if ! craftsman_backup; then
395
+ warn "上書きの前の控えを取れませんでした: $CRAFTSMAN_BACKUP_DIR(★鉄則は上書きしません)"
396
+ craftsman_record failed backup-failed "$CRAFTSMAN_VER" "$CRAFTSMAN_SHA"
397
+ craftsman_notify_failure
398
+ elif mkdir -p "$(dirname "$CRAFTSMAN_SKILL_DST")" 2>/dev/null \
361
399
  && cp -f "$CRAFTSMAN_SKILL_SRC" "$CRAFTSMAN_SKILL_DST" 2>/dev/null \
362
400
  && cmp -s "$CRAFTSMAN_SKILL_SRC" "$CRAFTSMAN_SKILL_DST" 2>/dev/null; then
401
+ if [[ "$CRAFTSMAN_BACKUP" != "none" ]]; then
402
+ info " 上書きの前の控え: $CRAFTSMAN_BACKUP"
403
+ fi
363
404
  info " 更新しました(版 ${CRAFTSMAN_VER} / 中身 ${CRAFTSMAN_SHA}・この1台の全現場が共有します)"
364
405
  craftsman_record ok applied "$CRAFTSMAN_VER" "$CRAFTSMAN_SHA"
365
406
  else