Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 23 additions & 2 deletions docs/adr/adr-013-merge-pipeline.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ Claude が "pnpm merge-pr" を実行する
cli-merge-pipeline.exe (スタンドアロン)
├─ hooks-config.toml [merge_pipeline] を読み込み
├─ jj bookmark → gh pr list --head で PR を自動検出
├─ jj bookmark (ローカル → リモート追跡) → gh pr list --head で PR を自動検出
│ (--pr <番号> 指定時はこの検出をスキップ)
Comment thread
aloekun marked this conversation as resolved.
├─ pre_steps を順次実行(マージ前チェック)
├─ gh pr merge --squash --delete-branch を実行
├─ jj git fetch && jj new master@origin でローカル同期
Expand All @@ -59,7 +60,7 @@ cli-merge-pipeline.exe (スタンドアロン)
| 項目 | 決定 | 理由 |
|---|---|---|
| マージ戦略 | squash 固定 | master の履歴を 1 PR = 1 コミットに保つ |
| PR 検出 | jj bookmark から自動検出 | `pnpm push` / `pnpm create-pr` と同じ方式で一貫性がある |
| PR 検出 | jj bookmark から自動検出(ローカル → リモート追跡の順。`--pr <番号>` で明示指定も可) | `pnpm push` / `pnpm create-pr` と同じ方式で一貫性がある。検出が効かない状況の逃げ道として明示指定を残す(詳細: 後述「§ PR 検出のフォールバックと逃げ道」) |
| ブランチ削除 | `--delete-branch` で自動削除 | マージ済みブランチの残留を防ぐ |
| ローカル同期 | `jj git fetch` + `jj new master@origin` | マージ後すぐに master 最新から作業を開始できる。`master@origin` (= remote tracking ref) を直接参照することで local master bookmark の状態に依存しない (詳細: 後述「§ sync_local の前提条件」) |
| ステップ分離 | `pre_steps`(マージ前)/ `post_steps`(マージ後) | 学び提案等の post-merge 処理を正しいタイミングで実行 |
Expand Down Expand Up @@ -97,6 +98,24 @@ step_timeout = 120
- **`master@origin` は jj clone 直後から自動生成される**: 設定なしで必ず存在する ref のため、新 PC / fresh clone でも前提条件を満たす
- **ADR-011 (push 戦略) との分離**: ADR-011 が確立した `auto-track-bookmarks = "*"` 設定は push の関心領域 (新規 bookmark の auto-track) のためのもの。merge-pipeline は同設定の副作用 (= local bookmark の fast-forward) に偶発的に依存していたが、本設計でその依存を解消した

### PR 検出のフォールバックと逃げ道 (2026-08-11 追加、順位 397)

**問題**: bot が作った PR を人間がマージする経路([ADR-072](adr-072-nightly-todo-loop.md) の夜間ループ)では、PR の head が `claude/nightly-163@origin` のような**リモート専用 bookmark** しか持たない。fetch しただけの bookmark はローカルに作られない(jj の `git.auto-local-bookmark` 既定値。jj 0.42.0 で実測)ため、ローカル bookmark だけを見ていた PR 検出が空振りし、`pnpm merge-pr` が「PR が見つかりません」で exit 1 していた([#381](https://github.com/aloekun/claude-code-hook-test/pull/381) のマージで実測)。

**構造的な問題はその先にある**: `gh pr merge` は本 ADR の guard でブロックされているため、検出が効かない状況では**ブロックされる経路と動かない経路しかない**。回避策(`jj bookmark track` してから再実行)は非自明で、夜間 PR をマージするたびに要求される。

**決定**: PR 検出を 3 段構えにする。

1. `gh pr view`(jj 併用リポジトリでは HEAD が detached のため通常失敗する。git 運用の派生プロジェクト向けに残す)
2. **ローカル bookmark** → `gh pr list --head`
3. **リモート追跡 bookmark** → `gh pr list --head`(`jj bookmark track` は不要。この経路を通った場合はその旨をログに出す)

加えて `--pr <PR番号>` を追加し、bookmark 検出に依存しない経路を常に 1 つ確保する。検出失敗時のメッセージは、この `--pr` を第一手段として実行可能な形で提示する。

**ローカルを先に全 revset 走査してからリモートへ移る**二段構成にしてある(revset ごとに両方を見るのではなく)。ローカル bookmark が 1 つでも見つかる状況では従来と結果が完全に一致し、同じ探索ヘルパーを共有する push-runner / pr-monitor([ADR-024](adr-024-shared-jj-helpers-library.md))への回帰が構造的に起きない。bookmark を**書き換える**経路(push-runner の bookmark 前進など)はリモート専用 bookmark を対象にしてはならないため、探索結果は `Local` / `RemoteOnly` を区別して返す。

**残る制約**: bookmark が探索 revset(`@` / `@-` / `@--`)より深い位置にある場合は依然として検出できない(順位 386 の別問題)。この場合も `--pr` で回避できる。

#### 過去の不具合 (2026-06-26 観測)

新 PC で `.jj/repo/config.toml` に `auto-track-bookmarks` 設定が無い状態で merge-pipeline を実行したところ、stale local master に作業コピーが乗り、`post_steps` の post-merge-feedback subsession が古い lint warning (`unnecessary_sort_by`) を「fix」しようとして `src/lib-report-formatter/src/lib.rs` を stray 編集する事故が発生した。原因連鎖の半分が本 sync_local 設計のバグであり、本 ADR 改訂と [src/cli-merge-pipeline/src/main.rs](../../src/cli-merge-pipeline/src/main.rs) の修正で根本解消した。残り半分の連鎖 (Stop hook の subsession 無差別発火) は [ADR-004](adr-004-stop-hook-quality-gate.md) § takt subsession skip で多層防御を入れている。
Expand Down Expand Up @@ -124,3 +143,5 @@ step_timeout = 120
- [ADR-012: src/ ディレクトリの命名規約](adr-012-src-naming-convention.md) — `cli-` プレフィックスの命名根拠
- [ADR-014: Post-Merge Feedback](adr-014-post-merge-feedback.md) — `ai` ステップで呼び出す skill のフロー定義
- [ADR-029: Post-Merge Feedback の自動起動](adr-029-post-merge-feedback-auto-trigger.md) — `ai` ステップの具体実装仕様 (2026-04-23 追加)
- [ADR-024: 共通 jj ヘルパーライブラリ](adr-024-shared-jj-helpers-library.md) — bookmark 探索の共有先 (2026-08-11 追加)
- [ADR-072: 夜間 todo 消化ループ](adr-072-nightly-todo-loop.md) — リモート専用 bookmark を持つ PR の生成元 (2026-08-11 追加)
22 changes: 22 additions & 0 deletions docs/adr/adr-024-shared-jj-helpers-library.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,28 @@ PR-C で以下を実施:

なお公開 API のうち `capture_commit_id` / `diff_is_empty` は PR-C 時点では未移設。現状は cli-pr-monitor 内のみで使用されており、2 つ目の使用例が出たタイミングで本 crate に追加する (ADR-021 原則 1-4 系の共通化は将来 PR で段階的に実施)。

### モジュール分割と API 追加 (2026-08-11、順位 397)

`lib.rs` 単一ファイルが 800 行ガイドラインを超えたため、責務ごとに分割した。`lib.rs` は crate doc と再エクスポートだけを持つファサードとして残るため、**呼び出し側のパス (`lib_jj_helpers::get_jj_bookmarks` 等) は変わらない**。

```text
src/lib-jj-helpers/src/
├── lib.rs # crate doc + pub use による再エクスポートのみ
├── bookmarks.rs # bookmark 探索 (ADR-021 原則 5 系)
├── workspace.rs # workspace layout 解釈 (ADR-045 系)
├── pipeline_lock.rs # pipeline 排他 (順位 280)
└── pipeline_lock/tests.rs
```

あわせて、リモート追跡 bookmark を扱う API を追加した ([ADR-013](adr-013-merge-pipeline.md) § PR 検出のフォールバックと逃げ道):

- `query_remote_bookmarks_at(revset: &str, stderr_mode: &StderrMode) -> Vec<String>`
- `enum BookmarkSearch { Local(Vec<String>), RemoteOnly(Vec<String>), NotFound }`
- `get_jj_bookmarks_with_remote_fallback(stderr_mode, fallback_log) -> BookmarkSearch`
- `select_with_remote_fallback(revsets, local, remote, fallback_log) -> BookmarkSearch` (query 注入版の pure function)

**既存 API は変更していない**。リモートへのフォールバックは新 API を明示的に呼んだ場合にのみ起こり、かつローカル bookmark が 1 つでも見つかる状況では従来と結果が一致する。共有ヘルパーの変更が 3 クレートに効く以上、既定の探索挙動を書き換えるより新 API を足して呼び出し側に選ばせる方が回帰の面で安全である。`RemoteOnly` を型で区別するのは、**bookmark を書き換える経路 (push-runner の bookmark 前進など) がリモート専用 bookmark を対象にしてはならない**ため。

## 影響

### 採用される構成要素
Expand Down
2 changes: 1 addition & 1 deletion docs/harness-improvement-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ Anthropic 公式のハーネスエンジニアリング指針(決定論的基

| 内容 | 基準 | 管理先 | 期限 / 条件 |
|---|---|---|---|
| **順位 397: `pnpm merge-pr` が夜間 PR を検出できない** — WP-18 が新設した「bot が作った PR を人間がマージする」経路で生まれた。夜間 PR は remote 専用ブックマークしか持たず、`gh pr merge` は hook でブロックされるため**逃げ道が無い**。毎回 `jj bookmark track` が要る | 1 | [todo21.md](todo21.md) | 🚀 Tier 1、**採用率測定の運用に直結** |
| ~~順位 397: `pnpm merge-pr` が夜間 PR を検出できない~~ → **対処済み(2026-08-11)**。PR 検出をローカル → リモート追跡 bookmark の 2 段にし、bookmark 非依存の `--pr <番号>` と実行可能な失敗ヒントを追加した。設計は [ADR-013](adr/adr-013-merge-pipeline.md) § PR 検出のフォールバックと逃げ道 が正 | 1 | [ADR-013](adr/adr-013-merge-pipeline.md) | 完了 |
| **順位 398-400: post-merge feedback の進行中ガードと復旧経路** — 連続マージで確実に踏み、復旧に手動介入(context 削除)が要る。marker は**危険な手順(stale context を読む直接起動)を案内**しており、誤った PR のレポートを生成しうる。3 件は同一機構の 3 面で同一 PR で扱える | 2 | [todo21.md](todo21.md) | 🔧 Tier 2、運用中に再発する |
| **順位 401: CodeRabbit クォータの窓が直近消費に追随する** — 決定 16 で**自律 PR が毎晩 1 レビュー消費**するようになり、人間の作業が集中する日に競合する。ADR-019 へ観測を記録する | 1 | [todo21.md](todo21.md) | 💎 Tier 3、記録のみ |
| **順位 410: `autonomy-config.toml` の boolean パース edge case をテスト固定** — WP-18 成果物(`review-request.yml` / `cli-autonomy-gate`)自身の堅牢化。kill-switch 判定の fail-open は [#380](https://github.com/aloekun/claude-code-hook-test/pull/380) で修正済みだが、確認がテストとして残っていない | 1 | [todo21.md](todo21.md) | 🔧 Tier 2、成果物の堅牢化 |
Expand Down
3 changes: 2 additions & 1 deletion docs/todo-summary2.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,6 @@
| 391 | 🔧 Tier 3 | **jj の落とし穴 (squash 方向・空コミットでの bookmark ずれ) を dev-conventions へ (#369 T3 採用)** | todo21.md | S | なし (本セッションで複数回踏んだ。コミット確定は describe+bookmark set、new は新作業時のみ、を明文化) |
| 392 | 🔧 Tier 3 | **push パイプラインの terminal outcome を telemetry へ記録し失敗回数・原因を機械集計可能にする** | todo21.md | M | なし (2026-08-09 WP-18 失敗頻度分析で構造化記録の欠落が判明。stage + reason code を ADR-055 系へ fail-open で追記し ADR-062 月次で集計。順位 386/387/376 の効果測定ベースラインにもなる) |
| 396 | 🚀 Tier 1 | **hooks smoke suite の並列実行が Linux で `ETXTBSY` を起こす (flaky テスト、早期修正)** | todo21.md | S | なし (#376 CI で ubuntu のみ失敗、windows は成功、当該クレートは無変更。2 テストが並列に exe を copy→spawn し、fork した子が copy 側の書き込み fd を継承するため exec が Text file busy。直近 15 run で初出だが ADR-065 の両 OS matrix の信号品質を下げる。**flaky を放置すると「また flake だろう」で実バグを見落とす**ため WP-18 とは独立に早期着手する = 2026-08-10 ユーザー判断で Tier 1 へ格上げ) |
| 397 | 🚀 Tier 1 | **`pnpm merge-pr` が夜間 PR (remote 専用ブックマーク) を検出できない** | todo21.md | S-M | なし (2026-08-10 実測。#381 のマージが「PR が見つかりません」で exit 1。夜間 PR は remote 専用 bookmark しか持たず、`gh pr merge` は hook でブロックされるため**ブロックされる経路と動かない経路しかない**。採用率測定で毎回踏む) |
| 398 | 🔧 Tier 2 | **post-merge-feedback の進行中ガードが完了済みの run を進行中と誤判定する** | todo21.md | S-M | なし (2026-08-10 実測。ガードは context.json の mtime 1500s だけを見て完了を見ない。連続マージで確実に踏む。順位 399/400 と同一機構) |
| 399 | 🔧 Tier 2 | **`--feedback-only <PR>` が同じガードに阻まれ復旧手段として機能しない** | todo21.md | S | なし (2026-08-10 実測。PR 番号を引数で受け context 非依存の設計なのにガードだけ context 鮮度を見る。復旧専用コマンドが復旧に使えない) |
| 400 | 🔧 Tier 2 | **post-merge-feedback の marker が危険な復旧手順を案内し安全な手順に触れていない** | todo21.md | XS-S | なし (2026-08-10 実測。takt 直接起動は stale context を読み誤った PR のレポートを生成しうる。実際に #382 の marker 時点で context は #383 を指していた。安全な --feedback-only に言及が無い) |
Expand All @@ -159,6 +158,8 @@
| 409 | 🔧 Tier 2 | **shell の部分一致比較を検出するカスタムリントルール (系統 C-2)** | todo21.md | S-M | 順位 408 (規約側)。検出対象を安全装置の判定に絞れるかが採否の分かれ目。絞れなければ却下も正規の出口 (ADR-042 の mechanizable 判定) |
| 410 | 🔧 Tier 2 | **`autonomy-config.toml` の boolean パース edge case をテスト固定 (系統 C-3)** | todo21.md | S | なし (2026-08-10 採用。順位 408 の修正時に手で確認した edge case がテストとして残っていない。workflow の awk と Rust 側の解釈一致も確認できると望ましい) |
| 411 | 🚀 Tier 1 | **`cargo fmt` を PreToolUse でブロックし正しい対処を提示 (系統 F、規約ではなく機構)** | todo21.md | S | なし (2026-08-10 ユーザー判断で提案の形を変更。規約は毎セッション読まれコンテキストを圧迫するが hook は発火時のみコストが出る。ADR-042 へこの非対称を追記するのも本エントリの範囲。**反射的に実行されやすく無関係な差分を生む**ため WP-18 とは独立に早期着手する = 2026-08-10 ユーザー判断) |
| 412 | 💎 Tier 3 | **`resolve_main_workspace_root` の colocated 経路と file 経路で正規化の粒度が違う** | todo21.md | S | なし (2026-08-10 PR #385 の CodeRabbit 指摘。colocated は入力をそのまま返し file 経路は canonicalize する。現行 caller に破綻経路は見当たらないが、caller が文字列比較を始めた時点で分裂しうる。PR #385 は逐語移動 PR のため見送り) |
| 413 | 🔧 Tier 2 | **`CwdRestore` Drop guard が 8 定義 / 6 ファイルに複製。ADR-025 の統合トリガーと再評価期限を超過** | todo21.md | S-M | なし (2026-08-10 PR #385 の pre-push review 指摘。ADR-025 自身が「2 例目で `lib-test-helpers` へ統合」と定め再評価期限 2026-07-31 も過ぎている。抽出するか ADR-025 の status を更新するかの判断が要る) |

**戦略**: Tier 1 を 2〜3 セッションで片付け → Tier 2 で ADR-032 の前提 + rate-limit + convergence cost 削減を進める → Tier 3 で ADR-032 を land + ドキュメント整備。Tier 4-5 は cleanup / 外部展開で daily efficiency への直接効果は小さい。

Expand Down
Loading
Loading