Resolve config paths during lenient projection

This commit is contained in:
Ahmed Ibrahim
2026-05-07 00:20:39 +03:00
parent a81898ca68
commit 646f9baf7e
2 changed files with 41 additions and 2 deletions

View File

@@ -15,6 +15,7 @@ use crate::diagnostics::ConfigError;
use crate::diagnostics::config_error_from_toml;
use crate::diagnostics::first_layer_config_error_from_entries as typed_first_layer_config_error_from_entries;
use crate::diagnostics::io_error_from_config_error;
use crate::lenient::deserialize_with_enum_warnings;
use crate::merge::merge_toml_values;
use crate::overrides::build_cli_overrides_layer;
use crate::project_root_markers::default_project_root_markers;
@@ -870,9 +871,14 @@ pub fn resolve_relative_paths_in_config_toml(
base_dir: &Path,
) -> io::Result<TomlValue> {
// Use the serialize/deserialize round-trip to convert the
// `toml::Value` into a `ConfigToml` with `AbsolutePath
// `toml::Value` into a `ConfigToml` with `AbsolutePathBuf` fields resolved
// by the guard. Invalid enum values are ignored only for this typed
// projection; copy_shape_from_original preserves them in the raw layer so
// the final config load can still surface the startup warning.
let _guard = AbsolutePathBufGuard::new(base_dir);
let Ok(resolved) = value_from_config_toml.clone().try_into::<ConfigToml>() else {
let Ok((_sanitized, resolved, _enum_warnings)) =
deserialize_with_enum_warnings::<ConfigToml>(value_from_config_toml.clone())
else {
return Ok(value_from_config_toml);
};
drop(_guard);

View File

@@ -175,6 +175,39 @@ theme = "loudly"
Ok(())
}
#[tokio::test]
async fn invalid_enum_values_do_not_poison_relative_path_resolution() -> anyhow::Result<()> {
let tmp = tempdir().expect("tempdir");
std::fs::write(
tmp.path().join(CONFIG_TOML_FILE),
r#"
model_instructions_file = "instructions.md"
sandbox_mode = "make-it-so"
"#,
)
.expect("write config");
std::fs::write(tmp.path().join("instructions.md"), "resolved instructions")
.expect("write instructions");
let config = ConfigBuilder::default()
.codex_home(tmp.path().to_path_buf())
.harness_overrides(ConfigOverrides {
cwd: Some(tmp.path().to_path_buf()),
..Default::default()
})
.build()
.await?;
assert_eq!(
(config.base_instructions.as_deref(), config.startup_warnings,),
(
Some("resolved instructions"),
vec!["Ignoring invalid config value at sandbox_mode: \"make-it-so\"".to_string()],
)
);
Ok(())
}
#[tokio::test]
async fn invalid_untagged_notification_value_does_not_delete_tui_table() -> anyhow::Result<()> {
let tmp = tempdir().expect("tempdir");