Skip to main content

kcode_k1_daemon_lib_testkit/
lib.rs

1#![forbid(unsafe_code)]
2
3const REQUIRED_LINES: &[&str] = &[
4    "kcode-k1-access = \"0.6.2\"",
5    "kcode-k1-access-audio-classifier = \"0.1.0\"",
6    "kcode-k1-access-full-audio = \"0.10.0\"",
7    "kcode-k1-access-launch-nodes = \"0.2.2\"",
8    "kcode-k1-access-persons = \"0.3.0\"",
9    "kcode-k1-access-profiles = \"0.6.2\"",
10    "kcode-k1-audio-classification = \"0.6.0\"",
11    "kcode-k1-audio-classifier = \"0.1.1\"",
12    "kcode-k1-authority-filters = \"0.2.0\"",
13    "kcode-k1-chat-service = \"0.10.9\"",
14    "kcode-k1-codex-adapter = \"0.5.3\"",
15    "kcode-k1-codex-websearch = \"0.2.0\"",
16    "kcode-k1-daemon-code-services = \"0.1.5\"",
17    "kcode-k1-daemon-http-boundary = \"0.1.1\"",
18    "kcode-k1-daemon-provider-config = \"0.1.6\"",
19    "kcode-k1-daemon-startup-error = \"0.1.1\"",
20    "kcode-k1-daemon-web-startup = \"0.1.1\"",
21    "kcode-k1-full-audio = \"0.4.0\"",
22    "kcode-k1-http-access-context = \"0.2.0\"",
23    "kcode-k1-http-access-profile-presentation = \"0.1.0\"",
24    "kcode-k1-http-audio = \"0.4.0\"",
25    "kcode-k1-http-chat = \"0.7.2\"",
26    "kcode-k1-http-kmap = \"0.1.0\"",
27    "kcode-k1-http-launch-nodes = \"0.3.0\"",
28    "kcode-k1-http-people = \"0.9.0\"",
29    "kcode-k1-http-persons = \"0.3.0\"",
30    "kcode-k1-ktool-set-launch-node = \"0.1.1\"",
31    "kcode-k1-ktool-social = \"0.1.1\"",
32    "kcode-k1-launch-nodes = \"0.4.0\"",
33    "kcode-k1-objects = \"0.2.2\"",
34    "kcode-k1-peering = \"0.3.1\"",
35    "kcode-k1-txn-ordering = \"0.5.1\"",
36    "kcode-speaker-v3-analysis = \"0.3.5\"",
37];
38
39const OBSOLETE_LINES: &[&str] = &[
40    "kcode-k1-access = \"0.6.1\"",
41    "kcode-k1-access-full-audio = \"0.9.1\"",
42    "kcode-k1-access-full-audio = \"0.9.4\"",
43    "kcode-k1-access-launch-nodes = \"0.2.0\"",
44    "kcode-k1-audio-classification = \"0.5.9\"",
45    "kcode-k1-audio-classification = \"0.5.10\"",
46    "kcode-k1-chat-service = \"0.3.0\"",
47    "kcode-k1-chat-service = \"0.6.0\"",
48    "kcode-k1-chat-service = \"0.7.0\"",
49    "kcode-k1-chat-service = \"0.8.0\"",
50    "kcode-k1-chat-service = \"0.9.0\"",
51    "kcode-k1-chat-service = \"0.10.0\"",
52    "kcode-k1-chat-service = \"0.10.1\"",
53    "kcode-k1-chat-service = \"0.10.2\"",
54    "kcode-k1-chat-service = \"0.10.3\"",
55    "kcode-k1-chat-service = \"0.10.4\"",
56    "kcode-k1-chat-service = \"0.10.5\"",
57    "kcode-k1-chat-service = \"0.10.6\"",
58    "kcode-k1-chat-service = \"0.10.7\"",
59    "kcode-k1-chat-service = \"0.10.8\"",
60    "kcode-k1-codex-adapter = \"0.5.0\"",
61    "kcode-k1-codex-adapter = \"0.5.1\"",
62    "kcode-k1-codex-websearch = \"0.1.0\"",
63    "kcode-k1-daemon-code-services = \"0.1.0\"",
64    "kcode-k1-daemon-code-services = \"0.1.1\"",
65    "kcode-k1-daemon-code-services = \"0.1.2\"",
66    "kcode-k1-daemon-code-services = \"0.1.3\"",
67    "kcode-k1-daemon-code-services = \"0.1.4\"",
68    "kcode-k1-daemon-http-boundary = \"0.1.0\"",
69    "kcode-k1-daemon-provider-config = \"0.1.4\"",
70    "kcode-k1-daemon-provider-config = \"0.1.5\"",
71    "kcode-k1-daemon-startup-error = \"0.1.0\"",
72    "kcode-k1-daemon-web-startup = \"0.1.0\"",
73    "kcode-k1-full-audio = \"0.3.7\"",
74    "kcode-k1-http-audio = \"0.3.0\"",
75    "kcode-k1-http-audio = \"0.3.1\"",
76    "kcode-k1-http-chat = \"0.2.0\"",
77    "kcode-k1-http-chat = \"0.5.0\"",
78    "kcode-k1-http-chat = \"0.6.0\"",
79    "kcode-k1-http-chat = \"0.6.1\"",
80    "kcode-k1-http-chat = \"0.7.0\"",
81    "kcode-k1-http-chat = \"0.7.1\"",
82    "kcode-k1-http-launch-nodes = \"0.2.0\"",
83    "kcode-k1-ktool-set-launch-node = \"0.1.0\"",
84    "kcode-k1-ktool-social = \"0.1.0\"",
85    "kcode-k1-launch-nodes = \"0.3.0\"",
86    "kcode-k1-objects = \"0.2.1\"",
87    "kcode-k1-peering = \"0.3.0\"",
88    "kcode-k1-web-code-ktool-service = \"0.1.1\"",
89    "kcode-k1-web-http = \"0.1.0\"",
90];
91
92const REQUIRED_SOURCE: &[&str] = &[
93    "AudioClassification::open(",
94    ".shutdown()",
95    "kcode_k1_http_audio::authenticated_routes",
96    "SocialKtools::new(",
97    "SetLaunchNodeKtool::new(",
98    "let web = open(",
99    "web.router()",
100    "web.projection()",
101    "CodeServices::open(",
102    ".into_parts()",
103    "K1ChatService::open_with_social_and_set_launch_node_and_rust_code_and_web_code(",
104    "with_cause(\"daemon files\")",
105    "with_cause(\"Code services\")",
106    "redacted_stage(\"Vault\")",
107    "redacted_stage(\"Gemini API key\")",
108    "redacted_stage(\"Gemini client\")",
109];
110
111const PROHIBITED_SOURCE: &[&str] = &[
112    "audio-classification-v2",
113    "http_audio_artifacts",
114    "retry_fragment",
115    "artifact_route",
116    "open_router(",
117    "RustCodeKtoolService::new(",
118    "K1WebCodeKtoolService::new(",
119    "let chat = K1ChatService::open(",
120    "K1ChatService::open_with_social(",
121    "K1ChatService::open_with_social_and_set_launch_node(",
122    ".map_err(stage(",
123    "StartupError::Stage(",
124];
125
126pub fn verify_manifest(manifest: &str) {
127    for required in REQUIRED_LINES {
128        assert!(
129            manifest.lines().any(|line| line == *required),
130            "missing required manifest line: {required}"
131        );
132    }
133    for obsolete in OBSOLETE_LINES {
134        assert!(
135            !manifest.lines().any(|line| line == *obsolete),
136            "obsolete manifest line: {obsolete}"
137        );
138    }
139    assert!(
140        !manifest.lines().any(|line| line
141            .trim_start()
142            .starts_with("kcode-k1-http-audio-artifacts")),
143        "artifact manifest selection"
144    );
145    assert!(
146        !manifest.lines().any(|line| line.contains(" = \"=")),
147        "manifest contains an exact internal pin"
148    );
149}
150
151pub fn verify_source(source: &str) {
152    for required in REQUIRED_SOURCE {
153        assert!(
154            source.contains(required),
155            "missing required source evidence: {required}"
156        );
157    }
158    for prohibited in PROHIBITED_SOURCE {
159        assert!(
160            !source.contains(prohibited),
161            "prohibited source token: {prohibited}"
162        );
163    }
164}
165
166#[cfg(test)]
167mod tests {
168    use super::*;
169
170    fn good_manifest() -> String {
171        REQUIRED_LINES.join("\n")
172    }
173
174    fn good_source() -> &'static str {
175        "AudioClassification::open(\nservice.shutdown()\nkcode_k1_http_audio::authenticated_routes\nSocialKtools::new(\nSetLaunchNodeKtool::new(\nlet web = open(\nweb.router()\nweb.projection()\nCodeServices::open(\ncode_services.into_parts()\nK1ChatService::open_with_social_and_set_launch_node_and_rust_code_and_web_code(\nwith_cause(\"daemon files\")\nwith_cause(\"Code services\")\nredacted_stage(\"Vault\")\nredacted_stage(\"Gemini API key\")\nredacted_stage(\"Gemini client\")"
176    }
177
178    #[test]
179    fn accepts_current_inputs() {
180        verify_manifest(&good_manifest());
181        verify_source(good_source());
182    }
183
184    #[test]
185    fn rejects_missing_audio_requirements() {
186        for line in [
187            "kcode-k1-access-full-audio = \"0.10.0\"",
188            "kcode-k1-audio-classification = \"0.6.0\"",
189            "kcode-k1-full-audio = \"0.4.0\"",
190            "kcode-k1-http-audio = \"0.4.0\"",
191            "kcode-k1-peering = \"0.3.1\"",
192            "kcode-speaker-v3-analysis = \"0.3.5\"",
193        ] {
194            assert!(
195                std::panic::catch_unwind(|| verify_manifest(&good_manifest().replace(line, "")))
196                    .is_err()
197            );
198        }
199    }
200
201    #[test]
202    fn rejects_missing_code_and_error_requirements() {
203        for line in [
204            "kcode-k1-chat-service = \"0.10.9\"",
205            "kcode-k1-daemon-code-services = \"0.1.5\"",
206            "kcode-k1-daemon-startup-error = \"0.1.1\"",
207            "kcode-k1-daemon-web-startup = \"0.1.1\"",
208            "kcode-k1-objects = \"0.2.2\"",
209        ] {
210            assert!(
211                std::panic::catch_unwind(|| verify_manifest(&good_manifest().replace(line, "")))
212                    .is_err()
213            );
214        }
215    }
216
217    #[test]
218    fn rejects_missing_source_evidence() {
219        for evidence in REQUIRED_SOURCE {
220            assert!(
221                std::panic::catch_unwind(|| verify_source(&good_source().replace(evidence, "")))
222                    .is_err()
223            );
224        }
225    }
226
227    #[test]
228    fn rejects_prohibited_source_tokens() {
229        for token in PROHIBITED_SOURCE {
230            assert!(
231                std::panic::catch_unwind(|| verify_source(&format!("{} {token}", good_source())))
232                    .is_err()
233            );
234        }
235    }
236
237    #[test]
238    fn rejects_artifact_package_selection() {
239        assert!(
240            std::panic::catch_unwind(|| verify_manifest(&format!(
241                "{}\n kcode-k1-http-audio-artifacts = \"0.4.0\"",
242                good_manifest()
243            )))
244            .is_err()
245        );
246    }
247
248    #[test]
249    fn rejects_old_audio_and_displaced_composition_lines() {
250        for line in [
251            "kcode-k1-audio-classification = \"0.5.10\"",
252            "kcode-k1-full-audio = \"0.3.7\"",
253            "kcode-k1-access-full-audio = \"0.9.4\"",
254            "kcode-k1-http-audio = \"0.3.1\"",
255            "kcode-k1-peering = \"0.3.0\"",
256            "kcode-k1-chat-service = \"0.10.8\"",
257            "kcode-k1-daemon-code-services = \"0.1.4\"",
258            "kcode-k1-daemon-startup-error = \"0.1.0\"",
259            "kcode-k1-daemon-web-startup = \"0.1.0\"",
260            "kcode-k1-objects = \"0.2.1\"",
261        ] {
262            assert!(
263                std::panic::catch_unwind(|| verify_manifest(&format!(
264                    "{}\n{line}",
265                    good_manifest()
266                )))
267                .is_err()
268            );
269        }
270    }
271
272    #[test]
273    fn full_chat_composition_does_not_match_former_names() {
274        let current =
275            "K1ChatService::open_with_social_and_set_launch_node_and_rust_code_and_web_code(";
276        assert!(!current.contains("K1ChatService::open_with_social("));
277        assert!(!current.contains("K1ChatService::open_with_social_and_set_launch_node("));
278    }
279
280    #[test]
281    fn rejects_blanket_error_discarding() {
282        for token in [
283            ".map_err(stage(\"Objects\"))",
284            "StartupError::Stage(\"public origin\")",
285        ] {
286            assert!(
287                std::panic::catch_unwind(|| verify_source(&format!("{} {token}", good_source())))
288                    .is_err()
289            );
290        }
291    }
292
293    #[test]
294    fn rejects_exact_internal_pin() {
295        assert!(
296            std::panic::catch_unwind(|| verify_manifest(&format!(
297                "{}\nkcode-k1-peering = \"=0.3.1\"",
298                good_manifest()
299            )))
300            .is_err()
301        );
302    }
303
304    #[test]
305    fn rejects_unrelated_obsolete_line() {
306        assert!(
307            std::panic::catch_unwind(|| verify_manifest(&format!(
308                "{}\nkcode-k1-http-chat = \"0.7.1\"",
309                good_manifest()
310            )))
311            .is_err()
312        );
313    }
314}