use sim_kernel::{Cx, EvalFabric, Result};
use crate::{
CompiledIntent, IntentLibrary, IntentStatus, LiftOptions, VerifyCatalog, forge_lift_once,
normalize_prose,
};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum PromotePolicy {
KeepCandidate,
AutoVerifiedOnProbePass,
RequireHumanApprovalForGolden,
}
#[derive(Clone, Debug)]
pub struct ForgeResolver {
library: IntentLibrary,
lift_options: LiftOptions,
verify_catalog: VerifyCatalog,
}
impl ForgeResolver {
pub fn new(library: IntentLibrary, lift_options: LiftOptions) -> Self {
Self::new_with_verifiers(library, lift_options, VerifyCatalog::new())
}
pub fn new_with_verifiers(
library: IntentLibrary,
lift_options: LiftOptions,
verify_catalog: VerifyCatalog,
) -> Self {
Self {
library,
lift_options,
verify_catalog,
}
}
pub fn library(&self) -> &IntentLibrary {
&self.library
}
pub fn library_mut(&mut self) -> &mut IntentLibrary {
&mut self.library
}
pub fn verify_catalog(&self) -> &VerifyCatalog {
&self.verify_catalog
}
pub fn verify_catalog_mut(&mut self) -> &mut VerifyCatalog {
&mut self.verify_catalog
}
pub fn resolve(
&mut self,
cx: &mut Cx,
target: &dyn EvalFabric,
prose: &str,
policy: PromotePolicy,
) -> Result<CompiledIntent> {
let (_, source) = normalize_prose(prose)?;
if let Some(intent) = self.library.golden_by_source(&source) {
return Ok(intent.clone());
}
let mut lifted = forge_lift_once(cx, target, prose, &self.lift_options)?;
self.apply_policy(cx, &mut lifted, policy)?;
self.library.store_resolved(lifted)
}
fn apply_policy(
&self,
cx: &mut Cx,
intent: &mut CompiledIntent,
policy: PromotePolicy,
) -> Result<()> {
intent.status = IntentStatus::Candidate;
match policy {
PromotePolicy::KeepCandidate | PromotePolicy::RequireHumanApprovalForGolden => {}
PromotePolicy::AutoVerifiedOnProbePass => {
intent.probes = self.verify_catalog.probe_ids_for(&intent.name);
let report = self.verify_catalog.verify_intent_probes(cx, intent)?;
if report.accepted() {
intent.status = IntentStatus::Verified;
}
}
}
Ok(())
}
}
impl Default for ForgeResolver {
fn default() -> Self {
Self::new(IntentLibrary::new(), LiftOptions::default())
}
}
pub fn forge_resolve(
cx: &mut Cx,
target: &dyn EvalFabric,
prose: &str,
policy: PromotePolicy,
) -> Result<CompiledIntent> {
ForgeResolver::default().resolve(cx, target, prose, policy)
}
pub fn forge_resolve_with_options(
library: &mut IntentLibrary,
lift_options: &LiftOptions,
cx: &mut Cx,
target: &dyn EvalFabric,
prose: &str,
policy: PromotePolicy,
) -> Result<CompiledIntent> {
let mut resolver = ForgeResolver::new(std::mem::take(library), lift_options.clone());
let intent = resolver.resolve(cx, target, prose, policy)?;
*library = resolver.library;
Ok(intent)
}