optimize-loop について
optimize-loopは、動作と結果を保ったままコードやSQLを最適化するスキルです。正しさのゲートと指標を組み合わせ、ゲートを通過して指標が改善した変更だけを残します。
主な機能
- 01設定可能な正しさのゲートと指標
- 02コードリファクタリングとSQL調整モード
- 031回につき1つの変更
- 04スナップショット、復元、台帳記録
- 05停滞または反復上限で停止
活用シーン
- 01テストを通しながらコードの複雑さを減らす
- 02結果セットを保ってSQLの実行時間を短縮
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ gaasher/ agent-loop-skills --skill optimize-loopインストール後、Claude Code で/optimize-loopを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
examples/refactor.run.yamlsql.run.yamltools/bench.pymetrics.py詳細
最適化ループ
差し替え可能な正しさゲート+最小化するメトリクスを備えた評価器・最適化器ループです。成果物は編集可能なもの(コードモジュールや SQL クエリ)で、フィードバックシグナルは 2 つの要素から成ります。必ず通過しなければならないバインド済みゲート(動作/結果が変わらないこと)と、値を下げなければならないバインド済みメトリクス(最小化するコスト)です。変更を 1 つ適用し、ゲートを確認して、メトリクスを測定します。ゲートに合格し、かつメトリクスが改善した場合にのみ変更を保持し、それ以外の場合は元に戻します。メトリクスの改善が止まるか、予算が尽きるまで繰り返します。ループが始まったら、許可を求めて中断しないでください。
すぐに使える 2 つのバインディングが tools/ に同梱されています(どちらもベンダー提供で、標準ライブラリのみを使用します)。
- code mode — ゲート:
<gate_cmd>(テストスイート)が終了コード 0 で終了すること。メトリクス:tools/metrics.pyがcomplexity(主指標)、max_nesting、loc(辞書順のタイブレーカー)を出力します。値は小さいほど良好です。 - sql mode — ゲート:
tools/bench.pyの結果セットのhashがベースラインと一致すること。メトリクス:同じツールのmedian_msです。値は小さいほど良好です。
どちらのモードでも、ゲートは譲れません。ゲートに失敗した変更は改善ではなく、リグレッションです。グラウンドトゥルース(code mode ではテスト/tools/metrics.py、sql mode ではデータベース/tools/bench.py)は絶対に編集しないでください。測定対象を編集して数値を動かしても、ループの目的を損ないます。
使用する場面
維持すべき明確な正しさの制約と、最小化する数値がある場合に使用します。たとえば、テストスイートに合格しているコードのリファクタリング(複雑さを減らす)や、結果セットが固定された SQL クエリの調整(レイテンシを減らす)です。デフォルトでは、同梱されている対応ツールを使用します。代替手段として、合格時に終了コード 0 を返す任意の <gate_cmd> と、最小化する単一の数値を出力する任意の <metric_cmd> をバインドできます(例:リンターの問題数、または SQL 以外のエンジンでの実行時間+結果フィンガープリント)。機能の追加やバグ修正には使用しないでください。こうした変更は動作を変えることを意図しており、このループはそれを防ぐためのものです。
セットアップ
バインディングは対話的に解決します。 作業ディレクトリに loop.run.yaml が存在する場合は読み込み、値を 1 行で復唱して確認を取り、ループに進みます。存在しない場合は、まず <mode> を選択します(ゲートとメトリクスが決まります)。次に、Claude Code では(AskUserQuestion ツールを利用できます)、各バインディングの候補値を推定して推奨オプションとして提示します。それ以外の環境では、それぞれを引用符付きのプレーンテキストのプロンプトで尋ねます。その後、loop.run.yaml を書き込み、他のファイルを作成する前に値を確認します。
<gate_cmd> と <metric_cmd> は差し替え可能な中核部分です。表に従って <mode> ごとにバインドします。sql mode では 1 つのベンチマークコマンドが両方を提供します。hash がゲート、median_ms がメトリクスです。
| binding | 意味 | デフォルト | 推定方法 |
|---|---|---|---|
<mode> | code(テスト対象のリファクタリング)または sql(結果が固定されたクエリ) | — | 成果物の種類 |
<editable_files> | ループで変更可能なファイル | — | code:ソースファイル(テスト/設定/ツール以外)。sql:クエリファイル(+任意のインデックスファイル) |
<gate_cmd> | 必ず合格しなければならないバインド済みゲート。不合格なら元に戻す | — | code:テストコマンド(合格時に終了コード 0)。sql:暗黙 — 候補の hash が、ベンチマークコマンドのベースライン hash と一致すること |
<metric_cmd> | 最小化する数値を出力するバインド済みメトリクス | — | code:python3 <skill_dir>/tools/metrics.py <editable_files>(→ complexity、次に max_nesting、loc)。sql:python3 <skill_dir>/tools/bench.py --db <db> --query <query_file> --setup <indexes_file> --repeat 5(→ median_ms、hash) |
<sandbox_root> | スナップショットと台帳の保存先 | ./sandbox | — |
<budget> | 最大反復回数(上限) | 8 | — |
<patience> | 改善のない反復が連続 N 回に達したら停止 | 3 | — |
<skill_dir> はこのスキルがインストールされているフォルダーです。loop.run.yaml に書き込む際は、実際のパスに置き換えてください。
デフォルト以外のエンジン/言語では、上記の要件を満たす任意の <gate_cmd>/<metric_cmd> をバインドしてください。
設定例は examples/refactor.run.yaml(code)と examples/sql.run.yaml(sql)の 2 つです。
停止条件に達するまで(停滞または <budget>)
このチェックリストをコピーして、項目を確認してください。
- イテレーション 0 — ベースライン:
<gate_cmd>(コード)を実行します — 成功しない場合は停止します(動作を保護するには、ループの開始時点でゲートを通過している必要があります)。<metric_cmd>を実行し、メトリクスを現時点の最良値として記録します。sql モードでは、ベースラインのhashを正しさの基準として記録します。ベースラインの行を記録します。 -
<editable_files>内のすべてのファイルのスナップショットを<sandbox_root>/iter<N>/に保存し、このイテレーションを元に戻せるようにします。 - 焦点を絞った変更を1 つ適用します(モードごとのアイデアは以下を参照してください)。各メトリクスの変化を特定できるよう、イテレーションごとにアイデアを 1 つだけ試します。
- ゲートを確認します。コードの場合は
<gate_cmd>を実行し、sql の場合は<metric_cmd>から候補のhashを読み取ります。 - ゲートに失敗した場合(テストが 0 以外を返す/
hashがベースラインと異なる/ツールでエラーが発生した場合)は、変更を破棄します。スナップショットから復元し、理由を記録して続行します。 - メトリクスを測定し、最良値と比較します。コードの場合は、トリプル
(complexity, max_nesting, loc)を辞書順で比較します(まず complexity を比較し、同値の場合にのみmax_nesting、続いてlocを参照します)。sql の場合はmedian_msを比較し、計測ノイズを明確に上回る差がある場合のみ採用します(デフォルトは相対値で 3% 以上)。 - メトリクスが最良値を厳密に上回る場合は採用します(最良値を更新し、ファイルはそのままにします)。それ以外の場合は破棄します(スナップショットから復元します)。
- 台帳に行を追加し、停滞(
<patience>)または<budget>に達したら停止します。
変更のアイデア — コードモード: ネストした if/else をガード節に整理する、手書きのループを標準ライブラリの呼び出し(sum、min、max、statistics.*)に置き換える、重複した分岐をまとめる、不要なコードを削除する。公開されている動作(名前、シグネチャ、戻り値の形、発生する例外)は維持してください。テストスイートが契約です。
変更のアイデア — sql モード: 絞り込み/結合/グループ化された列をカバーするインデックスを <indexes_file> に追加する、クエリを書き換える(相関サブクエリ → JOIN + GROUP BY、繰り返し計算の共通化、SELECT * を必要な列の指定に置き換える、絞り込みを前倒しする、不要な DISTINCT/ソートを削除する)。hash は行の多重集合を対象とするため、行の順序の変更は検出できません。ORDER BY が契約の一部である場合は、書き換え後も順序が保たれていることを目視で確認してください。
辞書順での採用(コードモード)、現在の最良値 (18, 3, 64): (15, 3, 45) は採用(complexity が低い);(18, 2, 70) は採用(complexity は同値で、ネストが少ない);(18, 3, 61) は採用(同値で、行数が少ない);(18, 3, 64) は破棄(進展なし);(19, 1, 20) は破棄(ネストや loc が単純でも、complexity の増加が優先されます)。
停滞のカウント: 最良値を更新しなかったイテレーションはすべて(ゲート失敗、変更の不具合、メトリクスの改善不足による破棄を含む)、改善なしカウンターを 1 増やし、採用のたびに 0 にリセットします。改善のないイテレーションが <patience> 回連続すると実行を終了します。<budget> はハード上限です。停止時に、作業ファイルが最良のイテレーションの状態になるよう復元します(最新の変更が破棄された場合)。ベースラインと最良値のメトリクス(sql モードでは速度向上率も)、推移、採用された変更一式を報告してください。予算に達する前にアイデアが尽きた場合は、早めに停止せず、さらに検討してください。
台帳
<sandbox_root>/ledger.tsv はタブ区切りとし、説明にカンマを使わないでください。status は {keep, discard, baseline} のいずれかです。使用中の <mode> に応じた列を使用してください。
コードモードのヘッダー iter complexity max_nesting loc status description:
iter complexity max_nesting loc status description
0 23 7 86 baseline unmodified module
1 19 5 78 keep flatten summarize guard clauses
2 19 5 80 discard extract helper (no complexity gain)
3 13 3 40 keep use statistics + min/max/median
SQL モードのヘッダー iter median_ms rows hash_ok status description(hash_ok は {yes,no,-} のいずれか):
iter median_ms rows hash_ok status description
0 1121.06 10 - baseline correlated subquery no index
1 6.82 10 yes keep rewrite correlated subquery as JOIN + GROUP BY
2 1.18 10 yes keep add index orders(customer_id, amount)
4 0.40 10 no discard drop ORDER BY — changed result set
最後とは限らないため、最良のイテレーションを報告してください。
制約
- 編集するファイルは
<editable_files>内に限ってください。ゲートの正解基準は読み取り専用です。コードの場合はテストとtools/metrics.py、SQL の場合はデータベースとtools/bench.pyです。数値を動かすために測定方法を編集すると、実行は無効になります。 - 正確性ゲートに妥協はありません。ゲートに失敗する変更(テストが失敗する、または
hashがベースラインと異なる)は最適化ではなく回帰です。メトリクスにかかわらず元に戻してください。動作を変更した後にゲートを通過した場合、ゲートが不十分なのであって、変更が安全という意味ではありません。脆弱なゲートを信頼するより、動作を同一に保つことを優先してください。 - メトリクスの差分を個別の変更に帰属できるよう、1回の反復につき変更は1つにしてください。
- 候補はすべて同じ方法で測定してください(コードでは同じ
<gate_cmd>、SQL では同じ--repeat)。単発のノイズの多い実行ではなく、メトリクスを比較してください。 - 変更は既存の依存関係の範囲内にとどめてください。プロジェクトにないインポートを追加しないでください(標準ライブラリは問題ありません)。
- サンドボックスは自己完結型です。指定された
<sandbox_root>の外へ../で抜けないでください。 - 続行するかどうかを尋ねるためにループを中断しないでください。収束するか、予算に達するまで実行してください。