Feature Description
Make the FTS (full-text search) index rebuild incremental. Currently every compile / watch --once --repo / graph refresh run does a full DROP + recreate + re-index of the SQLite FTS tables, regardless of how many files actually changed — even a single new note triggers a complete rebuild of the entire index.
Motivation
On large vaults (e.g. 2500+ sources, ~8600 wiki pages) the full FTS rebuild dominates the compile pipeline:
- ~70–80% of compile/watch runtime is spent in
rebuildSearchIndex (verified in engine chunk-2PN46RDI.js, line ~19517): it DROP + re-creates pages/page_search, re-reads every wiki page file + manifest, parses frontmatter, then runs a full FTS5 re-index (INSERT INTO page_search SELECT ...).
- A clean run with zero changes takes the same 85–93 minutes as a run that changed 100 files. There is no incremental path at all.
- This makes the tool impractical for daily-driver workflows: adding one note to the vault costs ~1.5 hours of CPU on the next sync, and on constrained hardware (1 vCPU VPS) it risks sustained-load throttling.
The LLM analysis phase (ingest) is already incremental — only new/changed files get analyzed. The search index is the outlier.
Proposed Solution
A few possible directions (any would help):
- True incremental FTS: track per-source content hashes (already computed for ingest dirty-checking) and only re-insert/delete the rows for pages whose source content or generated wiki page changed, instead of dropping all tables.
- Skip FTS rebuild when nothing changed: reuse the existing dirty/hash logic — if no sources, no wiki pages, and no graph pages changed since the last index build, leave
fts-000.sqlite untouched (fast path: seconds instead of 90 min).
- Separate the FTS rebuild from the graph/wiki generation so it can be scheduled independently (e.g. nightly) rather than running on every
graph refresh --file.
Option 2 alone would remove the largest cost for the common "no changes / few changes" case without a full engine rewrite.
Alternatives Considered
- Telling users to run syncs less often (every 2–3 days) — works around the problem but keeps the 90-min worst case on every actual change.
- Disabling the FTS rebuild entirely — not acceptable, since the search index is what makes
query fast (~5s vs ~45s for raw grep over the vault).
- Switching to an external incremental indexer — heavy integration cost; native fix is preferable.
Environment
- Version: 3.20.0 (npm / GitHub Releases latest)
- Vault: ~2500 sources, ~8600 wiki pages, FTS index ~1.27 GB
- Hardware: 1 vCPU / 3.8 GB RAM (constrained — makes full rebuilds especially painful)
Feature Description
Make the FTS (full-text search) index rebuild incremental. Currently every
compile/watch --once --repo/graph refreshrun does a full DROP + recreate + re-index of the SQLite FTS tables, regardless of how many files actually changed — even a single new note triggers a complete rebuild of the entire index.Motivation
On large vaults (e.g. 2500+ sources, ~8600 wiki pages) the full FTS rebuild dominates the compile pipeline:
rebuildSearchIndex(verified in enginechunk-2PN46RDI.js, line ~19517): it DROP + re-createspages/page_search, re-reads every wiki page file + manifest, parses frontmatter, then runs a full FTS5 re-index (INSERT INTO page_search SELECT ...).The LLM analysis phase (ingest) is already incremental — only new/changed files get analyzed. The search index is the outlier.
Proposed Solution
A few possible directions (any would help):
fts-000.sqliteuntouched (fast path: seconds instead of 90 min).graph refresh --file.Option 2 alone would remove the largest cost for the common "no changes / few changes" case without a full engine rewrite.
Alternatives Considered
queryfast (~5s vs ~45s for raw grep over the vault).Environment