Skip to content

fix(cli-push-runner): rename summary の波括弧形式パース修正 + WP-17 再分割計画 (2a) - #350

Merged
aloekun merged 3 commits into
masterfrom
feat/wp17-r2a-docs-parser
Aug 3, 2026
Merged

fix(cli-push-runner): rename summary の波括弧形式パース修正 + WP-17 再分割計画 (2a)#350
aloekun merged 3 commits into
masterfrom
feat/wp17-r2a-docs-parser

Conversation

@aloekun

@aloekun aloekun commented Aug 3, 2026

Copy link
Copy Markdown
Owner

概要

WP-17 PR 2(Phase B 無人 fix push)の再分割 2a です。incident で組み替えが必要に
なった資産のうち、計画書の更新rename パーサ修正の 2 点を land します。
lib 抽出 + gate(2b)、Phase B workflow + 有効化(2c)は後続 PR です。

コードの実挙動を変えるのは 2 コミット目のみで、1 コミット目は docs です。

コミット

  1. docs(harness-plan) — WP-17 の実行状況と再分割計画(2a/2b/2c)を反映
  2. fix(cli-push-runner) — rename summary の波括弧形式をパースできるよう修正

1. 計画書更新

2026-08-02 の incident(一括実装 → PR size gate で分割 → 先頭 PR が simplicity REJECT
→ takt fix が lib 抽出 2 crate を丸ごと削除し、gate 全 PASS のまま空洞化 push が
「成功」)を受けた再分割計画を計画書に反映します。原因分析と再発防止は
ADR-068(fix 後退検知 backstop、#348)/ ADR-069(PR chain 宣言規約、#349)として
land 済みで、本節はその上で残資産をどう land するかの実行手順です。

別セッションが本節だけで作業を再開できるよう、change_id 単位の資産表・回収手順・
conflict 解決指針・2b の chain 宣言(ADR-069 初回 dogfood)まで自己完結的に記載
してあります。

2. rename パーサ修正

jj diff --summary の rename / copy 行を誤ってパースし、rename を含む PR が一律
push 不能
になっていた不具合の修正です。WP-17 2a の push が exit 5 で停止して顕在化
しました。

実測書式と旧実装のずれ

jj (0.42.0 / Windows) は共通 prefix / suffix を括り出した波括弧形式で出します:

R src\{cli-autonomy-gate => lib-autonomy-policy}\src\decision.rs

旧実装は <status> <old> <new> の 3 トークン空白区切りを前提に rsplit_once(' ')
していたため、上の行から lib-autonomy-policy}\src\decision.rs という壊れたパスを
取り出していました。これが --git 側の b/src/lib-autonomy-policy/src/decision.rs
と一致せず、常に「未収録」と判定されます。判定は block 側に倒れるので fail-closed
ではありますが、正当な push を止める誤検知です。

根拠が fixture だった問題

3 トークン形式を前提にした根拠は、コード内コメントが引用していた lib_docs_policy
"R docs/a.md docs/b.md" というテスト文字列でした。これは jj の出力を観測したもの
ではなく手で作った fixture で、実挙動の証拠になっていません。dev-conventions の
「外部 fixture 参照テストは値まで assert」が想定する失敗そのものです。本 PR のテストは
実測値を定数 OBSERVED_RENAME_SUMMARY として持ち、それを assert します。

なお lib-docs-policy / cli-pr-monitor::scope_guard は R/C 行を即 fail-closed reject
していて 3 トークン前提には依存していないため、同種の潜在バグはありません(レビューで
cross-file 確認済み)。旧コメントの「実証」は同じ fixture 文字列の偶然の一致でした。

修正方針

個別ケースを潰すのではなく、rename 行の入力空間を 1 バッチで固定します
(dev-conventions: パーサ修正は全 branch を一度に堅牢化):

  • 波括弧形式: prefix + new + suffix を結合して復元
  • 矢印形式(共通部分なし): old => new の new 側
  • 上記以外(旧 3 トークン形式・閉じ括弧欠落・矢印欠落)は NoneErr で fail-closed

空白区切りへの fallback は残しません。波括弧のパースに失敗した行が fallback で
「それらしいパス」に化けると書式変化を検知できず gate が沈黙するためです
(既存方針「未知は明示的に reject」と同じ)。

波括弧の全 branch(中間 rename / 上位移動 {sub/ => } / 下位移動 { => sub/} /
ファイル名のみ / copy)をテーブル駆動で固定しました。

既知の未検証点

矢印形式(共通 prefix/suffix なし)は実出力を観測できていない推定です。doc に
その旨を明記してあります。推定が外れても未知形は NoneErr に倒れるため、
書式変化は沈黙せず push 停止として現れます。

回収経緯(レビュー時の参考)

本修正の実装は incident コミット(mxzwmsyp)に lib 抽出の gut-revert と混在しており、
rebase / duplicate では回収できませんでした。

検証

  • cargo test -p cli-push-runner 291 件 pass(rename 系 4 件を含む)
  • cargo clippy -p cli-push-runner --all-targets -- -D warnings
  • pnpm push の quality_gate 全グループ PASS(lint / test / build / rust-lint-test /
    lint:docs / test:e2e)
  • pre-push review: security-review APPROVE / simplicity-review APPROVE

後続

  • 2b: lib-scope-guard / lib-autonomy-policy 抽出 + cli-fix-push-gate(約 1,130 行)
  • 2c: pr-monitor.yml の Phase B fix job + autonomy-config.toml 有効化 + ADR-067(約 470 行)

マージ後、stale remote ブランチ feat/wp17-pr2a-policy-libs(incident 時の汚染版)の
削除をお願いします。

🤖 Generated with Claude Code

Summary by CodeRabbit

  • バグ修正

    • ファイルの rename/copy 情報を正しく解釈し、新しいパスを確実に復元できるよう改善しました。
    • 不正な形式や空のパスを明示的に拒否し、予期しない処理を防止します。
    • 複数の rename/copy パターンに対応し、関連する検証を強化しました。
  • ドキュメント

    • 開発計画を更新し、進捗、受け入れ基準、検証手順をより具体化しました。

aloekun and others added 2 commits August 3, 2026 13:18
ここまでの実行状況を master 版計画書へ反映し、WP-17 PR 2 の再分割を別セッションの
Opus がドキュメントのみで実施できる自己完結記述にする。

反映した実行状況:
- PR 1 (ADR-066 / #347): 完了。exe 単体 drill 充足済、観測中への遷移は 2c 後
- PR 2: 実装済・未 land。incident (gut-revert) と事前整備 2 本
  (ADR-068 / #348、ADR-069 / #349 = マージ済) の経緯を 3 行で要約
- Actions variable AUTONOMY_ENABLED 設定済みの事実と、2c マージで Phase B が
  即 live になる帰結 (マージ前の variable 削除推奨) を明記

再分割計画 (2a/2b/2c) の要点:
- 資産表: ローカル jj コミット 8 件を change_id で列挙 (rebase 耐性のため
  commit_id ではなく change_id を正とする旨を明記)、実在確認コマンド付き
- 2a: 計画書 (本コミット) + rename パーサ修正。mxzwmsyp は gut-revert 混入のため
  rebase 不可 — tests.rs は restore、diff.rs は #348 の pub(crate) 変更と重なるため
  hunk 単位の手適用、という回収手順を明記
- 2b: lib 抽出 + cli-fix-push-gate を同一 PR (ADR-044 充足 = incident の失敗の裏返し)。
  ADR-069 chain 宣言の本文を計画書に事前記載し、2b の diff に載せる手順と
  「初回 dogfood の実測結果を ADR-069 へ記帳」まで指示
- 2c: workflow + config 有効化 + ADR-067。マージ後の実走スモーク段 0-2 (ユーザー
  操作込み) を順序付きで記載
- jj 運用の注意: describe 適用先事故 (本セッションで 3 回発生) の予防として
  「編集前に必ず jj new」を明記。ADR-016 / ADR-028 / VSCode での draft 提示方法も記載

受け入れ基準を再分割構成に合わせて更新 (PR 1 / 2b drill = 充足済、2c = 実走スモーク)。

本コミットは未 push (master の local 子)。再分割 2a の先頭コミットとして次セッションが
流用する (計画書 § 2a 手順 1 に記載)。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`jj diff --summary` の rename / copy 行を誤ってパースし、**rename を含む PR が一律
push 不能** になっていた不具合を修正する。WP-17 PR 2a の push が exit 5 で停止して
顕在化した。

## 実測書式と旧実装のずれ

jj (0.42.0 / Windows) は共通 prefix / suffix を括り出した波括弧形式で出す:

    R src\{cli-autonomy-gate => lib-autonomy-policy}\src\decision.rs

旧実装は `<status> <old> <new>` の 3 トークン空白区切りを前提に rsplit_once(' ')
していたため、上の行から `lib-autonomy-policy}\src\decision.rs` という壊れたパスを
取り出していた。これが `--git` 側の `b/src/lib-autonomy-policy/src/decision.rs` と
一致せず、常に「未収録」と判定されていた。

判定は block 側に倒れるので fail-closed ではあるが、正当な push を止める誤検知。

## 根拠が fixture だった問題

3 トークン形式を前提にした根拠は、コード内コメントが引用していた lib_docs_policy の
`"R docs/a.md docs/b.md"` というテスト文字列だった。これは jj の出力を観測したもの
ではなく手で作った fixture で、実挙動の証拠になっていない。dev-conventions の
「外部 fixture 参照テストは値まで assert」が想定する失敗そのもの。本コミットの
テストは実測値を定数 OBSERVED_RENAME_SUMMARY として持ち、それを assert する。

## 修正方針

個別ケースを潰すのではなく、rename 行の入力空間を 1 バッチで固定する
(dev-conventions: パーサ修正は全 branch を一度に堅牢化):
- 波括弧形式: prefix + new + suffix を結合して復元
- 矢印形式 (共通部分なし): `old => new` の new 側
- 上記以外 (旧 3 トークン形式・閉じ括弧欠落・矢印欠落) は None → Err で fail-closed

空白区切りへの fallback は残さない。波括弧のパースに失敗した行が fallback で
「それらしいパス」に化けると書式変化を検知できず gate が沈黙するため
(既存方針「未知は明示的に reject」と同じ)。

波括弧の全 branch (中間 rename / 上位移動 `{sub/ => }` / 下位移動 `{ => sub/}` /
ファイル名のみ / copy) をテーブル駆動で固定した。

## 回収経緯

本修正の実装は 2026-08-02 の incident コミット (mxzwmsyp) に lib 抽出の gut-revert と
混在していたため、rebase / duplicate では回収できなかった。tests.rs は master 未変更の
ため restore、diff.rs は #348 の `parse_git_diff_paths` pub(crate) 化と衝突するため
`summary_line_new_path` の R/C 分岐と `rename_new_path` 追加だけを手で適用している
(計画書 § WP-17 2a 手順 2)。`summary_line_new_path` の doc は「末尾トークン」前提の
記述が本修正で stale になるため現状に合わせて更新した。

検証: cargo test -p cli-push-runner 291 件 pass、clippy -D warnings 緑。

Co-Authored-By: Claude Opus 5 (1M context) <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: b1da8228-d440-42dd-b89a-4a7c9128e0b9

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

WP-17の計画書をPR 1およびPR 2a/2b/2cの構成に更新した。R/C summaryのnew path復元を実測形式に対応させ、不正形式を拒否するテストを追加した。

Changes

WP-17計画とdiffパーサ

Layer / File(s) Summary
WP-17実施計画の再整理
docs/harness-improvement-plan.md
PR 1の完了内容を記録した。PR 2を2a/2b/2cへ分割し、各作業、検証手順、受け入れ基準を追加した。
rename/copy new path復元
src/cli-push-runner/src/stages/diff.rs, src/cli-push-runner/src/stages/diff/tests.rs
波括弧形式と矢印形式からnew pathを復元する処理へ変更した。未知status、空パス、不正形式を拒否する。複数のrename/copy形状と不正入力をテストする。

Estimated code review effort: 3 (Moderate) | ~20 minutes

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 タイトルは、rename summary の波括弧形式パース修正と WP-17 2a 計画更新という主要変更を明確に示しています。
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/wp17-r2a-docs-parser

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: 実行中(rust (ubuntu-latest): in_progress、rust (windows-latest): in_progress。いずれも未確定)
  • レビュー状況: CodeRabbit は処理中("Currently processing new changes..." — レビュー本体は未着)。人間レビュー・インラインコメントともに 0 件。
  • Verdict: user_decision(CI・CodeRabbit レビューともに結果未確定のため、現時点では approved / needs_fix を判定する根拠がない。陽性証拠が揃うまで判断を保留する)

Applicable Findings (Critical / High / Major)

該当なし(レビュー未着のため findings 自体が存在しない)

Applicable Findings (Medium 以下)

該当なし

Filtered (not applicable)

該当なし

次のアクション

  • CI(rust ubuntu/windows)と CodeRabbit レビューの完了を待ち、findings が出た時点で改めて本 workflow の分析を確認する。
  • 診断可能な範囲の diff 概要: 3 ファイル変更(+171/-48)。docs/harness-improvement-plan.md は WP-17 進捗更新と PR 2 再分割計画(2a/2b/2c)の追記(ドキュメントのみ)。src/cli-push-runner/src/stages/diff.rsjj diff --summary の rename/copy 行パースを、実測した波括弧形式(R src\{old => new}\file.rs)に対応させる修正(旧実装は 3 トークン空白区切り前提で壊れていた)。src/cli-push-runner/src/stages/diff/tests.rs は同修正に対応するテストの更新・追加。
  • CI/レビューが完了した時点で、本 PR がドキュメント計画に記載された「2a: rename パーサ修正」の切り出しとして意図どおりのスコープ(2 ファイルのみ)に収まっているかを人間が最終確認すること。

@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: 3

🧹 Nitpick comments (1)
docs/harness-improvement-plan.md (1)

188-189: 🩺 Stability & Availability | 🔵 Trivial

AUTONOMY_ENABLED の停止をマージ前の必須手順にしてください。

Line 188 は AUTONOMY_ENABLED=true のため、2c のマージ直後に Phase B が有効になると記載しています。現在の文面では、マージ前の variable 削除が任意です。構文検証と段 0 の確認が完了するまで、variable を削除または false にしてください。その後、管理されたスモーク段階で true に戻してください。

🤖 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 188 - 189, Update the
“マージ前の確認” steps so disabling the AUTONOMY_ENABLED Actions variable by deleting
it or setting it to false is mandatory before merge, and keep it disabled
through syntax validation and smoke stage 0. State that it may be restored to
true only during the controlled smoke rollout.
🤖 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 162-164: 「tests.rs」を復元する前に、master と mxzwmsyp
の対象コミットが存在し、対象ファイルに差異がないことを「jj diff --from master --to mxzwmsyp --
src/cli-push-runner/src/stages/diff/tests.rs」で確認する手順を追加してください。その確認後にのみ、既存の「jj
restore --from mxzwmsyp」を実行する流れにしてください。
- Around line 190-193: Update the “マージ後の実走スモーク” steps to state that
workflow_dispatch receives the PR head branch via the target PR/headBranch
contract, not the default ref. Document the pr_number-to-target-PR and
headBranch inspection behavior, and clarify that the non-claude/ test must
observe the FIX_PUSH_DENY message; relying on default ref inspection does not
satisfy the smoke test.

In `@src/cli-push-runner/src/stages/diff.rs`:
- Around line 199-206: In summary_line_new_path, stop trimming rest before
parsing so valid paths retain leading and trailing spaces and remain consistent
with diff --git header comparisons. Preserve the existing status handling and
path separator normalization, and add regression tests covering leading and
trailing spaces for M, R, and C paths.

---

Nitpick comments:
In `@docs/harness-improvement-plan.md`:
- Around line 188-189: Update the “マージ前の確認” steps so disabling the
AUTONOMY_ENABLED Actions variable by deleting it or setting it to false is
mandatory before merge, and keep it disabled through syntax validation and smoke
stage 0. State that it may be restored to true only during the controlled smoke
rollout.
🪄 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: 767d137c-707d-40a3-bdc4-84a28350f86b

📥 Commits

Reviewing files that changed from the base of the PR and between 3af6556 and 434ced5.

📒 Files selected for processing (3)
  • docs/harness-improvement-plan.md
  • src/cli-push-runner/src/stages/diff.rs
  • src/cli-push-runner/src/stages/diff/tests.rs

Comment on lines +162 to +164
2. **パーサ修正の回収**: `mxzwmsyp` は rename パーサ修正(`src/cli-push-runner/src/stages/diff.rs` + `src/cli-push-runner/src/stages/diff/tests.rs` の 2 ファイル)と incident の gut-revert(lib 削除等)が混在しており、**rebase / duplicate では回収できない**。次の手順で 2 ファイル分だけ取り出す:
- `tests.rs` は #348 以降 master で未変更のため丸ごと取得可: `jj restore --from mxzwmsyp -- src/cli-push-runner/src/stages/diff/tests.rs`
- `diff.rs` は **restore 不可**(#348 が `parse_git_diff_paths` の `pub(crate)` 化を入れており、mxzwmsyp 版で上書きすると `post_takt_regate.rs` が compile error になる)。`jj diff -r mxzwmsyp -- src/cli-push-runner/src/stages/diff.rs` で hunk を確認し、`summary_line_new_path` の R/C 分岐変更と `rename_new_path` 関数追加、関連 doc 更新だけを現ファイルへ手で適用する(`pub(crate)` 行とは重ならない)。

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/sh
set -eu

for file in \
  src/cli-push-runner/src/stages/diff/tests.rs \
  src/cli-push-runner/src/stages/diff.rs
do
  printf '\n=== %s: master -> mxzwmsyp ===\n' "$file"
  jj diff --from master --to mxzwmsyp -- "$file"
done

Repository: aloekun/claude-code-hook-test

Length of output: 281


🏁 Script executed:

#!/bin/sh
set -eu

printf 'Repository files:\n'
git ls-files | rg '(^docs/harness-improvement-plan\.md$|src/cli-push-runner/src/stages/diff\.(rs|tests|rs)$)' || true

printf '\nRelevant plan lines:\n'
sed -n '152,170p' docs/harness-improvement-plan.md

printf '\nGit refs/names containing target files and comments about `#348` / master / mxzwmsyp:\n'
rg -n "mxzwmsyp|`#348`|master|rename/test|pub\\(crate\\)|parse_git_diff_paths|summary_line_new_path|rename_new_path" docs src || true

Repository: aloekun/claude-code-hook-test

Length of output: 50386


🏁 Script executed:

#!/bin/sh
set -eu

printf 'Git refs:\n'
git show-ref | rg 'refs/(heads|tags|remotes|jj)(/|@\b)|refs/remotes/origin|heads/master|refs/remotes/origin/master' || true

printf '\nRepo tree around referenced file:\n'
find src/cli-push-runner/src/stages -maxdepth 2 -type f -print | sort

printf '\nPlan marker lines:\n'
sed -n '155,168p' docs/harness-improvement-plan.md

Repository: aloekun/claude-code-hook-test

Length of output: 3101


復元前に tests.rs の復元前提を明記してください。

jj restore は作業ツリーの tests.rs を上書きするため、master / mxzwmsyp の対象コミットが存在して差異がない前提を jj diff --from master --to mxzwmsyp -- src/cli-push-runner/src/stages/diff/tests.rs で確認する手順を追加してください。

🤖 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 162 - 164,
「tests.rs」を復元する前に、master と mxzwmsyp の対象コミットが存在し、対象ファイルに差異がないことを「jj diff --from
master --to mxzwmsyp --
src/cli-push-runner/src/stages/diff/tests.rs」で確認する手順を追加してください。その確認後にのみ、既存の「jj
restore --from mxzwmsyp」を実行する流れにしてください。

Comment thread docs/harness-improvement-plan.md Outdated
Comment on lines +190 to +193
6. **マージ後の実走スモーク**(ユーザー操作込み。順序厳守):
- 段 0: repository ruleset で `claude/` 以外への `GITHUB_TOKEN` push を deny(5 層目の防波堤。ユーザー、GitHub UI)。
- 段 1: variable `AUTONOMY_ENABLED` = `true` を設定 → 適当な非 `claude/` PR に対し workflow_dispatch → fix job が `[FIX_PUSH_DENY] branch=... claude/ prefix ではない` で degrade することを確認。
- 段 2: `claude/` prefix のテストブランチで docs 指摘のある PR を作り、allow 経路(gate exit 0 → workflow step が push)と deny 経路(variable 削除で次 run から job skip)を観測。

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/sh
set -eu

rg -n -C 8 \
  'workflow_dispatch|pull_request|head|branch|FIX_PUSH_DENY|Gate fix push' \
  .github/workflows/pr-monitor.yml \
  src/cli-fix-push-gate

Repository: aloekun/claude-code-hook-test

Length of output: 15270


🏁 Script executed:

#!/bin/sh
set -eu

printf 'Tracked files matching harness/fix/gate/pr-monitor:\n'
git ls-files | rg 'harness|fix|gate|pr-monitor|claude-code-hook|docs/cli|docs/harness' || true

printf '\nCandidate workflow files:\n'
fd -a '\.ya?ml$' .github/workflows docs src . 2>/dev/null | sed 's#^\./##' | head -200

printf '\nKey occurrences:\n'
rg -n -C 6 \
  'workflow_dispatch|FIX_PUSH_DENY|Gate fix push|fix push|AUTONOMY|claude/|GITHUB_TOKEN push|pr_number|head_branch|base_ref|pull_request' \
  .github docs src 2>/dev/null || true

Repository: aloekun/claude-code-hook-test

Length of output: 50386


🏁 Script executed:

#!/bin/sh
set -eu

printf 'docs/harness-improvement-plan.md relevant section:\n'
sed -n '160,220p' docs/harness-improvement-plan.md

printf '\nExact occurrences in docs:\n'
rg -n -C 6 'FIX_PUSH_DENY|workflow_dispatch|AUTONOMY_ENABLED|FIX_PUSH_DENY|push deny|GITHUB_TOKEN push' docs || true

printf '\nExact occurrences in workflows/src without huge source dump:\n'
rg -n -C 6 'FIX_PUSH_DENY|AUTONOMY_ENABLED|workflow_dispatch|headBranch|headRef|prefix\.|GITHUB_TOKEN push|fix push' .github src docs 2>/dev/null \
  --glob '!src/**/main.rs' --glob '!**/*.rs' | head -n 300 || true

printf '\nAll occurrences in code/docs under tracked files (less output):\n'
python3 - <<'PY'
import subprocess, sys
p = subprocess.run(['git','ls-files','docs/harness-improvement-plan.md','.','.github','src'], capture_output=True, text=True)
files = [f for f in p.stdout.splitlines() if f]
terms = ['FIX_PUSH_DENY','AUTONOMY_ENABLED','workflow_dispatch','head_ref','headRef','headBranch','GITHUB_TOKEN push','push deny']
for f in files:
    if f.endswith(('.py','.js','.ts','.yml','.yaml','.toml','.md')):
        try:
            txt = open(f, encoding='utf-8', errors='replace').read()
        except Exception:
            continue
        for t in terms:
            if t in txt:
                print(f'\n--- {f}: term {t} ---')
                for line in txt.splitlines():
                    if t in line:
                        print(line.strip())
PY

Repository: aloekun/claude-code-hook-test

Length of output: 50387


workflow_dispatch は PR head branch を受け取ると記載してください。

段 1 は「非 claude/ PR」を対象に FIX_PUSH_DENY branch=... claude/ prefix ではない を観測することですが、workflow_dispatch 入力には pr_number はあります。workflow が対象 PR と headBranch の契約で検査を行い、既定 ref 検査では smoke が成功しないことを文書に明示してください。

🤖 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 190 - 193, Update the
“マージ後の実走スモーク” steps to state that workflow_dispatch receives the PR head branch
via the target PR/headBranch contract, not the default ref. Document the
pr_number-to-target-PR and headBranch inspection behavior, and clarify that the
non-claude/ test must observe the FIX_PUSH_DENY message; relying on default ref
inspection does not satisfy the smoke test.

Comment on lines 199 to 206
fn summary_line_new_path(status: &str, rest: &str) -> Option<String> {
let trimmed = rest.trim();
let path = match status {
"M" | "A" | "D" => trimmed,
"R" | "C" => trimmed.rsplit_once(' ').map(|(_, new)| new)?,
"M" | "A" | "D" => trimmed.to_string(),
"R" | "C" => rename_new_path(trimmed)?,
_ => return None,
};
(!path.is_empty()).then(|| path.replace('\\', "/"))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

In Jujutsu jj version 0.42.0, how does jj diff --summary render file paths whose names have leading or trailing spaces on Windows and Unix?

💡 Result:

In Jujutsu version 0.42.0, the jj diff --summary command renders file paths by using the platform-specific path formatting logic [1]. It does not apply special quoting or escaping to paths that contain leading or trailing spaces, meaning these characters are typically output as they exist in the repository's file system structure [2]. On both Windows and Unix-based systems, jj uses its internal path converter, which generally preserves the literal characters of the file path [1]. Because jj diff --summary presents output in a simple format (typically two status letters followed by a space and the file path, e.g., "M file name "), paths with leading or trailing spaces are rendered literally, which can create ambiguity when parsing the output programmatically [2]. Users or tools attempting to parse the output of jj diff --summary must account for the fact that the path is not encapsulated in quotes, making it difficult to distinguish trailing spaces in a filename from the whitespace separator used by the CLI [2]. For robust integration, developers are often advised to use templates (via the -T option) if they require a specific, unambiguous output format [3][4].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate and inspect the relevant source section and nearby tests/usages without running repository code.
printf 'Files:\n'
fd -a 'diff\.rs$' . || true

printf '\nOutline diff.rs:\n'
ast-grep outline src/cli-push-runner/src/stages/diff.rs --view compact || true

printf '\nRelevant diff.rs lines 180-212 and 230-250:\n'
sed -n '180,212p;230,250p' src/cli-push-runner/src/stages/diff.rs | cat -n

printf '\nSearch summary_line_new_path/rename_new_path usages/tests:\n'
rg -n "summary_line_new_path|rename_new_path| summary | trim\\(\\)|\\bM\\b|\\bR\\b|\\bC\\b" src/cli-push-runner/src/stages/diff.rs

Repository: aloekun/claude-code-hook-test

Length of output: 4164


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'Tests around parser in diff.rs):\n'
sed -n '250,330p' src/cli-push-runner/src/stages/diff.rs | cat -n

printf '\nRust behavior for trim on path-like strings and split_once \" => \":\n'
rg -n "jj diff --summary|rename_new_path|summary_line_new_path|parse_summary_paths" src/cli-push-runner/src/stages/diff.rs

Repository: aloekun/claude-code-hook-test

Length of output: 4690


🌐 Web query:

Jujutsu jj 0.42.0 docs summary diff summary status output format status M R C path

💡 Result:

In Jujutsu (jj) version 0.42.0, the jj status command displays a high-level summary of the repository's state, including changes in the working copy compared to its merged parents, conflicts, and conflicted bookmarks [1][2]. The output format for file changes in the working copy uses single-character status codes followed by the file path [3]. Based on the codebase and test snapshots for version 0.42.0, the common status indicators include [3]: M: Modified. The file has been changed [3]. A: Added. The file is new in the working copy [3]. D: Deleted. The file has been removed [3]. C: Copied. The file was copied [3]. R: Renamed. The file was renamed [3]. For copied (C) and renamed (R) files, the output format typically uses curly braces to indicate the transformation, such as {source => target} [3]. Additional details regarding the status output include: - Path Filtering: The command supports optional [FILESETS] to restrict the status display to specific paths [1][2]. - Untracked Files: As of version 0.42.0, jj status collapses fully untracked directories into a single line to keep the output clean [4][5]. - Implementation: The status indicators are derived from internal logic (e.g., TreeDiffEntry status_char), ensuring consistent mapping across the tool [4][5]. Note that for detailed diffs of specific revisions, users are directed to use jj diff --summary -r [revision] [1][2].

Citations:


🌐 Web query:

github jj-vcs jj "jj diff --summary" output format " R" rename source target

💡 Result:

The jj diff --summary output format for renames is designed to be compact and often uses brace expansion to represent changes in directory or file structures [1]. When a file or directory is renamed, Jujutsu (jj) typically reports the change with an 'R' status prefix followed by the path information [1]. The format frequently appears in the style: R {old_path => new_path} or, when the rename shares a common path prefix: R path/to/{old_name => new_name} Key characteristics of this format include: - Status Indicator: Lines representing renames begin with 'R ' [2][3]. - Brace Expansion: Jujutsu uses the {source => target} syntax to indicate the transformation [1]. - Path Handling: Parsers must be prepared to handle these brace-expanded strings to accurately extract the original and new paths [2][4]. Note that older versions or specific environments may produce this output with platform-native path separators (e.g., backslashes on Windows), which some tools normalize to forward slashes for cross-platform consistency [5]. Because this output is meant for human readability, automated tools often require custom parsing logic to strip the braces and split the path at the => delimiter to programmatically identify the source and target locations [2][3][4].

Citations:


🌐 Web query:

github jj-vcs jj "diff --summar" " M" "file paths" trim

💡 Result:

In the Jujutsu (jj) version control system, the command jj diff --summary provides a concise overview of changes, listing modified, added, or deleted files [1][2]. There is no native flag such as --trim or similar options to truncate or adjust the display of file paths in jj diff --summary [1][3]. The jj diff command accepts optional file paths (filesets) as arguments to filter which files are included in the output, but these act as a filter rather than a formatting control for the output path string [1][3]. If you require specific output formatting, such as truncating paths or changing how file names are displayed, jj allows you to define custom diff formats or use external tools [4]. You can configure ui.diff-formatter to use an external command, or specify an external tool with jj diff --tool <name>, which can then be configured in your jj settings to process the diff output as needed [4]. For simple path-only output, you can use the --name-only flag instead of --summary, which lists only the file paths that have changed [1][3]. If you need to perform additional manipulation on these paths, you can pipe the output of jj diff --name-only into standard command-line utilities like cut, sed, or awk.

Citations:


🌐 Web query:

github jj-vcs jj "diff --summary" " M " "trimmed" status path

💡 Result:

In Jujutsu (jj), the jj diff --summary command provides a concise list of changes for each path, indicating whether a file was modified (M), added (A), deleted (D), renamed (R), or copied (C) [1][2][3]. Output format: The command outputs one line per file [3]. Each line typically begins with a status character followed by a space and the file path [4][3]. Renamed and copied files include the source and destination paths separated by " -> " [3]. Example output includes [3]: M path/to/file.rs A new_file.rs D removed.rs R old/path.rs -> new/path.rs C from.rs -> to.rs Key details: - Status abbreviations: M (Modified), A (Added), D (Deleted), R (Renamed), C (Copied) [3]. - Whitespace handling: When parsing this output in scripts, it is common to use trim() or trim_end() on each line to handle potential trailing whitespace before splitting the line by the first space [5][6][3]. - Distinguishing from other flags: Note that the --types option also affects summary output by showing two-letter codes representing file types (e.g., F for file, L for symlink, C for conflict) instead of the action-based status (M, A, D) [2][7]. This summary output is frequently used in tooling to bridge Jujutsu with other systems, such as wrapping it to emulate git status or for automated analysis [5][4][6][3].

Citations:


🌐 Web query:

github jj-vcs jj diff summary output test M new path space

💡 Result:

The jj diff command in the Jujutsu VCS supports a --summary flag that displays a high-level overview of changes for each path, specifically indicating whether a file was modified (M), added (A), or deleted (D) [1][2][3]. When you run jj diff --summary, the output typically lists these indicators followed by the file path [4]. If a file path contains spaces, Jujutsu correctly preserves the path in the output, which is generally presented as a simple list of status indicators and paths [4][5]. For users who need to programmatically parse this output, the jj diff command's summary format is often consistent, and some tools leverage it by parsing these lines [5]. If you need to handle paths with spaces programmatically, you may find that standard line-based parsing remains effective because the path is typically the final element of each summary line [5]. Key points regarding the diff summary output: - Status indicators: M (Modified), A (Added), D (Deleted) [1][3]. - Command usage: Use jj diff --summary or jj diff -s to enable this view [1][2][6]. - Path handling: Paths, including those with spaces, are displayed in the output [4]. - Configuration: You can set a default diff formatter in your configuration file using the [ui] diff-formatter = ":summary" setting [7]. For more complex reporting or to change the output structure, you can also use the --template option, which allows you to define a custom format for each diff entry using available keywords [1][8].

Citations:


パスから空白を除去しないでください。

trim() は先頭または末尾の空白を持つ有効なパスを変更します。これは jj diff --summary → 解析パスと diff --git のヘッダ比較の間に食い違いを生むため、正しい diff でも coverage gate が停止します。MRC の先頭・末尾空白を含むパスの回帰テストも追加してください。

🤖 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-push-runner/src/stages/diff.rs` around lines 199 - 206, In
summary_line_new_path, stop trimming rest before parsing so valid paths retain
leading and trailing spaces and remain consistent with diff --git header
comparisons. Preserve the existing status handling and path separator
normalization, and add regression tests covering leading and trailing spaces for
M, R, and C paths.

@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 (1m20s) / rust (windows-latest) pass (2m32s) / CodeRabbit check pass(レビュー完了)。analyze(本 job 自身)は pending(自己参照のため正常)
  • レビュー状況: CodeRabbit が本 review でレビュー本体を投稿(actionable comments 3 件 + nitpick 1 件)。人間レビューは 0 件、他 bot レビューなし
  • Verdict: user_decision(全 applicable findings が Minor/Trivial であり Critical/High/Major は無し)

Applicable Findings (Critical / High / Major)

該当なし

Applicable Findings (Medium 以下)

# File (Line) Reviewer Issue Recommended Action
1 src/cli-push-runner/src/stages/diff.rs:199-206 CodeRabbit summary_line_new_pathrest.trim() でパス前後の空白を除去しており、先頭/末尾に空白を含む正当なパスが diff --git ヘッダ側の比較値と食い違い得る(coverage gate 誤検知の可能性)。Minor trim を外し、M/R/C それぞれで前後空白を含むパスの回帰テストを追加するか検討
2 docs/harness-improvement-plan.md:164 CodeRabbit 2a 手順内「tests.rs#348 以降 master で未変更のため丸ごと取得可」の前提を jj restore 実行前に jj diff --from master --to mxzwmsyp -- .../tests.rs で確認する手順が明記されていない。Minor 復元前の差分確認コマンドを手順に追記
3 docs/harness-improvement-plan.md:193 CodeRabbit 2c 節「マージ後の実走スモーク」段1の記述が、workflow_dispatch が対象 PR の headBranch 契約経由でブランチを受け取る点(既定 ref 検査では smoke が成立しない点)を明記していない。Minor pr_number → 対象PR → headBranch 検査である旨を追記
4 docs/harness-improvement-plan.md:188-189 CodeRabbit 2c「マージ前の確認」で AUTONOMY_ENABLED の停止が「意図的に段階を踏むなら」という任意表現になっており、必須手順として明記されていない。Trivial 構文検証・段0確認完了までの variable 無効化を必須手順として明文化(対象は将来PR 2cのため本PRのブロッカーではない)

Filtered (not applicable)

該当なし

次のアクション

PR #350 の CodeRabbit 指摘 3 件への対応。

## 1. rename_new_path の矢印分岐から冗長な trim を削除

指摘: 「パスから空白を除去しないでください」(diff.rs、Minor)。

矢印分岐だけが `new.trim()` していて波括弧分岐 (`format!` で結合、trim なし) と
非対称だった。呼び出し元 `summary_line_new_path` が既に `rest.trim()` 済みの文字列を
渡す唯一の呼び手なので、この trim は冗長でもある。

**これはバグ修正ではなく対称性の回復である**: 現実的な入力では両者の結果は一致し、
削除による挙動変化は観測できない (だからこそ安全に削除できる)。狙いは「同じパスが
分岐によって違う結果になり得る」状態を残さないこと。

なお post-pr-review の分析は本指摘を false positive と判定していたが、根拠が誤り
だった (指摘位置を `path.replace('\', "/")` と読み「バックスラッシュ変換であって
空白除去ではない」とした)。CodeRabbit は複数行コメントを範囲末尾に anchor するため
実際の対象は関数全体で、trim は確かに存在した。結論 (非ブロッキング) は一致するが
理由が違うので、指摘の芯を採用して直す。

テストには空白を含むパスのケースを 2 件追加した (波括弧 / 矢印の両分岐)。区切りの
`" => "` と紛れる位置に空白があっても内部の空白が保持され、両分岐が同じ結果を返す
ことを固定する。

## 2. tests.rs restore の前提を明記 (docs)

指摘: 「復元前に tests.rs の復元前提を明記してください」(計画書 L164、Minor)。

`jj restore` で丸ごと上書きしてよいのは「master 側が未変更」の間だけ。前提の確認
コマンドと、崩れていた場合の切り替え先 (diff.rs と同じ hunk 単位の手適用) を書いた。
前提を確認せず restore すると master 側の変更を無言で巻き戻すため、確認手順まで含めて
残す。

## 3. workflow_dispatch の ref 選択を明記 + スモーク段 0.5 を追加 (docs)

指摘: 「workflow_dispatch は PR head branch を受け取ると記載してください」
(計画書 L193、Minor)。

dispatch は起動時に ref を選べ、選んだ ref 版の workflow 定義で走る。これは 2c の
実走スモークの前提として重要で、計画書が「マージ後の実走スモーク」としか書いて
いなかったのは記述不足だった。fix job はマージ前に 2c ブランチ ref に対して実走できる。

これを踏まえ段 0.5 (マージ前 dispatch) を追加した。gate と config は master ref から
調達される (ADR-066 決定 3) ため、マージ前は config が `enabled = false` のままで
fix job は config 層で停止する = **deny 経路 (kill-switch が効く側) をマージ前に検証でき、
allow 経路だけがマージ後に残る**。`AUTONOMY_ENABLED` が既に true で「2c マージ = 即 live」
の一発勝負になる状況に対する段階化として意味がある。

手順 4 (マージ前に variable を削除して段階を踏む案) は段 0.5 が variable 層を通す必要が
あるため順序が矛盾していた。削除するとしても段 0.5 の後、と順序を明記して整合させた。

検証: cargo test -p cli-push-runner 291 件 pass、clippy -D warnings 緑。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@aloekun
aloekun merged commit 91f09aa into master Aug 3, 2026
3 checks passed
@aloekun
aloekun deleted the feat/wp17-r2a-docs-parser branch August 3, 2026 07:30
aloekun added a commit that referenced this pull request Aug 3, 2026
* refactor(lib-scope-guard): ADR-054 scope 判定コアを lib へ抽出 (WP-17 PR 2)

Phase B (CI 側の無人 fix push) が同じ scope 検証を必要とするため、cli-pr-monitor に
閉じていた判定コアを lib 化する。挙動は不変。

抽出根拠は ADR-044 層 1 の「3+ crate 重複」ではなく **判定の同一性**。同一 ADR
(ADR-054) の防御がローカル経路と CI 経路に分岐すると、片方だけ緩んだ時点で injection
防御が無効化される。重複数ではなくこの drift リスクを根拠に、2 呼び手の時点で抽出する
(lib-docs-policy が ADR-035 の path 基準を単一実装へ集約したのと同じ理由)。

lib に置いたもの (純粋な文字列処理のみ):
- normalize_path / allowlist_from_paths / parse_changed_files / find_out_of_scope
- ALWAYS_ALLOWED (.takt/review-diff.txt)

呼び出し側に残したもの: diff の取得 (jj / git)、mode 判定 (enforce/observe)、
kill-switch、ログ出力。lib は「変更ファイル集合が許可集合に収まるか」だけを答える。

allowlist の入力を Finding 型ではなくパス文字列の iterator にしたのは、findings の
表現が経路ごとに異なるため (ローカル = lib_report_formatter::Finding、CI = JSON)。
これにより lib は依存ゼロを保てる。

テストも移設し、lib 側に 11 件 (境界値の網羅: 空 summary / 空白行 / tab 区切り /
空白を含むパス / 空 allowlist)。cli-pr-monitor 側には Finding→パスの glue と
mode/統合テストのみ残す。tab 区切り拒否のテストを新規追加した — git diff --name-status
は tab 区切りで、CI 経路が正規化を怠ると fail-closed に倒れることを固定するため。

検証: cargo clippy -D warnings 緑、cli-pr-monitor 260 件 + lib-scope-guard 11 件 pass。

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

* refactor(lib-autonomy-policy): kill-switch 判定コアを lib へ抽出 (WP-17 PR 2a)

後続 PR (WP-17 PR 2b) の fix push 直前ゲート `cli-fix-push-gate` が kill-switch を
含む全軸を 1 回で評価できるようにするため、cli-autonomy-gate 内の decision.rs /
sources.rs を lib へ移す。挙動は不変 (テスト 21 件は PR 1 と同数を維持)。

**本 PR の時点で 2 つ目の呼び手はまだ存在しない。** ADR-044 層 1 は「2 つ目の使用例が
出た時点で extract」と定めるが、後から昇格すると kill-switch 判定が一時的に 2 箇所へ
分岐する期間ができる。その期間を作らないための**明示的な前倒し判断**であり、
層 1 の厳密な充足ではない。この位置づけは各 module doc にも記載した
(pre-push review の simplicity facet が「存在しない 2nd caller を根拠にしている」と
指摘し、未来形へ言い換える fix が入った。指摘は妥当で、4 箇所すべてが修正済み)。

exe 連鎖 (`cli-autonomy-gate && cli-fix-push-gate`) を採らなかった理由:
workflow 側で `&&` を書き忘れると kill-switch を通り越して fix push が走る。
「1 つでも欠けたら停止」の fail-closed 合成が呼び手のミスで壊れる経路を残さないため、
ライブラリ共有にして fix push ゲートが構造的に kill-switch を含む形にする。

cli-autonomy-gate は CLI 面 (引数解析・loud 出力・exit コード・telemetry) だけを持つ
薄い exe になり、汎用の kill-switch 判定 (pnpm autonomy-status / 単体 drill) を担う。

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

* feat(cli-fix-push-gate): Phase B の fix push 直前ゲートを追加 (WP-17 PR 2)

ADR-052 自動実行可クラスの 4 軸を 1 回の呼び出しで AND 評価する決定論ゲート。
GitHub Actions の Phase B job が push 直前に呼び、非ゼロなら push を止めて
Phase A 相当 (分析コメントのみ) へ degrade する。

4 軸と根拠:
- kill-switch (ADR-066 / ADR-052 原則 5): --config + env AUTONOMY_ENABLED
- target 軸 (ADR-052 原則 2): --branch が claude/ prefix であること
- 内容軸 (ADR-052 原則 2 / ADR-035): fix diff が docs-only であること
- scope (ADR-054): 変更ファイルが findings 由来 allowlist に収まること

各軸の基準は既存の単一実装 (lib-autonomy-policy / lib-docs-policy / lib-scope-guard)
を借り、本 crate 固有のロジックは AND 合成と判定順序だけに留めた。基準の再実装は
ADR-035 / ADR-054 が防ごうとした drift の再生産にあたるため。

判定順は kill-switch → ブランチ → 空 diff → 内容軸 → scope。空 diff を内容軸より先に
見るのは、is_docs_only_summary が空入力へ false を返す仕様で、そのままだと「変更なし」が
「docs-only ではない」と誤報告されるため (drill 6 で実確認)。

findings の出所に関する契約を inputs.rs の doc に明記した: findings は fix を書いた
エージェント自身ではなく、先行する読み取り専用の分析 step の出力でなければならない。
同一エージェントが両方を出すと scope guard が自己申告の追認になり ADR-054 の防御が
成立しない (ローカル経路で review facet と fix step が別エージェントなのと同じ分離)。

loud 出力は deny 理由 1 つに絞らず 4 軸すべての状態を出す。drill 3 (非 claude ブランチ)
では autonomy=allowed branch=not-isolated content=docs-only scope=in-scope と出て、
ブランチだけが原因と 1 行で読める。

引数は 4 つとも必須。省略で軸が無検査になる fail-open を作らないため、どれか 1 つでも
落とすと exit 2 になることをテストで固定した。

テスト 22 件 + 実 exe drill 7 シナリオ (全軸 OK → exit 0、kill-switch / 非 claude
ブランチ / scope violation / code 変更 / 空 diff / rename fail-closed → 全て exit 1)。

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

* docs(wp17): lib module doc を呼び手実在の現実に合わせる + 2b の chain 宣言 (WP-17 2b)

先行 3 コミット (lib-scope-guard / lib-autonomy-policy 抽出、cli-fix-push-gate 追加) は
incident 前に「抽出だけの PR」として書かれており、module doc が呼び手を「計画中・本 diff
の時点では未実装」と説明していた。本 PR は抽出と最初の呼び手を同一 PR に入れるため
(ADR-069 § 決定 3-1)、その前提が成立しない。文言を現実に合わせる。

## 時制修正 (4 ファイル)

- `lib-autonomy-policy/src/lib.rs`: 呼び手 2 件 (`cli-autonomy-gate` / `cli-fix-push-gate`)
  を実在として記載。「前倒しで lib 化した (ADR-044 層 1 の厳密な充足ではない)」という
  但し書きは、2 呼び手が同一 PR に揃った今は不要なので落とし、層 1 充足と書く。
- `lib-scope-guard/src/lib.rs`: 同上。「CI 側の呼び手はまだ実装されていない」を削除。
  lib 化の根拠 (重複数ではなく判定の同一性) は ADR-054 の防御に関わるので残す。
- `cli-autonomy-gate/src/main.rs`: `cli-fix-push-gate` を実在として参照。
- `cli-pr-monitor/src/stages/scope_guard.rs`: 「将来 CI 経路が追加された際に」を現在形へ。

## chain 宣言の精緻化 (ADR-069 初回 dogfood)

計画書の「2b の chain 宣言」を、ADR-069 § 決定 1 の 3 要件に照らして具体化した:

- **未消費は 1 つだけ**であることを明示。`lib-scope-guard` / `lib-autonomy-policy` は
  どちらも呼び手 2 件が本 PR の diff 内に揃っており missing-consumer ではない。
  宣言が要るのは `cli-fix-push-gate` の workflow 呼び手のみ。
- **名前一致要件**を満たすため、2c の実体 (未 land コミット lqxzpvuw) と照合して step 名を
  実名 `Gate fix push (deterministic, 4-axis AND)` に修正した (旧記載 `Gate fix push` は
  前方一致にすぎず、ADR-069 の「矛盾する宣言は降格根拠にならない」に触れうる)。
  exe パスと 4 引数も実体と突き合わせ済み。

宣言付き先頭 PR が missing-consumer で REJECT されないことが ADR-069 試験運用の
decision trigger (a) の初回実測になる。結果は ADR-069 の判断基準へ記帳する。

## 計画書の状態行

2a を完了 (PR #350) に、2b を実施中に更新。この更新自体が計画書を本 PR の diff に載せ、
ADR-069 § 決定 1「置き場所 = diff 内の計画文書のみ」を満たす手段でもある。

検証: cargo test --workspace 1945 件 pass、clippy --workspace --all-targets -D warnings 緑、
pnpm lint:docs / lint:md 0 error。

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

* fix(review): apply CodeRabbit fixes for #351

Resolved findings:
- [Minor] docs/harness-improvement-plan.md:185 2c の workflow に一致する chain 宣言に更新してください。

* docs(wp17): chain 宣言の検証状態を diff 内/外で分けて明記 (CodeRabbit #351)

CodeRabbit 指摘「2c の workflow に一致する chain 宣言に更新してください」への対応。

## 経緯 — takt fix が真の記述を偽に書き換えた

指摘を受けた post-pr-review の fix step は、宣言の「2c の実体で step 名・パス・引数を
照合済み」を「実装済みの実体と照合済みではない」へ書き換えて auto-push した。これは
**事実に反する**。2c の実装はローカルの未 land コミットとして存在し、step 名
`Gate fix push (deterministic, 4-axis AND)`・exe パス・4 引数はいずれも実体と照合済み
である (照合は 2b 着手時に実施)。

一方 CodeRabbit の懸念自体は正当だった: 本 PR の diff だけを見るレビュアーには、その
照合の主張を検証する手段がない。fix 後の記述は「偽だが検証可能」、修正前の記述は
「真だが検証不能」で、どちらも宣言として不十分だった。

## 修正内容

主張を検証可能性で 2 つに分ける:

- **diff 内で照合できるもの**: 引数 4 種と exe 名 (`main.rs` の `parse_args` / `USAGE`)。
  ADR-069 § 決定 1 の名前一致要件は、この部分で本 diff 内に閉じて満たされる。
- **diff 外の主張**: step 名と exe パス。2c の未 land 実装と照合済みであることを述べつつ、
  **本 PR の diff だけでは検証できない主張である**と明示し、名前一致の最終確認は 2c の
  diff レビューで行うと書く。

真である事実を落とさず、レビュアーが何を確認できて何を確認できないかを判別できる形に
した。宣言の強度は落ちない — ADR-069 が要求する名前一致は diff 内で閉じている。

なお本件は「fix step の出力を実測検証する」(#309 / ADR-068) が docs 領域でも必要である
ことの実例になった。WP-17 完了後の feedback 採否で扱う。

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

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
aloekun added a commit that referenced this pull request Aug 4, 2026
WP-17 (イベント駆動バックボーン完成) で唯一残っていた受け入れ基準 — 実走スモーク段 2
= Phase B allow 経路の完走 — が 2026-08-04 に充足したことを記帳し、#350#357 の
post-merge feedback 採否とセッション発案のハーネス改善 1 件を todo へ確定する。
コード変更は含まない。

## 段 2 の結果 (ADR-067 § 検証記録)

`workflow_dispatch` を 4 回実行し、4 回目で 13 step 完走に至った。

| 回 | 検出した欠陥 | 対処 |
|---|---|---|
| 1 | `gh api` は `--slurp` と `--jq` を併用できない | PR #356 |
| 2 | findings agent の出力がコードフェンスで囲まれ `jq` が失敗 | PR #357 |
| 3 | `Apply fixes` が findings ファイルを読めず空 diff | PR #358 |
| 4 | なし (完走) | — |

4 回目の実測: findings 3 件 / `Apply fixes` は `permission_denials_count=0`・`num_turns=6` /
`Gate fix push` が `[FIX_PUSH_ALLOW] autonomy=allowed branch=isolated content=docs-only
scope=in-scope(1 files)` / `Push fix` が `ee9557a..86f424c` を push / `Report degrade to
Phase A` は skip (= degrade しなかった証拠)。

無人 fix が書いた内容も実測検証し、仕込んだ不整合 3 点を過不足なく修正・範囲外の編集
ゼロ (1 ファイル / 3 insertions / 3 deletions) であることを確認した。

`AUTONOMY_ENABLED` を削除した状態での dispatch では fix job 自体が skip され、ADR-066 の
「欠損 → 安全状態」が実 Actions ランタイムで機能することも確認した。

## ADR-067 § 残課題 1 の方針を訂正

同節に書いていた修正方針「`allowedTools` を `Read(findings-input/**)` にする」は**誤り**
だった。同ディレクトリには未要約の raw な CodeRabbit テキスト (`comments.json` /
`reviews.json`) があり、glob を与えると write 権限を持つ fix agent がそれを直接読める。
findings agent と fix agent を分離した § 決定 2 / ADR-054 の設計目的が崩れる。実装時の
pre-push security review が REJECT で指摘し、単一ファイル指定に改めて land した (#358)。

**静的検査を通らないのはコードだけではない — ADR に書かれた修正方針そのものが誤って
いることがある**。この一般化を dev-conventions へ convention として追加した。

## 主な変更

- `docs/adr/adr-067-*.md`: 段 2 完走の検証記録、残課題 1〜4 を「段 2 で閉じた課題」へ移し
  方針訂正を明記、ruleset の実体 (`~ALL` 対象 / `claude/**` 除外 / admin bypass) を残課題へ、
  `coderabbitai[bot]` allowlist の follow-up 判断 (追加しない = WP-18 で再判断) を追記
- `docs/adr/adr-066-*.md`: bounded lifetime の実走観測 1 run 目を記録 (trigger (a)(c) 充足、
  (b) は variable 側のみ充足で config 側の実走観測は未実施)
- `docs/adr/adr-068-*.md`: Phase B 1 run 目で docs-only fix の事実性誤りが観測されなかった
  ことを記録 (追加機構の再検討条件は未充足のまま)
- `docs/harness-improvement-plan.md`: 引き継ぎ節を実施記録へ書き換え、WP-17 受け入れ基準の
  段 0〜2 を充足済みへ更新
- `docs/dev-conventions.md` + `CLAUDE.md`: convention「LLM を含む自動化経路は実走でしか
  検証できない」を追加
- `docs/todo20.md` (新規) + `docs/todo-summary2.md`: 順位 365-373 の 9 エントリを登録。
  内訳は post-merge feedback 採用 19 件を実装時の PR 粒度で 8 エントリへまとめたもの (365-372)
  と、Rust exe の自動再ビルド 2 層案 (373)。却下 5 件も理由付きで記録
- `docs/todo.md` / `docs/todo14.md` / `docs/todo3-11.md`: todo14.md が約 70KB に達したため
  新規追加先を todo20.md へ。preamble 数詞を 22 へ更新 (cli-docs-lint の検出に追従)

## 順位 373 の実測データ (Rust exe の自動再ビルド)

`.claude/*.exe` は gitignore された生成物で、`pnpm build:all` を明示実行しない限り古い
バイナリが使われ続ける。2026-08-04 時点で `cli-fix-push-gate` (3/3 ファイル)・
`cli-autonomy-gate` (1/1)・`hooks-session-start` (1/8) の 3 パッケージが古い状態だった。

| 操作 | 小パッケージ | 大パッケージ (30 ファイル) |
|---|---|---|
| `cargo build --release` (変更あり) | 4.3 秒 | 9.9 秒 |
| `cargo check` | 0.39 秒 | 0.70 秒 |

この差から、PostToolUse には `cargo check` を、Stop hook には `build --release` + deploy を
割り当てる 2 層構成を採る。PostToolUse で build しない理由 (編集ごとの 4〜10 秒、中間状態の
compile error がノイズになる、deploy が毎回走る) も todo エントリに記録した。

## 自動起動経路への懸念 (新規記録)

段 1 で `coderabbitai[bot]` の permission が `none` と実測され `pull_request_review` 経路が
恒久 deny になるため、Phase B の起動は `issue_comment` (walkthrough) 経路だけになる。この
経路は初回 1 回きりで、その時点では CodeRabbit の実レビューがまだ無いことが多い。「findings
がある状態で Phase B が自動起動する窓」が実質的に無い可能性がある。段 2 は
`workflow_dispatch` による手動起動だったため**自動起動経路は未検証**である。WP-18 着手時に
bot allowlist の要否と併せて実測する (ADR-067 § 検証記録に記録)。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
aloekun added a commit that referenced this pull request Aug 5, 2026
WP-17 (イベント駆動バックボーン完成) で唯一残っていた受け入れ基準 — 実走スモーク段 2
= Phase B allow 経路の完走 — が 2026-08-04 に充足したことを記帳し、#350#357 の
post-merge feedback 採否とセッション発案のハーネス改善 1 件を todo へ確定する。
コード変更は含まない。

## 段 2 の結果 (ADR-067 § 検証記録)

`workflow_dispatch` を 4 回実行し、4 回目で 13 step 完走に至った。

| 回 | 検出した欠陥 | 対処 |
|---|---|---|
| 1 | `gh api` は `--slurp` と `--jq` を併用できない | PR #356 |
| 2 | findings agent の出力がコードフェンスで囲まれ `jq` が失敗 | PR #357 |
| 3 | `Apply fixes` が findings ファイルを読めず空 diff | PR #358 |
| 4 | なし (完走) | — |

4 回目の実測: findings 3 件 / `Apply fixes` は `permission_denials_count=0`・`num_turns=6` /
`Gate fix push` が `[FIX_PUSH_ALLOW] autonomy=allowed branch=isolated content=docs-only
scope=in-scope(1 files)` / `Push fix` が `ee9557a..86f424c` を push / `Report degrade to
Phase A` は skip (= degrade しなかった証拠)。

無人 fix が書いた内容も実測検証し、仕込んだ不整合 3 点を過不足なく修正・範囲外の編集
ゼロ (1 ファイル / 3 insertions / 3 deletions) であることを確認した。

`AUTONOMY_ENABLED` を削除した状態での dispatch では fix job 自体が skip され、ADR-066 の
「欠損 → 安全状態」が実 Actions ランタイムで機能することも確認した。

## ADR-067 § 残課題 1 の方針を訂正

同節に書いていた修正方針「`allowedTools` を `Read(findings-input/**)` にする」は**誤り**
だった。同ディレクトリには未要約の raw な CodeRabbit テキスト (`comments.json` /
`reviews.json`) があり、glob を与えると write 権限を持つ fix agent がそれを直接読める。
findings agent と fix agent を分離した § 決定 2 / ADR-054 の設計目的が崩れる。実装時の
pre-push security review が REJECT で指摘し、単一ファイル指定に改めて land した (#358)。

**静的検査を通らないのはコードだけではない — ADR に書かれた修正方針そのものが誤って
いることがある**。この一般化を dev-conventions へ convention として追加した。

## 主な変更

- `docs/adr/adr-067-*.md`: 段 2 完走の検証記録、残課題 1〜4 を「段 2 で閉じた課題」へ移し
  方針訂正を明記、ruleset の実体 (`~ALL` 対象 / `claude/**` 除外 / admin bypass) を残課題へ、
  `coderabbitai[bot]` allowlist の follow-up 判断 (追加しない = WP-18 で再判断) を追記
- `docs/adr/adr-066-*.md`: bounded lifetime の実走観測 1 run 目を記録 (trigger (a)(c) 充足、
  (b) は variable 側のみ充足で config 側の実走観測は未実施)
- `docs/adr/adr-068-*.md`: Phase B 1 run 目で docs-only fix の事実性誤りが観測されなかった
  ことを記録 (追加機構の再検討条件は未充足のまま)
- `docs/harness-improvement-plan.md`: 引き継ぎ節を実施記録へ書き換え、WP-17 受け入れ基準の
  段 0〜2 を充足済みへ更新
- `docs/dev-conventions.md` + `CLAUDE.md`: convention「LLM を含む自動化経路は実走でしか
  検証できない」を追加
- `docs/todo20.md` (新規) + `docs/todo-summary2.md`: 順位 365-373 の 9 エントリを登録。
  内訳は post-merge feedback 採用 19 件を実装時の PR 粒度で 8 エントリへまとめたもの (365-372)
  と、Rust exe の自動再ビルド 2 層案 (373)。却下 5 件も理由付きで記録
- `docs/todo.md` / `docs/todo14.md` / `docs/todo3-11.md`: todo14.md が約 70KB に達したため
  新規追加先を todo20.md へ。preamble 数詞を 22 へ更新 (cli-docs-lint の検出に追従)

## 順位 373 の実測データ (Rust exe の自動再ビルド)

`.claude/*.exe` は gitignore された生成物で、`pnpm build:all` を明示実行しない限り古い
バイナリが使われ続ける。2026-08-04 時点で `cli-fix-push-gate` (3/3 ファイル)・
`cli-autonomy-gate` (1/1)・`hooks-session-start` (1/8) の 3 パッケージが古い状態だった。

| 操作 | 小パッケージ | 大パッケージ (30 ファイル) |
|---|---|---|
| `cargo build --release` (変更あり) | 4.3 秒 | 9.9 秒 |
| `cargo check` | 0.39 秒 | 0.70 秒 |

この差から、PostToolUse には `cargo check` を、Stop hook には `build --release` + deploy を
割り当てる 2 層構成を採る。PostToolUse で build しない理由 (編集ごとの 4〜10 秒、中間状態の
compile error がノイズになる、deploy が毎回走る) も todo エントリに記録した。

## 自動起動経路への懸念 (新規記録)

段 1 で `coderabbitai[bot]` の permission が `none` と実測され `pull_request_review` 経路が
恒久 deny になるため、Phase B の起動は `issue_comment` (walkthrough) 経路だけになる。この
経路は初回 1 回きりで、その時点では CodeRabbit の実レビューがまだ無いことが多い。「findings
がある状態で Phase B が自動起動する窓」が実質的に無い可能性がある。段 2 は
`workflow_dispatch` による手動起動だったため**自動起動経路は未検証**である。WP-18 着手時に
bot allowlist の要否と併せて実測する (ADR-067 § 検証記録に記録)。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
aloekun added a commit that referenced this pull request Aug 5, 2026
WP-17 (イベント駆動バックボーン完成) で唯一残っていた受け入れ基準 — 実走スモーク段 2
= Phase B allow 経路の完走 — が 2026-08-04 に充足したことを記帳し、#350#357 の
post-merge feedback 採否とセッション発案のハーネス改善 1 件を todo へ確定する。
コード変更は含まない。

## 段 2 の結果 (ADR-067 § 検証記録)

`workflow_dispatch` を 4 回実行し、4 回目で 13 step 完走に至った。

| 回 | 検出した欠陥 | 対処 |
|---|---|---|
| 1 | `gh api` は `--slurp` と `--jq` を併用できない | PR #356 |
| 2 | findings agent の出力がコードフェンスで囲まれ `jq` が失敗 | PR #357 |
| 3 | `Apply fixes` が findings ファイルを読めず空 diff | PR #358 |
| 4 | なし (完走) | — |

4 回目の実測: findings 3 件 / `Apply fixes` は `permission_denials_count=0`・`num_turns=6` /
`Gate fix push` が `[FIX_PUSH_ALLOW] autonomy=allowed branch=isolated content=docs-only
scope=in-scope(1 files)` / `Push fix` が `ee9557a..86f424c` を push / `Report degrade to
Phase A` は skip (= degrade しなかった証拠)。

無人 fix が書いた内容も実測検証し、仕込んだ不整合 3 点を過不足なく修正・範囲外の編集
ゼロ (1 ファイル / 3 insertions / 3 deletions) であることを確認した。

`AUTONOMY_ENABLED` を削除した状態での dispatch では fix job 自体が skip され、ADR-066 の
「欠損 → 安全状態」が実 Actions ランタイムで機能することも確認した。

## ADR-067 § 残課題 1 の方針を訂正

同節に書いていた修正方針「`allowedTools` を `Read(findings-input/**)` にする」は**誤り**
だった。同ディレクトリには未要約の raw な CodeRabbit テキスト (`comments.json` /
`reviews.json`) があり、glob を与えると write 権限を持つ fix agent がそれを直接読める。
findings agent と fix agent を分離した § 決定 2 / ADR-054 の設計目的が崩れる。実装時の
pre-push security review が REJECT で指摘し、単一ファイル指定に改めて land した (#358)。

**静的検査を通らないのはコードだけではない — ADR に書かれた修正方針そのものが誤って
いることがある**。この一般化を dev-conventions へ convention として追加した。

## 主な変更

- `docs/adr/adr-067-*.md`: 段 2 完走の検証記録、残課題 1〜4 を「段 2 で閉じた課題」へ移し
  方針訂正を明記、ruleset の実体 (`~ALL` 対象 / `claude/**` 除外 / admin bypass) を残課題へ、
  `coderabbitai[bot]` allowlist の follow-up 判断 (追加しない = WP-18 で再判断) を追記
- `docs/adr/adr-066-*.md`: bounded lifetime の実走観測 1 run 目を記録 (trigger (a)(c) 充足、
  (b) は variable 側のみ充足で config 側の実走観測は未実施)
- `docs/adr/adr-068-*.md`: Phase B 1 run 目で docs-only fix の事実性誤りが観測されなかった
  ことを記録 (追加機構の再検討条件は未充足のまま)
- `docs/harness-improvement-plan.md`: 引き継ぎ節を実施記録へ書き換え、WP-17 受け入れ基準の
  段 0〜2 を充足済みへ更新
- `docs/dev-conventions.md` + `CLAUDE.md`: convention「LLM を含む自動化経路は実走でしか
  検証できない」を追加
- `docs/todo20.md` (新規) + `docs/todo-summary2.md`: 順位 365-373 の 9 エントリを登録。
  内訳は post-merge feedback 採用 19 件を実装時の PR 粒度で 8 エントリへまとめたもの (365-372)
  と、Rust exe の自動再ビルド 2 層案 (373)。却下 5 件も理由付きで記録
- `docs/todo.md` / `docs/todo14.md` / `docs/todo3-11.md`: todo14.md が約 70KB に達したため
  新規追加先を todo20.md へ。preamble 数詞を 22 へ更新 (cli-docs-lint の検出に追従)

## 順位 373 の実測データ (Rust exe の自動再ビルド)

`.claude/*.exe` は gitignore された生成物で、`pnpm build:all` を明示実行しない限り古い
バイナリが使われ続ける。2026-08-04 時点で `cli-fix-push-gate` (3/3 ファイル)・
`cli-autonomy-gate` (1/1)・`hooks-session-start` (1/8) の 3 パッケージが古い状態だった。

| 操作 | 小パッケージ | 大パッケージ (30 ファイル) |
|---|---|---|
| `cargo build --release` (変更あり) | 4.3 秒 | 9.9 秒 |
| `cargo check` | 0.39 秒 | 0.70 秒 |

この差から、PostToolUse には `cargo check` を、Stop hook には `build --release` + deploy を
割り当てる 2 層構成を採る。PostToolUse で build しない理由 (編集ごとの 4〜10 秒、中間状態の
compile error がノイズになる、deploy が毎回走る) も todo エントリに記録した。

## 自動起動経路への懸念 (新規記録)

段 1 で `coderabbitai[bot]` の permission が `none` と実測され `pull_request_review` 経路が
恒久 deny になるため、Phase B の起動は `issue_comment` (walkthrough) 経路だけになる。この
経路は初回 1 回きりで、その時点では CodeRabbit の実レビューがまだ無いことが多い。「findings
がある状態で Phase B が自動起動する窓」が実質的に無い可能性がある。段 2 は
`workflow_dispatch` による手動起動だったため**自動起動経路は未検証**である。WP-18 着手時に
bot allowlist の要否と併せて実測する (ADR-067 § 検証記録に記録)。

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
aloekun added a commit that referenced this pull request Aug 8, 2026
* docs(todo): WP-18 で検出した問題を 4 エントリへ登録 (順位 374-377)

WP-18 (夜間 todo 消化ループ、#361 / #362 / #363) の実装中に pre-push review・
CodeRabbit・ユーザー指摘で検出した問題 9 件のうち、todo 登録が要る 8 件を **実装時の
PR 粒度**で 4 エントリへまとめる。切り分けは 2026-08-06 にユーザー確認済み。

## 評価時の #1 を検証し、todo 登録が不要になった

#1 は「Bash prefix 許可の悪用可能性検証と全経路への横展開」として登録予定だった。
ユーザー指示により登録前に検証したところ、**前提が誤りだった**。

#363 の security review は「`Bash(cargo test:*)` は前方一致でシェルを解釈しないため
`cargo test` に任意コマンドを連結すると通過する」と主張していた。公式ドキュメントは
これを明確に否定している:

  Claude Code is aware of shell operators, so a rule like `Bash(safe-cmd *)` won't give
  it permission to run the command `safe-cmd && other-cmd`. The recognized command
  separators are `&&`, `||`, `;`, `|`, `|&`, `&`, and newlines. A rule must match each
  subcommand independently.

`--allowedTools` も同じルール体系に属する (managed settings の deny を --allowedTools で
上書きできない、と明記されている)。

結果:

- `pr-monitor.yml` の Phase A 分析 agent に**当該の穴は無く、対処不要**。production の
  live な穴という当初の見立ては誤りだった
- 残作業は `ADR-072` 決定 5 の根拠記述の訂正のみで、#363 が open のうちに同 PR へ直接
  反映する。よって todo エントリを立てない

検証結果と経緯はセクション冒頭の対応表に残した。

## この一件自体を教訓として取り込んだ

「レビュー指摘への対応時チェックリスト」エントリに 4 項目目を追加した — **指摘が技術的
前提 (ツールの挙動・仕様) に依拠しているなら、対処より先にその前提を検証する**。とくに
設計変更や他経路への横展開を伴う場合。

今回は未検証の前提のまま (a) agent から Bash を落とす設計変更を行い、(b) それを ADR の
決定として記録し、(c) さらに「同じ形が production にもある」と横展開の警告まで出していた。
一次情報に当たれば 1 回の WebFetch で否定できた。

## 内訳

- 順位 374: WP-18 夜間ループの実走スモーク実施 (Tier 1、評価時の #2/#3)
- 順位 375: レビュー指摘への対応時チェックリスト (Tier 2、評価時の #4/#5/#6 + 今回の #1)
- 順位 376: push-runner の bookmark 自動前進がスタック境界を壊す (Tier 2、評価時の #7)
- 順位 377: 夜間ループの防御を検知から防止へ格上げする判断 (Tier 3、評価時の #8/#9)

## まとめ方の方針

リポジトリの既存バッチ登録 (#350#357 の 24 件を 8 エントリへ) と同じく実装時の PR 粒度で
まとめた。評価時の番号との対応はセクション冒頭に表で残してある。

順位 374 (スモーク) の観測項目は `ADR-072` の実走スモーク節に表があるため、todo 側は
スケジューリングの掛かりだけを持ちチェックリストを複製しない。同じ表を 2 箇所で管理すると
必ず drift する (#362 の post-merge feedback が指摘した single source-of-truth 問題と同型)。

ADR-033 (絶対番号は table のみに保持) に従い、エントリ本文には順位番号を書いていない。
todo20.md は 50KB 閾値内。pnpm lint:docs / markdownlint ともに green。

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

* docs(todo): #363 post-merge feedback の採用 6 件を登録 (順位 378-383)

WP-18 最終 PR (#363、ADR-072) のマージ後 feedback が Tier 1 に 4 件・Tier 2 に 2 件を
採用候補として挙げた。ユーザー承認 (2026-08-07) を得て登録する。

## 6 件は 1 本の根から出ている

台帳 (docs/claude-code-web-tasks.md) の 内容 / 対象ファイル / 注意 は自由記述のまま
無人 agent のプロンプトへ流入する。agent は $GITHUB_WORKSPACE 全体に書き込め、その
出力は draft PR 本文という公開面に出る。ADR-054 の信頼境界そのもの。

- 378 (XS) 台帳を ADR-035 の docs-only 除外パス表へ追加 — 他 3 件の前提。台帳だけを
  変える PR が緩い評価経路に乗ると、対策そのものを迂回する台帳 PR が通りうる
- 379 (S)  tool scope を work/** へ限定 — ADR-072 決定 7 の改ざん検知が必要になって
  いる根本原因。実装後も検知層は残す (防御を 1 枚に減らす変更ではない)
- 380 (M)  台帳フィールドを untrusted data として明示 framing
- 381 (S)  台帳由来 SUMMARY の draft PR 本文出力に screening
- 382 (M)  injection payload の regression test (380 に依存)
- 383 (S)  is_separator_row のパイプ検証欠落

## 期限を「定常運用開始前」に固定する

実効リスクは現時点では低い — 悪意ある台帳行を master へマージするのはユーザー自身で、
単独運用では外部からの注入経路が無い。ただし夜間ループが定常運用に入り draft PR の
流量が増えると前提が変わるため、無期限の Tier 積みにしない。

順位 374 (実走スモーク) は dry_run で PR を作らないため本件の実害が無く、待たせない。

## 383 は実コードで確認済み

is_table_row は行頭 | を要求するが、is_separator_row は split_cells の結果しか見ない。
split_cells("---") は ["---"] を返し全セルが '-' のみなので真になる。markdown の
水平線がセパレータ行として通る (todo ファイル自身が --- を使っている)。
ADR-072 決定 2 の fail-closed 設計の coverage hole。

## 併せて

順位 374 のスモーク観測項目数を 4 → 8 へ修正した (ADR-072 側の実測と不一致だった)。

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

* docs(harness-plan): WP-18 を 3 PR マージ済へ更新し残作業 2 系統を明示する

#363 のマージ (2026-08-07) で WP-18 の実装 3 本がすべて land した。

## 「実装完了 = WP 完了」ではないことを表で残す

コードは全部 master にあるが、**夜間ループはまだ 1 度も走っていない**。この状態を
「実装済」の一語で片付けると、次のセッションが受け入れ基準を満たしたものと誤読する。
残作業を 2 系統に分けて表にした:

1. 実走スモーク (順位 374) — 受け入れ基準の中核
2. prompt injection 対策 4 件 (順位 378-381) — 定常運用開始前に必須

## スモークの前提が充足したことを記録

受け入れ基準の表は「(a) workflow が master にある (b) 台帳に無人可マークがある」を
未充足として書いていたが、**両方ともマージで解消した**。残る操作は GitHub UI 側の
AUTONOMY_ENABLED 設定のみなので、その 1 点へ書き換えた。

## 依存関係を明示する

378-381 は 1 本の根 (台帳の自由記述が無検証で agent プロンプトへ流入) から出ている。
一方スモークは dry_run で PR を作らないため本件の実害が無い。したがって
**スモークは 378-381 を待たずに着手してよい**と明記した。次セッションが順序で
迷わないようにするため。

## 未 push の改善 3 点の所在を残す

#363 の最終 push が security REJECT で止まったため、改ざん検知の red 化 / 決定 10 の
色分け表 / 決定 6 の列挙基準が master に載っていない。ローカル bookmark
wp18/unpushed-improvements (fc22403c) に保持していることを記録した。いずれも
可観測性と文書の改善で、fail-closed 自体は master 版でも成立している。

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

* docs(todo): 外部設定 (GitHub App / variables / secrets) の実体記録を登録 (順位 384)

新セッションでの指摘 (2026-08-07): workflow は vars.NIGHTLY_APP_ID /
secrets.NIGHTLY_APP_PRIVATE_KEY を参照するが、App の作成・インストール・登録を
記録した文書がリポジトリ内に無い。

## 欠けているのは設計根拠ではなく運用実体

ADR-072 決定 8 は「なぜ App token か」「なぜ PAT ではないか (オーナー PAT は
Repository admin として ADR-067 の ruleset backstop を素通りする)」「どの権限を
付けるか (Workflows は付けない)」「なぜ publish 直前に発行するか (token 寿命
1 時間)」を厚く残している。

記録が無いのは以下:

- App を実際に作成した事実・日付・名称・インストール範囲
- NIGHTLY_APP_ID = variable / NIGHTLY_APP_PRIVATE_KEY = secret という登録先の別
- 既存の Claude GitHub App との区別 (あちらは Workflows を含む広い権限を持つ別物)
- 再構築手順 (鍵ローテーション・派生プロジェクト展開)

NIGHTLY_APP の文字列はリポジトリ全体で workflow の 2 行と ADR 残課題の 1 行にしか
現れない。

## これは ADR-051 違反

ADR-051 (クロスシステム設定 coupling) は内部設定と外部 SaaS 設定が論理結合する場合に
(1) 両設定ファイルへの相互参照コメント (2) 期待値の組み合わせ表の ADR 必須記載
(3) 変更は両側を同一 PR、の 3 点を規律として定めている。workflow ↔ GitHub App +
repository variables/secrets はこの型で、3 点とも未実施。

前例として ADR-067 段 0 は repository ruleset を ruleset 名つきで「設定済み」と
記録している。ADR-072 は同じ扱いをしていない。同型の欠落が AUTONOMY_ENABLED にも
あり (ADR-066 は「Actions variable を使う」とは書くが現状値を記録していない)、
本エントリで一緒に扱う。

## 順位 374 と同時実施にする理由

スモークでは AUTONOMY_ENABLED の設定と App token の実動確認のため GitHub UI を
触るので、その過程で実値がすべて揃う。先行して記録しようとすると値が確定せず
二度手間になる。

## 教訓を残す

App の作成手順・Expire user authorization tokens の扱い・既存 App との違いは
2026-08-07 のセッションでユーザーへ提示したが、リポジトリへ残さなかった。会話は
次のセッションに残らないが workflow は残る。参照だけが残って由来が消える状態を
作った。順位 375 と同じクラスの失敗としてエントリ本文に記録した。

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

* fix(review): CodeRabbit Major 4 件を妥当性判定のうえ 3 件へ対応する (#364)

自動 fix 経路 (f698d19) が 1 件 (#4 台帳への非記録ルール追加) を対応済みで、
本コミットはその内容を含んだうえで残りを手で対応した結果である。同一ファイルの
近接行のため path 単位で分離できず 1 コミットに畳み込まれている。

## 妥当性の判定

severity ラベルではなく、プロジェクトの設計方針に照らして 1 件ずつ判定した。

- #1 adr-072:335 (秘密値を ADR に記録しない) — **妥当**。「実走スモークで実値を
  確認し ADR へ追記する」は秘密鍵本文まで書くと読める。ADR-051 が記録を課すのは
  結合の存在と期待値の組み合わせであって秘密の実値ではない。設定メタデータに
  限定し、鍵本文と token は ADR にも git 履歴にも残さないことを明記した
- #2 harness-improvement-plan:223 (受け入れ基準が成功経路だけ) — **妥当**。本
  プロジェクトは背圧 12 シナリオ・kill-switch 8 シナリオと停止側を drill で
  固めてきたが、夜間ループの停止側は実走未観測。WP-17 の残課題 (明示的 false と
  config 側 deny が実走未観測) と同じ穴。AUTONOMY_ENABLED の 3 状態を受け入れ
  基準へ追加した。指摘本文が名指しした 2 箇所 (計画書 L223 / todo20 L293-304) の
  両方に反映している
- #3 todo20:480 (prompt injection の回帰 fixture) — **妥当**。順位 382 の payload
  例 "; echo PWNED; #" は shell injection であって prompt injection ではない。
  台帳テキストが流れ込む先は shell ではなく LLM プロンプトなので、テストが目的と
  噛み合っていなかった。自然言語 adversarial payload (本命) と shell/パース形式
  payload (堅牢性) の 2 系統へ分離した

## 自動 fix の実測確認

f698d19 は 1 ファイル 2 行追加のみで範囲外の編集ゼロ。内容も妥当だったため
そのまま採用した (ADR-068 の後退検知の趣旨に沿って diff を実測で確認済み)。

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

---------

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