Skip to content

fix(hooks-stop-quality): 品質ゲートの cwd 依存を修正 (push パイプライン改善 T7) - #284

Merged
aloekun merged 4 commits into
masterfrom
fix/stop-quality-cwd-dependency
Jul 17, 2026
Merged

fix(hooks-stop-quality): 品質ゲートの cwd 依存を修正 (push パイプライン改善 T7)#284
aloekun merged 4 commits into
masterfrom
fix/stop-quality-cwd-dependency

Conversation

@aloekun

@aloekun aloekun commented Jul 17, 2026

Copy link
Copy Markdown
Owner

Summary

  • Stop hook の main 冒頭で cwd をプロジェクトルートへ正規化する
    (normalize_cwd_to_project_root)。ルートは exe パス (<root>/.claude/<hook>.exe)
    から導出し、CLAUDE_PROJECT_DIR env には依存しない
  • これにより cwd drift 由来の 2 症状を同時に解消する: (1) ルート相対 step
    (file-length) の誤失敗 = 由来 incident、(2) takt subsession 判定の空振り
  • 回帰テスト tests/t7_cwd_independence.rs を追加 (E2E 5 本 + unit 2 本、26 → 33 pass)。
    exe を <root>/.claude/ に staging して spawn し、exe-relative 解決を実配置で検証する
  • ADR-005 に「hook プロセス内部のパス解決も exe-relative」を追記。CLAUDE_PROJECT_DIR
    が現在も空になることを実測で確認した記録を残す
  • main.rs が 800 行上限に触れたため takt 判定を takt_subsession.rs へ分離

Context

Why: Stop hook はセッションの cwd を継承して起動されるため、cwd がリポジトリルート
以外 (例: .takt/runscd したまま Stop) だと hooks-config.toml のルート相対 step
が「指定されたパスが見つかりません」で失敗し、品質ゲートが誤 block していた
(2026-07-16 に実発火)。pnpm / cargo 系 step は設定ファイルを上方探索するため偶然
通っており、ルート相対パスを書いた step だけが壊れる非対称が症状をまだらにして
発見を遅らせていた。

Trigger: docs/push-pipeline-fix-plan.md §4 T7 (push パイプライン改善計画)。

方針からの逸脱 (ユーザー承認済み): 計画は「正規化は step 実行の子プロセスにのみ適用し、
takt subsession 判定は元 cwd を使う形が安全」としていたが、調査の結果その判定も同じ
根本原因で既に壊れていた
(cwd = .takt/runs だと .takt/runs/.takt/runs を探して空振り
→ active run 未検出 → ADR-004 の edit:false subsession skip が効かず、PR #221 の事故が
再発しうる)。元 cwd の維持は「安全」ではなく既知不具合の温存にあたるため、両症状に効く
main 冒頭 1 回の正規化を採用した。回帰テストで修正前に実際に失敗することを確認済み。

ルート導出手段: 計画は (a) CLAUDE_PROJECT_DIR env と (b) exe パスを両論併記し
「実装時にどちらが確実か確認して選ぶ」としていた。実測すると VSCode 拡張環境
(Claude Code 2.1.212) で CLAUDE_PROJECT_DIRで、ADR-005 が 2026-03-17 に記録した
不安定性が現存する。よって (b) を採用 — 既存規約 (順位 287 / ADR-010、config_path() /
pipeline_lock::exe_claude_dir() / lib_telemetry::exe_dir()) と同形。

Scope decision: 方針 2 の CP932 デコードフォールバックは本 PR に含めず
§6 backlog 11 へ分離した (ユーザー承認済み)。影響先が共有 lib-subprocess
(push-runner / merge-pipeline) に及び、§2 原則 4「1 PR 1 変更」から外れるため。
cwd 修正で incident の文字化けは消えるが、exe 欠落時等で経路自体は残るため却下ではない。

Validation

  • pnpm push quality_gate: 全 4 グループ PASS (47.3s) — lint / test / build /
    rust-lint-test (clippy + cargo test + --ignored)
  • cargo test -p hooks-stop-quality: 33 pass (unit 28 + E2E 5)、cargo test --workspace 全 pass
  • pre-push review (pre-push-review-refute, 3 iterations / 9m59s):
    convergence_verdict: fully_resolved
  • 回帰テストが素通りしないことの実証: normalize_cwd_to_project_root() の呼び出しを
    外すと bad 2 本がちょうど失敗し good 3 本は通る。失敗内容は由来 incident の逐語再現
  • 実機 before/after (本リポジトリの実 config、配布 exe): cwd = .takt/runs
    before = {"decision":"block"...} + **file-length** failed / after = 出力なし (通過)。
    cwd = repo root と深い cwd (src/lib-subprocess/src) も通過
  • fail-open 退行ガード: 「実失敗する step は cwd に依らず block する」を good 側で固定済み

References

Summary by CodeRabbit

  • 改善

    • Stop 品質ゲートが実行時の作業ディレクトリに左右されにくくなり、プロジェクトルートを正しく解決できるようになりました。
    • 実行中かつ新しい Takt セッションを適切に検出し、期限切れのセッションを誤って有効扱いしないよう改善しました。
  • テスト

    • 作業ディレクトリが異なる場合や、実行中・完了済みセッションの判定に関する回帰テストを追加しました。
  • ドキュメント

    • パス解決方針、タイムアウト対応、検証結果を設計資料・実施計画へ反映しました。

aloekun and others added 2 commits July 17, 2026 15:08
T6 の作業コミット時点では PR が未採番だったため、計画書の §4 実施結果と §8
判定記録に「PR 未採番 — 採番後に backfill」と書いて負債を明示していた。PR #283
がマージされたため採番情報のみを更新する。

変更 (3 箇所、いずれも採番情報のみ):
- §4 T6 実施結果の見出し: PR 未採番 → PR #283
- §4 T6 の backlog 10 への申し送り: 「本 PR では触れず」→「PR #283 では触れず」
  (T5 が §4/§8 の「本 PR」を番号へ解決した慣習に揃える)
- §8 判定記録の T6 行: PR 未採番 → PR #283

由来: PR #282 (T5) の post-PR レビューで「T4 行が『本 PR』のまま放置され PR #282
で backfill する羽目になった」負債が指摘され、同じ形を繰り返さないために T6 では
未採番であることを明示していた。本コミットでその明示を回収する。

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Stop hook はセッションの cwd を継承して起動されるため、cwd がリポジトリルート
以外 (例: .takt/runs に cd したまま Stop) だと 2 つの症状が黙って出ていた:

1. hooks-config.toml のルート相対 step (file-length) が「指定されたパスが
   見つかりません」で失敗し、品質ゲートが誤 block する (2026-07-16 に実発火)。
   pnpm / cargo 系 step は設定ファイルを上方探索するため偶然通っており、
   ルート相対パスを書いた step だけが壊れる非対称が発見を遅らせていた。
2. takt subsession 判定が <cwd>/.takt/runs を探して空振りし、active run を
   検出できない。ADR-004 の edit:false subsession skip が効かなくなる。

同一の根本原因なので main 冒頭で cwd を 1 度だけプロジェクトルートへ正規化する。
ルートは exe パス (<root>/.claude/<hook>.exe) から導出する — CLAUDE_PROJECT_DIR
env は VSCode 拡張環境で空になることを実測確認した (ADR-005 の不安定性が現存)。
config / pipeline lock / telemetry が既に採る exe-relative 規約と同形。

ルート特定不能時は警告のみで継続 (fail-open、pipeline_is_running と同じ線引き)。
main.rs が 800 行上限に触れたため takt 判定を takt_subsession.rs へ分離した。

回帰テスト: tests/t7_cwd_independence.rs に E2E 5 本 + unit 2 本 (26 → 33)。
exe を <root>/.claude/ に staging して spawn し、exe-relative 解決を実配置で
検証する。正規化の呼び出しを外すと bad 2 本が失敗し good 3 本は通ることを確認済み。
@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: aea963a0-5322-4208-ab76-fc3c832535db

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Stop hook の cwd を実行ファイル配置から導出したプロジェクトルートへ正規化し、takt subsession 判定を専用モジュールへ分離しました。Windows の cwd 独立性回帰テストと、T6/T7 の実装記録・ADR 更新も追加されています。

Changes

Stop hook の cwd 独立化

Layer / File(s) Summary
Takt subsession 判定の分離と検証
src/hooks-stop-quality/src/takt_subsession.rs
.takt/runsmeta.json を走査し、running かつ mtime が 1500 秒以内の run のみ active と判定する処理と失敗系・境界値テストを追加しました。
実行ファイル相対の cwd 正規化
src/hooks-stop-quality/src/main.rs
.claude 配下の exe からプロジェクトルートを導出し、main 冒頭で cwd を変更します。導出・変更に失敗した場合は警告後に継続し、takt 判定は専用モジュールへ委譲します。
cwd 独立性の回帰テスト
src/hooks-stop-quality/tests/t7_cwd_independence.rs
root および .takt/runs cwd からの成功・失敗 step、active run の skip、completed run の gate 実行を Windows 専用テストで検証します。

実装記録と設計文書

Layer / File(s) Summary
T7 の設計・実施記録
docs/adr/adr-005-hooks-path-resolution-with-template.md, docs/push-pipeline-fix-plan.md
CLAUDE_PROJECT_DIR が空である実測結果、exe-relative 方針、cwd 正規化、T7 のテスト・実機検証結果を記録しました。
T6 完了記録と backlog 更新
docs/push-pipeline-fix-plan.md
T6 を PR #283 の実装済みとして更新し、CP932 フォールバックを別 backlog 項目として追加しました。

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant StopHookMain
  participant ProjectRootResolver
  participant CwdNormalizer
  participant QualityGate
  participant TaktSubsession
  StopHookMain->>ProjectRootResolver: exe パスからプロジェクトルートを導出
  StopHookMain->>CwdNormalizer: 起動時に cwd を正規化
  StopHookMain->>QualityGate: Stop 品質ゲートを実行
  QualityGate->>TaktSubsession: active takt run を判定
  TaktSubsession-->>QualityGate: skip 判定を返却
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed Stop品質ゲートのcwd依存修正という主変更を正しく表しており、変更内容と整合しています。
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/stop-quality-cwd-dependency

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown
Contributor

🤖 PR Monitor 分析 (GitHub Actions バックストップ)

  • トリガー: issue_comment (created) / 実行 run
  • CI: CodeRabbit チェックのみ存在し PENDING (Review in progress)。他の GitHub Actions チェックは無し。mergeStateStatus: UNSTABLE(必須チェック未完了によるものと推定)。mergeable: MERGEABLE
  • レビュー状況: CodeRabbit はレビュー未着 (処理中プレースホルダーコメントのみ、実指摘は 0 件)。人間レビューア・他 bot のレビューも 0 件 (reviewDecision 空)。
  • Verdict: approved (現時点で applicable な指摘が 0 件のため。ただし CodeRabbit レビュー未完了であり最終判定ではない — 次回発火時に指摘が追加され得る)

Applicable Findings (Critical / High / Major)

(該当なし)

Applicable Findings (Medium 以下)

(該当なし)

Filtered (not applicable)

(該当なし)

diff 概要 (レビュー指摘が無いため軽量サマリー)

T7 (Stop hook 品質ゲートの cwd 依存修正、docs/push-pipeline-fix-plan.md 記載タスク) の実装 PR。5 ファイル変更:

  • src/hooks-stop-quality/src/main.rs: main() 冒頭に normalize_cwd_to_project_root() を追加し、exe パス (<root>/.claude/<hook>.exe) からプロジェクトルートを導出して cwd を正規化。既存の takt subsession 判定ロジックを takt_subsession.rs へ切り出し(800行制限対応、ADR-010/ADR-043 に整合)。
  • src/hooks-stop-quality/src/takt_subsession.rs (新規): 上記切り出し先。ロジック自体は変更なく移動のみ。
  • src/hooks-stop-quality/tests/t7_cwd_independence.rs (新規、Windows限定): E2E 回帰テスト5本。修正前に実際に失敗することを確認済みと PR 内 doc に記載。
  • docs/adr/adr-005-hooks-path-resolution-with-template.md: exe-relative パス解決の追記 (恒久化)。
  • docs/push-pipeline-fix-plan.md: T6(PR fix(cli-push-runner): diff stage の timeout 欠落を修正 (push パイプライン改善 T6) #283)/T7(本PR) の実施結果を記録、backlog 追加。

変更はテスト・ADR裏付けとも充実しており、CLAUDE.md 記載の ADR-005/ADR-010/ADR-043/ADR-049 の規約に沿った設計。

次のアクション

  • CodeRabbit のレビュー完了を待ってから最終マージ判断を行うこと (現時点の分析は指摘0件の暫定状態)。
  • mergeStateStatus: UNSTABLE の原因 (必須チェック未完了と推定) を確認し、CodeRabbit 完了後に再評価すること。

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/hooks-stop-quality/tests/t7_cwd_independence.rs`:
- Around line 91-96: In the t7 hook test around wait_with_timeout_safe, retain
the returned process status and assert status.success() instead of discarding
it. Join and preserve stderr before the assertion so failed hooks include stderr
diagnostics, while keeping the existing stdout-based block_reason flow for
successful exits.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 0fb8e04a-732e-40d9-a86d-589f3394895a

📥 Commits

Reviewing files that changed from the base of the PR and between 69607a8 and 983d616.

📒 Files selected for processing (5)
  • docs/adr/adr-005-hooks-path-resolution-with-template.md
  • docs/push-pipeline-fix-plan.md
  • src/hooks-stop-quality/src/main.rs
  • src/hooks-stop-quality/src/takt_subsession.rs
  • src/hooks-stop-quality/tests/t7_cwd_independence.rs

Comment thread src/hooks-stop-quality/tests/t7_cwd_independence.rs Outdated
@github-actions

Copy link
Copy Markdown
Contributor

🤖 PR Monitor 分析 (GitHub Actions バックストップ)

  • トリガー: pull_request_review (submitted) / 実行 run
  • CI: CodeRabbit チェックは pass (Review completed)。analyze チェックは pending (未完了、詳細ジョブへのアクセスは今回未取得)。mergeStateStatus: UNSTABLEmergeable: MERGEABLE
  • レビュー状況: CodeRabbit が COMMENTED でレビュー完了 (2026-07-17T07:24:56Z、actionable comment 1件)。人間レビューア・他 bot のレビューなし (reviewDecision 空)。前回の GitHub Actions 分析コメント (issue_comment イベント、2026-07-17T07:22:11Z 投稿) 以降に本レビューが新規追加されたため再分析。
  • Verdict: needs_fix

Applicable Findings (Critical / High / Major)

# File (Line) Reviewer Issue Recommended Action
1 src/hooks-stop-quality/tests/t7_cwd_independence.rs:91-96 CodeRabbit (Major) run_hook() 内で wait_with_timeout_safe(...) の戻り値 (プロセスの exit status) を捨てているため、hook が non-zero exit で終了しても stdout が block JSON でなければ block_reason(&out) == None として素通りし、テストが「実は起動/実行に失敗している」ケースを検出できない status.success() を assert し、失敗時に stderr を含めて診断できるようにする (stdout ベースの block_reason フローは成功時のみ維持)

Applicable Findings (Medium 以下)

(該当なし)

Filtered (not applicable)

(該当なし)

次のアクション

  • Major finding (t7_cwd_independence.rs の exit status 未検証) を修正: wait_with_timeout_safe の戻り値を保持し status.success() を assert、失敗時は stderr を出力する。
  • analyze チェックが pending のまま残っているため、完了後に結果を確認すること (本分析では待機していない)。

aloekun added 2 commits July 17, 2026 16:28
Resolved findings:
- [Major] src/hooks-stop-quality/tests/t7_cwd_independence.rs:96 hook の終了ステータスを確認してください
auto-fix が追加した assert_hook_success は exit code assert 自体は入れたが、
指摘の「失敗時は stderr を出す」部分が未達だった: メッセージに stdout を渡しており、
かつ stderr.join() より前に呼ばれるため構造上 stderr を出せない。

本 hook の診断 (cwd 正規化の警告等) は eprintln! = stderr にしか出ないため、
指摘が想定する「非 0 exit かつ stdout が空」の失敗では stderr だけが手掛かりになる。
stderr を join してから assert に渡す形へ補正した。

guard が空振りでないことを実証済み: staged exe を where.exe (非 0 exit・stdout 空) に
差し替えると 5 本すべてが exit code Some(2) で失敗する (guard 導入前なら None を
期待する 3 本が false green で素通りしていた)。
@aloekun
aloekun merged commit f228060 into master Jul 17, 2026
2 of 3 checks passed
@aloekun
aloekun deleted the fix/stop-quality-cwd-dependency branch July 17, 2026 07:50
@github-actions

Copy link
Copy Markdown
Contributor

🤖 PR Monitor 分析 (GitHub Actions バックストップ)

  • トリガー: pull_request_review (submitted) / 実行 run
  • CI: CodeRabbit チェック passanalyze チェックは取得時点で pending(詳細ジョブ未確認)。なお PR 自体は既に MERGED 済み (mergedAt: 2026-07-17T07:50:02Z, merge commit head 3a3bb5bb)。
  • レビュー状況:
    • CodeRabbit: COMMENTED でレビュー完了 (07:24:56Z)。actionable comment 1件 (Major) を提起。
    • aloekun (PR作者): 上記指摘に対する修正コミット (3a3bb5bb, 07:34:32Z, "CodeRabbit 指摘の stderr 出力を補完") を push し、review コメントで対応内容と検証結果 (where.exe を使った negative-control 実証) を報告 (07:49:06Z)。
    • CodeRabbit: 追加レビュー (COMMENTED, 07:49:29Z, 本 run のトリガー) で "confirmed—this directly closes the false-green path" と修正を確認・クローズ。
  • Verdict: approved (前回発火時点 [needs_fix, 07:26:46Z 投稿分] で指摘された Major finding は、本 run のトリガーとなったレビューで修正確認済み。他に未解決の applicable finding は無し)

Applicable Findings (Critical / High / Major)

(該当なし — 唯一の Major finding は解決済み。下記参照)

Applicable Findings (Medium 以下)

(該当なし)

Filtered (not applicable)

(該当なし)

参考: 解決済み指摘

# File (Line) Reviewer Issue 状態
1 src/hooks-stop-quality/tests/t7_cwd_independence.rs:91-96 CodeRabbit (Major) run_hook() 内で wait_with_timeout_safe(...) の exit status を捨てており、hook が non-zero exit・stdout 空で失敗しても素通りする false-green の穴があった commit 3a3bb5bbstatus.success() assert + stderr 保持を実装、CodeRabbit が修正内容を確認・承認済み

次のアクション

  • PR は既にマージ済みのため追加のマージ判断アクションは不要。
  • analyze チェックが取得時点で pending のままだった点のみ、後続セッションで完了状態を確認しておくと良い (ブロッキングではない可能性が高い)。

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.

1 participant