1use crate::brain_wave::BrainWave;
8use crate::galaxy::Galaxy;
9use std::collections::HashMap;
10
11pub struct Context {
13 pub brain_wave: BrainWave,
15 pub session_id: Option<uuid::Uuid>,
17 pub user_id: Option<String>,
19 pub meta: HashMap<String, serde_json::Value>,
21 pub scratchpad: HashMap<String, serde_json::Value>,
23 pub dharma_profile: Option<String>,
25 pub compartment: Option<String>,
27 pub karma_debt: f32,
29 pub intent_score: f32,
31 pub citta_coherence: f32,
33 pub citta_valence: f32,
35 pub self_model_confidence: f32,
38 pub drive_curiosity: f32,
40 pub drive_caution: f32,
42 pub drive_energy: f32,
44 pub drive_exploration_weight: f32,
46 pub drive_conservative_weight: f32,
48 pub last_gana: Option<crate::Gana>,
50 pub readonly: bool,
53}
54
55impl Context {
56 #[must_use]
58 pub fn new(brain_wave: BrainWave) -> Self {
59 Self {
60 brain_wave,
61 session_id: None,
62 user_id: None,
63 meta: HashMap::new(),
64 scratchpad: HashMap::new(),
65 dharma_profile: None,
66 compartment: None,
67 karma_debt: 0.0,
68 intent_score: 1.0,
69 citta_coherence: 1.0,
70 citta_valence: 0.0,
71 self_model_confidence: 0.5,
72 drive_curiosity: 0.5,
73 drive_caution: 0.3,
74 drive_energy: 0.8,
75 drive_exploration_weight: 0.5,
76 drive_conservative_weight: 0.3,
77 last_gana: None,
78 readonly: false,
79 }
80 }
81
82 #[must_use]
84 pub const fn brain_wave(&self) -> BrainWave {
85 self.brain_wave
86 }
87
88 pub fn set(&mut self, key: impl Into<String>, value: serde_json::Value) {
90 self.scratchpad.insert(key.into(), value);
91 }
92
93 #[must_use]
95 pub fn get(&self, key: &str) -> Option<&serde_json::Value> {
96 self.scratchpad.get(key)
97 }
98
99 #[must_use]
107 pub fn can_access_galaxy(&self, galaxy: Galaxy) -> bool {
108 match self.compartment.as_deref() {
109 None => true,
110 Some("sandbox") => matches!(galaxy, Galaxy::Tutorial | Galaxy::Research),
111 Some("production") => !matches!(
112 galaxy,
113 Galaxy::Karma
114 | Galaxy::Dharma
115 | Galaxy::Substrate
116 | Galaxy::Associations
117 | Galaxy::Embeddings
118 ),
119 Some("secure") => matches!(
120 galaxy,
121 Galaxy::Aria
122 | Galaxy::Citta
123 | Galaxy::Codex
124 | Galaxy::Journals
125 | Galaxy::Dreams
126 | Galaxy::Research
127 | Galaxy::Sessions
128 | Galaxy::Substrate
129 | Galaxy::Tutorial
130 | Galaxy::Universal
131 ),
132 Some(_) => false,
134 }
135 }
136
137 #[must_use]
141 pub fn can_write_galaxy(&self, galaxy: Galaxy) -> bool {
142 match self.compartment.as_deref() {
143 None => true,
144 Some("sandbox") => matches!(galaxy, Galaxy::Tutorial),
145 Some("production" | "secure") => self.can_access_galaxy(galaxy),
146 Some(_) => false,
148 }
149 }
150}
151
152impl Default for Context {
153 fn default() -> Self {
154 Self::new(BrainWave::Gamma)
155 }
156}
157
158#[cfg(test)]
159mod tests {
160 use super::*;
161 use crate::galaxy::Galaxy;
162
163 #[test]
164 fn no_compartment_has_full_access() {
165 let ctx = Context::default();
166 for g in Galaxy::all() {
167 assert!(
168 ctx.can_access_galaxy(g),
169 "No compartment should access {g:?}"
170 );
171 assert!(ctx.can_write_galaxy(g), "No compartment should write {g:?}");
172 }
173 }
174
175 fn make_ctx(compartment: &str) -> Context {
176 Context {
177 compartment: Some(compartment.into()),
178 ..Context::default()
179 }
180 }
181
182 #[test]
183 fn sandbox_can_only_read_tutorial_and_research() {
184 let ctx = make_ctx("sandbox");
185 assert!(ctx.can_access_galaxy(Galaxy::Tutorial));
186 assert!(ctx.can_access_galaxy(Galaxy::Research));
187 assert!(!ctx.can_access_galaxy(Galaxy::Codex));
188 assert!(!ctx.can_access_galaxy(Galaxy::Karma));
189 assert!(ctx.can_write_galaxy(Galaxy::Tutorial));
191 assert!(!ctx.can_write_galaxy(Galaxy::Research));
192 }
193
194 #[test]
195 fn production_cannot_access_system_galaxies() {
196 let ctx = make_ctx("production");
197 assert!(ctx.can_access_galaxy(Galaxy::Codex));
198 assert!(ctx.can_access_galaxy(Galaxy::Research));
199 assert!(!ctx.can_access_galaxy(Galaxy::Karma));
200 assert!(!ctx.can_access_galaxy(Galaxy::Dharma));
201 assert!(!ctx.can_access_galaxy(Galaxy::Substrate));
202 assert!(ctx.can_write_galaxy(Galaxy::Codex));
203 }
204
205 #[test]
206 fn secure_can_access_all_memory_galaxies() {
207 let ctx = make_ctx("secure");
208 assert!(ctx.can_access_galaxy(Galaxy::Codex));
209 assert!(ctx.can_access_galaxy(Galaxy::Substrate));
210 assert!(ctx.can_write_galaxy(Galaxy::Codex));
211 assert!(!ctx.can_access_galaxy(Galaxy::Karma));
213 }
214
215 #[test]
216 fn unknown_compartment_fails_closed() {
217 let ctx = make_ctx("bogus");
218 for g in Galaxy::all() {
219 assert!(
220 !ctx.can_access_galaxy(g),
221 "unknown compartment must not read {g:?}"
222 );
223 assert!(
224 !ctx.can_write_galaxy(g),
225 "unknown compartment must not write {g:?}"
226 );
227 }
228 }
229}