Repository navigation
Description
何が起きているか
PR #2192(2026-10-30、既定の --budget-minutes 30)の cross-refactoring は、改修計画の時点で使えた時間が 5.09 分だった。提案 23 件のうち 20 件が時間で見送られ、採用は 3 件だった。
30 分の内訳(リファクタリング計画のコメントの「時間の上限」の表から):
| 区間 | 時間 |
|---|---|
| 着手前のテスト・指標・提案 | 約 7 分 |
| 改修計画 | 3 分 |
| 最終ゲートの確かめ(CI の待ち。#2203 で扱う) | 13.4 分 |
| 最終ゲートの修正・余裕 | 約 4 分 |
| 実装に使えた時間 | 約 5 分 |
直近 2 か月の実績(ai-plugins の 103 回。PR のリファクタリング計画のコメントから集計)でも、採用件数は版より予算で決まっている。
| 予算 | 時期 | 回数 | 採用/回 | 使えた時間/回 | 使えた時間 1 分あたりの採用 |
|---|---|---|---|---|---|
| 30 分以下 | 10.17.8〜10.17.57 | 10 | 1.2 | 7.0 分 | 0.17 |
| 40 分以上 | 10.17.8〜10.17.57 | 16 | 10.8 | 39.9 分 | 0.27 |
| 30 分以下 | 10.17.58〜10.17.75 | 16 | 1.6 | 3.9 分 | 0.42 |
| 40 分以上 | 10.17.58〜10.17.75 | 5 | 6.8 | 26.4 分 | 0.26 |
| 30 分以下 | 10.18.0〜 | 3 | 3.0 | 6.5 分 | 0.46 |
| 40 分以上 | 10.18.0〜 | 4 | 12.2 | 38.3 分 | 0.32 |
使えた時間あたりの効率は予算でほとんど変わらない。30 分では固定でかかる時間が予算の大半を使い、実装に回る時間が残らない。
同じ 10/4〜10/17・同じ版で、novel リポジトリ(着手前のテストが短い)は 30 分で 1 回 9.4 件を採用している。ai-plugins は着手前のテストが 400 秒前後あり、使えた時間が 0.3〜8 分だった(PR #1745・#1780・#1799 は 1 分未満で採用 0)。全体の時間で決める既定は、リポジトリのテストの長さで中身が変わる。
方針の変更(2026-11-01)
予算を固定の分数(既定 30 分、案の「実装に使える時間 20 分」も含む)で決めるのをやめ、テストの所要とコード量から決める。
固定の値はリポジトリのテストの長さで中身が変わり(上の novel と ai-plugins の差)、PR の大きさにも追従しない。
「実装に使える時間」を固定値で渡す元の案は、下の式の N × u を定数にした特別な場合に当たる。
実績の分析(2026-11-01)
材料: PR のリファクタリング計画のコメント 108 件(2026-09-06〜11-01。時間の記録がある 64 件、内訳を逆算できる 63 件)、各 PR の着手前の差分、配分の履歴(cross-refactoring-allocation.jsonl の実行の行 8 件)。
| 分かったこと | 数値 |
|---|---|
| 固定でかかる時間はテストの所要で決まり、差分の大きさにほぼ依らない | 固定分(予算 − 使えた時間)の中央値 24.9 分。x̂ + (4.7 + 0.43·x̂) + v̂ + 2F で中央値の誤差 1.1 分で再現。着手前のテスト・最終ゲート・修正と差分の行数 D の相関は ρ = 0.00〜0.03 |
| 提案と改修計画はほぼ一定 | 4.5〜7.5 分(配分の履歴の実測) |
| 提案件数は差分の大きさと弱くしか連動しない | D との ρ = 0.21(p = 0.10)、変更ファイル数との ρ = 0.30。300 行未満で約 14 件、それ以上は 19〜23 件で頭打ち |
| 採用件数は使えた時間で決まる | 計画で採った件数と使えた時間の ρ = 0.84。64 回のうち 49 回が時間で頭打ち |
| 項目 1 件の実際の所要は約 3 分 | 計画の後の壁時計 ÷ 検証した項目の中央値 159 秒(8 回)。使えた時間 ÷ 最終の採用件数は 3.7 分 |
| 範囲テストの回は 1 件の見積りが 3〜5 倍に膨らむ | #2092 以降の scope の回で計画の見積りが 1 件 6.3〜12.9 分。commands/plan.py の measured_verify が着手前の範囲テスト全体(約 500 秒)を項目ごとに載せている。実測の検証は 1 件 5〜50 秒 |
| 予算の外にこぼれる時間がある | 着手前のテストの打ち切りと打ち直し(180〜540 秒 × 回数)は開始の記録より前で、予算に現れない。最終ゲートの実測(687〜930 秒)が見込みを超えた回が 7 回中 5 回 |
提案
想定最大時間 B(分)を次の式で決める。記号: x̂ = 着手前のテストの所要の見込み、v̂ = 最終ゲートの確かめの見込み(CI に任せる戦略は CI の壁時計、手元は全体テスト)、F = 配分の fix、D = 範囲に入るプロダクションコード(テストを除く)の変更行数、u = 項目 1 件の所要。
候補 1: 着手前に D と T だけで決める
固定分(T) = x̂ + P + v̂ + 2F, P = 4.7 + 0.43·x̂(提案と改修計画)
N(D) = clamp(4·log10(D), 6, 16) # D=100 → 8、1,000 → 12、10,000 以上 → 16
B = 固定分(T) + N(D) × u, u = 3(配分の履歴から更新)
下限 = 固定分(T) + 3u、上限 = min(固定分(T) + 16u, 120)
今の ai-plugins(x̂ 8.5 分・CI 15.4 分・2F 3.5 分・D 1,000 行)で約 72 分。#2203 が入れば約 57 分。
候補 2: 計画の時点で N を提案件数で決め直す
着手時は候補 1 と同じで、改修計画の時点で N = clamp(重複を除いた提案件数, 3, 20) に置き換える。D と提案件数の相関が弱いため当たりやすいが、B が計画の時点まで確定しない。
過去の回への試算
| 予算の理由で見送った 712 件のうち入る件数 | 予算の中央値 | |
|---|---|---|
| 候補 1 | 456 件(64%) | 62 分 |
| 候補 2 | 570 件(80%) | 82 分 |
ただし #2092 以降の範囲テストの回だけで見ると、候補 1 でも 136 件のうち 32 件しか入らない。1 件の見積り(measured_verify)を実測に合わせる修正を同時に入れないと、式で予算を広げても効かない。
決めること(設計で):
- 候補 1 と候補 2 のどちらにするか
- 固定分を B に依らない形にする(今の提案の枠 0.20·B・計画の枠 0.10·B・余裕 0.05·B は、B を固定分から決めると循環するため置き換える)
- 1 件の見積りの直し方(範囲テストの全体の秒を項目ごとに載せない。項目ごとの検証の実測を使う)
--budget-minutesの扱い(明示したときは上限として効かせる・式を使わない、のどちらか)と、検査のプランが渡している予算(60・75・90 分)の置き換え- 着手前のテストの打ち切りと打ち直しの時間を予算に入れるか
- 予算を 2 回に分けて決めるか(2026-11-01 の追加の検討): 着手時はテストの所要と指標で見込みを出して提案・計画の枠に使い、計画の時点で「グレード medium 以上の実際の提案件数 × 手法ごとの 1 件の実測」で確定する
- 差分の行数の代わりに使う指標の候補(件数の見込み): 範囲に入るパスの数(提案件数との ρ = 0.36)・変更ファイル数(ρ = 0.30)。行数は ρ = 0.21。提案の前に測るコード指標(閾値を超えた箇所の数)は未検証で、設計の工程でコメントの指標の表を集計して確かめる
- 1 件の所要を一律の u でなく手法ごとの配分テーブルの実測で見積もるか(実測の中央値: extract_method 53 秒・replace_with_lookup_table 118 秒・consolidate_duplication 338 秒)。テストを足す要る項目(範囲のテストの薄さ)は 1 件約 60 秒を足す
- グレード low の項目を予算の件数に数えないか
- 着手前のテストの所要と提案件数の ρ = 0.41 は時期の交絡(テストが長くなった時期と提案が増えた時期が重なる)が混ざっている見込みで、件数の指標には使わない。差分の大きさと取り消しの件数はほぼ無相関(ρ = −0.17〜0.05)
受け入れ条件
- 既定(
--budget-minutesなし)で起動したとき、想定最大時間がテストの所要の見込みと差分の大きさから決まり、固定の分数を使わない - リファクタリング計画に、固定でかかる時間の見込み・見込みの件数(と 1 件の所要)・想定最大時間と、それぞれの材料(x̂・v̂・F・D)が載る
- 範囲テストの回で、計画が使う 1 件の見積りが項目ごとの検証の実測に基づき、着手前の範囲テストの全体の秒を項目ごとに載せない
- この ai-plugins で既定の起動を実際に 1 回行い、予算の理由の見送りが、同じ規模の過去の回(スプリント m2170 #2192 など)より減ったことを確かめる
関連
- 検査のプランの構造改善が既定の予算で下限に届かず、33 行の差分でも refactor が落ちて abort へ進む #2047(既定の予算で下限に届かず abort へ進む): 下限まで上げる対処は v10.27.5 で入った。この issue で既定の決め方そのものを置き換える
- 見積もりの部品が cross-refactoring の予算とスプリントの大きさ(L)へつながっていない #2022(見積もりの部品が予算とつながっていない)
- cross-refactoring: 最終ゲートの CI の待ち(予算 30 分のうち 13.4 分)を想定最大時間の勘定から外し、別の上限で待つ #2203(最終ゲートの CI の待ちを予算から外す): 入れば固定分が約 15 分減る
- 意味の薄いテストを徹底的に削る: 削る基準を決めて要らないテストを消す(全体テストを 3 分以内にする #2291 の削る側) #2204(全体テストの短縮): 固定分の x̂・v̂ が減る
根拠のデータ
- 103 件の集計(元の本文): 2026-09-06〜10-30 の PR のリファクタリング計画のコメント(
<!-- cross-refactoring plan rf<N> -->) - 例: スプリント m2170 #2192 ・ スプリント m1290 #1799 ・ スプリント m2087 #2152
- 2026-11-01 の分析の全文は下の折りたたみ(集計の生データとスクリプトは分析した手元にだけあり、コミットしていない)
分析の全文(2026-11-01)
結論(先に)
-
固定でかかる時間は差分の大きさ D にほぼ比例しない。テストの所要 T だけで決まる。 予算から使えた時間を引いた値(B − A)は、
x̂ + (4.7 + 0.43·x̂) + v̂ + 2Fで、中央値の絶対誤差 1.1 分で再現できる(63 回。v̂ と F はその回の上限の表の値を使ったので、実質は提案と改修計画の P の当てはまり)。
x̂ = 着手前のテストの所要、v̂ = 最終ゲートの確かめ(CI に任せるなら CI の壁時計 c、手元なら全体テスト w)、F = 修正 1 回の見込み(配分のfix)。 -
提案件数は D とほとんど相関しない(Spearman ρ = 0.21、p = 0.10。変更ファイル数とは ρ = 0.30、p = 0.02)。
D が 300 行未満で 14 件前後、それ以上ではどの大きさでも 19〜23 件で頭打ちになる。
採用件数を決めているのは使えた時間 A である(計画で採った件数と A の ρ = 0.84)。予算で頭打ちになったのは 64 回のうち 49 回。 -
項目 1 件の実際の所要は約 3 分(計画の後の壁時計 ÷ 検証した項目は 8 回の中央値 159 秒。63 回の使えた時間 ÷ 計画で採った件数は 2.3 分、÷ 最終の採用件数は 3.7 分)。
一方で、着手前のテストを範囲で走らせる回(スプリント s2086 #2092 以降の scope)は、計画が使う 1 件の見積りが 9.6〜12.9 分に膨らんでいる。
検証の見積りに着手前の範囲テストの全体の実測(約 500 秒)を 1 件ずつ載せているためで(commands/plan.pyのmeasured_verify)、
実測の検証は 1 件 5〜50 秒である。式で予算を広げても、この見積りを直さないと scope の回では見送りがほとんど解消しない。 -
推奨の式(候補 1):
想定最大時間 B = 固定分(T) + N(D) × u 固定分(T) = x̂ + P + v̂ + 2F P = 4.7 + 0.43·x̂(提案と改修計画。分) N(D) = clamp(4·log10(D), 6, 16) D = 範囲に入るプロダクションコードの変更行数(追加 + 削除) u = 3 分(項目 1 件の実測) 下限 = 固定分 + 3u、上限 = 固定分 + 16u(かつ 120 分)今の ai-plugins(x̂ 8.5 分・c 15.4 分・2F 3.5 分・D 1,000 行)では 固定分 35.8 分 + 12 件 × 3 分 = 約 72 分。
cross-refactoring: 最終ゲートの CI の待ち(予算 30 分のうち 13.4 分)を想定最大時間の勘定から外し、別の上限で待つ #2203(最終ゲートの CI の待ちを予算から外す)が入れば約 57 分になる。 -
過去 63 回に当てると、予算の理由の見送り 712 件のうち 候補 1 で 456 件(64%)、候補 2(N を提案件数にする)で 570 件(80%) が入る計算になる。
ただし スプリント s2086 #2092 以降の scope の回では、見積りが膨らんでいるため 136 件のうち 32 件しか入らない(3. の見積りを直す前提で初めて効く)。
1. データと前処理
| 材料 | 件数・範囲 | 使い方 |
|---|---|---|
PR のリファクタリング計画のコメント(<!-- cross-refactoring plan rf<N> -->) |
108 件(2026-09-06〜11-01、PR 108 本で 1 本 1 件) | 予算 B・使えた時間 A・着手前のテスト x・w・c・時間の上限の表・項目の状態・見送りの理由と見積り |
| うち時間の記録がある回 | 64 件(#951 以降。#951 は時間の上限の表が旧形式で内訳を逆算できず、内訳は 63 件) | 本分析の主な対象 |
| うち時間の記録が無い回(#448〜#972 のラウンド制) | 44 件 | 提案件数と差分の相関の確認だけに使う |
| PR の差分 | 108 本。git diff --numstat <merge-base> <着手前の HEAD> |
下記 D |
配分の履歴 cross-refactoring-allocation.jsonl |
32 行(run 8・init_test 24。#2152〜#2363) | 手順別・項目別の秒 |
結果 cross-refactoring-rf*.json |
11 件(うち 2 件は着手前で止まり phases が空) | 手順の壁時計と CLI の秒 |
差分の大きさ D の取り方。 PR の今の差分はリファクタリングのコミットを含むため使わない。コメントの「着手前のテストの結果 … HEAD 」
(64 件)を着手前の HEAD とし、マージコミットの第 1 親(未マージの #2363 は origin/develop)との merge-base からの差分を取った。
HEAD の無い 44 件は、PR の commits で最初のリファクタリングのコミット(Test: … — / Refactor: <手法> — / 現状固定)の直前を HEAD とした。
| 列 | 定義 |
|---|---|
D_all / D_files |
全ファイルの追加 + 削除 / ファイル数 |
D_code |
拡張子 .py .sh .ts .tsx .js .mjs .cjs のうちテスト(tests/・test_*・*_test.py・*.test.*・conftest.py)を除いた行数 |
D_scope_code / D_scope_code_files |
D_code のうち、コメントの「対象範囲」(refactor-scope.py が決めた scope)に入るもの。以下の D はこれ |
時間の内訳の逆算。 コメントの「時間の上限」の表から、実装(timeline.py・budget.py)の式を逆にたどった。
- 開始 = H − B(H = 想定最大時間の終わり)
- バッファ R = (H − 直しの試行の打ち切り) + F。
fix_end = 開始 + B − 危険フラグ − 最終ゲート − final_fixとfix = final_fix(同じ配分の値)による - 最終ゲートの確かめ v(危険フラグ + 最終ゲートの全体テスト) = (H − fix_end) − F
- 計画の時点の経過 E = B − A − R(
available_minutes = B − E − R)、提案と改修計画 P = E − x
2. 固定でかかる時間の内訳
2.1 全体(63 回、分)
| 区間 | 中央値 | p10 | p90 | 最小 | 最大 | 何に比例するか |
|---|---|---|---|---|---|---|
| 着手前のテスト x | 5.6 | 1.8 | 8.4 | 0.3 | 10.9 | テストの所要。D とは ρ = 0.00 |
| 提案と改修計画 P(指標の測定を含む) | 6.7 | 4.4 | 9.4 | 3.7 | 18.6 | ほぼ一定(4.7 + 0.43·x、r = 0.48)。D とは ρ = 0.14(p = 0.26)、提案件数とは ρ = 0.41 |
| 最終ゲートの確かめ v | 7.6 | 4.4 | 13.4 | 1.3 | 15.4 | テストの所要(CI に任せる回は c そのもの、手元の回は w・x と同程度)。D とは ρ = 0.03 |
| 修正の 2 枠 2F(検証の修正 + 最終ゲートの修正) | 2.9 | 1.9 | 11.0 | 1.7 | 11.0 | 一定(配分の fix。履歴が無いと初期値 5.5 分 × 2 = 11 分) |
| 固定の合計 B − A | 24.9 | 17.9 | 34.9 | 14.7 | 49.5 | |
| 使えた時間 A | 9.9 | 2.8 | 43.0 | 0.3 | 53.6 |
配分の履歴(8 回)の実測でも、提案は 197〜362 秒、改修計画は 62〜94 秒、指標の測定は 1〜47 秒で、P は 4.5〜7.5 分に収まる。
P が x と弱く相関するのは、着手前のテストが長い回ほど提案の CLI が並行して遅くなるか、提案の枠(0.20·B)の取り方の違いによると見られる(確かめていない)。
2.2 期ごと(中央値、分)
| 期 | 回数 | B | x | P | v | 2F | R | B − A | A |
|---|---|---|---|---|---|---|---|---|---|
| #989〜#1374(戦略の記録なし) | 12 | 30 | 2.1 | 5.0 | 4.2 | 11.0 | 15.2 | 22.5 | 7.2 |
| #1383〜#1732(local-full、x ≈ 3 分) | 19 | 60 | 3.7 | 7.6 | 7.0 | 2.2 | 11.2 | 24.2 | 40.6 |
| #1745〜#2070(local-full、x ≈ 7 分) | 20 | 30 | 7.1 | 7.0 | 7.7 | 2.7 | 10.6 | 26.0 | 4.8 |
| #2092〜#2363(scope / CI で全体) | 12 | 65 | 8.1 | 6.9 | 13.3 | 5.2 | 18.8 | 34.9 | 32.5 |
- 固定分は 22.5 → 35 分へ伸びてきた。伸びたのは x(テストの増加)と v(CI の壁時計 c が 296 → 922 秒)で、P はほぼ同じ
- B = 30 分のままでは、固定分が 26 分を越えた スプリント m744 #1745 以降に使えた時間が 0.3〜8 分になる(スプリント m744 #1745・スプリント m653 #1780・スプリント m1290 #1799・スプリント m1743 #1825 は 1 分未満)
2.3 予算の外でかかっている時間(データの注意)
- 着手前のテストの打ち切りと打ち直し。 配分の履歴の init_test では、上限
max(0.10·B, 3·s)が B = 30 のとき 180 秒になり、
スプリント m2087 #2152・スプリント m1426 #2247・スプリント l20261031-2 #2250・スプリント m26-1 #2268・スプリント l20261031-3 #2283・スプリント l20261031-5 #2312・スプリント m26-2 #2318 で打ち切り(180 秒、続いて 450〜540 秒)→ 打ち直しが起きている。
スプリント m1426 #2247 は 180 + 540 + 653 秒。この時間は記録上の開始より前で、B にも A にも現れない - 最終ゲートの確かめは見込みより長い。 履歴の
reserve.final_whole_testは見込み 616〜922 秒に対し実測 687〜930 秒(7 回のうち 5 回が見込みを超過。スプリント m2087 #2152・スプリント m2169 #2178 は 616 秒の見込みに 930 秒)。v̂ は c の直近の実測の最大を使うのが安全
3. 提案件数・採用件数と差分の大きさ
3.1 相関(時間の記録がある 64 回、Spearman)
| 組 | 全体 (n=64) | 頭打ちあり (n=49) | 頭打ちなし (n=15) |
|---|---|---|---|
| 提案件数 × D(範囲のコード行) | +0.21 (p=0.10) | +0.21 (p=0.15) | −0.04 (p=0.89) |
| 提案件数 × 範囲のコードのファイル数 | +0.30 (p=0.02) | +0.33 (p=0.02) | −0.16 (p=0.57) |
| 提案件数 × 全差分行 D_all | +0.13 (p=0.31) | +0.09 | −0.09 |
| 計画で採った件数 × D | −0.22 (p=0.09) | −0.19 | +0.13 |
| 最終の採用件数 × D | −0.19 (p=0.13) | −0.17 | −0.10 |
| 計画で採った件数 × 使えた時間 A | +0.84 (p<0.001) | — | −0.15 |
| 最終の採用件数 × 使えた時間 A | +0.59 (p<0.001) | — | — |
- 「頭打ちあり」= 見送りの理由に
budgetがある回(49 回、見送り計 712 件) - ラウンド制の 44 回(Add: 運用モード operation を新設する(#423) #448〜mcp-serena: 言語サーバの設定・検査・誘導の hook を足し、Claude Code と Codex で定義・参照・診断を使えるようにする(#818) #972)でも提案件数 × D は ρ = +0.18(p = 0.26)で、同じ傾向
- 提案件数は「提案件数 = 項目の数 + 見送りの行 − 重複(duplicate)− 実装の締め切りで止まった項目(not_done、項目と二重に載る)」
3.2 D の区間ごと
| D(範囲のコード行) | 回数 | 提案件数 中央値(平均) | 計画で採った 中央値 | 最終の採用 平均 | 頭打ちの回 |
|---|---|---|---|---|---|
| 0〜299 | 8 | 14(14.6) | 4.5 | 4.5 | 8 |
| 300〜799 | 15 | 19(19.7) | 11 | 7.9 | 9 |
| 800〜1,499 | 23 | 23(22.8) | 6 | 5.2 | 16 |
| 1,500〜2,999 | 13 | 19(21.0) | 3 | 4.2 | 12 |
| 3,000 以上 | 5 | 18(16.0) | 2 | 3.2 | 4 |
提案は 3 者(claude / codex / kiro)が出し、重複を除くと 1 回 14〜23 件に収まる(コード上の上限 90 件には届かない)。
D が効くのは 300 行未満とそれ以上の境くらいで、それより大きくても提案は増えない。 採用件数は D ではなく A で決まっている。
3.3 頭打ちにならなかった 15 回
#1391・#1410・#1445・#1452・#1469・#1467・#1506・#1520・#1521・#1573・#1581・#1701・#1732・#2133(B = 60〜90)と #951。
計画で採った件数の中央値 18、最終の採用 11、提案 18。提案のほぼ全件が入るのに要った使えた時間は 30〜49 分(#951 を除く)だった。
4. 項目 1 件あたりの所要
4.1 実測(配分の履歴 8 回、秒)
| 種類 | 標本 | 中央値 | p25 | p75 | p90 | 最大 |
|---|---|---|---|---|---|---|
| 実装(structure/*、1 項目) | 51 | 54 | 46 | 66 | 91 | 508(consolidate_duplication) |
| テストの追加(1 項目) | 9 | 60 | 53 | 74 | 79 | 79 |
| 検証(1 項目) | 54 | 18 | 5 | 41 | 49 | 49 |
| 修正(1 起動) | 8 | 96 | 31 | 219 | 219 | 219 |
| 計画の後の壁時計 ÷ 検証した項目(待ち・直列化を含む) | 8 回 | 159 | 87 | 197 | 297 | 297 |
手法別(件数, 1 件の秒): extract_method 34 件 53 秒、replace_with_lookup_table 3 件 118 秒、introduce_named_constant 3 件 119 秒、
consolidate_duplication 2 件 338 秒、introduce_parameter_object 1 件 237 秒、その他 1〜2 件で 27〜81 秒。
4.2 コメントからの換算(63 回)
| 集計 | 値 |
|---|---|
| 使えた時間 ÷ 計画で採った件数 | 2.3 分 |
| 使えた時間 ÷ 最終の採用件数 | 3.7 分 |
| 最終の採用 ÷ 計画で採った件数 | 0.62(取り消し 0.18) |
u = 3 分を 1 件の所要とする(計画で採った 1 件あたり 2.3〜2.7 分に、修正と待ちの余裕を少し足した値)。
4.3 計画が使う見積り(見送った行の「見積り X 分」)
| 期 | 1 件の見積り(中央値の範囲) |
|---|---|
| #989〜#2070 | 1.0〜4.6 分(多くは 1.1〜2.5 分) |
| #2092〜#2363 の scope で x が長い回(#2092・#2103・#2152・#2247・#2268・#2318・#2348・#2363) | 6.3〜12.9 分 |
| #2178・#2192・#2209(scope で x が 20〜46 秒) | 1.5〜2.2 分 |
commands/plan.py は item["estimate"]["verify"] = max(配分の verify, measured_verify) とし、budget.measured_verify_minutes は
着手前の範囲テスト全体の実測(mode が scope のとき)を返す。範囲テストが 500 秒なら 1 件ごとに 8.3 分の検証が載る。
実測の検証は 1 件 5〜50 秒(4.1)なので、この回たちでは見積りが実測の 3〜5 倍になり、予算の見送りを増やしている
(例: #2363 は A = 16.3 分で採用 3・時間の見送り 16、見積りは 9.4〜15.2 分)。
5. 式の候補
記号(分): x̂ = 着手前のテストの所要の見込み(今の s。範囲テストの履歴、無ければ w)、v̂ = 最終ゲートの確かめの見込み
(CI に任せる戦略は c、手元は w。直近の実測が大きければそれ)、F = 配分の fix、D = 範囲に入るプロダクションコードの変更行数。
候補 1(推奨): 着手前に D と T だけで決める
固定分(T) = x̂ + P + v̂ + 2F, P = 4.7 + 0.43·x̂
N(D) = clamp(4·log10(D), 6, 16) # D=100 → 8、300 → 9.9、1,000 → 12、3,000 → 13.9、10,000 以上 → 16
B = 固定分(T) + N(D) × u, u = 3
下限 = 固定分(T) + 3u(3 件は必ず入る)
上限 = min(固定分(T) + 16u, 120)
- 固定分は B に依らない(今の提案の枠 0.20·B・改修計画の枠 0.10·B・余裕 0.05·B は、B が固定分から決まるので循環しない形に置き換える必要がある)
- N(D) は「提案のうち採れる見込みの件数」。提案件数(14〜23 件)の約 6 割で、最終の採用率 0.62 とも合う
- 利用者が「実装に使える時間」を渡す cross-refactoring: 既定の予算を固定の分数でなく、テストの所要とコード量から決める #2202 の提案とは、
N(D) × uをその値で置き換えれば同じ形になる
候補 2: 提案の後に N を実際の提案件数で決め直す
B(着手時) = 候補 1 と同じ
B(計画時) = 固定分(T) + clamp(重複を除いた提案件数, 3, 20) × u # 改修計画の時点で上書き
D と提案件数の相関が弱い(ρ = 0.2〜0.3)ため、計画の時点で分かる提案件数を使うほうが当たる。そのかわり B は計画の時点まで確定しない
(リファクタリング計画に「着手時の見込み」と「計画時の確定値」の 2 つを載せることになる)。
6. 過去の各回への試算
方法: その回の実際の固定分(E + R)はそのまま、式の B から使えた時間 A' = B' − (E + R) を出し、A' − A の余りへ、
その回の時間で見送った項目をコメントの順(順位の順)に budget.select と同じく「入るものは入れ、入らないものは飛ばす」で詰めた。
見積りはコメントの「見積り X 分」(計画の単位)をそのまま使う。
| 式 | B の中央値 | B の p10〜p90 | 予算の見送り 712 件のうち入る件数 | 実際より B が小さくなる回 |
|---|---|---|---|---|
| 実際 | 30 | 30〜75 | — | — |
| 候補 1(u = 3) | 62.4 | 51〜72 | 456(64%) | 19 |
| 候補 2(u = 3) | 82.3 | 64〜90 | 570(80%) | 3 |
| 参考: 候補 1 で u をその回の見積りの中央値にした場合 | 52.1 | 40〜108 | 331(46%) | 18 |
| 参考: 候補 2 で u をその回の見積りの中央値にした場合 | 67.3 | 47〜180(上限) | 527(74%) | 4 |
期ごと(入る件数 / その期の予算の見送り、B の中央値):
| 期 | 見送り | 候補 1(u = 3) | 候補 2(u = 3) |
|---|---|---|---|
| #989〜#1374 | 159 | 106、62 分 | 121、76 分 |
| #1383〜#1732 | 34 | 10、55 分 | 20、78 分 |
| #1745〜#2070(B = 30 で A が 0.3〜8 分の回) | 373 | 301、63 分 | 365、85 分 |
| #2092〜#2363(scope、見積りが膨らんだ回) | 136 | 32、70 分 | 54、93 分 |
- スプリント m744 #1745〜スプリント s2065 #2070 は候補 1 でほぼ解消する(スプリント m744 #1745・スプリント m653 #1780・スプリント m1290 #1799・スプリント m1793 #1801・スプリント m1743 #1825 は見送り 12〜23 件がすべて入る)
- スプリント s2086 #2092 以降は予算を広げても入らない。 x が長い 8 回は、式の B(54〜79 分)が実際の B(52〜90 分)とあまり変わらず、増えた数分に 1 件 10 分前後の見積りが入らない(入る 32 件のうち 31 件は x が短い スプリント m2169 #2178・スプリント m2170 #2192・スプリント m2171 #2209)。4.3 の見積りを
「項目の範囲テストの実測(配分のverify)」へ直すことが式と同じくらい効く - 候補 1 が実際より B を小さくする 19 回は、B = 60〜90 で頭打ちにならなかった回(ミッション m1337 #1391〜スプリント m1385 #1732・スプリント m1914 #2133)。使えた時間の換算(2.3 分/件)で
1〜3 件ずつ(スプリント m1560 #1573 は約 10 件、スプリント m1914 #2133 は約 5 件)採れなくなる見込み。候補 2 ではこの損失は 3 回・各 1〜5 件に減る
6.1 各回の値
列: x・P・v・2F は分。D は範囲のコード行(ファイル数)。式の列は「B(分)/ 入る予算の見送りの件数」。
| PR | 戦略 | B | A | x | P | v | 2F | D | D ファイル | 提案 | 計画で採った | 最終の採用 | 時間の見送り | 見積り中央値 | 候補 1 | 候補 2 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| #951 | — | 30 | 16.13 | 1.1 | — | — | — | 7458 | 29 | 9 | 9 | 5 | 0 | — | — | — |
| #989 | — | 30 | 9.87 | 1.7 | 3.96 | 3.45 | 11.0 | 543 | 3 | 18 | 5 | 4 | 13 | 1.9 | 54.4 / 13 | 75.6 / 13 |
| #988 | — | 30 | 10.13 | 1.7 | 3.65 | 3.48 | 11.0 | 55 | 2 | 14 | 4 | 3 | 10 | 1.9 | 42.6 / 7 | 63.7 / 10 |
| #998 | — | 20 | 3.05 | 0.6 | 4.08 | 1.25 | 11.0 | 141 | 1 | 12 | 3 | 1 | 9 | 1.4 | 43.6 / 9 | 53.8 / 9 |
| #1230 | — | 30 | 9.12 | 1.8 | 4.41 | 3.65 | 11.0 | 1470 | 11 | 15 | 6 | 0 | 7 | 1.5 | 60.0 / 7 | 67.0 / 7 |
| #1255 | — | 30 | 8.68 | 1.9 | 4.7 | 3.75 | 11.0 | 35786 | 140 | 20 | 2 | 2 | 15 | 3.1 | 70.1 / 12 | 82.1 / 14 |
| #1300 | — | 30 | 5.09 | 2.3 | 6.94 | 4.65 | 11.0 | 11430 | 109 | 18 | 1 | 1 | 17 | 4.2 | 71.7 / 8 | 77.7 / 10 |
| #1302 | — | 30 | 7.64 | 2.1 | 5.19 | 4.12 | 11.0 | 510 | 8 | 19 | 1 | 1 | 17 | 4.4 | 55.2 / 5 | 79.8 / 11 |
| #1325 | — | 30 | 5.99 | 2.3 | 6.22 | 4.53 | 11.0 | 1363 | 14 | 25 | 1 | 0 | 24 | 4.6 | 61.1 / 6 | 83.5 / 11 |
| #1342 | — | 30 | 6.75 | 2.3 | 5.23 | 4.68 | 11.0 | 16090 | 275 | 14 | 1 | 1 | 13 | 4.6 | 71.7 / 8 | 65.7 / 7 |
| #1348 | — | 30 | 7.07 | 2.2 | 5.41 | 4.35 | 11.0 | 1768 | 15 | 22 | 4 | 4 | 18 | 1.5 | 62.1 / 17 | 83.2 / 18 |
| #1354 | — | 30 | 6.07 | 2.5 | 5.41 | 5.02 | 11.0 | 2506 | 34 | 13 | 1 | 0 | 12 | 3.6 | 65.1 / 7 | 63.3 / 7 |
| #1374 | local-full | 30 | 7.28 | 2.5 | 4.25 | 4.98 | 11.0 | 2158 | 25 | 17 | 3 | 2 | 14 | 1.5 | 64.3 / 14 | 75.2 / 14 |
| #1383 | local-full | 60 | 31.06 | 2.7 | 9.79 | 5.43 | 11.0 | 315 | 15 | 17 | 16 | 1 | 1 | 4.4 | 55.0 / 0 | 76.0 / 1 |
| #1391 | local-full | 60 | 45.29 | 2.8 | 4.64 | 5.58 | 1.7 | 850 | 17 | 16 | 16 | 0 | 0 | — | 51.1 / 0 | 64.0 / 0 |
| #1410 | local-full | 60 | 43.26 | 2.8 | 6.79 | 5.5 | 1.7 | 537 | 13 | 12 | 11 | 4 | 0 | — | 48.6 / 0 | 51.8 / 0 |
| #1445 | local-full | 60 | 42.0 | 3.2 | 6.6 | 6.4 | 1.8 | 1255 | 20 | 21 | 21 | 11 | 0 | — | 54.7 / 0 | 77.5 / 0 |
| #1452 | local-full | 60 | 40.36 | 3.3 | 7.84 | 6.67 | 1.8 | 1611 | 11 | 18 | 18 | 18 | 0 | — | 56.4 / 0 | 71.9 / 0 |
| #1469 | local-full | 60 | 43.96 | 3.3 | 4.37 | 6.58 | 1.8 | 354 | 6 | 18 | 11 | 9 | 0 | — | 48.4 / 0 | 71.8 / 0 |
| #1467 | local-full | 60 | 43.03 | 3.4 | 4.87 | 6.87 | 1.8 | 327 | 5 | 22 | 21 | 21 | 0 | — | 48.5 / 0 | 78.3 / 0 |
| #1506 | local-full | 60 | 38.19 | 3.7 | 8.49 | 7.43 | 2.2 | 1244 | 29 | 22 | 22 | 15 | 0 | — | 56.7 / 0 | 79.6 / 0 |
| #1520 | local-full | 60 | 42.11 | 3.7 | 4.62 | 7.4 | 2.2 | 961 | 6 | 24 | 23 | 21 | 0 | — | 55.4 / 0 | 79.6 / 0 |
| #1521 | local-full | 60 | 42.98 | 3.5 | 4.5 | 6.9 | 2.2 | 863 | 12 | 14 | 14 | 0 | 0 | — | 53.9 / 0 | 60.7 / 0 |
| #1542 | local-scoped-ci-whole | 30 | 5.84 | 2.1 | 4.08 | 6.97 | 11.0 | 181 | 4 | 15 | 1 | 1 | 14 | 3.4 | 52.8 / 6 | 70.7 / 11 |
| #1554 | local-scoped-ci-whole | 75 | 40.61 | 4.1 | 12.34 | 6.97 | 11.0 | 3741 | 33 | 19 | 7 | 7 | 12 | 4.6 | 71.4 / 0 | 85.5 / 1 |
| #1573 | local-full | 75 | 47.16 | 4.5 | 12.15 | 9.03 | 2.1 | 385 | 4 | 21 | 21 | 16 | 0 | — | 53.4 / 0 | 82.3 / 0 |
| #1581 | local-full | 75 | 48.61 | 5.4 | 5.64 | 10.7 | 4.7 | 1069 | 13 | 15 | 15 | 12 | 0 | — | 64.1 / 0 | 72.8 / 0 |
| #1663 | local-full | 60 | 30.52 | 5.3 | 8.78 | 10.67 | 4.7 | 555 | 18 | 26 | 23 | 16 | 3 | 1.9 | 60.6 / 0 | 87.7 / 3 |
| #1673 | local-full | 60 | 23.47 | 5.7 | 8.48 | 11.37 | 11.0 | 669 | 13 | 17 | 15 | 6 | 2 | 1.5 | 69.1 / 2 | 86.2 / 2 |
| #1701 | local-full | 60 | 35.68 | 5.0 | 7.61 | 9.97 | 1.8 | 775 | 19 | 21 | 21 | 16 | 0 | — | 58.2 / 0 | 83.6 / 0 |
| #1718 | local-full | 60 | 31.46 | 5.6 | 9.44 | 11.2 | 2.3 | 1161 | 20 | 31 | 28 | 18 | 2 | 1.8 | 63.0 / 2 | 86.2 / 2 |
| #1732 | local-full | 60 | 30.1 | 6.0 | 9.68 | 11.9 | 2.4 | 1140 | 24 | 22 | 22 | 0 | 0 | — | 64.2 / 0 | 87.5 / 0 |
| #1745 | local-full | 30 | 0.27 | 6.5 | 7.89 | 12.98 | 2.4 | 258 | 6 | 14 | 0 | 0 | 12 | 1.3 | 58.3 / 12 | 71.3 / 12 |
| #1763 | local-full | 30 | 2.04 | 5.7 | 8.54 | 11.37 | 2.4 | 1683 | 24 | 18 | 2 | 1 | 15 | 1.0 | 65.3 / 15 | 80.6 / 15 |
| #1780 | local-full | 30 | 0.94 | 6.7 | 6.57 | 13.42 | 2.4 | 1275 | 19 | 19 | 0 | 0 | 18 | 1.2 | 67.4 / 18 | 87.1 / 18 |
| #1799 | local-full | 30 | 0.7 | 6.7 | 6.75 | 13.45 | 2.4 | 866 | 16 | 22 | 0 | 0 | 22 | 1.2 | 65.4 / 22 | 90.1 / 22 |
| #1801 | local-full | 30 | 1.31 | 6.6 | 6.54 | 13.18 | 2.4 | 537 | 8 | 24 | 1 | 1 | 23 | 1.2 | 62.4 / 23 | 89.7 / 23 |
| #1825 | local-full | 30 | 0.92 | 6.7 | 6.51 | 13.47 | 2.4 | 2124 | 38 | 18 | 1 | 0 | 17 | 1.1 | 70.1 / 17 | 84.2 / 17 |
| #1842 | local-full | 50 | 21.33 | 9.6 | 7.17 | 9.57 | 2.4 | 987 | 8 | 28 | 17 | 16 | 11 | 1.1 | 66.3 / 11 | 90.3 / 11 |
| #1863 | local-full | 30 | 6.89 | 6.4 | 7.51 | 6.38 | 2.8 | 1203 | 22 | 24 | 6 | 6 | 18 | 1.2 | 60.0 / 18 | 83.0 / 18 |
| #1882 | local-full | 30 | 6.98 | 6.9 | 6.45 | 6.92 | 2.7 | 482 | 21 | 25 | 4 | 4 | 21 | 1.2 | 56.4 / 20 | 84.2 / 21 |
| #1904 | local-full | 30 | 7.41 | 6.6 | 6.65 | 6.6 | 2.7 | 753 | 16 | 29 | 5 | 5 | 24 | 1.4 | 58.0 / 18 | 83.5 / 24 |
| #1930 | local-full | 30 | 6.31 | 7.0 | 6.99 | 6.98 | 2.7 | 939 | 13 | 24 | 4 | 1 | 20 | 1.4 | 60.1 / 20 | 84.4 / 20 |
| #1951 | local-full | 30 | 8.3 | 7.2 | 4.54 | 7.23 | 2.7 | 489 | 6 | 16 | 5 | 4 | 11 | 1.4 | 57.2 / 11 | 73.0 / 11 |
| #1963 | local-full | 30 | 4.46 | 7.4 | 7.98 | 7.4 | 2.8 | 1258 | 42 | 23 | 2 | 2 | 21 | 1.6 | 62.6 / 19 | 85.4 / 21 |
| #1973 | local-full | 30 | 2.69 | 7.7 | 9.15 | 7.7 | 2.8 | 1295 | 23 | 31 | 1 | 1 | 30 | 1.9 | 63.5 / 17 | 86.2 / 28 |
| #1996 | local-full | 30 | 3.28 | 7.7 | 8.58 | 7.72 | 2.7 | 1057 | 23 | 25 | 1 | 1 | 24 | 2.2 | 62.4 / 14 | 86.2 / 24 |
| #2024 | local-full | 30 | 5.04 | 7.6 | 7.01 | 7.62 | 2.7 | 1565 | 18 | 28 | 3 | 0 | 25 | 2.1 | 64.3 / 15 | 85.9 / 25 |
| #2034 | local-full | 30 | 4.11 | 7.4 | 8.44 | 7.37 | 2.7 | 1318 | 30 | 29 | 2 | 0 | 27 | 2.1 | 62.8 / 15 | 85.3 / 25 |
| #2043 | local-full | 40 | 14.97 | 8.4 | 5.27 | 8.38 | 3.0 | 33 | 11 | 12 | 5 | 0 | 6 | 2.5 | 46.3 / 2 | 64.1 / 6 |
| #2053 | local-full | 60 | 33.93 | 8.0 | 7.03 | 8.02 | 3.0 | 1358 | 25 | 29 | 15 | 0 | 14 | 2.6 | 64.8 / 1 | 87.2 / 10 |
| #2070 | local-full | 30 | 7.69 | 7.7 | 3.97 | 7.7 | 2.9 | 1587 | 9 | 16 | 2 | 0 | 14 | 2.5 | 64.8 / 13 | 74.4 / 14 |
| #2092 | local-scoped-ci-whole | 60 | 25.09 | 6.2 | 6.66 | 11.08 | 11.0 | 24 | 5 | 14 | 12 | 11 | 2 | 10.2 | 53.6 / 0 | 77.6 / 1 |
| #2103 | local-scoped-ci-whole | 60 | 34.1 | 5.6 | 6.93 | 11.08 | 2.3 | 1851 | 16 | 35 | 14 | 14 | 17 | 6.3 | 65.3 / 0 | 86.1 / 4 |
| #2133 | local-full | 90 | 40.54 | 9.9 | 18.64 | 9.92 | 11.0 | 447 | 14 | 10 | 10 | 10 | 0 | — | 71.6 / 0 | 69.8 / 0 |
| #2152 | local-scoped-ci-whole | 90 | 53.58 | 8.3 | 6.89 | 10.27 | 11.0 | 295 | 7 | 21 | 14 | 14 | 7 | 9.6 | 67.4 / 0 | 97.8 / 0 |
| #2178 | local-scoped-ci-whole | 30 | 6.85 | 0.7 | 4.89 | 10.27 | 7.3 | 245 | 1 | 15 | 7 | 6 | 8 | 2.2 | 51.9 / 7 | 68.3 / 8 |
| #2192 | local-scoped-ci-whole | 30 | 5.09 | 0.8 | 5.52 | 13.4 | 5.2 | 2280 | 34 | 23 | 3 | 3 | 20 | 2.0 | 64.7 / 10 | 84.4 / 18 |
| #2209 | local-scoped-ci-whole | 30 | 5.69 | 0.3 | 5.17 | 13.57 | 5.2 | 1337 | 19 | 18 | 3 | 0 | 15 | 1.5 | 61.5 / 14 | 78.0 / 15 |
| #2247 | local-scoped-ci-whole | 70 | 30.97 | 10.9 | 9.63 | 13.28 | 5.2 | 1170 | 44 | 23 | 4 | 4 | 19 | 11.6 | 75.6 / 0 | 98.8 / 2 |
| #2268 | local-scoped-ci-whole | 75 | 36.65 | 10.9 | 8.97 | 13.28 | 5.2 | 2399 | 48 | 26 | 12 | 10 | 14 | 12.9 | 79.3 / 0 | 98.7 / 1 |
| #2318 | local-scoped-ci-whole | 75 | 40.05 | 8.4 | 7.59 | 15.37 | 3.6 | 1589 | 34 | 20 | 15 | 0 | 5 | 12.4 | 74.1 / 0 | 95.7 / 1 |
| #2348 | local-scoped-ci-whole | 75 | 42.6 | 7.9 | 5.54 | 15.37 | 3.6 | 833 | 16 | 24 | 11 | 11 | 13 | 9.9 | 70.0 / 0 | 95.0 / 1 |
| #2363 | local-scoped-ci-whole | 52 | 16.25 | 8.5 | 8.44 | 15.37 | 3.4 | 1596 | 17 | 19 | 3 | 3 | 16 | 10.4 | 74.1 / 1 | 92.7 / 3 |
7. データの欠け・外れ値・仮定
- 件数の差。 cross-refactoring: 既定の予算を固定の分数でなく、テストの所要とコード量から決める #2202 は 103 回と書くが、取得できた計画のコメントは 108 件(2026-09-06〜11-01)。うち時間の記録があるのは 64 件で、
cross-refactoring: 既定の予算を固定の分数でなく、テストの所要とコード量から決める #2202 の表の 54 回(10.17.8〜)とも数え方が違う。cross-refactoring: 既定の予算を固定の分数でなく、テストの所要とコード量から決める #2202 の回数は版で区切っており、本分析は PR 番号で区切った - cross-refactoring を想定最大時間に収める 1 回の計画実行へ改める(#933 実装) #951 は内訳なし。 時間の上限の表が旧形式(final_fix の行が無い)で R を逆算できない
- 逆算の仮定。 R = (H − fix_end) + F は「検証の修正の枠 = 最終ゲートの修正の枠 = 配分の fix」(
budget.reserve)に依る。
floor で上げた回(検査のプランの構造改善が既定の予算で下限に届かず、33 行の差分でも refactor が落ちて abort へ進む #2047 の仕組み)は、コメントの B が上げた後の値なので、上げる前の B は分からない - D の外れ値。 ミッション m1142b #1255(35,786 行)・ミッション m1323 #1342(16,090 行)・ミッション m1142c #1300(11,430 行)・cross-refactoring を想定最大時間に収める 1 回の計画実行へ改める(#933 実装) #951(7,458 行)は生成物・移動を含む大きな PR。
相関は Spearman(順位)で見たので影響は小さい。N(D) は 16 件で頭打ちにしてある - D の着手前の HEAD の推定。 時間の記録が無い 44 件は commits の題から推定した(リファクタリングの題の形が違う回は過大になりうる)。主な分析(64 件)はコメントの HEAD を使った
- 差分の範囲。 「対象範囲」の項目をパスの前方一致で判定した。テストの判定は名前の規則によるため、
tests/の外の検査用スクリプトはプロダクションコードに数えている - 1 件の所要の標本が少ない。 配分の履歴の実行の行は 8 回(スプリント m2087 #2152〜スプリント lroot-2 #2363、実装担当はすべて claude)。kinds の秒は CLI の申告に近い値で、
手順の壁時計(implement の 920〜1,865 秒)より小さい。u = 3 分は壁時計側(4.1 の最下行と 4.2)から取った - 試算の仮定。 「入る件数」は、増えた時間で計画が採れたはずの件数であり、採った項目が最後まで採用される保証ではない(最終の採用率は 0.62)。
実装担当の並列・修正の回数・最終ゲートの失敗は考えていない。採り直し(readopt)で実際に後から採られた分も差し引いていない - ai-plugins だけのデータ。 他のリポジトリ(cross-refactoring: 既定の予算を固定の分数でなく、テストの所要とコード量から決める #2202 の novel など)の x・c は大きく違う。式は T を入力に持つので形はそのまま使えるが、
P = 4.7 + 0.43·x̂ の係数は ai-plugins の当てはめ - 予算の外の時間。 着手前のテストの打ち切りと打ち直し(2.3)は記録上の開始より前で、本分析の固定分に入っていない
Activity
takemi-ohama commentedon Oct 31, 2026
同じ事象を PR #2247 の作業中に確認した。
takemi-ohama commentedon Oct 31, 2026
同じ事象を PR #2250 の作業中に確認した。
[-]cross-refactoring: 既定の予算を全体の 30 分でなく「実装に使える時間」で指定し、固定でかかる時間を実測から足す[/-][+]cross-refactoring: 既定の予算を固定の分数でなく、テストの所要とコード量から決める[/+]takemi-ohama commentedon Nov 3, 2026
#2457 へ統合した(2026-11-03、利用者の指示)。予算はコーディング時間だけを数えて選定にだけ使い、予算を理由に打ち切らない。この Issue の記録と実績の分析は #2457 から参照する。