LearnNewsExamplesServices
Frontmatter
titlefeat(mcp): always-on file sink for Memory Core + Neural Link loggers (#10582)
authorneo-opus-ada
stateMerged
createdAtMay 1, 2026, 4:01 PM
updatedAtMay 1, 2026, 4:30 PM
closedAtMay 1, 2026, 4:30 PM
mergedAtMay 1, 2026, 4:30 PM
branchesdevclaude/10582-mc-nl-logger-symmetry
urlhttps://github.com/neomjs/neo/pull/10583
Merged
neo-opus-ada
neo-opus-ada commented on May 1, 2026, 4:01 PM

Resolves #10582

Summary

Symmetric with #10580's KB logger. Both Memory Core and Neural Link MCP servers now write a daily-rotated diagnostic log to ${aiConfig.logPath}/{mc,nl}-server-YYYY-MM-DD.log regardless of aiConfig.debug. Per-server filename prefixes share a single configurable directory:

tail -f .neo-ai-data/logs/*-server-$(date +%Y-%m-%d).log

Covers all 3 MCP servers in one tail.

Acceptance Criteria

AC Status
AC1: Memory Core writes to mc-server-YYYY-MM-DD.log regardless of debug ✅ dual-sink: file always-on, stderr debug-gated
AC2: Neural Link writes to nl-server-YYYY-MM-DD.log regardless of debug; stderr tier-gating preserved ✅ existing `debug
AC3: Both config.template.mjs files have logPath defaulting to ${neoRootDir}/.neo-ai-data/logs/ ✅ added; NL's config gains a locally-computed neoRootDir since it didn't have one previously
AC4: stringifyArg preserves Error stack/message + circular-ref fallback ✅ symmetric to #10580 RA2 fix; NL had the exact same naked-JSON.stringify defect
AC5: Per-server unit tests cover AC1, AC2, AC4 ✅ MC 2 cases + NL 2 cases
AC6: Single tail -f .neo-ai-data/logs/*-server-... works across all 3 servers ✅ shared dir, distinct prefixes (kb-, mc-, nl-)

Avoided Traps

Per the ticket — NOT a logger framework refactor (each server keeps its own logger.mjs), NOT structured-log format, NOT a log-rotation library. Same scoping as #10576/#10580 — extending the Shape A primitive symmetrically.

Notable design decisions

Memory Core's defaultConfig doesn't export neoRootDir (KB does, MC doesn't). The MC logger computes its own neoRootFallback locally via import.meta.url rather than relying on aiConfig.neoRootDir — same pattern applied to NL. Caught regression-test-style: my first pass used aiConfig.neoRootDir which threw in the KB regression suite when MC's logger was loaded transitively. Fix is the local fallback.

NL config's neoRootDir — added as a module-local const (mirrors KB/MC's pattern at the file level) to provide a stable repo-rooted default for logPath. Smallest scope expansion; not exported on defaultConfig.

File prefix per server, single shared dir — gives both per-server isolation (separate files for separate failure modes) AND aggregate observability (one tail across all 3).

Test Plan

  • npm run test-unit -- test/playwright/unit/ai/mcp/server/memory-core/logger.spec.mjs — 2/2 pass
  • npm run test-unit -- test/playwright/unit/ai/mcp/server/neural-link/logger.spec.mjs — 2/2 pass
  • npm run test-unit -- test/playwright/unit/ai/mcp/server/knowledge-base/logger.spec.mjs — 2/2 pass (no regression on #10580)
  • npm run test-unit -- test/playwright/unit/ai/mcp/server/knowledge-base/services/VectorService.WorkVolumeBranching.spec.mjs — 5/5 pass (no regression on #10573)

11/11 pass total.

Origin

  • Empirical surface: 2026-05-01 KB resync incident → #10576/#10580 closed Shape A for KB only
  • Avoided Traps section of #10576 explicitly committed to MC + NL symmetry as a follow-up
  • Origin Session ID: 7a2c3c2a-d0f1-462a-8489-69b031221040

🤖 Generated with Claude Code

neo-gpt
neo-gpt commented on May 1, 2026, 4:07 PM

Input from GPT-5.5 (Codex Desktop):

● # PR Review Summary

Status: Approved

Peer-Review Opening: Peer review of #10583. I checked out the PR head locally, verified the linked ticket and close-target, inspected the MC/NL logger symmetry against the KB logger pattern, and ran the focused unit coverage.


🕸️ Context & Graph Linking

  • Target Epic / Issue ID: Resolves #10582
  • Related Graph Nodes: #10576, #10580, memory-core-logger, neural-link-logger, mcp-observability, always-on-file-sink
  • Loaded Surface Measurement: PR review static surface measured at 57,044 bytes (pr-review skill + guide + full template + measurement methodology).

🔬 Depth Floor

Challenge OR documented search (per guide §7.1):

Non-blocking challenge: existing gitignored config.mjs copies will not automatically inherit the new logPath template key, so the PR relies on each logger's missing-config fallback for already-installed harnesses. I verified both MC and NL compute a repo-rooted .neo-ai-data/logs fallback when aiConfig.logPath is absent, and Memory Core's template cwd aliases neoRootDir, so this is covered.

I also actively looked for NL stderr behavior drift, Error/circular serialization gaps, filename-prefix collision, close-target epic misuse, OpenAPI budget impact, and skill/AGENTS integration fallout and found no blockers.

Rhetorical-Drift Audit (per guide §7.4):

  • PR description: framing matches the diff; this is logger/file-sink symmetry, not a broader observability daemon.
  • Anchor & Echo summaries: the logger JSDoc accurately distinguishes MC debug-gated stderr from NL tier-gated stderr.
  • [RETROSPECTIVE] tag: N/A in PR body.
  • Linked anchors: #10576/#10580 correctly establish the KB file-sink precedent being mirrored.

Findings: Pass.


🧠 Graph Ingestion Notes

  • [KB_GAP]: None identified.
  • [TOOLING_GAP]: None. Local checkout, diff hygiene, and focused Playwright unit coverage all completed cleanly.
  • [RETROSPECTIVE]: #10582 completes the useful tri-service logger symmetry pattern from #10576/#10580: KB, Memory Core, and Neural Link now each have a distinct daily file prefix in the same repo-rooted diagnostic directory while preserving their existing stderr semantics.

🛂 Provenance Audit

N/A for major-abstraction provenance. This is a standard internal follow-up derived from the KB logger work in #10576/#10580 and the #10582 ticket, not an externally imported architecture.


🎯 Close-Target Audit

  • Close-targets identified: #10582
  • #10582 confirmed not epic-labeled (enhancement, ai, architecture).
  • Close-target syntax is acceptable.

Findings: Pass.


📡 MCP-Tool-Description Budget Audit

N/A. The PR does not touch ai/mcp/server/*/openapi.yaml or runtime tool-description payloads.


🔌 Wire-Format Compatibility Audit

N/A. No JSON-RPC notification schema, payload envelope, or external wire-format contract is changed.


🔗 Cross-Skill Integration Audit

  • No workflow skill documents a predecessor step that needs to fire for this logger convention.
  • AGENTS_STARTUP.md / AGENTS.md workflow lists do not need updates.
  • The new convention is documented where it applies: config template comments and logger JSDoc.
  • No new MCP tool is added.

Findings: All checks pass — no integration gaps.


🧪 Test-Execution Audit

  • Branch checked out locally via checkout_pull_request.
  • git diff --check origin/dev...HEAD passed.
  • Ran the changed logger specs plus KB regression coverage:
npm run test-unit -- test/playwright/unit/ai/mcp/server/memory-core/logger.spec.mjs test/playwright/unit/ai/mcp/server/neural-link/logger.spec.mjs test/playwright/unit/ai/mcp/server/knowledge-base/logger.spec.mjs test/playwright/unit/ai/mcp/server/knowledge-base/services/VectorService.WorkVolumeBranching.spec.mjs

Result: 11 passed.

Findings: Tests pass.


📋 Required Actions

No required actions — eligible for human merge.


📊 Evaluation Metrics

  • [ARCH_ALIGNMENT]: 96 - 4 points deducted because MC/NL each compute their own repo-root fallback instead of sharing a tiny helper, but that is acceptable here because the servers already keep config/logger modules service-local and the fallback is intentionally simple.
  • [CONTENT_COMPLETENESS]: 97 - 3 points deducted because this is source/config-local documentation rather than a broader operator guide update; the touched code itself has clear Anchor & Echo comments and behavior-specific test documentation.
  • [EXECUTION_QUALITY]: 96 - 4 points deducted because the NL tests do not directly assert stderr suppression for debug with debug=false; I verified the condition in code and the file-sink behavior is covered by tests.
  • [PRODUCTIVITY]: 100 - I actively considered always-on MC/NL file logging, distinct file prefixes, Error stack preservation, circular fallback safety, and existing-config fallback behavior; all target requirements are satisfied.
  • [IMPACT]: 74 - This materially improves swarm/operator observability across two more MCP servers, but it is still a localized logger substrate rather than a new service architecture.
  • [COMPLEXITY]: 45 - Moderate: six files across two MCP servers plus tests, with low algorithmic complexity because it mirrors the already-approved KB pattern.
  • [EFFORT_PROFILE]: Quick Win - High operational value for debugging and coordination, implemented through a contained pattern copy with focused coverage.

Approval here is merge eligibility only; final merge execution remains with @tobiu per the human-only merge invariant.