use crate::cli::memory::open_or_create_handle;
use crate::cli::output::OutputConfig;
use crate::cli::GitCommands;
use anyhow::Result;
use trusty_memory_core::git::GitExtractor;
use trusty_memory_core::RoomType;
pub async fn handle(cmd: GitCommands, palace: &str, out: &OutputConfig) -> Result<()> {
match cmd {
GitCommands::Ingest {
path,
since: _,
limit,
dry_run,
} => {
let repo_path = match path {
Some(p) => p,
None => std::env::current_dir()?,
};
out.print_header(palace, "git/ingest");
let extractor = GitExtractor::new(repo_path)?;
let facts = extractor.extract(None, limit)?;
println!("Extracted {} facts from git history", facts.len());
if dry_run {
for fact in &facts {
let preview_len = fact.narrative.len().min(80);
let preview = &fact.narrative[..preview_len];
println!(" [{:.2}] would store {preview}", fact.importance);
}
out.print_success("dry-run complete");
return Ok(());
}
let handle = open_or_create_handle(palace).await?;
let mut stored = 0usize;
for fact in &facts {
let tags = fact_tags(fact);
let room = fact
.entities
.room_types
.first()
.cloned()
.unwrap_or(RoomType::General);
handle
.remember(fact.narrative.clone(), room, tags, fact.importance)
.await?;
stored += 1;
}
out.print_success(&format!("ingested {stored} commit(s)"));
}
GitCommands::Watch { path: _, interval } => {
println!("Watching for new commits every {interval}s (full impl in #12 wiring)");
}
}
Ok(())
}
fn fact_tags(fact: &trusty_memory_core::git::GitFact) -> Vec<String> {
let mut tags = vec![
format!("git:{}", &fact.sha[..fact.sha.len().min(8)]),
format!("author:{}", fact.author),
];
if !fact.conventional.commit_type.is_empty() {
tags.push(format!("type:{}", fact.conventional.commit_type));
}
if let Some(scope) = &fact.conventional.scope {
tags.push(format!("scope:{scope}"));
}
for issue in &fact.entities.issue_refs {
tags.push(format!("issue:{issue}"));
}
tags
}