Skip to content
🚧 Early alpha — building the foundation. See the roadmap →

WASM-A pivot — synthesis (sqlite-vec deferred; calendar-anchored 2026-11-06 revisit)

Created Updated
QuestionVerdictConfidence
Ship vec from day 1 in v0.1.5 (WASM-B)?REJECT — demo artifact incompatible with Electron rendererHigh (5 issues confirmed in succession)
Defer vec; ship plain sqlite-wasm in v0.1.5 (WASM-A)?ADOPT — Phase 1 substrate scaffolding green; 6/6 smoke tests passHigh
Calendar-anchored revisit for vec2026-11-06 (6 months out)Locked
Ch 24 §4 substrate commitment violated?No — substrate is @sqlite.org/sqlite-wasm + sqlite-vec. Vec deferred temporarily per schema spec §7 line 733 (“v0.1+ optional add-on; defer concrete DDL”). Substrate commitment intact.High

WASM-B rejection (one breath): the sqlite-vec-wasm-demo artifact (v0.1.9, official from asg017) is a demo build (-sENVIRONMENT=web; debug symbols; no size optimization). Obsidian’s Electron renderer is a hybrid environment — window (Chromium) AND process (Node integration) both exist. The demo’s emscripten-generated env detection sees process.versions?.node and aborts with “not compiled for this environment”. Patching that surface revealed 4 more downstream emscripten quirks (new URL('.', blobURL) rejection; Module.postRun already processed init order; etc.). Each fix exposed the next layer of mismatch. The artifact is fundamentally wrong-environment for Electron.

WASM-A adoption (one breath): @sqlite.org/sqlite-wasm (the official SQLite-team build) is also web-targeted but has been hardened for Electron via well-established Obsidian-plugin precedent. Loading it via Blob URL (Obsidian’s app:// URLs can’t be dynamic-imported as ES modules) just works. All 6 Phase 1 substrate-scaffolding smoke tests pass on the first integration attempt. SQL projection (Tier 2’s primary value) is fully operational.

Calendar revisit (one breath): trigger-based revisit alone allows infinite postponement. A hard date (2026-11-06) forces a check even if no triggers fire — the upstream tooling could improve quietly. We commit to checking on that date OR sooner if any of the 5 listed signals fire.

§3 The 5-issue chain — what specifically broke

Section titled “§3 The 5-issue chain — what specifically broke”

Honest record so future-us doesn’t underestimate the next attempted vec integration:

#IssueRoot causeResolution attempted
1Build target mismatchsqlite-vec-wasm-demo uses BigInt literals (ES2020+); esbuild was set to ES2018Bumped esbuild target to ES2020 ✓
2wdio service file copy gapobsidian-launcher hardcodes copying only manifest.json + main.js + styles.css (verified at node_modules/obsidian-launcher/dist/chunk-DSNG7BMO.js:1535-1538); the additional .wasm + .mjs aren’t copied to the test vaultAdded wdio.conf.mts before hook to copy them manually ✓
3Env-detection throwDemo artifact’s emscripten init does if (typeof process !== 'undefined' && process.versions?.node) throw new Error('not compiled for this environment'). Obsidian’s renderer exposes Node integration → throwsPatched the .mjs string before Blob URL load ✓
4new URL('.', blobURL) rejectionWhen loaded via Blob URL, import.meta.url becomes a blob: URL; Chromium rejects relative-URL parent computationPatched import.meta.url references to a placeholder HTTPS URL ✓
5Module.postRun already processedEmscripten init order issue surfaced after the prior fixes. Init context is in inconsistent stateUnresolved — root cause not fully diagnosed; treated as evidence the demo artifact isn’t tractable in this environment

Superseded 2026-09-12. Issue #2 above (the wdio file-copy gap) no longer applies to the shipped distribution path: the plugin now embeds the SQLite engine directly in main.js, so no loose .wasm/.mjs files need to be copied into any vault, test or production. See inline SQLite distribution synthesis. This does not change the sqlite-vec pivot decision recorded here or its calendar-anchored 2026-11-06 revisit.

After issue #5, the user accepted the WASM-A revert. The cumulative pattern (5 issues in succession, each requiring a non-trivial workaround) is itself the diagnosis: the demo artifact is the wrong tool for this environment. A proper vec integration needs either upstream Electron support or a custom build (WASM-C).

§4 What’s locked in (revised v0.1.5 substrate commitments)

Section titled “§4 What’s locked in (revised v0.1.5 substrate commitments)”
Aspectv0.1.5 lock
Substrate (v0.1.5 ship state)@sqlite.org/sqlite-wasm@3.53.0-build1 (plain — no vec)
Vector layerDeferred; schema reserves the concept_embeddings vec0 virtual table DDL commented out for additive re-introduction
WASM packagingWASM-A (npm-installable plain sqlite-wasm; loaded via Blob URL workaround for Obsidian app:// URL constraint)
Schema additivityConcepts / mappings / junction_notes don’t depend on vec → vec lands additively when re-introduced; no schema migration needed
Substrate commitment from Ch 24 §4Intact — @sqlite.org/sqlite-wasm + sqlite-vec is still the chosen pair; vec is sequenced separately
Bundle size~700 KB compressed plugin total (within Ch 24 §2.2 budget)

§5 Migration triggers — when to revisit

Section titled “§5 Migration triggers — when to revisit”

Per Ch 24 §5 Q4 (revised in this session). Calendar-anchored revisit: 2026-11-06. Even if no signal fires below, re-check the upstream sqlite-vec packaging state on that date.

Re-evaluate when ANY of:

  1. Bundle-size pressure surfaces — community plugin reviewer pushback, mobile load-time issues, user complaints. Lower priority for WASM-A (we’re under budget); will be the dominant trigger if/when WASM-B is retried.
  2. sqlite-vec upstream ships a production-quality npm-installable WASM — size-optimized, Electron-compatible, distinct from the demo. Most likely path 1.
  3. @sqlite.org/sqlite-wasm ships sqlite-vec compiled in — the SQLite team statically links sqlite-vec into their build. Aligned incentives (SQLite Inc sponsors sqlite-vec).
  4. @sqlite.org/sqlite-wasm gains runtime extension loading in WASM — currently disabled for browser security; if upstream flips it on, sqlite-vec loads as a runtime extension cleanly.
  5. Concrete need for custom build (WASM-C) that no off-the-shelf artifact satisfies — custom flags, patches, size trim, reproducibility for compliance.
  6. Demo artifact is abandoned upstream — no release for 12+ months AND no community fork has gained traction.

If the 2026-11-06 checkpoint arrives and all are still negative → push the checkpoint another 6 months OR commit to WASM-C (custom emcc build with -Os + LTO + feature trim).

Prior decisionThis pivot’s relationship
Ch 24 §4 v0.1 lock — substrate is sqlite-wasm + sqlite-vecPreserved. Vec is sequenced (deferred), not abandoned. The substrate pair is still the chosen end-state.
Ch 24 §3 vector-layer decouplingReinforced. The fact that vec can be sequenced separately because it’s purely additive in the schema is the modularity property paying dividends.
v0.1 schema spec §7 line 733 — “Loading sqlite-vec is a v0.1+ optional add-on; defer concrete DDL”Sanctioned. This pivot is exactly what the spec line authorized.
Path C user instruction (2026-05-05) — ship vec from day 1Walked back with user approval. User explicitly accepted “if we need to revert, then we will later” framing 2026-05-05; user explicitly approved revert 2026-05-06 after reviewing the 5-issue chain. Calendar revisit (2026-11-06) is the new commitment.
v0.1.5 milestone scopeAdjusted: “Out (deferred)” list grew with vector-search UI + embedding generation; substrate ships plain sqlite-wasm; revisit checkpoint section added.

No commitments are abandoned. The vec layer is deferred, not removed.

  • Does not foreclose vec ever shipping — calendar revisit keeps the option live; rollback path is ~30 min if vec is later removed
  • Does not change the substrate commitment — sqlite-wasm + sqlite-vec is still the end-state
  • Does not change the schema — concepts / mappings / junction_notes tables don’t reference vec; the concept_embeddings vec0 virtual table is reserved (commented-out DDL in migrations.ts); vec lands additively
  • Does not change the recovery property — Tier 2 still purely a Tier 1 projection; deletable; reprojectable
  • Does not change Tier 1 schema — Tier 1 is unchanged; vector embeddings would be a Tier 2-only feature when vec ships
  • Does not invalidate Phase 2 work — projector ships completely; v0.1.5 Phases 3-6 proceed unchanged
  • Phase 3 (query API + closure cache) unblocks immediately — recursive-CTE transitive closure works on plain sqlite-wasm; no vec dependency
  • Phase 4 (plugin integration) — onLayoutReady projection trigger; clear-sidecar command; settings toggle. All vec-independent.
  • v0.1.6 (Bases query layer) — vec-independent
  • v0.1.7 (exporters STRM/OSCAL/SSSOM) — vec-independent
  • v0.1.8 (audit trail) — vec-independent
  • v0.1-RC — ships without vec; bundle stays well under 1.2 MB
  • 2026-11-06 checkpoint — revisit vec packaging state; sequence WASM-B retry or WASM-C custom build per signals at that time

§10 Owner input added 2026-08-21 — index proliferation is a first-class cost

Section titled “§10 Owner input added 2026-08-21 — index proliferation is a first-class cost”

Raised by the owner while deciding an unrelated Tier 2 defect, and recorded here because it is a direct input to the 2026-11-06 revisit rather than to anything shipping sooner.

The concern, in the owner’s framing: a vault may eventually run several plugins that each index it. The owner maintains a separate search plugin of their own, and the prospect of four plugins independently crawling and embedding the same vault is a real cost — battery, memory, startup time, and duplicated storage. “Do we want to index the whole vault” is a much larger question than any single defect makes it look.

Why this does not apply to Tier 2 as it stands today (verified 2026-08-21 against src/tier2/projector.ts):

WorryActual behavior
A second full-vault crawlThere is none. The projector never reads file contents. Frontmatter comes from app.metadataCache, the index Obsidian builds once and every plugin shares
Indexing every noteIt does not. Files without a _crosswalker block are skipped, so only Crosswalker-generated notes are stored. A pathFilter can narrow it further
Duplicating what a search plugin doesDifferent data structure for a different question. A search index answers “which notes contain this text”; Tier 2 answers “what is transitively connected to this concept across frameworks” — joins, recursion, anti-joins, which is precisely why Tier 2 exists rather than Bases alone

Why it applies squarely to sqlite-vec. Vector search is the point where Crosswalker would stop reusing shared infrastructure and start building its own embedding index over vault content — the exact shape of the owner’s concern. Any revisit that concludes “adopt sqlite-vec” must therefore answer:

  1. What content gets embedded — only Crosswalker-generated notes, as the projector does today, or vault-wide? Vault-wide is a materially different product decision and should not arrive by implication.
  2. What is the cost when other embedding plugins are already installed, and is there any way to consume an existing index rather than build a second?
  3. Could the capability be delivered by cooperating with a search plugin the user already runs? Note the constraint found 2026-08-21: Obsidian offers no standard cross-plugin index API. metadataCache is the shared one and Tier 2 already uses it. Plugin-to-plugin access means reaching into another plugin’s runtime object, which is undocumented, breaks on their releases, and hard-fails when that plugin is absent.
  4. Is the added capability worth being the fourth thing indexing the vault?

Standing principle this establishes, independent of the vec decision: reuse the shared index before building a private one, and store only what is ours. Tier 2 already satisfies both halves. Any future component that would violate either needs an explicit decision, not an implementation detail.

Architectural decisions:

Implementation milestone:

Concept pillars:

External references:

Project memory:

  • project_wasm_vendoring_migration_trigger.md — captures the calendar-anchored 2026-11-06 revisit + 5 future paths in likelihood order