Skip to content

fix: auto-update の稼働確認が登録済みの hook を未登録と誤判定する問題を修正(v0.76.1) - #164

Merged
okash1n merged 1 commit into
mainfrom
fix/auto-update-health-jq-any
Aug 31, 2026
Merged

fix: auto-update の稼働確認が登録済みの hook を未登録と誤判定する問題を修正(v0.76.1)#164
okash1n merged 1 commit into
mainfrom
fix/auto-update-health-jq-any

Conversation

@loadbalance-sudachi-kun

Copy link
Copy Markdown
Contributor

Fixes #161

概要

_check_auto_update_health の hook 検出が jq -e の「最後の出力で終了コードを決める」仕様に依存しており、auto-update より後ろに別の SessionStart hook が登録されていると、登録済みでも未登録と判定していた。

機能自体は正常に動作しており、変わるのは表示のみ。

原因

jq -e '.hooks.SessionStart[]?.hooks[]?.command | contains("auto-update")' "$settings"

.hooks.SessionStart[]?.hooks[]?.command は hook の数だけ出力を生成する。jq -e の終了コードは最後の出力で決まるため、配列の末尾が auto-update 以外だと false が最後になり exit 1 となる。

回避できる設定が存在しなかった

イシュー本文では「推測される」とされていた点を確認した。

  • _FEATURE_ORDERlib/features.sh:56-61)は feature-recommendation を末尾に置く
  • _feature_deploy_enabledlib/features.sh:74-88)は、非 MDM では ENABLE_FEATURE_RECOMMENDATION の値によらず return 0 する
  • merge_deeplib/json-builder.sh:111-120)は配列を連結するため、この順序がそのまま settings.json に反映される

したがって非 MDM かつ auto-update 有効な環境では、SessionStart の末尾が auto-update になる設定が存在しない。

イシュー本文より影響範囲が広い点

_check_auto_update_health の呼び出し箇所は 2 つある。

  • lib/update.sh(更新完了時)
  • setup.shsetup_finalize

イシューは setup.sh --update のみと記載しているが、Standard / Full の新規インストール完了時にも同じ誤警告が出ていた--dry-run_update_report が早期 return するため影響しない。

修正

any(GEN; COND) で単一の真偽値に畳み込む。同ファイルの _strip_retired_hook_entries(L1290 / L1331)が既に使っているイディオムに揃えた。

jq -e 'any(.hooks.SessionStart[]?.hooks[]?.command?;
           type == "string" and contains("auto-update"))' "$settings"

イシューの提案フィルタを採用しなかった理由

イシューの [...] | any(contains("auto-update")) は順序依存を解消するが、command キーを持たない hook エントリがあると null | contains(...) で jq がエラー終了(exit 5)する。終了コードを捨てている以上、これは「未登録」と区別できず同じ誤警告が再発する

7 パターンでの実測(jq-1.7.1-apple):

ケース 現行 イシュー案 採用案 期待
auto-update の後に別 hook 1 0 0 0
auto-update が末尾 0 0 0 0
auto-update なし 1 1 1 1
{} 4 1 1 非 0
command キー欠落が先行 5 5 0 0
command が非文字列で先行 5 5 0 0
不正 JSON 5 5 5 → 判定不能扱い

SessionEnd 側もあわせて修正

隣接する SessionEnd 判定(L2104)も同じ形だった。SessionEnd hook を登録する feature は現状 auto-update だけなので顕在化していないが、2 つ目が追加された時点で同じ誤判定になる。片方だけ直すと罠が残るため同時に修正した。

判定不能を「有効」と報告しないようにした

イシューの「補足(副次的な点)」に対応する。

jq が無い場合のフォールバックは grep -q '"SessionStart"'grep -q "auto-update" をファイル全体に対して独立に評価していた。両者が同じ file-wide マッチを共有するため、SessionEnd にしか auto-update が無くても両方登録済みと判定する。これは #161 とは逆方向の誤り(半登録を「有効」と報告)。

jq は前提ツール(check_jqsetup.sh の全経路を gate する)でこの分岐は実質到達しない。そのためフォールバックを削除し、probe_rc で 0 / 1 / その他を区別して、判定不能時は警告も「有効です」の表示も行わないようにした。settings.json が読めない・壊れている場合も同様に扱う。これも _strip_retired_hook_entries が既に使っているパターン。

テスト

tests/unit/test-auto-update.sh に 8 件追加した。同関数にはこれまでテストが無く、tests/unit/test-setup-refactor.sh:768 に無効化用のスタブがあるだけだった。

関数が $HOME/.claude-starter-kit を参照し、Check 2 / 3 が同じ issues[] に積むため、HOME を temp に隔離しないと開発機の状態で結果が変わる。テストは HOME を上書きし、固定トークンに置き換えた STR_* で判定する。

修正前のコードでは 8 件中 4 件が失敗する(順序依存 / command 欠落 / legacy CLI の SessionEnd / 不正 JSON)。

実行した検証

  • shellcheck -S warning lib/update.sh tests/unit/test-auto-update.sh — いずれもクリーン
  • tests/unit/test-auto-update.sh — 19/19 通過(修正前 15/19)
  • tests/run-unit-tests.sh — 598 PASS。失敗は fonts: direct download fallback receives font definition 1 件のみで、これは変更前(554e455)にも再現する既存のもの

アップグレード経路

ENABLE_* フラグ、profile 既定値、生成ファイル、settings キー、manifest のいずれも追加・変更していない。変更は診断関数の判定ロジックに閉じており、保存済み設定の解釈も変えていないため、既存インストールが取りこぼす新規キーはない。既存環境では、次回の更新または新規インストール完了時から誤警告が出なくなる。

ドキュメント

  • CHANGELOG.md — 更新済み(## [0.76.1]
  • i18n/en/strings.sh / i18n/ja/strings.sh — 変更不要。STR_AUTOUPDATE_NO_HOOK は SessionStart 欠落と SessionEnd 欠落の両分岐から出力されるため「揃って登録されていません」の文言は修正後も正確。tests/unit/test-i18n-strings.sh はキーのパリティのみ検査しており、キーの増減もない
  • README.md / README.en.md / docs/ — 変更不要。この稼働確認とその警告文はどこにも記載されていない
  • MDM — 影響なし。mdm/render-expected.pylib/features.sh / profiles/*.conf / i18n/*/CLAUDE.md.base / feature partials のみを読み、lib/update.sh は読まない。lib/*.sh~/.claude に配布もされない

🤖 Generated with Claude Code

Fixes #161

_check_auto_update_health が次のフィルタで判定していた。

  jq -e '.hooks.SessionStart[]?.hooks[]?.command | contains("auto-update")'

このフィルタは hook 1 件につき 1 出力を出し、jq -e は最後の出力だけで
終了コードを決める。auto-update より後ろに別の SessionStart hook が
登録されていると最後が false になり exit 1、登録済みでも未登録と判定
されていた。

_FEATURE_ORDER は feature-recommendation を末尾に置き、
_feature_deploy_enabled は非 MDM では ENABLE_FEATURE_RECOMMENDATION の値に
よらず常に配備する。このため Standard / Full の通常環境では、この誤警告を
回避できる設定が存在しなかった。

any(GEN; COND) で単一の真偽値に畳み込む形に変更した。同ファイルの
_strip_retired_hook_entries(L1290 / L1331)が既に使っているイディオムに
揃えている。

あわせて修正した点:

- SessionEnd 側(L2104)も同じ形だった。SessionEnd hook を登録する feature
  は現状 auto-update だけなので顕在化していないが、2 つ目が追加された
  時点で同じ誤判定になる。片方だけ直すと罠が残るため同時に修正した
- command キーを持たない hook エントリがあると null | contains(...) が
  jq をエラー終了(exit 5)させ、終了コードを捨てている以上「未登録」と
  区別できなかった。type == "string" ガードを追加した
- 呼び出し箇所は lib/update.sh(更新完了時)と setup.sh(setup_finalize)の
  2 つで、新規インストールでも同じ誤警告が出ていた。イシュー本文は更新時
  のみと記載していたが、実際にはより広い

判定不能を「有効」と報告しないようにした:

  jq が無い場合のフォールバックは grep -q '"SessionStart"' と
  grep -q "auto-update" をファイル全体に対して独立に評価しており、
  SessionEnd にしか auto-update が無くても両方登録済みと判定していた。
  これは #161 とは逆方向の誤りで、イシューでも副次的な点として挙げられて
  いる。jq は前提ツールでこの分岐は実質到達しないため、フォールバックを
  削除し、判定不能時は警告も「有効です」の表示も行わないようにした。
  settings.json が読めない・壊れている場合も同様に扱う。

回帰テスト 8 件を tests/unit/test-auto-update.sh に追加した。関数が
$HOME/.claude-starter-kit を参照するため、HOME を temp に隔離しないと
開発機の状態に依存する。

検証:
- shellcheck -S warning: lib/update.sh / tests/unit/test-auto-update.sh ともにクリーン
- tests/unit/test-auto-update.sh: 19/19 通過(修正前は 15/19、新規 8 件のうち 4 件が失敗)
- tests/run-unit-tests.sh: 既存の fonts 失敗 1 件のみ。本変更に起因する失敗なし

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Aug 31, 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-08-31T05:21:40.016057Z 7e0a5a9 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.

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.

auto-update hook が登録済みでも「自動更新は無効です」と誤警告される(jq -e の複数出力による順序依存)

2 participants