cvars: a capture can boot on a player's setting, not only the defaults

A capture reads no `config.toml` — that hermetic boot is exactly what keeps an
A/B exact — so there was no way to ask offline whether a report still reproduces
at the player's own numbers. `WOW_CVAR=<name>=<value>[;…]` applies after the file
and the preset, so it wins; unset it moves nothing and every capture keeps
booting on the registered defaults. An unknown name or a malformed step is
reported and skipped, because a typo in a measurement should not take the run
down with it.

Written for grom's report that interiors go "really grey and flat" when it snows
with Interior Darkness turned down. That is `interiorGain`, and reproducing it
needed his 1.25 in a capture that boots at 0.5.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgstFWtn1RxEJ5kVrpgYwn
This commit is contained in:
2026-10-19 13:16:02 -06:00
co-authored by Claude Opus 5
parent 948373f7a4
commit 9d16c200a6
+79
View File
@@ -2340,6 +2340,9 @@ fn load_config(world: &mut World) {
if seeds_graphics_preset(&stored_kind) {
cvars.seed_graphics_preset();
}
// Last, so it beats the file and the preset both: the one way to reproduce a player's
// setting in a capture, which is otherwise hermetic and boots on the registered defaults.
apply_env_overrides(&mut cvars);
cvars.take_events()
};
for event in events {
@@ -2347,6 +2350,31 @@ fn load_config(world: &mut World) {
}
}
/// `WOW_CVAR=<name>=<value>[;<name>=<value>…]`, applied after the file and the preset so it wins.
///
/// A capture reads no `config.toml` — that is what keeps an A/B exact — so without this there is
/// no way to ask "does it still look wrong at *his* settings?" offline. Unset, it does nothing,
/// and every capture keeps booting on the registered defaults.
fn apply_env_overrides(cvars: &mut Cvars) {
let Ok(script) = std::env::var("WOW_CVAR") else {
return;
};
for step in script.split(';').map(str::trim).filter(|s| !s.is_empty()) {
match step.split_once('=') {
Some((name, value)) => {
let (name, value) = (name.trim(), value.trim());
match cvars.set(name, value) {
SetOutcome::Changed | SetOutcome::Unchanged | SetOutcome::Staged => {
info!("cvar: WOW_CVAR set {name} = {value}");
}
outcome => warn!("cvar: WOW_CVAR {name} = {value} refused ({outcome:?})"),
}
}
None => warn!("cvar: WOW_CVAR step {step:?} is not <name>=<value>"),
}
}
}
/// MONKEY (presets): which [`StoredConfig`] arm a boot took, kept past the table's move.
enum StoredKind {
Absent,
@@ -3037,6 +3065,57 @@ mod tests {
Cvars::default()
}
/// `WOW_CVAR` is how a capture reproduces a player's setting. A capture reads no
/// `config.toml` — that hermetic boot is what keeps an A/B exact — so without this there is no
/// way to ask offline whether a report still reproduces at *their* numbers. Unset it must do
/// nothing at all, or every capture ever taken drifts off the registered defaults.
#[test]
fn the_env_override_beats_the_defaults_and_is_inert_when_unset() {
let _l = crate::local_state::test_env::ENV_LOCK
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
let mut untouched = fresh_registry();
{
let _c = crate::local_state::test_env::EnvGuard::unset("WOW_CVAR");
apply_env_overrides(&mut untouched);
}
assert_eq!(
untouched.take_events().len(),
0,
"unset, it must not move a single row"
);
let mut cvars = fresh_registry();
let before = cvars.get("interiorGain").map(str::to_string);
assert_eq!(before.as_deref(), Some("0.5"), "the registered default");
{
let _c = crate::local_state::test_env::EnvGuard::set(
"WOW_CVAR",
"interiorGain=1.25; nightGain=0.9",
);
apply_env_overrides(&mut cvars);
}
assert_eq!(cvars.get("interiorGain"), Some("1.25"));
assert_eq!(cvars.get("nightGain"), Some("0.9"));
// An unknown name and a malformed step are reported, not fatal: a typo in a measurement
// must not take the run down with it.
let mut noisy = fresh_registry();
{
let _c = crate::local_state::test_env::EnvGuard::set(
"WOW_CVAR",
"noSuchCvar=1;interiorGain",
);
apply_env_overrides(&mut noisy);
}
assert_eq!(
noisy.get("interiorGain"),
Some("0.5"),
"a malformed step changes nothing"
);
}
/// **The round trip, for every rung**: apply a preset, derive, and get that preset's own name
/// back. This is the property the whole ladder rests on — without it the dropdown would show
/// `Custom` the instant after the player picked something, which is the exact failure the