1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
// Copyright 2024-2026 Reflective Labs
// SPDX-License-Identifier: MIT
//! Generic proposal lifecycle trait.
//!
//! The `ProposalLifecycle<I, P, V, F>` trait defines the contract for
//! transforming intents into facts through validation and promotion.
//!
//! # Type Parameters
//!
//! - `I`: Intent type (what we're trying to achieve)
//! - `P`: Proposal type (what agents suggest)
//! - `V`: Validation proof type (evidence validation occurred)
//! - `F`: Fact type (promoted result)
//!
//! # Design Axiom
//!
//! **"Agents suggest, engine decides"** - proposals become facts only
//! through explicit validation and promotion via this trait.
//!
//! # The Gate Pattern
//!
//! The lifecycle enforces a two-step process:
//!
//! 1. **Validation**: `validate(intent, proposal) -> Result<V, ValidationError>`
//! - Checks proposal against policy and intent
//! - Returns a proof object (typically wrapping a `ValidationReport`)
//! - This proof is required for promotion
//!
//! 2. **Promotion**: `promote(validated) -> Result<F, PromotionError>`
//! - Consumes the validation proof
//! - Creates the final fact with complete audit trail
//! - No bypass path - must have proof
//!
//! # Example Implementation
//!
//! ```ignore
//! impl ProposalLifecycle<Intent, Proposal<Draft>, ValidatedProposal, Fact>
//! for MyGate
//! {
//! fn validate(&self, intent: &Intent, proposal: Proposal<Draft>)
//! -> Result<ValidatedProposal, ValidationError>
//! {
//! // Run validation checks
//! // Return proof bundled with validated proposal
//! }
//!
//! fn promote(&self, validated: ValidatedProposal)
//! -> Result<Fact, PromotionError>
//! {
//! // Extract report and proposal from proof
//! // Create Fact with PromotionRecord
//! }
//! }
//! ```
//!
//! # Relationship to PromotionGate
//!
//! `PromotionGate` is the concrete implementation of this trait for
//! Converge's standard proposal-to-fact flow. Custom gates can implement
//! this trait with different type parameters for specialized domains.
use ValidationError;
use cratePromotionError;
/// Generic lifecycle for proposal-to-fact promotion.
///
/// This trait defines the contract for transforming proposals into facts
/// through explicit validation and promotion. The key invariant is that
/// promotion requires validation proof - there is no bypass path.
///
/// # Type Parameters
///
/// - `I`: Intent type - defines what we're trying to achieve. The intent
/// provides context for validation decisions.
///
/// - `P`: Proposal type - what agents suggest. This is the input that
/// needs to be validated before it can become a fact.
///
/// - `V`: Validation proof type - evidence that validation occurred.
/// Typically bundles a `ValidationReport` with the validated proposal.
/// This type ensures validation cannot be skipped.
///
/// - `F`: Fact type - the promoted result. Facts are immutable, governed
/// truths that can only be created through this lifecycle.
///
/// # Invariants
///
/// - **No bypass path**: `promote()` requires validation proof `V`
/// - **Proof consumption**: The proof is consumed by `promote()`
/// - **Complete audit**: The resulting fact has a `PromotionRecord`
/// - **Determinism**: Same input should produce same validation result