LearnNewsExamplesServices
Frontmatter
id12180
titleOrphan test-* Chroma collections accumulate (incomplete test cleanup)
stateClosed
labels
bugaitesting
assignees[]
createdAtMay 29, 2026, 10:03 PM
updatedAtJun 6, 2026, 1:26 AM
githubUrlhttps://github.com/neomjs/neo/issues/12180
authorneo-opus-ada
commentsCount3
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[x] 12331 Isolate unit-test chroma + sqlite-daemon stores + orphan-purge
blocking[]
closedAtJun 6, 2026, 1:26 AM

Orphan test-* Chroma collections accumulate (incomplete test cleanup)

neo-opus-ada
neo-opus-ada commented on May 29, 2026, 10:03 PM

Context

Discovered while diagnosing #12166 (PR #12179): a direct query of a live deployment's Chroma (2026-05-29) found 1,263 orphan test-memory-* / test-session-* collections out of 1,269 total — only ~6 are real (neo-knowledge-base, neo-agent-memory, neo-agent-sessions, neo-native-graph). They sit in default_tenant / default_database, the SAME tenant/db as production collections.

The Problem

#10867 (merged PR #10868) deliberately gave unit tests process-isolated collection names — test-memory-${Date.now()}-… / test-session-${Date.now()}-… (see ai/mcp/server/memory-core/config.template.mjs under UNIT_TEST_MODE, plus per-spec beforeAll blocks) — so cleanupChromaManager() deletes the test collections instead of wiping neo-agent-memory / neo-agent-sessions. That P0-wipe fix holds: production is protected.

The flip side was never closed. Those uniquely-named test collections are created in whatever Chroma the suite points at (localhost:8000 in single-host deployments = the live store), and the cleanup side is incomplete: any spec that creates them without an afterAll cleanupChromaManager(), plus every interrupted/killed run (CI cancel, local Ctrl-C), leaves its collections behind. Because names are unique per run, orphans accumulate monotonically → 1,263 and counting. This bloats every listCollections call (a hot path for ChromaManager + KB ops) and consumes disk.

The Architectural Reality

  • ai/mcp/server/memory-core/config.template.mjscollections.memory / collections.session resolve to test-memory-${Date.now()}-… under UNIT_TEST_MODE.
  • test/playwright/unit/ai/.../util.mjs cleanupChromaManager() — the teardown primitive #10867 relies on; effective only when a spec actually calls it in afterAll AND the run reaches teardown.
  • Tests connect to the configured Chroma host:port; in a single-host deployment that is the operator's live store (default_tenant/default_database), so test collections land beside production.

The Fix (directions — choose at intake)

  1. Robust teardown — audit every spec that creates test-* collections; ensure each has an afterAll cleanup. Necessary but insufficient (interrupted runs still orphan).
  2. Wholesale isolation — point unit tests at an ephemeral / namespaced Chroma (separate tenant/database, or a throwaway persist dir) so they never touch the live store and the whole namespace is purgeable. Strongest option.
  3. Orphan purge utility — a maintenance script under ai/scripts/maintenance/ that deletes test-memory-* / test-session-* collections (optionally older than N), runnable on demand + optionally at suite start. Covers interrupted-run residue and the existing backlog.

Acceptance Criteria

  • Unit tests can no longer leave test-* collections in a production Chroma tenant/database (via isolation and/or guaranteed teardown).
  • A purge mechanism exists for stale test-* orphan collections (covers interrupted-run residue).
  • Verified: a full unit-suite run AND a deliberately-interrupted run leave zero net-new test-* collections in the live store (or only inside an auto-purged isolated namespace).

Out of Scope

  • #10867's production-protection (done — test-* naming + cleanupChromaManager failsafe).
  • One-time cleanup of the existing 1,263 orphans in a specific deployment (an operator action; the §3 purge utility serves it).

Related

  • #10867 — introduced the test-* isolation naming; this ticket closes its un-addressed cleanup flip-side.
  • #10845 — destructive-op guard (parent of #10867).
  • #12166 / PR #12179 — discovery context (orthogonal aiConfig parent-chain work).

Origin Session ID: 653970c8-8466-4609-8a15-28350234af10

Retrieval Hint: "orphan test-memory test-session Chroma collections accumulate unit test isolation cleanup #10867"