Skip to main content

converge_kernel/
lib.rs

1// Copyright 2024-2026 Reflective Labs
2// SPDX-License-Identifier: MIT
3
4//! # Converge Kernel
5//!
6//! This crate is the curated in-process execution API for Converge.
7//! Consumers embed the kernel here; they author packs in `converge-pack`
8//! and use `converge-model` for shared semantic types.
9
10mod provider_selection;
11
12pub use provider_selection::ProviderSelectionSuggestor;
13
14pub mod formation {
15    //! Grouped offering API for self-assembling formations.
16    //!
17    //! The stable pattern is:
18    //! - semantics in `converge-model`
19    //! - authoring in `converge-pack`
20    //! - runnable machinery in `converge-kernel`
21
22    pub use crate::ProviderSelectionSuggestor;
23    pub use converge_model::formation::{
24        DeliberatedFormationTemplate, FormationCatalog, FormationKind, FormationPlan,
25        FormationRequest, FormationTemplate, FormationTemplateMetadata, FormationTemplateQuery,
26        OpenClawFormationTemplate, ProfileSnapshot, RoleAssignment, ScoredFormationTemplate,
27        ScoringWeights, StaticFormationTemplate, SuggestorCapability, SuggestorProfile,
28        SuggestorRole,
29    };
30    pub use converge_optimization::suggestors::FormationAssemblySuggestor;
31    pub use converge_provider::{
32        Capability, CapabilityAssignment, CostClass, LatencyClass, ProviderAssignment,
33        ProviderRequest,
34    };
35}
36
37pub mod admission {
38    //! External observation admission API.
39    //!
40    //! Admission stages observations as proposals. It does not construct
41    //! authoritative facts; promotion remains engine-owned.
42
43    pub use converge_model::{
44        AdmissionActor, AdmissionActorKind, AdmissionContent, AdmissionError, AdmissionReceipt,
45        AdmissionRequest, AdmissionSource,
46    };
47
48    use crate::{ContextState, ConvergeError};
49
50    /// Stages an external observation for governed promotion.
51    pub fn admit_observation(
52        context: &mut ContextState,
53        request: AdmissionRequest,
54    ) -> Result<AdmissionReceipt, ConvergeError> {
55        context.submit_observation(request)
56    }
57}
58
59pub use converge_core::gates::hitl::{
60    ContextItem, GateDecision, GateEvent, GateEventKind, GateRequest, GateVerdict, HitlPolicy,
61    TimeoutAction, TimeoutPolicy,
62};
63pub use converge_core::gates::{
64    AuthorityLevel, FlowAction, FlowGateAuthorizer, FlowGateContext, FlowGateInput,
65    FlowGateOutcome, FlowGatePrincipal, FlowGateResource, FlowPhase, StopReason,
66};
67pub use converge_core::recall::{
68    CandidateProvenance, CandidateSourceType, RecallCandidate, RecallPolicy, RecallQuery,
69    RecallUse, RelevanceLevel, recall_from_store,
70};
71pub use converge_core::{
72    AdmissionActor, AdmissionActorKind, AdmissionContent, AdmissionError, AdmissionReceipt,
73    AdmissionRequest, AdmissionSource, ApprovalPointId, BackendId, BoundaryKind, BoundaryTarget,
74    Budget, BudgetResource, ChainId, ConstraintName, ConstraintValue, ContextSnapshot,
75    ContextState, ConvergeError, ConvergeResult, CorrectionTarget, CorrelationId, Criterion,
76    CriterionEvaluator, CriterionId, CriterionOutcome, CriterionResult, DecisionStep, Engine,
77    EngineHitlPolicy, EventId, EventQuery, ExperienceEvent, ExperienceEventEnvelope,
78    ExperienceEventKind, ExperienceEventObserver, ExperienceRecord, ExperienceStore,
79    ExperienceStoreError, ExperienceStoreResult, FactContent, FactContentKind, HitlPause,
80    IntegrityProof, Invariant, InvariantClass, InvariantResult, LamportClock, MerkleRoot,
81    OverrideTarget, PackId, RunResult, StreamingCallback, SuggestorId, TenantId, TraceLinkId,
82    TruthId, TypesBudgets, TypesIntentId, TypesIntentKind, TypesRootIntent, TypesRunHooks,
83    UnitInterval, UserExperienceEvent, UserExperienceEventEnvelope,
84};
85pub use converge_pack::{
86    AgentEffect, ArtifactId, Context, ContextFact, ContextKey, ProposedFact, Suggestor,
87    ValidationError,
88};
89
90// Experience-side surface (artifact lifecycle, replay traces).
91// These let downstream consumers (Organism learning, Helms, etc.) reference
92// governed-artifact and replay vocabulary without importing converge_core.
93pub use converge_core::experience_store::ArtifactKind;
94pub use converge_core::governed_artifact::LifecycleEvent;
95pub use converge_core::kernel_boundary::{LocalReplayTrace, RemoteReplayTrace, ReplayTrace};
96
97#[cfg(test)]
98mod tests {
99    use super::{
100        BudgetResource, ContextKey, ContextState, StopReason,
101        admission::{
102            AdmissionActor, AdmissionActorKind, AdmissionContent, AdmissionRequest,
103            AdmissionSource, admit_observation,
104        },
105        formation::{
106            Capability, FormationCatalog, FormationRequest, FormationTemplate,
107            FormationTemplateMetadata, ProviderRequest, StaticFormationTemplate, SuggestorRole,
108        },
109    };
110
111    #[test]
112    fn kernel_reexports_runtime_stop_and_budget_types() {
113        let stop = StopReason::converged();
114        assert!(matches!(stop, StopReason::Converged));
115        assert!(matches!(BudgetResource::Tokens, BudgetResource::Tokens));
116    }
117
118    #[test]
119    fn kernel_groups_formation_offering_api() {
120        let formation = FormationRequest {
121            id: "req-1".to_string(),
122            required_roles: vec![SuggestorRole::Analysis],
123            required_capabilities: vec![],
124        };
125        let provider = ProviderRequest {
126            id: "provider-1".to_string(),
127            required_capabilities: vec![Capability::Reasoning],
128            backend_requirements: None,
129        };
130
131        assert_eq!(formation.required_roles, vec![SuggestorRole::Analysis]);
132        assert_eq!(provider.required_capabilities, vec![Capability::Reasoning]);
133    }
134
135    #[test]
136    fn kernel_reexports_template_catalog_surface() {
137        let catalog = FormationCatalog::new().with_template(FormationTemplate::static_template(
138            StaticFormationTemplate::new(FormationTemplateMetadata::new(
139                "analysis-only",
140                "Single-role analysis formation",
141                [SuggestorRole::Analysis],
142            )),
143        ));
144
145        assert_eq!(catalog.len(), 1);
146        assert_eq!(
147            catalog.get("analysis-only").map(FormationTemplate::id),
148            Some("analysis-only")
149        );
150    }
151
152    #[test]
153    fn kernel_admission_stages_observation() {
154        let mut context = ContextState::new();
155        let request = AdmissionRequest::new(
156            AdmissionActor::new("organism-runtime", AdmissionActorKind::System).unwrap(),
157            AdmissionSource::new("truth-document").unwrap(),
158            ContextKey::Seeds,
159            "truth-doc-1",
160            AdmissionContent::new(r#"{"claim":"approved source"}"#).unwrap(),
161        )
162        .unwrap();
163
164        let receipt = admit_observation(&mut context, request).unwrap();
165
166        assert!(receipt.staged());
167        assert_eq!(receipt.proposal_id().as_str(), "truth-doc-1");
168    }
169}