@@ -46,6 +46,8 @@ exposed through a bounded query helper.
4646 manifest absent).
4747 - ` workspace/kb/structural_index/units/ ` (content-addressed cache for
4848 incremental unit reuse).
49+ - ` workspace/kb/structural_index/native/ ` and sidecar ` provenance.json ` files
50+ (prebuilt index attachments and metadata manifests).
4951 - CODE_ROOT source files (via generated helper script — the script parses all
5052 source files under ` CODE_ROOT ` ).
5153- ** Writes** :
@@ -186,6 +188,39 @@ helper probes each tier per partition and selects the highest available:
186188 grep; no structural index is written. Manifest records ` status: "empty" ` .
187189 Consumers fall back to grep-based discovery (today's behavior byte-for-byte).
188190
191+ ** Native Index Probing & Resolution Rules** :
192+
193+ - ** Probe instruction** : Before evaluating per-partition backends, probe
194+ ` workspace/kb/structural_index/native/ ` and subdirectories
195+ ` native/{scip,lsif,kythe}/ ` for prebuilt index files.
196+ - ** Snapshot-declaration convention** : Because native formats (SCIP, LSIF,
197+ Kythe) do not embed snapshot identity directly in their binary payload,
198+ prebuilt indexes MUST declare their target snapshot using a sidecar
199+ ` provenance.json ` manifest located at
200+ ` workspace/kb/structural_index/native/provenance.json ` or
201+ ` native/<kind>/provenance.json ` . The manifest contains an array of
202+ attachments:
203+ ` [{"kind": "scip|lsif|kythe", "path": "...", "snapshot_id": "...", "root_fingerprint": "...", "language": "...", "indexer": "...", "precision": "semantic", "files": [...]}] ` .
204+ A native index is matched if its declared ` snapshot_id ` equals ` SNAPSHOT_ID `
205+ (when ` SNAPSHOT_ID != "unknown" ` ) or its ` root_fingerprint ` matches the
206+ workspace's calculated root fingerprint. If the ` files ` array is absent or
207+ empty, treat the native index as covering no individual files directly (record
208+ in ` manifest.native_indexes ` but do not update ` coverage ` rows; fall through
209+ to lower tiers for all files).
210+ - ** Record-and-Defer Ingestion Rule** : Parsing raw binary native indexes (e.g.
211+ SCIP protobuf) in pure Python without dependencies is costly and complex.
212+ Option A builder scripts MUST detect matching prebuilt native indexes, record
213+ their entries in ` manifest.native_indexes ` , and set the ` coverage ` table
214+ ` backend ` (e.g., ` "scip" ` or ` "scip-clangd" ` ) for all files listed in the
215+ provenance manifest. If ` catalog.sqlite ` is NOT populated with symbols from
216+ the native index (raw binary deferred to harness/MCP readers), set
217+ ` coverage.status = "deferred" ` and ` precision = "deferred" ` (with
218+ ` indexed_files = 0 ` ). This prevents the query helper from claiming an
219+ un-ingested partition is "authoritative empty" at ` semantic ` precision,
220+ ensuring consumers run the mandatory grep fallback. When ` catalog.sqlite ` IS
221+ populated (e.g., via Option B pre-ingestion or ` scip-to-sqlite ` ), set
222+ ` precision = "semantic" ` and ` status = "indexed" ` .
223+
189224** LSP is NOT equivalent to SCIP / LSIF.** LSP is an interactive protocol whose
190225workspace state may be partial or mutable. Use it only when the server can
191226demonstrate snapshot identity AND complete workspace coverage. A running
@@ -198,7 +233,7 @@ indexers (e.g., a SCIP index for Go + tree-sitter for Python) within a single
198233catalog.
199234
200235The determinism lives in a runtime-generated versioned helper
201- (` build_structural_index.py ` , ` # MANTIS_HELPER_VERSION = 4 ` , grep-and-regenerate
236+ (` build_structural_index.py ` , ` # MANTIS_HELPER_VERSION = 5 ` , grep-and-regenerate
202237on reuse) that probes and selects backends per partition. No shipped binaries;
203238air-gapped-safe.
204239
@@ -231,8 +266,8 @@ a different integer, REGENERATE.
231266#### Builder: ` build_structural_index.py `
232267
2332681 . Write the builder to ` workspace/helpers/build_structural_index.py ` . The FIRST
234- LINE MUST be exactly ` # MANTIS_HELPER_VERSION = 4 ` . Before reusing an
235- existing helper, grep its first lines for ` MANTIS_HELPER_VERSION = 4 ` ; if
269+ LINE MUST be exactly ` # MANTIS_HELPER_VERSION = 5 ` . Before reusing an
270+ existing helper, grep its first lines for ` MANTIS_HELPER_VERSION = 5 ` ; if
236271 that marker is absent or a different integer, REGENERATE the helper.
2372722 . The builder partitions the codebase into semantic units (see Per-Language
238273 Semantic Units), computes content-addressed cache keys, checks ` units/ ` for
@@ -261,8 +296,8 @@ a different integer, REGENERATE.
261296#### Query helper: ` query_structural_index.py `
262297
2632981 . Write the query helper to ` workspace/helpers/query_structural_index.py ` . The
264- FIRST LINE MUST be exactly ` # MANTIS_HELPER_VERSION = 4 ` . Before reusing an
265- existing helper, grep its first lines for ` MANTIS_HELPER_VERSION = 4 ` ; if
299+ FIRST LINE MUST be exactly ` # MANTIS_HELPER_VERSION = 5 ` . Before reusing an
300+ existing helper, grep its first lines for ` MANTIS_HELPER_VERSION = 5 ` ; if
266301 absent or a different integer, REGENERATE.
2673022 . The query helper provides bounded, paginated operations against
268303 ` catalog.sqlite ` (or a remote endpoint — identical API). It IS the
@@ -316,13 +351,14 @@ workspace/kb/structural_index/
316351├── shards/ # Partitioned serving data (large corpora)
317352│ └── shard_0000.sqlite
318353├── native/ # Prebuilt index attachments (SCIP, Kythe, LSIF)
354+ │ ├── provenance.json # Prebuilt index provenance manifest
319355│ ├── scip/
320356│ └── kythe/
321357└── tmp/ # Temporary objects during build
322358
323359workspace/helpers/
324- ├── build_structural_index.py # Builder (MANTIS_HELPER_VERSION = 4 )
325- └── query_structural_index.py # Query helper (MANTIS_HELPER_VERSION = 4 )
360+ ├── build_structural_index.py # Builder (MANTIS_HELPER_VERSION = 5 )
361+ └── query_structural_index.py # Query helper (MANTIS_HELPER_VERSION = 5 )
326362
327363workspace/kb/structural_index.jsonl # Compatibility pointer
328364```
@@ -347,7 +383,7 @@ workspace/kb/structural_index.jsonl # Compatibility pointer
347383 "coverage" : {"total_files" : 0 , "indexed_files" : 0 , "failed_files" : 0 , "deferred_files" : 0 },
348384 "shards" : [{"id" : " " , "path" : " " , "checksum" : " " , "partition_key" : " " , "symbol_count" : 0 , "edge_count" : 0 }],
349385 "deferred_units" : [{"unit_id" : " " , "language" : " " , "files" : [], "priority" : 4 , "reason" : " " }],
350- "native_indexes" : [{"kind" : " scip" , "path" : " " , "language" : " " , "indexer" : " " , "precision" : " " }],
386+ "native_indexes" : [{"kind" : " scip" , "path" : " " , "snapshot_id" : " " , "root_fingerprint" : " " , " language" : " " , "indexer" : " " , "precision" : " " }],
351387 "baseline" : {"source" : " ci|local|none" , "snapshot_id" : " " , "manifest_path" : " " },
352388 "overlay" : {"units_added" : 0 , "units_modified" : 0 , "files" : []},
353389 "compat_pointer" : {"path" : " structural_index.jsonl" , "full_export" : true , "symbol_count" : 0 },
@@ -379,7 +415,7 @@ CREATE TABLE IF NOT EXISTS symbols (
379415 kind TEXT NOT NULL ,
380416 signature TEXT ,
381417 backend TEXT NOT NULL ,
382- precision TEXT NOT NULL CHECK (precision IN (' semantic' ,' typecheck' ,' ast' ,' symbol-only' ,' heuristic' ,' coverage-only' )),
418+ precision TEXT NOT NULL CHECK (precision IN (' semantic' ,' typecheck' ,' ast' ,' symbol-only' ,' heuristic' ,' deferred ' , ' coverage-only' )),
383419 corpus TEXT DEFAULT ' default' ,
384420 partition_key TEXT ,
385421 unit_cache_key TEXT ,
0 commit comments