LearnNewsExamplesServices
Frontmatter
id15213
titleExtend the AiConfig antipattern lint to A1 module-level env re-derivation
stateClosed
labels
enhancementaiarchitecturebuild
assigneesneo-opus-grace
createdAtJul 16, 2026, 9:23 AM
updatedAtJul 16, 2026, 6:11 PM
githubUrlhttps://github.com/neomjs/neo/issues/15213
authorneo-opus-grace
commentsCount2
parentIssue12456
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[x] 14500 ADR-0019 lint: fail-build on defensive optional-chaining (B3) + env-helper reintroduction (A5) on AiConfig
blocking[]
closedAtJul 16, 2026, 6:11 PM
milestonev13.2

Extend the AiConfig antipattern lint to A1 module-level env re-derivation

Closed Backlog/active-chunk-6 enhancementaiarchitecturebuild
neo-opus-grace
neo-opus-grace commented on Jul 16, 2026, 9:23 AM

Context

PR #15211 (#14500) shipped the ADR-0019 mechanical backstop for B3 (defensive optional-chaining on AiConfig reads) and A5 (hasEnvValue reintroduction). A1 — module-level env re-derivation (const DB_PATH = process.env.X || path.join(...)) in ai/ files that already import AiConfig — was explicitly scoped out as the named fast-follow: it needs a two-signal detection (import-awareness) that the B3/A5 single-regex shape doesn't, and bundling it would have slowed the ratchet's landing. This leaf completes the mechanically-detectable subset of the catalog.

The Problem

A1 is tagged [live-on-dev] in the ADR-0019 §3 catalog (daemon entrypoints re-derive paths with AiConfig in scope). The sanctioned form is reading the resolved leaf at the use site — the leaf already owns env-override-with-default. Nothing mechanical prevents new A1 sites; review diligence is the empirically-falsified defense (the same 4/4-miss class that motivated the parent epic).

The Architectural Reality

  • buildScripts/util/check-aiconfig-antipatterns.mjs (shipped by PR #15211) carries an extensible RULES array, the shared codeMask string/comment masking (imported from the B4 sibling), an ESCAPE_MARKER relief valve, and a census-seeded ALLOWLIST ratchet. A1 slots in as a third rule — but with a file-level pre-condition, not just a line regex.
  • The A1-vs-C1 distinction is load-bearing (ADR-0019 §3 classification correction + §5.5): A1 = re-derivation in a file that DOES import AiConfig (fix: read the leaf); genuine C1 = a non-entrypoint pure-defaults module with NO Neo import (its process.env literals are the SANCTIONED form). The lint MUST fire only when the file imports AiConfig (or Memory_Config/Neo.ai.Config shapes) — otherwise it would flag the pure-defaults pattern the ADR prescribes.
  • Detection heuristic: a module-level const|let|var declaration whose initializer reads process.env. in an AiConfig-importing ai/ file. Column-0 declaration is the pragmatic module-level signal in Neo's indent style; the escape marker covers judgment-call residue (e.g. a deliberate bootstrap-boundary value object per §5.5).

The Fix

  1. Add an A1 rule to check-aiconfig-antipatterns.mjs: on the current dev code-only projection, it fires per offending line ONLY when the file content also matches an AiConfig import (two-signal: file gate + same-line, column-zero declaration regex). This leaf does not widen the shared codeMask; executable template-interpolation and parser-grade mask fidelity are owned by successor #15276 and are pinned here as an explicit boundary.
  2. Census the current ai/ tree at implementation time; seed the ALLOWLIST with live A1 files (the daemon entrypoints named by the ADR are expected members) so the ratchet bites only NEW offenders.
  3. Extend the spec: positive (re-derivation with import), negative (pure-defaults module WITHOUT AiConfig import must NOT flag — the C1-sanctioned form), function-local process.env reads must NOT flag (module-level only), escape marker, allowlist.
  4. The existing workflow (aiconfig-antipattern-lint.yml) already covers the checker path — no workflow change expected.

Acceptance Criteria

  • On the current dev codeMask, A1 flags same-line, column-zero module-level declarations whose executable process.env. token remains visible, ONLY in ai/ files importing AiConfig (two-signal detection). Masked template-interpolation is explicitly outside this leaf and owned by #15276.
  • The C1-sanctioned pure-defaults shape (no Neo/AiConfig import) does NOT flag — spec-pinned negative.
  • Function-local env reads do NOT flag — spec-pinned negative.
  • ESCAPE_MARKER + ALLOWLIST semantics identical to B3/A5; allowlist seeded from a fresh census.
  • Spec suite green; live scan reports 0 new violations at head.

Out of Scope

  • B5 / C1 / A6 / A7 checks (AST-level; separate fast-follows under the parent epic).
  • Parser/tokenizer-grade shared codeMask fidelity, including executable template interpolation and the broader slash/continuation grammar (#15276).
  • Cleanup of the allowlisted A1 sites (Diamond-2 subs own that).

Decision Record impact

aligned-with ADR 0019 (implements its §7.2 sub-2 catalog subset; no amendment).

Related

Parent epic: #12456 · predecessor: #14500 / PR #15211 (B3+A5 ratchet, checker + workflow + spec shapes to mirror) · terminal predecessor: PR #15226 (closed Drop+Supersede) · parser-grade mask successor: #15276.

Live latest-open sweep: checked latest 20 open issues at 2026-07-16 ~07:22Z; no equivalent found. A2A in-flight claim sweep: herd-window claims (#14674, #15207, #15185, #15087, D#15204/G5) all disjoint — clean. Structure-map gate: N/A — extends an existing buildScripts/util checker in place; sibling precedent is the file itself.

Origin Session ID: 75ed6708-c66b-4989-862d-2286e87abbf1

Retrieval Hint: "AiConfig antipattern lint A1 module-level env re-derivation two-signal import-aware"

tobiu referenced in commit 82d701d - "feat(build): A1 env-re-derivation rule — the salvage re-land on the dev mask (#15213) (#15275) on Jul 16, 2026, 6:11 PM
tobiu closed this issue on Jul 16, 2026, 6:11 PM