LearnNewsExamplesServices
Frontmatter
id17472
titleADR-0019''s catalog has no row for the violation #17448 just shipped a fix for: two leaves, one env var
stateClosed
labels
documentationenhancementaiarchitectureagent-os
assigneesneo-gpt-emmy
createdAtAug 21, 2026, 3:52 PM
updatedAtAug 25, 2026, 12:36 AM
githubUrlhttps://github.com/neomjs/neo/issues/17472
authorneo-opus-vega
commentsCount1
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtAug 25, 2026, 12:36 AM

ADR-0019's catalog has no row for the violation #17448 just shipped a fix for: two leaves, one env var

Closed Backlog/active-chunk-18 documentationenhancementaiarchitectureagent-os
neo-opus-vega
neo-opus-vega commented on Aug 21, 2026, 3:52 PM

Context

Found by @neo-opus-grace while reviewing PR #17465 (#17448), and filed by me as ticket author of the PR that surfaced it. She raised it as a [KB_GAP] observation rather than a required action, correctly — it is a catalog gap, not a defect in the PR.

Live latest-open sweep: latest 15 open issues read at 2026-08-21T13:35Z. state:all searches for ADR-0019 catalog row, aiconfig catalog taxonomy gap, leaf duplication env var — zero hits. No A2A claim on this scope.

ADR-0019 read in full before authoring, per §critical_gates #10.

The Problem

#17448 removed two Tier-1 leaves bound to one env var (chatProvider and modelProvider, both on NEO_MODEL_PROVIDER, with an in-docblock instruction to keep them aligned by hand). I labelled it a Group B violation, and the ADR's decision sentence (:26) backs that by name:

"Never re-implement, alias, export, pass-along, mutate, or defend against the SSOT."

alias is right there. But no row in the tabled catalog covers it, and a reviewer checks the table.

Verified row by row at tree d6a7e9c92f:

group what the rows actually cover leaf+leaf?
A1–A9 re-deriving resolution outside the SSOT — module-level process.env reads, cascade hooks, resolution helpers, inline test-mode ternaries, hasEnvValue, path-join formulas no
A6 leaf+formula duplication (one path defined in both) no — the second definition is a formula
B1–B5 indirection around the SSOT — exporting subtrees, const X = AiConfig.Y pointers, defensive ?., runtime writes, pass-along threading no

So the nearest neighbours are A6 (duplication, but leaf+formula) and B1–B5 (indirection, but not duplication). Two leaves duplicating each other inside the SSOT falls between them. A first grep of mine returned three apparent matches; printing them showed all three were false positives — "leaf" recurring in the remedy column, not the pattern column. The gap is real.

Why it matters more than a missing row usually would

§critical_gates #10 makes reading this ADR mandatory before authoring or reviewing any ai/ config touch, and names "The ADR §3 catalog is the forbidden-pattern list." So the catalog is not illustrative — it is the operative checklist a reviewer runs. A pattern the decision sentence forbids but the checklist omits is a pattern that passes review by construction.

The empirical case is already recorded: the duplicate leaf pair survived in configBase.mjs with a docblock openly describing the manual-sync arrangement, and a spec (config.template.spec.mjs) that actively pinned the two-sources-of-truth invariant with expect(Config.modelProvider).toBe(Config.chatProvider). Nothing flagged it, because nothing in the table describes it.

The Architectural Reality

  • learn/agentos/decisions/0019-aiconfig-reactive-provider-ssot.md:26 — the decision sentence naming alias.
  • :48-56 — Group A rows; :53 is A6, the closest analogue.
  • :61-65 — Group B rows; all indirection-around, none duplication-inside.
  • PR #17465 — the fix, and the worked example a new row can cite.
  • .claude/CLAUDE.md §critical_gates #10 — what makes the catalog operative rather than illustrative.

Contract Ledger Matrix

Target Surface Source of Authority Proposed Behavior Fallback Docs Evidence
ADR-0019 §3 catalog the decision sentence at :26 one new row: two leaves bound to one env var, or two leaves declaring one value none — this adds a row, it removes no rule the ADR itself #17448 shipped past two gates and a spec
the new row's remedy existing A6 convention "one definition — delete the leaf with no readers, or migrate readers and delete the other" PR #17465 chose deletion; reader count decided which
Groups A and B boundary ADR §3 the row must land in whichever group the ADR's own framing implies — an open question, see below A = re-derivation, B = indirection; this is neither

The open question this ticket does NOT decide

Which group does it belong to? Group A is "re-implementing resolution", Group B is "indirection around the SSOT". Leaf+leaf duplication is neither — it is duplication inside the SSOT with no indirection and no re-derivation. Three candidate shapes, and I deliberately do not pick:

  1. A new A10 — treating duplication as a Group-A concern, consistent with A6 already being a duplication row.
  2. A new B6 — treating "alias" as the operative word, since the decision sentence lists it among the Group-B-flavoured verbs.
  3. A third group — "duplication inside the SSOT", with A6 moved into it, since A6 is arguably misfiled in Group A for the same reason.

Option 3 is the tidiest and the highest blast radius, because it renumbers an existing row that other artifacts may cite. That is a taxonomy decision for the ADR's owners, not a cleanup call — which is why this is a ticket asking for the row, not a PR adding one.

Acceptance Criteria

  • The catalog contains a row whose pattern column describes two leaves bound to one env var (or two leaves declaring one value), with a remedy and a [live: …] / [proposed] status marker matching the existing row format.
  • The row's group placement is recorded with a one-line rationale, so the A-vs-B-vs-new-group question is answered in the ADR rather than re-litigated per review.
  • If A6 moves, every artifact citing A6 is updated in the same change — a grep for A6 across learn/ and .agents/ with the tree recorded, so a renumber cannot silently orphan a citation.
  • A reviewer running only the §3 catalog against #17448's original configBase.mjs state would now flag it. Demonstrated against the pre-fix revision, not asserted.
  • §critical_gates #10's description of the catalog stays accurate if the group structure changes.

Out of Scope

  • Re-auditing the codebase for other instances. Worth doing; not this ticket. Adding the row is what makes such an audit checkable.
  • Changing the decision sentence. It already forbids this. Only the catalog is incomplete.
  • #17448 / PR #17465. Grace explicitly scoped this as not a defect in that PR, and its label is correct by the decision sentence.

Avoided Traps

Adding the row unilaterally as a "doc fix". The group placement is a taxonomy decision, and option 3 renumbers a row other artifacts may cite. A one-line diff with a cross-substrate consequence is exactly the shape that should not ride in on someone's cleanup PR.

Treating "the decision sentence covers it" as sufficient. It is why my Group-B label was correct and simultaneously why the gap is dangerous: the sentence is read once, the table is read every review. Grace's framing — "a reviewer checks the table" — is the whole finding.

Assuming the grep. My first census of the rows returned three matches and all three were false positives from the remedy column. Any AC here needs the rows read, not counted.

Related

  • #17448 / PR #17465 — the worked example; a new row should cite it.
  • #17344, #17466 — open tickets in the same ADR-0019 family, useful as further worked examples if the row wants more than one.
  • ADR 0019 — the subject.

Credit: @neo-opus-grace, PR #17465 review (reviewId 4993847156).

Retrieval Hint: ADR-0019 section 3 catalog has no row for two leaves bound to one env var; A6 is leaf+formula duplication and B1-B5 are indirection around the SSOT so leaf+leaf duplication inside the SSOT is untabled; decision sentence names alias but reviewers check the table

tobiu referenced in commit 0b46957 - "docs(agentos): catalog duplicate AiConfig leaves (#17472) (#17741) on Aug 25, 2026, 12:36 AM
tobiu closed this issue on Aug 25, 2026, 12:36 AM