Skip to content

feat: Bash 優先指示を解除する native-file-tools フックを追加(v0.78.0) - #170

Merged
okash1n merged 2 commits into
mainfrom
fix/bash-first-steer-native-tools
Sep 7, 2026
Merged

feat: Bash 優先指示を解除する native-file-tools フックを追加(v0.78.0)#170
okash1n merged 2 commits into
mainfrom
fix/bash-first-steer-native-tools

Conversation

@loadbalance-sudachi-kun

Copy link
Copy Markdown
Contributor

概要

Claude Code 2.1.261 は auto / bypassPermissions モードのセッションに「ファイルの読み書きは Read/Edit/Write ではなく cat / sed / heredoc で行え」という指示を注入する(バイナリ内の未文書化 feature flag CLAUDE_CODE_THRIFTY_SONIC。Fable 5.1 系モデルでは強制有効、Opus 5 は GrowthBook のコホート配信)。この状態ではモデルが Read/Edit/Write をほぼ使わないため、キットの次の仕組みが無音で動かなくなる

  • PostToolUse Edit|Write の prettier-hooks / biome-hooks、PreToolUse Write の doc-blocker、PostToolUse Write の doc-size-guard
  • paths: 付き Rules とサブディレクトリの CLAUDE.md(Read 時に読み込まれる仕組みのため)
  • native checkpoint / rewind の変更追跡、security-guidance の編集時パターン警告

settings.jsonenvCLAUDE_CODE_THRIFTY_SONIC="0" を入れる env-only feature native-file-tools を追加し、Standard / Full で既定有効にする。あわせて、レビューで見つかった既存バグ(custom プロファイルで保存設定を再利用すると agent-teams の env が配布されない)を修正した。

発端: https://kawasin73.hatenablog.com/entry/2026/09/05/092056

実 CLI での再現と修正確認

条件: Claude Code 2.1.261、claude-fable-5-1、--permission-mode auto--setting-sources project --strict-mcp-config --permission-prompts none。合成 git リポジトリを新規セッションごとに複製し、同一課題(TS 関数リネーム、docs 追記、AGENTS.md 作成、SUMMARY.md 作成)を与えた。観測は stream-json --include-hook-events、観測専用フック(PreToolUse / PostToolUse / InstructionsLoaded)、git 差分、トランスクリプトに永続化される auto_mode attachment で行い、モデルの自己申告は使っていない。

条件 指示注入 (bashFirst) 使用ツール Biome 整形 doc-blocker ask doc-size 警告 paths Rules / nested CLAUDE.md
auto・フラグなし ×3 true Bash のみ 0/3 0/3 0/3 0/3
auto・"0" ×3 なし Read/Write(+Bash) 3/3 3/3 2/3 ※ 3/3
auto・キット生成 settings.json ×2 なし Read/Edit/Write 2/2 2/2 2/2 2/2
acceptEdits・フラグなし なし Read/Write – ※
acceptEdits・"1" なし Read/Write
bypassPermissions・フラグなし true (bypass) Bash のみ × × × ×
auto・フラグなし・「Read/Edit/Write を使え」 true Read/Edit/Write
auto・"0"・「Bash で編集しろ」 なし Bash のみ × × × ×

※ 初回 3 セッションは課題文の AGENTS.md 作成が seq で済む書き方で Write が発生せず、doc-size-guard の正常対照が成立していない。課題文を修正した以降はすべて発火した。

default / plan モードは実測していない(バイナリの条件式が auto / bypassPermissions 以外で即座に空を返すことからの判断)。prettier-hooks は PATH に prettier がなく、同じ tool_input.file_path 契約の biome-hooks で代表した。

修正内容

  • features/native-file-tools/: hooks.json{"env":{"CLAUDE_CODE_THRIFTY_SONIC":"0"}} のみ。agent-teams / no-flicker と同じ配布形態
  • 登録: lib/features.shprofiles/*.conf(Standard / Full true、Minimal false)、wizard/defaults.confwizard/registry.sh_CONFIG_KEYS、HOOK_KEYS / HOOK_TOKENS native-tools / HOOK_LABELS)、wizard/steps.sh(確認画面・非対話デフォルト)、wizard/wizard.sh(グローバル初期化・更新経路の補完)、i18n/{en,ja}/strings.shmdm/install-mdm.sh(許可キー 2 か所)
  • _fill_late_feature_defaultswizard/registry.sh に新設): agent-teams / native-file-tools の後発キー補完を集約し、更新経路(_restore_config_from_manifest)・非対話 fresh install(_fill_noninteractive_defaults)・対話ウィザードの保存設定再利用(fill_missing_profile_defaults)の 3 経路から呼ぶ
  • ドキュメント: README(日英)に仕組み・保証範囲・無効化方法・--hooks 例、security-guidance 編集時警告の適用条件、native rewind が Bash 編集を追跡しない注記。docs/wizard-config-mapping*.mddocs/mdm/README.mdcommands/checkpoint.mdCLAUDE.mdCHANGELOG.md(0.78.0)
  • テスト: tests/unit/test-native-file-tools.sh(17 件。修正前のコードでは 12 件が失敗)、tests/unit/test-docs-sync.sh にキー追加
  • 実 CLI ハーネス(CI 非連動): tests/manual/bash-first-steer/。合成 fixture 生成・ケース実行・集計スクリプトと期待結果表。モデルを実際に呼ぶため通常 CI には組み込まない

修正した既存バグ

custom プロファイルで setup.sh を直接再実行し「保存された設定を再利用する」を選ぶと、fill_missing_profile_defaults はプロファイル conf を読むだけで、conf を持たない custom では後発キーが空のままになり、env フラグメントが出力されていなかった(agent-teams で #138 以来発生。install.sh 経由は常に --update が付くため影響せず、README が案内する「リポジトリ更新後に ./setup.sh を再実行」の手順でのみ発生)。fill_missing_profile_defaults からも補完を呼ぶようにし、回帰テストを追加した。

保証範囲と残る制約

  • 保証するのは通常のツール選択が戻ること。Bash の使用を禁止するものではなく、利用者が Bash 編集を指示した場合やモデルが意図的に Bash を選んだ場合は、従来どおりフック・paths Rules・rewind の対象外(対照ケースで確認)
  • doc-blocker / doc-size-guard が Edit に反応しない点は従来からの制限で、今回の対象外
  • Bash 編集への hook 対応(matcher 追加や git status ベースの後追い整形)は意図的に見送った。任意のシェルを正規表現で解析する方式は誤発火の検証コストに見合わないと判断し、既存制限として文書化した
  • 未文書化フラグのため、Claude Code 側で撤去された場合はフラグメントからキーを外せば、3-way merge がキーを変更していない利用者の settings.json から除去する([P4-14] 配布設定の世代依存ピンの整理(agent-teams env / effortLevel / legacy 経路 / dead var) #120 の effortLevel 撤去と同じ経路)。残っても未知の env は無視される

更新経路(レビュー観点)

経路 挙動
fresh install(minimal / standard / full) profile conf の既定値
fresh install(--profile=custom 非対話) _fill_noninteractive_defaults_fill_late_feature_defaults で true
setup.sh --update / 自動アップデート _restore_config_from_manifest が profile conf → 保存 conf → 補完の順で決める。保存 conf の明示的な false は保持
setup.sh 直接再実行 + 保存設定再利用(対話) fill_missing_profile_defaults_fill_late_feature_defaults(今回修正)
--hooks CSV トークン native-tools
MDM 許可キーに追加。renderer はレジストリ駆動のため変更なし。test-mdm-keys-in-sync で profiles / registry / allowlist の一致を検査
dry-run 通常の deploy フローと同じ build_settings_file を通る

実行した確認

  • bash -c 'source tests/helpers.sh; source tests/unit/test-native-file-tools.sh; print_summary': 修正前 12/14 FAIL → 修正後 17/17 PASS
  • bash tests/run-unit-tests.sh: 828 件中 827 PASS。唯一の FAIL は fonts: direct download fallback receives font definition で、base コミット e3a0dd3 の clean worktree でも同一失敗(環境依存、今回の変更と無関係)。この FAIL で print_summary が非ゼロ終了し MDM スイートに到達しないため、MDM は単独実行した
  • MDM_TEST_BASH=/bin/bash /bin/bash tests/run-mdm-tests.sh(前面・単独実行): 12 ファイル 987 assertions、FAIL 0。nohup 下では runner の HUP self-test が必ず失敗するので注意
  • bash tests/run-scenarios.sh: 49 件中 48 PASS、SKIP 1(bash4-noninteractive-unavailable、Bash 4+ 環境の既定)
  • git ls-files -z '*.sh' | xargs -0 -n 1 shellcheck -S warning(未追跡の新規 .sh も含めて 105 本): 指摘 0
  • 修正後の実 CLI: setup.sh --profile=full --hooks=doc-block,biome,doc-size,native-tools が生成した settings.json をそのまま使った auto モード 2 セッションで、指示注入なし・Read/Edit/Write 使用・3 フック発火・paths Rules / nested CLAUDE.md ロードを確認
  • 独立コードレビュー(4 観点の Reviewer → 各指摘を反証検証、24 エージェント): 確認された 7 件(保存設定再利用の補完漏れ、ハーネスの引数検証順、rewind / kit-removed 経路の文言 ほか)はすべて対応済み

実 CLI の生ログ(stream-json、観測フックの JSONL、git 差分)はセッション固有の一時ディレクトリにあり、PR には含めていない。再実行手順は tests/manual/bash-first-steer/README.md

判断を仰ぎたい点

  • native-file-tools を Standard / Full で既定有効にしてよいか(未文書化フラグの解除設定を既定で配ることの是非)
  • Minimal を既定 false のままにするか(Minimal は rules を配布するが、キット配布の rules は paths: なしで起動時ロードのため影響は利用者追加分に限られる)

Claude Code 2.1.261 が auto / bypassPermissions セッションに注入する
Bash 優先指示(未文書化 flag CLAUDE_CODE_THRIFTY_SONIC)で、Edit|Write
フック・paths 付き Rules・nested CLAUDE.md・native rewind が無音で
動かなくなる問題を実 CLI で再現し、env-only feature として
CLAUDE_CODE_THRIFTY_SONIC=0 を配布する(Standard / Full 既定有効)。

- features/native-file-tools を追加し、registry / profiles / wizard /
  i18n / MDM 許可キー / docs / CHANGELOG 0.78.0 に登録
- 後発キーの補完を _fill_late_feature_defaults に集約し、custom
  プロファイルの保存設定再利用で agent-teams の env が配布されない
  既存バグも修正
- 回帰テスト tests/unit/test-native-file-tools.sh(修正前 12 件 FAIL)と
  実 CLI 検証ハーネス tests/manual/bash-first-steer/(CI 非連動)を追加
- README(日英)に security-guidance 編集時警告の適用条件と native
  rewind が Bash 編集を追跡しない注記を追加
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 6, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-06T08:59:42.710004Z 1640bb8 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

レビューで確認した 3 件に対応した。

- tests/unit/test-native-file-tools.sh: `if ( set -e; ... )` の条件内では
  set -e が効かず、最後のコマンドの終了コードしか判定に使われない。
  レジストリ・hook トークン・--hooks CSV の各アサーションに `|| exit 1` を
  付けて拘束化した。main(修正前)に対する失敗件数は 14 件から 15 件になる
- tests/manual/bash-first-steer/run-case.sh: BFS_KIT_SETTINGS に渡した
  kit 生成 settings.json が SessionStart / SessionEnd フックを含む場合は
  拒否する。フックコマンドは実環境の ~/.claude/hooks/ を指すため、
  Standard / Full の既定値では auto-update(git pull + setup.sh --update)
  などが fixture セッションから実インストールに対して走ってしまう
- ハーネスの README と CHANGELOG の記述を実測に合わせて修正
  (修正前の失敗件数 12 件 → 17 件中 15 件、リリース日 2026-09-07)

Claude-Session: https://claude.ai/code/session_01C9mrbbXQgV9fJ8Zy5UoEYc
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Repo admins can enable using credits for code reviews in their settings.

@okash1n
okash1n merged commit 98124ab into main Sep 7, 2026
11 checks passed
okash1n added a commit that referenced this pull request Sep 8, 2026
Bash は if の条件として実行される ( ... ) サブシェルとその内部の set -e に
対して errexit を無視し、( ... ) || rc=$? も同じ扱いになる。最後のコマンド
の終了コードしか判定に使われないため、途中の [[ ]] や関数呼び出しの失敗は
無視されていた(#170 で test-native-file-tools.sh の 3 ブロックを修正済み)。

tests/unit/*.sh の該当ブロックを全数監査し、実際に非拘束だった 12 文に
house style の `|| exit 1` を付けた。

- test-deploy-refactor.sh (2): build_settings_file の終了コードが捨てられ、
  MDM 側は最終判定が `! jq -e` なのでビルド失敗でも空振りで pass していた
- test-ghostty.sh (5): 否定テストの fixture 生成(_ghostty_test_make_app、
  ln -s)と deploy_ghostty_config の終了コード。fixture が作れなくても
  「拒否された」扱いで pass していた
- test-mdm-install.sh (5): launcher の quiescence / quick-exit ケースは
  最後のコマンドが trap - EXIT や while で _rc が常に 0 になり、PGID と
  group 状態のアサーションが死んでいた

他の 5 ファイル(fonts / prerequisites / update-refactor / setup-refactor /
mdm-detect)は既に拘束済みで変更なし。各修正はアサーションを反転させる
mutation check で FAIL に転じることを確認した。MDM ファイルは CI の
run-mdm-tests.sh が実行時検証。

Claude-Session: https://claude.ai/code/session_01C9mrbbXQgV9fJ8Zy5UoEYc
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants