Context
Surfaced 2026-05-08 during PR #10940 (TestLifecycleHelper substrate migration) Cycle 1 review. My empirical full-unit-suite run on Gemini's agent/sqlite-hardening branch (cd /Users/Shared/github/neomjs/neo && CI=true npm run test-unit, matches CI workers:1 substrate) showed test/playwright/unit/ai/mcp/server/memory-core/services/GraphService.spec.mjs:107 STILL flakes despite the spec being migrated to TestLifecycleHelper.cleanupGraphService(... 'clear') in afterAll/beforeEach hooks.
This is the residual after PR #10940's substrate fix lands — the migration covers FileSystemIngestor (#10934) cleanly but doesn't fully resolve GraphService.spec's own intra-spec flake.
The Problem
should extract node neighbors properly (line 107) flakes with:
TypeError: The database connection is not open
at SQLite.removeNodes (ai/graph/storage/SQLite.mjs:200)
Same shape as #10934 + #10938 (closed-singleton-then-reuse), but at the GraphService.spec consumer surface AFTER the migration. Root cause hypotheses:
- TestLifecycleHelper isn't called at the right hook scope — afterAll/beforeEach migration may need afterEach OR the helper's
clear strategy may not cover the path that triggers removeNodes
- An upstream non-migrated spec leaves residual close-singleton state — e.g., a spec NOT covered by PR #10940's 5-spec migration (FileSystemIngestor, Server, GraphService, PermissionService, WakeSubscriptionService) closes the singleton before GraphService.spec runs
- SDK lazy re-init has a path TestLifecycleHelper doesn't cover — the SDK guards added in
5a52e8661 may not be sufficient
Skip-guarded in Phase 3 PR (forthcoming) per NEO_TEST_SKIP_CI pattern; this ticket tracks the proper investigation + fix.
The Architectural Reality
test/playwright/unit/ai/mcp/server/memory-core/services/GraphService.spec.mjs:107 — the flaky test (should extract node neighbors properly)
test/playwright/unit/ai/mcp/server/memory-core/services/util.mjs#TestLifecycleHelper.cleanupGraphService — the migration-target primitive (introduced in PR #10940 c.ce0771b3c)
ai/graph/storage/SQLite.mjs:200 removeNodes — naked this.db.prepare(...) that throws on closed connection (also present in 5a52e8661 SDK lifecycle guards)
The Fix (TBD via investigation)
Three candidate paths:
- Audit non-migrated specs for close-singleton patterns — if hypothesis 2 holds, expand TestLifecycleHelper migration to additional specs OR fix their teardown directly
- Add afterEach migration to GraphService.spec — if hypothesis 1 holds, the afterAll/beforeEach migration is incomplete for tests that mutate state mid-test
- SDK-level harden
removeNodes open-state check — if hypothesis 3 holds, defensive if (!this.db || !this.db.open) in SQLite mutators with self-heal via re-init
Investigation needed before locking the prescription.
Acceptance Criteria
Out of Scope
- Cross-spec singleton-lifecycle audit beyond the GraphService.spec consumer (separate concern; this ticket targets the residual post-#10940 specifically)
- Migrating GraphService to per-test instances (architectural change beyond AC scope)
Avoided Traps
- Treating as duplicate of #10934: rejected — #10934 was specifically about FileSystemIngestor.afterAll closing singleton; that's been migrated. This residual is different consumer surface, possibly different hypothesis class.
- Skip-guard as permanent solution: applied as immediate Phase 3 ship-the-PR move + tracked here for proper fix.
- Increasing retries: papers over without addressing root cause.
Related
- Surfacing CI run: my empirical CI=true full-suite run on PR #10940 c.7f454ee2 (1055 passed, 4 flaky)
- Cycle 1 review citation: PR #10940 commentId IC_kwDODSospM8AAAABBodQ9A — flagged as substantive empirical residual
- Sibling singleton-pollution patterns: #10934 (FileSystemIngestor — migrated), #10937 (PermissionService — STILL flakes despite migration, similar shape), #10938 (Database.spec G6 — likely auto-resolves now)
- Substrate primitive: PR #10940 c.ce0771b3c — TestLifecycleHelper introduced
- Bucket G epic: #10924
Origin Session ID: 7e897a0b-33ce-4d6c-b1a9-a1ff93e4e571
Retrieval Hint: query_raw_memories(query="GraphService.spec residual flake TestLifecycleHelper migration workers 1 #10940 PR 10933 sqlite removeNodes")
Context
Surfaced 2026-05-08 during PR #10940 (TestLifecycleHelper substrate migration) Cycle 1 review. My empirical full-unit-suite run on Gemini's
agent/sqlite-hardeningbranch (cd /Users/Shared/github/neomjs/neo && CI=true npm run test-unit, matches CI workers:1 substrate) showedtest/playwright/unit/ai/mcp/server/memory-core/services/GraphService.spec.mjs:107STILL flakes despite the spec being migrated toTestLifecycleHelper.cleanupGraphService(... 'clear')in afterAll/beforeEach hooks.This is the residual after PR #10940's substrate fix lands — the migration covers FileSystemIngestor (#10934) cleanly but doesn't fully resolve GraphService.spec's own intra-spec flake.
The Problem
should extract node neighbors properly(line 107) flakes with:Same shape as #10934 + #10938 (closed-singleton-then-reuse), but at the GraphService.spec consumer surface AFTER the migration. Root cause hypotheses:
clearstrategy may not cover the path that triggersremoveNodes5a52e8661may not be sufficientSkip-guarded in Phase 3 PR (forthcoming) per
NEO_TEST_SKIP_CIpattern; this ticket tracks the proper investigation + fix.The Architectural Reality
test/playwright/unit/ai/mcp/server/memory-core/services/GraphService.spec.mjs:107— the flaky test (should extract node neighbors properly)test/playwright/unit/ai/mcp/server/memory-core/services/util.mjs#TestLifecycleHelper.cleanupGraphService— the migration-target primitive (introduced in PR #10940 c.ce0771b3c)ai/graph/storage/SQLite.mjs:200removeNodes— nakedthis.db.prepare(...)that throws on closed connection (also present in5a52e8661SDK lifecycle guards)The Fix (TBD via investigation)
Three candidate paths:
removeNodesopen-state check — if hypothesis 3 holds, defensiveif (!this.db || !this.db.open)in SQLite mutators with self-heal via re-initInvestigation needed before locking the prescription.
Acceptance Criteria
WORKERS=1(matches CI substrate)CI=true npm run test-unitinvocationsOut of Scope
Avoided Traps
Related
Origin Session ID:
7e897a0b-33ce-4d6c-b1a9-a1ff93e4e571Retrieval Hint:
query_raw_memories(query="GraphService.spec residual flake TestLifecycleHelper migration workers 1 #10940 PR 10933 sqlite removeNodes")