LearnNewsExamplesServices
Frontmatter
title>-
authorneo-opus-vega
stateClosed
createdAtJul 16, 2026, 10:02 AM
updatedAtJul 27, 2026, 12:05 AM
closedAtJul 16, 2026, 10:37 AM
mergedAt
branchesdev ← agent/14674-template-extendable-base
urlhttps://github.com/neomjs/neo/pull/15219
contentTrust
projected
quarantined0
signals[]
Closed
neo-opus-vega
neo-opus-vega commented on Jul 16, 2026, 10:02 AM

Resolves #14674

The config plane's overlay-drift class gets its root fix: every default leaf and formula moves into a new non-singleton Neo.ai.ConfigBase (ai/configBase.mjs, zero instantiation side effects), and ai/config.template.mjs becomes the thin, still-eager Neo.ai.Config singleton subclass — byte-identical external behavior, so the Tier-2 server templates' side-effect import (which materializes the Tier-1 parent for getParent registry resolution) and the Playwright template-resolver world are untouched. New-shape operator overlays subclass the base and carry delta-only leaf() declarations: Neo.setupClass's descriptor-driven hierarchical merge (the merge: 'deep' descriptor on the Provider's data_) makes a leaf added to the base reach every subclass overlay with zero overlay edits — spec-proven. Namespace-idempotency IS the dual-shape loader: a snapshot-style overlay self-registers Neo.ai.Config first and wins exactly as today (fail-open, deprecated-honest in the template docblock + migration output); ConfigProvider.load()'s .mjs side-effect-import path covers both shapes unchanged. A new ai/scripts/setup/migrateConfigOverlay.mjs converts existing snapshot overlays: preview-first (--write applies with a .pre-migration.bak), idempotent via shape detection, and diffing at the DECLARATION level (leaf descriptors projected without the derived parse function) so the machine's env can neither fake nor mask a delta; non-renderable differing leaves (function-valued defaults) are reported honestly and left to inherit. initServerConfigs' verbatim root copy means fresh bootstraps get the subclass shape automatically with no pipeline change.

Evidence: L2 (51 unit specs green across the five impacted suites + lint-config-template-ssot clean) → L3 (live read-only preview of the migration script against this machine's real operator-managed snapshot overlay: drift none, deltas none, dummyEmbeddingFunction honestly skipped). Residual: none — close-target ACs covered by specs + the live preview.

Deltas from ticket

  • Design correction recorded on the ticket (two checkpoint comments): the initially-sketched lazy default export was falsified against the Tier-2 seam (per-server templates side-effect-import the root template precisely to eagerly materialize the Tier-1 parent) — the shipped shape is three files with NO laziness; the template stays eager and byte-identical.
  • Overlay-delta contract sharpened: deltas must be leaf() declarations, not bare primitives — a primitive merged over a leaf descriptor does not survive ConfigProvider construction (empirically falsified). Documented in the template docblock with a worked example.
  • leaf()'s real return shape drove the diff design: {default, env, ...metadataSpread, type, parse: Function|null} — the derived parse (a function on every env-bound leaf) is excluded from equality via a projection, and spread metadata is reconstructed into the leaf() 4th argument on render.
  • The "three lived drift instances as named fixtures" AC (E6 seed): the inheritance proof covers the drift CLASS structurally (any base leaf reaches a delta overlay unchanged); the three historical instance leaf-names from the retired-epic corpus are not individually re-enumerated here. If the reviewer wants them named, that is a follow-up fixture addition, not a design gap.
  • Loader change turned out to be zero-code: the "loader accepts both shapes" AC is satisfied by namespace-idempotency + the existing load() import path — verified rather than built.

Test Evidence

  • Lane suites: npx playwright test -c <unit config> test/playwright/unit/ai/{configBase,config.template,ConfigProvider,migrateConfigOverlay}.spec.mjs test/playwright/unit/test/ConfigTemplateResolver.spec.mjs --workers=1 — 51 passed (root-fix inheritance proof, deep-merge sibling survival, formula inheritance, zero-side-effect base, template-shape ledger assertions, resolver world unchanged, migration helpers incl. parse-identity immunity + metadata round-trip).
  • SSOT lint: node ai/scripts/lint/lint-config-template-ssot.mjs — clean (0 violations, baselines intact).
  • Live falsifier (read-only): node ai/scripts/setup/migrateConfigOverlay.mjs against this machine's real snapshot overlay — drift none / deltas none / one honest function-default skip; the generated subclass overlay renders cleanly.
  • Directly touched surfaces: ai/configBase.mjs + ai/config.template.mjs: configBase.spec.mjs + config.template.spec.mjs | ai/scripts/setup/migrateConfigOverlay.mjs: migrateConfigOverlay.spec.mjs.

Post-Merge Validation

  • Run node ai/scripts/setup/migrateConfigOverlay.mjs (preview) on a deployment clone with a hand-edited snapshot overlay and confirm the delta report matches the operator's known edits before any --write.
  • After the next template leaf addition lands, confirm a migrated (subclass-shape) overlay resolves it with zero overlay edits — the root-fix proof against live history.

Commits

  • 99e8a757c7 — split the template into the extendable non-singleton ConfigBase + the thin eager singleton subclass; adapt the ledger spec; add the inheritance/deep-merge/formula/zero-side-effect proofs.
  • 5aa02fec82 — the snapshot-overlay migration script (preview-first, idempotent, declaration-level projection diff) + its 12-spec suite.

Evolution

Two of my own assumptions died to live falsification mid-implementation: reaching the overlay class through the config proxy's constructor returns a bound function that drops statics (everything misread as drift → fixed via the registry path), and the assumed leaf() shape omitted the derived parse function (everything misread as non-renderable → fixed via the projection). Both are the same lesson the ticket's own stale-extractor paragraph taught: read the primitive before coding against its imagined shape.

Authored by Vega (Claude Fable 5, Claude Code). Session c4f8e75b-bf73-448b-bee3-6a17e3b1cb45.

neo-opus-vega
neo-opus-vega commented on Jul 16, 2026, 10:37 AM

Superseding with #re-filed PR — this PR object never received a single Actions event (opened/reopened/synchronize all suppressed while sibling branches trigger normally; elimination trail in the session record). Same commits continue on agent/14674-configbase-split.