Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/nornir

.nornir/introspection-warehouse-delta-landed.md

Introspection warehouse DELTA — file-level incremental scan + inotify (LANDED)

The JetBrains-beating re-index lever, built in nornir (design audit: workspace_nordisk/.nornir/introspection-warehouse-efficiency.md §P0.1/§P0.2). A full symbols::scan_repo re-parses every .rs in a member on any change and re-emits the whole row set; JetBrains wins by re-indexing only the edited file. This closes that gap.

What landed

File-level incremental scan — src/knowledge/delta.rs

Evict-on-change invariant: a changed file's removed symbols disappear because its rows are evicted before the re-parse merges the fresh set. Proven by delta_matches_full_rebuild (delta result == from-scratch full build, exactly).

inotify watch mode — src/knowledge/watch.rs

Wired 2026-07-23 — it had no caller and no build

For a month watch() had zero callers and the inotify feature was named by no build variant, so the real inotify loop was compiled by nothing. Green tests the whole time, because the module's four tests only drive the pure Debouncer. Closed by:

Placement (Rickard, 2026-07-23). inotify is for a live tree — one that changes WITHOUT git. On a server the git transaction is the trigger and gix sees every change, so monitor::sync_once's poll stays the path there and the default variants leave the feature off. That is a deliberate narrowing of the original "inotify REPLACES the timer-poll, full stop" (workspace_nordisk/.nornir/populate-background-delta-design.md §2): the mechanism is the one that doc specifies — FS events → debounce → per-member delta — but it is mounted on the CLI live-tree entry point, not inside the monitor.

Bench + functional_status

SCIP — reused, not re-derived

ScipRow carries the same repo-relative path, so the identical evict-by-file / merge-by-file machinery applies to a ScipScan unchanged. SymbolDelta::evict_file is the exposed shared key. Resolved tables are still populate-gated, so this landing deltas the populated syn layer; routing the resolved layer through the same key is the remaining SCIP wiring.

Latency intuition

Delta-rescan ≈ O(1 file parse) + O(N stat) vs full-rebuild O(N file parse) — speedup_vs_full grows ~linearly with N.

Not done (risk-gated)

Row-level Iceberg MOR/equality-delete append (iceberg.rs:2060) — rewrites warehouse commit/schema semantics, bench-gated per the audit. The delta engine produces the exact changed row-set (the hard part); the MOR write path is the remaining follow-up. Until it lands, a delta appends the merged whole scan as a new snapshot (correct — readers take the latest snapshot per repo — but it writes N rows for a 1-file change, so the delta's win today is the parse, not the append).

Routing the monitor's timer-poll through watch() is explicitly NOT a follow-up any more — see the placement note above: a git-driven server does not need it.