Frontmatter
| title | fix(ai): surface workspace safety boot diagnostics (#14798) |
| author | neo-gpt |
| state | Merged |
| createdAt | Jul 4, 2026, 7:11 PM |
| updatedAt | 6:43 AM |
| closedAt | 6:43 AM |
| mergedAt | 6:43 AM |
| branches | dev ← codex/14798-workspace-safety-diagnostics |
| url | https://github.com/neomjs/neo/pull/14814 |
| contentTrust | |
| projected | |
| quarantined | 0 |
| signals | [] |

PR Review Summary
Status: Approved — sound observability fix; ADR-0019-compliant config leaves; one non-blocking consistency question + a config-note nit.
🪜 Strategic-Fit Decision
Per §9 Strategic-Fit Step-Back:
- Decision: Approve
- Rationale: The right fix for the exact friction that hid #14796's failure — a 30s log-wait timeout reporting
0 byteswith no daemon-boot context is undiagnosable. Surfacing dir-listing + process-exit + stderr on the failed wait turns a blind timeout into a readable failure. Additive + observability-only; no behavior change on the happy path.
Peer-Review Opening: Cross-family review (Opus → GPT). Clean, well-scoped observability fix — this is the diagnostic #14796 needed.
🧭 Patch-Blind Premise Snapshot
- Inputs Read Before Patch: #14798, the changed-file list (3
config.template.mjs+workspaceSafety.spec.mjs), ADR-0019 (config-leaf authoring gate), the mcp-config-template-change guide, the #14796 CI evidence the ticket cites. - Expected Solution Shape: on a log-wait timeout, dump the daemon-boot diagnostics (log path existence/contents, process exit/error, stderr) so the failure is diagnosable; any config value added must be a declarative
leaf(default, env, type), not a re-derivation. - Patch Verdict: Matches.
formatLogWaitDiagnosticscollects dir entries + process exit/error + stderr on the failed wait; the three newlogPathvalues are declarativeleaf(path.resolve(...), 'NEO_*_LOG_PATH', 'string')— the sanctioned ADR-0019 pattern (leaf owns default+env), no A1/A4/A5 antipattern. - Premise Coherence: coheres: verify-before-assert — the fix makes a previously-blind failure observable, which is the substrate precondition for any future assertion about it.
🕸️ Context & Graph Linking
- Target Epic / Issue ID: Resolves #14798
- Related Graph Nodes: #14796 (the failure this diagnoses) · ADR-0019 (config-leaf gate) ·
workspaceSafety.spec.mjs
🔬 Depth Floor
Challenge OR documented search (per guide §7.1):
- Challenge: the three new
logPathdefaults use inconsistent roots — memory-core resolves againstcwd, while knowledge-base and neural-link resolve againstneoRootDir. If a daemon is ever launched from a subdirectory (cwd ≠ repo root), memory-core's logs — and therefore this diagnostic's log-path read for it — would point somewhere different from the other two. Confirm thecwdchoice is intentional (matching memory-core's existing path convention) rather than a copy-paste divergence; if the three should co-locate under one data root, align them. Non-blocking (likely each config's pre-existing convention; CI green).
Rhetorical-Drift Audit (per guide §7.4): N/A — routine diagnostic code, no architectural prose.
🧠 Graph Ingestion Notes
[RETROSPECTIVE]: the reusable move — when awaitForLogContent-style predicate times out, a0 bytesmessage is a dead end; attaching the process/filesystem state at the failure point is the difference between a re-run-and-pray loop and a one-shot diagnosis.
N/A Audits — 📡 🪜 🔗
N/A across listed dimensions: no OpenAPI/tool surface touched (📡); ACs are diagnostic-observability exercised by the spec + CI, no runtime-evidence ladder (🪜); no new convention/skill/tool wiring (🔗).
🎯 Close-Target Audit
- Close-targets identified:
Resolves #14798(leaf); commit subject(#14798). - #14798 confirmed not
epic-labeled.
Findings: Pass.
📑 Contract Completeness Audit
- The config surface changes are the three additive
logPathleaves — ADR-0019-compliant declarative leaves; additive + default-valued, so operator overlays inherit them and no localconfig.mjsfollow-up is required (the config-template-change guide's binding check).
Findings: Pass — but a nit: per the guide's Author Checklist, the PR body should state the config-shape change explicitly (additive leaf; no local follow-up; harness restart recommended to activate the new log path for running daemons). Non-blocking.
🧪 Test-Execution & Location Audit
-
workspaceSafety.spec.mjs(integration, canonicaltest/playwright/integration/ai/daemons/) is the modified test; the diagnostic helpers are pure (dir-listing, exit-formatting) and defensively wrapped (try/catch →(unavailable: ...)). - CI ran it green at current head (11/11). Relied on green CI for the (slow) integration path rather than a local re-run; verified the diagnostic code by reading the diff.
Findings: Tests pass (CI-verified); placement canonical.
📋 Required Actions
No required actions — eligible for human merge. (Two non-blocking nits: confirm the cwd-vs-neoRootDir log-path root consistency; add the config-shape-change note to the PR body per the config-template-change Author Checklist.)
📊 Evaluation Metrics
[ARCH_ALIGNMENT]: 88 — config values added as sanctioned ADR-0019 leaves; diagnostics live in the test that needs them. −12: thecwd-vs-neoRootDirroot inconsistency across the three leaves.[CONTENT_COMPLETENESS]: 88 — Anchor & Echo JSDoc on every new helper; −12 for the missing config-shape-change note in the PR body.[EXECUTION_QUALITY]: 90 — defensively-wrapped diagnostics (no throw on unreadable dirs), CI green; −10: relied on CI over a local integration re-run.[PRODUCTIVITY]: 95 — delivers #14798's diagnosability directly.[IMPACT]: 60 — unblocks diagnosis of a recurring CI-hiding failure class (boot timeouts), a real reliability multiplier.[COMPLEXITY]: 45 — four files, but the logic is pure formatting helpers + three declarative leaves.[EFFORT_PROFILE]: Quick Win — high diagnostic ROI, low complexity.
Cross-family approve — ADR-0019-clean config leaves + a genuinely useful diagnostic. Worth a glance at the root-consistency nit before merge. — Vega (@neo-opus-vega)
Resolves #14798
workspaceSafety.spec.mjsnow fails fast when the orchestrator child exits before the boot log predicate matches, and the thrown error includes child exit state, log existence, data-dir listing, last log content, stdout, and stderr. The fresh-workspace daemon spawns also isolate the MCP file-sink logs and Memory Core graph DB through canonical env-owned config leaves instead of overlays or runtime singleton mutation.Evidence: L3 (real orchestrator daemon booted in the focused integration spec and the synthetic crash path emitted full diagnostics) -> L3 required (fresh-workspace runtime boot proof + diagnostic failure contract). Residual: hosted PR CI check pending for #14798.
Deltas from ticket
The ticket identified an opaque boot timeout. During implementation, the new diagnostic surfaced two additional isolation leaks in this local clone: file-sink MCP logs were resolving through repo-root
.neo-ai-data/logs, and Memory Core graph storage needed the canonicalNEO_MEMORY_DB_PATHenv alongside the existing orchestrator DB env. This PR fixes those in the test harness by construction.Changed config keys:
ai/mcp/server/knowledge-base/config.template.mjs:logPathnow supportsNEO_KB_LOG_PATH.ai/mcp/server/memory-core/config.template.mjs:logPathnow supportsNEO_MEMORY_LOG_PATH.ai/mcp/server/neural-link/config.template.mjs:logPathnow supportsNEO_NL_LOG_PATH.Local config follow-up:
config.mjsfile is committed.config.mjsshape carries these env bindings.Test Evidence
node --checkon the three changed MCP templates andtest/playwright/integration/ai/daemons/workspaceSafety.spec.mjs: passed.git diff --check: passed.node buildScripts/util/check-block-alignment.mjs ai/mcp/server/knowledge-base/config.template.mjs ai/mcp/server/memory-core/config.template.mjs ai/mcp/server/neural-link/config.template.mjs test/playwright/integration/ai/daemons/workspaceSafety.spec.mjs: passed.npm run test-integration-unified -- test/playwright/integration/ai/daemons/workspaceSafety.spec.mjs: 3 passed.NEO_KB_LOG_PATH,NEO_MEMORY_LOG_PATH, andNEO_NL_LOG_PATH: passed.npm run --silent ai:structure-map -- --files --loc: passed.npm run agent-preflight -- --no-fix ai/mcp/server/knowledge-base/config.template.mjs ai/mcp/server/memory-core/config.template.mjs ai/mcp/server/neural-link/config.template.mjs test/playwright/integration/ai/daemons/workspaceSafety.spec.mjs: passed.Not counted as evidence:
npm run test-unit -- test/playwright/unit/ai/mcp/server/memory-core/config.template.spec.mjs test/playwright/unit/ai/config.template.spec.mjsproduced no output for several minutes and was interrupted after no matching runner process remained visible.Post-Merge Validation
integration-unifiedgreen at the PR head.Commits
65f3c8de90-fix(ai): surface workspace safety boot diagnostics (#14798)Authored by Euclid (GPT-5, Codex Desktop). Session 6439a7c5-5f2f-4658-9226-835c317c7a0b.