Skip to content

feat(cloud-harness): ADR-060 Cloud ハーネス有効化 — tracked dispatcher 登録 + SessionStart 実体確保の 2 層分離 - #319

Merged
aloekun merged 5 commits into
masterfrom
claude/select-next-task-6nb2d9
Jul 25, 2026
Merged

feat(cloud-harness): ADR-060 Cloud ハーネス有効化 — tracked dispatcher 登録 + SessionStart 実体確保の 2 層分離#319
aloekun merged 5 commits into
masterfrom
claude/select-next-task-6nb2d9

Conversation

@aloekun

@aloekun aloekun commented Jul 25, 2026

Copy link
Copy Markdown
Owner

概要

Claude Code Web で hooks が「半整備」になる構造(WP-15 注意 B)の根本対応。実測で確定した 3 つのプラットフォーム制約により、従来の生成物ベース(settings.local.json)の hook 登録はクラウドでは原理的に機能しない:

  1. セットアップスクリプトは環境キャッシュ構築時に 1 回だけ実行される
  2. リポ内の git 追跡外生成物(hook バイナリ / settings.local.json / .jj / node_modules / target/)は毎セッションの fresh clone で消滅する
  3. hooks は Claude Code 起動時に snapshot され、セッション中の settings 生成は登録に間に合わない

対応として 登録層(tracked)と実体確保層(毎セッション再構築)のライフサイクル分離 を導入する。詳細は ADR-060

変更内容

  • scripts/cloud-hook-dispatch.mjs(新規): tracked settings から起動される cross-platform dispatcher。import.meta.url 自己位置解決(ADR-005 の .mjs 適用)。CLAUDE_CODE_REMOTE + CLOUD_HARNESS opt-in の 2 段ゲートでローカル/未 opt-in 環境では完全不活性。バイナリ不在時は warn + exit 0(ADR-043 からの意図的逸脱 — 復旧コマンド自体が block されるデッドロック回避。ADR-060 § 決定 5)
  • .claude/settings.json: dispatcher 経由の hooks 登録を追加(SessionStart / UserPromptSubmit / PreToolUse / PostToolUse×3 / Stop×3、構成・timeout はテンプレートと同一)
  • scripts/cloud-setup.sh: --session-phase(SessionStart hook から毎セッション: バイナリ + jj + pnpm install)/ --cache-phase(UI セットアップスクリプト欄: pnpm store + cargo warmup 暖機)を追加。引数なしは後方互換
    • RETURN trap 残留バグ修正: 冪等再実行が exit 1 になる実測バグ(trap が関数返却後も残留し消滅済み local tmp_dirset -u が捕捉)を自己解除型 trap で解消
    • git HEAD 再アタッチ(A-4): jj git init --colocate の HEAD detach により git push が src refspec does not match any で失敗する問題(本 PR 作業中に実際に遭遇)を機構化(ADR-042)
  • src/hooks-stop-quality/main.rs: rust 1.94 新 lint redundant_iter_cloned の債務解消(toolchain pin が無いためクラウド Stop gate の lint:rust が fail する dogfood 阻害要因)
  • docs/adr/adr-060 + CLAUDE.md 索引: 設計根拠と ADR-039 3 点セット

ADR-039 kill-switch table

項目 内容
起動経路 Web UI 環境変数欄 CLOUD_HARNESS=1(または true)+ settings.json hooks(merge 済みが前提)
停止コマンド 環境変数欄から CLOUD_HARNESS を削除(次セッションから全 hook が exit 0 no-op)
影響範囲 クラウドセッションのみ。ローカル Windows は CLAUDE_CODE_REMOTE ゲートで恒久不活性(従来の settings.local.json 経路が継続)
bounded lifetime dogfood 5 セッション or 2026-09-30 で採否判定(ADR-060 § 決定 4)

DoD / 検証(Linux 実機リハーサル)

  • cargo test --workspace green(1720 passed / 0 failed)+ cargo clippy --workspace --all-targets -- -D warnings green(rust 1.94.1)
  • Stop gate 全 step green: pnpm lint / lint:md / lint:docs / test / build
  • --session-phase 実機実行: 9 hook バイナリ + jj 0.42 + node_modules 配置、冪等再実行 exit 0
  • dispatcher E2E: --setuphooks-session-start の additionalContext 実出力まで貫通
  • セキュリティゲート実発火: jj git push 直叩きが dispatcher 経由で exit 2 block(jj-push-guard)、安全コマンドは exit 0 通過。残り 5 hook バイナリも合成 stdin JSON で正常動作
  • settings.json: JSON parse green + 全 hook 名が配置バイナリ 9 個と一致

マージ後の有効化手順(ユーザー操作)

  1. Web UI 環境変数欄: CLOUD_HARNESS=1CARGO_TARGET_DIR=/opt/cargo-target を追加
  2. Web UI セットアップスクリプト欄: bash scripts/cloud-setup.sh --cache-phase へ変更(欄の変更がキャッシュ再構築を兼ねる)
  3. 新規セッションで発火確認(E2E 検証はマージ後の新規セッションでのみ可能)

🤖 Generated with Claude Code

https://claude.ai/code/session_01FqB6tSGZsEjT3VuydstnoG


Generated by Claude Code

Summary by CodeRabbit

  • 新機能

    • クラウドセッションで、開始・再開、プロンプト送信、ツール実行前後、停止時の処理を自動化しました。
    • セッション開始時に必要な環境や依存関係を準備し、既存の開始処理を継続して実行します。
    • CLOUD_HARNESS による明示的な有効化に対応し、通常のローカル環境への影響を抑えました。
  • ドキュメント

    • クラウド環境の構成方針、セットアップ手順、制約事項を追加しました。

claude added 4 commits July 25, 2026 05:08
run_quality_steps の steps.iter().cloned() が QualityStepConfig 全体を clone して
いたが、実際に使うのは name / cmd の 2 field のみ。rust 1.94 の clippy が
redundant_iter_cloned として検出し -D warnings で fail する。

CI (release-binaries.yml) は build 時点の stable で green だったが、rust-toolchain
pin が無いため cloud セッションの新しい stable では Stop gate の lint:rust step が
この債務で fail する (ADR-060 の dogfood 前提を壊す)。必要 field のみ clone する形
に変更して解消。

検証: cargo clippy --workspace --all-targets -- -D warnings green /
cargo test --workspace green (Linux, rust 1.94.1)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FqB6tSGZsEjT3VuydstnoG
…保の 2 層分離

Claude Code Web で hooks が半整備になる構造 (WP-15 注意 B) の根本対応。実測で確定
した 3 制約 — (1) セットアップスクリプトはキャッシュ構築時のみ実行、(2) リポ内
生成物は毎セッション fresh clone で消滅、(3) hooks は起動時 snapshot されセッション
中の settings 生成は登録に間に合わない — により、生成物ベースの hook 登録は
クラウドでは原理的に機能しない。登録と実体確保をライフサイクル分離する:

- scripts/cloud-hook-dispatch.mjs (新規): tracked settings から起動される
  cross-platform dispatcher。import.meta.url 自己位置解決 (ADR-005 の .mjs 適用、
  CLAUDE_PROJECT_DIR 非依存)。CLAUDE_CODE_REMOTE + CLOUD_HARNESS opt-in の
  2 段ゲートでローカルでは完全不活性。バイナリ不在は warn + exit 0 (ADR-043 から
  の意図的逸脱、復旧コマンド自体が block されるデッドロック回避。ADR-060 § 決定 5)
- scripts/cloud-setup.sh: --session-phase (SessionStart hook から毎セッション。
  バイナリ配置 + jj 導入/init + pnpm install、generate_settings は skip) と
  --cache-phase (UI セットアップスクリプト欄。pnpm store + cargo warmup 暖機、
  要 CARGO_TARGET_DIR=リポ外) を追加。引数なしは旧来動作で後方互換
- RETURN trap の残留バグ修正: 関数返却後も trap がシェルに残り、後続関数の
  return で消滅済み local tmp_dir を set -u が捕捉して --session-phase 再実行が
  exit 1 になっていた (リハーサルで実測)。trap 発火時に自己解除する形へ
- docs/adr/adr-060 + CLAUDE.md 索引: 設計根拠・ADR-039 3 点セット (opt-in env
  CLOUD_HARNESS / kill-switch = env 削除 / dogfood 5 セッション or 2026-09-30 で
  採否判定)・ユーザー側 Web UI 設定手順を記録

.claude/settings.json への hooks 登録は別 commit (要ユーザー承認の設定変更)。
登録が入るまで dispatcher は完全 dead code ではなく不活性 (opt-in 前と同状態)。

検証 (Linux 実機リハーサル): --session-phase 実行で 9 hook バイナリ + jj 0.42 +
node_modules 配置 / 冪等再実行 exit 0 / --setup E2E で hooks-session-start の
additionalContext 実出力 / dispatcher 経由で hooks-pre-tool-validate が
jj-push-guard を exit 2 block (安全コマンドは exit 0) / 残り 5 hook バイナリも
合成 stdin JSON で exit 0 / Stop gate 全 step (lint / lint:md / lint:docs / test /
build) green / cargo clippy + cargo test --workspace green

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FqB6tSGZsEjT3VuydstnoG
jj git init --colocate は git HEAD を detach し、環境によってはローカルブランチ
ref も残らない (ADR-060 リハーサルで実測: push が src refspec does not match any
で失敗)。jj 中心のローカル flow は影響しないが、クラウドセッションの Claude は
git で commit/push するため、init 前に取得した現ブランチへ HEAD を戻す。
開始時点で既に detached だった run は戻し先が不明なので warn で明示する
(無言 skip だと push 失敗まで露見しない)。

検証: attached → no-op / detached + ブランチ名不明 → warn の両経路を実機確認。
bash -n green。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FqB6tSGZsEjT3VuydstnoG
…0 登録層)

tracked な settings.json への登録により、クラウドセッションの起動時 snapshot に
hooks が確実に載る (ADR-060 § 決定 1)。全 command は cross-platform dispatcher
(scripts/cloud-hook-dispatch.mjs) 経由で、CLAUDE_CODE_REMOTE + CLOUD_HARNESS の
2 段ゲートによりローカルでは不活性、クラウドでも opt-in env 設定までは不活性。
構成・timeout はテンプレート (settings.local.json.template) と同一。

検証: JSON parse green / 全 hook 名が配置済みバイナリ 9 個と一致。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FqB6tSGZsEjT3VuydstnoG
@coderabbitai

coderabbitai Bot commented Jul 25, 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 Plus

Run ID: d2203896-58cf-45a1-a905-ea50da07d8c6

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

クラウド用フック登録、環境ゲート付きディスパッチャ、SessionStart/キャッシュの二段階セットアップを追加した。セットアップ時の一時ディレクトリ処理と jj 初期化を修正し、品質ステップの並列実行引数の所有方法も整理した。

Changes

クラウドハーネスのフック登録

Layer / File(s) Summary
フック登録と運用方針
.claude/settings.json, docs/adr/adr-060-cloud-harness-sessionstart-dispatcher.md, CLAUDE.md
SessionStart、UserPromptSubmit、PreToolUse、PostToolUse、Stop からディスパッチャを呼び出す設定と、登録層・実体確保層を分離する ADR-060 を追加した。
ディスパッチとセッション実体確保
scripts/cloud-hook-dispatch.mjs, scripts/cloud-setup.sh
環境変数による有効化判定、フックバイナリの同期実行、--setup による SessionStart セットアップ、--session-phase--cache-phase の分岐を実装した。
セットアップとリポジトリ復旧
scripts/cloud-setup.sh, docs/adr/adr-060-cloud-harness-sessionstart-dispatcher.md
一時ディレクトリ用トラップを更新し、colocated jj 初期化後の detached HEAD を元のブランチへ再接続する処理を追加した。

品質ステップ並列実行整理

Layer / File(s) Summary
ワーカー引数の所有整理
src/hooks-stop-quality/src/main.rs
ワーカーへステップ全体ではなく名前とコマンドを個別にクローンして渡し、コマンド展開と実行に利用する値を整理した。

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

Sequence Diagram(s)

sequenceDiagram
  participant SessionStart
  participant cloud-hook-dispatch.mjs
  participant cloud-setup.sh
  participant hooks-session-start
  SessionStart->>cloud-hook-dispatch.mjs: --setup と stdin JSON を送信
  cloud-hook-dispatch.mjs->>cloud-setup.sh: --session-phase を実行
  cloud-setup.sh-->>cloud-hook-dispatch.mjs: セットアップ結果を返却
  cloud-hook-dispatch.mjs->>hooks-session-start: stdin JSON を渡して起動
  hooks-session-start-->>SessionStart: 終了コードを返却
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 ADR-060 のクラウドハーネス有効化と、dispatcher 登録・SessionStart 実体確保の 2 層分離を的確に要約しています。
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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 claude/select-next-task-6nb2d9

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)。他の CI check は未報告
  • レビュー状況: CodeRabbit — レビュー未着 (処理中、指摘なし)。人間レビュー・他 bot レビューともに 0 件
  • Verdict: approved (現時点で applicable な指摘が 0 件のため。CodeRabbit のレビュー結果到着後に再評価が必要)

Applicable Findings (Critical / High / Major)

該当なし

Applicable Findings (Medium 以下)

該当なし

Filtered (not applicable)

該当なし

次のアクション

  • CodeRabbit のレビュー完了を待ち、指摘が投稿された時点で本 workflow が再度分析する (現時点でのポーリング・待機は行わない)
  • 変更差分は .claude/settings.json (hooks 追加)・CLAUDE.md・新規 ADR-060・scripts/cloud-hook-dispatch.mjs (新規)・scripts/cloud-setup.shsrc/hooks-stop-quality/src/main.rs の6ファイル (+461/-13)。.claude/settings.json への変更は sensitive-file protection 対象のため、将来 CodeRabbit がここに指摘を出した場合は user_decision_path 扱いになる点に留意
  • mergeStateStatus: UNSTABLE は CodeRabbit check が pending であることに起因する可能性が高く、追加対応は不要

@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 `@scripts/cloud-setup.sh`:
- Around line 103-106: Update the temporary-directory cleanup traps in both
install_harness_binaries and install_jj at scripts/cloud-setup.sh lines 103-106
and 206-207: use a cleanup trap covering both RETURN and EXIT so die() paths
remove the directory, then explicitly disable both traps after successful
cleanup to prevent later function returns from referencing the local tmp_dir.
🪄 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 Plus

Run ID: 3575b1a5-8d8c-4dce-bc8a-c0bf915f8aa2

📥 Commits

Reviewing files that changed from the base of the PR and between 4984eac and 45df11c.

📒 Files selected for processing (6)
  • .claude/settings.json
  • CLAUDE.md
  • docs/adr/adr-060-cloud-harness-sessionstart-dispatcher.md
  • scripts/cloud-hook-dispatch.mjs
  • scripts/cloud-setup.sh
  • src/hooks-stop-quality/src/main.rs

Comment thread scripts/cloud-setup.sh Outdated
Comment on lines +103 to +106
# 途中で失敗しても一時ディレクトリを残さない。RETURN trap は関数返却後もシェルに残留し、
# 後続関数の return で消滅済み local tmp_dir を参照して set -u で落ちるため
# (--session-phase 再実行が exit 1 になる実測バグ)、発火時に自己解除する。
trap 'rm -rf "${tmp_dir}"; trap - RETURN' RETURN

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

# die が exit する実装か、既存 EXIT trap を上書きしないかを確認する。
rg -n -A5 -B2 '^(die\(\)|trap )' scripts/cloud-setup.sh

Repository: aloekun/claude-code-hook-test

Length of output: 496


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

echo "== trap occurrences =="
rg -n '^[[:space:]]*trap ' scripts/cloud-setup.sh

echo
echo "== die definition and callers around install functions =="
sed -n '60,120p' scripts/cloud-setup.sh
echo
sed -n '180,225p' scripts/cloud-setup.sh

echo
echo "== structural probe: RETURN vs EXIT trap semantics in this script pattern =="
python3 - <<'PY'
from pathlib import Path
text = Path('scripts/cloud-setup.sh').read_text()
# Lightweight semantic check: RETURN traps do not fire on top-level EXIT from a sourced script;
# functions returning normally do, but functions that call exit do not continue to return.
print('has only RETURN trap for tmp_dir cleanup:', text.count('trap - RETURN') == text.count('rm -rf "${tmp_dir}"; trap - RETURN') and 'EXIT' not in text[
    text.find('trap - RETURN'):
    text.find('trap - RETURN') + 256
])
PY

Repository: aloekun/claude-code-hook-test

Length of output: 4111


死んだプロセスが残った一時ディレクトリをCleanupしてください。

die()exit 1 するため、RETURN trap は呼ばれません。install_harness_binaries()install_jj() では curl/node/tar などの失敗経路で一時ディレクトリが残りうるため、trap - RETURN EXIT で cleanup を実行し、成功時に両方の trap を解除してください。

修正案
-  trap 'rm -rf "${tmp_dir}"; trap - RETURN' RETURN
+  trap 'rm -rf "${tmp_dir}"; trap - RETURN EXIT' RETURN EXIT
📍 Affects 1 file
  • scripts/cloud-setup.sh#L103-L106 (this comment)
  • scripts/cloud-setup.sh#L206-L207
🤖 Prompt for 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.

In `@scripts/cloud-setup.sh` around lines 103 - 106, Update the
temporary-directory cleanup traps in both install_harness_binaries and
install_jj at scripts/cloud-setup.sh lines 103-106 and 206-207: use a cleanup
trap covering both RETURN and EXIT so die() paths remove the directory, then
explicitly disable both traps after successful cleanup to prevent later function
returns from referencing the local tmp_dir.

@github-actions

Copy link
Copy Markdown
Contributor

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

  • トリガー: pull_request_review (submitted) / 実行 run
  • CI: analyze (本 workflow自身) が in_progress のほかは CodeRabbit チェックのみ登録され SUCCESS (Review completed)。ビルド/テスト系 CI は未登録。mergeable: MERGEABLE / mergeStateStatus: UNSTABLE (CodeRabbit 以外に check が無いことに起因、追加対応不要)
  • レビュー状況: CodeRabbit — レビュー1件 (state: COMMENTED, 2026-07-25T05:19:02Z, actionable comments 1件)。人間レビュー・他 bot レビューは 0 件、reviewDecision 未設定
  • Verdict: user_decision

Applicable Findings (Critical / High / Major)

該当なし

Applicable Findings (Medium 以下)

# File (Line) Reviewer Issue Recommended Action
1 scripts/cloud-setup.sh (L103-106, 同型 L206-207) CodeRabbit (Minor) install_harness_binaries/install_jjtmp_dir 一時ディレクトリ削除が RETURN trap のみに依存している。今回の diff で「RETURN trap 自己解除」(set -u 落ち回避) は修正済みだが、die()exit 1 するため RETURN trap 自体が発火せず、curl/tar 失敗などのエラー経路で tmp_dir が残置され得る問題は未解消 trap '...; trap - RETURN EXIT' RETURN EXIT のように EXIT も併せて捕捉し、成功時に両 trap を解除する (CodeRabbit 提示の diff 通り)。install_harness_binaries と install_jj の両方に適用

Filtered (not applicable)

該当なし

次のアクション

  • 上記 Minor 指摘 (tmp_dir リーク) は .claude/ 対象外の通常ソースであり ADR にも意図的設計としての記載なし。次のローカルセッションで CodeRabbit 提示の diff を適用し EXIT trap も追加することを推奨 (severity Minor のため必須ではないが低コストな修正)
  • 人間レビューはまだ 0 件。マージ判断には別途 human review を待つ必要がある
  • CI 側は CodeRabbit 以外の check が無いため、build/test パイプラインが別途走る設定かどうかは変更なし (今回の diff 起因ではない)

die() は exit 1 するため RETURN trap では curl 失敗・checksum 不一致等の失敗
経路で一時ディレクトリが残る (CodeRabbit 指摘、検証の上正当と判断)。EXIT にも
掛け、発火時に両方を自己解除する。

検証: 存在しない release tag で die 経路を実走し tmp dir 残留ゼロ /
正常経路の冪等再実行 exit 0 維持 / bash -n green。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FqB6tSGZsEjT3VuydstnoG
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