---
number: 12185
title: >-
  refactor(ai): Stage-4 consumer codemod — Proxy-routed reads + scalar/tenant
  hidden-default removal (#12106)
author: neo-opus-ada
state: MERGED
createdAt: '2026-05-30T00:24:14Z'
updatedAt: '2026-05-30T00:36:37Z'
closedAt: '2026-05-30T00:36:33Z'
mergedAt: '2026-05-30T00:36:33Z'
head: agent/12106-services-mcp-codemod
base: dev
url: 'https://github.com/neomjs/neo/pull/12185'
---
## Summary

Stage 4 of Epic #12101 — consumer-side codemod migrating `ai/services` + `ai/mcp` off the non-getter `aiConfig` anti-patterns (Discussion #12100 sub-classes A / B / D-prod / E) onto the canonical Proxy-routed read + the no-hidden-default contract. Behaviour-preserving.

## Deltas

- **A (12):** `aiConfig.data.X` → `aiConfig.X` (drop the Proxy bypass) — DreamService, ConceptDiscoveryService, GapInferenceEngine, DatabaseService, SessionService, GraphService.
- **D-prod (8):** bootstrap `aiConfig.data.debug = true` → `aiConfig.debug = true` (proxy set-trap → `setData`) — the 6 mcp-servers + run-bridge + mcp-cli. (No `aiConfig.set()` method exists — Discussion #12100 hypothesized one; the proxy assignment is the write path.)
- **B (3):** `ProviderReadinessHelper` default-params `config = aiConfig.data` → `config = aiConfig`.
- **E (scalar + tenant):** removed config-backed redundant `?? <literal>` fallbacks — `guideGapWeightThreshold`/`minSourceLength`/`prScanLimit`, `mcpSyncMaxChunks` (×2), `defaultTenantId`/`defaultRepoSlug` (DocumentService/QueryService/SearchService). The config leaf provides each value verbatim; behaviour-identical.

## Test Evidence

963 `ai/services` unit specs pass. The 8 failing memory-core specs are **pre-existing env-flaky** (need live ollama/models/MC) — confirmed failing identically on stashed-clean dev (`git stash` → same 8 fail → `pop`). `node --check` clean on all 19 files.

Evidence: every removed E default is config-backed — verified the owning `leaf(...)` in the templates (`guideGapWeightThreshold: leaf(0.8)`, `mcpSyncMaxChunks: leaf(50)`, `defaultTenantId: leaf('neo-shared')`, …). The tenant filters now read `aiConfig.defaultTenantId` verbatim (= `'neo-shared'` for any current config), so the fail-closed isolation is unchanged.

## Post-Merge Validation

None for the bulk — behaviour-preserving.

⚠️ **Open sub-decision (deliberately NOT in this PR):** the 9 KB `Source` `?? '<path>'` fallbacks are #11660's *deliberate* byte-equivalence-for-stale-configs shims. The `sourcePaths` leaf defines all 9 verbatim, so the no-hidden-default contract says remove them — but removal breaks KB ingestion for operator overlays predating #11660's `sourcePaths` block. Surfaced as a config-SSOT-vs-backward-compat call before removal.

FAIR-band: n/a — operator-directed epic lane (#12101 Stage 4).

Refs #12106.

Authored by Claude Opus 4.8 (Claude Code, 1M context).
