ANTIGRAVITY LABEN
記事一覧/Agents & Manager
Agents & Manager/2026-08-07上級

変更したファイルからテストを選ばせたら、9 割が「該当なし」でした — import グラフで届く範囲を 3 リポジトリで測る

変更起点でテストを選ぶ仕組みを自己検証ループに入れたところ、大半の変更で対象が 0 本になりました。到達範囲を 3 リポジトリで実測し、選択契約を組み直すまでの記録です。

エージェント運用13テスト戦略静的解析Antigravity349

プレミアム記事

自己検証ループの実行時間を削るつもりでした。

エージェントが変更を出したあと、毎回テスト一式を走らせるのは待ち時間が長く、失敗しても原因の切り分けに時間がかかります。個人開発では、その待ち時間はそのまま自分の一日から差し引かれます。変更したファイルから逆にたどって、関係するテストだけを走らせればよいはずでした。

仕組みを入れて最初の数十件を流したところ、返ってきたのは「対象テスト 0 本」ばかりでした。

計測全体が 0.4 秒で終わったので、まずファイルを読めていないバグを疑いました。逆依存の辺数を数えると 3,177 本。グラフは確かに出来ていました。0 本という答えのほうが正しかったのです。

その日に測り直した内容を残しておきます。

何を測ったか

対象は公開リポジトリ 3 本です。ディレクトリ構成の癖が異なるものを選びました。

リポジトリ解析対象ファイル相対 import の辺グラフ構築時間
vite1,5401,409303 ms
hono388914240 ms
nest1,7273,177339 ms

測るのは 1 つだけです。ソースファイルを 1 本変更したとき、import の逆方向をたどって到達できるテストファイルが、テスト全体の何割になるか。

エージェントに「この変更に関係するテストを選べ」と任せるとき、内部で起きているのはこの計算です。割合が小さいほど実行は速く、しかし取りこぼしの危険は増えます。

グラフを組む

相対 import だけを解決します。@nestjs/common のようなワークスペース参照やパスエイリアスは意図的に外しました。エージェントが数百ミリ秒で組める範囲に限定したかったからです。

import os, re, subprocess
from collections import defaultdict, deque
 
EXTS = [".ts", ".tsx", ".mts", ".js", ".mjs", ".jsx"]
 
# import 文と副作用 import の両方を拾う
IMP = re.compile(
    r'''(?:^|\n)\s*(?:import|export)\b[^;\n]*?from\s*['"]([^'"]+)['"]'''
    r'''|(?:^|\n)\s*import\s*['"]([^'"]+)['"]'''
)
# re-export だけで構成された index.ts を「バレル」として印を付ける
REEXP = re.compile(r'''(?:^|\n)\s*export\s+(?:\*|\{)[^;]*?from\s*['"]''')
 
 
def resolve(base_dir, spec, fileset):
    """相対指定を実ファイルへ解決する。解決できなければ None。"""
    if not spec.startswith("."):
        return None
    raw = os.path.normpath(os.path.join(base_dir, spec))
    cands = [raw] + [raw + e for e in EXTS]
    cands += [os.path.join(raw, "index" + e) for e in EXTS]
    # ESM の相対指定は .js と書いて .ts を指すことがある
    if raw.endswith(".js"):
        cands += [raw[:-3] + e for e in (".ts", ".tsx", ".mts")]
    for c in cands:
        if c in fileset:
            return c
    return None
 
 
def build(repo):
    out = subprocess.run(["git", "-C", repo, "ls-files"],
                         capture_output=True, text=True).stdout
    paths = [p for p in out.split("\n")
             if p.strip() and os.path.splitext(p)[1] in EXTS]
    fileset = set(paths)
    fwd, barrel = defaultdict(set), set()
 
    for p in paths:
        try:
            src = open(os.path.join(repo, p), encoding="utf-8",
                       errors="ignore").read()
        except OSError:
            continue  # サブモジュール等で実体が無い場合は飛ばす
        if os.path.basename(p).startswith("index.") and len(REEXP.findall(src)) >= 3:
            barrel.add(p)
        d = os.path.dirname(p)
        for m in IMP.finditer(src):
            t = resolve(d, m.group(1) or m.group(2), fileset)
            if t and t != p:
                fwd[p].add(t)
 
    rev = defaultdict(set)
    for a, bs in fwd.items():
        for b in bs:
            rev[b].add(a)
    return paths, rev, barrel

errors="ignore" を入れているのは、実体のないパスが git ls-files に混ざるためです。ここで例外を上げると解析が途中で止まり、辺の少ないグラフを正しいものとして扱ってしまいます。最初の実行で 0 本ばかり返ってきたとき、私が真っ先に疑ったのがこの経路でした。

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

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
vite・hono・nest で測ると、1 ファイルの変更から到達するテストは中央値 0.0〜0.7% に対し p90 は 0.3〜50.4%。平均値で設計判断を下すと外れます
vite ではソース 1,148 本のうち 89.6% が import グラフ上どのテストにも到達しません。怖いのは選びすぎではなく、静かに 0 本を返す取りこぼしでした
index.ts の再エクスポートを経路から外すと nest の到達率は平均 4.0%→1.4%、p90 14.5%→2.5%。バレルが選択範囲を約 3 倍に広げていました
Stripe による安全な決済 · いつでもキャンセル可能

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

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

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

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

関連記事

Agents & Manager2026-07-16
AGENTS.md を厚くするほどルールが守られなくなった — 遵守率を計測して指示を削るまで
AGENTS.md に書いたルールが守られない。衝突でも読み込み失敗でもなく、単に無視されていました。ルールを検証可能な述語に分解し、遵守率を継続計測して指示を削るまでの運用記録です。
Agents & Manager2026-06-28
Antigravity の計画を、承認する前に削る
Planning モードが出してきた実行プランを、丸ごと承認するのではなく、危険なステップだけ削ってから渡す。部分編集という運用を、個人開発の現場目線で整理しました。
Agents & Manager2026-05-20
Antigravity エージェントのプロンプトキャッシュとコンテキスト戦略 — 長期運用で月額APIコストを6〜8割削る実装パターン
長く回し続けるエージェントほど、月末の請求は地味に効いてきます。個人開発で5,000万DL規模のアプリ事業を回しながらAdMob収益と並走させてみたところ、プロンプトキャッシュとコンテキスト戦略の組み合わせで API 費用を 6〜8 割削減できた実装の手応えがありました。本番運用で実際に使っているキャッシュ階層・コンテキスト圧縮・TTL 設計を、コードと数値でまとめました。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →