windows: skills test fixtures name USERPROFILE, and the win32 quoted form

`os.homedir()` reads USERPROFILE on Windows, so a fixture home that named only
HOME sent the global installs into the runner's real profile. The Windows hook
command carries the JSON-quoted path, so a host path's backslashes arrive
escaped; derive the expectation instead of pinning the POSIX spelling.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vau2X53xGTjjTCXWMVBoNY
This commit is contained in:
Paul Bakaus
2026-09-03 14:28:51 -07:00
co-authored by Claude Fable 5.1
parent 85087c20c4
commit 476d43d95f
2 changed files with 11 additions and 2 deletions
+7 -1
View File
@@ -134,7 +134,10 @@ fn run_cli(args: &[&str], cwd: &str, env: &HashMap<String, String>) -> Run {
fn base_env(home: &str, tmp: &str, bundle: &str) -> HashMap<String, String> {
let mut env = HashMap::new();
// `os.homedir()` reads USERPROFILE on Windows and HOME on posix, so a
// fixture home has to name both or the verb writes into the real profile.
env.insert("HOME".to_string(), home.to_string());
env.insert("USERPROFILE".to_string(), home.to_string());
env.insert("TMPDIR".to_string(), tmp.to_string());
env.insert("TEMP".to_string(), tmp.to_string());
env.insert("IMPECCABLE_BUNDLE_PATH".to_string(), bundle.to_string());
@@ -348,7 +351,10 @@ fn claude_project_and_user_scopes_use_claude_agents_dir() {
let bundle_dir = create_fake_universal_bundle(&root, &[".claude"]);
write(&format!("{home}/.claude/agents/impeccable-finish-reviewer.md"), "stale copy\n");
let env: HashMap<String, String> = HashMap::from([("HOME".to_string(), home.clone())]);
let env: HashMap<String, String> = HashMap::from([
("HOME".to_string(), home.clone()),
("USERPROFILE".to_string(), home.clone()),
]);
let sys = sys_for(&tmp, &env);
let project_results =
bundle::copy_provider_agents(&sys, &bundle_dir, &tmp, &[".claude"], Some(Scope::Project)).unwrap();
+4 -1
View File
@@ -99,7 +99,10 @@ fn windows_form_keeps_double_quoted_absolute_path() {
let out = rewrite_hook_commands_for_platform(&claude_bundle_manifest(), ".claude", root, true, true);
for c in commands(&out) {
let p = skill_launcher(root, ".claude");
assert_eq!(c, format!("command=[ ! -f \"{p}\" ] || \"{p}\" hook"));
// The Windows form is the JSON-quoted path, so a host path's
// backslashes arrive escaped inside the command string.
let q = serde_json::to_string(&p).unwrap();
assert_eq!(c, format!("command=[ ! -f {q} ] || {q} hook"));
assert!(!c.contains(&format!("'{p}")));
}
}