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