converge_core/truth.rs
1// Copyright 2024-2026 Reflective Labs
2// SPDX-License-Identifier: MIT
3
4//! Truth catalog primitives.
5//!
6//! Truths describe jobs, policies, and invariants above domain packs.
7//! Applications provide the catalog content; the runtime consumes a common
8//! shape for intent construction, guardrails, and pack participation.
9
10use serde::{Deserialize, Serialize};
11
12use crate::{Context, Criterion, FactId, TypesIntentConstraint};
13
14/// What class of truth is being described.
15#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
16pub enum TruthKind {
17 /// A job-to-be-done spanning multiple packs.
18 Job,
19 /// A cross-cutting policy or guardrail.
20 Policy,
21 /// A module-local or pack-local invariant.
22 Invariant,
23}
24
25/// Portable truth definition.
26#[derive(Debug, Clone, Serialize, Deserialize)]
27pub struct TruthDefinition {
28 /// Stable truth identifier.
29 pub key: String,
30 /// Truth class.
31 pub kind: TruthKind,
32 /// Human-readable summary.
33 pub summary: String,
34 /// Required or optional success criteria.
35 pub success_criteria: Vec<Criterion>,
36 /// Hard and soft constraints derived from the truth.
37 pub constraints: Vec<TypesIntentConstraint>,
38 /// Human approval points that the runtime must respect.
39 pub approval_points: Vec<String>,
40 /// Which packs should participate when this truth is active.
41 pub participating_packs: Vec<String>,
42}
43
44/// Machine-evaluable outcome for a single criterion.
45#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
46pub enum CriterionResult {
47 /// The criterion was satisfied, with fact IDs that justify the result.
48 Met { evidence: Vec<FactId> },
49 /// The criterion is currently blocked on human intervention.
50 Blocked {
51 /// Why the criterion is blocked.
52 reason: String,
53 /// Optional approval or workflow reference the host can surface.
54 approval_ref: Option<String>,
55 },
56 /// The criterion was evaluated and is not satisfied.
57 Unmet { reason: String },
58 /// The runtime could not determine whether the criterion was satisfied.
59 Indeterminate,
60}
61
62/// Evaluated outcome for a specific criterion.
63#[derive(Debug, Clone, Serialize, Deserialize)]
64pub struct CriterionOutcome {
65 /// The criterion that was evaluated.
66 pub criterion: Criterion,
67 /// The result of the evaluation.
68 pub result: CriterionResult,
69}
70
71/// Application-provided boundary for evaluating success criteria.
72pub trait CriterionEvaluator: Send + Sync {
73 /// Evaluate a criterion against the converged context.
74 fn evaluate(&self, criterion: &Criterion, context: &Context) -> CriterionResult;
75}
76
77/// Application-provided truth catalog boundary.
78pub trait TruthCatalog: Send + Sync {
79 /// List all truths known to the application.
80 fn list_truths(&self) -> Vec<TruthDefinition>;
81
82 /// Resolve a truth by key.
83 fn find_truth(&self, key: &str) -> Option<TruthDefinition> {
84 self.list_truths()
85 .into_iter()
86 .find(|truth| truth.key == key)
87 }
88}