Skip to content

refactor(pr-monitor): CronCreate park モデルを撤去し single-shot 化 (WP-17 PR 3) - #353

Merged
aloekun merged 4 commits into
masterfrom
feat/wp17-pr3-wakeup-removal
Aug 3, 2026
Merged

refactor(pr-monitor): CronCreate park モデルを撤去し single-shot 化 (WP-17 PR 3)#353
aloekun merged 4 commits into
masterfrom
feat/wp17-pr3-wakeup-removal

Conversation

@aloekun

@aloekun aloekun commented Aug 3, 2026

Copy link
Copy Markdown
Owner

概要

WP-17 PR 3(wakeup 機構の廃止)です。cli-pr-monitor を「1 回 check して必ず terminal
報告で終了する」single-shot モデルへ移行し、CronCreate park モデル(Bb-1/Bb-2)と
hooks-session-start の catch-up nudge を撤去します。

3 コミット / 22 ファイル / +575 -2503 行。diff の大半が削除の撤去 PR で、分割すると
park モデルが中途半端に残る壊れた中間状態を作るため、PR size gate は ADR-069 § 決定 3-3
の正規経路(PR_SIZE_CHECK_OVERRIDE=1 + 本欄での理由明記)でバイパスしました。

なぜ廃止するか

挙動の変化

状況 旧(park モデル) 新(single-shot)
review 未確定 park + wakeup 予約 terminal pending_review 報告
rate-limit reset 待ち park terminal rate_limited 報告(ADR-064 (b) の保留判定文を維持)
fresh push checker を呼ばず initial park 即 1 回 check して報告

いずれも「後続は GitHub Actions 経路が処理」を明示し、pending を silent success に
見せません(ADR-064 陽性証拠原則)。

残したもの(park の付随物ではないため)

  • 時刻窓アンカーの継続(should_continue_state): 同一 PR + 同一 head なら
    started_at / fix_push_time を維持。落とすと再実行のたびに CR コメントの新着判定窓が
    リセットされる
  • 順位 141 の mergeable shortcut([RATE_LIMIT_BUT_MERGEABLE]): rate-limit 中でも
    mergeable なら即 merge を提案する独立機能。rate_limit.rs へ移設して維持
  • rate-limit の retry 上限 / comment dedup

pre-push レビューが検出した回帰 2 件(両方修正済み)

本 PR は 2 ラウンドの REJECT を受け、どちらも実在の回帰でした:

  1. shortcut の silent 削除(High): 初版 diff が rate_limit_signal.rs の削除に順位 141
    shortcut を巻き込んでいた。「他の撤去物は全て ADR に列挙されているのに、これだけ無言で
    消えている」という検出 → テストごと復元
  2. head_commit 保存の欠落(High): rate-limit 系 terminal で head_commit 保存が落ち、
    次回実行の継続判定が fresh 初期化に倒れて時刻窓がリセットされる回帰。本 PR 自身が
    動機に挙げた incident class(docs: PR-W5 (#234) land 反映 + post-merge-feedback 採用 3 件を todo 登録 (順位 248-250) #237/feat: Linux バイナリビルド + クラウド setup script (WP-15) #307/fix(monitor): 不完全な信号から success を導く fail-open 2 件を修正 (rate-limit 検知 / 判定文) #309)の再導入
    だった → 保存 + 回帰テスト 2 件

前方互換

旧 state file(wakeup fields)・旧 config([review_recheck] / max_duration_secs)が
残っていても unknown field として無視されます(前方互換テストで固定)。

ADR 記帳

  • ADR-018 amendment: 廃止の決定・根拠・維持したもの・ADR-064 検証残の移し替え
  • ADR-064: 検証残 (a) park 実観測 = moot として閉じ、(b) 判定文保留保証 = Actions 経路へ
  • ADR-034: Bundle b の park モデル記述に「廃止済み・歴史記録」注記

検証

  • cargo test --workspace 1901 件 pass(park 系テスト約 52 件削除、新モデル + 回帰テスト追加)
  • cargo clippy --workspace --all-targets -- -D warnings 緑、lint:docs / lint:md 0 error
  • pre-push review: security / simplicity とも最終 APPROVE

この PR 自身がスモーク段 1 の観測対象です

AUTONOMY_ENABLED 再設定済み・master 版 workflow・非 claude/ ブランチという構成なので、
CodeRabbit レビュー到着時に fix job が起動し prefix 層で deny([FIX_PUSH_DENY] branch=... claude/ prefix ではない、job は緑)となるのが期待動作です。観測結果は
ADR-067 の検証記録に記帳します。

マージ後の運用変更

  • pnpm push チェイン末尾の監視は「その時点の状態報告」になります。レビュー未着なら
    pending_review で終わり、後続は Actions 経路のコメントか手動 --monitor-only 再実行で
    把握します(Claude セッションが CronCreate で wakeup を予約する運用は終了)
  • マージ後に .claude/ の exe 再ビルドが必要です(cli-pr-monitor / hooks-session-start /
    cli-push-runner。配備乖離の再発防止は WP-17 完了後の feedback 採否で扱う予定)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • 変更点

    • PR監視を単発チェック方式に変更し、未完了レビューやレート制限時は状態を明示して終了するようになりました。
    • 後続の監視処理はGitHub Actions経路へ引き継がれます。
    • 旧来の待機・再チェック設定および関連通知を整理しました。
    • 既存の状態継続、再試行上限、重複コメント防止は維持されています。
  • ドキュメント

    • PR監視方式の変更方針、検証状況、設定移行に関するドキュメントを更新しました。

aloekun and others added 3 commits August 4, 2026 00:00
cli-pr-monitor を「1 回 check して必ず terminal 報告で終了する」モデルへ移行する。
旧 Bb-1/Bb-2 の park モデル (未確定なら state に wakeup 時刻を書き、[PR_MONITOR_PARK]
envelope で Claude に CronCreate 予約を依頼し、発火時の再 invoke で継続する) を撤去した。

## なぜ廃止するか (ADR-018 amendment)

- wakeup はローカルセッションの寿命に依存する。PR #237 でセッション終了による
  CronCreate 失効 = 監視の取りこぼしを実観測した。
- WP-17 で GitHub Actions 経路 (pr-monitor workflow の Phase A/B) が常設になった。
  CodeRabbit のレビュー到着・後続コメントがそのままトリガーになるため、ローカルの
  時限 wakeup は冗長になった。

## 挙動の変化

- 未確定 (review 未完) → 旧: park + wakeup 予約 / 新: terminal `pending_review` 報告
  (「後続は GitHub Actions 経路が処理」を明示。ADR-064 の陽性証拠原則どおり
  pending を silent success に見せない)
- rate-limit reset 待ち → 旧: park / 新: terminal `rate_limited` 報告 (ADR-064 (b) の
  保留判定文を維持)。reset 経過後の即時 retrigger 投稿と comment dedup は残す
- fresh push → 旧: checker を呼ばず initial park / 新: 即 1 回 check して報告

## 残したもの (park の付随物ではないため)

- **時刻窓アンカーの継続** (`should_continue_state`): 同一 PR + 同一 head なら
  state.started_at / fix_push_time を維持する。これを落とすと再実行のたびに
  `--push-time` が「今」になり、push 後に届いた CR コメントが新着判定から漏れる。
  旧 `should_resume_wakeup` から wakeup 時刻経過の条件だけを外した形
- rate_limit_retries / rate_limit_last_retriggered_at (dedup と retry 上限は
  invocation 跨ぎで引き続き意味を持つ)
- **順位 141 の mergeable shortcut** (`[RATE_LIMIT_BUT_MERGEABLE]` signal):
  「rate-limit 中でも既に mergeable なら即 merge を選べる」独立機能で、park の
  付随物ではない。初版 diff は rate_limit_signal.rs の削除に巻き込んで silent に
  消しており、pre-push simplicity review が REJECT
  (SIM-NEW-src-cli-pr-monitor-rate_limit-L138: 他の撤去物は全て ADR/計画書に
  列挙されているのに shortcut だけ無言で消えている = 意図の疑い) → fix step が
  rate_limit.rs へテストごと復元した (実測検証済み)。terminal 化した
  `finalize_waiting_reset` から引き続き発火する。signal 文面の選択肢 B は
  single-shot 後の実態 (Actions 経路 / --monitor-only 再実行) に合わせて更新
- **rate-limit 系 terminal での head_commit 保存**: 2 回目の pre-push review が、
  `finalize_waiting_reset` / `finalize_posted_retrigger` で head_commit 保存が
  落ちている回帰を REJECT で検出 (SIM-NEW-rate_limit-L154: 保存が無いと次回
  `--monitor-only` の継続判定が fresh 初期化に倒れ、時刻窓リセットで CR コメントを
  取りこぼす — 本 PR 自身が動機に挙げた incident class の再導入)。fix step が
  両関数への保存 + 回帰テスト 2 件を追加した (実測検証済み)

## 撤去したもの

- state: next_wakeup_at_unix / wakeup_reason / review_recheck_count (旧 state file に
  残っていても unknown field として無視される — 前方互換テストを追加)
- poll: review_recheck.rs / review_recheck_signal.rs (park scheduling と PARK envelope
  整形の全量)。rate_limit_signal.rs はファイルとしては削除したが、上記のとおり
  shortcut 部分は rate_limit.rs へ移設して維持
- config: [review_recheck] セクションと sanitize / overflow 検査 (wakeup 時刻の加算
  演算ごと消滅)、monitor.max_duration_secs (ループ上限)。旧 config は unknown
  field/section として無視される — 前方互換テストを追加

検証: cargo test -p cli-pr-monitor 226 件 pass、workspace 全緑、
clippy --workspace -D warnings 緑。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…R 3)

pr_monitor catch-up nudge (Bb-3) は「park 中にセッションが終了して CronCreate が失効
した場合の救済」だった。park/wakeup モデルの廃止 (同 PR の cli-pr-monitor 変更) に伴い
救済対象の状態が存在しなくなるため、機構ごと撤去する。

- hooks-session-start: pr_monitor.rs module 削除 + main.rs の配線解除
- .claude/hooks-config.toml: telemetry registry から `pr_monitor_catchup` id を除去
  (過去の firings jsonl には残るが現役 id ではない)。あわせて、どのコードも読んで
  いなかった daemon 時代 (ADR-009) の死に設定 [post_pr_monitor] セクションを撤去
  (現行の監視設定はリポジトリルートの pr-monitor-config.toml が正)
- cli-telemetry-report: doc comment の例示 id を現役のものへ差し替え

検証: cargo test --workspace 1893 件 pass、clippy --workspace -D warnings 緑。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…17 PR 3)

- ADR-018 追記 (2026-08-03): park モデル廃止の決定・根拠・維持したもの (時刻窓アンカー
  の state 継続 / rate-limit dedup) を記録。ADR-064 検証残の移し替え ((a) park 実観測は
  moot / (b) 判定文の保留保証は Actions 経路の検証残へ) を明記
- ADR-064 ステータス欄: 同じ移し替えを検証残の側からも記載 (両方に記録して検証の穴を
  残さない — 計画書の着手前決定 2)
- ADR-034: Bundle b の CronCreate park モデル記述に「廃止済み、歴史記録として読む」
  注記を追加
- 計画書: PR 3 を実施中に更新し、実装で確定した設計判断 (should_continue_state を残す
  理由) と「本 PR の PR がスモーク段 1 の観測対象を兼ねる」ことを記載

検証: pnpm lint:docs / lint:md 0 error。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 3, 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: ababc9df-57f6-4981-80b6-f5faf04787c0

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

CronCreateのpark/wakeup方式を廃止しました。cli-pr-monitorをsingle-shot実行へ変更し、未完了レビューとrate-limitをterminal状態として報告します。状態継続、retry上限、comment dedupは維持します。

Changes

PR監視single-shot移行

Layer / File(s) Summary
設定と状態契約の更新
src/cli-pr-monitor/src/config.rs, src/cli-pr-monitor/src/state.rs, pr-monitor-config.toml, templates/pr-monitor-config.toml, src/cli-pr-monitor/src/main.rs, src/check-ci-coderabbit/src/main.rs, src/cli-pr-monitor/src/util.rs
旧polling、review recheck、wakeup設定とstate fieldsを削除しました。旧state JSONは未知フィールドを無視して読み込めます。
状態継続判定と監視起動
src/cli-pr-monitor/src/stages/monitor.rs
同一PR、repository、head commitの場合だけ既存stateを継続します。monitor-only経路も同じ判定を使用します。
未確定レビューのterminal処理
src/cli-pr-monitor/src/stages/poll/mod.rs, src/cli-pr-monitor/src/stages/poll/iteration.rs
poll loopをsingle-shot APIへ変更しました。未確定レビューをpending_reviewとしてstateへ保存し、後続処理を示すsummaryを返します。
rate-limit terminal処理とshortcut
src/cli-pr-monitor/src/stages/poll/rate_limit.rs, src/cli-pr-monitor/src/stages/poll/rate_limit/tests.rs
rate-limitのpark処理をrate_limitedまたはpending_reviewのterminal結果へ変更しました。mergeableかつcleanなPR向けのshortcutと、その状態保存・dedup・fail-open動作をテストしました。
旧連携と設計記録の撤去
.claude/hooks-config.toml, src/hooks-session-start/src/main.rs, src/cli-telemetry-report/src/config.rs, docs/adr/*, docs/harness-improvement-plan.md, docs/todo18.md
PR monitor catch-up、旧hook設定、CronCreate前提の記録とtelemetry IDを削除またはsingle-shot方針へ更新しました。

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

Sequence Diagram(s)

sequenceDiagram
  participant CLI
  participant Monitor
  participant PollLoop
  participant StateFile
  participant GitHubActions
  CLI->>Monitor: single-shot checkを開始する
  Monitor->>StateFile: 同一PR・repository・headのstateを確認する
  Monitor->>PollLoop: 継続stateで監視を実行する
  PollLoop->>StateFile: pending_reviewまたはrate_limitedを保存する
  PollLoop->>GitHubActions: 後続イベント経路を報告する
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 タイトルは CronCreate の park モデル撤去と cli-pr-monitor の single-shot 化という主要変更を明確に示しています。
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/wp17-pr3-wakeup-removal

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

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

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

  • トリガー: issue_comment (created) / 実行 run
  • CI: pending (rust (ubuntu-latest) pending, rust (windows-latest) pending, CodeRabbit pending)
  • レビュー状況: CodeRabbit はレビュー未着 (「Review in progress」プレースホルダーコメントのみ、24 ファイルを処理中との通知)。人間レビュー・インラインコメントともに 0 件。
  • Verdict: user_decision (レビュー・CI がいずれも未確定のため判定不能。現時点では blocker となる指摘は無い)

Applicable Findings (Critical / High / Major)

該当なし (レビュー指摘 0 件)

Applicable Findings (Medium 以下)

該当なし

Filtered (not applicable)

該当なし

軽量サマリー (diff 概要)

  • 変更ファイル数: 24 (Rust ソース 13、設定/テンプレート 3、ドキュメント/ADR 5、その他 3)
  • 変更の性質: PR タイトル通り「CronCreate park モデルの撤去 + single-shot 化」のリファクタ。.claude/hooks-config.toml から旧 [post_pr_monitor] daemon/CronCreate 設定セクションを削除し、pr-monitor-config.toml を正とするコメントに置換。cli-pr-monitor 配下 (stages/poll/*, state.rs, util.rs 等) と hooks-session-start/src/pr_monitor.rs に実装変更。ADR-018/034/064 と docs/todo18.md, docs/harness-improvement-plan.md を追随更新。
  • mergeStateStatus: BLOCKED (CI 未完了のため)

次のアクション

  • CI (rust ubuntu/windows) と 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: 4

🤖 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 `@docs/harness-improvement-plan.md`:
- Around line 205-213: 同じ計画書の旧 park 検証残を更新し、rate-limit 時の park 観測項目を moot
として閉じてください。該当する WP-17 または rate-limit 検証残の記載では、削除済みの park/wakeup 機構への作業指示を除き、PR
イベントを担う GitHub Actions 経路の検証項目だけを残してください。
- Around line 205-213: GitHub Actions 経路の rate-limit
保留判定を実走行で検証し、pull_request_review、issue_comment、rate-limit 中の
retry、coderabbitai[bot] の dedup 判定を含む smoke/integration 結果を
docs/adr/adr-064-monitor-success-positive-evidence.md に追記して検証残を完了させる。既存の wakeup
廃止方針や関連する ADR 記録は変更せず、Actions 側の実行結果と判定を ADR-064 に反映する。

In `@src/cli-pr-monitor/src/stages/poll/mod.rs`:
- Around line 103-106: Update the head_commit assignments in
finalize_pending_review (src/cli-pr-monitor/src/stages/poll/mod.rs, lines
103-106), finalize_posted_retrigger
(src/cli-pr-monitor/src/stages/poll/rate_limit.rs, line 115), and
finalize_waiting_reset (src/cli-pr-monitor/src/stages/poll/rate_limit.rs, line
178) to update state only when ctx.pr_info.head_commit is Some, matching the
existing write-once behavior of fix_push_time; preserve the existing state value
when it is None.

In `@src/cli-pr-monitor/src/stages/poll/rate_limit/tests.rs`:
- Around line 213-248: テスト関数 finalize_waiting_reset_persists_head_commit の
pr_info で pr_number を Some(42) ではなく None に変更し、emit_shortcut_signal_if_eligible
が実際の gh CLI を呼び出さず早期 return するようにしてください。head_commit
の状態更新と永続化に関する既存の検証はそのまま維持してください。
🪄 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: c3357712-b61c-45e3-a220-82602a2253a9

📥 Commits

Reviewing files that changed from the base of the PR and between d12462d and 3cb0df3.

📒 Files selected for processing (24)
  • .claude/hooks-config.toml
  • docs/adr/adr-018-pr-monitor-takt-migration.md
  • docs/adr/adr-034-coderabbit-auto-monitoring.md
  • docs/adr/adr-064-monitor-success-positive-evidence.md
  • docs/harness-improvement-plan.md
  • docs/todo18.md
  • pr-monitor-config.toml
  • src/check-ci-coderabbit/src/main.rs
  • src/cli-pr-monitor/src/config.rs
  • src/cli-pr-monitor/src/main.rs
  • src/cli-pr-monitor/src/stages/monitor.rs
  • src/cli-pr-monitor/src/stages/poll/iteration.rs
  • src/cli-pr-monitor/src/stages/poll/mod.rs
  • src/cli-pr-monitor/src/stages/poll/rate_limit.rs
  • src/cli-pr-monitor/src/stages/poll/rate_limit/tests.rs
  • src/cli-pr-monitor/src/stages/poll/rate_limit_signal.rs
  • src/cli-pr-monitor/src/stages/poll/review_recheck.rs
  • src/cli-pr-monitor/src/stages/poll/review_recheck_signal.rs
  • src/cli-pr-monitor/src/state.rs
  • src/cli-pr-monitor/src/util.rs
  • src/cli-telemetry-report/src/config.rs
  • src/hooks-session-start/src/main.rs
  • src/hooks-session-start/src/pr_monitor.rs
  • templates/pr-monitor-config.toml
💤 Files with no reviewable changes (4)
  • src/cli-pr-monitor/src/stages/poll/rate_limit_signal.rs
  • src/cli-pr-monitor/src/stages/poll/review_recheck_signal.rs
  • src/cli-pr-monitor/src/stages/poll/review_recheck.rs
  • src/hooks-session-start/src/pr_monitor.rs

Comment on lines +205 to +213
#### WP-17 PR 3: wakeup 機構(CronCreate 系)の廃止(旧ステップ 3) — 実施中(本 PR)

- 廃止対象: cli-pr-monitor の CronCreate park モデル(ADR-018 追記の Bundle b で再導入。PR #237 で失効事例を観測済み)。
- park / wakeup 経路: state の `next_wakeup_at_unix` / `wakeup_reason`、monitor stage の wakeup invocation、`[PR_MONITOR_PARK]` envelope 出力。
- hooks-session-start の pr_monitor catch-up nudge(park 失効の救済層。機構ごと dead code になるため撤去)。
- 代替: PR イベント(レート制限中の再開含む)は GitHub Actions 経路(Phase A/B)が引き受ける。CodeRabbit の後続コメント / レビュー到着がそのままトリガーになるため、ローカルの時限 wakeup は不要。
- 記録: ADR-018 amendment を起票し、着手前決定 2 の ADR-064 検証残移し替え((a) moot / (b) Actions 経路へ引き継ぎ)を amendment と ADR-064 ステータス欄の両方に記載。ADR-034 の CronCreate 参照も同 PR で整合を取る。
- 実装メモ(本 PR で確定した設計判断): 時刻窓アンカーの state 継続(`should_continue_state` = 同一 PR + 同一 head なら `started_at` / `fix_push_time` を維持)は park の付随物ではないため**残した**。落とすと手動再実行のたびに `--push-time` が「今」へリセットされ、push 後に届いた CR コメントが新着判定から漏れる。rate-limit の retry 上限 / comment dedup も同様に維持。
- 本 PR の PR がそのまま**スモーク段 1 の観測対象**を兼ねる(variable 再設定済みの状態で、非 `claude/` PR に対する fix job の prefix deny をマージ済み master 版 workflow で確認する)。

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

park 検証残を同じ計画書から更新してください。

Line [205]-[213] で park/wakeup の廃止を記録しています。しかし、同じファイルの Line [90]-[93] は、rate-limit 時の park 観測を現在の残作業として残しています。削除済み機構への作業指示になります。park の観測を moot として閉じ、GitHub Actions 経路の検証残だけを記載してください。

修正案
-### WP-15 追補残: レート制限 park の実観測
+### WP-15 追補残: GitHub Actions 経路の検証

-- 残作業: 実 push/PR サイクルで CodeRabbit レート制限が自然発生した際に
-  (a) 監視が success で終わらず park することを実観測したら完了。
+- `park` の実観測は WP-17 PR 3 で機構が廃止されたため moot として閉じる。
+- 残作業: GitHub Actions 経路で保留判定と後続処理を確認する。
🤖 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 `@docs/harness-improvement-plan.md` around lines 205 - 213, 同じ計画書の旧 park
検証残を更新し、rate-limit 時の park 観測項目を moot として閉じてください。該当する WP-17 または rate-limit
検証残の記載では、削除済みの park/wakeup 機構への作業指示を除き、PR イベントを担う GitHub Actions
経路の検証項目だけを残してください。

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

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

workflow="$(fd -t f -a 'pr-monitor.yml' . | head -n 1)"
test -n "$workflow"

rg -n -C 8 \
  'pull_request_review|issue_comment|workflow_dispatch|pr_number|cli-pr-monitor|monitor-only|pending_review|rate_limited' \
  "$workflow"

rg -n -C 6 \
  'head_commit|dedup|rate.limit|pending_review|rate_limited' \
  src/cli-pr-monitor \
  docs/adr/adr-064-monitor-success-positive-evidence.md

Repository: aloekun/claude-code-hook-test

Length of output: 167


🏁 Script executed:

#!/bin/bash
set -euopipefail

printf '\n=== tracked candidate files ===\n'
git ls-files | rg '(^docs/harness-improvement-plan\.md$|^docs/adr/adr-064|pr-monitor|cli-pr-monitor)' || true

printf '\n=== harness lines 190-225 ===\n'
sed -n '190,225p' docs/harness-improvement-plan.md | nl -ba -v190

printf '\n=== adr-064 file size and headings ===\n'
fd -t f 'adr-064' docs src || true
while IFS= read -r f; do
  echo "--- $f"
  wc -l "$f"
  sed -n '1,120p' "$f"
done < <(fd -t f 'adr-064' docs)

printf '\n=== repo-wide searches ===\n'
rg -n -C 4 \
  'pull_request_review|issue_comment|workflow_dispatch|pr_number|cli-pr-monitor|monitor-only|pending_review|rate_limited|head_commit|dedup|rate.limit|next_wakeup_at_unix|wakeup_reason|CronCreate' \
  . || true

Repository: aloekun/claude-code-hook-test

Length of output: 820


🏁 Script executed:

#!/bin/bash
set -e

printf '\n=== tracked candidate files ===\n'
git ls-files | rg '(^docs/harness-improvement-plan\.md$|^docs/adr/adr-064|pr-monitor|cli-pr-monitor)' || true

printf '\n=== harness lines 190-225 ===\n'
sed -n '190,225p' docs/harness-improvement-plan.md | nl -ba -v190

printf '\n=== adr-064 related files ===\n'
git ls-files | rg '(^docs/adr/adr-064|--064--|adr-[0-9]+.*monitor)' || true
while IFS= read -r f; do
  echo "--- $f ($(wc -l < "$f") lines)"
  sed -n '1,160p' "$f"
done < <(git ls-files | rg '(^docs/adr/adr-064|--064--|adr-[0-9]+.*monitor)')

printf '\n=== repo-wide searches ===\n'
rg -n -C 4 \
  'pull_request_review|issue_comment|workflow_dispatch|pr_number|cli-pr-monitor|monitor-only|pending_review|rate_limited|head_commit|dedup|rate\.limit|next_wakeup_at_unix|wakeup_reason|CronCreate' \
  . || true

Repository: aloekun/claude-code-hook-test

Length of output: 1787


🏁 Script executed:

#!/bin/bash
set -e

printf '\n=== harness lines 190-225 ===\n'
sed -n '190,225p' docs/harness-improvement-plan.md | awk '{printf "%4d\t%s\n", NR+189, $0}'

printf '\n=== adr-064 evidence excerpt ===\n'
sed -n '1,120p' docs/adr/adr-064-monitor-success-positive-evidence.md | awk '{printf "%4d\t%s\n", NR, $0}'

printf '\n=== workflow relevant contents ===\n'
sed -n '1,260p' .github/workflows/pr-monitor.yml | awk '{printf "%4d\t%s\n", NR, $0}'

printf '\n=== key references in source/docs ===\n'
rg -n -C 4 'pull_request_review|issue_comment|workflow_dispatch|pr_number|cli-pr-monitor|monitor-only|pending_review|rate_limited|head_commit|dedup|rate\.limit|next_wakeup_at_unix|wakeup_reason|CronCreate|actions' \
  .github/workflows/pr-monitor.yml \
  docs/adr/adr-064-monitor-success-positive-evidence.md \
  src/cli-pr-monitor \
  docs/harness-improvement-plan.md \
  --glob '!**/target/**' \
  || true

Repository: aloekun/claude-code-hook-test

Length of output: 50386


GitHub Actions 経路での rate-limit 保留判定を実走行してください。

wakeup 廃止で PR が Actions 経路に依存するため、docs/adr/adr-064-monitor-success-positive-evidence.md の検証残は Actions 側で閉じてください。pull_request_reviewissue_comment・レート制限中の retry・coderabbitai[bot] の dedup 判定を含む smoke/integration 実行結果を ADR-064 に追記してください。

🤖 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 `@docs/harness-improvement-plan.md` around lines 205 - 213, GitHub Actions 経路の
rate-limit 保留判定を実走行で検証し、pull_request_review、issue_comment、rate-limit 中の
retry、coderabbitai[bot] の dedup 判定を含む smoke/integration 結果を
docs/adr/adr-064-monitor-success-positive-evidence.md に追記して検証残を完了させる。既存の wakeup
廃止方針や関連する ADR 記録は変更せず、Actions 側の実行結果と判定を ADR-064 に反映する。

Comment on lines +103 to +106
state.head_commit = ctx.pr_info.head_commit.clone();
state.fix_push_time = state
.fix_push_time
.or_else(|| ctx.fix_push_time.map(String::from));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

terminal 化の 3 経路が head_commit を None で上書きします。 共通の根本原因は、pr_info.head_commit の値を条件なしで state へ代入していることです。gh pr view --json headRefOid の取得が失敗すると pr_info.head_commit は None になり、既存 state の継続アンカーが消えます。その結果、次回 --monitor-only 実行時に should_continue_state が false となり、時刻窓が「今」にリセットされ、その間に届いた CodeRabbit コメントを取りこぼします。fix_push_time と同じ write-once 方針へ揃えてください。

  • src/cli-pr-monitor/src/stages/poll/mod.rs#L103-L106: finalize_pending_reviewctx.pr_info.head_commit が Some のときだけ state.head_commit を更新する。
  • src/cli-pr-monitor/src/stages/poll/rate_limit.rs#L115-L115: finalize_posted_retrigger で同じ条件付き更新にする。
  • src/cli-pr-monitor/src/stages/poll/rate_limit.rs#L178-L178: finalize_waiting_reset で同じ条件付き更新にする。
📍 Affects 2 files
  • src/cli-pr-monitor/src/stages/poll/mod.rs#L103-L106 (this comment)
  • src/cli-pr-monitor/src/stages/poll/rate_limit.rs#L115-L115
  • src/cli-pr-monitor/src/stages/poll/rate_limit.rs#L178-L178
🤖 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 `@src/cli-pr-monitor/src/stages/poll/mod.rs` around lines 103 - 106, Update the
head_commit assignments in finalize_pending_review
(src/cli-pr-monitor/src/stages/poll/mod.rs, lines 103-106),
finalize_posted_retrigger (src/cli-pr-monitor/src/stages/poll/rate_limit.rs,
line 115), and finalize_waiting_reset
(src/cli-pr-monitor/src/stages/poll/rate_limit.rs, line 178) to update state
only when ctx.pr_info.head_commit is Some, matching the existing write-once
behavior of fix_push_time; preserve the existing state value when it is None.

Comment on lines +213 to +248
fn finalize_waiting_reset_persists_head_commit() {
let tmp = tempfile::tempdir().unwrap();
let state_path = tmp.path().join("state.json");
let mut state = PrMonitorState::new(Some(42), Some("o/r".into()), "t".into());
state.rate_limit = Some(RateLimitState {
until_unix_secs: 9_999_999_999,
comment_event_time: "2026-08-03T00:00:00Z".into(),
wait_minutes: 47,
wait_seconds: 10,
});
let rl = state.rate_limit.clone().unwrap();
let pr_info = crate::util::PrInfo {
pr_number: Some(42),
repo: Some("o/r".into()),
push_time: None,
head_commit: Some("deadbeef".into()),
fix_push_time: None,
};

let outcome = finalize_waiting_reset(
&mut state,
&rl,
&pr_info,
&serde_json::Value::Null,
&state_path,
);

assert_eq!(outcome.action, "rate_limited");
assert_eq!(state.head_commit.as_deref(), Some("deadbeef"));
let persisted = crate::state::read_state_from(&state_path).unwrap();
assert_eq!(
persisted.head_commit.as_deref(),
Some("deadbeef"),
"head_commit が persist されないと should_continue_state が次回 fresh 初期化に倒れる"
);
}

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

このテストは実 gh CLI を呼び出します。

pr_infopr_number: Some(42) を設定しているため、finalize_waiting_reset 内の emit_shortcut_signal_if_eligiblefetch_mergeable_status を実行し、gh pr view を呼び出します。ネットワークと認証に依存するため、CI で遅延または不安定になります。このテストの検証対象は head_commit の persist だけです。pr_number を None にして shortcut 経路を早期 return させてください。

♻️ 提案する修正
     let pr_info = crate::util::PrInfo {
-        pr_number: Some(42),
-        repo: Some("o/r".into()),
+        pr_number: None,
+        repo: None,
         push_time: None,
         head_commit: Some("deadbeef".into()),
         fix_push_time: None,
     };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
fn finalize_waiting_reset_persists_head_commit() {
let tmp = tempfile::tempdir().unwrap();
let state_path = tmp.path().join("state.json");
let mut state = PrMonitorState::new(Some(42), Some("o/r".into()), "t".into());
state.rate_limit = Some(RateLimitState {
until_unix_secs: 9_999_999_999,
comment_event_time: "2026-08-03T00:00:00Z".into(),
wait_minutes: 47,
wait_seconds: 10,
});
let rl = state.rate_limit.clone().unwrap();
let pr_info = crate::util::PrInfo {
pr_number: Some(42),
repo: Some("o/r".into()),
push_time: None,
head_commit: Some("deadbeef".into()),
fix_push_time: None,
};
let outcome = finalize_waiting_reset(
&mut state,
&rl,
&pr_info,
&serde_json::Value::Null,
&state_path,
);
assert_eq!(outcome.action, "rate_limited");
assert_eq!(state.head_commit.as_deref(), Some("deadbeef"));
let persisted = crate::state::read_state_from(&state_path).unwrap();
assert_eq!(
persisted.head_commit.as_deref(),
Some("deadbeef"),
"head_commit が persist されないと should_continue_state が次回 fresh 初期化に倒れる"
);
}
fn finalize_waiting_reset_persists_head_commit() {
let tmp = tempfile::tempdir().unwrap();
let state_path = tmp.path().join("state.json");
let mut state = PrMonitorState::new(Some(42), Some("o/r".into()), "t".into());
state.rate_limit = Some(RateLimitState {
until_unix_secs: 9_999_999_999,
comment_event_time: "2026-08-03T00:00:00Z".into(),
wait_minutes: 47,
wait_seconds: 10,
});
let rl = state.rate_limit.clone().unwrap();
let pr_info = crate::util::PrInfo {
pr_number: None,
repo: None,
push_time: None,
head_commit: Some("deadbeef".into()),
fix_push_time: None,
};
let outcome = finalize_waiting_reset(
&mut state,
&rl,
&pr_info,
&serde_json::Value::Null,
&state_path,
);
assert_eq!(outcome.action, "rate_limited");
assert_eq!(state.head_commit.as_deref(), Some("deadbeef"));
let persisted = crate::state::read_state_from(&state_path).unwrap();
assert_eq!(
persisted.head_commit.as_deref(),
Some("deadbeef"),
"head_commit が persist されないと should_continue_state が次回 fresh 初期化に倒れる"
);
}
🤖 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 `@src/cli-pr-monitor/src/stages/poll/rate_limit/tests.rs` around lines 213 -
248, テスト関数 finalize_waiting_reset_persists_head_commit の pr_info で pr_number を
Some(42) ではなく None に変更し、emit_shortcut_signal_if_eligible が実際の gh CLI を呼び出さず早期
return するようにしてください。head_commit の状態更新と永続化に関する既存の検証はそのまま維持してください。

@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

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

  • トリガー: pull_request_review (submitted) / 実行 run
  • CI: rust (ubuntu-latest) pass (1m31s) / rust (windows-latest) pass (4m39s) / CodeRabbit pass (Review completed)。本 workflow 自身の analyze job のみ pending (実行中)。
  • レビュー状況: CodeRabbit が新規レビューを投稿 (state: COMMENTED、Actionable comments: 4件、2026-08-03T15:36 UTC)。人間レビューは 0 件、reviewDecision 未設定。mergeStateStatus: BLOCKED (承認未確定のため)。
  • Verdict: user_decision (applicable な指摘は存在するが、いずれも Minor 止まりで Critical/High/Major は無い)

Applicable Findings (Critical / High / Major)

該当なし

Applicable Findings (Medium 以下)

# File (Line) Reviewer Issue Recommended Action
1 docs/harness-improvement-plan.md (L90-93) CodeRabbit WP-15 追補残「レート制限 park の実観測」が、本PRで ADR-064 に追加した amendment (park 観測は moot として閉じた) と不整合なまま残っている 当該箇所を moot 扱いに更新し、GitHub Actions 経路の検証残のみを残す文言に揃える
2 src/cli-pr-monitor/src/stages/poll/mod.rs (L103-106)、rate_limit.rs (L115, L178) CodeRabbit head_commit を条件なしで state へ上書きしており、gh pr view 失敗時に None で既存の継続アンカーを消してしまう。次回 --monitor-only 実行時に should_continue_state が false になり時刻窓がリセットされ、その間の CR コメントを取りこぼす fix_push_time と同じ write-once 方針に揃え、Some のときのみ更新する
3 src/cli-pr-monitor/src/stages/poll/rate_limit/tests.rs (L213-248) CodeRabbit finalize_waiting_reset_persists_head_commitpr_number: Some(42) を設定しているため emit_shortcut_signal_if_eligible 経由で実際の gh CLI を呼び出しうる (ネットワーク依存でCI不安定化) pr_number/repoNone にして shortcut 経路を早期 return させる

Filtered (not applicable)

# File (Line) Issue Filter Reason
1 docs/harness-improvement-plan.md (L205-213) GitHub Actions 経路での rate-limit 保留判定の実走行検証・ADR-064 への結果追記を求める指摘 既に ADR-064 の Amendment (2026-08-03) で「Actions 経路の同等保証は同経路の検証残として引き継ぐ」と明示的に記録済み。実走行スモークは自然発生条件依存の運用タスクであり、本PRのコード修正対象ではない

次のアクション

aloekun added a commit that referenced this pull request Aug 3, 2026
…bit #353)

PR #353 の CodeRabbit 指摘 3 件への対応。うち 2 件は本 PR が持ち込んだ実バグだった。

## 指摘 2 (Minor): terminal 化 3 経路が head_commit を None で上書きする

`finalize_pending_review` / `finalize_waiting_reset` / `finalize_posted_retrigger` が
`state.head_commit = pr_info.head_commit.clone()` と**無条件代入**していた。
`util::get_pr_head_commit` は gh 失敗を None に潰すため、API 障害のたびに保存済み OID が
消える。その状態で次回 `--monitor-only` を実行すると `should_continue_state` が None を
見て継続を拒否し、時刻窓アンカーが「今」へリセットされて間に届いた CR コメントを
取りこぼす — 本 PR が動機に挙げた incident class (#237/#307/#309) と同型。

CodeRabbit が「共通の根本原因」と指摘したとおり 3 経路に同じ欠陥があったため、
`PrMonitorState::record_head_commit(Option<&str>)` を state.rs に置き、Some のときだけ
上書きする単一実装へ集約した。取得失敗は「head が変わった」の証拠ではないので既存値の
保持が正しい (fail-safe)。回帰テスト 2 件 (None で消えない / Some で上書きする) を追加。

## 指摘 3 (Minor): テストが実 gh CLI を呼ぶ

`finalize_waiting_reset` は内部で `fetch_mergeable_status` → `run_gh_quiet` を呼ぶため、
前コミットで追加した回帰テストが実 gh プロセスを起動していた (ネットワーク依存・低速)。

`finalize_waiting_reset_with(..., fetch_mergeable: impl FnOnce(&PrInfo) -> Option<..>)`
へ本体を切り出し、production は `fetch_mergeable_status` を、テストは closure を渡す形に
した (cli-push-runner の `verify_diff_covers_pr_range` と同じ注入の流儀)。

あわせて「注入したものが実際に使われている」ことを確認するテストを追加した — `|_| None`
を渡すだけのテストでは、fetcher を無視する実装でも通ってしまい注入の正しさを判別できない。
Cell フラグで呼び出し自体を観測する。

## 指摘 1 (Minor): 計画書の stale な park 検証残

「WP-15 追補残: レート制限 park の実観測」は park 廃止で (a) が moot になっていた。
見出しを「レート制限時の保留保証 (GitHub Actions 経路)」へ改め、(a) の終了と (b) の
引き継ぎ先を明記した (ADR-018 amendment / ADR-064 ステータス欄と同じ内容を計画書側にも
反映し、3 箇所の記述を揃える)。

検証: cargo test --workspace 1905 件 pass (新規 4 件)、clippy --workspace -D warnings 緑、
pnpm lint:docs / lint:md 0 error。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…d 回帰復元 (CodeRabbit #353)

PR #353 のレビュー指摘への対応。CodeRabbit 3 件 + pre-push simplicity 1 件で、
**4 件中 3 件は本 PR が持ち込んだ実バグ / カバレッジ欠落**だった。

## CodeRabbit 指摘 2 (Minor): terminal 化 3 経路が head_commit を None で上書きする

`finalize_pending_review` / `finalize_waiting_reset` / `finalize_posted_retrigger` が
`state.head_commit = pr_info.head_commit.clone()` と**無条件代入**していた。
`util::get_pr_head_commit` は gh 失敗を None に潰すため、API 障害のたびに保存済み OID が
消える。その状態で次回 `--monitor-only` を実行すると `should_continue_state` が None を
見て継続を拒否し、時刻窓アンカーが「今」へリセットされて間に届いた CR コメントを
取りこぼす — 本 PR が動機に挙げた incident class (#237/#307/#309) と同型。

CodeRabbit が「共通の根本原因」と指摘したとおり 3 経路に同じ欠陥があったため、
`PrMonitorState::record_head_commit(Option<&str>)` を state.rs に置き、Some のときだけ
上書きする単一実装へ集約した。取得失敗は「head が変わった」の証拠ではないので既存値の
保持が正しい (fail-safe)。回帰テスト 2 件 (None で消えない / Some で上書きする) を追加。

## CodeRabbit 指摘 3 (Minor): テストが実 gh CLI を呼ぶ

`finalize_waiting_reset` は内部で `fetch_mergeable_status` → `run_gh_quiet` を呼ぶため、
前コミットで追加した回帰テストが実 gh プロセスを起動していた (ネットワーク依存・低速)。

`finalize_waiting_reset_with(..., fetch_mergeable: impl FnOnce(&PrInfo) -> Option<..>)`
へ本体を切り出し、production は `fetch_mergeable_status` を、テストは closure を渡す形に
した (cli-push-runner の `verify_diff_covers_pr_range` と同じ注入の流儀)。

あわせて「注入したものが実際に使われている」ことを確認するテストを追加した — `|_| None`
を渡すだけのテストでは、fetcher を無視する実装でも通ってしまい注入の正しさを判別できない。
Cell フラグで呼び出し自体を観測する。

## pre-push simplicity 指摘 (SIM-NEW-rate_limit-L122, Medium): fail-closed 回帰の消失

tests.rs のファイル分割時に `finalize_posted_retrigger_action_required_when_write_state_fails`
だけが欠落していた。この関数は 2 つの sibling (`finalize_waiting_reset` /
`finalize_pending_review`) と**逆に fail-closed** で、理由は `@coderabbitai review` 投稿と
いう副作用を伴うため state 永続化の成否で重複投稿を防ぐ必要があるから。fail-open 側 2 件の
回帰テストは移行されていたのに、意図的に非対称な唯一の経路のテストが落ちていた。復元し、
非対称の理由を doc comment に明記した。

## CodeRabbit 指摘 1 (Minor): 計画書の stale な park 検証残

「WP-15 追補残: レート制限 park の実観測」は park 廃止で (a) が moot になっていた。
見出しを「レート制限時の保留保証 (GitHub Actions 経路)」へ改め、(a) の終了と (b) の
引き継ぎ先を明記した (ADR-018 amendment / ADR-064 ステータス欄と同じ内容を計画書側にも
反映し、3 箇所の記述を揃える)。

検証: cargo test --workspace 1906 件 pass (新規 5 件)、clippy --workspace -D warnings 緑、
pnpm lint:docs / lint:md 0 error。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@aloekun
aloekun force-pushed the feat/wp17-pr3-wakeup-removal branch from f626224 to c4bc65e Compare August 3, 2026 16:10
@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

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

  • トリガー: workflow_dispatch (manual) / 実行 run
  • CI: rust (ubuntu-latest) pass (1m33s) / rust (windows-latest) pass (4m13s)(いずれも最新コミット c4bc65e に対する run 30830912136)。CodeRabbit チェックは "Review skipped: incremental reviews are disabled" 表示(review 自体は別途 reviews API 経由で投稿済み、下記参照)。
  • レビュー状況: CodeRabbit が commit 3cb0df3 に対し 2026-08-03T15:36 UTC にレビュー投稿(COMMENTED、Actionable comments 4件)。その後 2026-08-03T16:04 UTC に修正コミット c4bc65e("head_commit の None 上書き防止 + テストの gh 依存除去 + fail-close…")が push され、CI が再実行・pass。CodeRabbit はこの修正コミットに対して未だ再レビューしていない(reviews API 上、最新レビューは commit 3cb0df3 のまま)。人間レビューは 0 件、reviewDecision 未設定、mergeStateStatus: BLOCKED(承認未確定によるものと推定)。
  • Verdict: approved(CodeRabbit 指摘ベースでは、前回分析時点の Medium 指摘 3 件はすべて修正コミットで対応済みと diff 上で確認。現時点で残る applicable な指摘なし。ただし CodeRabbit 自身の再レビューはまだ届いていない点に留意)

Applicable Findings (Critical / High / Major)

該当なし

Applicable Findings (Medium 以下)

該当なし(前回分析の #1#3 はいずれも c4bc65e で対応済みと確認)

Filtered (not applicable)

該当なし

前回指摘の対応状況(参考・diff で確認済み)

前回 # 指摘内容 対応状況
1 docs/harness-improvement-plan.md の WP-15 追補残が旧 park 前提のまま c4bc65e で "2026-08-04 更新" として (a) park 廃止による moot 化、(b) Actions 経路への引き継ぎ、を明記済み
2 head_commit を無条件上書きし gh 失敗時に継続アンカーが消える PrMonitorState::record_head_commitSome のときのみ上書きする write-once 実装に変更。ユニットテスト record_head_commit_keeps_existing_when_current_unavailable / _overwrites_when_current_available で固定
3 rate_limit テストが実 gh CLI を呼びうる (pr_number: Some(42)) pr_numberNone に変える代わりに、finalize_waiting_reset_with へ shortcut 判定用のクロージャを注入する DI 方式へ変更し、テストからは実 gh 呼び出しが発生しない構造に修正

次のアクション

  • CodeRabbit による c4bc65e への再レビュー到着を待つ(新たな指摘が出れば次回起動時に分析)。
  • mergeStateStatus が BLOCKED のままなので、マージ前に必要なレビュー承認(human review)の有無を人間側で確認・判断する。
  • 現時点で追加のコード修正は不要と判断。

@aloekun
aloekun merged commit 53de889 into master Aug 3, 2026
3 checks passed
@aloekun
aloekun deleted the feat/wp17-pr3-wakeup-removal branch August 3, 2026 16:36
aloekun added a commit that referenced this pull request Aug 4, 2026
スモーク段 2 の 2 回目の実走 (2026-08-04) で `Extract findings JSON` step が exit 1 で失敗し、
Phase B が findings 取得直後で停止した。

## 原因: 出力形式の保証を指示層だけに委ねていた

findings agent は仕込んだ docs 指摘 3 件を**過不足なく検出**していたが、出力を ```json で
囲んで返した:

    jq: parse error: Invalid numeric literal at line 2, column 0
    [FIX_PUSH_DENY] findings agent の出力が JSON 配列ではありません
    ```json
    [
      {"file": "docs/phase-b-smoke-test.md", ...},
      ...
    ]
    ```

prompt は「前置き・後書き・**コードフェンスを一切含まない** JSON 配列のみ」と明示していたが、
agent はこれに従わなかった。**指示層だけで出力形式を保証する設計では、モデルの気まぐれで
経路全体が止まる** (ADR-042: ルールでなく仕組みで守る)。

## 修正: 決定論層でフェンス行を落とす

`Extract findings JSON` で jq に渡す前に sed でフェンス行のみを除去する:

    sed -e 's/^[[:space:]]*```[[:alnum:]]*[[:space:]]*$//' "$RAW_FILE" > "$FINDINGS_FILE"

設計上の線引き:

- **フェンスを剥がす以上のことはしない**。中身の修復 (引用符の補完、部分抽出等) は試みない。
  agent が全く違う形式を返した場合は従来どおり落とすべきで、ヒューリスティックな救済は
  「壊れた入力をそれらしく通す」経路を作る
- **fail-closed は維持**。剥がした後も配列でなければ下の guard が exit 1 で止める
- 診断出力を `$RAW_FILE` (剥がす前) に変更。フェンス以外が原因で落ちた場合に、agent が実際に
  何を返したかがログに残る

prompt 側も二層目の防御として残し、「フェンスがあると後続がパースに失敗する」という理由と
実際に発生した日付を明記した (指示は保険であり主たる担保ではない旨も併記)。

## 検証

- **実際に落ちた入力でロジックを実測**: ```json で囲まれた配列 → 除去後にパース成功
  (isArray: true、要素 2 件)。フェンスなしの素の配列 → 副作用なくパース成功
- js-yaml パースで 13 step 構造と claude_args 全行のフラグ形式を確認
- 実走検証はスモーク段 2 (PR #355) の 3 回目の dispatch が兼ねる

## 併せて観測できたこと (段 2 の中間成果)

- findings agent が仕込んだ不整合 3 点を正確に検出 = 観測装置の設計は妥当
- 決定論的著者フィルタ (#352) と gh api 修正 (#356) が実走で正常動作
- degrade 分岐 (#353 で修正) が `GATE_OUTCOME: skipped` を正しく判別し、
  「gate step に到達しませんでした」を出力 = fail-closed と診断が設計どおり機能

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
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