Compare commits

...

1 Commits

Author SHA1 Message Date
celia-oai
8d1f0e2a87 changes 2026-02-27 13:02:51 -08:00
11 changed files with 199 additions and 199 deletions

View File

@@ -437,7 +437,6 @@ mod tests {
dependencies: Some(SkillDependencies { tools }),
policy: None,
permission_profile: None,
permissions: None,
path_to_skills_md: PathBuf::from("skill"),
scope: SkillScope::User,
}

View File

@@ -483,7 +483,6 @@ mod tests {
dependencies: None,
policy: None,
permission_profile: None,
permissions: None,
path_to_skills_md: PathBuf::from(path),
scope: codex_protocol::protocol::SkillScope::User,
}

View File

@@ -253,7 +253,6 @@ mod tests {
dependencies: None,
policy: None,
permission_profile: None,
permissions: None,
path_to_skills_md: skill_doc_path,
scope: codex_protocol::protocol::SkillScope::User,
}

View File

@@ -1,5 +1,4 @@
use crate::config::Config;
use crate::config::Permissions;
use crate::config_loader::ConfigLayerStack;
use crate::config_loader::ConfigLayerStackOrdering;
use crate::config_loader::default_project_root_markers;
@@ -12,7 +11,6 @@ use crate::skills::model::SkillLoadOutcome;
use crate::skills::model::SkillMetadata;
use crate::skills::model::SkillPolicy;
use crate::skills::model::SkillToolDependency;
use crate::skills::permissions::compile_permission_profile;
use crate::skills::system::system_cache_root_dir;
use codex_app_server_protocol::ConfigLayerSource;
use codex_protocol::models::PermissionProfile;
@@ -64,7 +62,6 @@ struct LoadedSkillMetadata {
dependencies: Option<SkillDependencies>,
policy: Option<SkillPolicy>,
permission_profile: Option<PermissionProfile>,
permissions: Option<Permissions>,
}
#[derive(Debug, Default, Deserialize)]
@@ -521,7 +518,6 @@ fn parse_skill_file(path: &Path, scope: SkillScope) -> Result<SkillMetadata, Ski
dependencies,
policy,
permission_profile,
permissions,
} = load_skill_metadata(path);
validate_len(&name, MAX_NAME_LEN, "name")?;
@@ -544,7 +540,6 @@ fn parse_skill_file(path: &Path, scope: SkillScope) -> Result<SkillMetadata, Ski
dependencies,
policy,
permission_profile,
permissions,
path_to_skills_md: resolved_path,
scope,
})
@@ -595,14 +590,11 @@ fn load_skill_metadata(skill_path: &Path) -> LoadedSkillMetadata {
policy,
permissions,
} = parsed;
let permission_profile = permissions.clone().filter(|profile| !profile.is_empty());
LoadedSkillMetadata {
interface: resolve_interface(interface, skill_dir),
dependencies: resolve_dependencies(dependencies),
policy: resolve_policy(policy),
permission_profile,
permissions: compile_permission_profile(skill_dir, permissions),
permission_profile: permissions.filter(|profile| !profile.is_empty()),
}
}
@@ -835,9 +827,7 @@ mod tests {
use crate::config::ConfigBuilder;
use crate::config::ConfigOverrides;
use crate::config::ConfigToml;
use crate::config::Constrained;
use crate::config::ProjectConfig;
use crate::config::types::ShellEnvironmentPolicy;
use crate::config_loader::ConfigLayerEntry;
use crate::config_loader::ConfigLayerStack;
use crate::config_loader::ConfigRequirements;
@@ -1066,7 +1056,6 @@ mod tests {
dependencies: None,
policy: None,
permission_profile: None,
permissions: None,
path_to_skills_md: normalized(&skill_path),
scope: SkillScope::User,
}]
@@ -1215,7 +1204,6 @@ mod tests {
}),
policy: None,
permission_profile: None,
permissions: None,
path_to_skills_md: normalized(&skill_path),
scope: SkillScope::User,
}]
@@ -1272,7 +1260,6 @@ interface:
dependencies: None,
policy: None,
permission_profile: None,
permissions: None,
path_to_skills_md: normalized(skill_path.as_path()),
scope: SkillScope::User,
}]
@@ -1392,44 +1379,6 @@ permissions:
macos: None,
})
);
#[cfg(target_os = "macos")]
let macos_seatbelt_profile_extensions =
Some(crate::seatbelt_permissions::MacOsSeatbeltProfileExtensions::default());
#[cfg(not(target_os = "macos"))]
let macos_seatbelt_profile_extensions = None;
assert_eq!(
outcome.skills[0].permissions,
Some(Permissions {
approval_policy: Constrained::allow_any(crate::protocol::AskForApproval::Never),
sandbox_policy: Constrained::allow_any(
crate::protocol::SandboxPolicy::WorkspaceWrite {
writable_roots: vec![
AbsolutePathBuf::try_from(normalized(
skill_dir.join("output").as_path(),
))
.expect("absolute output path")
],
read_only_access: crate::protocol::ReadOnlyAccess::Restricted {
include_platform_defaults: true,
readable_roots: vec![
AbsolutePathBuf::try_from(normalized(
skill_dir.join("data").as_path(),
))
.expect("absolute data path")
],
},
network_access: true,
exclude_tmpdir_env_var: false,
exclude_slash_tmp: false,
}
),
network: None,
allow_login_shell: true,
shell_environment_policy: ShellEnvironmentPolicy::default(),
windows_sandbox_mode: None,
macos_seatbelt_profile_extensions,
})
);
}
#[tokio::test]
@@ -1454,34 +1403,7 @@ permissions: {}
outcome.errors
);
assert_eq!(outcome.skills.len(), 1);
#[cfg(target_os = "macos")]
let expected = Some(Permissions {
approval_policy: Constrained::allow_any(crate::protocol::AskForApproval::Never),
sandbox_policy: Constrained::allow_any(
crate::protocol::SandboxPolicy::new_read_only_policy(),
),
network: None,
allow_login_shell: true,
shell_environment_policy: ShellEnvironmentPolicy::default(),
windows_sandbox_mode: None,
macos_seatbelt_profile_extensions: Some(
crate::seatbelt_permissions::MacOsSeatbeltProfileExtensions::default(),
),
});
#[cfg(not(target_os = "macos"))]
let expected = Some(Permissions {
approval_policy: Constrained::allow_any(crate::protocol::AskForApproval::Never),
sandbox_policy: Constrained::allow_any(
crate::protocol::SandboxPolicy::new_read_only_policy(),
),
network: None,
allow_login_shell: true,
shell_environment_policy: ShellEnvironmentPolicy::default(),
windows_sandbox_mode: None,
macos_seatbelt_profile_extensions: None,
});
assert_eq!(outcome.skills[0].permission_profile, None);
assert_eq!(outcome.skills[0].permissions, expected);
}
#[cfg(target_os = "macos")]
@@ -1513,24 +1435,21 @@ permissions:
outcome.errors
);
assert_eq!(outcome.skills.len(), 1);
let profile = outcome.skills[0]
.permissions
.as_ref()
.expect("permission profile");
assert_eq!(
profile.macos_seatbelt_profile_extensions,
Some(
crate::seatbelt_permissions::MacOsSeatbeltProfileExtensions {
macos_preferences:
crate::seatbelt_permissions::MacOsPreferencesPermission::ReadWrite,
macos_automation:
crate::seatbelt_permissions::MacOsAutomationPermission::BundleIds(vec![
"com.apple.Notes".to_string()
],),
macos_accessibility: true,
macos_calendar: true,
}
)
outcome.skills[0].permission_profile,
Some(PermissionProfile {
macos: Some(codex_protocol::models::MacOsPermissions {
preferences: Some(codex_protocol::models::MacOsPreferencesValue::Mode(
"readwrite".to_string(),
),),
automations: Some(codex_protocol::models::MacOsAutomationValue::BundleIds(
vec!["com.apple.Notes".to_string()],
)),
accessibility: Some(true),
calendar: Some(true),
}),
..Default::default()
})
);
}
@@ -1564,17 +1483,19 @@ permissions:
);
assert_eq!(outcome.skills.len(), 1);
assert_eq!(
outcome.skills[0].permissions,
Some(Permissions {
approval_policy: Constrained::allow_any(crate::protocol::AskForApproval::Never),
sandbox_policy: Constrained::allow_any(
crate::protocol::SandboxPolicy::new_read_only_policy(),
),
network: None,
allow_login_shell: true,
shell_environment_policy: ShellEnvironmentPolicy::default(),
windows_sandbox_mode: None,
macos_seatbelt_profile_extensions: None,
outcome.skills[0].permission_profile,
Some(PermissionProfile {
macos: Some(codex_protocol::models::MacOsPermissions {
preferences: Some(codex_protocol::models::MacOsPreferencesValue::Mode(
"readwrite".to_string(),
)),
automations: Some(codex_protocol::models::MacOsAutomationValue::BundleIds(
vec!["com.apple.Notes".to_string()],
)),
accessibility: Some(true),
calendar: Some(true),
}),
..Default::default()
})
);
}
@@ -1624,7 +1545,6 @@ permissions:
dependencies: None,
policy: None,
permission_profile: None,
permissions: None,
path_to_skills_md: normalized(&skill_path),
scope: SkillScope::User,
}]
@@ -1666,7 +1586,6 @@ permissions:
dependencies: None,
policy: None,
permission_profile: None,
permissions: None,
path_to_skills_md: normalized(&skill_path),
scope: SkillScope::User,
}]
@@ -1721,7 +1640,6 @@ permissions:
dependencies: None,
policy: None,
permission_profile: None,
permissions: None,
path_to_skills_md: normalized(&skill_path),
scope: SkillScope::User,
}]
@@ -1764,7 +1682,6 @@ permissions:
dependencies: None,
policy: None,
permission_profile: None,
permissions: None,
path_to_skills_md: normalized(&skill_path),
scope: SkillScope::User,
}]
@@ -1810,7 +1727,6 @@ permissions:
dependencies: None,
policy: None,
permission_profile: None,
permissions: None,
path_to_skills_md: normalized(&shared_skill_path),
scope: SkillScope::User,
}]
@@ -1872,7 +1788,6 @@ permissions:
dependencies: None,
policy: None,
permission_profile: None,
permissions: None,
path_to_skills_md: normalized(&skill_path),
scope: SkillScope::User,
}]
@@ -1910,7 +1825,6 @@ permissions:
dependencies: None,
policy: None,
permission_profile: None,
permissions: None,
path_to_skills_md: normalized(&shared_skill_path),
scope: SkillScope::Admin,
}]
@@ -1952,7 +1866,6 @@ permissions:
dependencies: None,
policy: None,
permission_profile: None,
permissions: None,
path_to_skills_md: normalized(&linked_skill_path),
scope: SkillScope::Repo,
}]
@@ -2021,7 +1934,6 @@ permissions:
dependencies: None,
policy: None,
permission_profile: None,
permissions: None,
path_to_skills_md: normalized(&within_depth_path),
scope: SkillScope::User,
}]
@@ -2050,7 +1962,6 @@ permissions:
dependencies: None,
policy: None,
permission_profile: None,
permissions: None,
path_to_skills_md: normalized(&skill_path),
scope: SkillScope::User,
}]
@@ -2083,7 +1994,6 @@ permissions:
dependencies: None,
policy: None,
permission_profile: None,
permissions: None,
path_to_skills_md: normalized(&skill_path),
scope: SkillScope::User,
}]
@@ -2197,7 +2107,6 @@ permissions:
dependencies: None,
policy: None,
permission_profile: None,
permissions: None,
path_to_skills_md: normalized(&skill_path),
scope: SkillScope::Repo,
}]
@@ -2234,7 +2143,6 @@ permissions:
dependencies: None,
policy: None,
permission_profile: None,
permissions: None,
path_to_skills_md: normalized(&skill_path),
scope: SkillScope::Repo,
}]
@@ -2289,7 +2197,6 @@ permissions:
dependencies: None,
policy: None,
permission_profile: None,
permissions: None,
path_to_skills_md: normalized(&nested_skill_path),
scope: SkillScope::Repo,
},
@@ -2301,7 +2208,6 @@ permissions:
dependencies: None,
policy: None,
permission_profile: None,
permissions: None,
path_to_skills_md: normalized(&root_skill_path),
scope: SkillScope::Repo,
},
@@ -2342,7 +2248,6 @@ permissions:
dependencies: None,
policy: None,
permission_profile: None,
permissions: None,
path_to_skills_md: normalized(&skill_path),
scope: SkillScope::Repo,
}]
@@ -2381,7 +2286,6 @@ permissions:
dependencies: None,
policy: None,
permission_profile: None,
permissions: None,
path_to_skills_md: normalized(&skill_path),
scope: SkillScope::Repo,
}]
@@ -2424,7 +2328,6 @@ permissions:
dependencies: None,
policy: None,
permission_profile: None,
permissions: None,
path_to_skills_md: normalized(&repo_skill_path),
scope: SkillScope::Repo,
},
@@ -2436,7 +2339,6 @@ permissions:
dependencies: None,
policy: None,
permission_profile: None,
permissions: None,
path_to_skills_md: normalized(&user_skill_path),
scope: SkillScope::User,
},
@@ -2502,7 +2404,6 @@ permissions:
dependencies: None,
policy: None,
permission_profile: None,
permissions: None,
path_to_skills_md: first_path,
scope: SkillScope::Repo,
},
@@ -2514,7 +2415,6 @@ permissions:
dependencies: None,
policy: None,
permission_profile: None,
permissions: None,
path_to_skills_md: second_path,
scope: SkillScope::Repo,
},
@@ -2587,7 +2487,6 @@ permissions:
dependencies: None,
policy: None,
permission_profile: None,
permissions: None,
path_to_skills_md: normalized(&skill_path),
scope: SkillScope::Repo,
}]
@@ -2647,7 +2546,6 @@ permissions:
dependencies: None,
policy: None,
permission_profile: None,
permissions: None,
path_to_skills_md: normalized(&skill_path),
scope: SkillScope::System,
}]

View File

@@ -3,7 +3,6 @@ use std::collections::HashSet;
use std::path::PathBuf;
use std::sync::Arc;
use crate::config::Permissions;
use codex_protocol::models::PermissionProfile;
use codex_protocol::protocol::SkillScope;
@@ -16,8 +15,6 @@ pub struct SkillMetadata {
pub dependencies: Option<SkillDependencies>,
pub policy: Option<SkillPolicy>,
pub permission_profile: Option<PermissionProfile>,
// This is an experimental field.
pub permissions: Option<Permissions>,
/// Path to the SKILLS.md file that declares this skill.
pub path_to_skills_md: PathBuf,
pub scope: SkillScope,

View File

@@ -1,5 +1,4 @@
use std::collections::HashSet;
use std::path::Path;
#[cfg(target_os = "macos")]
use codex_protocol::models::MacOsAutomationValue;
@@ -20,7 +19,6 @@ use crate::protocol::ReadOnlyAccess;
use crate::protocol::SandboxPolicy;
pub(crate) fn compile_permission_profile(
_skill_dir: &Path,
permissions: Option<PermissionProfile>,
) -> Option<Permissions> {
let PermissionProfile {
@@ -225,21 +223,18 @@ mod tests {
let read_dir = skill_dir.join("data");
fs::create_dir_all(&read_dir).expect("read dir");
let profile = compile_permission_profile(
&skill_dir,
Some(PermissionProfile {
network: Some(true),
file_system: Some(FileSystemPermissions {
read: Some(vec![
absolute_path(&skill_dir.join("data")),
absolute_path(&skill_dir.join("data")),
absolute_path(&skill_dir.join("scripts/../data")),
]),
write: Some(vec![absolute_path(&skill_dir.join("output"))]),
}),
..Default::default()
let profile = compile_permission_profile(Some(PermissionProfile {
network: Some(true),
file_system: Some(FileSystemPermissions {
read: Some(vec![
absolute_path(&skill_dir.join("data")),
absolute_path(&skill_dir.join("data")),
absolute_path(&skill_dir.join("scripts/../data")),
]),
write: Some(vec![absolute_path(&skill_dir.join("output"))]),
}),
)
..Default::default()
}))
.expect("profile");
assert_eq!(
@@ -284,7 +279,7 @@ mod tests {
let skill_dir = tempdir.path().join("skill");
fs::create_dir_all(&skill_dir).expect("skill dir");
let profile = compile_permission_profile(&skill_dir, None);
let profile = compile_permission_profile(None);
assert_eq!(profile, None);
}
@@ -295,13 +290,10 @@ mod tests {
let skill_dir = tempdir.path().join("skill");
fs::create_dir_all(&skill_dir).expect("skill dir");
let profile = compile_permission_profile(
&skill_dir,
Some(PermissionProfile {
network: Some(true),
..Default::default()
}),
)
let profile = compile_permission_profile(Some(PermissionProfile {
network: Some(true),
..Default::default()
}))
.expect("profile");
assert_eq!(
@@ -330,17 +322,14 @@ mod tests {
let read_dir = skill_dir.join("data");
fs::create_dir_all(&read_dir).expect("read dir");
let profile = compile_permission_profile(
&skill_dir,
Some(PermissionProfile {
network: Some(true),
file_system: Some(FileSystemPermissions {
read: Some(vec![absolute_path(&skill_dir.join("data"))]),
write: Some(Vec::new()),
}),
..Default::default()
let profile = compile_permission_profile(Some(PermissionProfile {
network: Some(true),
file_system: Some(FileSystemPermissions {
read: Some(vec![absolute_path(&skill_dir.join("data"))]),
write: Some(Vec::new()),
}),
)
..Default::default()
}))
.expect("profile");
assert_eq!(
@@ -379,20 +368,17 @@ mod tests {
let skill_dir = tempdir.path().join("skill");
fs::create_dir_all(&skill_dir).expect("skill dir");
let profile = compile_permission_profile(
&skill_dir,
Some(PermissionProfile {
macos: Some(MacOsPermissions {
preferences: Some(MacOsPreferencesValue::Mode("readwrite".to_string())),
automations: Some(MacOsAutomationValue::BundleIds(vec![
"com.apple.Notes".to_string(),
])),
accessibility: Some(true),
calendar: Some(true),
}),
..Default::default()
let profile = compile_permission_profile(Some(PermissionProfile {
macos: Some(MacOsPermissions {
preferences: Some(MacOsPreferencesValue::Mode("readwrite".to_string())),
automations: Some(MacOsAutomationValue::BundleIds(vec![
"com.apple.Notes".to_string(),
])),
accessibility: Some(true),
calendar: Some(true),
}),
)
..Default::default()
}))
.expect("profile");
assert_eq!(
@@ -419,8 +405,8 @@ mod tests {
let skill_dir = tempdir.path().join("skill");
fs::create_dir_all(&skill_dir).expect("skill dir");
let profile = compile_permission_profile(&skill_dir, Some(PermissionProfile::default()))
.expect("profile");
let profile =
compile_permission_profile(Some(PermissionProfile::default())).expect("profile");
assert_eq!(
profile.macos_seatbelt_profile_extensions,

View File

@@ -9,6 +9,7 @@ use crate::features::Feature;
use crate::sandboxing::SandboxPermissions;
use crate::shell::ShellType;
use crate::skills::SkillMetadata;
use crate::skills::permissions::compile_permission_profile;
use crate::tools::runtimes::ExecveSessionApproval;
use crate::tools::runtimes::build_command_spec;
use crate::tools::sandboxing::SandboxAttempt;
@@ -225,9 +226,7 @@ impl CoreShellActionProvider {
}
fn skill_escalation_execution(skill: &SkillMetadata) -> EscalationExecution {
skill
.permissions
.as_ref()
compile_permission_profile(skill.permission_profile.clone())
.map(|permissions| {
EscalationExecution::Permissions(EscalationPermissions::Permissions(
EscalatedPermissions {
@@ -238,13 +237,6 @@ impl CoreShellActionProvider {
},
))
})
.or_else(|| {
skill
.permission_profile
.clone()
.map(EscalationPermissions::PermissionProfile)
.map(EscalationExecution::Permissions)
})
.unwrap_or(EscalationExecution::TurnDefault)
}

View File

@@ -514,6 +514,140 @@ async fn shell_zsh_fork_skill_without_permissions_inherits_turn_sandbox() -> Res
Ok(())
}
/// Empty skill permissions should behave like no skill override and inherit the
/// turn sandbox instead of forcing an explicit read-only skill sandbox.
#[cfg(unix)]
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn shell_zsh_fork_skill_with_empty_permissions_inherits_turn_sandbox() -> Result<()> {
skip_if_no_network!(Ok(()));
let Some(runtime) = zsh_fork_runtime("zsh-fork empty skill permissions test")? else {
return Ok(());
};
let outside_dir = tempfile::tempdir_in(std::env::current_dir()?)?;
let outside_path = outside_dir
.path()
.join("zsh-fork-skill-empty-permissions.txt");
let outside_path_quoted = shlex::try_join([outside_path.to_string_lossy().as_ref()])?;
let script_contents = format!(
"#!/bin/sh\nprintf '%s' allowed > {outside_path_quoted}\ncat {outside_path_quoted}\n"
);
let outside_path_for_hook = outside_path.clone();
let script_contents_for_hook = script_contents.clone();
let server = start_mock_server().await;
let test = build_zsh_fork_test(
&server,
runtime,
AskForApproval::OnRequest,
SandboxPolicy::DangerFullAccess,
move |home| {
let _ = fs::remove_file(&outside_path_for_hook);
write_skill_with_shell_script_contents(
home,
"mbolin-test-skill",
"sandboxed.sh",
&script_contents_for_hook,
)
.unwrap();
write_skill_metadata(home, "mbolin-test-skill", "permissions: {}\n").unwrap();
},
)
.await?;
let (script_path_str, command) = skill_script_command(&test, "sandboxed.sh")?;
let first_call_id = "zsh-fork-skill-empty-permissions-1";
let first_arguments = shell_command_arguments(&command)?;
let first_mocks = mount_function_call_agent_response(
&server,
first_call_id,
&first_arguments,
"shell_command",
)
.await;
submit_turn_with_policies(
&test,
"use $mbolin-test-skill",
AskForApproval::OnRequest,
SandboxPolicy::DangerFullAccess,
)
.await?;
let approval = wait_for_exec_approval_request(&test)
.await
.expect("expected exec approval request before completion");
assert_eq!(approval.call_id, first_call_id);
assert_eq!(approval.command, vec![script_path_str.clone()]);
assert_eq!(approval.additional_permissions, None);
test.codex
.submit(Op::ExecApproval {
id: approval.effective_approval_id(),
turn_id: None,
decision: ReviewDecision::ApprovedForSession,
})
.await?;
wait_for_turn_complete(&test).await;
let first_output = first_mocks
.completion
.single_request()
.function_call_output(first_call_id)["output"]
.as_str()
.unwrap_or_default()
.to_string();
assert!(
first_output.contains("allowed"),
"expected empty skill permissions to inherit full-access turn sandbox, got output: {first_output:?}"
);
assert_eq!(fs::read_to_string(&outside_path)?, "allowed");
let second_call_id = "zsh-fork-skill-empty-permissions-2";
let second_arguments = shell_command_arguments(&command)?;
let second_mocks = mount_function_call_agent_response(
&server,
second_call_id,
&second_arguments,
"shell_command",
)
.await;
let _ = fs::remove_file(&outside_path);
submit_turn_with_policies(
&test,
"use $mbolin-test-skill",
AskForApproval::OnRequest,
SandboxPolicy::DangerFullAccess,
)
.await?;
let cached_approval = wait_for_exec_approval_request(&test).await;
assert!(
cached_approval.is_none(),
"expected second run to reuse the cached session approval"
);
let second_output = second_mocks
.completion
.single_request()
.function_call_output(second_call_id)["output"]
.as_str()
.unwrap_or_default()
.to_string();
assert!(
second_output.contains("allowed"),
"expected cached empty-permissions skill approval to inherit the turn sandbox, got output: {second_output:?}"
);
assert_eq!(fs::read_to_string(&outside_path)?, "allowed");
Ok(())
}
/// The validation to focus on is: writes to the skill-approved folder succeed,
/// and writes to an unrelated folder fail, both before and after cached approval.
#[cfg(unix)]

View File

@@ -1522,7 +1522,6 @@ mod tests {
dependencies: None,
policy: None,
permission_profile: None,
permissions: None,
path_to_skills_md: PathBuf::from("test-skill"),
scope: SkillScope::User,
}]),

View File

@@ -191,7 +191,6 @@ fn protocol_skill_to_core(skill: &ProtocolSkillMetadata) -> SkillMetadata {
}),
policy: None,
permission_profile: None,
permissions: None,
path_to_skills_md: skill.path.clone(),
scope: skill.scope,
}

View File

@@ -936,7 +936,6 @@ async fn submission_prefers_selected_duplicate_skill_path() {
dependencies: None,
policy: None,
permission_profile: None,
permissions: None,
path_to_skills_md: repo_skill_path,
scope: SkillScope::Repo,
},
@@ -948,7 +947,6 @@ async fn submission_prefers_selected_duplicate_skill_path() {
dependencies: None,
policy: None,
permission_profile: None,
permissions: None,
path_to_skills_md: user_skill_path.clone(),
scope: SkillScope::User,
},