LearnNewsExamplesServices
Frontmatter
id15387
titlefix(ai): config-overlay import-shape regex bridges a bare import into the next → false "stale config" boot-crash (harness-brick regression)
stateClosed
labels
bugaiarchitecture
assigneesneo-opus-grace
createdAtJul 18, 2026, 1:35 AM
updatedAtJul 18, 2026, 1:50 AM
githubUrlhttps://github.com/neomjs/neo/issues/15387
authorneo-opus-grace
commentsCount0
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtJul 18, 2026, 1:50 AM

fix(ai): config-overlay import-shape regex bridges a bare import into the next → false "stale config" boot-crash (harness-brick regression)

Closed Backlog/active-chunk-7 bugaiarchitecture
neo-opus-grace
neo-opus-grace commented on Jul 18, 2026, 1:35 AM

Symptom

After a harness restart, MCP servers fail to start — neo-mjs-neural-link, neo-mjs-github-workflow, neo-mjs-memory-core: "Server disconnected." The preflight throws:

[Neo AI] Stale config overlay — a materialized config.mjs is missing template-owned config shape:
  - neural-link/config.mjs: missing os:default
  - github-workflow/config.mjs: missing path:default

The config.mjs files are not actually stale — they plainly import os from 'os' / import path from 'path' and use them. The guard is wrong.

Root cause

ai/scripts/setup/initServerConfigs.mjs:397projectSourceShape's import extractor:

for (const match of src.matchAll(/^import\s+([\s\S]*?)\s+from\s+['"]([^'"]+)['"]/gm)) {

[\s\S]*? spans across lines. Every server config.mjs now begins with the bare Tier-1 participation import import '../../../config.mjs'; (added by #15294 / #15314), immediately above import os from 'os'. The bare import has no from, so the non-greedy [\s\S]*? bridges from its import to the next import's from 'os', swallowing import os into a malformed body — so the os:default binding is never extracted. assertConfigFresh then classifies os:default/path:default as missing crash-causing shape and throws at boot → the server process dies.

Empirically confirmed: projectSourceShape(realConfigSrc).imports.includes('os:default') returns false on a config that imports os. configBase.mjs starts with import os directly (no bare import first), so it projects correctly — the asymmetry is the whole bug, and it's why the tests missed it.

Blast radius

Every harness bricks on the next restart after #15314 — every real config.mjs has the bare-import-then-os/path shape.

Fix

initServerConfigs.mjs:397[\s\S]*?[^;]*?. A bare import ends in ;, so [^;] cannot bridge into the next statement; multiline named imports contain no ; before from, so they still parse. Verified to restore every dropped binding and clear the boot guard for all five servers. A regression test with a bare-import-then-default fixture is added.

Decision Record

NOT_NEEDED — aligned with ADR 0019; this is a defect fix in the overlay-freshness tooling, no config-surface or SSOT semantics change.

Acceptance Criteria

  • projectSourceShape extracts the :default binding of an import that immediately follows a bare side-effect import.
  • assertConfigFresh no longer throws for the five shipped server config.mjs shapes (bare Tier-1 import + os/path).
  • Regression test covers the bare-import-then-default ordering.

Regression from: #15294 / #15314 (server config overlay base-extraction).

tobiu referenced in commit a377290 - "fix(ai): config-overlay import regex no longer bridges a bare import into the next (#15387) (#15388) on Jul 18, 2026, 1:50 AM
tobiu closed this issue on Jul 18, 2026, 1:50 AM