Client or integration
OpenCodex Dashboard / management API
Area
Configuration persistence / provider and model management
Summary
The rebase-on-save landed for #1273 cannot distinguish two situations that look
identical from the merge's point of view:
- a key is present on disk and absent in the live config because this writer**
**deleted it;
- a key is present on disk and absent in the live config because this writer**
**never held it — another writer added it to the file after our config was
loaded.
Absence alone does not say which. Both readings are defensible and each breaks
the other's scenario:
| Scenario |
Deletion reading |
Ignorance reading |
live deletes a field, disk still has it (PUT /api/grok/selection with []) |
correct: field is cleared |
wrong: field comes back |
| another writer adds a key after we loaded, we save something unrelated |
wrong: key is dropped |
correct: key survives |
Two independent fixes for #1462 landed on opposite sides of this. d6e4545b2 on
dev restricts the rebase to keys the baseline knew about, which fixes the Grok
case; the contributor's later head d51bd2856 arms provenance on every config
load, which preserves disk-added keys but leaves the Grok case failing (9 pass /
1 fail on tests/grok-management-api.test.ts). Reimplementing the first rule
inside the second design breaks its own regression, an independently loaded config rebases a non-server save.
Both scenarios currently pass on dev, so this is not an active user-facing
defect — it is an unresolved rule that the next change in this area will hit.
Reproduction
Deletion case, against d51bd2856:
const config = loadConfig(); config.grokExcludedModels = ["a"]; saveConfig(config);
PUT /api/grok/selection with {"excluded": []} on a server whose live
config was loaded before step 1.
- Expected
grokExcludedModels to be gone; it is still ["a"].
Ignorance case, against a rebase restricted to baseline-known keys:
const stale = loadConfig(); then, from a second loadConfig(), set
disabledModels and saveConfig().
stale.contextCapValue = 240_000; saveConfig(stale);
- Expected
disabledModels to survive; it is dropped.
Version
2.12.x (dev at 62be62222)
Operating system
macOS 15 (arm64); not platform-specific
Provider and model
Not provider-specific
Logs or error output
deletion case: Expected: undefined Received: [ "a" ]
ignorance case: Expected: ["disk/model"] Received: undefined
Anything else
Two directions look viable, and the choice belongs to whoever owns this
subsystem rather than to whichever patch merges last:
- Record deletion intent where the deletion happens. There are eight or more
delete config.<field> sites across the management routes; each would mark
the removal so the merge can tell intent from absence.
- Refresh the baseline on every cooperating write rather than arming it once
at server startup, so a key added by another writer is no longer invisible to
this instance.
Context and the full two-scenario analysis:
devlog/_plan/260811_bug_pair_landing/080_wp10_publication_plan.md.
Client or integration
OpenCodex Dashboard / management API
Area
Configuration persistence / provider and model management
Summary
The rebase-on-save landed for #1273 cannot distinguish two situations that look
identical from the merge's point of view:
**deleted it;
**never held it — another writer added it to the file after our config was
loaded.
Absence alone does not say which. Both readings are defensible and each breaks
the other's scenario:
PUT /api/grok/selectionwith[])Two independent fixes for #1462 landed on opposite sides of this.
d6e4545b2ondevrestricts the rebase to keys the baseline knew about, which fixes the Grokcase; the contributor's later head
d51bd2856arms provenance on every configload, which preserves disk-added keys but leaves the Grok case failing (9 pass /
1 fail on
tests/grok-management-api.test.ts). Reimplementing the first ruleinside the second design breaks its own regression,
an independently loaded config rebases a non-server save.Both scenarios currently pass on
dev, so this is not an active user-facingdefect — it is an unresolved rule that the next change in this area will hit.
Reproduction
Deletion case, against
d51bd2856:const config = loadConfig(); config.grokExcludedModels = ["a"]; saveConfig(config);PUT /api/grok/selectionwith{"excluded": []}on a server whose liveconfig was loaded before step 1.
grokExcludedModelsto be gone; it is still["a"].Ignorance case, against a rebase restricted to baseline-known keys:
const stale = loadConfig();then, from a secondloadConfig(), setdisabledModelsandsaveConfig().stale.contextCapValue = 240_000; saveConfig(stale);disabledModelsto survive; it is dropped.Version
2.12.x (
devat62be62222)Operating system
macOS 15 (arm64); not platform-specific
Provider and model
Not provider-specific
Logs or error output
Anything else
Two directions look viable, and the choice belongs to whoever owns this
subsystem rather than to whichever patch merges last:
delete config.<field>sites across the management routes; each would markthe removal so the merge can tell intent from absence.
at server startup, so a key added by another writer is no longer invisible to
this instance.
Context and the full two-scenario analysis:
devlog/_plan/260811_bug_pair_landing/080_wp10_publication_plan.md.