LearnNewsExamplesServices
Frontmatter
id14256
titleVerify SessionService direct-upsert auto-embed persisted a vector
stateClosed
labels
enhancementaitestingarchitecture
assigneesneo-opus-vega
createdAtJun 27, 2026, 6:39 PM
updatedAtJun 27, 2026, 7:03 PM
githubUrlhttps://github.com/neomjs/neo/issues/14256
authorneo-opus-vega
commentsCount0
parentIssue14228
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtJun 27, 2026, 7:03 PM

Verify SessionService direct-upsert auto-embed persisted a vector

Closed v13.1.0/archive-v13-1-0-chunk-7 enhancementaitestingarchitecture
neo-opus-vega
neo-opus-vega commented on Jun 27, 2026, 6:39 PM

Context

Leaf slice of #14228 (Prevent metadata-only rows on the Chroma auto-embed write paths) — the SessionService half of AC2. The drain-path half shipped as #14254 (PR #14255). This covers the two direct-upsert auto-embed sites that bypass the WAL drain entirely.

The Problem

SessionService persists via collection.upsert({documents}) with no explicit embeddings at two sites, relying on Chroma's collection embedding-function to auto-generate the vector:

  • summarizeSessionthis.sessionsCollection.upsert(...) (the session summary).
  • ingestAntigravityArtifactsthis.memoryCollection.upsert(...) (the implementation plan).

If that auto-embed is non-atomic (provider timeout / oversized input / model-not-resident), the document/metadata persist while the vector does not — a metadata-only row (the #13999 corruption shape) on a path with no WAL retry queue behind it.

The Architectural Reality

  • ai/services/memory-core/SessionService.mjssummarizeSession (sessionsCollection.upsert) + ingestAntigravityArtifacts (memoryCollection.upsert).
  • The atomic vector-write invariant classifyRowVector (ai/services/memory-core/helpers/vectorWriteInvariant.mjs) — reused as the SSOT predicate.

The Fix (delivered — branch agent/14228-sessionservice-verify)

  • New ai/services/memory-core/helpers/verifyPersistedVector.mjs: reads the just-upserted vector back (get({ids, include:['embeddings']})) and classifies it with classifyRowVector. Disposition differs from the drain (no WAL behind these single-shot persists of expected data):
    • metadata-only → logged loud for the autonomous recovery actuator to re-embed;
    • never deletes (the document is real data the caller expects);
    • never throws (a verify failure, including a read-back error, must not break the persist path);
    • opt-in on expectedDimension (no-ops without it).
  • Wired after both SessionService upserts.

Acceptance Criteria

  • Post-upsert vector verify at both auto-embed sites, reusing the canonical classifyRowVector.
  • Disposition: metadata-only → log-loud (recovery-actuator backstop); never delete; never throw; opt-in on expectedDimension.
  • Unit coverage: valid → null; missing → reason + warn + no-delete; wrong-dimension; read-back failure → null + warn + no-throw; opt-in skip.
  • No regression: the legitimate persist path is unchanged.

Out of Scope

  • The drain-path verify — #14254 (PR #14255).
  • The empirical Chroma-atomicity V-B-A (#14228 AC1) — sandbox-unreachable; deferred to the parent.
  • The explicit-embedding write path (#14029) + the heal actuator (#14134).

V-B-A note (refines the parent's AC3)

#14228 AC3 assumed SessionService is an interactive-hot path needing a sample/gate. V-B-A: both sites are background-ish (per-session summarization + per-artifact ingestion, infrequent) — not a per-request query path — so an unconditional per-upsert verify (one get) is affordable; no config-gate / Contract-Ledger row is required for this surface.

Related

#14228 (parent), #14254 (drain-slice sibling, PR #14255), #14029 (explicit-embed sibling gate), #14134 (heal actuator), #13999 (incident), #14039 (v13.1 epic).

Live latest-open sweep: checked latest open issues at 2026-06-27T16:38Z; no equivalent SessionService-verify ticket found.

Authored by Vega (@neo-opus-vega · Claude Opus 4.8, Claude Code). Origin Session ID: 09af5f18-b64c-417b-be84-8cb3305005d2.

Handoff Retrieval Hints: query_raw_memories("SessionService direct-upsert auto-embed verify metadata-only"); anchors: ai/services/memory-core/helpers/verifyPersistedVector.mjs, SessionService.mjs summarizeSession + ingestAntigravityArtifacts.

tobiu referenced in commit 413ea81 - "fix(ai): verify SessionService direct-upsert auto-embed persisted a vector — prevent metadata-only rows (#14256) (#14257) on Jun 27, 2026, 7:03 PM
tobiu closed this issue on Jun 27, 2026, 7:03 PM