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
158 changes: 158 additions & 0 deletions issues/issue-113-cross-refactoring-4th-trial-report.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
# cross-refactoring 4 回目の実機試行の結果

Pull Request #127(NDF v8.5.0)で直した 5 件を実機で確かめた記録である。
対象は Pull Request #128(Draft のまま閉じた)。

経緯は次の 3 つにある。

- [issue-113-cross-refactoring-trial-report.md](issue-113-cross-refactoring-trial-report.md) — 1 回目
- [issue-113-cross-refactoring-retrial.md](issue-113-cross-refactoring-retrial.md) — 2 回目
- [issue-113-cross-refactoring-re-retrial.md](issue-113-cross-refactoring-re-retrial.md) — 3 回目

## 結果

**3 回目に見つけた 4 件のうち、実機で踏める 3 件は直っていた。**
一方でラウンド 2 の再レビューで**進行が終わらない経路**に入り、手で止めた。
原因は 3 回目より前から存在した欠落で、レビュー結果が 2 回続けて欠けたときにだけ現れる。

## 実行条件

| 項目 | 値 |
| --- | --- |
| ホスト | Claude Code(提案・レビューには不参加) |
| 提案・レビュー | codex / gemini / kiro |
| 適用の母集合 | claude / codex / kiro |
| 使用する版 | プラグインキャッシュの v8.5.0 |
| ラウンド上限 | 3(実際は 2 ラウンド目で停止) |
| 着手前のテスト | 463 passed |

```bash
/ndf:cross-refactoring 128 \
--scope plugins/ndf-shared/skills/cross-refactoring/scripts \
plugins/ndf-shared/skills/cross-refactoring/tests \
plugins/ndf-shared/skills/cross-review/scripts/lib \
plugins/ndf-shared/skills/cross-review/tests \
--sync-command "bash scripts/build-runtime-plugins.sh" \
--baseline-test "uv run --with pytest python -m pytest \
plugins/ndf-shared/skills/cross-refactoring/tests \
plugins/ndf-shared/skills/cross-review/tests -q" \
--max-outer-rounds 3
```

## 到達点

```mermaid
flowchart TD
Init([初期化・作業ディレクトリ・Skill 配置]):::ok --> P1
P1["R1 提案(3 CLI 並列)11 件"]:::ok --> M1
M1["統合 5 件 → 採用 5 件"]:::ok --> A1
A1["R1 適用(codex)13 コミット / 901 秒"]:::ok --> V1
V1["検証: 採用 2 / 失敗 3"]:::ok --> D1
D1["積み直し競合 → ラウンド全件へ退避<br/>取り消し 13 コミット"]:::ok --> P2
P2["R2 提案(同期後)8 件 → 採用 5 件"]:::ok --> A2
A2["R2 適用(kiro)5 コミット"]:::ok --> V2
V2["検証: 採用 5 / 失敗 0"]:::ok --> S2
S2["生成物を同期(9 ファイル)→ 進行側が push"]:::ok --> RV2
RV2["R2 レビュー: gemini 承認 / codex 結果なし"]:::ng --> LOOP
LOOP["差し戻し上限 → 変更要求として扱う<br/>修正フェーズ → 起点なしで弾かれる<br/>修正ラウンドが進まず同じ経路を反復"]:::ng --> Stop
Stop([手で停止]):::stop

classDef ok fill:#dfd,stroke:#383
classDef ng fill:#fdd,stroke:#933
classDef stop fill:#eef,stroke:#557
```

## v8.5.0 の修正の確認

| # | 直したこと | 観測 | 判定 |
| --- | --- | --- | --- |
| 12 | 生成物の同期コミット | `🔧 生成物を同期しました(bash scripts/build-runtime-plugins.sh / 9 ファイル)` が出て、`Chore: 生成物を同期する(cross-refactoring 進行側)` が push まで届いた | 成立 |
| 13 | 同期の後段の失敗 | 実機では後段が落ちなかったため未到達。旧版と新版を並べた再現で確認した(下記) | 別手段で確認 |
| 14 | 実装担当のコミット | 適用フェーズで codex / kiro とも手順書どおりコミットを作れた。作業ツリーに残骸は出なかった | 成立 |
| 15 | 見送り後の読み取り同期 | ラウンド 1 の全件取り消しで HEAD が `4642657` → `a66ed1e` へ動いた後、提案の直前に読み取り用 3 つとも `a66ed1e` へ同期された。ラウンド 2 の提案は消えた関数を 1 件も指していない | 成立 |

修正 13 は実機で踏めなかったため、`pre-commit` で `git commit` を必ず落とす作業ツリーを
作り、旧版と新版で `_sync_generated` を呼び分けて比べた。

| 版 | 中断後の作業ツリー |
| --- | --- |
| 8.3.0 | `' M generated.txt'` が残る |
| 8.5.0 | 空(`reset --hard` と `clean -fd` で戻る) |

修正 12 も同じ方法で、旧版が `_worktree_changes()` から `{'enerated.txt': 'M '}` を返して
`git add` が `pathspec ... did not match any files` で落ちること、新版が
`{'generated.txt': ' M'}` を返して通ることを確認した。

## 見つけた不具合

### 16. レビュー結果が欠け続けると進行が終わらない

**進行が止まらない。** レビュー結果が 2 回続けて欠けた後、修正フェーズと再レビューを
無限に往復する。実測ではラウンド 2 で 3 巡し、手で停止するまで終わらなかった。

`cmd_judge_review` には変更要求を返す出口が 2 つある。

| 出口 | `fix_base_sha` の記録 |
| --- | --- |
| 通常の変更要求 | する |
| 差し戻しの上限に達したため変更要求として扱う | **しない** |

`cmd_merge_fix` は `commits_in_range(work, entry.get("fix_base_sha"), head)` で修正の
範囲を求め、起点が空なら `None` が返る。範囲を確定できないので終了コード 2 で弾かれるが、
このとき `fix_rounds` は増えない。`cmd_should_abandon` は `fix_rounds` が上限に達したかで
見送りへ移るため、**上限に永久に到達しない**。

```
修正ラウンド 0 / 3 — まだ修正します
❌ 修正の範囲を確定できませんでした(起点 None / HEAD 0b45dc9...)。検証できない修正は採りません
===== レビュー =====
(以降くり返し)
```

この欠落は v8.5.0 で入ったものではない。v8.3.0 でも同じ位置にあり、レビュー結果が
2 回続けて欠ける条件を過去 3 回の試行が満たさなかったため現れていない。

**直し方**: 差し戻し上限の出口でも `fix_base_sha` を記録する。あわせて、
`merge-fix` が範囲を確定できずに終わったときも `fix_rounds` を進め、見送りへ到達させる。

### 17. 実装担当に直せない指摘が渡る

レビュー結果の欠落は、`findings` へ次の 1 件として記録される。

```json
{"reviewer": "cross-refactoring", "item_id": null,
"summary": "レビュー結果の形式が 2 回続けて不正だった: codex のレビュー結果がありません",
"resolved": false}
```

対象の改善項目が無く、コードのどこを直せば解決するのかも書かれていない。実装担当は
これを受け取っても何もできず、修正フェーズが空回りする。不具合 16 を直しても、
承認済みの項目が「レビュー担当が動かなかった」という理由だけで見送りへ進む。

**直し方**: レビュー担当が結果を残さなかったことは、実装担当への変更要求ではなく
**進行側の問題**として扱う。片方の結果が欠けたまま上限に達したら、残る 1 者の判定で
決めるか、進行を中断して利用者に判断を渡す。

## 運用上の観測

| 事象 | 内容 |
| --- | --- |
| codex がレビュー結果を残さない | ラウンド 2 で 3 回とも、手順書を読み進めた後に何も投稿せず終了した。`sentinel` は書かれるため監視は「完了」と見なし、`result.json` の不在だけが手掛かりになる |
| 差分予算による失敗 | ラウンド 1 の 2 件が予算超過で落ちた(265 行 / 240 行、183 行 / 180 行)。`long_method` の抽出は見積より膨らみやすい |
| 積み直しの競合 | ラウンド 1 は同じファイルの隣接行を触る項目が重なり、3 回目と同じくラウンド全件へ退避した |

## 集計

| 実装担当 | 担当R | 適用 | 見送り | 予算超過率 | 所要秒 |
| --- | ---: | ---: | ---: | ---: | ---: |
| codex / default | 1 | 0 | 5 | 0.40 | 1800 |
| kiro / default | 1 | 0 | 0 | — | 320 |

| レビュー担当 | レビュー回数 | 指摘 | 所要秒 |
| --- | ---: | ---: | ---: |
| codex / default | 0 | 0 | 0 |
| gemini / default | 3 | 0 | 480 |
| kiro / default | 0 | 0 | 0 |

kiro は既定モデル(auto)で動いたため、両ラウンドとも比較用の集計から分離された。
1 回の実行内の値なので、ランタイムの優劣を読む材料にはならない。
51 changes: 51 additions & 0 deletions issues/issue-113-cross-refactoring-4th-trial.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
# cross-refactoring 4 回目の実機試行

Pull Request #127(NDF v8.5.0)で直した 5 件が実機で成立するかを確かめる。

経緯は次の 3 つにある。

- [issue-113-cross-refactoring-trial-report.md](issue-113-cross-refactoring-trial-report.md) — 1 回目
- [issue-113-cross-refactoring-retrial.md](issue-113-cross-refactoring-retrial.md) — 2 回目
- [issue-113-cross-refactoring-re-retrial.md](issue-113-cross-refactoring-re-retrial.md) — 3 回目

## 目的

3 回目で見つけた 4 件と、投稿の成否を突き合わせない課題を直した。生成物を持つ
リポジトリで進行が止まる不具合 12 は、`--sync-command` を渡す構成でしか踏まないため、
同じ構成でもう一度通す。

## 確かめること

| # | 直したこと | 何が観測できれば通ったと言えるか |
| --- | --- | --- |
| 12 | 生成物の同期コミット | `Chore: 生成物を同期する(cross-refactoring 進行側)` が積まれ、`git add` が落ちない |
| 13 | 同期の後段の失敗 | 失敗しても作業ツリーが綺麗に戻り、次の実行が清浄性の検査で止まらない |
| 14 | 実装担当のコミット | 手順書の迂回手段でコミットが作れる。作れなくても取り込みが 0 件として続行する |
| 15 | 見送り後の読み取り同期 | 次ラウンドの提案が、取り消しで消えた対象を指さない |
| — | 投稿の成否の突き合わせ | cross-review が申告と GitHub 側の実数を照合する |

## 対象範囲

| パス | 内容 |
| --- | --- |
| `plugins/ndf-shared/skills/cross-refactoring/scripts/` | `refactor.py` / `launch-cli.sh` / `prepare-worktrees.sh` |
| `plugins/ndf-shared/skills/cross-refactoring/tests/` | 現状固定テスト |
| `plugins/ndf-shared/skills/cross-review/scripts/lib/` | 収束ループの共通層 |
| `plugins/ndf-shared/skills/cross-review/tests/` | 現状固定テスト |

## 実行条件

| 項目 | 値 |
| --- | --- |
| ホスト | Claude Code(提案・レビューには不参加) |
| 提案・レビュー | codex / gemini / kiro |
| 適用の母集合 | claude / codex / kiro |
| 使用する版 | リポジトリ内の `plugins/ndf-claude`(v8.5.0) |
| ラウンド上限 | 3 |
| 着手前のテスト | 463 passed |

## 注意

`plugins/ndf-shared/` は編集元であり、`scripts/build-runtime-plugins.sh` で
`ndf-claude` / `ndf-codex` / `ndf-kiro` へ同期する。同期は進行側の責務のため
`--sync-command` で渡す。