ANTIGRAVITY LABEN
記事一覧/Tips & 活用術
Tips & 活用術/2026-06-28上級

ポイントリリースの後に無人運用が壊れていないかを30秒で確かめる

Antigravity が短い間隔でポイントリリースを重ねる中、更新後にスケジュール実行だけが静かに壊れる事故をどう防ぐか。ゴールデン出力との差分で更新の影響を検知し、ダメなら自動で戻すスモークテストの仕組みを紹介します。

Antigravity285CLI3無人運用2回帰テスト個人開発79

「昨日まで動いていた夜間バッチが、今朝だけ空振りしている」。Antigravity が 6 月に v2.2.1・v2.1.4・v2.0.11 と立て続けにポイントリリースを出した週、私自身もまさにこの状況に出くわしました。手元で対話的に使っているぶんには何も変わって見えないのに、agy をヘッドレスで呼んでいるスケジュール実行だけが、出力形式の微妙な変化で後段のパースに失敗していたのです。

公式の変更履歴を毎朝読むのは現実的ではありませんし、読んでも「自分のスクリプトに効くかどうか」は書いてありません。必要なのは、更新の前後で自分のユースケースの出力が変わったかどうかを、機械的に・短時間で判定する仕掛けです。以下では、ゴールデン出力との差分で回帰を検知し、壊れていたら前のバージョンへ自動で戻す、軽量なスモークテストを組み立てます。

なぜ「壊れ方」が静かなのか

ポイントリリースが怖いのは、メジャー更新と違って身構えないからです。バグ修正と性能改善が中心なので、まさか自分の自動処理が止まるとは思いません。ところが無人運用で効いてくるのは、機能の有無ではなく出力の細部です。

実際に私が踏んだのは次のような変化でした。ヘッドレス出力の先頭に進捗行が一行増えた、JSON の整形が変わって末尾の改行有無が揺れた、終了コードは 0 のままなのに本文が空で返ってきた。どれも対話 UI では誰も気づきません。けれど、出力を jq や正規表現で受けている後段にとっては致命的です。終了コードだけを見て成否を判定していると、空の本文をそのまま「成功」として次の工程へ流してしまいます。

つまり守るべき境界は「コマンドが成功したか」ではなく「いつもと同じ形の出力が返ってきたか」です。ここを押さえると、対策はぐっと具体的になります。

ゴールデン出力を一度だけ固定する

最初にやるのは、安定して動いている「いまのバージョン」で、代表的な入力に対する出力を一度だけ記録することです。完全一致を求めると日付や乱数で毎回壊れるので、揺れる部分を正規化してから比べます。

#!/usr/bin/env bash
# capture_golden.sh — いま動いているバージョンの基準出力を保存する
set -euo pipefail
 
GOLDEN_DIR="${HOME}/.agy_smoke"
mkdir -p "$GOLDEN_DIR"
 
# 実運用と同じヘッドレス呼び出しを再現する(自分のバッチに合わせて差し替える)
run_case() {
  agy run --headless --no-tty \
      --prompt-file "$1" \
      --output json 2>/dev/null
}
 
# 揺れる値(日付・UUID・所要時間)を伏せ字にして比較を安定させる
normalize() {
  sed -E \
    -e 's/[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9:.]+Z?/<TS>/g' \
    -e 's/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/<UUID>/g' \
    -e 's/"elapsed_ms":[0-9]+/"elapsed_ms":<N>/g'
}
 
agy --version > "$GOLDEN_DIR/version.txt"
for f in cases/*.prompt; do
  name="$(basename "$f" .prompt)"
  run_case "$f" | normalize > "$GOLDEN_DIR/${name}.golden"
  echo "captured: $name"
done
echo "golden version: $(cat "$GOLDEN_DIR/version.txt")"

ここで大事なのは、スモーク用の入力 cases/*.prompt を本番のバッチと同じ種類にしておくことです。私は記事生成・要約・JSON 抽出の 3 つだけを代表ケースとして置いています。網羅は狙わず、壊れたら一番困る経路だけを薄く守る、という方針です。ケースが多すぎると毎回の確認が重くなり、結局回さなくなります。

更新前にスモークし、ダメなら戻す

基準ができたら、更新の直前にもう一度同じケースを流し、ゴールデンと比べます。構造的な差分が出たら、その更新は自分のユースケースを壊している可能性が高い、と判断して止めます。

#!/usr/bin/env bash
# smoke_check.sh — 現在の出力をゴールデンと突き合わせる。差分があれば exit 1
set -euo pipefail
GOLDEN_DIR="${HOME}/.agy_smoke"
 
source_funcs() { :; }   # run_case / normalize は capture_golden.sh と共有する想定
run_case() { agy run --headless --no-tty --prompt-file "$1" --output json 2>/dev/null; }
normalize() {
  sed -E \
    -e 's/[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9:.]+Z?/<TS>/g' \
    -e 's/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/<UUID>/g' \
    -e 's/"elapsed_ms":[0-9]+/"elapsed_ms":<N>/g'
}
 
fail=0
for g in "$GOLDEN_DIR"/*.golden; do
  name="$(basename "$g" .golden)"
  current="$(run_case "cases/${name}.prompt" | normalize)"
 
  # 1) 本文が空でないこと(終了コード 0 でも空返しを弾く)
  if [ -z "$(echo "$current" | jq -r '.text // empty' 2>/dev/null)" ]; then
    echo "✗ ${name}: empty body"
    fail=1; continue
  fi
  # 2) 構造の差分(キー集合の変化を検知。値の中身までは見ない)
  ref_keys="$(echo "$(cat "$g")" | jq -S 'keys' 2>/dev/null || echo '[]')"
  cur_keys="$(echo "$current" | jq -S 'keys' 2>/dev/null || echo '[]')"
  if [ "$ref_keys" != "$cur_keys" ]; then
    echo "✗ ${name}: schema drift"
    diff <(echo "$ref_keys") <(echo "$cur_keys") || true
    fail=1; continue
  fi
  echo "✓ ${name}"
done
exit "$fail"

差分の比較を「キー集合の変化」に絞っているのには理由があります。本文の文字列は更新ごとに自然に揺れるため、完全一致で見るとスモークが毎回赤くなって信用されなくなります。後段のパースが実際に依存しているのは出力の構造、つまりどのキーが存在するかなので、そこだけを厳しく見ます。空本文チェックを別に置いているのは、終了コード 0 のまま中身が空という、最も静かな壊れ方を取り逃さないためです。

更新と検証をひとつの流れにする

最後に、バージョン固定・更新・スモーク・自動ロールバックをひとつのスクリプトにまとめます。段階移行が無難だという経験則を、手順として固定してしまうわけです。

#!/usr/bin/env bash
# guarded_upgrade.sh — スモークが通った時だけ更新を確定し、ダメなら戻す
set -euo pipefail
GOLDEN_DIR="${HOME}/.agy_smoke"
 
prev="$(agy --version | awk '{print $NF}')"
echo "current: $prev"
 
# 1) 更新前のスモーク(今の環境が健全であることを先に保証)
if ! ./smoke_check.sh; then
  echo "更新前から赤い。基準を取り直すまで更新しない。"; exit 1
fi
 
# 2) 更新(バージョンを明示固定。最新追従は避ける)
target="${1:?usage: guarded_upgrade.sh <version>}"
agy self update --version "$target"
 
# 3) 更新後のスモーク。落ちたら即ロールバック
if ./smoke_check.sh; then
  echo "✅ $target はスモーク通過。確定します。"
  agy --version > "$GOLDEN_DIR/version.txt"
else
  echo "🚨 $target でスモーク失敗。$prev へ戻します。"
  agy self update --version "$prev"
  ./smoke_check.sh && echo "ロールバック完了($prev で健全)"
  exit 1
fi

agy self update のオプション名やサブコマンドは環境やバージョンで差があるので、agy self update --help で実際の指定方法を確認してから組み込んでください。要は「最新へ自動追従させず、検証を通ったバージョンだけを明示的に固定する」という考え方が核で、コマンドの細部は読み替えればそのまま使えます。

この仕組みを入れてから、ポイントリリースに対する私の態度は変わりました。更新を恐れて先送りするのでも、無防備に最新へ飛びつくのでもなく、30 秒のスモークが通れば取り込み、落ちれば戻す。Dolice Labs の複数サイトを個人開発で一人で回していると、更新の判断に時間をかけられないので、この「通れば進む・落ちれば戻る」の自動化が効きました。

小さく守る発想に切り替える

ポイントリリースの不確実性に対して、変更履歴を読み込んで身構えるのは続きません。代わりに、自分のユースケースの出力という一点だけを基準化し、更新の前後で機械的に突き合わせる。守る対象を「コマンドの成否」から「いつもの出力の形」へずらすだけで、静かな回帰のほとんどは検知できます。

次の一歩として、まずは壊れたら一番困る経路をひとつだけ選び、capture_golden.sh で基準を取ってみてください。たった一ケースでも、次のポイントリリースが来たときに「これは取り込んでいいのか」を秒で判断できる足場になります。同じように無人運用と更新の板挟みになっている方の助けになれば嬉しいです。

シェア

お読みいただきありがとうございます

Antigravity Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

Tips & 活用術2026-06-28
エージェントに作らせた音声を会話の中でそのまま聴く — インライン再生が変えた確認の手数
Antigravity の最近のポイントリリースで会話ビューに音声ファイルのインライン描画が入りました。エージェントに作らせた音声をその場で聴ける変化を、アプリの音声アセットを確認する実務に落とし込みます。
Tips & 活用術2026-05-05
Antigravity × モバイル収益設計の全体像:AdMob・IAP・サブスクリプションを組み合わせた個人開発者の収益最大化フレームワーク
AdMob・アプリ内購入・サブスクリプションを一元化したモバイル収益戦略の設計書。Antigravity を使って収益ダッシュボードから価格 A/B テストまで自動化する、個人開発者向けの実装ガイドです。
Tips & 活用術2026-04-27
Antigravity で CHANGELOG.md を git ログから半自動で書く — 個人開発でも意思決定の履歴を残す
半年前の自分の判断が思い出せない — 個人開発でよくある問題です。Antigravity に git log を読ませて CHANGELOG.md のドラフトを作る半自動ワークフローを、実際のスクリプト付きで紹介します。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →