LearnNewsExamplesServices
Frontmatter
id11832
titleSub 6: Neo.util.Env THIN substrate primitive (lift EnvConfig.mjs parsers to src/util/Env.mjs)
stateClosed
labels
enhancementairefactoringarchitecture
assigneesneo-opus-ada
createdAtMay 23, 2026, 1:21 PM
updatedAtJun 7, 2026, 7:14 PM
githubUrlhttps://github.com/neomjs/neo/issues/11832
authorneo-opus-ada
commentsCount0
parentIssue11831
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[x] 11833 Sub 1: Orchestrator masterclass-reference refactor (4-way Service-DI + 2-value chain + configure() removal)
closedAtMay 23, 2026, 2:15 PM

Sub 6: Neo.util.Env THIN substrate primitive (lift EnvConfig.mjs parsers to src/util/Env.mjs)

Closed v13.0.0/archive-v13-0-0-chunk-13 enhancementairefactoringarchitecture
neo-opus-ada
neo-opus-ada commented on May 23, 2026, 1:21 PM

Parent Epic

#11831Sub 6 of 6 (substrate-prerequisite; blocks Sub 1).

Scope

THIN substrate-utility primitive. Lift ai/mcp/server/shared/helpers/EnvConfig.mjs parsers verbatim to src/util/Env.mjs as Neo.util.Env (mirrors Neo.util.String static-class precedent). Provides Orchestrator-needed parser surface so Sub 1 can implement the 2-value chain via Neo.util.Env.parseNumber().

Scope-bounded per Discussion #11828 Cycle-3.1 deferral fixup (avoid recreating the #11075 "start somewhere" failure). DOES NOT include the full 61-file consumer migration — that decomposes into separate Sub 6a/6b/6c follow-up tickets (orchestrator-cluster, mcp-cluster, daemon-cluster, ad-hoc-cluster).

Acceptance Criteria

  1. Create src/util/Env.mjs extending Base, Neo.setupClass() registered as Neo.util.Env. Mirrors src/util/String.mjs static-class pattern.
  2. API surface (lifted from EnvConfig.mjs + Orchestrator-needed): parseNumber(rawValue, envVarName, warn?), parseBool(rawValue, envVarName, warn?), parsePort(rawValue, envVarName, warn?), parseUrl(rawValue, envVarName, warn?), parseString(rawValue), applyEnvBindings(data, bindings, env?, warn?), setDeep(obj, path, value).
  3. Boolean compatibility: parseBool accepts permissive token set preserving both MCP ('true'/'false') and daemon (PrimaryRepoSyncService.parseEnabledFlag '0'/'no'/'off') semantics. Tokens: true = 'true'/'yes'/'on'/'1'; false = 'false'/'no'/'off'/'0'; else warn + undefined. Case-insensitive after trim.
  4. Add Env entry to src/util/_export.mjs barrel.
  5. Availability: consumers use direct import Env from '<path>/src/util/Env.mjs' (NOT relying on Neo.util.Env global — orchestrator-daemon.mjs boots src/core/_export.mjs, not the util barrel).
  6. Decoders MUST NOT know AiConfig / defaults / aliases / fallback chains / specific domain consumers (substrate-tier discipline). Fallback to AiConfig stays at consumer call-site.
  7. Number(undefined) === NaN gotcha protection: parseNumber returns undefined (NOT NaN) for absent input, so Env.parseNumber(...) ?? AiConfig.X correctly falls through to AiConfig fallback.
  8. Test surface: test/playwright/unit/util/Env.spec.mjs proves decoder semantics: absent/empty/null → undefined no warn; well-formed → decoded; malformed → warn + undefined; ?? fallback works correctly; boolean tokens (both MCP + daemon sets); port out-of-range; URL normalization; prototype-pollution guards in setDeep; applyEnvBindings skip-on-absent + skip-on-malformed.

Out-of-scope (follow-up subs)

  • 61-file / 80 env-var consumer migration → Sub 6a (orchestrator-cluster), Sub 6b (mcp-cluster), Sub 6c (daemon-cluster), Sub 6d (ad-hoc-cluster)
  • EnvConfig.mjs deletion → after Sub 6a/6b consumers rewire
  • CadenceEngine.parseInterval deletion → after Sub 1 lands
  • PrimaryRepoSyncService.parseEnabledFlag deletion → after Sub 6c daemon migration

Files (new + touched)

  • NEW: src/util/Env.mjs (~190 lines, lifted from EnvConfig.mjs + Orchestrator-needed surface)
  • EDIT: src/util/_export.mjs (add Env import + export entry)
  • NEW: test/playwright/unit/util/Env.spec.mjs
  • (no EnvConfig.mjs deletion — consumer rewire deferred to follow-up subs to keep this PR thin)

Authored by: [Claude Opus 4.7] (Claude Code)

tobiu referenced in commit 07e4389 - "feat(util): Neo.util.Env substrate primitive for env-var parsing (#11832) (#11838) on May 23, 2026, 2:15 PM
tobiu closed this issue on May 23, 2026, 2:15 PM
tobiu referenced in commit 27f7a65 - "refactor(agentos): Orchestrator masterclass-reference (4-way Service-DI + Neo.util.Env + configure() removal) (#11833) (#11842) on May 23, 2026, 3:10 PM
tobiu referenced in commit 7e7adb2 - "refactor(agentos): delete obsolete CadenceEngine.parseInterval + PrimaryRepoSyncService.parseEnabledFlag (#11835) (#11843) on May 23, 2026, 3:28 PM