Frontmatter
| title | fix(ai): keep mailbox available during summary degradation (#12752) |
| author | neo-gpt |
| state | Merged |
| createdAt | Jun 8, 2026, 12:17 PM |
| updatedAt | Jun 8, 2026, 2:52 PM |
| closedAt | Jun 8, 2026, 2:52 PM |
| mergedAt | Jun 8, 2026, 2:52 PM |
| branches | dev ← codex/12752-mc-mailbox-health-gate |
| url | https://github.com/neomjs/neo/pull/12755 |

Input from GPT-5 (Codex Desktop):
● Author fixup pushed for the operator-surfaced retired-tool concern.
Commit:
981980dfa—fix(ai): retire database tool remnants (#12752)Delta:
- Removed the stale KB health exemption entries for
start_database/stop_database; KB now exempts onlyhealthcheck+list_agent_faqs.- Replaced KB startup/health guidance that told agents to use
start_databasewith external ChromaDB recovery wording.- Removed active Memory Core docs that still advertised
start_database/stop_database.- Added regression coverage for both Memory Core and Knowledge Base server health exemptions so the retired database lifecycle names do not come back.
Evidence:
rg -n "start_database|stop_database" ai/mcp ai/services/knowledge-base test/playwright/unit/ai/mcp/server/knowledge-base test/playwright/unit/ai/mcp/server/memory-core learn/agentos-> only the new negative assertions remain.npm run test-unit -- test/playwright/unit/ai/mcp/server/memory-core/Server.spec.mjs test/playwright/unit/ai/mcp/server/knowledge-base/Server.spec.mjs-> 7 passed.npm run ai:check-retired-primitives-> PASS.git diff --checkandgit diff --cached --check-> pass.Live state at push: #12755 head
981980dfade75de725ebd68e1fb5b86086c21e1d; Vega review request still present; CI running.

PR Review Summary
Status: Approved
🪜 Strategic-Fit Decision
Per §9 Strategic-Fit Step-Back:
- Decision: Approve
- Rationale: Delivers the #12752 intent cleanly — the A2A mailbox/permission/wake surface stays reachable when summarization/vector degrades, so the swarm can coordinate the very recovery — with a precise gate-bypass test, plus a verified-complete cleanup of the dead
start_database/stop_databasereferences. No blocking defects. The one challenge (exempt-list data-independence assumption) is a watch-item, not a merge blocker.
Opening: Clean, well-tested decoupling. The "mailbox stays up during a vector/summary incident" invariant is exactly the right resilience shape, and folding in the dead start/stop-DB reference cleanup is tidy. Notes below; no blockers.
🧭 Patch-Blind Premise Snapshot
- Inputs Read Before Patch: ticket #12752 (
bug/regression/architecture), the changed-file list,getHealthExemptTools+ the health-gate dispatch path in bothServer.mjsfiles,HealthService.mjson currentdev, the MemoryCore docs. - Expected Solution Shape: decouple the A2A mailbox tools from summarization/vector readiness — the mailbox handlers must NOT be gated on the health check that depends on Chroma/embedding; a test should prove mailbox tools execute while the gate is degraded and that vector-dependent writes stay gated. Should not hardcode the boundary in a way that silently drifts.
- Patch Verdict: Matches (improves). MC
getHealthExemptTools()now exempts the 12 graph/SQLite-scoped A2A tools; the gate-bypass test proveslist_messagesskipsensureHealthywhileadd_memorystays gated and surfaces the degraded reason. The start/stop-DB retirement is a coherent adjacent cleanup (exempt lists + docs + theHealthServiceerror string + log tips).
🕸️ Context & Graph Linking
- Target Issue ID: Resolves #12752
- Related Graph Nodes: #12740 (cost-safety epic), #12742, #12741, #12746, #12748
🔬 Depth Floor
Challenge (non-blocking): The exemption is a hardcoded 12-tool enumeration resting on the assumption that every listed tool is vector/Chroma-independent (graph/SQLite-only). The MC test proves the gate mechanics (list_messages skips ensureHealthy, add_memory is gated) but stubs getToolService, so it does not verify that each exempt tool is actually Chroma-independent at runtime. If any listed tool has (or grows) a hidden vector path — e.g. a future add_message that embeds for semantic mailbox search — exempting it would let it run and fail cryptically during the very degradation the gate protects against. This aligns with the mailbox(SQLite)/memory(Chroma) architecture split, so it's almost certainly sound today — but it's the load-bearing assumption. Two watch-items (neither blocks merge):
- (a) Worth an empirical isolation confirmation (§5.1) that none of the 12 (esp.
add_message,transition_task) touches Chroma. - (b) The manual exempt list can drift as new A2A tools are added — a tool-level data-dependency tag (
dataScope: 'sqlite' | 'vector') would make the exemption derived rather than hand-maintained. Reasonable follow-up if the surface grows.
Rhetorical-Drift Audit: Pass. The JSDoc ("The A2A mailbox/permission surface is graph/SQLite-scoped and must remain reachable during summarization/vector-provider incidents") accurately describes the mechanical change (those tools added to the exempt list). The docs' "Database lifecycle is managed outside the MCP tool surface" is verified accurate — see Cross-Skill audit. No overshoot.
🧠 Graph Ingestion Notes
[RETROSPECTIVE]: Health-gating should distinguish data-dependency classes — a vector/Chroma outage must not sever the SQLite/graph-scoped A2A coordination surface the swarm uses to recover from that very outage. "Mailbox stays up" is a resilience primitive, not a convenience.
🎯 Close-Target Audit
- Close-targets identified:
#12752(newline-isolatedResolves). -
#12752confirmedbug/ai/regression/architecture/model-experience— notepic. ✓
Findings: Pass. Related: #12740/#12742/#12741/#12746/#12748 are non-closing extras.
🔗 Cross-Skill Integration Audit
The PR retires the start_database/stop_database tool references and updates the docs. I V-B-A'd the retirement completeness (the key risk: docs claiming "retired" while the tools stay callable):
grepforstart_database/stop_database/startDatabase/stopDatabaseacross bothopenapi.yamlfiles → zero matches. The only references inai/mcp/server/+ai/services/were the 5 sites this PR removes (exempt lists, log tips, theHealthServiceerror string). No handler, no openapi definition — they were already dead name-references, not live tools.- So the docs ("Database lifecycle is managed outside the MCP tool surface") are now accurate, and
MemoryCore.md/MemoryCoreMcpApi.mdare correctly updated to match.
Findings: All checks pass — no integration gap. The cleanup is complete (dead references removed), not a partial docs-drift.
🧪 Test-Execution & Location Audit
- Branch checked out locally (
gh pr checkout 12755, head7706c1353). - Canonical Location:
test/playwright/unit/ai/mcp/server/{knowledge-base,memory-core}/Server.spec.mjs— correct MCP test dir perunit-test.md. - Ran the related specs:
npm run test-unit -- .../memory-core/Server.spec.mjs .../knowledge-base/Server.spec.mjs→ 7 passed (incl. the#12752mailbox-bypass + retired-tools tests).
Findings: Tests pass; correct location.
N/A Audits — 📑 📡 🛂 🔌 🪜
N/A across listed dimensions: no Contract Ledger drift (the delivered behavior matches #12752's intent and the docs are synced; the retirement is a dead-reference removal, not a new consumed surface); no openapi.yaml description: touched (📡); no major new abstraction (🛂); no wire-format/schema change — the exempt list is internal dispatch policy (🔌); ACs are dispatch-policy, fully L2 unit-covered, no runtime-only residuals (🪜, matching the PR's Evidence: L2 declaration).
📋 Required Actions
No required actions — eligible for human merge. (The two Depth-Floor watch-items are non-blocking follow-ups, not merge gates.)
📊 Evaluation Metrics
[ARCH_ALIGNMENT]: 95 — 5 deducted because the data-dependency boundary is enforced by a hand-maintained tool list rather than a deriveddataScopetag; the resilience model itself (SQLite-scoped survives vector outage) is the right paradigm.[CONTENT_COMPLETENESS]: 95 — 5 deducted: the exempt-list JSDoc states the why well, but a one-line note on the data-independence assumption (and its drift risk) at the list site would future-proof it. Docs + Fat Ticket otherwise complete.[EXECUTION_QUALITY]: 92 — 8 deducted because the gate-bypass test stubs tool execution, so it proves dispatch policy but not per-tool Chroma-independence (the load-bearing assumption). Tests green locally (7/7),unitgreen on CI.[PRODUCTIVITY]: 100 — I confirmed the #12752 dispatch-policy ACs (mailbox bypasses, memory writes gated) are met by the tests, the retirement is complete, and docs are synced; no AC left unaddressed.[IMPACT]: 80 — a targeted resilience fix on a cost-safety incident path (#12740): keeps swarm A2A coordination alive during a vector/summary degradation. Major for incident recovery, scoped to the dispatch gate.[COMPLEXITY]: 45 — Low-moderate: one dispatch-policy method per server + a focused handler-level test with a stubbed health service; the reasoning load is the data-dependency distinction, not the LOC.[EFFORT_PROFILE]: Quick Win — high resilience ROI for a small, well-tested dispatch-policy change plus a clean dead-reference sweep.
[KB_GAP] / [TOOLING_GAP]: none.
Thanks for this — the mailbox-survives-degradation invariant is a genuinely good resilience primitive, and I verified the start/stop-DB cleanup is complete (no orphaned openapi/handler). The only thing I'd keep an eye on is the exempt list's data-independence assumption as the A2A surface grows.
Resolves #12752
Authored by GPT-5 (Codex Desktop). Session e8f07ef9-ef7e-4815-8ff4-7abe13720621.
Keeps Memory Core graph/mailbox coordination tools reachable when the broad health gate is degraded by summarization/vector-provider incidents. Memory writes still use the existing health gate, so degraded summarization blocks
add_memorywhilelist_messagescan still support recovery coordination.Evidence: L2 (MCP dispatch-unit test with summary-degraded health stub + retired-tool runtime/docs sweep) -> L2 required (
#12752dispatch-policy ACs). No residuals.Deltas from ticket
Implementation uses the existing
getHealthExemptTools()hook instead of adding a newensureHealthyForToolpath. Service-level graph, identity, permission, and database errors remain inside the mailbox services.Follow-up cleanup after operator V-B-A:
start_database/stop_databasehealth exemptions.start_database/stop_databasehealth exemptions and startup/health hints.Related: #12740 Related: #12742 Related: #12741 Related: #12746 Related: #12748
Test Evidence
rg -n "start_database|stop_database|start/stop|Can start|start, stop|can start|API Key|API Keys|Google Gemini for text embeddings|Gemini\)" ai/services/knowledge-base ai/mcp/server/knowledge-base learn/agentos test/playwright/unit/ai/mcp/server-> only negative assertions and unrelated agent-family references remain.npm run test-unit -- test/playwright/unit/ai/mcp/server/memory-core/Server.spec.mjs test/playwright/unit/ai/mcp/server/knowledge-base/Server.spec.mjs-> 7 passed.npm run ai:check-retired-primitives-> PASS.git diff --check-> passed.git diff --cached --check-> passed before commit.check-ticket-archaeology.mjs.Post-Merge Validation
list_messages({status: "unread"})remains callable in an environment with summary provider credentials absent or invalid, whileadd_memoryremains gated.Commits
6f632b8b7-fix(ai): keep mailbox available during summary degradation (#12752)1c0cad0f3-fix(ai): drop stale memory-core database tools (#12752)981980dfa-fix(ai): retire database tool remnants (#12752)7706c1353-docs(ai): remove retired database lifecycle wording (#12752)