diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c086af..2699982 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/), and this project adheres to [Semantic Versioning](https://semver.org/). +## [0.61.0] - 2026-06-12 + +LLM 性能監査(#121)P2 の第 1 弾(#111)。tmux-hooks のハードブロックをリマインダーに降格した。 + +### Changed +- **tmux-hooks のハードブロックを非ブロックのリマインダーに降格(#111)**: TMUX 外での dev サーバー起動(`npm run dev` 等)を exit 2 でブロックしていた挙動を撤廃。現行 Claude Code はネイティブの background 実行(`run_in_background`)とログ取得を備えており、ブロックはむしろネイティブ機能の利用を妨害していた。新挙動: (1) `run_in_background=true` は即許可(出力なし)、(2) TMUX 外の foreground dev サーバーは exit 0 + stderr 1 行のリマインダー(run_in_background を第一候補、永続セッションが必要なら tmux を代替として提示)、(3) npm test / cargo build / docker 等への「Consider running in tmux」定常 advisory は削除(高頻度コマンドへの情報量ゼロのノイズ) + ## [0.60.0] - 2026-06-12 LLM 性能監査(#121)P1 の最終弾(#110)。pre-compact-commit を opt-in 化し、履歴を汚さない stash 方式に書き換えた。 diff --git a/README.en.md b/README.en.md index 3990f9e..13350dd 100644 --- a/README.en.md +++ b/README.en.md @@ -190,7 +190,7 @@ Hooks are automated safety checks that run automatically when Claude Code execut |---|---| | **Safety Net** | Blocks destructive git/filesystem commands (`git reset --hard`, `rm -rf`, `git push --force`, etc.) before execution | | **Auto Update** | Checks for starter kit updates on session start and applies them in the background | -| Tmux Reminder | Suggests tmux for long-running commands | +| Tmux Reminder | Suggests run_in_background for foreground dev servers (non-blocking) | | Git Push Review | Pauses before git push for code review | | Doc Blocker | Prevents creation of unnecessary .md/.txt files | | Prettier Auto-format | Formats JS/TS files after edits | diff --git a/README.md b/README.md index 2f14261..0ea374a 100644 --- a/README.md +++ b/README.md @@ -470,7 +470,7 @@ URL・公式ドキュメント・ブログ・ニュース・OSS ページを読 |---|---| | **Safety Net** | **破壊的な git/ファイルシステムコマンド(`git reset --hard`、`rm -rf` 等)を実行前にブロック** | | **自動アップデート** | **セッション開始時にスターターキットの最新版を自動で適用** | -| Tmux リマインダー | 長時間コマンドに tmux の使用を提案 | +| Tmux リマインダー | foreground の dev サーバーに run_in_background を提案(非ブロック) | | Git Push レビュー | コードを共有する前に確認を促す | | Doc ブロッカー | 不要なドキュメントファイルの作成を防止 | | Prettier 自動フォーマット | JS/TS ファイルを自動で見た目を整える | diff --git a/docs/wizard-config-mapping.en.md b/docs/wizard-config-mapping.en.md index 0ccffc0..bc216bd 100644 --- a/docs/wizard-config-mapping.en.md +++ b/docs/wizard-config-mapping.en.md @@ -58,7 +58,7 @@ These flags are used to merge the corresponding `features/*/hooks.json` fragment | `ENABLE_SAFETY_NET` | Safety Net | Block destructive commands | Yes | | `ENABLE_AUTO_UPDATE` | Auto Update | Check for starter kit updates on session start | Yes | | `ENABLE_WEB_CONTENT_UPDATE` | Web Content Update | Check web extraction skill dependency updates | Yes | -| `ENABLE_TMUX_HOOKS` | Tmux Reminder | Encourage tmux for long-running work | Yes | +| `ENABLE_TMUX_HOOKS` | Tmux Reminder | Suggest run_in_background for foreground dev servers (non-blocking) | Yes | | `ENABLE_GIT_PUSH_REVIEW` | Git Push Review | Pause before push and open a diff | Yes | | `ENABLE_DOC_BLOCKER` | Doc Blocker | Prevent unnecessary `.md` / `.txt` files | Yes | | `ENABLE_PRETTIER_HOOKS` | Prettier Auto-format | Format JS / TS edits | Yes | diff --git a/docs/wizard-config-mapping.md b/docs/wizard-config-mapping.md index 8723df8..6dd5dbc 100644 --- a/docs/wizard-config-mapping.md +++ b/docs/wizard-config-mapping.md @@ -58,7 +58,7 @@ | `ENABLE_SAFETY_NET` | Safety Net | 危険なコマンドの遮断 | はい | | `ENABLE_AUTO_UPDATE` | Auto Update | セッション開始時の更新確認 | はい | | `ENABLE_WEB_CONTENT_UPDATE` | Web Content Update | Web 取得スキル依存の更新確認 | はい | -| `ENABLE_TMUX_HOOKS` | Tmux Reminder | 長時間処理を tmux に誘導 | はい | +| `ENABLE_TMUX_HOOKS` | Tmux Reminder | foreground の dev サーバーに run_in_background を提案(非ブロック) | はい | | `ENABLE_GIT_PUSH_REVIEW` | Git Push Review | push 前に差分確認 | はい | | `ENABLE_DOC_BLOCKER` | Doc Blocker | 不要な `.md` / `.txt` 作成を抑制 | はい | | `ENABLE_PRETTIER_HOOKS` | Prettier Auto-format | JS / TS 編集後の整形 | はい | diff --git a/features/tmux-hooks/feature.json b/features/tmux-hooks/feature.json index 98d596b..b9b7abb 100644 --- a/features/tmux-hooks/feature.json +++ b/features/tmux-hooks/feature.json @@ -1,10 +1,14 @@ { "name": "tmux-hooks", "displayName": "Tmux Reminder", - "description": "Block dev servers outside tmux and suggest tmux for long-running commands", + "description": "Non-blocking reminder: suggest run_in_background (or tmux) for foreground dev servers", "category": "hook", "default": true, - "profiles": { "minimal": false, "standard": true, "full": true }, + "profiles": { + "minimal": false, + "standard": true, + "full": true + }, "dependencies": [], "conflicts": [] } diff --git a/features/tmux-hooks/scripts/check-bash.sh b/features/tmux-hooks/scripts/check-bash.sh index dcd6e48..fc0393a 100755 --- a/features/tmux-hooks/scripts/check-bash.sh +++ b/features/tmux-hooks/scripts/check-bash.sh @@ -3,17 +3,18 @@ set -euo pipefail input="$(cat)" cmd="$(printf '%s' "$input" | jq -r '.tool_input.command // ""')" +run_in_background="$(printf '%s' "$input" | jq -r '.tool_input.run_in_background // false')" +# Native background execution manages the process and its logs — nothing to add. +if [[ "$run_in_background" == "true" ]]; then + exit 0 +fi + +# Foreground dev server outside tmux: non-blocking reminder only. if printf '%s' "$cmd" | grep -qE '(npm run dev|pnpm( run)? dev|yarn dev|bun run dev)' \ && [[ -z "${TMUX:-}" ]] \ && ! printf '%s' "$cmd" | grep -qE 'tmux[[:space:]]+(new-session|new|send-keys)'; then - echo '[Hook] BLOCKED: Dev server must run in tmux for log access' >&2 - echo '[Hook] Use: tmux new-session -d -s dev "npm run dev"' >&2 - echo '[Hook] Then: tmux attach -t dev' >&2 - exit 2 + echo '[Hook] Reminder: prefer run_in_background for dev servers (or tmux new-session for a persistent session)' >&2 fi -if printf '%s' "$cmd" | grep -qE '(npm (install|test)|pnpm (install|test)|yarn (install|test)|bun (install|test)|cargo build|make|docker|pytest|vitest|playwright)' \ - && [[ -z "${TMUX:-}" ]]; then - echo '[Hook] Consider running in tmux for session persistence' >&2 -fi +exit 0 diff --git a/i18n/en/strings.sh b/i18n/en/strings.sh index 69bf3d1..2602e79 100644 --- a/i18n/en/strings.sh +++ b/i18n/en/strings.sh @@ -84,7 +84,7 @@ STR_HOOKS_TITLE="Select hooks to enable (enter numbers separated by spaces):" STR_HOOKS_SAFETY_NET="Safety Net - Block destructive git/filesystem commands (cc-safety-net)" STR_HOOKS_AUTO_UPDATE="Auto Update - Automatically update starter kit on session start" STR_HOOKS_WEB_CONTENT_UPDATE="Web Content Update - Auto-update web-content-extraction skill deps on session start (opt-in)" -STR_HOOKS_TMUX="Tmux Reminder - Suggest tmux for long-running commands" +STR_HOOKS_TMUX="Tmux Reminder - Suggest run_in_background for foreground dev servers (non-blocking)" STR_HOOKS_GIT_PUSH="Git Push Review - Pause before git push for review" STR_HOOKS_DOC_BLOCK="Doc Blocker - Block creation of random .md/.txt files" STR_HOOKS_PRETTIER="Prettier Auto-format - Format JS/TS files after edits" diff --git a/i18n/ja/strings.sh b/i18n/ja/strings.sh index 8b0e420..56e296c 100644 --- a/i18n/ja/strings.sh +++ b/i18n/ja/strings.sh @@ -82,7 +82,7 @@ STR_HOOKS_TITLE="有効にするフックを選択してください(番号を STR_HOOKS_SAFETY_NET="Safety Net - 破壊的な git/ファイルシステムコマンドをブロック (cc-safety-net)" STR_HOOKS_AUTO_UPDATE="自動アップデート - セッション開始時にスターターキットを自動更新" STR_HOOKS_WEB_CONTENT_UPDATE="Web取得スキル更新 - セッション開始時に web-content-extraction の依存を自動更新(opt-in)" -STR_HOOKS_TMUX="Tmux リマインダー - 長時間コマンドに tmux を提案" +STR_HOOKS_TMUX="Tmux リマインダー - foreground の dev サーバーに run_in_background を提案(非ブロック)" STR_HOOKS_GIT_PUSH="Git Push レビュー - push 前に一時停止してレビュー" STR_HOOKS_DOC_BLOCK="ドキュメントブロッカー - 不要な .md/.txt ファイルの作成を防止" STR_HOOKS_PRETTIER="Prettier 自動フォーマット - JS/TS ファイルを編集後にフォーマット" diff --git a/tests/unit/test-hook-fixtures.sh b/tests/unit/test-hook-fixtures.sh index 99a6768..6534649 100644 --- a/tests/unit/test-hook-fixtures.sh +++ b/tests/unit/test-hook-fixtures.sh @@ -105,13 +105,13 @@ bash "$PROJECT_DIR/features/git-push-review/scripts/remind.sh" <"$_pre_push_fixt bash "$PROJECT_DIR/features/feature-recommendation/scripts/check-pending.sh" <"$_hook_fixture_dir/sessionstart-startup.json" >/dev/null 2>/dev/null || _script_smoke_ok=false _tmux_rc=0 -bash "$PROJECT_DIR/features/tmux-hooks/scripts/check-bash.sh" <"$_pre_dev_fixture" >/dev/null 2>"$_hook_tmp/tmux.err" || _tmux_rc=$? +env -u TMUX bash "$PROJECT_DIR/features/tmux-hooks/scripts/check-bash.sh" <"$_pre_dev_fixture" >/dev/null 2>"$_hook_tmp/tmux.err" || _tmux_rc=$? if [[ "$_script_smoke_ok" == "true" ]] \ && assert_matches "console\\.log found" "$(cat "$_hook_tmp/console.err")" \ && assert_matches "Reminder: review your staged changes" "$(cat "$_hook_tmp/push.err")" \ - && [[ "$_tmux_rc" -eq 2 ]] \ - && assert_matches "Dev server must run in tmux" "$(cat "$_hook_tmp/tmux.err")"; then + && [[ "$_tmux_rc" -eq 0 ]] \ + && assert_matches "prefer run_in_background" "$(cat "$_hook_tmp/tmux.err")"; then pass "hook-fixtures: distributed hook scripts consume real-schema fixtures" else fail "hook-fixtures: distributed hook scripts should consume real-schema fixtures" diff --git a/tests/unit/test-runtime-hooks.sh b/tests/unit/test-runtime-hooks.sh index 4ad82c1..41f6f3a 100644 --- a/tests/unit/test-runtime-hooks.sh +++ b/tests/unit/test-runtime-hooks.sh @@ -75,3 +75,62 @@ fail "$test_name" fi } + + +{ + test_name="tmux-hooks: run_in_background dev server passes without any output" + _th_tmp="$(mktemp -d)" + _SETUP_TMP_FILES+=("$_th_tmp") + _th_rc=0 + printf '{"tool_name":"Bash","tool_input":{"command":"%s","run_in_background":true}}' "npm run dev" \ + | env -u TMUX bash "$PROJECT_DIR/features/tmux-hooks/scripts/check-bash.sh" >/dev/null 2>"$_th_tmp/bg.err" || _th_rc=$? + if [[ "$_th_rc" -eq 0 ]] && [[ ! -s "$_th_tmp/bg.err" ]]; then + pass "$test_name" + else + fail "$test_name" + fi +} + +{ + test_name="tmux-hooks: foreground dev server is a non-blocking reminder (no exit 2)" + _th_tmp2="$(mktemp -d)" + _SETUP_TMP_FILES+=("$_th_tmp2") + _th_rc=0 + printf '{"tool_name":"Bash","tool_input":{"command":"%s"}}' "npm run dev" \ + | env -u TMUX bash "$PROJECT_DIR/features/tmux-hooks/scripts/check-bash.sh" >/dev/null 2>"$_th_tmp2/fg.err" || _th_rc=$? + if [[ "$_th_rc" -eq 0 ]] \ + && grep -q "prefer run_in_background" "$_th_tmp2/fg.err" \ + && ! grep -q "BLOCKED" "$_th_tmp2/fg.err"; then + pass "$test_name" + else + fail "$test_name" + fi +} + +{ + test_name="tmux-hooks: build/test commands no longer trigger advisory noise" + _th_tmp3="$(mktemp -d)" + _SETUP_TMP_FILES+=("$_th_tmp3") + _th_rc=0 + printf '{"tool_name":"Bash","tool_input":{"command":"npm test"}}' \ + | env -u TMUX bash "$PROJECT_DIR/features/tmux-hooks/scripts/check-bash.sh" >/dev/null 2>"$_th_tmp3/adv.err" || _th_rc=$? + if [[ "$_th_rc" -eq 0 ]] && [[ ! -s "$_th_tmp3/adv.err" ]]; then + pass "$test_name" + else + fail "$test_name" + fi +} + +{ + test_name="tmux-hooks: dev server inside tmux session stays silent" + _th_tmp4="$(mktemp -d)" + _SETUP_TMP_FILES+=("$_th_tmp4") + _th_rc=0 + printf '{"tool_name":"Bash","tool_input":{"command":"npm run %s"}}' "dev" \ + | env TMUX=fake-session bash "$PROJECT_DIR/features/tmux-hooks/scripts/check-bash.sh" >/dev/null 2>"$_th_tmp4/in-tmux.err" || _th_rc=$? + if [[ "$_th_rc" -eq 0 ]] && [[ ! -s "$_th_tmp4/in-tmux.err" ]]; then + pass "$test_name" + else + fail "$test_name" + fi +}