Skip to main content

eidos_ekf/
model.rs

1use serde::{Deserialize, Serialize};
2use std::collections::BTreeMap;
3use std::path::PathBuf;
4
5#[derive(Debug, Clone, Default, PartialEq, Eq)]
6pub struct PackageRequest {
7    pub manifest: Option<PathBuf>,
8    pub start_dir: Option<PathBuf>,
9    pub vault: Option<PathBuf>,
10    pub docs: Option<PathBuf>,
11    pub code: Option<PathBuf>,
12}
13
14#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
15pub struct Manifest {
16    pub ekf_version: Option<String>,
17    pub name: Option<String>,
18    #[serde(default)]
19    pub partitions: Vec<PartitionManifest>,
20    #[serde(default)]
21    pub sources: SourceManifest,
22    #[serde(default)]
23    pub trust: BTreeMap<String, String>,
24    #[serde(default)]
25    pub gates: BTreeMap<String, BTreeMap<String, String>>,
26    #[serde(default)]
27    pub relations: BTreeMap<String, BTreeMap<String, String>>,
28}
29
30#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
31pub struct PartitionManifest {
32    pub id: String,
33    #[serde(default, skip_serializing_if = "Option::is_none")]
34    pub title: Option<String>,
35    pub source: String,
36    #[serde(default)]
37    pub roots: Vec<String>,
38    #[serde(default, skip_serializing_if = "Option::is_none")]
39    pub role: Option<String>,
40    #[serde(default)]
41    pub languages: Vec<String>,
42    #[serde(default)]
43    pub tags: Vec<String>,
44}
45
46#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
47pub struct TrustPolicy {
48    pub gold_ground_threshold: u32,
49    #[serde(default, skip_serializing_if = "Option::is_none")]
50    pub stale_after_days: Option<u64>,
51    #[serde(default, skip_serializing_if = "Option::is_none")]
52    pub agent_accepted_ttl_days: Option<u64>,
53}
54
55#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
56pub struct RelationPolicy {
57    pub forward_phrase: String,
58    pub reverse_phrase: String,
59    pub context_score: i64,
60    pub searchable: bool,
61    pub traversable: bool,
62    #[serde(default, skip_serializing_if = "Vec::is_empty")]
63    pub domain_kinds: Vec<String>,
64    #[serde(default, skip_serializing_if = "Vec::is_empty")]
65    pub range_kinds: Vec<String>,
66}
67
68impl RelationPolicy {
69    pub(crate) fn new(
70        forward_phrase: impl Into<String>,
71        reverse_phrase: impl Into<String>,
72        context_score: i64,
73    ) -> Self {
74        Self {
75            forward_phrase: forward_phrase.into(),
76            reverse_phrase: reverse_phrase.into(),
77            context_score,
78            searchable: true,
79            traversable: true,
80            domain_kinds: Vec::new(),
81            range_kinds: Vec::new(),
82        }
83    }
84}
85
86impl Default for TrustPolicy {
87    fn default() -> Self {
88        Self {
89            gold_ground_threshold: 5,
90            stale_after_days: None,
91            agent_accepted_ttl_days: None,
92        }
93    }
94}
95
96#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
97pub struct SourceManifest {
98    #[serde(default)]
99    pub docs: Vec<String>,
100    #[serde(default)]
101    pub skills: Vec<String>,
102    #[serde(default)]
103    pub agents: Vec<String>,
104    #[serde(default)]
105    pub capabilities: Vec<String>,
106    #[serde(default)]
107    pub brief_profiles: Vec<String>,
108    #[serde(default)]
109    pub workflows: Vec<String>,
110    #[serde(default)]
111    pub evals: Vec<String>,
112    #[serde(default)]
113    pub code: Vec<CodeSource>,
114}
115
116#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
117pub struct CodeSource {
118    pub path: String,
119    #[serde(default, skip_serializing_if = "Option::is_none")]
120    pub source: Option<String>,
121    #[serde(default)]
122    pub languages: Vec<String>,
123}
124
125#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
126#[serde(rename_all = "snake_case")]
127pub enum DiagnosticSeverity {
128    Info,
129    Warning,
130    Error,
131}
132
133#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
134pub struct EkfDiagnostic {
135    pub severity: DiagnosticSeverity,
136    pub kind: String,
137    pub message: String,
138    #[serde(default, skip_serializing_if = "Option::is_none")]
139    pub source: Option<String>,
140}
141
142#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
143pub struct ResolvedSources {
144    #[serde(default, skip_serializing_if = "Option::is_none")]
145    pub vault: Option<PathBuf>,
146    #[serde(default, skip_serializing_if = "Option::is_none")]
147    pub docs: Option<PathBuf>,
148    #[serde(default, skip_serializing_if = "Option::is_none")]
149    pub code: Option<PathBuf>,
150    #[serde(default, skip_serializing_if = "Vec::is_empty")]
151    pub source_roots: Vec<ResolvedSourceRoot>,
152}
153
154#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
155pub struct ResolvedSourceRoot {
156    pub kind: String,
157    pub path: PathBuf,
158    #[serde(default, skip_serializing_if = "Option::is_none")]
159    pub partition: Option<String>,
160    /// Declared extraction languages for code roots (from the owning partition or the legacy
161    /// `sources.code` entry). Empty = no restriction. Extraction honors this as a filter.
162    #[serde(default, skip_serializing_if = "Vec::is_empty")]
163    pub languages: Vec<String>,
164    /// How Eidos v0.1 treats this root: `compiled` feeds the graph, `planning` feeds the task
165    /// planner, `eval` feeds package gates, and `declared` is validated/reported package contract
166    /// only.
167    pub status: String,
168}
169
170#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
171pub struct ResolvedPartition {
172    pub id: String,
173    #[serde(default, skip_serializing_if = "Option::is_none")]
174    pub title: Option<String>,
175    pub source: String,
176    #[serde(default, skip_serializing_if = "Option::is_none")]
177    pub role: Option<String>,
178    #[serde(default, skip_serializing_if = "Vec::is_empty")]
179    pub roots: Vec<PathBuf>,
180    pub status: String,
181    #[serde(default, skip_serializing_if = "Vec::is_empty")]
182    pub languages: Vec<String>,
183    #[serde(default, skip_serializing_if = "Vec::is_empty")]
184    pub tags: Vec<String>,
185}
186
187#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
188pub struct PackageReport {
189    pub manifest_found: bool,
190    #[serde(default, skip_serializing_if = "Option::is_none")]
191    pub manifest_path: Option<PathBuf>,
192    #[serde(default, skip_serializing_if = "Option::is_none")]
193    pub package_root: Option<PathBuf>,
194    #[serde(default, skip_serializing_if = "Option::is_none")]
195    pub name: Option<String>,
196    pub resolved: ResolvedSources,
197    #[serde(default, skip_serializing_if = "Vec::is_empty")]
198    pub partitions: Vec<ResolvedPartition>,
199    #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
200    pub gates: BTreeMap<String, BTreeMap<String, String>>,
201    #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
202    pub gate_intents: BTreeMap<String, BTreeMap<String, GateIntent>>,
203    #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
204    pub trust: BTreeMap<String, String>,
205    #[serde(default)]
206    pub trust_policy: TrustPolicy,
207    #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
208    pub relation_profiles: BTreeMap<String, RelationPolicy>,
209    #[serde(default, skip_serializing_if = "Vec::is_empty")]
210    pub diagnostics: Vec<EkfDiagnostic>,
211}
212
213#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
214pub struct GateIntent {
215    pub capability: String,
216    pub signal: String,
217    pub description: String,
218}
219
220#[derive(Debug, Clone, PartialEq, Eq)]
221pub struct PackageConfig {
222    pub manifest: Option<Manifest>,
223    pub report: PackageReport,
224}