1use sim_kernel::{Cx, EvalFabric, Result};
2
3use crate::{
4 CompiledIntent, IntentLibrary, IntentStatus, LiftOptions, VerifyCatalog, forge_lift_once,
5 normalize_prose,
6};
7
8#[derive(Clone, Copy, Debug, PartialEq, Eq)]
10pub enum PromotePolicy {
11 KeepCandidate,
13 AutoVerifiedOnProbePass,
18 RequireHumanApprovalForGolden,
20}
21
22#[derive(Clone, Debug)]
24pub struct ForgeResolver {
25 library: IntentLibrary,
26 lift_options: LiftOptions,
27 verify_catalog: VerifyCatalog,
28}
29
30impl ForgeResolver {
31 pub fn new(library: IntentLibrary, lift_options: LiftOptions) -> Self {
33 Self::new_with_verifiers(library, lift_options, VerifyCatalog::new())
34 }
35
36 pub fn new_with_verifiers(
39 library: IntentLibrary,
40 lift_options: LiftOptions,
41 verify_catalog: VerifyCatalog,
42 ) -> Self {
43 Self {
44 library,
45 lift_options,
46 verify_catalog,
47 }
48 }
49
50 pub fn library(&self) -> &IntentLibrary {
52 &self.library
53 }
54
55 pub fn library_mut(&mut self) -> &mut IntentLibrary {
57 &mut self.library
58 }
59
60 pub fn verify_catalog(&self) -> &VerifyCatalog {
62 &self.verify_catalog
63 }
64
65 pub fn verify_catalog_mut(&mut self) -> &mut VerifyCatalog {
67 &mut self.verify_catalog
68 }
69
70 pub fn resolve(
77 &mut self,
78 cx: &mut Cx,
79 target: &dyn EvalFabric,
80 prose: &str,
81 policy: PromotePolicy,
82 ) -> Result<CompiledIntent> {
83 let (_, source) = normalize_prose(prose)?;
84 if let Some(intent) = self.library.golden_by_source(&source) {
85 return Ok(intent.clone());
86 }
87
88 let mut lifted = forge_lift_once(cx, target, prose, &self.lift_options)?;
89 self.apply_policy(cx, &mut lifted, policy)?;
90 self.library.store_resolved(lifted)
91 }
92
93 fn apply_policy(
94 &self,
95 cx: &mut Cx,
96 intent: &mut CompiledIntent,
97 policy: PromotePolicy,
98 ) -> Result<()> {
99 intent.status = IntentStatus::Candidate;
100 match policy {
101 PromotePolicy::KeepCandidate | PromotePolicy::RequireHumanApprovalForGolden => {}
102 PromotePolicy::AutoVerifiedOnProbePass => {
103 intent.probes = self.verify_catalog.probe_ids_for(&intent.name);
104 let report = self.verify_catalog.verify_intent_probes(cx, intent)?;
105 if report.accepted() {
106 intent.status = IntentStatus::Verified;
107 }
108 }
109 }
110 Ok(())
111 }
112}
113
114impl Default for ForgeResolver {
115 fn default() -> Self {
116 Self::new(IntentLibrary::new(), LiftOptions::default())
117 }
118}
119
120pub fn forge_resolve(
126 cx: &mut Cx,
127 target: &dyn EvalFabric,
128 prose: &str,
129 policy: PromotePolicy,
130) -> Result<CompiledIntent> {
131 ForgeResolver::default().resolve(cx, target, prose, policy)
132}
133
134pub fn forge_resolve_with_options(
136 library: &mut IntentLibrary,
137 lift_options: &LiftOptions,
138 cx: &mut Cx,
139 target: &dyn EvalFabric,
140 prose: &str,
141 policy: PromotePolicy,
142) -> Result<CompiledIntent> {
143 let mut resolver = ForgeResolver::new(std::mem::take(library), lift_options.clone());
144 let intent = resolver.resolve(cx, target, prose, policy)?;
145 *library = resolver.library;
146 Ok(intent)
147}