6月末に Antigravity へ組み込み Guide スキルが入ってから、私は繰り返しの作業を Guide にまとめる回数が増えました。ブログの push 手順、記事の検証手順、リリース前のチェック。手順を一度書いておけば、動的サブエージェントにそのまま渡せて、毎回説明し直す手間が消えます。
ところが数週間後、ある Guide がエージェントを、もう存在しないスクリプトのパスへ案内していました。リポジトリ側でファイルを整理したのに、Guide の手順だけが古いまま取り残されていたのです。エラーは出ませんでした。エージェントは指示どおりに動こうとして、存在しない対象を前に静かに空振りしていました。
この静かなずれこそ、手順を固定する仕組み全般が抱える弱点です。ここで扱うのは、Guide とコードの乖離を早めに見つけ、Guide を薄く保つ設計です。個人開発で使っている検証の形とあわせて整理します。
なぜ Guide スキルは静かにずれるのか
Guide スキルは、ある時点のコードや運用を写し取った手順書です。写し取った瞬間は正確でも、コードは動き続けます。ファイルは移動し、コマンドのオプションは変わり、前提にしていた挙動も更新されます。
問題は、Guide とコードのあいだに接続が無いことです。コードを直しても Guide は何も知りません。Guide が古くなっても、誰かが実際にその手順を最後まで走らせるまで、ずれは表に出ません。しかもエージェントは指示に忠実なので、古い手順でも律儀に実行しようとして、失敗ではなく空振りという最も気づきにくい形で終わります。
ずれが起きる3つの層
私が Guide を見直すとき、まずどの層でずれているかを切り分けます。層ごとに検出のしやすさが違うからです。
| 層 | ずれの例 | 検出のしやすさ |
| パス | 参照するファイルやスクリプトが移動・削除された | 実在照合で機械的に検出しやすい |
| 手順 | コマンドのオプションや順序が変わった | 実行して初めて分かる。中程度 |
| 前提 | 「この処理は冪等」など暗黙の前提が崩れた | 人が読まないと分からない。難しい |
このうちパス層は、機械照合でほぼ自動的に潰せます。手順層は実行時のチェックへ、前提層は Guide を薄く保つ設計へ寄せる、という役割分担にしています。まずは一番潰しやすいパス層から仕組みで固めるのが費用対効果に優れていました。
乖離を検出する — 参照先の実体を照合する
考え方はシンプルです。Guide の中に書かれた「ファイルのパス」「呼び出すスクリプト」「参照するコマンド」を抜き出し、それが今のリポジトリに実在するかを確かめます。実在しなければ、その Guide はパス層でずれています。
- Guide の本文からパスらしき文字列を抽出する
- リポジトリのルートを基準に、その実体が存在するか確認する
- 存在しないものを乖離候補として一覧にする
- push の直前にこの照合を走らせ、乖離があれば止める
大事なのは、これを人の目視ではなく仕組みに任せることです。目視は Guide が増えるほど抜けます。私はブログごとに複数の Guide を持っているので、目視での棚卸しはすぐに破綻しました。
コードで見つける
パス層の照合を行う最小限のスクリプトが次です。Guide の中からスラッシュを含むトークンを拾い、リポジトリ内に実在するかを確かめます。抽出の精度は運用に合わせて調整してください。
#!/usr/bin/env python3
# Guide スキル内の参照パスが実在するか照合する
import re
import sys
from pathlib import Path
repo = Path(sys.argv[1]).resolve() # リポジトリのルート
guide = Path(sys.argv[2]) # 対象の Guide ファイル
text = guide.read_text(encoding="utf-8")
# コードブロックとインラインコードからパスらしきトークンを拾う
candidates = set()
for m in re.finditer(r"`([^`\n]+)`", text):
token = m.group(1).strip()
# 相対パス・スクリプト・設定ファイルらしきもののみ対象
if re.search(r"[\w./-]+\.(?:py|mjs|sh|ts|json|mdx)$", token) or token.startswith("./"):
candidates.add(token.lstrip("./"))
missing = []
for c in candidates:
# クエリや引数を落として先頭のパス部分だけ見る
path_part = c.split()[0]
if not (repo / path_part).exists():
missing.append(path_part)
if missing:
print(f"⚠️ drift in {guide.name}: {len(missing)} reference(s) not found")
for x in sorted(missing):
print(f" - {x}")
sys.exit(1)
print(f"✅ {guide.name}: all references exist")
実際に自分の Guide 群へ通したところ、整理で移動したスクリプトへの参照が数件見つかりました。どれもエラーにはならず、走らせて初めて空振りに気づく類のものです。照合を1回挟むだけで、その空振りを push 前に潰せました。
直し方 — コードを真実に、Guide は薄く
乖離を見つけたら直しますが、直し方に方針があります。Guide を単一の真実にしないことです。
Guide にコマンドの全手順やパスを事細かに書き込むほど、コードが変わったときにずれる面積が広がります。私は逆に、実体はコード側に置き、Guide からはそれを呼ぶだけ、という形へ寄せています。
| やり方 | ずれる面積 | 直す手間 |
| Guide に手順を全部書く(厚い) | 広い。コード変更のたびにずれる | 都度 Guide も直す。二重管理 |
| 実体はスクリプト、Guide は呼ぶだけ(薄い) | 狭い。呼び先の名前だけ | スクリプトを直せば済む。一元化 |
厚い Guide は書いた直後は親切ですが、時間が経つほど負債になります。薄い Guide は最初こそ素っ気なく見えますが、コードを真実に据えているので、コードを直せば Guide は自然と正しいままです。私自身は、本番で回すブログの Guide ほどこの薄い形を推奨します。厚い手順を書き込むより、実体をコードへ寄せて乖離を回避するほうが、長い目で楽でした。
運用に組み込む
検出スクリプトは、思い出したときに走らせるのでは意味がありません。私は push の直前の品質チェックに、この照合を一段として組み込んでいます。
- push 前に、変更した Guide を対象に照合を走らせる
- 乖離が1件でも出たら push を止め、Guide を薄くするか参照を直す
- 定期的に全 Guide を一括照合し、触っていない Guide のずれも拾う
こうしておくと、コードを整理した副作用で古くなった Guide が、次の push のタイミングで自動的に浮かび上がります。エージェントが空振りする前に、人が気づける位置へずれを引き上げておくのが狙いです。
次の一歩
もし Guide スキルを増やし始めているなら、まず手元の Guide を1つだけ選び、その中のパス参照が今も実在するか照合してみてください。おそらく1件か2件、静かにずれた参照が見つかります。そこから、その Guide を薄くしてコードを真実に寄せる方向へ直していけば、次にリポジトリを整理したときも、Guide はあなたの手を煩わせずに正しいままでいてくれます。