#!/usr/bin/env sh
# cc-tmux: /rename 即時追従ウォッチャ(FR-041 強化, T044)。
# 参照: contracts/hooks.md, lib/name.sh
#
# Claude Code は /rename・セッション命名時に transcript(JSONL) へ
# {"type":"custom-title","customTitle":"..."} を追記する。本スクリプトは
# transcript を tail -F で監視し、custom-title 行が追記された瞬間に
# タブ名を追従させる。追記イベントでのみ動くイベント駆動であり、
# 定期ポーリング(sleep ループでの再読込)はしない。
#
# 引数: <session_id> <window_id> <transcript_path>
# 起動: フック(SessionStart/busy)から setsid/nohup でデタッチ起動(多重防止 pidfile)。
# 終了: SessionEnd の stop_namewatch(kill)、または状態ディレクトリ消滅の検知。
set -u
CC_DIR=$(cd "$(dirname "$0")/.." && pwd)
. "$CC_DIR/lib/state.sh"
. "$CC_DIR/lib/tmux.sh"
. "$CC_DIR/lib/name.sh"
sid=${1:-}
win=${2:-}
tr_path=${3:-}
[ -n "$sid" ] && [ -n "$win" ] && [ -n "$tr_path" ] || exit 0
[ -f "$tr_path" ] || exit 0
cc_in_tmux || exit 0
command -v jq >/dev/null 2>&1 || exit 0
d=$(cc_state_dir "$sid")
[ -d "$d" ] || exit 0
pidf="$d/namewatch.pid"
# 多重防止(スピナーと同じ pidfile 方式)。
if [ -f "$pidf" ]; then
p=$(cat "$pidf" 2>/dev/null)
if [ -n "$p" ] && kill -0 "$p" 2>/dev/null; then
exit 0
fi
fi
printf '%s' "$$" >"$pidf"
fifo="$d/namewatch.fifo"
rm -f "$fifo"
mkfifo "$fifo" 2>/dev/null || exit 0
# tail は明示 pid で管理する(macOS には setsid が無くプロセスグループ kill が
# 使えないため、グループではなく個別に殺す)。
tail -n 0 -F "$tr_path" >"$fifo" 2>/dev/null &
tailpid=$!
cleanup() {
trap - EXIT TERM INT
kill "$tailpid" 2>/dev/null
rm -f "$pidf" "$fifo" 2>/dev/null
}
trap cleanup EXIT
trap 'cleanup; exit 0' TERM INT
# 最新の明示名を反映(変化時のみ)。ロジックはフックの follow_name と同一。
apply() {
n=$(name_follow "$sid" "$tr_path" 2>/dev/null) || return 0
[ -n "$n" ] || return 0
prev=$(state_meta "$sid" name 2>/dev/null) || prev=""
if [ "$n" != "$prev" ]; then
state_meta_set "$sid" name "$n"
cc_tmux_rename_force "$win" "$n"
cc_tmux_refresh
fi
}
# 追記行のうち custom-title を含むものにだけ反応する。
while IFS= read -r line; do
[ -d "$d" ] || break # SessionEnd 後(状態破棄済み)は自主終了
case $line in
*'"custom-title"'*) apply ;;
esac
done <"$fifo"
exit 0