turn-eta — ターン完了時刻を予測し、実際にかかった時間から学習する
作業を始める前に、ステップを番号付きリストとして書き出し、いつ終わるかを宣言します。各ステップが完了した時点で計測し、ターン終了時には実際の終了時刻を返信の最後に記載します。次の推定時にはそのログを読み込みます。
実行タイミング
実作業を含むすべてのターン — ファイル編集、コマンド実行、コードベース検索など。
- ターンに作業が含まれる場合 → 着手する前に
planを呼び出し、返信の先頭にその出力を、出力順に配置します:最初に**ETA …**行を単独で、その後に番号付きステップ。終了時刻が読者が求めている情報であり、ステップ一覧はその根拠です。各ステップが完了するたびにstep <id>を呼び出し、ターンの作業がすべて完了したらdone <id>を呼び出します。 - 最終段落も時刻情報であり、何がまだ実行中かによって内容が変わります。
- 返信を書く前にすべての作業が完了している場合 →
doneが出力するブロック全体:終了行はdoneからの終了時刻。その時点でETAは期限切れになっています。ETAを再掲すると、読者に時計がすでに否定した推測を渡すことになり、代わりに各ステップの所要時間がどこがずれたかを示します。 - 何かがまだ実行中の場合(バックグラウンドジョブ、委任タスクなど) → 予測:
**ETA 17:45**。返信を書く時点で再計算し、planが以前出力した数字をそのまま貼り付けないでください。
- 返信を書く前にすべての作業が完了している場合 →
- 会話のみのターン(質問に答える、何を作るか決めるなど) → 何もしない。ノイズです。
- 一行の修正にもこの儀式は不要です。複数のステップがある場合に使用してください。
コマンド
ピュアNode、インストール不要。スキルがインストールされている場所から呼び出します。
# 作業前 — ステップに名前を付け、ETAを取得
node <skill>/scripts/eta.js plan \
"再現手順の確認" "日付パーサーの修正" "フィクスチャの更新" "テストスイートの再実行" \
--provider anthropic --model claude-opus-5 --size M
# **ETA 17:45** (14分)
#
# 1. 再現手順の確認
# 2. 日付パーサーの修正
# 3. フィクスチャの更新
# 4. テストスイートの再実行
#
# 4ステップ、約14分 (anthropic/claude-opus-5 M で 3.5分/ステップ、6ターン)
#
# (直近6回の推定は3分長く見積もっていました)
# ターンID: 48i35qek
# 各ステップが完了するたび — 計測し、残りを実測ペースから再予測
node <skill>/scripts/eta.js step 48i35qek
# 2/4 日付パーサーの修正 — 8分06秒
#
# **ETA 17:49** (4分後)
# ターンの作業がすべて完了したとき
node <skill>/scripts/eta.js done 48i35qek
# **FINISHED 17:48** (推定14分 / 実績17分)
# 現在のログの内容を表示
node <skill>/scripts/eta.js stats
ステップは数だけでなく名前を付けてください。 plan は数字だけを拒否します。誰も確認できない数字は計画ではありません。名前付きのステップがあれば、読者は作業開始前に「3番を飛ばして」と言えます。その番号付きリストを返信の先頭に置き、その後で作業を行ってください。
必ず自身の --provider と --model を指定してください。 シェルはどのモデルが駆動しているか認識できません。自分自身を識別する識別子を使用してください — --provider anthropic --model claude-opus-5、--provider openai --model gpt-5-codex、--provider google --model gemini-3-pro など。指定がない場合は unknown/unknown として記録されますが、それでも動作はしますが、すべてのモデルが同一のプールにまとめられます。
--size は S(小さな修正)、M(通常、デフォルト)、L(大きな変更)です。大まかで構いません。小さなターンが大きなターンの平均を引きずらないようにするためのものです。
ターンIDは必須です。 plan が出力するIDを、すべての step および最終の done まで引き継いでください — step 48i35qek、done 48i35qek。同じプロジェクトで作業している別のエージェントも同じログに書き込むため、IDなしの呼び出しは以前は開いているターンを無理やり閉じる可能性がありました — それが他人のターンである場合も含みます。step と done はIDなしでは拒否するようになりました。4時間以上誰も触れていないターンは放棄されたものとみなします。
ログの保存場所
<プロジェクトルート>/.eta/<provider>/<model>/log.tsv
プロジェクト内に保存されるため、エージェントの権限が作業ディレクトリに制限されていても、自身の履歴を読み取ることができます。プロジェクトルートは最も近い上位の .git ディレクトリ、なければカレントディレクトリです。Provider と Model はフォルダとして分けられるため、あるモデルのペースが別のモデルのものに静かに混ざることはありません。
.eta/ を .gitignore に追加してください。これはあなたのマシンとあなたのターンの計測値であり、他の誰にとっても意味がなく、ターンごとに変化します。
TURN_ETA_DIR に別の .eta ディレクトリを設定すると、複数のプロジェクト間で履歴を共有できます。これはローカルのログが十分な情報を持たない場合にのみ参照されます。
推定が改善される仕組み
done は推定値、実績値、各ステップの所要時間を記録します。plan はそれらを読み戻し、ステップあたりの中央値(分) を計算します。最も狭い一致から外側に向かって進み、完了ターンが3つ以上ある最初の階層で停止します:
- 同一プロバイダ + 同一モデル + 同一サイズ
- 同一プロバイダ + 同一モデル
- 同一プロバイダ、任意のモデル
- このプロジェクトの
.eta内のすべて TURN_ETA_DIRの共有ログ、同じ順序- それ以外はステップあたり4分
平均ではなく中央値を使用するため、1つのターンが長引いても将来のすべての推定に影響を与えません。各階層の直近20ターンのみをカウントします。plan は使用した階層を表示するため、数値が謎のままになることはありません。
ターン途中では、step はその履歴と、このターンで実際に経過しているペースをブレンドします。重みはターンの進行度に基づきます:4ステップ中1ステップ完了時点では履歴がまだ3/4を担い、3ステップ完了時点ではこのターンが3/4を担います。1つの遅い最初のステップが終了時刻を大きく狂わせることはありません。