use std::collections::HashMap;
use std::path::Path;
use crate::core::agent_skill_codeploy::{co_deploy_skill_set, log_declared_skills};
use crate::core::manifest::HarnessPlan;
use crate::core::paths::FrameworkPaths;
use crate::core::skill_deployer::DeployStats;
use crate::core::skill_tiers::{
deploy_all_skill_tiers, list_project_custom_stems, list_source_stems,
};
pub(super) fn deploy_session_skills(
fw: &FrameworkPaths,
plan: &HarnessPlan,
project_dir: &Path,
declared_skills: &HashMap<String, Vec<String>>,
roster_errors: &mut Vec<String>,
) -> DeployStats {
match crate::core::skill_staleness::stale_skills(&plan.skill_source, &fw.claude_skills_dir()) {
Ok(stale) if !stale.is_empty() => tracing::warn!(
project_dir = %project_dir.display(),
stale_skills = %stale.join(", "),
"deployed skills were stale relative to bundled assets — refreshing now \
(run `tm doctor` to audit; long-lived worktrees drift until re-provisioned)"
),
Ok(_) => {}
Err(e) => roster_errors.push(format!(
"skill staleness undetermined — the ownership ledger at {} could not be read: {e}",
fw.claude_skills_dir().display()
)),
}
let bundled_stems = list_source_stems(&plan.skill_source).unwrap_or_default();
let user_stems = list_source_stems(&fw.user_skill_source_dir()).unwrap_or_default();
let project_stems = list_project_custom_stems(&fw.claude_skills_dir()).unwrap_or_default();
let co_deploy_skills = co_deploy_skill_set(declared_skills);
log_declared_skills(declared_skills, &project_stems, &user_stems, &bundled_stems);
crate::core::provisioning_stage::emit(
crate::core::provisioning_stage::ProvisioningStage::DeployingSkills,
);
let stats = match deploy_all_skill_tiers(
&plan.skill_source,
&fw.user_skill_source_dir(),
&fw.claude_skills_dir(),
|name| plan.skill_selected(name) || co_deploy_skills.contains(name),
) {
Ok(result) => result.stats,
Err(err) => {
tracing::error!(
project_dir = %project_dir.display(),
"skill deploy FAILED — session will launch WITHOUT the tm/mpm skill \
set: {err}. Identity/output-style provisioning continues regardless."
);
roster_errors.push(format!("skill deploy failed: {err}"));
DeployStats::default()
}
};
crate::core::skill_retire::retire_orphaned_skills(fw, Some(project_dir));
stats
}