Repository navigation
Description
test(core): add a deterministic per-field guard that every config schema field survives normalization — the Arbitrary round-trip missed the provider_routes drop that reached production
Evidence (verified 2026-11-01 on main 23b2e8e659)
packages/core/src/config/normalize.ts rebuilds the config document key by
key (normalizeExperimental at line 461ff, the nativeAtomic table at
lines 218–232, and per-section helpers). A schema field that nobody adds to
the rebuild is silently dropped — no diagnostic, no error.
This exact omission has now bitten twice in the routing surface alone:
experimental.provider_routes(added by feat(core): provider routes — provider-level pools with ordered/round-robin/weighted selection #1134) was never added to
normalizeExperimental; every normalized config silently lost its provider
route groups. It reached production: on 2026-11-01, collapsing the GPT
routes to a single provider route produced zero group decisions across
~40 minutes / 374 decisions, and the seats vanished with no candidate, no
exclusion entry, and no warning (fix commit5436247665, PR fix(config): provider_routes dropped by config normalization — provider-route groups never candidated (#1134) #1277).experimental.model_route_settings(feat(routes): experimental.model_route_settings — route machinery constants as config (#1141) #1142) was dropped by the same
omission; invisible only because its defaults equal the old hardcoded
constants.
The existing guard did not catch either: packages/core/test/config/normalization.test.ts
has a property test, "preserves arbitrary JSON-round-tripped native
configuration" (line ~144), which runs Arbitrary.schema(Info) for only
100 runs. The schema is almost entirely optional and deeply nested, so a
given run rarely populates any specific field — and the test file's own
history proves the gap: the property test has existed since 2026-10-17
(commit 1fc489d878), provider_routes entered the schema later (#1132),
and the drop still shipped. The regression tests added by #1277
(normalization.test.ts lines 960 and 992) pin those two fields by name —
the next new field gets no such protection unless someone remembers.
Proposal
Add a deterministic guard test in
packages/core/test/config/normalization.test.ts (or a sibling file) that
enumerates the schema itself — e.g. Object.keys(Config.Info.fields) and
Object.keys(ConfigExperimental.Info.fields) — and, for every field,
asserts a normalization round-trip with that field populated by a minimal
schema-valid value (generated per-field via Arbitrary on the single field
schema, or a maintained minimal-fixture table keyed by field name, failing
loudly when a new field has no fixture). Fields with intentional transforms
(legacy migrations, experimental.policies → top-level policies,
experimental.aliases → top-level aliases, malformed-note filtering) are
asserted at their documented destination, reusing the existing
withoutEmptyCompatibilityContainers / withoutMalformedNotes adjustments
where they already encode the intent.
Why it matters
Config normalization sits under every config read in the fork; its failure
mode is the worst kind — a user's setting silently does nothing. The routing
features are actively growing new experimental fields (#1132–#1142 in the
last weeks), so the hand-maintained rebuild list will keep drifting from
the schema until the schema itself drives the test.
Acceptance criteria
- A test enumerates all
Config.Infotop-level fields and all
ConfigExperimental.Infofields from the schema (not a hand-copied
list) and asserts each survivesConfigNormalize.normalize+
decode, at its documented destination for intentionally-moved fields. - The test fails when run against a normalize.ts with one handled field
deliberately removed (mutation-checked during development, e.g.
against the pre-fix(config): provider_routes dropped by config normalization — provider-route groups never candidated (#1134) #1277 tree or a temporary local removal). - Existing normalization tests still pass; the two fix(config): provider_routes dropped by config normalization — provider-route groups never candidated (#1134) #1277 per-field
regression tests may stay or be subsumed. - Runs in the normal
packages/coretest suite (no new CI wiring).
Activity
developing-today commentedon Nov 1, 2026
OPENCODE-344
dezren39 commentedon Nov 1, 2026
🤖 Agent note · filed
packages/core/src/config/normalize.ts) rebuilds the document key by key, and the schema-driven guard that should catch a dropped field does not: the Arbitrary round-trip property test (100 runs over an almost-all-optional schema) existed since 2026-10-17 yet missed theexperimental.provider_routesdrop (feat(core): provider routes — provider-level pools with ordered/round-robin/weighted selection #1134) that reached production on 2026-11-01 (fix fix(config): provider_routes dropped by config normalization — provider-route groups never candidated (#1134) #1277) and themodel_route_settingsdrop (feat(routes): experimental.model_route_settings — route machinery constants as config (#1141) #1142) from the same omission. Verified this run against main 23b2e8e (normalize.ts:461ff, normalization.test.ts:144ff/960/992, git history 1fc489d). Enqueued as a repo-task/v1 packet on repo-health-opencode-pilot.Config.Info.fields+ConfigExperimental.Info.fields; mutation-checked against a removed field.dezren39 commentedon Nov 1, 2026
🤖 Agent note · state: picked up
Merge pull request #1293 from developing-today/queue/5621-1285-per-fi…
dezren39 commentedon Nov 1, 2026
🤖 Agent note · state: done
bun test test/config/normalization.test.tsre-run: 97 pass, 0 fail. Mutation check (prior attempt): guard fails with provider_routes handler disabled in normalize.ts, restored after. Codex review on PR test(core): per-field normalization survival guard (#1285) #1293: completed, no findings.