LearnNewsExamplesServices
Frontmatter
id12166
titleaiConfig realm inheritance via state.Provider parent chain
stateClosed
labels
enhancementaiarchitecture
assigneesneo-opus-ada
createdAtMay 29, 2026, 12:16 PM
updatedAtMay 29, 2026, 10:26 PM
githubUrlhttps://github.com/neomjs/neo/issues/12166
authorneo-opus-ada
commentsCount0
parentIssue12101
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtMay 29, 2026, 10:26 PM

aiConfig realm inheritance via state.Provider parent chain

Closed v13.0.0/archive-v13-0-0-chunk-14 enhancementaiarchitecture
neo-opus-ada
neo-opus-ada commented on May 29, 2026, 12:16 PM

Context

During this session's deep exploration of BaseConfig extends Neo.state.Provider (10-subagent facet analysis + operator dialogue, 2026-05-29), it became clear that PR #12164 reuses the Provider's reactive data plumbing but not its hierarchy. Operator-directed: model the aiConfig realm as a real Provider parent chain — Tier-1 = parent holding realm-wide data, each MCP-server config = child inheriting it. This maps the framework's component-tree provider hierarchy (Body) onto the Brain's config tiers, where there is no component tree.

Substantive rationale / provenance: operator-directed across multiple turns this session (the getParent() override mechanism was operator-proposed); grounded in the graduated Epic #12101 "extend Provider, don't reinvent" mandate. Not premature convergence — the shape was converged in operator dialogue. Open to cross-family peer review at PR time.

The Problem

No config sets a parent. KB + MC import AiConfig and snapshot shared leaves via default: AiConfig.x (~30 leaves in MC, ~11 in KB); the 3 workflow/inspection servers hand-copy literals. Result: massive sibling duplication, stale-snapshot risk (values frozen at module-eval), and N independent owners of every shared leaf. The Provider parent chain that would eliminate this already exists and is unused.

The Architectural Reality

  • Provider#getParent() (src/state/Provider.mjs:396) resolves _parent, else falls back to the component tree. The Brain has no component tree → override getParent() to return the Tier-1 singleton.
  • Raw-instance access is globalThis.Neo.ai.Config (placed by applyToGlobalNs, Neo.mjs:141 / singleton path :972) — not Neo.get('Neo.ai.Config'), which is id-keyed and returns nothing for a className (operator-corrected + V-B-A'd 2026-05-29).
  • getOwnerOfDataProperty (:376) recurses to the parent → reads resolve up the chain. Enumeration asymmetry: getTopLevelDataKeys (:460) is LOCAL-only — ownKeys / spread / Object.keys / JSON.stringify over a namespace do NOT merge parent leaves (facet-9 audit: no current consumer enumerates a shared namespace; all reads are keyed/dotted/destructured).
  • Split rule (operator): "as soon as ≥2 children need a leaf ⇒ move it up to Tier-1." Same env var + same default = shared; differing default ⇒ stays local.

The Fix

  1. BaseConfig.getParent() override: const root = Neo.ai?.Config; return root && root !== this ? root : null — identity guard prevents the root self-parenting (no recursion); not-yet-loaded ⇒ null ⇒ resolves locally. BaseConfig cannot statically import the root (circular — root extends BaseConfig), so it reads the global ns; lazy per-access resolution means the root only needs loading before the first realm-leaf read, not before a server constructs.
  2. Realm split: move shared leaves (auth.*, engines.chroma.*, model/graph/embedding providers, vectorDimension, backupPath, dummyEmbeddingFunction per the dummy-EF SSOT sub) to Tier-1; delete from servers (drop import AiConfig + default: AiConfig.x snapshots). Servers keep only genuinely-own leaves (ports, log prefixes, collections, behavior flags).
  3. Cross-tier write validation: internalSetData resolves getOwnerOfDataProperty(key) and validates against the owner's registry (facet-8: a child write to a parent-owned leaf currently bypasses validation on both tiers).

Contract Ledger

Target Surface Source of Authority Proposed Behavior Fallback Docs Evidence
BaseConfig.getParent() ai/BaseConfig.mjs (new override) Returns Tier-1 Neo.ai.Config raw singleton; null for root/unloaded local resolution JSDoc Provider seam verified Provider.mjs:376/396
Shared realm leaves (auth.*, chroma.*, providers…) server config.template.mjs → Tier-1 Declared once at Tier-1; servers inherit via chain local re-declare to override JSDoc Duplication confirmed (facet-5)
internalSetData owner-registry validation ai/BaseConfig.mjs Validate against owner's #leafMetadataRegistry Cross-tier bypass confirmed (facet-8)

Acceptance Criteria

  • BaseConfig.getParent() override + identity guard; unit test: a server config resolves a Tier-1-only leaf via the chain; root returns null; a bare instance with no root registered resolves locally.
  • Shared leaves declared once at Tier-1; servers no longer import AiConfig for default: AiConfig.x snapshots.
  • All existing consumers still read AiConfig.X.Y unchanged (facet-9: every call-site is keyed/dotted/destructured).
  • Cross-tier write validates against the owner's registry.
  • No new enumeration/spread/JSON.stringify over a realm namespace (enumeration stays local-only).

Out of Scope

  • data + afterSetData reshape and the leaf(default, env, type) factory — separate, elegance-not-correctness (file only if pursued).
  • Enumeration-merge override for ownKeys/getTopLevelDataKeys — DEFERRED; no current consumer needs it (document as a latent hazard).
  • The dummyEmbeddingFunction definition-consolidation — the dummy-EF SSOT sub (this ticket makes it chain-inherited).
  • internalSetData object-leaf validation completeness — the validation-completeness sub.

Avoided Traps

  • Per-child parent: config wiring (rejected): forces a static import edge → transitive unitTestMode className co-instantiation in every spec worker; proxy-vs-raw footgun; runtime-parent-must-be-overlay ambiguity. The getParent() override dissolves all three (no import edge; returns the raw globalThis.Neo.ai.Config; one global singleton resolves to the overlay at runtime).

Decision Record impact

none — extends Epic #12101's "extend Provider, don't reinvent" mandate; operator-directed this session. Downstream amendment note: if peer review at PR time reshapes the wiring, this body's Fix section may need refresh.

Related

  • Epic #12101; Discussion #12100 (graduated source); PR #12164 (merged Stage 1); the dummy-EF SSOT sub (becomes chain-inherited).

Origin Session ID: b124b83a-2cca-4a2b-a711-64868439ba1e Retrieval Hint: "aiConfig parent chain getParent override realm split globalThis Neo.ai.Config"

tobiu referenced in commit 1d08070 - "refactor(ai): defrag uses canonical dummyEmbeddingFunction; drop github-workflow copy (#12165) (#12169) on May 29, 2026, 1:32 PM
tobiu referenced in commit bffd8b4 - "refactor(ai): BaseConfig prototype shape — data+afterSetData + leaf() factory (#12168) (#12172) on May 29, 2026, 4:48 PM
tobiu referenced in commit c0f6baf - "feat(ai): aiConfig realm split — KB + MC inherit Tier-1 leaves via getParent chain (#12166) (#12179) on May 29, 2026, 10:26 PM
tobiu closed this issue on May 29, 2026, 10:26 PM