Skip to main content

organism_planning/
lib.rs

1//! Planning layer.
2//!
3//! Multi-model collaborative planning. A huddle runs several reasoning
4//! systems in parallel, then the debate loop refines candidate plans
5//! before they're handed to the simulation swarm.
6//!
7//! Plans flow through converge's PromotionGate like any other proposal.
8//! No special bypass; standard convergence pipeline applies.
9
10pub mod charter_derivation;
11pub mod collaboration;
12pub mod dd;
13pub mod debate;
14pub mod huddle;
15pub mod kb;
16pub mod shape_hypothesis;
17pub mod suggestor;
18pub mod topology_transition;
19
20use converge_pack::FactId;
21use organism_intent::IntentPacket;
22use serde::{Deserialize, Serialize};
23use uuid::Uuid;
24
25pub use collaboration::{
26    CollaborationCharter, CollaborationDiscipline, CollaborationMember, CollaborationRole,
27    CollaborationTopology, CollaborationValidationError, ConsensusRule, TeamFormation,
28    TeamFormationMode, TurnCadence,
29};
30
31// ── Plan ───────────────────────────────────────────────────────────
32
33/// A candidate plan produced by reasoning. Plans are *proposals*, not
34/// commitments — authority is recomputed at the commit boundary.
35#[derive(Debug, Clone, Serialize, Deserialize)]
36pub struct Plan {
37    pub id: Uuid,
38    pub intent: Uuid,
39    pub steps: Vec<PlanStep>,
40    pub rationale: String,
41    pub annotation: PlanAnnotation,
42    pub contributor: ReasoningSystem,
43}
44
45#[derive(Debug, Clone, Serialize, Deserialize)]
46pub struct PlanStep {
47    pub action: String,
48    pub expected_effect: String,
49}
50
51impl Plan {
52    pub fn new(intent: &IntentPacket, rationale: impl Into<String>) -> Self {
53        Self {
54            id: Uuid::new_v4(),
55            intent: intent.id,
56            steps: Vec::new(),
57            rationale: rationale.into(),
58            annotation: PlanAnnotation::default(),
59            contributor: ReasoningSystem::LlmReasoning,
60        }
61    }
62}
63
64// ── Plan Annotation ────────────────────────────────────────────────
65
66#[derive(Debug, Clone, Default, Serialize, Deserialize)]
67pub struct PlanAnnotation {
68    pub impacts: Vec<Impact>,
69    pub costs: Vec<CostEstimate>,
70    pub risks: Vec<Risk>,
71}
72
73#[derive(Debug, Clone, Serialize, Deserialize)]
74pub struct Impact {
75    pub description: String,
76    pub confidence: f64,
77}
78
79#[derive(Debug, Clone, Serialize, Deserialize)]
80pub struct CostEstimate {
81    pub description: String,
82    pub compute_cost: f64,
83    pub time_cost: f64,
84    pub unit: String,
85}
86
87#[derive(Debug, Clone, Serialize, Deserialize)]
88pub struct Risk {
89    pub description: String,
90    pub likelihood: Likelihood,
91    pub impact: RiskImpact,
92    pub mitigation: Option<String>,
93}
94
95#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
96#[serde(rename_all = "snake_case")]
97pub enum Likelihood {
98    Low,
99    Medium,
100    High,
101}
102
103#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
104#[serde(rename_all = "snake_case")]
105pub enum RiskImpact {
106    Low,
107    Medium,
108    High,
109    Critical,
110}
111
112// ── Reasoning Systems ──────────────────────────────────────────────
113
114#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
115#[serde(rename_all = "snake_case")]
116pub enum ReasoningSystem {
117    LlmReasoning,
118    ConstraintSolver,
119    MlPrediction,
120    CausalAnalysis,
121    CostEstimation,
122    DomainModel,
123}
124
125// ── Huddle ─────────────────────────────────────────────────────────
126
127#[derive(Debug, Clone, Serialize, Deserialize)]
128pub struct PlanContribution {
129    pub system: ReasoningSystem,
130    pub suggestions: Vec<String>,
131    pub constraints: Vec<String>,
132    pub risks: Vec<Risk>,
133}
134
135/// A reasoning capability participating in a huddle.
136#[async_trait::async_trait]
137pub trait Reasoner: Send + Sync {
138    fn name(&self) -> &str;
139    fn system_type(&self) -> ReasoningSystem;
140    async fn propose(&self, intent: &IntentPacket) -> anyhow::Result<Plan>;
141    fn contribute(&self, context: &serde_json::Value) -> PlanContribution;
142}
143
144// ── Plan Bundle (debate output) ────────────────────────────────────
145
146#[derive(Debug, Clone, Serialize, Deserialize)]
147pub struct PlanBundle {
148    pub plans: Vec<Plan>,
149    pub debate_rounds: u32,
150}
151
152// ── Hypothesis Tracking ───────────────────────────────────────────
153
154/// Lifecycle state of a tracked hypothesis.
155#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
156#[serde(rename_all = "snake_case", tag = "outcome")]
157pub enum HypothesisOutcome {
158    Open,
159    Confirmed,
160    Falsified { contradiction_id: FactId },
161    Superseded,
162    Unresolved,
163}
164
165/// A hypothesis tracked across convergence cycles.
166///
167/// Created from a `ContextKey::Hypotheses` fact. The tracker records
168/// when it was first seen, its confidence trajectory, and its final outcome.
169#[derive(Debug, Clone, Serialize, Deserialize)]
170pub struct TrackedHypothesis {
171    pub fact_id: FactId,
172    pub domain: String,
173    pub claim: String,
174    pub confidence: f64,
175    pub formed_cycle: u32,
176    pub resolved_cycle: Option<u32>,
177    pub outcome: HypothesisOutcome,
178}