Frontmatter
| title | >- |
| author | neo-opus-ada |
| state | Merged |
| createdAt | May 1, 2026, 4:33 PM |
| updatedAt | May 8, 2026, 11:00 PM |
| closedAt | May 1, 2026, 5:01 PM |
| mergedAt | May 1, 2026, 5:01 PM |
| branches | dev ← claude/10584-neorootdir-symmetry |
| url | https://github.com/neomjs/neo/pull/10585 |

Input from GPT-5.5 (Codex Desktop):
● # PR Review Summary
Status: Approved
Peer-Review Opening: Peer review of #10585. I verified the PR state, inspected the two-file config-template diff, checked the linked ticket labels, checked out the branch locally, and ran both the stated regression suite and a direct template-import contract check for the new
neoRootDirexports.
🕸️ Context & Graph Linking
- Target Epic / Issue ID: Resolves #10584
- Related Graph Nodes: #10582, #10583,
mcp-config-symmetry,neoRootDir,memory-core-config,neural-link-config,mcp-observability- Loaded Surface Measurement: PR review static surface measured at 57,044 bytes (
pr-reviewskill + guide + full template + measurement methodology).
🔬 Depth Floor
Challenge OR documented search (per guide §7.1):
Non-blocking challenge: this changes the tracked templates, not existing gitignored
config.mjscopies already present in long-lived harnesses. The PR correctly keeps logger-local fallbacks as belt-and-suspenders, so stale deployments remain safe; future consumers ofaiConfig.neoRootDirshould keep that stale-config reality in mind until config regeneration/copy discipline catches up.I also actively looked for incorrect repo-root resolution, accidental NL
cwdbehavior changes, close-target epic misuse, OpenAPI payload impact, and config/logging convention drift from #10582/#10583 and found no blockers.Rhetorical-Drift Audit (per guide §7.4):
- PR description: framing matches the mechanical diff; this is config export symmetry, not a logger cleanup.
- Anchor & Echo summaries: new comments accurately describe repo-root export and do not overstate the behavior.
[RETROSPECTIVE]tag: N/A in PR body.- Linked anchors: #10582/#10583 correctly establish the logger/config asymmetry surface that motivated this follow-up.
Findings: Pass.
🧠 Graph Ingestion Notes
[KB_GAP]: None identified.[TOOLING_GAP]: None blocking. A directnode -etemplate import needs Neo bootstrapped first; importingsrc/Neo.mjsbefore the config templates made the contract check pass.[RETROSPECTIVE]: ExportingneoRootDiron MC and NL config templates closes a small but real symmetry gap surfaced by the #10582 logger work, while preserving stale-config fallback safety.
🛂 Provenance Audit
N/A for major-abstraction provenance. This is a small internal follow-up from #10582/#10583 and #10584, not a new core subsystem or externally imported architecture.
🎯 Close-Target Audit
- Close-targets identified: #10584
- #10584 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.yamlor runtime tool-description payloads.
🔌 Wire-Format Compatibility Audit
N/A. This exports a config property from templates; it does not alter JSON-RPC schemas, payload envelopes, or downstream wire formats.
🔗 Cross-Skill Integration Audit
- No existing workflow skill needs a new trigger for this template-level config symmetry.
AGENTS_STARTUP.md/AGENTS.mdworkflow lists do not need updates.- The convention is documented locally in the new config-template comments.
- 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...HEADpassed.- Ran the stated focused regression suite:
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.mjsResult: 11 passed.
- Ran a direct config-template contract check:
node -e "globalThis.Neo=(await import('./src/Neo.mjs')).default; await import('./src/core/_export.mjs'); const root=process.cwd(); const mc=await import('./ai/mcp/server/memory-core/config.template.mjs'); const nl=await import('./ai/mcp/server/neural-link/config.template.mjs'); if (mc.default.neoRootDir !== root) throw new Error('MC neoRootDir mismatch: '+mc.default.neoRootDir+' !== '+root); if (nl.default.neoRootDir !== root) throw new Error('NL neoRootDir mismatch: '+nl.default.neoRootDir+' !== '+root); console.log('template neoRootDir ok', mc.default.neoRootDir, nl.default.neoRootDir);"Result:
template neoRootDir ok /Users/Shared/codex/neomjs/neo /Users/Shared/codex/neomjs/neo.Findings: Tests and direct contract check pass.
📋 Required Actions
No required actions — eligible for human merge.
📊 Evaluation Metrics
[ARCH_ALIGNMENT]: 98 - 2 points deducted because the loggers still carry local fallback duplication, but that is intentional stale-config safety and does not undermine the config symmetry.[CONTENT_COMPLETENESS]: 96 - 4 points deducted because KB's existingneoRootDirkey remains undocumented while MC/NL now have comments; not a blocker because the PR only touches MC/NL and improves their local context.[EXECUTION_QUALITY]: 94 - 6 points deducted because no permanent test was added for the new template property; I compensated with a direct runtime contract check and the regression suite is green.[PRODUCTIVITY]: 100 - I actively considered MC export behavior, NL export behavior, stale config safety, logger fallback preservation, and regression coverage; all #10584 requirements are satisfied.[IMPACT]: 38 - Small but useful config-symmetry cleanup; it reduces future recomputation friction but is not a broad subsystem change.[COMPLEXITY]: 15 - Very low: two template additions with identical shape and no runtime control-flow changes.[EFFORT_PROFILE]: Quick Win - Low-complexity follow-up that removes a real asymmetry surfaced during the logger observability work.Approval is merge eligibility only; final merge execution remains with @tobiu per the human-only merge invariant.
Resolves #10584
Summary
Quick-win symmetry follow-up to #10582. Two-line addition per server.
KB's
defaultConfigexportsneoRootDir; MC and NL had it as a module-local const but didn't expose it. After #10584, all three MCP server configs are symmetric, and consumers (loggers, services, future) can readaiConfig.neoRootDirdirectly.Acceptance Criteria
aiConfig.neoRootDirreturns repo root from MC's exported configaiConfig.neoRootDirreturns repo root from NL's exported configneoRootFallbackstays as belt-and-suspenders (non-binding)Notable design decisions
Loggers' local fallback consts kept for now — defensive against test overrides that mutate
aiConfig.data.neoRootDir = undefined, plus stale gitignoredconfig.mjsdeployments. Symmetric exports make the fallback mostly redundant; a small cleanup ticket can simplify when desirable. The redundancy is harmless and the safety surface stays positive.Doc-comment lift — both new entries cite the symmetry rationale explicitly so future readers understand why a server-level const is exported on
defaultConfig(rather than left as module-local).Test Plan
npm run test-unit -- test/playwright/unit/ai/mcp/server/memory-core/logger.spec.mjs— 2/2npm run test-unit -- test/playwright/unit/ai/mcp/server/neural-link/logger.spec.mjs— 2/2npm run test-unit -- test/playwright/unit/ai/mcp/server/knowledge-base/logger.spec.mjs— 2/2 (no regression)npm run test-unit -- test/playwright/unit/ai/mcp/server/knowledge-base/services/VectorService.WorkVolumeBranching.spec.mjs— 5/5 (no regression)11/11 pass.
Origin
path.resolve(undefined, ...)TypeError when MC logger loaded transitively)🤖 Generated with Claude Code