fix(config): allow thinkingLevelMap in persisted model schema#91037
Conversation
|
Codex review: needs maintainer review before merge. Reviewed June 6, 2026, 9:01 PM ET / 01:01 UTC. Summary PR surface: Source +16, Tests +85, Generated 0. Total +101 across 4 files. Reproducibility: yes. source-reproducible: current main and Review metrics: 1 noteworthy metric.
Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Land this schema alignment after normal maintainer review and green checks; no broader provider or runtime refactor appears needed for this bug. Do we have a high-confidence way to reproduce the issue? Yes, source-reproducible: current main and Is this the best way to solve the issue? Yes: adding a strict optional AGENTS.md: found and applied where relevant. Codex review notes: model gpt-5.5, reasoning high; reviewed against 6d2566682a3f. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Source +16, Tests +85, Generated 0. Total +101 across 4 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
|
Independent L2 verification (LiuwqGit)Verified the same fix shape locally on branch Evidence after fix
{ "ok": true }Before (main): Tests (all green)Key regression tests:
Proof limitationsNo live Entra ID / Microsoft Foundry environment — L2 schema-validation proof only. Happy to help if additional CI or proof gaps remain. |
|
The red checks here ( I hit the identical set on my now-closed #91045 (the same Foundry Flagging so the red CI isn't chased as a fault of this diff — the schema change plus the positive/negative regression tests here look like the right shape. I closed #91045 in favor of this one. 👍 |
The persisted zod ModelDefinitionSchema (src/config/zod-schema.core.ts) was strict and had no thinkingLevelMap key, while the rest of the contract already carried it: the TS type (ModelDefinitionConfig.thinkingLevelMap in types.models.ts), the runtime TypeBox schema (ThinkingLevelMapSchema in agents/sessions/model-registry.ts), and the foundry writer (buildFoundryThinkingLevelMap, 7 keys: off/minimal/low/medium/high/xhigh/max). On Microsoft Foundry Entra ID onboarding the writer's persisted model entry hit the strict schema, validation failed with Unrecognized key "thinkingLevelMap", and updateConfig atomically rolled the whole write back, so onboarding never completed. This is schema drift, not an illegal field. Fix: add an optional thinkingLevelMap to the zod ModelDefinitionSchema, mirroring the TypeBox key set 1:1 (string | null values) and keeping .strict(). The writer and normalizeResolvedModel are unchanged. docs/.generated/config-baseline.sha256 is a derived artifact of this schema change, regenerated via `pnpm config:docs:gen` (config:docs:check now passes); it was not hand-edited. Closes openclaw#91011
60fb8c6 to
7813ccb
Compare
|
Land-ready maintainer proof for rebased head What changed:
Tested locally before landing: Real behavior proof status:
CI note:
|
Summary
Microsoft Foundry onboarding with Entra ID failed to persist: writing the
config hit a strict-schema validation error and
updateConfigatomically rolledthe whole write back, so onboarding never completed.
Root cause — schema drift
thinkingLevelMapis part of the established model contract everywhere exceptthe persisted zod schema:
thinkingLevelMap?ModelDefinitionConfig.thinkingLevelMap—src/config/types.models.tsThinkingLevelMapSchema—src/agents/sessions/model-registry.tsbuildFoundryThinkingLevelMap—extensions/microsoft-foundry/shared.tsModelDefinitionSchema(.strict()) —src/config/zod-schema.core.tsThe foundry writer's persisted model entry carries
thinkingLevelMap(7 keys),but the strict persisted
ModelDefinitionSchemahad no such key, so the writewas rejected and rolled back. This is schema drift, not an illegal field — the
runtime
normalizeResolvedModelre-adds the field anyway.Fix
Add an optional
thinkingLevelMapto the zodModelDefinitionSchema, mirroringthe runtime TypeBox schema 1:1: the 7
ModelThinkingLevelkeys(
off/minimal/low/medium/high/xhigh/max), valuesstring | null, with the object kept.strict().buildFoundryThinkingLevelMap,onModelSelected) andnormalizeResolvedModelare unchanged — only the persisted schema neededto accept the existing field.
Tests
src/config/config.schema-regressions.test.ts:thinkingLevelMapnow passesvalidateConfigObject. This is the assertion that reproduces and would havecaught the bug.
thinkingLevelMapkey outsideModelThinkingLevel(e.g.adaptive) is still rejected — proves.strict()was not loosened topassthrough.
extensions/microsoft-foundry/index.test.ts: asserts the realwriter output (Entra ID + reasoning model) emits only allowed
thinkingLevelMapkeys with
string | nullvalues.extensions/AGENTS.mdforbids importing
src/**from a plugin, so the persisted-validationassertion lives in the core test, and the extension side asserts the writer
output is a subset of the allowed key set.
Real behavior proof (required for external PRs)
Note on affected version: the bug ships in the released
2026.6.1(npmlatest) and thebetachannel (2026.6.5-beta.2), not justmain— the originally reported version (2026.6.1) was correct. An interimgrepofdist/extensions/microsoft-foundry/shared.jsreturned 0 and briefly suggested 2026.6.1 was unaffected, but that was a bundling artifact: the writer'sthinkingLevelMapemission lives in a helper chunk thatshared.jsonly imports. Actually running each shipped build's writer + validator confirms all three are affected (table below).thinkingLevelMap?2026.6.1(npmlatest)ok=false@models.0ok=true2026.6.5-beta.2(npmbeta)ok=false@models.0ok=truemain@4d142b185e(PR parent)ok=false(Unrecognized key: "thinkingLevelMap")Behavior or issue addressed: Microsoft Foundry Entra ID onboarding cannot persist. The Foundry writer puts a model entry carrying
thinkingLevelMapinto the config, but the persisted strict zodModelDefinitionSchemahad no such key, soupdateConfigvalidation fails and atomically rolls the whole write back. Reported error:models.providers.microsoft-foundry.models.0: Unrecognized key: "thinkingLevelMap".Real environment tested: Node v22.22.1, win32 x64 (Windows 10.0.19045).
[email protected](npmlatest) and[email protected](npmbeta).mainat commit4d142b185e(this PR's parent; contained in tagv2026.6.5-beta.2).fix/91011-foundry-thinkinglevelmap-schema(60fb8c6bdc).validateConfigObject(src/config/validation.ts) over the real output ofbuildFoundryAuthResult(extensions/microsoft-foundry/shared.ts). Nothing hand-edited — allokvalues come from the validator.Exact steps or command run after this patch:
Real Foundry writer output (Entra ID, reasoning model) fed to the real persisted validator, for a given checkout root:
Shipped builds were exercised the same way against their built ESM dist (
dist/extensions/microsoft-foundry/shared.js+dist/config/config.js), with a control that removes onlythinkingLevelMap.Evidence after fix (console output):
===== BEFORE (unpatched main 4d142b1) =====
writer-emitted thinkingLevelMap: {"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null,"max":null}
[positive] validateConfigObject(real foundry configPatch).ok = false
issues: [{"path":"models.providers.microsoft-foundry.models.0","message":"Unrecognized key: "thinkingLevelMap""}]
[negative] adaptive-key entry .ok = false
[subset] writer keys = {off,minimal,low,medium,high,xhigh,max} | outOfSet = []
===== AFTER (this PR branch) =====
writer-emitted thinkingLevelMap: {"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null,"max":null}
[positive] validateConfigObject(real foundry configPatch).ok = true
[negative] adaptive-key entry .ok = false
[subset] writer keys = {off,minimal,low,medium,high,xhigh,max} | outOfSet = []
===== SHIPPED 2026.6.1 (npm latest) =====
writer-emitted thinkingLevelMap: {"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null,"max":null}
[with thinkingLevelMap] ok = false | issues = [{"path":"models.providers.microsoft-foundry.models.0","message":"Invalid input"}]
[without thinkingLevelMap] ok = true (control: thinkingLevelMap is the sole cause)
===== SHIPPED 2026.6.5-beta.2 (npm beta) =====
writer-emitted thinkingLevelMap: {"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null,"max":null}
[with thinkingLevelMap] ok = false | issues = [{"path":"models.providers.microsoft-foundry.models.0","message":"Invalid input"}]
[without thinkingLevelMap] ok = true (control: thinkingLevelMap is the sole cause)
Observed result after fix: The real Foundry writer's Entra ID model entry (with the 7-key
thinkingLevelMap) is rejected by the unpatched persisted schema (ok=false, the exactUnrecognized key: "thinkingLevelMap"rollback cause) and rejected identically by the shipped2026.6.1and2026.6.5-beta.2builds (control confirmsthinkingLevelMapis the sole cause). With this patch the same entry validates (ok=true), an out-of-set level key (adaptive) is still rejected (ok=false,.strict()preserved), and the writer's emitted keys are a subset of the allowedModelThinkingLevelset.What was not tested: A full end-to-end live Entra ID / Foundry onboarding run (
openclaw models auth login) whereupdateConfigactually persists to disk and demonstrably does not roll back — that needs a real Azure Foundry endpoint plus Entra (managed identity) credentials, which I don't have.Proof limitations or environment constraints: Because there's no Azure Foundry/Entra environment, I reproduced the bug by colliding the two halves whose mismatch causes the rollback — the real shipped Foundry writer output and the real persisted config validator (the exact pair
updateConfigruns) — rather than driving live onboarding. Shipped builds report a generic"Invalid input"(minified-bundle zod formatting); the control (removing onlythinkingLevelMapflipsoktotrue) plus the unpatched-source run (verbatimUnrecognized key: "thinkingLevelMap") jointly pin the cause. Supplemental: this PR's vitest passes —node scripts/run-vitest.mjs extensions/microsoft-foundry/index.test.ts src/config/config.schema-regressions.test.ts src/commands/models/auth.test.ts(config-regressions 34, auth 37, foundry index 41).Before evidence: See the
BEFORE,SHIPPED 2026.6.1, andSHIPPED 2026.6.5-beta.2blocks above — all produced from unpatched/shipped builds, all rejecting the real Foundry writer output.Generated baseline
docs/.generated/config-baseline.sha256changed because the new (documented)schema key alters the generated config-doc baseline. It was regenerated via
pnpm config:docs:gen— the sanctioned step thatconfig:docs:check's own errormessage instructs — and is not hand-edited;
config:docs:checknow passes.Verification
All three files green (config-regressions 34, auth 37, foundry index 41).
auth.test.tsmocksupdateConfig, so it does not exercise the real rollback,but it is included since the schema underpins that write path.
Not done: no live Microsoft Foundry / Entra ID verification (no environment).
Coverage is the schema↔writer alignment proven by the unit tests above.
Closes #91011