Lab のサイトを直していた昼過ぎ、私は /boost に「テストまで通してから返してください」と頼みました。返ってきた要約には、テストスイートが通ったと書かれておりました。ところが手元で同じコマンドを叩くと、ビルドの途中で止まります。
原因はコードではありませんでした。私の作業ツリーには、git が追跡していないのに、ビルドが読みにいくファイルが何枚か置いてあったのです。/boost はそれらが存在しない場所で検証を終えていました。
このずれは、エージェントの賢さとは無関係です。どこで検証したかを知らないまま「検証済み」を受け取ると、通ったのは自分の木ではありません。 その「どこ」を先に数えておく手順を書き残します。
/boost は、共有の作業ツリーでは動いていません
まず公式の記述を確認しておきます。/boost は思考量を上げるだけのコマンドではなく、Orchestrator が課題を分解し、専用のサブエージェントへ実装と調査を振り分け、ローカルでビルドとテストを走らせて独立に検証する三段構えのパイプラインです。詳細は Boost deep reasoning (/boost) にまとまっています。
見落とされやすいのは、実行モードの比較表にある「ワークスペースモデル」の行です。
| 項目 | 既定のエージェント | /boost |
|---|---|---|
| ワークスペース | 共有の作業ツリー | 使い捨ての隔離ワークツリー |
| 検証 | 単発のツール確認 | 複数ラウンドの独立検証 |
| アーキテクチャ | 単一エージェントの直列ループ | 三段の推論階層 |
| 想定時間 | 数秒〜数分 | 数秒〜数時間 |
既定のエージェントは、私が見ている作業ツリーをそのまま触ります。/boost は違います。サブエージェントは隔離された作業空間で走り、そこでビルドターゲットとテストスイートを実行してから結果を報告します。デバッグの出力やスクラッチの差分が本筋の会話に混ざらないという利点は、そのまま「手元の散らかりも持ち込まれない」という意味になります。
散らかりの中に、ビルドが必要としているものが混ざっていた——それが私の躓きでした。
隔離された木に現れないものを、実際に数えます
推測で済ませず、同じ条件を手元で再現します。git worktree で HEAD から新しい木を作り、いまの作業ツリーとファイル一覧を突き合わせるだけです。
#!/usr/bin/env bash
# worktree-gap.sh — いまの作業ツリーにあって、HEAD から作った新しい worktree には現れないパスを数える。
# 使い方: ./worktree-gap.sh [リポジトリのパス]
set -uo pipefail
REPO="${1:-$(pwd)}"
cd "$REPO" || exit 1
git rev-parse --is-inside-work-tree >/dev/null || exit 1
PROBE="$(mktemp -d)"
cleanup() { git worktree remove --force "$PROBE" >/dev/null 2>&1; rm -rf "$PROBE"; }
trap cleanup EXIT
git worktree add --detach -q "$PROBE" HEAD || exit 1
LIST_HERE="$(mktemp)"; LIST_THERE="$(mktemp)"; MISSING="$(mktemp)"
trap 'cleanup; rm -f "$LIST_HERE" "$LIST_THERE" "$MISSING"' EXIT
find . -path ./.git -prune -o -type f -print | sed 's|^\./||' | sort > "$LIST_HERE"
( cd "$PROBE" && find . -path ./.git -prune -o -type f -print ) | sed 's|^\./||' | sort > "$LIST_THERE"
comm -23 "$LIST_HERE" "$LIST_THERE" > "$MISSING"
echo "== 新しい worktree に現れないパス(上位ディレクトリ別・件数) =="
awk -F/ '{ print (NF>1 ? $1"/" : $0) }' "$MISSING" | sort | uniq -c | sort -rn
echo
echo "== うち、追跡下のコードや設定が名前で参照しているもの =="
FOUND=0
while IFS= read -r p; do
base="$(basename "$p")"
case "$base" in .DS_Store|*.log|*.tmp) continue ;; esac
SRC="$(git grep -lF -- "$base" HEAD -- . 2>/dev/null | sed 's|^HEAD:||' | grep -v '^\.gitignore$' | head -3 | paste -sd, -)"
if [ -n "$SRC" ]; then
printf ' %s <- %s\n' "$p" "$SRC"
FOUND=$((FOUND + 1))
fi
done < <(awk -F/ 'NF<=4' "$MISSING" | head -200)
if [ "$FOUND" -eq 0 ]; then
echo " (なし。.gitignore だけが名前を知っているものは参照元から除外しています)"
fi
echo
printf '合計 %s 件が、新しい worktree には存在しません。\n' "$(wc -l < "$MISSING" | tr -d ' ')"前半は差分の一覧、後半が本題です。差分に出たファイル名を、追跡下のコードと設定に対して git grep で引き当てます。名前で呼ばれているのに新しい木には無いファイルこそ、隔離ワークツリーでの検証が素通りしている場所です。
.gitignore を参照元から外しているのには理由があります。無視されているファイルは、ほぼ必ず .gitignore に名前が載っています。これを数えてしまうと差分の全件が「参照あり」になり、一覧の意味が消えてしまうのです。
検証用に、.env・生成物・ローカル設定・依存パッケージを置いた小さなリポジトリを作って走らせたところ、出力はこうなりました。
== 新しい worktree に現れないパス(上位ディレクトリ別・件数) ==
1 public/
1 node_modules/
1 config/
1 .env
== うち、追跡下のコードや設定が名前で参照しているもの ==
config/local.json <- src/load.ts
public/generated/articles.json <- src/load.ts
合計 4 件が、新しい worktree には存在しません。node_modules/ と .env は差分には出ますが、参照元の欄には上がってきません。前者は依存の再インストールで埋まりますし、後者は .gitignore しか名前を知らないためです。一方 src/load.ts から名前で呼ばれている二つは、隔離ワークツリーには存在しないまま、そこでテストが走ったことになります。
このスクリプトが取りこぼすもの
正直に書いておきます。私が最初に書いた版では、二段目の一覧に public/generated/articles.json が出てきませんでした。
原因は絞り込みの深さです。差分の件数が多くなりすぎるのを避けようとして awk -F/ 'NF<=2' と書いており、階層が三段以上のパスを捨てていました。生成物は public/generated/ のように深い場所へ置かれることが多く、いちばん見つけたいものを自分で除外していたわけです。上の版では NF<=4 に直してあります。
残る限界も三つ挙げます。
| 限界 | 何が起きるか | どうするか |
|---|---|---|
| ファイル名だけの照合 | index.ts のような一般的な名前は誤って一致します | 参照元の欄を目で確かめる。一意な名前ほど信頼できます |
| 環境変数は見えない | パスを環境変数で渡している場合、名前が本文に現れません | CI の設定ファイルを別途読み合わせる |
| 実行順序は分からない | 参照されていても、当該テストが通らない経路かもしれません | 件数ではなく、当たりを付けるための一覧として使う |
要するに、これは判定器ではなく手がかりです。ゼロ件だから安全という保証にはなりませんし、十件出たから /boost を使えないという話でもありません。私の環境では見えていない依存が、まだ他にもあるかもしれません。
数えたあとに、どこで線を引くか
一覧を見ながら、私は依頼の仕方を三通りに分けるようになりました。
参照元の欄が空なら、/boost の検証結果をそのまま受け取ります。アルゴリズムの詰めや競合状態の追跡は、まさにこのコマンドが想定している用途です。
参照元に生成物が並んだときは、依頼文の中で生成の手順まで含めます。「テストの前に生成スクリプトを走らせてください」と一行足すだけで、隔離ワークツリーの側でも同じ前提が揃います。私の場合、コンテンツを JSON へ書き出す工程がここに当たりました。
参照元に秘密情報や外部サービスの資格情報が混じるときは、/boost に検証まで任せません。実装だけを受け取り、テストは手元で回します。検証を委ねてよいかどうかは、モデルの能力ではなく、木の中身が揃っているかで決めています。 この線引きだけは、急いでいる日ほど守るようにしております。
なお /boost は有料プランで使えるコマンドで、サブエージェントは作業空間に設定された権限をそのまま引き継ぎます。保護された操作は承認を求めてきますので、隔離されているからといって権限が緩むわけではありません。ここは スラッシュコマンドの一覧 側にも整理されています。
まずは手元のリポジトリで一度だけ上のスクリプトを走らせて、参照元の欄に何が並ぶかをご覧いただければと思います。私はその出力を見て、自分が git に預けていないものの多さに手が止まりました。数えるところからしか、線は引けないのだと感じています。
お読みいただきありがとうございました。