mod scan;
mod types;
pub use scan::scan_project;
pub use types::{
is_kg_empty_for_subject, result_to_json, BootstrapResult, BootstrapTriple, ScannedFile,
KG_EMPTY_HINT,
};
use anyhow::{Context, Result};
use std::path::{Path, PathBuf};
use trusty_common::memory_core::store::kg::Triple;
use crate::AppState;
pub async fn bootstrap_palace(
state: &AppState,
palace_id: &str,
project_path: Option<&Path>,
) -> Result<BootstrapResult> {
let handle = state
.registry
.open_palace(
&state.data_root,
&trusty_common::memory_core::palace::PalaceId::new(palace_id),
)
.with_context(|| format!("open palace {palace_id}"))?;
let scan_root: PathBuf = match project_path {
Some(p) => p.to_path_buf(),
None => handle
.data_dir
.clone()
.unwrap_or_else(|| state.data_root.join(palace_id)),
};
let palace_id_owned = palace_id.to_string();
let (triples, scanned_files, project_subject) =
tokio::task::spawn_blocking(move || scan_project(&scan_root, &palace_id_owned))
.await
.context("join scan_project")??;
let now = chrono::Utc::now();
let mut all = triples;
all.push(BootstrapTriple {
subject: project_subject.clone(),
predicate: "bootstrapped_at".to_string(),
object: now.to_rfc3339(),
provenance: "bootstrap:temporal".to_string(),
});
let existing = handle
.kg
.query_active(&project_subject)
.await
.context("kg.query_active for created_at check")?;
if !existing.iter().any(|t| t.predicate == "created_at") {
all.push(BootstrapTriple {
subject: project_subject.clone(),
predicate: "created_at".to_string(),
object: now.to_rfc3339(),
provenance: "bootstrap:temporal".to_string(),
});
}
let mut asserted = 0usize;
for bt in &all {
let triple = Triple {
subject: bt.subject.clone(),
predicate: bt.predicate.clone(),
object: bt.object.clone(),
valid_from: now,
valid_to: None,
confidence: 1.0,
provenance: Some(bt.provenance.clone()),
};
handle
.kg
.assert(triple)
.await
.with_context(|| format!("kg.assert {} {}", bt.subject, bt.predicate))?;
asserted += 1;
}
Ok(BootstrapResult {
palace: palace_id.to_string(),
project_subject,
triples_asserted: asserted,
scanned_files,
})
}