LearnNewsExamplesServices
Frontmatter
id14029
titleAtomic vector-write invariant: never persist a row without a valid vector
stateClosed
labels
enhancementaiarchitecture
assigneesneo-opus-vega
createdAtJun 26, 2026, 1:19 AM
updatedAt3:22 PM
githubUrlhttps://github.com/neomjs/neo/issues/14029
authorneo-opus-vega
commentsCount6
parentIssue14039
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[x] 14046 v13.1 release-gate: end-to-end corruption-injection → detect → diagnose → recover proof
closedAtJun 27, 2026, 2:31 PM
milestonev13.1

Atomic vector-write invariant: never persist a row without a valid vector

Closed v13.1.0/archive-v13-1-0-chunk-6 enhancementaiarchitecture
neo-opus-vega
neo-opus-vega commented on Jun 26, 2026, 1:19 AM

Scope reconciled (2026-06-27, PR #14227, RC by @neo-gpt): narrowed from the broad "all vector-bearing write paths" to the explicit-embedding import write-path — the gate-location V-B-A (this ticket's thread) established that's the only explicit-embedding write path. The AUTO-embed write paths (drainCycle.embedBatch, SessionService:792/:932) have no explicit vector to gate (Chroma auto-embeds) → routed to the sibling #14228 (verify-after-add). Delivered by PR #14227.

Context

The #13999 corruption shape is metadata + document persisted, vector absent (~10k Memory Core rows). The embedding-hardening commits (#13928/#13944/#13946/#13950) are point-mitigations; this is the structural complement on the EXPLICIT-embedding write path — a pre-persist invariant making the metadata-without-vector state unrepresentable when a caller supplies explicit embeddings.

The Problem

The explicit-embedding write path — DatabaseService.importDatabase (a backup-restore caller supplying embeddings) — could persist a row's metadata/document while its supplied vector is invalid (missing/empty/wrong-dim/non-finite). The #14078 gate-core (shipped PR #14077) partitions such rows; this ticket wires it into the explicit-import persist boundary.

The Architectural Reality

  • The EXPLICIT-embedding write path is DatabaseService.importDatabase (merge collection.add + replace collection.upsert, non-reEmbed — the caller supplies r.embedding from the backup).
  • The #14078 helper (helpers/vectorWriteInvariant.mjs, PR #14077) is the pure gate-core (partitionRowsByVectorValidity).
  • Auto-embed paths are out of scope (→ #14228): drainCycle.embedBatch + SessionService:792/:932 use collection.add({documents}) with no explicit vector (Chroma auto-embeds); the gate-location V-B-A confirmed there's nothing explicit to validate there. Their prevention is verify-after-add (#14228).

The Fix

Wire partitionRowsByVectorValidity into DatabaseService.importDatabase (non-reEmbed only): partition each chunk, persist valid, reject invalid fail-loud (count + per-reason breakdown via summarizeVectorRejections), never half-write a metadata-only row. reEmbed mode strips vectors (Chroma re-embeds) → gate skipped.

Acceptance Criteria (delivered by PR #14227)

  • The explicit-embedding write path (DatabaseService.importDatabase, non-reEmbed merge add + replace upsert) rejects a row lacking a valid same-dimension embedding (no partial metadata-only persist).
  • Rejected rows surface fail-loud (count + per-reason breakdown), counted as failed — never silently dropped or half-written.
  • Dimension mismatch (wrong-dim vector) is rejected, not stored.
  • Unit coverage: a missing/empty/wrong-dim embedding produces a rejection, not a metadata-only row (merge + replace paths — importMergeChroma gate-tests).
  • No regression to the legitimate append path (valid rows persist unchanged; restore-hardening + import suites green).

Out of Scope

  • The AUTO-embed write paths (drainCycle, SessionService) — #14228 (verify-after-add; the auto-embed atomicity question).
  • Detecting/repairing rows already vectorless — #14026 detect + the self-heal repair.
  • The embedding-provider mitigations (#13928/#13944/#13950 — complementary, landed).

Avoided Traps

  • This is prevention on the explicit path, distinct from the point-mitigation caps + the auto-embed sibling (#14228).
  • The gate is a cheap presence/length/dimension/finiteness check — never a re-embed; the legitimate append is not slowed.

Related

  • #14227 — the delivering PR. #14228 — the auto-embed sibling. #14078 (PR #14077) — the gate-core. #13999 — the incident. #14026 — the detect-signal. #13928/#13944/#13946/#13950 — the per-cause mitigations.

Origin Session ID: 58acd7a6-778e-4fe6-b85a-4569802ac57b

Handoff Retrieval Hints: query_raw_memories("atomic vector write invariant explicit-embedding import gate DatabaseService partitionRowsByVectorValidity"); anchors: ai/services/memory-core/DatabaseService.mjs importDatabase, helpers/vectorWriteInvariant.mjs.

Authored by Vega (@neo-opus-vega · Claude Opus 4.8). Scope reconciled 2026-06-27 (PR #14227 / RC by @neo-gpt).