use super::orient::{QuestionKind, SituPicture};
use anyhow::Result;
use atlas::{
invocation::{SkillContext, SkillInput},
SkillRegistry,
};
use serde_json::json;
pub struct DecisionPacket {
pub invocations: Vec<(String, SkillInput)>,
pub rationale: String,
}
pub fn select_skills(
situ: &SituPicture,
registry: &SkillRegistry,
ctx: &SkillContext,
) -> Result<DecisionPacket> {
let mut invocations: Vec<(String, SkillInput)> = Vec::new();
let mut rationale_parts: Vec<String> = Vec::new();
for q in &situ.open_questions {
match q.kind {
QuestionKind::InvestigateErrors => {
if registry.get("scout").is_some() {
invocations.push((
"scout".into(),
SkillInput::new(json!({
"command": "echo '[investigate errors — no command set]'",
"working_dir": ctx.working_dir,
"dry_run": true
})),
));
rationale_parts.push("scout(dry_run) for error investigation".into());
}
}
QuestionKind::RecallRelatedFacts => {
if registry.get("archivist").is_some() {
invocations.push((
"archivist".into(),
SkillInput::new(json!({
"query": q.detail,
"top_k": 5,
"min_confidence": 0.3
})),
));
rationale_parts.push(format!("archivist(\"{}\")", q.detail));
}
}
QuestionKind::DescribeProjectLayout => {
if registry.get("cartograph").is_some() {
invocations.push((
"cartograph".into(),
SkillInput::new(json!({
"root": ctx.working_dir,
"depth": 2,
"output_format": "compact"
})),
));
rationale_parts.push("cartograph(depth=2)".into());
}
}
}
}
let rationale = if rationale_parts.is_empty() {
"no open questions".into()
} else {
rationale_parts.join(", ")
};
Ok(DecisionPacket {
invocations,
rationale,
})
}