Skip to content

Implement HNSW + BM25 write-fresh behind a consumer-owned storage seam (operator ruling 2026-08-17) #30

Description

@forkwright

Finding

heurema's retrieval subsystems (HNSW vector index, FTS/BM25) are unimplemented stubs, and the governing ruling for how they get built was delivered verbally and lived only on a collab board channel whose seat has since been absorbed. Recording it here so the design constraint survives at a harder rung.

Operator ruling (2026-08-17, substance verbatim): don't lose anything of value in this domain, but abstract it for fleet use in a coherent way such that aletheia and future customers can have their needs met completely and without compromise — an established set of primitives where things can be abstracted.

The working rule this resolves to: derived code is rewritten; sovereign code is abstracted. The extraction ban applies to MPL-2.0 CozoDB-derived material and stays exactly as it is (the docs-drift CI guard greps extract.*(hnsw|bm25|fts).*krites and nothing here reintroduces that framing). Sovereign code carries no provenance question and discarding it would lose real value for no legal gain.

Evidence

Per-subsystem measurement (against krites @ aletheia origin/main, 2026-08-17):

subsystem krites state consequence
HNSW sovereign twin exists: krites/runtime/hnsw_sovereign/, 2,912 lines, all 8 ledger rows sovereign, verbatim_pct 0.0, complete, off by default behind krites_sovereign_hnsw prove in production, then abstract the algorithm core into heurema
FTS/BM25 no sovereign twin; 24/34 files derived at 67.5% mean verbatim, tokenizer 60–89% genuinely write-fresh in heurema — nothing to preserve

The design problem that needs solving (stated by the aletheia seat): heurema's shipped VectorIndex { insert, query, remove, len } trait cannot express aletheia's usage. In krites, retrieval is impl SessionTx<'_> { hnsw_knn, fts_search }, the HNSW graph is persisted as encoded KV tuples inside the same transactional store as ordinary relations, and filter predicates arrive as compiled Bytecode. A trait with nowhere to put a transaction handle cannot host that.

Intended shape: heurema owns the algorithm, the consumer owns the storage binding. Graph construction, beam search, neighbour selection and pruning live in heurema, parameterised over a storage seam; krites binds that seam to SessionTx/KV tuples, standalone consumers bind it to PersistenceBackend (thesauros/atmis). One algorithm, two bindings, neither consumer compromised.

Why this matters

  • The stale framing "gated on aletheia Phase 05g extracting HNSW + FTS cleanly" describes a program that already executed: Phase 05g shipped in aletheia v0.35.0, and the ruling on the far side is that extraction is permanently off. Any surface still saying "extract" is confidently wrong (heurema#21/docs(heurema): settle Phase 2 source as write-fresh, permanently #23, kanon#3479 cleaned most of them).
  • heurema currently has zero consumers compiling against it; the wiring program that would make pinax/mneme real depends on these primitives existing for real rather than as NotYetImplemented.
  • The storage-seam shape is the crux design decision and was explicitly left open for review before building.

Desired correction

  1. Land the storage-seam design (reviewed, not just written): heurema owns graph construction / beam search / neighbour selection / pruning, parameterised over the seam; document the two bindings.
  2. Implement HNSW behind the seam, starting from the proven hnsw_sovereign core (abstract, not extract).
  3. Write FTS/BM25 fresh in heurema.
  4. Update any doc surface still describing extraction or a Phase-05g gate.

Note: the two seats that held this design context (aletheia-metis and mining) are down as of 2026-08-18; their offers of help (heurema repo mechanics — CI, release, lint, crate hygiene; pinax/mneme wiring once primitives are real; a review pass on the seam) are recorded here so they can be re-made when successor seats exist.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions