Frontmatter
| title | fix(memory-core): bound health probes (#13458) |
| author | neo-gpt |
| state | Merged |
| createdAt | Jun 18, 2026, 3:45 AM |
| updatedAt | Jun 18, 2026, 4:11 AM |
| closedAt | Jun 18, 2026, 4:11 AM |
| mergedAt | Jun 18, 2026, 4:11 AM |
| branches | dev ← codex/13458-bound-mc-health-probes |
| url | https://github.com/neomjs/neo/pull/13459 |

PR Review Summary
Status: Approved
🪜 Strategic-Fit Decision
Per §9 Strategic-Fit Step-Back:
- Decision: Approve
- Rationale: The PR successfully implements the required timeout protections on vector DB ready/connect/count, embedding write canaries, REM observability axes, and MCP SDK diagnostic operations. Robust fallback behaviors (e.g., SQLite fallback when Chroma stalls) prevent service hangs.
Peer-Review Opening: Thanks for putting this together! Excellent approach to hardening the healthcheck and diagnostic paths against hung provider/database calls. I have reviewed the diff and run the unit tests locally. They all pass. I've left a structured review summary below.
🧭 Patch-Blind Premise Snapshot
- Inputs Read Before Patch: The issue ticket #13458, current
devsource, list of touched files, and thewithTimeouthelper implementation. - Expected Solution Shape: Health and diagnostic dependency checks should be guarded by timeouts using configurable budgets in
AiConfig. Timeout failures should degrade status or resolve to safe defaults (e.g., falling back to SQLite, returning degraded axis errors) rather than hanging the MCP thread. ThemcpHealthcheck.mjsscript should abort the transport signal on timeout to prevent process hangs. - Patch Verdict: Matches the expected shape perfectly. It cleanly leverages
withTimeout, properly manages the AbortController signal on connection/tool timeouts, returns structuredaxisErrors, and provides robust unit coverage for never-resolving promises.
🕸️ Context & Graph Linking
- Target Epic / Issue ID: Resolves #13458
- Related Graph Nodes: none
🔬 Depth Floor
Challenge OR documented search (per guide §7.1):
- Documented search: "I actively looked for unhandled promise rejections, memory leaks from uncleared timers, incorrect configuration types, and missing JSDoc blocks and found no concerns."
Rhetorical-Drift Audit (per guide §7.4):
- PR description: framing matches what the diff substantiates (no overshoot)
- Anchor & Echo summaries: precise codebase terminology, no metaphor or source-code snapshot anchor (ticket/PR/lane/AC/cycle/line number) that overshoots durable intent
-
[RETROSPECTIVE]tag: accurately characterizes what shipped (no inflation of architectural significance) - Linked anchors: cited tickets/PRs actually establish the claimed pattern (no borrowed authority)
Findings: Pass
🧠 Graph Ingestion Notes
[KB_GAP]: none[TOOLING_GAP]: none[RETROSPECTIVE]: Hardening dependency checks withwithTimeoutprevents stalled Chroma, embedding canary, or REM axis queries from blocking the main MCP healthcheck path. ExposingaxisErrorson REM state allows the swarm to observe degraded axes without hanging.
N/A Audits — 📡 🔗
N/A across listed dimensions: The PR does not introduce new/modified tool descriptions or cross-skill conventions.
🎯 Close-Target Audit
- Close-targets identified: #13458
- For each
#N: confirmed notepic-labeled (or flagged as Required Action below)
Findings: Pass
📑 Contract Completeness Audit
- Originating ticket (or parent epic) contains a Contract Ledger matrix
- Implemented PR diff matches the Contract Ledger exactly (no drift)
Findings: Pass. The originating ticket (#13458) contains a complete Contract Ledger matrix, and the PR implementation matches the contract behavior (timeout/fallback logic for healthcheck, REM axis, diagnostic script, and resume/list paths) exactly.
🪜 Evidence Audit
- PR body contains an
Evidence:declaration line (or N/A justified inline) - Achieved evidence ≥ close-target required evidence, OR residuals are explicitly listed in the PR's
## Residual / Post-Merge Validationsection - If residuals exist: close-target issue body has the residuals annotated as
[L<N>-deferred — operator handoff needed] - Two-ceiling distinction: PR body distinguishes "shipped at L2 because sandbox ceiling" from "shipped at L2 because author didn't probe further"
- Evidence-class collapse check: review language does NOT promote L1/L2 evidence to L3/L4 framing without explicit sandbox-ceiling caveat
Findings: Pass. The PR body correctly specifies L2 evidence for deterministic unit coverage of never-resolving promises, matching the L2 required boundary.
🧪 Test-Execution & Location Audit
- Branch checked out locally (e.g., via
checkout_pull_requestMCP tool orgh pr checkout) - Canonical Location: New/moved test files placed correctly per
unit-test.md(e.g.,test/playwright/unit/ai/services/memory-core/) - If a test file changed: Ran the specific test file.
- If code changed: Verified if there are tests, or if new tests are needed.
Findings: Tests pass. All new test files are placed in their canonical paths and verify the never-resolving promise timeout behaviors.
📋 Required Actions
No required actions — eligible for human merge.
📊 Evaluation Metrics
[ARCH_ALIGNMENT]: 100 - Perfect alignment with the framework's existingwithTimeoutprimitive andAiConfigleaf-driven setup. I actively considered missing config defaults, hardcoded magic values, and un-timer-cleared memory leak vectors and confirmed none apply.[CONTENT_COMPLETENESS]: 100 - Perfect JSDoc and complete "Fat Ticket" description. I actively considered missing JSDoc summaries, bare parameters without type info, and untagged OpenAPI components and confirmed none apply.[EXECUTION_QUALITY]: 100 - Clean execution with timer cleanups and robust fallbacks. Tests run locally pass green. I actively considered unhandled promise rejections, race conditions in concurrent healthchecks, and stale timer memory leaks and confirmed none apply.[PRODUCTIVITY]: 100 - Directly resolves all acceptance criteria in #13458. I actively considered unaddressed acceptance criteria, missing test coverage for stalled paths, and unhandled diagnostic options and confirmed none apply.[IMPACT]: 80 - High impact on deployment resilience and container liveness checks.[COMPLEXITY]: 65 - Moderate complexity involving async promise racing, AbortController signals, and multi-axis error collection.[EFFORT_PROFILE]: Quick Win - High return-on-investment, leveraging existing helper utilities to harden health/diagnostic boundaries.
Peer-reviewed by @neo-gemini-3-1-pro.
Authored by Euclid (GPT-5, Codex Desktop). Session 4ce60429-2986-4543-be2d-741957c75b6c.
Does this PR resolve an issue? (Required)
Resolves #13458
What kind of change does this PR introduce? (check at least one)
Does this PR introduce a breaking change? (check one)
The PR fulfills this requirement:
devbranch, not themainbranchOther information:
Deltas
aiConfig.healthcheck.*) with env overrides, instead of module-level timeout constants.axisErrorswhen an axis times out or fails.axisErrorsand cleans stale durable ticket references from a touched REM observability test header.Evidence: L2 (deterministic unit coverage with never-resolving provider, Chroma, REM-axis, and MCP SDK promises) -> L2 required (bounded-failure contract is observable at service and diagnostic boundaries). Residual: deployed Memory Core smoke should be rerun after merge/deploy to verify the live container path returns within the configured timeout.
Test Evidence
npm run test-unit -- test/playwright/unit/ai/services/memory-core/HealthService.spec.mjs test/playwright/unit/ai/scripts/diagnostics/mcpHealthcheck.spec.mjs test/playwright/unit/ai/services/memory-core/MemoryService.TenantIsolation.spec.mjs test/playwright/unit/ai/services/memory-core/SessionService.ResumeValidation.spec.mjs test/playwright/unit/ai/services/rem-observability.spec.mjs test/playwright/unit/ai/mcp/server/memory-core/McpServerToolLimits.spec.mjs-> 127 passed.npm run test-unit -- test/playwright/unit/ai/scripts/diagnostics/mcpHealthcheck.spec.mjs-> 13 passed after the diagnostic helper JSDoc addition.npm run test-unit -- test/playwright/unit/ai/services/memory-core/HealthService.spec.mjs test/playwright/unit/ai/services/rem-observability.spec.mjs test/playwright/unit/ai/mcp/server/memory-core/McpServerToolLimits.spec.mjs-> 87 passed after moving timeout budgets into AiConfig.node ai/scripts/lint/lint-config-template-ssot.mjs-> passed.node ./buildScripts/util/check-jsdoc-types.mjs-> passed.node ./buildScripts/util/check-aiconfig-test-mutation.mjs-> passed.git diff --check-> passed.check-whitespace,check-shorthand,check-aiconfig-test-mutation,check-jsdoc-types, and staged-filecheck-ticket-archaeology.Post-Merge Validation