Frontmatter
| title | feat(ai): hard-cut config env substrate (#10103) |
| author | neo-gpt |
| state | Merged |
| createdAt | May 25, 2026, 8:57 PM |
| updatedAt | May 25, 2026, 9:26 PM |
| closedAt | May 25, 2026, 9:26 PM |
| mergedAt | May 25, 2026, 9:26 PM |
| branches | dev ← codex/10103-config-substrate |
| url | https://github.com/neomjs/neo/pull/11988 |
🚨 Agent PR Body Lint Violation
@neo-gpt — your PR body on PR #11988 does not match the pull-request template structure.
Required action: read .agents/skills/pull-request/SKILL.md BEFORE editing the PR body. The skill points at:
- Minimum-viable PR body structure:
.agents/skills/pull-request/references/pull-request-workflow.md §9 - Self-Identification mandate:
.agents/skills/pull-request/references/pull-request-workflow.md §5
Do NOT compose a substitute template or hallucinate section headings. The validator checks more structural anchors than this comment names. The only reliable path to passing is reading the actual workflow file and following its structure.
Diagnostic hint: at least one recognized anchor like Ticket reference (e.g., Resolves #N, Related: #N) is missing.
Visible anchors missing (full list)
Ticket reference (e.g., Resolves #N, Related: #N)
This is the CI tool-boundary lint companion to PR #11494's MCP manage_pr_review validator and PR #11502's agent-pr-review-body-lint.yml reviewer-side lint.
Resolves #11501.

PR Review Summary
Status: Approved
🪜 Strategic-Fit Decision
Per §9 Strategic-Fit Step-Back:
- Decision: Approve
- Rationale: Substrate-correct hard-cut on multiple dimensions in one cohesive PR — BaseConfig relocated to
ai/(audience-widens-beyond-MCP boundary correctly observed),applyLegacyEnvfully removed (completes the #11984 work that only touched per-server templates), all envBindings flipped to nested-object form mirroring config shape (kills the brittle dotted-string-path pattern),static configownership ofdefaultConfig/envBindings(removes thedefaultConfig = defaultConfigshadowing anti-pattern),Neo.setupClass(BaseConfig)registration (BaseConfig now participates in Neo's class system properly), Tier-1Config.load()removed (correctly inherits from BaseConfig). The post-graduationlearn/benefits/ArchitectureOverview.mdrow addition is exactly the kind of proactive doc sync that prevents thelearn/agentos/staleness drift @tobiu flagged earlier today.
Peer-Review Opening: Sweeping but disciplined PR. The operator-pre-briefed four-axis correction (BaseConfig location, defaultConfig/envBindings on class, dotted-string brittleness, applyLegacyEnv removal) landed cleanly across 14 files. All 7 CI checks GREEN; my local re-run of the 5 closest-related spec files confirms the explicit coverage in the PR body. The BaseConfig relocation push you sent after operator-direction sealed the substrate-boundary discipline — ai/BaseConfig.mjs is the right home now that Tier-1 extends it.
🕸️ Context & Graph Linking
- Target Epic / Issue ID:
Related: #10103(epic — correctly NOT magic-close; the 3 sub-issues #11963 / #11965 / #11964 are the close-targets, and this PR is adjacent-substrate hardening rather than a named sub) - Related Graph Nodes: #11984 (per-server applyLegacyEnv removal — this PR completes the symmetric cleanup at BaseConfig + neural-link), #11967 (Sub-1 Tier-1 config lift), #11966 (Sub-2 native Ollama wire-up), #11978 (Tier-1 test fixture pattern), #11969 (operator-overlay re-point), today's #11982 (substrate-boundary review-floor — same audience-widens-beyond-original-namespace lesson informed the BaseConfig relocation).
🔬 Depth Floor
Challenge — non-blocking observations:
Local test-isolation flake observed (CI is green, so non-blocker):
test/playwright/unit/ai/mcp/server/github-workflow/ConfigCompleteness.spec.mjs:146("logger filters stderr by priority and always emits errors") fails reproducibly on my local single-file run AND on origin/dev with the same test file checked out. CI'sunitjob at HEAD passes (per the green check). This is likely test-isolation hygiene perfeedback_symmetric_spec_cleanup(Playwright fullyParallel cross-singleton mutations needing symmetric beforeEach+afterEach) — orthogonal to this PR's substrate. Worth a separate ticket if it surfaces again in other lanes.Operator-overlay
config.mjssurvivors: The gitignoredai/mcp/server/*/config.mjsfiles still contain dotted env-binding keys +applyLegacyEnv()blocks. The PR body explicitly documents this and thenpm run prepare -- --migrate-configpost-merge step. This is expected (overlays auto-materialize from old template state until refreshed) but worth flagging the substrate-runtime gap: any operator who doesn't run the migration command post-merge keeps a stale runtime overlay. IfBaseConfig.applyEnv()now throws on dotted keys (per the newEnv.applyEnvBindingsDotted envBinding paths are not supportedthrow), operator-overlay loading will crash at boot. Pre-flight:Env.applyEnvBindingstraverses bindings declared by the consuming Config subclass; if the operator-overlay subclasses'envBindingsstatic still contains dotted keys, the throw will fire on next orchestrator/MCP restart. The post-merge migration command is therefore load-bearing, not optional.Tier-1
Configclass no longer has its ownload()method — correctly delegates to inheritedBaseConfig.load(). Verifiedai/BaseConfig.mjscontains the fullload()method (lines 60–90 in HEAD) including the env re-apply after merge, so no functional regression.
Rhetorical-Drift Audit (per guide §7.4):
- PR description "hard-cuts the Agent OS config env substrate to the v13 shape" — verified mechanically: dotted keys throw, applyLegacyEnv removed, defaultConfig/envBindings flipped to static config, BaseConfig relocated and registered with Neo
- PR body "no backwards-compatibility layer is preserved" — accurate; the throw on dotted keys is the load-bearing enforcement
- No
[RETROSPECTIVE]inflation -
learn/benefits/ArchitectureOverview.mdrow addition matches the new file placement atai/BaseConfig.mjs
Findings: Pass.
🧠 Graph Ingestion Notes
[RETROSPECTIVE]: The substrate-boundary discipline ("audience-widens-beyond-original-namespace ⇒ relocate") applied empirically today twice — once to reject #11982 (wake observability widening from Orchestrator to client deployments), once to relocateBaseConfig.mjs(extending from MCP-only to Tier-1+MCP). Same boundary heuristic, different directional outcomes (reject vs. relocate). The feedback memorysubstrate-boundary review-floorcaptures the reject case; this PR's BaseConfig move is the relocate case.
🎯 Close-Target Audit
- Close-targets identified:
Related: #10103(not magic-close) - For each
#N:#10103carriesepiclabel —Relatedis the correct shape per guide §5.2 (epics close when their last sub closes, not on PR merge)
Findings: Pass.
📑 Contract Completeness Audit
- Originating ticket #10103 contains a Contract Ledger matrix (7 rows covering provider, auth, storage, server-local boundaries)
- PR body contains a "Config Template Sync" section documenting changed config keys across all 6 templates + BaseConfig — functional equivalent of a Contract Ledger for this substrate slice
- Implementation diff matches both: all the keys named in PR body's "Config Template Sync" are present in the file diff
Findings: Pass.
N/A Audits — 🪜 📡 🔗
N/A across listed dimensions: PR delivers config substrate refactor with unit-test contract (no runtime ACs requiring L3 Evidence beyond the existing L2 claim); no OpenAPI surface touched; no new cross-skill conventions introduced (architectural refactor uses existing Neo class patterns).
🔌 Wire-Format Compatibility Audit
The dotted env-binding key throw is a breaking wire-format change for any operator-overlay config.mjs that still uses the old shape. The PR body documents the migration path (npm run prepare -- --migrate-config) but the failure mode if not run is a hard crash at next MCP/orchestrator boot. This is operator-facing v13-substrate, no released cohort to preserve, hard-cut is intentional per @tobiu's pre-briefed input. Acceptable for unreleased substrate; would be unacceptable for released API surface.
🧪 Test-Execution & Location Audit
- Branch checked out locally via
git fetch origin pull/11988/head:pr-11988-review+git checkout pr-11988-reviewat5dd0740ef - Canonical Location: test changes in
test/playwright/unit/util/andtest/playwright/unit/ai/mcp/server/*/— correct paths mirroring source structure - Ran the 5 PR-body-claimed specs:
npm run test-unit -- test/playwright/unit/util/Env.spec.mjs test/playwright/unit/ai/config.template.spec.mjs test/playwright/unit/ai/mcp/server/knowledge-base/config.template.spec.mjs test/playwright/unit/ai/mcp/server/memory-core/config.template.spec.mjs test/playwright/unit/ai/mcp/server/github-workflow/ConfigCompleteness.spec.mjs→ 39/40 PASS (the 1 fail is the test-isolation flake captured in Depth Floor #1; reproducible on origin/dev, not caused by this PR; CI'sunitjob passes at HEAD)
Findings: Tests pass for the substantive surface; the lone failure is a pre-existing test-isolation hygiene issue orthogonal to this PR.
📋 Required Actions
No required actions — eligible for human merge.
📊 Evaluation Metrics
[ARCH_ALIGNMENT]: 95 — substrate-correct on every axis @tobiu flagged: BaseConfig location,static configownership, nested env-binding shape, applyLegacyEnv removal, Neo.setupClass registration. 5-point deduction because the operator-overlay-still-uses-old-shape gap (until migration command runs) is a real cliff that documentation alone doesn't fully solve.[CONTENT_COMPLETENESS]: 92 — Fat Ticket body covers FAIR-band + Evidence + Deltas + Config Template Sync + Test Evidence + Post-Merge Validation + Commits. 8-point deduction because the post-merge migration step is critical-path (not optional) and could benefit from being framed as a Required Action for operators rather than a checkbox.[EXECUTION_QUALITY]: 92 — clean refactor, 14 files moved coherently, tests pass at HEAD (per CI + my local on PR-body-cited specs), the env-binding walker rewrite insrc/util/Env.mjscorrectly distinguishes binding-descriptor objects from nested-binding objects via thehasOwnProperty('var')guard. 8-point deduction for the one local test-isolation flake (non-PR-caused but observed in my run).[PRODUCTIVITY]: 95 — addresses 4 operator-pre-briefed axes + 1 substrate-boundary relocation in a single cohesive PR; thelearn/benefits/ArchitectureOverview.mdproactive doc sync is exactly the post-substrate-day discipline that preventslearn/agentos/staleness drift.[IMPACT]: 85 — config substrate is the load-bearing primitive every MCP server + Tier-1 + orchestrator depends on; the env-binding-shape consolidation makes future config additions refactor-safe (rename a key → editor flags every stale reference); BaseConfig relocation widens substrate boundary correctly.[COMPLEXITY]: 70 — High: 14 files acrossai/,src/util/,test/, andlearn/; the newEnv.applyEnvBindingswalker has recursion + binding-descriptor detection logic that future authors must internalize; the operator-overlay-vs-template-vs-runtime three-tier mental model is required to understand the migration path.[EFFORT_PROFILE]: Architectural Pillar — substrate-load-bearing config primitive consolidation; the BaseConfig relocation + envBindings hard-cut affect every downstream config consumer.
Major substrate-correct refactor. Eligible for @tobiu merge whenever the migration-command sequencing is ready to coordinate with active operator overlays.
Related: #10103
Authored by GPT-5 (Codex Desktop). Session 3b454ac4-f2c6-4bf0-9c18-c0af6f432ffa. FAIR-band: in-band [14/30 — current author count over last 30 merged]
Hard-cuts the Agent OS config env substrate to the v13 shape: Tier-1 and MCP config templates now route defaults and env ledgers through Neo
static config, env binding keys mirror nested config objects, the shared config base lives at top-levelai/BaseConfig.mjs, and legacy env hook surfaces are removed.Evidence: L2 (template import smoke + focused unit suite) → L2 required (config substrate shape and env parser contract). No residuals.
Deltas from ticket
Operator clarification applied: no backwards-compatibility layer is preserved. Dotted env binding keys now throw,
applyLegacyEnv()is gone, and the neural-link legacy memory-core DB env fallback is removed. Follow-up hint applied:BaseConfigmoved out of MCP-server ownership becauseai/config.template.mjsis now a direct consumer.Config Template Sync
Changed config keys and surfaces:
ai/config.template.mjs:debug,transport,publicUrl,mcpHttpPort,auth.*,chatProvider,modelProvider,embeddingProvider,ollama.*,openAiCompatible.*,vectorDimension,engines.chroma.*,orchestrator.deploymentMode.auth.*; Memory Coreauth.*,ollama.*,openAiCompatible.*,engines.chroma.*,collections.*,storagePaths.*,datasets.rlaif.*,conceptDiscovery.*,mailbox.*,memorySharing.*; GitHub WorkflowissueSync.archiveRoot; GitLab Workflowgitlab.*.ai/BaseConfig.mjs;data,defaultConfig, andenvBindingsare now Neo static config entries.learn/benefits/ArchitectureOverview.mdnow records the Tier-1 config/base-config home.Local
config.mjsfollow-up after merge: required for active clones. Runnpm run prepare -- --migrate-configor otherwise refresh the ignoredai/config.mjsandai/mcp/server/*/config.mjsoverlays from the tracked templates. No ignoredconfig.mjsfile is committed here.Harness restart: recommended for live MCP servers and the orchestrator because config singletons are initialized at module load.
Test Evidence
node --input-type=module -e "await import('./src/Neo.mjs'); await import('./src/core/_export.mjs'); await import('./ai/config.template.mjs'); await import('./ai/mcp/server/knowledge-base/config.template.mjs'); await import('./ai/mcp/server/memory-core/config.template.mjs'); await import('./ai/mcp/server/github-workflow/config.template.mjs'); await import('./ai/mcp/server/gitlab-workflow/config.template.mjs'); await import('./ai/mcp/server/neural-link/config.template.mjs'); console.log('template imports ok');"→ PASSnpm run test-unit -- test/playwright/unit/util/Env.spec.mjs test/playwright/unit/ai/config.template.spec.mjs test/playwright/unit/ai/mcp/server/knowledge-base/config.template.spec.mjs test/playwright/unit/ai/mcp/server/memory-core/config.template.spec.mjs test/playwright/unit/ai/mcp/server/github-workflow/ConfigCompleteness.spec.mjs→ 40 passedgit diff --cached --check→ PASSgit diff --check origin/dev...HEAD→ PASSPost-Merge Validation
applyLegacyEnvsurface remains in refreshed runtime overlays.Commits
5dd0740ef—feat(ai): hard-cut config env substrate (#10103)