
AI開発のファイル丸読みをゼロにするSQLite構造化術|コード・GSC・SKILL全統合の実測録
AI エージェント(Antigravity / Claude Code / Cursor 等)にプログラム改修や大規模サイトの運用を任せたとき、画面上に Analyzed(ファイル読込)やディレクトリ探索のログが何十回も並び、本来の作業に入る前にトークン枠と待ち時間が溶けてしまった経験はないでしょうか。事前の構造化インデックスがない環境では、AI は目的の関数や設定値を探すだけで「800 行刻みの手探り read_file」を繰り返し、さらにはツール出力の 10KB 切り詰めによる「退避ログの再読込ループ」を引き起こしてしまいます。
結論からお伝えすると、手探りの Analyzed 連発と出力切り詰め地獄を根絶する最適解は、記事原稿だけでなく システムコード全拡張子・環境変数・管理ルール・Search Console 生 JSON・さらにはワークスペース外の SKILL.md と MCP ツールスキーマに至るまで「全本数・全領域」を Pure Rust × SQLite に直結し、あらゆる照会を 1.7〜21 ミリ秒・1 コールで完結させる構造化インデックス基盤 を組むことです。本記事では、当ラボが kb-search Rev. 2.12.0 で到達した全資産 SQLite 直結の内訳と、運用で判明したエッジケースの防御設計を余すところなく公開します。
-
ブログ1記事の修正でAIは何回ファイルを読む?68回のDB照会と丸読み破産の実測録 : 写真1枚の追記の裏側で走っていた延べ68回のSQLite照会と、もし丸読みしていた場合に発生する約2.3MB〜12MB超の見えないI/O破産を実稼働ログから解剖しています。
-
AI自律開発の最適化7層総括|設計書3層分離・SQLite・Rust・Swarmの全設計図 : 700 記事・1.1GB 超へ成長した開発環境を週間枠数 % で回すための 7 層アーキテクチャ全体像と、設計書 3 層分離の仕組みを総括した設計図です。
-
AIのツール呼び出し往復が遅い原因|Pure Rust前後一括化で出力83%減の実証録 : 小刻みな CLI 呼び出しによるクラウド LLM の往復ターン税を解消するため、前後の定型工程を
prepとfinishの 2 コマンドへ統合した実証記録です。 -
SQLiteはなぜMySQLより速い?Astro×WAL・FTS5で記事探索をミリ秒化した実装録 : サーバー通信ゼロの SQLite が個別のファイル開閉より 35% 高速に動作する原理と、WAL モード・FTS5 全文検索の基礎設計を解説しています。
-
Search Console「一括データエクスポート」は必要?BigQuery課金の罠と無料API比較 : 有料の BigQuery 連携を使わず、無料の Search Console API とローカル環境で全記事の検索パフォーマンスを管理する実践手順です。
-
Node.jsのnode-compile-cache肥大化対策|Astro 7・RAMDisk退避でSSD書込ゼロ化 : Node.js v22以降のコンパイルキャッシュ肥大化をAPFS RAMDiskへ逃がし、SQLite高速化とあわせてローカル開発のSSD摩耗をゼロにする環境構築録です。
-
AI エージェントが作業のたびに
Analyzed(read_file)やgrepを何十回も連発 し、コンテキスト膨張や応答遅延に悩んでいる方 -
ツールの検索結果が 10KB 上限で
.system_generated/steps/*/output.txtへ切り詰められ、AI がそのログファイルをまたread_fileする悪循環を止めたい方 -
記事原稿だけでなく ソースコード(Rust / TS / Swift / Astro)・環境変数・GSC データ・外部スキル定義まで一括で SQLite 構造化 する具体的なテーブル設計と運用ノウハウを知りたい方
結論:手探りファイル丸読みを根絶する全資産SQLite直結
AI エージェントを用いた開発で最大の障壁(ボトルネック)となるのは、AI の推論能力そのものではありません。AI が「どこに何が書いてあるか」を把握するために繰り返す 手探りのファイル丸読み(Analyzed)とディレクトリ探索 です。
これまで当ラボでは、ベクトル DB に頼らず BM25 と SQLite でトークン破産を防ぐ設計 や、前後の定型処理を Pure Rust で一括化するサンドイッチ構造 を構築してきました。しかし、日々の開発と監査のトランスクリプト(実行履歴)を精査すると、記事本文以外の領域でまだ多くの Analyzed が発生している事実が判明しました。
そこで kb-search Rev. 2.12.0 では、ワークスペース内の全コード・環境変数・管理文書から、ワークスペース外にある AI エージェント自身のスキル定義(SKILL.md)や MCP ツールスキーマまで、AI が参照し得るすべての情報を単一の SQLite 知識データベース(knowledge.sqlite)へ完全統合 しました。
事前インデックス不在が招くAnalyzed連発の罠
事前インデックスを持たない一般的な開発環境で AI エージェントに「この機能を修正して」「SEO の未登録記事を調べて」と指示すると、AI は以下のような手探り行動を開始します。
- ディレクトリ構造を知るために
lsやfindを何度も実行する。 - 関数名や設定キーを探すためにシェルで
grepを走らせ、大量のノイズ行をコンテキストに流し込む。 - 数千行あるソースコードや仕様書を、先頭から 800 行刻み(
L1-L800,L801-L1600…)で何度もread_file(Analyzed) して目的の箇所を探す。 - 新規記事やコンポーネントを作る際、書き方の見本を見るためだけに既存の
.mdxや.astroファイルを何本も覗き見する。
実際に当ラボでも、全領域の構造化を完了する前は、1 記事の執筆・改修セッションあたり 平均 28 回の read_file(Analyzed) が発生していました。その内訳を解析したところ、実に半分以上が「仕様書の該当節を探すための分割読込」や「関数定義の行番号を探すためのコード丸読み」といった、データベースがあれば 1 コールで即決できる重複確認だったのです。
出力10KB切り詰めが引き起こす二次Analyzed地獄
さらに厄介なのが、AI エージェント環境に組み込まれている 「ツール出力の切り詰め(Truncation)機構」 です。
たとえば Antigravity などのエージェント環境では、1 回のコマンド実行(run_command)で返却される標準出力が一定の閾値(約 10KB 前後)を超えると、コンテキスト保護のために出力の途中が省略されます。そして、全文は .system_generated/steps/*/output.txt という一時ログファイルへ自動的に退避されます。
すると AI エージェントは、「省略された真ん中のデータを読まなければ」と判断し、退避された output.txt に対して再び 800 行刻みの read_file(二次 Analyzed)を連発し始めます。
- 複数の検索コマンドを
&&で 1 行に連結して実行する ➔ 出力合計が 10KB を超えてoutput.txtへ退避される ➔ AI がoutput.txtをread_fileする。 - 巨大な JSON(Search Console の生データなど)や長い
SKILL.mdを検索する ➔ 10KB を超えて切り詰められる ➔ 再びread_fileが走る。
この連鎖が起きると、1 回の質問で済むはずの調査が 5〜10 ターンのファイル読込ループに化け、親エージェントのコンテキストウィンドウを急速に圧迫します。結果として、KV キャッシュの効率悪化や単一ターンのタイムアウト停止(30 分上限やツール呼び出し回数上限)を招く直接原因となります。
- 800行刻みの分割丸読み :4,000行のRustコードや長大な仕様書を先頭から何度も
read_fileして目的行を探す。 - GSC生JSON・レポートの分割読込 :1.4MBのJSONや長文レポートを直接読み、10連発以上の
Analyzedを消費する。 - 10KB超過による二次Analyzed :出力が
output.txtへ切り詰められ、退避ログを読むための追加read_fileが連鎖する。 - 外部SKILL・MCPの毎回読込 :ワークスペース外の
SKILL.mdやMCP定義を確認するたびにファイル開閉が発生する。
- コード6系統・全10領域の行範囲直結 :4,571行のコードも関数名や行範囲(
L769-L912)指定でわずか 3.6ms でピンポイント抽出。 - GSC診断の読取専用1コール化 :最大1.4MBのJSON 5種を約 20ms・9.2KB以内 の意思決定サマリーへ自動凝縮。
- 8.6KB安全キャップ+続きコマンド案内 :10KB切り詰め閾値の手前で安全に止め、続きの行範囲取得コマンドを自動提示。
- 仮想パス
@agy/による外部統合 :ワークスペース外のSKILL.md(24本)とMCPスキーマ(26本)も 1.71ms で即座に照会。

なるほどなぁ。AIが賢くなったから何でも自動で探してくれると思っとったけど、目次も索引もない図書館に放り込んで「端から全部めくって探せ」と命じとるようなものだったんじゃね。

まさにその通りです!しかも1回のメモ帳(出力)が10KBを超えると別室に保管されて、それをまたページめくりで読み直す二度手間が起きていました。最初から全資産の「構造化索引」をSQLiteで作っておけば、AIは最初から目的のページだけを数ミリ秒で開けるようになります。
知識DBと対話履歴DBの全収録内訳とミリ秒応答の実測値
では、手探りの Analyzed をゼロにするために、具体的にどのようなファイルをどの粒度で SQLite に収録しているのでしょうか。
2026年11月14日時点における、当ラボの Pure Rust 製インデックス・検索エンジン kb-search Rev. 2.12.0 の実測収録データをすべて公開します。データベースは役割に応じて 「知識 DB(knowledge.sqlite:597.7MB)」 と 「対話履歴 DB(conversations.sqlite:866.8MB)」 の 2 つに分離・連携させています。
全照会21ミリ秒以下!知識DBの全10収録領域
SQLite 公式のベンチマーク論文「35% Faster Than The Filesystem」 で実証されている通り、OS のファイルシステム上で数百〜数千個の個別ファイルを毎回 open() / read() / close() するよりも、単一の SQLite ファイルからデータを読み出す方がシステムコールとディスク I/O のオーバーヘッドが劇的に小さくなります。さらに Write-Ahead Logging(WAL モード) と FTS5 全文検索拡張(Trigram トークナイザー) を組み合わせることで、597.7MB の全資産に対するあらゆる構造照会・全文検索が 1.7〜21 ミリ秒(0.0017〜0.021 秒) で完了します。
現在の knowledge.sqlite に収録されている全 10 領域の内訳は以下の通りです。
| 収録領域(カテゴリ) | 対象拡張子・データ源 | 収録ファイル・項目数 | 容量・構造化要素数(2026/11/14実測) | 主な照会コマンドと実測応答速度 |
|---|---|---|---|---|
| 公開記事・共通パーツ | .mdx |
公開 756記事+共通 7 件 | 解剖 9,222 節(約697万字)/内部リンク 6,923 本/アフィ辞書 492 件 | card / tree <slug> --full(3〜13ms) |
| Astroコンポーネント | .astro |
49 本(985.2KB) | 4層構造・Props定義 574 要素(MDXグローバル登録 10 本) | tree components / tree <名>(2〜4ms) |
| TypeScript / JS / 設定 | .ts / .mjs / .js |
257 本(1,351.4KB) | 型・関数・定数 604 要素(*.min.js / *.bundle.js 自動除外) |
tree ts / code "<語句>"(2〜5ms) |
| Pure Rust ツール基盤 | .rs |
56 本(3,571.9KB) | 関数・構造体・impl 1,702 要素(最大5,029行のソースも網羅) | tree rust / tree <file> L開始-L終了(3.6ms) |
| Swift Macアプリ群 | .swift |
30 本(659.0KB) | View・型・関数・MARK 487 要素(6アプリ全ソース) | tree swift / tree <file> --full(2〜4ms) |
| Shell / LaunchAgent | .sh / .plist |
18 本(92.1KB) | Shell 12本(149要素)+plist 6本(59要素)=計 208 要素 | tree sh / tree plist(1.8〜3ms) |
| 環境変数・設定台帳 | .env / 各種設定 |
29 種(生秘密値マスク済) | コード内参照箇所 計 114 箇所 を自動マッピング | env [<語句>](1.9ms) |
| 管理ルール・TODO・下書き | .md(文書・draft) |
ルール 13 文書 / 下書き 897 本 | ルール 194 節・TODO 302 項目 / 下書き 28.5MB・18,979 節 | manual / todo / tree drafts(2〜8ms) |
| Search Console 生JSON | _local_db/gsc/*.json |
生JSON 5 種(最大 1.4MB) | 公開全記事の検索順位・CTR・未登録・AI検索クエリを統合 | gsc [--unindexed|--opportunities](約20ms) |
| 外部 SKILL / MCP 定義 | @agy/ 仮想パス |
SKILL関連 24 本 / MCP 26 本 | 14スキル+付属10本(175.0KB)+2サーバー26ツールスキーマ | skill / mcp(1.71ms) |
公開記事 756記事 の内訳は、AI国家構想が 398本、実機検証録が 358本 であり、これに非公開の共通パーツ 7 本を含めたすべての .mdx ファイルが、フロントマター・見出し階層・生本文(raw_mdx)ごと格納されています。
さらにプログラムコードについても、単なるファイル名一覧ではなく、言語ごとの構文要素(関数・構造体・型・View・Props 等)である 「シンボル単位」 で幾つ抽出されているかに注目してください。
対話履歴DBによる3043スレッドと記事の逆引き結線
もうひとつの柱である対話履歴データベース(conversations.sqlite:866.8MB)には、これまでの開発や壁打ちで蓄積された 総会話 3,043 スレッド が完全収録されています。
- Antigravity ローカル対話ログ :
2,180件 - Web 版 Gemini(Google Takeout 抽出)履歴 :
863件 - 記事 × 会話の逆引き結線インデックス :計
17,807リンク
この 17,807 本の逆引きリンクにより、ある記事をリライトしたり過去の設計意図を確認したいとき、AI は _gemini_history/ フォルダ内の何千ものテキストファイルを探し回る必要がありません。kb-search card <slug> や kb-search convos "<語句>" --article <slug> を 1 回叩くだけで、「この記事のどの数値が、いつのどのチャット履歴で議論・決定されたか」を数ミリ秒で特定できます。
コードと環境変数を丸読みせず1コール抽出する構造化設計
記事本文の検索だけでなく、普段のプログラミングやツール改修で Analyzed(read_file)をゼロにするために最も威力を発揮しているのが、コード・設定 6 系統(11 拡張子)の構文シンボル構造化(workspace_files × code_symbols テーブル) と 環境変数レジストリ(env) です。
コード6系統と原稿のシンボル抽出・行範囲直結
システム開発において、1 ファイルが数千行に成長することは珍しくありません。たとえば当ラボの Rust 製エンジン内部でも、データベース同期を担う db_sync.rs は 4,571 行、コード構文解析を担う code_outline.rs は 4,428 行、ドキュメント階層ナビを担う doc_nav.rs は 4,136 行 あります。
もし SQLite インデックスがなければ、AI エージェントは 4,500 行超のファイルを把握するために、1 回 800 行上限の read_file を 6 回連続で実行するか、曖昧な grep を何度も繰り返すことになります。
これを防ぐため、kb-search は Rust 標準ライブラリのファイルメタデータ操作(std::fs::Metadata) と SHA-256 ハッシュ比較によって変更ファイルだけを高速検知し、コード・設定 6 系統(11 拡張子:計 410 本・3,575 シンボル) と 原稿・ルール文書 2 系統 の計 8 系統それぞれに専用の構文パーサーを備え、開始行・終了行・シグネチャと生テキストを SQLite へ同期しています。
-
Pure Rust(
.rs:56本・1,702要素) :fn(関数)、struct(構造体)、enum(列挙型)、impl(実装ブロック)、mod(モジュール)の定義名と正確な行範囲(L開始-L終了)を抽出します。 -
TypeScript / JavaScript(
.ts/.tsx/.js/.mjs/.cjs:257本・604要素) :export function、interface、type、const定数群を抽出します。この際、検索ノイズやトークン肥大化の元凶となる*.min.jsや*.bundle.jsなどの圧縮ファイルはインデックス段階で自動的に完全除外 します。 -
Astro コンポーネント・ページ(
.astro:49本・574要素) : フロントマター(サーバー処理・Props型定義)、テンプレート HTML、<script>、<style>(CSS@mediaブロック)の 4 層構造および、MDX にグローバル自動注入されている 10 本のコンポーネント設定を構造化します。 -
Swift Mac アプリ群(
.swift:30本・487要素) :BlogLedger.appを含む 6 つの自作 macOS アプリから、SwiftUI のView、struct、class、func、および// MARK: -セクション境界を抽出します。 -
Shell スクリプト(
.sh/.command:12本・149要素) : RAMDisk 構築やデプロイ自動処理を担うシェルスクリプトから、ヒアドキュメント境界を考慮したうえで関数定義・export変数・エイリアスを行範囲付きで抽出します。 -
macOS LaunchAgent 設定定義(
.plist:6本・59要素) : プログラミング言語ではなく XML 形式の設定ファイルである Property List 専用パーサーにより、launchd自動実行ジョブのキー定義(Label,ProgramArguments,StartInterval等)と設定値を構造化します。 -
公開記事の生 MDX(公開 756記事+共通パーツ 7 本) : 文書系パーサーとして、フロントマター(
fm)、importブロック(imports)、および見出しごとの生 MDX 本文をarticles.raw_mdxカラムから行番号指定で直接引き抜けます。 -
管理ルール・仕様書・下書き・SKILL(
.md:ルール 13 文書・下書き 897 本・SKILL 関連 24 本) : 3 層分離された設計書や外部スキル定義のすべての章節をdoc_sectionsテーブルへ収録し、kb-search manual "3.1" --fullやkb-search skill <名>の 1 コール(1.7〜2.4ms)で該当節のみを取得できます。
この仕組みにより、AI が 4,571 行の db_sync.rs の中にある特定の同期処理を確認・修正したい場合は、以下のように動作します。
kb-search tree db_sync.rsで関数一覧と行番号を確認する(または最初から関数名を指定する)。kb-search tree db_sync.rs L769-L912 --full(またはカンマ区切りで複数箇所L1-L55,L769-L912)を実行する。- わずか
3.6msで、物理行番号付きの該当コード(144 行分)だけがコンテキストに返却される。
手探りの read_file は 0 回 です。事前にコード・設定 6 系統と文書 2 系統の構文シンボルおよび物理行番号を SQLite に構造化しておくことで、4,500 行超の巨大ファイルであっても「必要な関数範囲だけを 3.6 ミリ秒で引き抜いて即座に edit_file する」という最短動線が成立します。
生の秘密値を保存しない環境変数レジストリと参照追跡
コードと並んで AI が頻繁に手探り検索してしまうのが、「どの環境変数が、どのスクリプトや Rust コードの何行目で使われているか」という設定調査です。
しかし、.env ファイルをそのままデータベースに格納したり、AI に無造作に read_file させるのはセキュリティ上のリスクが伴います。そこで kb-search の環境変数レジストリ(env テーブル)では、「秘密値の完全マスク保護」と「コード内参照箇所の自動マッピング」 を両立させました。
- 生秘密値の非保存(マスク徹底) :
.env等に記述された API キーやトークンの「生の値」は一切 SQLite に保存せず、キー名・設定ファイルの場所・値の有無(マスク表示)のみを記録します。 - 29 種の環境変数 × 114 箇所のコード参照追跡 :Rust の
std::env::var("...")、TypeScript / Astro のimport.meta.env....やprocess.env....、シェルスクリプトの$VAR展開を静的解析し、29種の環境変数がどのファイルの何行目で参照されているか(計114箇所) をすべて紐付けています。
これにより、AI は kb-search env を 1 回呼ぶだけで(約 1.9ms)、機密情報を一切露出させることなく、環境変数の影響範囲を漏れなく把握できます。こうした堅牢なテキスト解析とゼロコピーの高速 CLI を自作するうえで、Rust の所有権と型システムは最高の武器になります。
最後の死角だったGSC生JSONと外部SKILLの統合
記事原稿とワークスペース内のコードをすべて SQLite 化した後、最後に残っていた「Analyzed 連発の死角」が 2 つありました。それが 「Search Console(GSC)の大型生 JSON・診断レポート」 と 「ワークスペース外にある AI エージェント自身の SKILL.md・MCP ツール定義」 です。
kb-search Rev. 2.12.0 では、この最後の 2 大死角も SQLite へ完全統合しました。
最大1.4MBのGSC生JSONを20ミリ秒で凝縮
当ラボでは、Search Console API を用いた無料自動監査システム により、全記事のインデックス登録状態、検索クエリ、表示回数、クリック率(CTR)、さらには生成 AI 検索(AI Mode / AI Overviews)経由の長文クエリをローカルの _local_db/gsc/ に自動収集しています。
しかし、この生データ(JSON 5 種類)は最大で 1.4MB に達し、自動生成される Markdown レポートも数千行の規模になります。そのため、以前は「今日の Search Console で改善すべき記事はある?」と AI に尋ねると、AI が _local_db/gsc/*.md や *.json を先頭から分割で read_file し、たった 1 回の確認で 10 連発以上の Analyzed を発生させていました。
これを根絶するため、新設した kb-search gsc サブコマンドでは、生 JSON と SQLite の記事台帳をメモリ上で高速結合し、以下の 5 つの切り口を 読み取り専用・副作用ゼロの 1 コール(約 20ms・出力最大 9.2KB 以内) で即座に取り出せるようにしました。
kb-search gsc(全体サマリー:インデックス登録率・急上昇クエリ・優先対応枠の一覧)kb-search gsc --unindexed(未登録記事のステータス別一覧と経過日数)kb-search gsc --opportunities(表示回数が多いのに CTR が低い「タイトル・スニペット改善候補」の抽出)kb-search gsc --top(クリック数・表示回数の上位牽引記事)kb-search gsc --genai(AI 会話検索・長文相談クエリの検出)kb-search gsc --slug <slug>(特定記事 1 本の検索クエリ内訳とインデックス履歴)
さらにここで、運用上の極めて重要な知見から 「14 日クールダウン判定の基準日ロジック」 を刷新しました。
-
OS の物理
mtimeが引き起こす「クールダウン汚染」の罠 : SEO リライトを行った記事は、Google のクローラーが再評価するまで最低 14 日間は様子を見る(クールダウン期間を置く)のが鉄則です。しかし、判定基準にファイルの物理更新日時(OS のmtime)を使うと、全記事に対して「表記揺れの一括置換」や「フロントマターの軽微な整形」を走らせた瞬間、全 700 記事以上のmtimeが今日の日付に書き換わり、「全記事が今日リライトされた(=すべてクールダウン中)」と誤判定されて改善候補がゼロになる事故 が起きます。 -
SQLite 論理更新日
COALESCE(updatedDate, pubDate)による解決 : そこでkb-search gscでは、OS のファイルシステム上のmtimeを一切参照せず、SQLite のarticlesテーブルに格納されたフロントマターの論理日付COALESCE(updatedDate, pubDate)を基準に 14 日クールダウンを計算します。これにより、機械的な一括校正を行っても SEO 上の実質的な最終リライト日が 1 ミリも汚染されず、真にテコ入れすべき記事だけを正確に抽出できます。
ワークスペース外のSKILLとMCPを仮想パスで同期
もうひとつの死角が、AI エージェントの機能を拡張する スキル定義ファイル(SKILL.md) と Model Context Protocol(MCP)公式仕様 に基づくツールスキーマ(JSON) です。
Antigravity などのエージェント環境では、これらのファイルはプロジェクトのフォルダ(ワークスペース)の中ではなく、ユーザーのホームディレクトリ配下(~/.gemini/antigravity/builtin/skills/ や ~/.gemini/antigravity/skills/、~/.gemini/antigravity/mcp/ など)に配置されています。そのため、AI がスキルや MCP ツールの使い方・引数スキーマを確認しようとするたび、毎回必ず外部パスへの read_file(Analyzed)が発生していました。
そこで kb-search Rev. 2.12.0 では、同期の対象領域をワークスペース外へも拡張し、仮想パス @agy/ プレフィックス を付与して knowledge.sqlite へ一括インデックス化しました。
- 外部・内蔵スキル定義(
SKILL.md関連) :計24本(14スキル本体+付属リファレンス・スクリプト10本、合計175.0KB)を見出しセクション単位まで分解して収録。 - MCP ツールスキーマ定義 :計
26本(2サーバー分の全ツール名・説明文・必須パラメータ・JSON Schema)を構造化収録。 - 実測照会スピード :
kb-search skill [<スキル名> [<節|L1-L99>]] [--full]およびkb-search mcp [<server> [<tool>]]により、わずか1.71msで必要なセクションや引数定義だけをピンポイント抽出。
公開 756記事(+共通パーツ7本・計9,222節)、下書き897本(18,979節)、管理ルール13文書、および対話履歴3,043スレッド(逆引き17,807リンク)を全文検索・行番号直結で保持。
計410本のコード・設定ファイル(6系統・11拡張子)から3,575個の構文シンボル(関数・型・View・Props・plistキー)を抽出し、.env の生秘密値をマスクしたうえで29種の環境変数と114箇所の参照行をマッピング。
GSC APIから取得した大型JSONを直接 read_file させず、COALESCE(updatedDate, pubDate) 基準の14日クールダウン判定と結合して約20msで要約出力。
~/.gemini/antigravity/ 配下の内蔵・カスタムスキルとMCP定義を仮想パス @agy/ で差分同期し、1.71msでセクション・引数単位の照会を実現。
運用で判明した2大エッジケースと再発防止ガードの実装
このように「すべてのファイルを SQLite に入れて CLI から引けるようにする」だけでも大きな効果がありますが、実際の AI エージェント環境(特にセキュリティサンドボックスと出力制限がある環境)で毎日運用してみると、単純な実装では防げない 2 つの重大なエッジケース(境界条件の罠) に直面しました。
読者の方がご自身の開発環境に同様の SQLite インデックスを導入する際、必ず役立つ防御設計として、当ラボが実装した 2 つの対策を詳しく共有します。
出力切り詰めを防ぐ8.6KBキャップと続き行の自動案内
1 つ目のエッジケースは、前半でも触れた 「エージェントのコマンド出力 10KB 切り詰め閾値との衝突」 です。
いくら SQLite から 2 ミリ秒でデータを引き出せても、--full オプションで長大な仕様書の章節や大きな SKILL.md を一括出力した際、出力テキストが 10KB を超えてしまえば、エージェント環境側で .system_generated/steps/*/output.txt への強制退避が発動します。すると AI は退避されたテキストファイルを読むために結局 read_file(二次 Analyzed)を実行してしまい、せっかくの SQLite 直結が台無しになります。
この問題を 100% 防ぐため、kb-search の出力フォーマッタには 「8.6KB 安全キャップ(GSC 統合サマリーでは 9.2KB 上限)」 と 「続き行範囲コマンドの自動案内」 を実装しました。
-
行単位のバイト数積算と安全停止 :
kb-searchがコードやドキュメントの行を出力する際、1 行ごとに UTF-8 バイト数を積算します。エージェント側の 10KB 切り詰め閾値に到達する手前の8.6KB(8,800 バイト前後) に達した時点で、行の途中で文字化けや構文崩壊を起こさないよう、直前の改行境界で出力をピタリと止めます。 -
続きを取得するための「完全コピペ用コマンド」を自動提示 : 出力を止めた末尾に、単なる「省略されました(truncated)」というメッセージではなく、
💡 続きを取得するには: ./scripts/run_kb_search.sh skill <name> L121-L240 --fullのように、次に叩くべき正確な開始行・終了行入りのコマンドを自動生成して添えます。 -
二次
read_fileの完全消滅 : これにより、AI エージェント側で.system_generated/steps/*/output.txtのファイル退避が一切発生しなくなり、万が一長文の後半が必要な場合でも、提示された行範囲コマンドをもう 1 回(約 2ms)呼ぶだけで安全に読み進められます。
サンドボックス権限エラー時のピンポン削除防止ガード
2 つ目のエッジケースは、「隔離サンドボックス実行時における外部ファイル(@agy/*)のピンポン削除問題」 です。
Antigravity をはじめとする最新の AI エージェントは、安全性のためにデフォルトで 標準サンドボックスモード(BypassSandbox: false) でコマンドを実行します。このサンドボックス内では、プロジェクトのワークスペース(/Users/$USER/Desktop/ai-blog-project 等)や RAMDisk(/Volumes/RAMDisk/$USER)への読み書きは許可されていますが、ワークスペース外にあるホームディレクトリ配下(~/.gemini/antigravity/ 等)へのアクセスは OS レベルで遮断され、PermissionDenied(権限エラー)が返ります。
ここで、一般的なデータベース同期(sync)のアルゴリズムを考えてみてください。通常、インデックス同期処理では「現在ディスク上に存在するファイル一覧」と「SQLite 内に記録されているファイル一覧」を照合し、ディスク上から消えたファイルを SQLite からも DELETE する(孤立レコードの自動パージ) という処理を行います。
もしこの削除ロジックをそのまま動かしてしまうと、以下のような 「ピンポン削除現象」 が発生します。
- サンドボックス外(人間のターミナルやデプロイ処理)で
kb-searchが動く ➔~/.gemini/antigravity/が読めるため、@agy/*の 50 レコード(SKILL 24 本+MCP 26 本)が SQLite に登録される。 - 次に AI エージェントがサンドボックス内(
BypassSandbox: false)から検索を実行し、自動差分同期が走る ➔~/.gemini/antigravity/の走査がPermissionDeniedで 0 件になる ➔ 同期エンジンが「外部ファイルがすべて削除された!」と誤認し、SQLite から@agy/*レコードを全削除してしまう。 - 結果として、AI がサンドボックス内から
kb-search skillやkb-search mcpを叩いた瞬間、せっかく登録したレコードが消えて検索ヒットが 0 件になる。

あらまぁ!お掃除機能が真面目に働きすぎるせいで、鍵がかかって外が見えないだけの時に「外の荷物が全部なくなった!」と勘違いして台帳から消しちゃうわけね!

そうなんです!普通にテストしているだけでは気づきにくい、サンドボックス環境ならではの落とし穴でした。そこで「本当にファイルが消えたのか、それともサンドボックス制限で見えないだけなのか」を厳密に区別する保護ガードを組み込みました。
具体的には、db_sync.rs の外部リソース同期フェーズにおいて、以下の 「ピンポン削除防止ガード」 を実装しています。
- 外部ディレクトリ(
~/.gemini/antigravity/builtin/skills等)を走査する際、ディレクトリ自体のメタデータ取得やread_dirがPermissionDenied等の I/O エラーを返した場合は、「サンドボックスによるアクセス制限中(Unreachable)」 というフラグを立てる。 - 孤立レコードの削除(パージ)処理を行う際、外部ディレクトリが Unreachable 状態であれば、仮想パス
@agy/で始まるすべてのレコード(workspace_files,code_symbols,doc_sections)を削除対象から完全除外して既存のキャッシュを 100% 温存 する。 - さらに
kb-search skillやkb-search mcpなどの読み取りコマンド側でも、すでに SQLite 内に@agy/*レコードが存在する場合は無駄な再同期を走らせず、即座に既存テーブルから1.71msで結果を返す。
この 2 つのエッジケース対策によって、サンドボックスの内外を問わず、いつでも安定してミリ秒応答・出力切り詰めゼロで全資産を引き出せる盤石な基盤が完成しました。
まとめ:自分の開発環境に全資産SQLite索引を導入する手順
最後に、本記事で解説した「手探り Analyzed ゼロ・全資産 SQLite 直結アーキテクチャ」をご自身のプロジェクトや AI 開発環境へ導入する際のステップを整理します。
最初からすべての言語パーサーを作る必要はありません。以下の 4 ステップで段階的に対象領域を広げていくのが最も確実です。
Markdown原稿やルール文書を見出し(##/###)単位で行番号とともにSQLiteへ格納し、章節の1コール抽出を作る。
主要言語の関数・型・View定義の開始/終了行を抽出し、*.min.js 等を除外したうえで行範囲ダイレクト取得を実装する。
GSC等の大型JSONを論理日付基準で要約し、外部の SKILL.md やMCP定義も仮想パス(@agy/)で同一DBへ取り込む。
出力切り詰めを防ぐ8.6KBキャップ+続きコマンド案内と、サンドボックス時のピンポン削除防止ガードを入れて完成。
推論ですが、1 回の機能改修や記事執筆で発生していた 20〜30 回の手探り read_file(800 行×25 回=約 20,000 行分のコンテキスト流入)と、10KB 切り詰めによる二次 Analyzed をこの SQLite 直結ナビへ置き換えることで、1 タスクあたりの入力トークン消費量は約 70〜85% 削減され、AI が最初のコード編集に着手するまでの初動時間も数分から十数秒へと劇的に短縮 されます。
-
手探りの
Analyzed(read_file)とgrep連発が消える : 597.7MB の知識 DB と 866.8MB の対話履歴 DB から、記事・コード6系統・環境変数・GSC・外部 SKILL・MCP の全 10 領域を 1.7〜21 ミリ秒 でピンポイント抽出できます。 -
10KB 出力切り詰めによる「退避ログ再読込」が起きない :
8.6KB安全キャップと続き行範囲コマンドの自動案内により、.system_generated/steps/*/output.txtへの切り詰め退避と二次Analyzedを物理的に防げます。 -
サンドボックス環境でも外部スキル・MCP を高速参照できる : 仮想パス
@agy/とピンポン削除防止ガードにより、PermissionDeniedが発生する隔離環境からでもSKILL.md(24 本)と MCP スキーマ(26 本)を 1.71ms で照会できます。
「AI エージェントにファイルを端から丸読みして探させる」のではなく、「Pure Rust と SQLite で構造化した高速な地図を渡して、AI には本来の思考と実装だけに集中してもらう」。規模が大きくなればなるほどこの差は何十倍もの生産性の違いとなって表れますので、ぜひご自身の開発環境にも SQLite 直結インデックスを取り入れてみてください。

