1pub const CONFIDENCE_STEP_TINY: f64 = 0.05;
54pub const CONFIDENCE_STEP_MINOR: f64 = 0.1;
55pub const CONFIDENCE_STEP_MEDIUM: f64 = 0.15;
56pub const CONFIDENCE_STEP_MAJOR: f64 = 0.2;
57pub const CONFIDENCE_STEP_PRIMARY: f64 = 0.25;
58
59pub use organism_intent::{
63 AdmissionController,
65 AdmissionResult,
66 ExpiryAction,
67 FeasibilityAssessment,
68 FeasibilityDimension,
69 FeasibilityKind,
70 ForbiddenAction,
71 IntentError,
72 IntentNode,
73 IntentPacket,
74 Reversibility,
75 admission::DefaultAdmissionController,
76 resolution::{
78 CapabilityRequirement, DeclarativeBinding, IntentBinding, IntentResolver, PackRequirement,
79 ResolutionLevel, ResolutionTrace,
80 },
81};
82
83pub use organism_planning::{
87 CollaborationCharter, CollaborationDiscipline, CollaborationMember, CollaborationRole,
88 CollaborationTopology, CollaborationValidationError, ConsensusRule, CostEstimate, Impact,
89 Likelihood, Plan, PlanAnnotation, PlanBundle, PlanContribution, PlanStep, Reasoner,
90 ReasoningSystem, Risk, RiskImpact, TeamFormation, TeamFormationMode, TurnCadence,
91 charter_derivation::{
92 DerivationRationale, DerivedCharter, IntentComplexity, derive_charter,
93 derive_charter_with_priors,
94 },
95 dd::{
96 BreadthResearchSuggestor, ContradictionFinderSuggestor, DdError, DdFactSummary, DdHooks,
97 DdLlm, DdSearch, DepthResearchSuggestor, FactExtractorSuggestor, FailoverDdLlm,
98 FailoverDdSearch, GapDetectorSuggestor, HookPatterns, SearchHit, SynthesisSuggestor,
99 consolidate_dd_hypotheses, extract_hooks_from_facts,
100 },
101 kb::{
102 HubCategory, KbConfig, RootPageDef, sanitize_filename, slugify, update_root_pages,
103 write_dd_to_vault, write_or_append_hub,
104 },
105 shape_hypothesis::{
106 ShapeCalibration, ShapeCandidate, ShapeCompetition, ShapeMetric, ShapeObservation,
107 calibrate_shape, classify_problem, generate_candidates, score_observation, select_winner,
108 },
109 suggestor::{HuddleSeedSuggestor, NamedPlan, SharedBudget},
110 topology_transition::{
111 CharterAdjustments, ConvergenceSignals, TransitionDecision, TransitionRule,
112 TransitionTrigger, apply_adjustments, default_transition_rules, evaluate_transitions,
113 },
114};
115
116pub use organism_adversarial::{
121 AdversarialSignal, AdversarialVerdict, AgentId, Challenge, Complexity, Finding, Severity,
122 SkepticismKind,
123};
124
125pub use organism_simulation::{
130 DimensionResult, OutcomeSimulationAgent, OutcomeSimulator, OutcomeSimulatorConfig,
131 RiskLikelihood, Sample, SimulationDimension, SimulationRecommendation, SimulationReport,
132 SimulationResult, SimulationVerdict,
133};
134
135pub use organism_learning::{
139 AdversarialContext, ErrorDimension, LearningEpisode, LearningSignal, Lesson, PredictionError,
140 PriorCalibration, SignalKind,
141 adapter::{
142 build_episode, build_episode_from_run, calibrate_priors, extract_signals,
143 extract_signals_from_run, has_infra_failure,
144 },
145};
146
147#[cfg(test)]
148mod tests {
149 use super::*;
150 use chrono::{Duration, Utc};
151
152 #[test]
153 fn intent_packet_roundtrip() {
154 let expires = Utc::now() + Duration::hours(1);
155 let intent = IntentPacket::new("ship feature X", expires);
156 let json = serde_json::to_string(&intent).unwrap();
157 let back: IntentPacket = serde_json::from_str(&json).unwrap();
158 assert_eq!(back.outcome, "ship feature X");
159 assert_eq!(back.reversibility, Reversibility::Reversible);
160 assert_eq!(back.expiry_action, ExpiryAction::Halt);
161 }
162
163 #[test]
164 fn intent_packet_builder_chain() {
165 let expires = Utc::now() + Duration::hours(2);
166 let intent = IntentPacket::new("approve expense", expires)
167 .with_context(serde_json::json!({"amount": 2500}))
168 .with_authority(vec!["finance".into()])
169 .with_reversibility(Reversibility::Irreversible)
170 .with_expiry_action(ExpiryAction::Escalate);
171
172 assert_eq!(intent.outcome, "approve expense");
173 assert_eq!(intent.context["amount"], 2500);
174 assert_eq!(intent.authority, vec!["finance"]);
175 assert_eq!(intent.reversibility, Reversibility::Irreversible);
176 assert_eq!(intent.expiry_action, ExpiryAction::Escalate);
177 }
178
179 #[test]
180 fn intent_packet_expired_detection() {
181 let past = Utc::now() - Duration::seconds(10);
182 let intent = IntentPacket::new("too late", past);
183 assert!(intent.is_expired(Utc::now()));
184
185 let future = Utc::now() + Duration::hours(1);
186 let intent2 = IntentPacket::new("still valid", future);
187 assert!(!intent2.is_expired(Utc::now()));
188 }
189
190 #[test]
191 fn reversibility_all_variants_serialize() {
192 for variant in [
193 Reversibility::Reversible,
194 Reversibility::Partial,
195 Reversibility::Irreversible,
196 ] {
197 let json = serde_json::to_string(&variant).unwrap();
198 let back: Reversibility = serde_json::from_str(&json).unwrap();
199 assert_eq!(variant, back);
200 }
201 }
202
203 #[test]
204 fn expiry_action_all_variants_serialize() {
205 for variant in [
206 ExpiryAction::Halt,
207 ExpiryAction::Escalate,
208 ExpiryAction::CompleteAndHalt,
209 ] {
210 let json = serde_json::to_string(&variant).unwrap();
211 let back: ExpiryAction = serde_json::from_str(&json).unwrap();
212 assert_eq!(variant, back);
213 }
214 }
215
216 #[test]
217 fn declarative_binding_empty() {
218 let binding = DeclarativeBinding::new().build();
219 assert!(binding.packs.is_empty());
220 assert!(binding.capabilities.is_empty());
221 assert!(binding.invariants.is_empty());
222 assert_eq!(
223 binding.resolution.levels_attempted,
224 vec![ResolutionLevel::Declarative]
225 );
226 }
227
228 #[test]
229 fn declarative_binding_full() {
230 let binding = DeclarativeBinding::new()
231 .pack("customers", "qualification")
232 .pack("knowledge", "enrichment")
233 .capability("web", "scraping")
234 .capability("ocr", "documents")
235 .invariant("lead_has_source")
236 .invariant("claim_has_provenance")
237 .build();
238
239 assert_eq!(binding.packs.len(), 2);
240 assert_eq!(binding.capabilities.len(), 2);
241 assert_eq!(binding.invariants.len(), 2);
242 assert!((binding.packs[0].confidence - 1.0).abs() < f64::EPSILON);
243 assert_eq!(binding.packs[1].pack_name, "knowledge");
244 assert_eq!(binding.capabilities[0].capability, "web");
245 }
246
247 #[test]
248 fn intent_binding_default() {
249 let binding = IntentBinding::default();
250 assert!(binding.packs.is_empty());
251 assert!(binding.capabilities.is_empty());
252 assert!(binding.invariants.is_empty());
253 assert_eq!(binding.resolution.prior_episodes_consulted, 0);
254 assert!((binding.resolution.completeness_confidence - 0.0).abs() < f64::EPSILON);
255 }
256
257 #[test]
258 fn resolution_level_serde() {
259 for level in [
260 ResolutionLevel::Declarative,
261 ResolutionLevel::Structural,
262 ResolutionLevel::Semantic,
263 ResolutionLevel::Learned,
264 ] {
265 let json = serde_json::to_string(&level).unwrap();
266 let back: ResolutionLevel = serde_json::from_str(&json).unwrap();
267 assert_eq!(level, back);
268 }
269 }
270
271 #[test]
272 fn resolution_trace_default() {
273 let trace = ResolutionTrace::default();
274 assert!(trace.levels_attempted.is_empty());
275 assert!(trace.levels_contributed.is_empty());
276 assert_eq!(trace.prior_episodes_consulted, 0);
277 }
278
279 #[test]
280 fn intent_binding_serde_roundtrip() {
281 let binding = DeclarativeBinding::new()
282 .pack("test_pack", "test reason")
283 .capability("web", "needed for scraping")
284 .invariant("my_invariant")
285 .build();
286
287 let json = serde_json::to_string(&binding).unwrap();
288 let back: IntentBinding = serde_json::from_str(&json).unwrap();
289 assert_eq!(back.packs.len(), 1);
290 assert_eq!(back.capabilities.len(), 1);
291 assert_eq!(back.invariants, vec!["my_invariant"]);
292 }
293
294 #[test]
295 fn intent_node_leaf() {
296 let expires = Utc::now() + Duration::hours(1);
297 let intent = IntentPacket::new("leaf task", expires);
298 let node = IntentNode::leaf(intent);
299 assert!(node.is_leaf());
300 assert!(node.children.is_empty());
301 assert_eq!(node.intent.outcome, "leaf task");
302 }
303
304 #[test]
305 fn feasibility_dimension_serde() {
306 for dim in [
307 FeasibilityDimension::Capability,
308 FeasibilityDimension::Context,
309 FeasibilityDimension::Resources,
310 FeasibilityDimension::Authority,
311 ] {
312 let json = serde_json::to_string(&dim).unwrap();
313 let back: FeasibilityDimension = serde_json::from_str(&json).unwrap();
314 assert_eq!(dim, back);
315 }
316 }
317
318 #[test]
319 fn feasibility_kind_serde() {
320 for kind in [
321 FeasibilityKind::Feasible,
322 FeasibilityKind::FeasibleWithConstraints,
323 FeasibilityKind::Uncertain,
324 FeasibilityKind::Infeasible,
325 ] {
326 let json = serde_json::to_string(&kind).unwrap();
327 let back: FeasibilityKind = serde_json::from_str(&json).unwrap();
328 assert_eq!(kind, back);
329 }
330 }
331
332 #[test]
333 fn admission_result_serde_roundtrip() {
334 let result = AdmissionResult {
335 feasible: true,
336 dimensions: vec![FeasibilityAssessment {
337 dimension: FeasibilityDimension::Capability,
338 kind: FeasibilityKind::Feasible,
339 reason: "all good".into(),
340 }],
341 rejection_reason: None,
342 };
343 let json = serde_json::to_string(&result).unwrap();
344 let back: AdmissionResult = serde_json::from_str(&json).unwrap();
345 assert!(back.feasible);
346 assert_eq!(back.dimensions.len(), 1);
347 assert!(back.rejection_reason.is_none());
348 }
349
350 #[test]
351 fn forbidden_action_serde_roundtrip() {
352 let fa = ForbiddenAction {
353 action: "delete_all".into(),
354 reason: "too destructive".into(),
355 };
356 let json = serde_json::to_string(&fa).unwrap();
357 let back: ForbiddenAction = serde_json::from_str(&json).unwrap();
358 assert_eq!(back.action, "delete_all");
359 assert_eq!(back.reason, "too destructive");
360 }
361
362 #[test]
363 fn challenge_fields() {
364 let challenge = Challenge::new(
365 SkepticismKind::EconomicSkepticism,
366 uuid::Uuid::new_v4(),
367 "spend too high",
368 Severity::Warning,
369 );
370 assert_eq!(challenge.kind, SkepticismKind::EconomicSkepticism);
371 assert_eq!(challenge.severity, Severity::Warning);
372 assert_eq!(challenge.description, "spend too high");
373 }
374
375 #[test]
376 fn challenge_is_blocking() {
377 let blocker = Challenge::new(
378 SkepticismKind::ConstraintChecking,
379 uuid::Uuid::new_v4(),
380 "hard stop",
381 Severity::Blocker,
382 );
383 let warning = Challenge::new(
384 SkepticismKind::ConstraintChecking,
385 uuid::Uuid::new_v4(),
386 "soft",
387 Severity::Warning,
388 );
389 assert!(blocker.is_blocking());
390 assert!(!warning.is_blocking());
391 }
392
393 #[test]
394 fn severity_all_variants_accessible() {
395 let variants = [Severity::Advisory, Severity::Warning, Severity::Blocker];
396 assert_eq!(variants.len(), 3);
397 }
398
399 #[test]
400 fn skepticism_kind_all_variants_accessible() {
401 let variants = [
402 SkepticismKind::AssumptionBreaking,
403 SkepticismKind::ConstraintChecking,
404 SkepticismKind::CausalSkepticism,
405 SkepticismKind::EconomicSkepticism,
406 SkepticismKind::OperationalSkepticism,
407 ];
408 assert_eq!(variants.len(), 5);
409 }
410
411 #[test]
412 fn simulation_dimension_all_variants_accessible() {
413 let variants = [
414 SimulationDimension::Outcome,
415 SimulationDimension::Cost,
416 SimulationDimension::Policy,
417 SimulationDimension::Causal,
418 SimulationDimension::Operational,
419 ];
420 assert_eq!(variants.len(), 5);
421 }
422
423 #[test]
424 fn dimension_result_construction() {
425 let result = DimensionResult {
426 dimension: SimulationDimension::Cost,
427 passed: true,
428 confidence: 0.95,
429 findings: vec!["within budget".into()],
430 samples: vec![],
431 };
432 assert!(result.passed);
433 assert!((result.confidence - 0.95).abs() < f64::EPSILON);
434 assert_eq!(result.findings.len(), 1);
435 }
436
437 #[test]
438 fn lesson_construction() {
439 let lesson = Lesson {
440 insight: "score 0.88 → approved".into(),
441 context: "expense approval".into(),
442 confidence: 0.9,
443 planning_adjustment: "none".into(),
444 };
445 assert_eq!(lesson.insight, "score 0.88 → approved");
446 assert!((lesson.confidence - 0.9).abs() < f64::EPSILON);
447 }
448}