Emit implicit skill usage for support reads

This commit is contained in:
alexsong-oai
2026-06-23 14:38:28 -07:00
parent 9a79536e6b
commit f9252814d7
2 changed files with 68 additions and 2 deletions
+10 -2
View File
@@ -327,8 +327,16 @@ fn finalize_skill_outcome(
disabled_paths: HashSet<AbsolutePathBuf>,
) -> SkillLoadOutcome {
outcome.disabled_paths = disabled_paths;
let (by_scripts_dir, by_doc_path) =
build_implicit_skill_path_indexes(outcome.allowed_skills_for_implicit_invocation());
// Usage-event detection should see any enabled skill file/script read, even when the
// skill is not model-routable through implicit invocation.
let (by_scripts_dir, by_doc_path) = build_implicit_skill_path_indexes(
outcome
.skills
.iter()
.filter(|skill| outcome.is_skill_enabled(skill))
.cloned()
.collect(),
);
outcome.implicit_skills_by_scripts_dir = Arc::new(by_scripts_dir);
outcome.implicit_skills_by_doc_path = Arc::new(by_doc_path);
outcome
+58
View File
@@ -402,6 +402,64 @@ async fn skills_for_config_disables_plugin_skills_by_name() {
);
}
#[tokio::test]
async fn skills_for_config_indexes_usage_detection_for_non_implicit_skills() {
let codex_home = tempfile::tempdir().expect("tempdir");
let cwd = tempfile::tempdir().expect("tempdir");
let skill_dir = codex_home.path().join("skills/preflight");
let agents_dir = skill_dir.join("agents");
let scripts_dir = skill_dir.join("scripts");
fs::create_dir_all(&agents_dir).expect("create skill metadata dir");
fs::create_dir_all(&scripts_dir).expect("create scripts dir");
let skill_path = skill_dir.join("SKILL.md");
let script_path = scripts_dir.join("preflight.py");
fs::write(
&skill_path,
"---\nname: preflight-skill\ndescription: support/preflight skill\n---\n\n# Body\n",
)
.expect("write skill");
fs::write(
agents_dir.join("openai.yaml"),
"policy:\n allow_implicit_invocation: false\n",
)
.expect("write skill metadata");
fs::write(&script_path, "print('ok')\n").expect("write script");
let config_layer_stack = config_stack(&codex_home, "");
let skills_service = SkillsService::new(
codex_home.path().abs(),
/*bundled_skills_enabled*/ true,
);
let outcome =
skills_for_config_with_stack(&skills_service, &cwd, &config_layer_stack, &[]).await;
assert!(
!outcome
.allowed_skills_for_implicit_invocation()
.iter()
.any(|skill| skill.name == "preflight-skill")
);
let workdir = cwd.path().abs();
let detected_names = [
format!("sed -n '1,20p' {}", skill_path.display()),
format!("python3 {}", script_path.display()),
]
.into_iter()
.map(|command| {
crate::detect_implicit_skill_invocation_for_command(&outcome, &command, &workdir)
.map(|skill| skill.name)
})
.collect::<Vec<_>>();
assert_eq!(
detected_names,
vec![
Some("preflight-skill".to_string()),
Some("preflight-skill".to_string())
]
);
}
#[tokio::test]
async fn skills_for_cwd_loads_repo_and_user_roots_with_local_fs() {
let codex_home = tempfile::tempdir().expect("tempdir");