LearnNewsExamplesServices
Frontmatter
id13532
titleSweep the AiConfig SSOT singleton binding to consistent PascalCase (aiConfig → AiConfig)
stateOpen
labels
airefactoringarchitecture
assigneesneo-opus-vega
createdAtJun 19, 2026, 10:30 AM
updatedAt3:22 PM
githubUrlhttps://github.com/neomjs/neo/issues/13532
authorneo-opus-vega
commentsCount1
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]

Sweep the AiConfig SSOT singleton binding to consistent PascalCase (aiConfig → AiConfig)

Open Backlog/active-chunk-2 airefactoringarchitecture
neo-opus-vega
neo-opus-vega commented on Jun 19, 2026, 10:30 AM

Context

PR #13526 surfaced a long-standing naming inconsistency for the AiConfig SSOT singleton import binding. Per @tobiu (2026-06-19): the config began as a plain proxy object bound as aiConfig (lowercase); after it was extended into a state.Provider-based SSOT (ADR 0019), the convention switched to AiConfig (uppercase — the config treated as a proper-noun SSOT singleton). The older code was never swept. #13526 re-introduced the lowercase binding because I lifted the pattern from MemoryService.mjs (the dominant existing usage).

Direction confirmed by @tobiu (2026-06-19), with the full scale in hand: normalize to uppercase AiConfig.

The Problem — V-B-A inventory (2026-06-19)

The config singleton (default export createConfigProxy(instance) from each ai/**/config.mjs) is imported under two casings:

  • lowercase aiConfig1,526 occurrences across 198 files: all MCP servers, the knowledge-base / github-workflow / gitlab-workflow / memory-core / neural-link services, and most specs. (The proxy-era pattern.)
  • uppercase AiConfig — 70 files: the daemons/orchestrator (the newest subsystem), the lifecycle/maintenance scripts, and the config-chain self-imports (config.mjs importing its parent/config.template.mjs as AiConfig). (The post-Provider pattern.)

The export is an instance/proxy, not a class — both casings bind the same singleton. This is purely a binding-name inconsistency; there is no contract/API change (the config export is identical), so no Contract Ledger applies.

Acceptance Criteria

  • AC1 — Sweep: normalize the ~198 lowercase-aiConfig files (import binding + all word-boundary usages) to AiConfig. After the sweep, grep -rwl '\baiConfig\b' over ai/, src/, test/, buildScripts/ returns only the explicit guard exceptions below.
  • AC2 — Prevent recurrence: codify the convention so it cannot silently re-rot — a one-line CONTRIBUTING/ADR-0019 note ("the AiConfig SSOT singleton is imported as AiConfig") plus, ideally, a fail-build lint (precedent: #13227's aiConfig-mutation lint) that flags a lowercase aiConfig import of a **/config.mjs default export. (AC2 may split to a sub if AC1 ships first.)
  • AC3 — Guards respected (see below); husky stays green; specs still pass (re-run reds for the AiConfig ESM import-race flake #12693 before blaming a diff).

Guards (must NOT be swept / care)

  • aiConfigDefaults — the separate TIER1 defaults module; a distinct identifier. A word-boundary \baiConfig\b rename does not match inside aiConfigDefaults, but verify.
  • Already-correct compounds: AiConfigModel, AiConfigDefaultsFixtureTest, AiConfigProviderTest, SnapshotAiConfigTest — leave.
  • ai/mcp/server/shared/logger.mjs uses aiConfig as a function parameter (local; receives the config object). Sub-decision: rename the params to AiConfig for full consistency (they reference the SSOT), or leave them as local camelCase. Recommend renaming for consistency; flag in the PR.
  • Mechanics: word-boundary rename only; no sed -i / bash redirection (§file_editing_tool_selection) — use the Edit tool or a sanctioned node codemod. check-aiconfig-test-mutation must stay green (this is a rename, not a mutation — verify specs still read-not-mutate).

Execution

Prefer a single mechanical word-boundary rename PR (the transformation is uniform + low-risk) with the guards verified and a cross-subsystem spot-check. If the 198-file diff proves too large to review, decompose by subsystem (memory-core · knowledge-base · github-workflow · gitlab-workflow · neural-link · shared · scripts · specs) into an epic + per-subsystem subs (1-PR-per-ticket).

Related

  • Surfaced by PR #13526 (provider-login slice, the lowercase re-introduction). Aligns-with ADR 0019 (AiConfig reactive Provider SSOT).
  • Sibling SSOT-hygiene: #12456 (read-then-re-implement antipatterns). Lint precedent: #13227. Flake guard: #12693. B4 isolation: #12435.

Release classification: post-release / consistency (not release-blocking) — boardless.

Origin Session ID: a200ff3b-5ea5-4fc0-b288-cd5fe2c917e0

Authored by Claude Opus 4.8 (Claude Code), @neo-opus-vega (Vega).