experiment-queue について
experiment-queueは、SSH経由でリモートGPUサーバー上の機械学習実験を一括管理するスキルです。パラメーターグリッドや複数シード、段階的なジョブ向けに、マニフェストと状態管理を使い、OOM再試行、古いセッションの整理、ウェーブ切り替えを行います。
主な機能
- 01マニフェスト、グリッド、自然言語からジョブを作成
- 02SSH経由でリモートGPUサーバー上のジョブを実行
- 03ジョブ状態を追跡しキュー状態を保存
- 04OOMを検出して遅延後に再試行
- 05古いセッションを整理してウェーブを切り替え
- 06教師・学生フェーズ間の依存関係に対応
活用シーン
- 01複数シードの実験グリッドを並列実行
- 02段階的な実験をウェーブ単位で実行
- 03教師モデルの学習後に学生ジョブを起動
- 04OOMで失敗したジョブを再試行
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ wanshuiyin/ auto-claude-code-research-in-sleep --skill experiment-queueインストール後、Claude Code で/experiment-queueを入力して読み込まれたか確認します。
同梱ファイルscripts/build_manifest.pyscripts/queue_manager.py
詳細
実験キュー
⏱ 外部の実行間隔:可視性のみ。 このスキルはすでに、切り離されたサーバー側スケジューラー(60秒ごとのポーリング+
depends_on+ウェーブ遷移)を独自に実行しています。 夜間の状況確認(完了 N 件/実行中 N 件/保留中 N 件)には、ステータス出力を使用してください。2つ目の/loop/CronCreateポーリングで囲まないでください。 調整されていない時計でスケジューラーが重複し、これを防ぐために実装されたウェーブ遷移ロジックと競合します。詳しくはshared-references/external-cadence.md(「既存のスケジューラーを重複させないでください」)を参照してください。
適切な状態追跡、OOM 再試行、古いプロセスのクリーンアップ、ウェーブ遷移を行いながら、SSH 接続したリモート GPU サーバー上で大規模な ML 実験をオーケストレーションします。
このスキルを使用する場面
/run-experiment では不十分な場合に使用します。
- GPU 間でバッチ処理する必要がある 10 件以上のジョブ
- 複数シードのスイープ(例:21 シード × 12 セル)
- ウェーブ遷移(ウェーブ 1 を実行して待機し、ウェーブ 2 を実行して待機し、ウェーブ 3 を実行する……)
- 教師+生徒の連鎖(教師を学習してから蒸留し、教師の完了後に生徒を自動起動)
- GPU の変更や待機による再試行が必要な OOM が発生しやすい設定
- 失敗したセルを再実行する必要がある 混合シードグリッド
次の場合は使用しないでください。
- 単発のアドホックな実験(
/run-experimentを使用) - Modal/Vast.ai へのデプロイ(それぞれ独自のオーケストレーションがあります)
- 実行間に手動で確認する必要がある実験
このスキルがある理由
2026-04-16 のセッション監査に基づくと、複数シードのグリッド実験で実時間を大きく消費する主な要因は次のとおりです。
- 古い screen プロセス — python が終了し、wandb のアップロードも完了しているのに screen が残り、次のウェーブを妨げる
- 共有 GPU 上の OOM — 前のジョブのメモリがまだ解放されていない
- ウェーブの競合 — 前のウェーブが完全に収束する前に新しいウェーブが起動する
- チェックポイントの欠落 — 教師の保存前に生徒が起動する
- パーサーの重複 — バッチごとに複数シード分析用の python を書き直す
これらはいずれも、オーケストレーションで解消できる純粋なエンジニアリング上の摩擦です。
基本概念
環境の前提条件:キュージョブは、
../shared-references/compute-env-contract.md(spec-hash 台帳+カーネルの証跡)に従って、対象環境がすでに構築・検証済みであることを前提とします。ジョブのウェーブが import 時点で停止する場合、それは環境の前提条件が満たされていないことを意味し、キューの不具合ではありません。再度キューに登録する前に、プロバイダーの.aris/compute/<provider>.md台帳を確認してください。
ジョブマニフェスト
マニフェストには、明示的な状態とともにジョブを記載します。
project: my_grid_experiment
cwd: /home/user/your_project
conda: my_env
# Optional: override conda hook path if conda is not at a standard location.
# Can be a bare path (wrapped automatically) or a full `eval "$(... shell.bash hook)"` string.
# Falls back to auto-detect of ~/anaconda3, ~/miniconda3, /opt/anaconda3, etc.,
# or the ARIS_CONDA_HOOK environment variable.
# conda_hook: /custom/path/to/conda
ssh: gpu-server
default_cmd: >
python run_distill.py --backbone softmax --lam 0.5
--K 500 --L 96 --W 16 --n_steps 30000 --batch_size 128 --lr 1e-4
preconditions:
- type: checkpoint_exists
path: checkpoints/transformer/teacher_L96_K500_N{N}.pt
gpus: [0, 1, 2, 3, 4, 5, 6, 7]
max_parallel: 8
gpu_free_threshold_mib: 500 # optional, default 500; raise for shared servers, lower for tight packing
oom_retry:
delay: 120
max_attempts: 3
jobs:
- id: s200_N64_n50K
args: {seed: 200, n_hidden: 64, n_train_subset: 50000, subset_seed: 2024}
- id: s200_N128_n50K
args: {seed: 200, n_hidden: 128, n_train_subset: 50000, subset_seed: 2024}
# ... 14 more
ジョブの状態遷移
pending → running → completed
↘ failed_oom → pending (after delay) [retry up to N]
↘ failed_other → stuck (needs manual inspection)
stale screen (process gone, screen lingering) → failed_other → stuck
stuckに関するオペレーター向け注意事項(キューではなく、エージェントの対応): キューはfailed_otherジョブを決定論的にstuckとして保留します。この部分はコードであり、変更されていません。stuckバッチを人間に引き継ぐ前に、運用エージェントは次を確認してください。同じ失敗が複数のジョブで繰り返される場合は、エージェントが生成したラッパー/試行スクリプトのみを対象に、一度だけクリーンな再実装を試してください。ユーザー/プロジェクトのソース(自分で作成していないrun_*.py)、マニフェスト、キューの状態、ログ、結果には決して手を加えないでください(shared-references/external-cadence.mdの 壊れた試行を単に修正するのではなく、再起動する を参照)。人間への引き継ぎは、単に試行コードが壊れている場合ではなく、契約や環境に疑問がある場合に限ってください。
ウェーブのオーケストレーション
「ウェーブ」とは、利用可能な GPU に収まるジョブのバッチです。次のウェーブは、以下のすべてを満たした場合にのみ開始します。
- 現在のウェーブのすべての python プロセスが終了している
- 現在のウェーブのタグに対応する古い screen プロセスが残っていない
- GPU メモリがしきい値以下(≤500 MiB)になっている
- 次のウェーブのジョブの前提条件チェックに合格している
ワークフロー
ステップ 1:マニフェストを解析する/グリッドから構築する
入力には次の形式を使用できます。
- YAML マニフェスト(ジョブリストを明示する形式。複雑なケースに推奨)
- グリッド仕様(パラメーター値の直積。例:
N=[64,128,256] × n=[50K,150K,500K,652K]) - 自然言語による説明(Claude がマニフェストに変換)
実行識別子を一度だけバインドし、以降のすべての手順(マニフェストの保存、scp、起動、監視、再開)で同じパスを参照するようにします。マニフェストを生成する前に、これらをローカルのシェル変数として設定します。
# REPLACE the placeholder path before running, or pre-export PROJECT_DIR:
PROJECT_DIR="${PROJECT_DIR:?set PROJECT_DIR to the local project root}"
RUN_TS=$(date -u +%Y%m%dT%H%M%SZ) # one timestamp per run, reused everywhere
LOCAL_RUN_DIR="$PROJECT_DIR/experiment_queue/$RUN_TS"
mkdir -p "$LOCAL_RUN_DIR"
再現性を確保するため、作成したマニフェストを $LOCAL_RUN_DIR/manifest.json に保存します。
ステップ 2:事前確認
- SSH 接続が機能することを確認します
- リモートに conda 環境が存在することを確認します
- リモートに
cwdが存在することを確認します - すべての前提条件(チェックポイント、入力ファイル)を確認します
- GPU が利用可能であること(少なくとも
max_parallel個の GPU が空いていること)を確認します
前提条件を満たさない場合は、ブロックされているジョブとその理由をユーザーに提示します。
ステップ 3:スケジューラーを起動する
正式なスケジューラーの実装は skills/experiment-queue/scripts/queue_manager.py にあります(Phase 3.3 の移行、Arch C)。tools/experiment_queue/queue_manager.py は、レガシーのリゾルバーチェーンとの互換性を保つために残されている Python の os.execv シムになりました。起動前に 3 つの準備を行います。
3a. ローカルのヘルパーディレクトリを解決する。 2 つのヘルパー(queue_manager.py、build_manifest.py)は、現在 ARIS リポジトリ内の skills/experiment-queue/scripts/ にあり、レガシーのリゾルバーレイヤー向けに tools/experiment_queue/ にシムが配置されています。スキルがどのプロジェクトレイアウトでも動作するように、次のハイブリッドチェーンを使用します。
# Layer 0: self-contained (CC 1.0+ exposes $CLAUDE_SKILL_DIR).
QUEUE_TOOLS=""
if [ -n "${CLAUDE_SKILL_DIR:-}" ] && [ -f "$CLAUDE_SKILL_DIR/scripts/queue_manager.py" ]; then
QUEUE_TOOLS="$CLAUDE_SKILL_DIR/scripts"
fi
# Layers 1-4: legacy chain via tools/experiment_queue/ shims.
if [ -z "$QUEUE_TOOLS" ]; then
cd "$(git rev-parse --show-toplevel 2>/dev/null || pwd)" || exit 1
if [ -z "${ARIS_REPO:-}" ] && [ -f .aris/installed-skills.txt ]; then
ARIS_REPO=$(awk -F'\t' '$1=="repo_root"{print $2; exit}' .aris/installed-skills.txt 2>/dev/null) || true
fi
if [ -z "${ARIS_REPO:-}" ] && [ -f "$HOME/.aris/repo" ]; then
ARIS_REPO=$(cat "$HOME/.aris/repo" 2>/dev/null) || true
fi
QUEUE_TOOLS=".aris/tools/experiment_queue"
[ -f "$QUEUE_TOOLS/queue_manager.py" ] || QUEUE_TOOLS="tools/experiment_queue"
[ -f "$QUEUE_TOOLS/queue_manager.py" ] || { [ -n "${ARIS_REPO:-}" ] && QUEUE_TOOLS="$ARIS_REPO/tools/experiment_queue"; }
[ -f "$QUEUE_TOOLS/queue_manager.py" ] || QUEUE_TOOLS=""
fi
[ -z "$QUEUE_TOOLS" ] && { echo "ERROR: experiment_queue helpers not found (layer 0: \$CLAUDE_SKILL_DIR/scripts/; layers 1-4: .aris/tools/, tools/, \$ARIS_REPO/tools/, \$ARIS_REPO/tools/ via ~/.aris/repo). Rerun install_aris.sh or smart_update.sh (refreshes ~/.aris/repo), set ARIS_REPO, or copy the canonical scripts from \$ARIS_REPO/skills/experiment-queue/scripts/." >&2; exit 1; }
.aris/tools シンボリックリンクは install_aris.sh(#174)によって設定されます。このシンボリックリンクがない古いインストールでは、tools/experiment_queue(ARIS リポジトリ内から呼び出した場合に動作)、$ARIS_REPO/tools/experiment_queue、またはグローバルポインターファイル ~/.aris/repo(#366、プロジェクトローカルのマニフェストがないインストール向け)を使って解決します。Phase 3.3 以降、これらのレガシーパスには、正式な skills/experiment-queue/scripts/ の場所に処理を転送する Python の os.execv シムが配置されています。そのため、既存のユーザーが何かを再実行する必要はありません。
3b. リモートパスを計算する。 リモート相対形式(scp の宛先用。最新の scp は SFTP モードで実行され、宛先パス内の $HOME を確実に展開しません)と、$HOME を先頭に付けた形式(リモートの bash が $HOME を展開する ssh ... command 文字列用)の両方を使用します。
REMOTE_RUN_REL=".aris_queue/runs/$RUN_TS" # for scp destinations (relative to remote home)
REMOTE_RUN_DIR="\$HOME/$REMOTE_RUN_REL" # for ssh command strings (literal $HOME, expanded on remote)
3c. リモートの実行ディレクトリを初期化し、ヘルパーとマニフェストをコピーする。 呼び出しごとに実行し、冪等にします。並行するキューが衝突せず、クラッシュ後の再開を再現可能にするため、/tmp ではなく一意の実行ディレクトリを使用します。
ssh <server> "mkdir -p \"$REMOTE_RUN_DIR/logs\" \"\$HOME/.aris_queue\""
scp "$QUEUE_TOOLS/queue_manager.py" "$QUEUE_TOOLS/build_manifest.py" <server>:.aris_queue/
scp "$LOCAL_RUN_DIR/manifest.json" <server>:"$REMOTE_RUN_REL/manifest.json"
3d. SSH ホスト上で、スケジューラーを切り離された nohup プロセスとして起動する:
ssh <server> "nohup python3 \"\$HOME/.aris_queue/queue_manager.py\" \\
--manifest \"$REMOTE_RUN_DIR/manifest.json\" \\
--state \"$REMOTE_RUN_DIR/queue_state.json\" \\
--log-dir \"$REMOTE_RUN_DIR/logs\" \\
> \"$REMOTE_RUN_DIR/queue_mgr.log\" 2>&1 &"
呼び出し側への注意:
-
queue_manager.pyが実際に使用するのは--log-dirです(OOM 検出用のジョブごとのログファイル)。--log <path>は渡さないでください。このフラグは宣言されていますが使用されず、単一の統合ログではジョブごとの stale-screen/OOM 判定ヒューリスティクスが機能しません。 -
監視や再開時に値を再生成せず読み込めるよう、
RUN_TS/REMOTE_RUN_REL/REMOTE_RUN_DIRをディスクに保存します。{ printf 'PROJECT_DIR=%q\n' "$PROJECT_DIR" printf 'RUN_TS=%q\n' "$RUN_TS" printf 'LOCAL_RUN_DIR=%q\n' "$LOCAL_RUN_DIR" printf 'REMOTE_RUN_REL=%q\n' "$REMOTE_RUN_REL" printf 'REMOTE_RUN_DIR=%q\n' "$REMOTE_RUN_DIR" } > "$LOCAL_RUN_DIR/run_meta.txt"
%q は値をシェルでエスケープし、後からファイルを安全に source できるようにします。REMOTE_RUN_DIR にはリテラルの $HOME が保持される点に注意してください(ローカルでは展開しないでください)。これは、後で ssh "..." 文字列内で再利用する正しい形式です。
3e. 既存のキューを再開する(ユーザーが求めた場合のみ)。 新しいキューでは、呼び出しごとに新しい RUN_TS を設定するのが正しい方法です。クラッシュしたキューを再開する場合は、RUN_TS を再生成せず、記録済みの値を読み込み、初期化(ステップ 3c)ではなく起動コマンド(ステップ 3d)のみを再実行します。
LOCAL_RUN_DIR="/abs/path/to/project/experiment_queue/<existing-run-ts>" # the run dir to resume
. "$LOCAL_RUN_DIR/run_meta.txt" # reloads PROJECT_DIR / RUN_TS / REMOTE_RUN_REL / REMOTE_RUN_DIR
# Then re-run Step 3d verbatim. Do NOT re-run Step 3c (would overwrite manifest.json + state.json).
2026-08 のスケジューラ修正前に書き込まれた queue_state.json には、旧コードが誤って失敗と判定したジョブが記録されています。それを再開すると、これらのジョブは stuck として保留され、再試行されません。そのため、ジョブがすべて failed_other の状態ファイルでは、何も起動されずに終了します。その状態ファイルを削除し、ステップ 3c からマニフェストを再実行してください。
スケジューラーは次の処理を行います:
- マニフェストを読み込みます
- ループ処理:保留中の各ジョブを空いている GPU に割り当て、
screenで起動します - ジョブの状態を(60 秒ごとに)ポーリングします
- stale screen を検出します(Python が終了したものの screen が切り離された状態 → 強制終了)
- OOM を検出します(ログに CUDA OOM がある →
failed_oomとしてマークし、遅延後に再試行) - 完了を検出します(期待される出力 JSON/ファイルが存在する →
completedとしてマーク) - 現在のウェーブが収束したら、次のウェーブを起動します
queue_state.jsonに状態を継続的に書き込みます
ステップ 4:モニタリング
ユーザーは、ステップ 3b の $REMOTE_RUN_DIR を使っていつでも状態を確認できます(以前の実行の場合は、$LOCAL_RUN_DIR/run_meta.txt から再読み込みしてください)。
ssh <server> "cat \"$REMOTE_RUN_DIR/queue_state.json\"" \
| jq '.jobs | group_by(.status) | map({(.[0].status): length}) | add'
注:/monitor-experiment は現在、スクリーンセッション、結果 JSON、W&B を中心に扱っており、queue_state.json を直接読み込む機能はまだありません。キューの状態をモニタリングするには、記録された REMOTE_RUN_DIR に対して上記のコマンドをそのまま実行してください(/monitor-experiment のキュー状態連携は今後の課題として追跡しています)。
ステップ 5:完了後
manifest.json 内のすべてのジョブが completed または stuck になった場合:
- リモートスケジューラー(
queue_manager.py)は、独自の stdout($REMOTE_RUN_DIR/queue_mgr.logに記録されます)にAll jobs doneと出力して正常終了します。ローカルのサマリーは書き込みません。 - ローカルのスキルエージェントが状態を集約し、
$LOCAL_RUN_DIR/summary.mdにまとめます($REMOTE_RUN_DIR/queue_state.jsonを読み込み、ステータスごとに分類し、必要に応じてジョブごとのログを取得します)。 analyze_on_complete: trueの場合、ローカルのスキルエージェントが/analyze-resultsを呼び出します。
グリッド指定構文
24 個のジョブエントリを手動で記述する代わりに:
grid:
N: [64, 128, 256]
n: [50000, 150000, 500000, 652000]
seed: [42, 200, 201]
template:
id: "s${seed}_N${N}_n${n}"
args: {seed: ${seed}, n_hidden: ${N}, n_train_subset: ${n}}
自動的に 36 個のジョブに展開されます。
ウェーブの連結
順次進行するフェーズ(教師 → 生徒)の場合:
phases:
- name: train_teachers
grid:
N: [384, 512]
template:
cmd: python run_train.py --direction c --backbone softmax --n_hidden ${N} ...
expected_output: checkpoints/transformer/teacher_L96_K500_N${N}.pt
- name: distill_students
depends_on: [train_teachers] # must be a LIST, even for a single dependency
grid:
N: [384, 512]
seed: [42, 200, 201]
template:
cmd: python run_distill.py --n_hidden ${N} --seed ${seed} ...
expected_output: figures/distill_sw_N${N}_*_seed${seed}.json
スケジューラーは depends_on を適用します。distill_students ジョブは、すべての
train_teachers ジョブが終端状態(completed または stuck)になるまで pending のままです。教師ジョブが失敗しても生徒ジョブは保留されないため、依存するウェーブを信頼する前に、queue_state.json で stuck のジョブを確認してください。
OOM への対処
stdout から OOM を検出します:
torch\.OutOfMemoryError: CUDA out of memory
検出した場合:
- ジョブを
failed_oomに設定 - スクリーンを終了
oom_retry.delay秒待機- 現在の GPU が空いているか確認し、空いていない場合は別の空き GPU を試す
pendingとして再キューに追加oom_retry.max_attemptsの最大試行回数に達したらstuckに設定
古いスクリーンの検出
60 秒ごとに、実行中のスクリーンごとに以下を行います:
- スクリーンが存在するか確認(
screen -ls) - Python の PID がまだ実行中か確認(
ps -p) - スクリーンは存在するが Python が終了している場合:
- 予期される出力ファイルが存在する場合 →
completedに設定し、古いスクリーンを終了 - 出力ファイルがない場合 →
failed_otherに設定し、スクリーンを終了
- 予期される出力ファイルが存在する場合 →
再起動時の再開
スケジューラーがクラッシュまたは強制終了された場合:
queue_state.jsonを読み込む- 各
runningジョブについて、スクリーンを確認する。まだ実行中であればそのまま維持し、そうでなければ状態を再評価する - 各
pendingジョブは通常どおり続行する - 冪等性:状態を失わずに安全にスケジューラーを再起動できます
出力:サマリーレポート
# Experiment Queue Summary
**Project**: my_grid_experiment
**Started**: 2026-04-16 11:36:29
**Completed**: 2026-04-16 18:02:14
**Total wall-clock**: 6h 25m
**Jobs**: 40 completed, 2 OOM-retried then completed, 0 stuck
## Phases
| Phase | Jobs | Success | OOM retries | Duration |
| --- | --- | --- | --- | --- |
| train_teachers | 2 | 2 | 0 | 58m |
| distill_students | 24 | 24 | 2 | 4h 02m |
| multi_seed_validation | 16 | 16 | 0 | 1h 25m |
## Results Files
- 42 JSON files in `figures/distill_sw_*.json`
## Next Steps
- Run `/analyze-results` on output JSONs
- Figures auto-regen via `artifact-sync` (if configured)
/run-experiment との比較
| 機能 | /run-experiment | experiment-queue |
|---|---|---|
| 単発の実験 | ✅ | ✅(過剰機能) |
| マルチ GPU 並列処理 | 基本的な対応 | 適切なスケジューリング |
| ウェーブの移行 | 手動 | 自動 |
| OOM の再試行 | 手動 | 自動 |
| 古いスクリーンのクリーンアップ | 手動 | 自動 |
| 教師→生徒の連結 | 手動 | 組み込み |
| 状態の永続化 | なし | あり(JSON) |
| クラッシュ後の再開 | なし | あり |
| グリッドの展開 | 手動 | 宣言的 |
ルール:5 個以下のジョブには /run-experiment を使用してください。10 個以上のジョブ、またはフェーズを含む処理には experiment-queue を使用してください。
主なルール
- 同じ GPU 上でスクリーンを重ねて実行しないでください — 新しいジョブを起動する前に、必ず
memory.used < 500 MiBになるまで待ちます - 状態は必ずディスクに書き込んでください — 状態が変化するたびに
queue_state.jsonにフラッシュします - スケジューラーは冪等です — 安全に再起動でき、状態ファイルから処理を再開します
- 予期される出力に基づいて完了を判定します — スクリーンの状態だけを信用せず、出力ファイルの存在を確認します
- 再試行回数には上限を設けます — OOM の再試行は最大 N 回までとし、その後
stuckに設定して通知します - 依存関係は起動時に適用されます — 依存先のフェーズにあるすべてのジョブが終端状態に達してから、ウェーブを起動します。「終端」には
stuckも含まれます。教師ジョブが失敗した場合でもフェーズは完了となり、生徒ジョブはチェックポイントがない状態で起動します。依存するウェーブの結果を信頼する前に、queue_state.jsonでstuckのジョブを確認してください。
既知の障害モード
- スケジュール中の SSH 接続切断:スケジューラーはリモートで実行を続けます(nohup)。再接続して確認してください
- 別のユーザーによる GPU の予約:スケジューラーは待機し、横取りしません
- リモートのディスク容量不足:スケジューラーは書き込み失敗を検出し、保留中のすべてのジョブを
stuckに設定して、アラートを出します
セッション例
ユーザー:「T5+T6 の全実験を実行:T5 = N∈{80,192} × n は 4 値 × seed {200,201}、T6 = N∈{384,512} × n は 4 値 × seed {42,200,201}。T6 では先に teacher を train する必要あり」
Claude が /experiment-queue を呼び出します:
- 説明を 2 フェーズのマニフェストに解析
- フェーズ 1:T5(teacher の依存関係なしで 16 ジョブ)+ T6 の teacher 学習(2 ジョブ)
- フェーズ 2:T6 の蒸留(teacher に依存する 24 ジョブ)
- nohup を使ってスケジューラーをデプロイ
- 報告:「スケジューラー PID 93534、合計 42 ジョブ、推定所要時間 6~7 時間」
その後、ユーザーはいつでも状況を確認するか、サマリーレポートを待つことができます。
関連項目
/run-experiment— 単一の実験をデプロイ/monitor-experiment— 進捗を確認(現在はqueue_state.jsonを読み取ります)/analyze-results— 実行後の分析skills/experiment-queue/scripts/queue_manager.py(正規の場所、Phase 3.3 で移動) — スケジューラーの実装。Step 3a のフォールバックチェーンを通じて実行時に解決されます。従来の場所にあるtools/experiment_queue/queue_manager.pyはos.execvの shim です。skills/experiment-queue/scripts/build_manifest.py(正規の場所、Phase 3.3 で移動) — グリッド仕様からマニフェストを構築します。同じ解決チェーンを使用します。従来の場所にあるtools/experiment_queue/build_manifest.pyはos.execvの shim です。
背景/出典
2026-04-16 の事後分析(Codex GPT-5.5 xhigh)で、1.5 日間にわたる複数 seed の論文実験セッションから特定されました:
- 実時間の浪費:古い screen、OOM、フェーズ間の移行、手動パーサー
- トークンの浪費:セッションごとにオーケストレーションコードを書き直すこと
- 認知的負担:成功したセル、失敗したセル、再試行するセルの追跡
このスキルは、特に実時間の浪費を対象としています。残る 2 つについては、artifact-sync と
paper-fix-auto-apply を参照してください。