
AI エディタ(Claude Code、Antigravity、Cursor など)でブログ記事や管理文書(CLAUDE.md・GEMINI.md・TODO.md)の階層目次を整えた後、次に必ずぶつかるのが 「では .astro や .ts、.mjs、.js、.rs といったソースコード群や大量の下書き .md は、全文検索だけで本当に足りているのか?」 という疑問です。
当ラボの稼働ログ(transcript.jsonl)を実際に点検したところ、公開 706記事 と管理 15 文書の階層ナビゲーションを完成させた裏で、グラフ用 .astro コンポーネント 2 本の Props 仕様と登録状況を確認するだけでも AI が 1 セッションあたり 5 ステップ・計 7 回の手探り read_file を連発 していた実態が浮かび上がりました。さらに知識データベースの中には、1 行に圧縮された約 39KB の marked.min.js が 2 本も紛れ込み、検索結果を静かに汚染していたのです。
std)のみの状態機械スキャナで全コード拡張子(.astro・.ts / .mjs / .js・.rs)と下書き .md(計 1,220 ファイル)を SQLite 階層シンボル表(code_symbols / doc_sections)へ統合し、圧縮バンドル(*.min.js)を索引から排除 することで、160KB 超の巨大コードでも 2.7〜5.7 ミリ秒 で構造を即答でき、ファイル読込量を 最大約 98.6% 削減 できます。-
AIのツール呼び出し往復が遅い原因|Pure Rust前後一括化で出力83%減の実証録 : 小刻みなCLI呼び出しによるクラウド推論往復税と出力重複を断つため、前後工程をPure Rustのprep・finish 2発へ統合して出力最大83.5%削減を達成した続編の実証録です。
-
CLAUDE.md・GEMINI.md・TODO丸読みの罠|SQLite階層目次で読込99%減の実測録 : 本記事の直前に実施した「最頻参照の管理文書・整合性マップ・TODO台帳」のSQLite階層ツリー化とJSON読込引き締めの前編記録です。
-
macOSのSQLiteを3.54.1へ更新する方法|Homebrew終了の壁とRust静的リンク実証録 : 本基盤の土台であるPure Rustバイナリへ最新SQLite 3.54.1(AVX2最適化)を静的リンクし、OS標準の古いライブラリ依存を断ち切った実装録です。
-
検索エンジン不要のRAG「DecisionRAG」とは?階層探索の数理と1日13ドル時代の節約術 : 埋め込みベクトル検索に頼らず「棚一覧→章・シンボル木→数行Read」の3段階で降りる階層ナビゲーションの理論的背景を解説しています。
-
JavaScriptの型消去はなぜ怖い?2.6万行のツールをPure Rustへ統合した実証録 : スクリプト群を外部依存ゼロのPure Rustバイナリへ統合し、コンパイル時の型検査と高速実行を両立させた設計録です。
-
Rust製CLIの起動ラッパーが遅い原因|シェルfork税撤廃とSQLiteゼロコピーで5ms化した実証録 : シェル起動オーバーヘッドと文字列コピーを削ぎ落とし、SQLiteクエリを1桁ミリ秒台へ引き上げた基盤チューニングの詳細です。
-
Node.jsスクリプトをRust化すべき基準|V8起動税78ms撤廃と43倍高速化の実証録 : 毎回起動する開発補助CLIにおいてNode.jsのV8初期化コストがどう効くのかを実測比較しています。
-
Astro・Next.js・TypeScript・Rust などの複数言語が混在するプロジェクトで、AI が関数の場所や
Props型を探すたびに何百行もコードをめくっている方 -
コンポーネント後半の数百行におよぶ
<style>(CSS)や、圧縮済みの*.min.jsが コンテキストや全文検索に混ざってトークンを浪費している方 -
言語ごとの重い外部 C ライブラリを増やさず、手元の SQLite と軽量 CLI だけで全拡張子共通のアウトライン機能を作りたい開発者の方
結論:全コード階層索引化で変わった実測値
まずは、ワークスペース内の全コードファイルおよび下書き資料(.astro 47 本、.ts / .mjs / .js 243 本、.rs 49 本、下書き .md 881 本の 計 1,220 ファイル・合計約 32.6MB、管理 15 文書を含め全 1,235 ファイル)を SQLite のユニバーサル階層インデックス(Schema v4.3)へ統合した前後の実測比較を示します(2026 年 11 月 9 日、RAM ディスク常駐の kb-search および gemini-gate にて実機計測)。
| 対象ファイル・作業場面 | 従来の動作(全文1行格納+手探りRead) | ユニバーサル階層ナビ導入後(tree / --outline) |
応答速度・読込量の変化 |
|---|---|---|---|
LineChart.astro(1,257行・32.3KB)の Props と登録確認 |
[...slug].astro と合わせて 5ステップ・7回の手探りRead(CSS混在で探索難航) |
tree LineChart.astro 1発で4層行範囲・Props・MDXグローバル登録済 を即答 |
応答 2.75〜5.71ms ( Props 15行=約450Bのみ読込で 約98.6%減) |
scanner.rs(3,844行・160.3KB)の特定関数改修 |
関数名を知らないと先頭から数百行ずつ分割 read_file |
--outline scanner.rs で全48構造体・関数の開始〜終了行を一覧 |
応答 2.74ms (160.3KB丸読み回避・該当30行約1.2KBで 約99.2%減) |
consts.ts(443行・24.4KB)の末尾ヘルパー確認 |
単一行定数が延々と並び、どこから関数が始まるか手探り | tree consts.ts が単一行定数157件を4群に自動要約し末尾関数行を明示 |
応答 3.08ms (定数の壁に埋もれず1画面で全体把握) |
astro.config.mjs(326行・12.8KB)の設定キー特定 |
正規表現を含む326行を丸ごと read_file |
tree astro.config.mjs で defineConfig 配下の各設定キー行番号を即答 |
応答 3.62ms (設定ブロック5〜15行のみピンポイント読込) |
長大技術メモ .md(18,454行・1.30MB)の章特定 |
巨大すぎて read_file 上限(46KB)で何度も途中切断 |
tree 23_ai_...md で見出し333節の物理行範囲を即答 |
応答 5.40ms (1.3MBの手探りめくりを完全根絶) |
圧縮バンドル marked.min.js(39.0KB×2本) |
workspace_files に収録され検索時に1行39KBがヒット |
同期フィルタと --outline の双方で *.min.js 等を完全除外 |
収録 2本(78KB)→ 0本 (検索ノイズと誤読込リスクを物理遮断) |

管理ファイル(GEMINI.md や TODO)を片付けたと思ったら、今度は .astro や .rs のソースコード側に 30KB や 160KB の大物がゴロゴロ隠れとったんじゃな!

そうなんです!しかもソースコードの場合は、単純に「キーワードで全文検索(SQLite FTS5)すれば済む」と思われがちなのですが、実際の AI の行動ログを追いかけると、コード特有の構造が原因で何度も手探り read_file が起きていたんですよ。
管理文書の次に潜んでいたコード丸読みの3大罠
前編の管理文書・TODO階層化記事を公開した直後、ワークスペース内の残りすべての拡張子を SQLite 上で棚卸ししたところ、ソースコードと技術資料に特有の 3 つの丸読み・ノイズ地雷 が見つかりました。
手探り7回!AstroのPropsとCSS混在の罠
1 つ目の罠は、Astro 公式のコンポーネント構文が持つ「1 ファイル多層構造」です。.astro ファイルは、先頭の --- で囲まれた TypeScript フロントマター、中央の HTML / JSX テンプレート、クライアント側 <script>、そして末尾の <style>(CSS)が 1 枚のファイルに同居しています。
実際に当ラボで 47 本ある .astro ファイル(計 748.4KB)を調べると、シミュレーター画面(glucose-exercise-simulator.astro:3,430 行・108.5KB)や記事レイアウト(BlogPost.astro:1,414 行・47.5KB)、折れ線グラフ(LineChart.astro:1,257 行・32.3KB)など、後半の何百行もが CSS スタイル定義で占められているファイルが多数ありました。
本日の稼働トランスクリプト(サブエージェント fe6fabc7 の生ログ)を確認すると、記事へ <BarChart> と <LineChart> を追加する際、AI は以下の手順を踏んでいました。
-
ルーティング側の確認(1 回目) : 個別
importが必要かどうかを確かめるため、src/pages/blog/[...slug].astroの後半(L230〜L296)をread_file。 -
両コンポーネントの先頭確認(2〜3 回目) :
BarChart.astro(L1〜L90)とLineChart.astro(L1〜L90)をread_file。 -
内部計算・描画境界の追加探索(4〜7 回目) : ラベル幅やセグメント処理の位置が先頭 90 行だけでは分からず、
BarChart.astroの L91〜210、L221〜330、L331〜、さらにLineChart.astroの L91〜を次々と手探りで追加read_file。
しかもこの時は 6 つのサブエージェント班を並列稼働させていたため、各班で同じ .astro ファイルへの手探り読込が重複発生していました。「このコンポーネントはグローバル登録済みか?」「Props は何行目か?」「テンプレートと <style> の境界は何行目か?」という地図さえ最初から SQLite にあれば、この手探り 7 連発は 1 回で終わるはずだったのです。
定数170件の壁と圧縮min.jsの検索汚染
2 つ目の罠は TypeScript(.ts)や設定ファイル(.mjs)、そして下書き .md における 「密度の偏り」 です。たとえばプロジェクト共通定数を集めた src/consts.ts(443 行・24.4KB)には、export const の単一行定義が 157 件 も並んだ後に、文字列置換や日付ソート用の重要な関数群が末尾(L375〜L442)に置かれています。これを見出しや要約なしで単純列挙するとアウトライン自体が 170 行に膨れ上がり、逆に全文検索だけに頼ると「どんな関数が入っているファイルなのか」が俯瞰できません。また、チャット履歴から抽出した技術資料 .md(881 本・計 28.1MB)も、これまでは rule 棚の対象外だったため、1.3MB(18,454 行)ある資料の見出しツリーを引けない状態でした。
3 つ目の罠が、圧縮済みバンドルファイル(*.min.js)の混入 です。workspace_files テーブルを拡張子別に集計したところ、メールビューア用フォルダに置かれていた marked.min.js(わずか 70 行なのに 39,903 バイト=39.0KB)が 2 本(計 78.0KB)そのまま全文インデックスへ登録されていました。ミニファイされた JS ファイルは 1 行が数万文字の塊になっているため、一般的な英単語で code 検索や grep をかけた際にヒットすると、意味のない圧縮コードが大量に出力へ混入する原因になります。
外部依存ゼロ!全拡張子対応Rust解剖器の急所
ここで開発者が最初に思い浮かべるのは、「Tree-sitter のような構文解析ライブラリを言語ごとに組み込もうか?」というアプローチです。しかし、.astro・.ts・.tsx・.mjs・.js・.rs のすべてに対して外部 C パーサーをリンクすると、ビルド時間が跳ね上がるうえ、独自構文を持つ .astro の 4 層分離やプロジェクト固有のルーティング突合までは面倒を見てくれません。
そもそも AI エディタが read_file の範囲を絞るために欲しいのは、完全な抽象構文木(AST)ではなく「どの宣言・レイヤーが何行目から何行目まであり、どんな型引数を受け取るか」という正確な物理行番号マップ です。そこで今回も外部クレート依存ゼロを貫き、Pure Rust の標準ライブラリ(std)だけで動く決定論的コード解剖モジュール(code_outline.rs)を実装しました。
*.min.js・*.min.mjs・*.min.css・*.bundle.js を同期入口で完全除外。各ファイルの更新ミリ秒(mtime_ms)とサイズを個別記録し、未変更ファイルは 0ms でスキップします。
ルール・設計 15 文書(TODO_SEO_ROADMAP.md 含む全 4 冊の TODO 台帳)に加え、881 本(28.1MB)の下書き・監査 .md 資料もコード枠を除外して見出しツリー化します。
.astro(4 層+Props+MDX グローバル登録突合)、.ts/.mjs/.js(関数・型・クラス・defineConfig・単一行定数自動圧縮)、.rs(構造体・enum・trait・impl・関数)の開始〜終了行を保持します。
棚一覧(tree components / tree rust)から個別ファイルの行番号特定まで数ミリ秒で返し、AI は目的の 10〜30 行だけを read_file して編集を完結させます。
Astroの4層分離とMDX登録の自動突合
.astro ファイルを解析するうえで最も喜ばれる工夫が、「4 層分離」と「ルーティング側の mdxComponents 自動突合」の組み合わせ です。
パーサーはまず先頭の --- フェンス(テンプレートリテラルやブロックコメント内の --- は無視)を正確に特定して Frontmatter 層 を切り出し、その中身を TypeScript スキャナへ渡して interface Props の各フィールド要約や Astro.props の分割代入、内部ヘルパー関数の行番号を抽出します。続いて残りの領域から HTML / JSX テンプレート層、クライアント用の <script> 層(中身も JS として再帰解剖)、そして <style> 層(scoped か is:global かの属性判定に加え、内部の @media クエリの行範囲まで抽出)へと 4 分割します。
さらに同期および --outline 実行時には、記事描画の大元である src/pages/blog/[...slug].astro の mdxComponents オブジェクトを自動で読み取り、各コンポーネントが 「MDX グローバル登録済み(記事側での import 不要)」か「個別 import 必要」か をメタ情報として刻印します。これにより、AI がわざわざ [...slug].astro を別で read_file して確認する手間そのものが消滅しました。
正規表現やRust生文字列で括弧が狂わない工夫
「自前の軽量レキサで波括弧 { ... } の深さを数えて関数の終了行を出す」と聞くと、ベテランのエンジニアほど 「文字列や正規表現の中に { や " があったら一発で括弧カウントがズレるのでは?」 と心配されるはずです。
実は当ラボの実コードにも、素朴なパーサーを即死させる「意地悪な実例」がそのまま存在していました。たとえば astro.config.mjs の 64 行目には、Git 出力の引用符を剥がす rawPath.replace(/^"(.*)"$/, '$1') という正規表現リテラルがあります。JS / TS の正規表現 /.../ を認識できない単純なスキャナだと、正規表現の真ん中にある 1 個だけのダブルクォート " を「文字列の開始」と誤認し、それ以降のコードがすべて文字列扱いになって波括弧の階層が崩壊します。
また Rust の字句構造(The Rust Reference)でも、&'static str のようなライフタイムの単一引用符 ' を文字リテラルの開始と勘違いしたり、日本語の全角記号文字リテラル ':'(3 バイト UTF-8)や生文字列 r#"..."#、さらには ネスト可能なブロックコメント /* 外側 /* 内側 */ 外側 */ で深さが狂う落とし穴があります。これらを 1 件残らず無力化するため、レキサには以下の状態機械ルールを組み込みました。
- JSの正規表現
/^"(.*)"$/内の単独"で文字列モードが反転し、以降の関数を全ロスト - テンプレート文字列
`${a ? {x: 1} : {}}`内のネストした{}で終了行がズレる - Rustのライフタイム
'aとマルチバイト文字':'の区別がつかず文字判定が暴走
- 直前トークンから正規表現リテラルと文字クラス
[...]を判定し、行末リセットも併用 - テンプレート文字列の
${...}深さスタックを保持し、式の終端}とブロック終端を完全分離 - Rustのネスト
/*...*/・生文字列r#...#・char_indices()による1文字リテラル判定を実装

なるほどねぇ!重たい外部ライブラリを入れなくても、「関数の始まりと終わりの行番号を狂わせないための急所」だけをしっかり押さえれば、標準機能だけでそんなに正確に切れちゃうわけね!

その通りです!しかも Rust コンパイラの無警告テスト(gemini-gate の自己診断テスト第 60・61 項)も通してあるので、未使用コードの放置や *.min.js のすり抜けが起きないかまで毎回自動で検証されています。
実機計測:160KBコードも3ミリ秒で丸裸に
完成したユニバーサル階層ナビゲーション基盤を実際に動かし、出力内容とミリ秒単位の応答速度、さらに実装中に見つけて潰した「思わぬ探索ボトルネック」の実測値を公開します。
全1220ファイル一括階層化の速度と削減率
引数なしで ./scripts/run_kb_search.sh tree を実行すると、わずか 5.61 ミリ秒 で管理 15 文書の状況に続けて、全コード・下書き拡張子の「ユニバーサル階層アウトライン棚」が表示されます。
=== ユニバーサル階層アウトライン棚(コード&下書き全拡張子対応) ===
• Astro コンポーネント/ページ (.astro) : 47本 ( 748.4KB) | 4層・Props 490要素 (MDXグローバル登録:10本) -> `tree components`
• TypeScript / JS / 設定 (.ts/.mjs/.js) : 243本 (1277.4KB) | 型・関数・定数 557要素 -> `tree ts` / `tree mjs` / `tree js`
• Pure Rust ツール基盤 (.rs) : 49本 (2541.2KB) | 関数・構造体・impl 1278要素 -> `tree rust`
• 下書き・監査・技術資料 (.md draft) : 881本 ( 28.1MB) | 見出しツリー 18852節 -> `tree drafts`
ここからたとえば kb-search tree LineChart.astro(5.71ms)または gemini-gate --outline LineChart.astro(2.75ms)を叩くと、1,257 行(32.3KB)あるファイルの中身を一文字も丸読みすることなく、以下の構造マップが即座に返ってきます。
■ src/components/LineChart.astro [.astro | 全1257行・32.3KB | 抽出要素:34 | MDXグローバル登録済(import不要)]
[L1-L486] (layer) frontmatter — Astro Frontmatter (TS/Props) L1-L486
[L10-L17] (type) ChartColor [export]
[L19-L30] (interface) LineSeries [export] — name: string, values: (number | null | u…, unit?: string…
[L44-L58] (props) Props [export] — title: string, subtitle?: string, labels: string[], series: LineSeries[]…
[L60-L74] (props_init) Astro.props — 分割代入・既定値展開
...
[L278-L419] (fn) computedSeries — 142行ブロック
[L488-L832] (layer) template — HTML / JSX テンプレート (345行)
[L834-L1256] (layer) style — <style> (scoped)
[L905-L935] (media) @media (prefers-color-scheme: dark)
[L1251-L1255] (media) @media (max-width: 600px)
これを見れば、「MDX グローバル登録済みだから import は不要」「Props の詳細を見たいなら 44〜58 行目の 15 行だけ を read_file すればよい」「ダークモードの配色を直したいなら 905〜935 行目の 31 行だけ を開けばよい」と一瞬で判断できます。また単一行定数が 157 件並ぶ consts.ts でも、パーサーが単一行定数ブロックを「L16-L51(33件)」「L54-L133(67件)」のように 4 行へ自動圧縮して表示するため、末尾のヘルパー関数(L375〜L442)が一目で分かります。
探索順の罠を潰して106msを2.7msへ短縮
実装直後のベンチマーク計測では、ひとつ面白い発見がありました。SQLite を経由せず直接ファイルを読んで解剖する gemini-gate --outline 側で、パスを省略して単体ファイル名だけで --outline LineChart.astro と叩くと 2.75 ミリ秒 だったのに、--outline scanner.rs と叩いた時だけ 106.65 ミリ秒 かかっていたのです。
原因を調べると、単体ファイル名から実ファイルを探すフォールバック処理が src/ ディレクトリを先頭から順番に再帰走査しており、tools/ 配下にある scanner.rs にたどり着く前に src/content/blog/ 配下の約 700 個の記事サブフォルダを毎回すべて開いていた ことによる I/O ロスでした。
そこで、「拡張子が .rs なら tools/ を最優先で走査し、かつ .astro や .rs の単体名探索では公開記事フォルダ(blog/)をスキップする」というわずか数行の探索順最適化を入れたところ、3,844 行(160.3KB)の scanner.rs でも 106.65ms → 2.74ms(約 39 倍高速化) へと一気に短縮されました。推測で満足せず、必ず全拡張子で実機ミリ秒を測ることの大切さを改めて実感した瞬間です。
ローカル索引を快適化する開発機材と時間単価
ここまで規模が大きくなると(公開記事・管理文書・下書き・システムコードの全見出し約 2.7 万節+コードシンボル 2,325 個+会話履歴 DB)、クラウド側の AI に毎回ファイルを読ませて探させるよりも、手元のローカル母艦のメモリ(RAM)上に SQLite と Rust バイナリを常駐させて数ミリ秒で捌く設計 が圧倒的な威力を発揮します。
当ラボのように 16GB の RAM ディスクと SQLite のメモリマップ(mmap_size 計 1.5GB)、さらに Astro の並列ビルドやブラウザ検証を同時に余裕で回すなら、これから選ぶ現行母艦としては 64GB ユニファイドメモリ構成の『Apple Mac mini(Pro 系チップ搭載モデル)』 が最もバランスの良い投資になります。Apple 公式の Mac mini 仕様ページでも確認できる通り省スペースかつ静音性に優れ、仮に初期投資が約 30 万円前後としても、毎日 8 時間・5 年間(1,825 日)使い倒せば 1 日あたり約 164 円(1 時間あたり約 21 円) の快適コスト(推論・試算)です。メモリ不足のスワップ待ちや AI クオータ上限で作業が止まる損失を考えれば、十分すぎるお釣りが来ます。
また、数万節の階層インデックスを蓄えた _local_db/knowledge.sqlite や日々のスナップショットを高速にバックアップ・持ち運びする外部ストレージには、Thunderbolt 3(最大 3,000MB/s)と USB 3.2 Gen 2 の両規格に対応した高耐久モデル 『SanDisk Professional PRO-G40 SSD』 が頼りになります。防塵防滴・耐衝撃ボディで放熱性が高く、たとえば 2TB〜4TB クラスを 5 年間(1,825 日)使えば 1 日あたり約 25〜40 円前後(推論・試算)で、大切なコード資産とローカル DB を一瞬で退避できます。
まとめ:全コード階層索引を作るコピペ指示書
公開記事、ルール定義書、TODO 台帳、JSON、そして今回の .astro・.ts / .mjs / .js・.rs・下書き .md まで階層アウトライン化が完了したことで、ワークスペース内から「AI が中身を手探りで丸読みしないと構造が分からないファイル」がついにゼロになりました。
-
導入効果が非常に大きいプロジェクト : コンポーネント(
.astro/.vue/.tsx等)やバックエンドコード(.ts/.rs/.go等)が合計 50〜100 ファイル以上あり、1 ファイル 300 行を超えるモジュールや圧縮済み.min.jsが混在している環境。 -
まだ不要なプロジェクト : 全ソースコードが 10〜20 ファイル程度で、どのファイルも 100 行前後に収まっている小規模ツールや学習用リポジトリ。
ご自身の開発環境にこの「全拡張子対応・コード階層 SQLite ナビゲーション」を導入する際も、人間が正規表現や字句解析の境界バグと格闘する必要はありません。ただし、軽量モデルに任せると正規表現リテラルやコメント内の波括弧処理を省略して行番号ズレを起こしやすいため、必ず 『Gemini 4 Argon』 または同等以上の最上位推論モデルを選び、以下のプロンプトをコピー&ペーストして事前調査から進めてみてください。
以下の2本の検証記事で解説されている「管理文書+全ソースコード拡張子(コンポーネント・TS/JS・Rust等)のユニバーサルSQLite階層ナビゲーション基盤」を参考に、私のプロジェクトでもコードの手探り丸読みと圧縮バンドルの検索汚染をゼロにしたいです。
- 前編(管理文書・TODO階層化):
https://lab.chihouzakki.com/blog/review/claude-md-todo-sqlite-tree-navigation-99pct-token-cut/ - 後編(全コード階層化・min.js除外):
https://lab.chihouzakki.com/blog/review/astro-ts-rust-code-tree-sqlite-outline-guide/
【厳守してほしい手順】
- いきなりコードを書き換えたり外部の重い依存ライブラリを追加したりせず、まず現在のワークスペース内の全ファイルを拡張子別に集計(ファイル数・総行数・総バイト数、および
*.min.js/*.bundle.js等の圧縮ノイズ有無)して報告してください。 - 私のプロジェクトの使用言語に合わせ、①圧縮ファイルの索引除外、②文字列・コメント・正規表現リテラルで波括弧カウントが狂わない決定論的シンボル抽出(コンポーネントの場合はテンプレート層とスタイル層の分離や
Props要約を含む)、③ファイル別の更新時刻(mtime)による差分同期とtreeコマンドの実装計画を作成して提示してください。 - 私が計画に合意してから実装し、実在ファイルで開始行〜終了行のズレがないことと応答ミリ秒を計測して報告してください。

家の見取り図があれば、おやつが隠してある引き出しまで一直線でトコトコ行けるニャ。全部の部屋をひっくり返して探すのはもう卒業して、サクッと仕事終わらせて撫でるでちぃ!
管理文書の目次化とあわせてソースコード側の「行番号の地図」もローカル SQLite に持たせておくと、AI エディタの動きが見違えるほど軽快になります。ぜひ手元のプロジェクトでも試してみてください。


