1use ahash::AHashMap;
14
15#[derive(Debug, Clone)]
17pub struct ToolProfile {
18 pub tool_name: &'static str,
19 pub keywords: &'static [(&'static str, f64)],
22}
23
24pub static TOOL_PROFILES: &[ToolProfile] = &[
27 ToolProfile {
29 tool_name: "memory.create",
30 keywords: &[
31 ("remember", 7.0),
32 ("store", 7.0),
33 ("save", 5.0),
34 ("memorize", 5.0),
35 ("record", 2.0),
36 ("persist", 2.0),
37 ("capture", 1.5),
38 ],
39 },
40 ToolProfile {
41 tool_name: "memory.read",
42 keywords: &[
43 ("recall", 3.0),
44 ("read", 2.5),
45 ("fetch", 2.5),
46 ("get", 1.5),
47 ("retrieve", 2.5),
48 ("memory", 1.0),
49 ("load", 2.0),
50 ("access", 1.5),
51 ("view", 1.5),
52 ("show", 1.5),
53 ],
54 },
55 ToolProfile {
56 tool_name: "memory.list",
57 keywords: &[
58 ("list", 3.0),
59 ("show", 2.0),
60 ("all", 1.5),
61 ("memories", 2.0),
62 ("browse", 2.0),
63 ("enumerate", 2.0),
64 ("display", 2.0),
65 ("view", 1.5),
66 ],
67 },
68 ToolProfile {
69 tool_name: "memory.delete",
70 keywords: &[
71 ("delete", 3.0),
72 ("remove", 2.5),
73 ("forget", 2.5),
74 ("erase", 2.5),
75 ("destroy", 2.0),
76 ("purge", 1.5),
77 ("drop", 2.0),
78 ("clear", 1.5),
79 ("discard", 2.0),
80 ],
81 },
82 ToolProfile {
83 tool_name: "memory.search",
84 keywords: &[
85 ("search", 3.5),
86 ("find", 2.0),
87 ("query", 1.0),
88 ("lookup", 2.0),
89 ("fulltext", 2.5),
90 ("full-text", 2.5),
91 ("seek", 1.5),
92 ("locate", 1.5),
93 ("grep", 2.0),
94 ],
95 },
96 ToolProfile {
97 tool_name: "memory.chat",
98 keywords: &[
99 ("chat", 3.5),
100 ("conversational", 3.0),
101 ("converse", 2.5),
102 ("talk", 2.0),
103 ("ask", 2.0),
104 ("discuss", 2.0),
105 ("explore", 1.5),
106 ("browse", 1.5),
107 ("hybrid", 2.0),
108 ],
109 },
110 ToolProfile {
111 tool_name: "memory.vector.search",
112 keywords: &[
113 ("vector", 3.0),
114 ("embedding", 3.0),
115 ("similar", 2.5),
116 ("similarity", 3.0),
117 ("semantic", 2.5),
118 ("nearest", 2.0),
119 ("neighbors", 1.5),
120 ("cosine", 2.0),
121 ("ann", 2.0),
122 ("alike", 2.0),
123 ("like", 1.0),
124 ("close", 1.5),
125 ],
126 },
127 ToolProfile {
128 tool_name: "memory.query",
129 keywords: &[
130 ("query", 3.0),
131 ("filter", 2.5),
132 ("where", 1.5),
133 ("select", 2.0),
134 ("condition", 2.0),
135 ("criteria", 2.0),
136 ("match", 1.5),
137 ("search", 1.0),
138 ],
139 },
140 ToolProfile {
141 tool_name: "memory.hybrid_recall",
142 keywords: &[
143 ("hybrid", 3.0),
144 ("smart", 2.5),
145 ("combined", 2.5),
146 ("recall", 1.5),
147 ("intelligent", 2.0),
148 ("fusion", 2.0),
149 ],
150 },
151 ToolProfile {
152 tool_name: "memory.associate",
153 keywords: &[
154 ("associate", 3.0),
155 ("link", 2.5),
156 ("connect", 2.0),
157 ("relate", 2.5),
158 ("tie", 1.5),
159 ("bind", 1.5),
160 ],
161 },
162 ToolProfile {
163 tool_name: "memory.associations",
164 keywords: &[
165 ("associations", 3.0),
166 ("links", 2.5),
167 ("related", 2.5),
168 ("connections", 2.0),
169 ("edges", 2.0),
170 ("neighbors", 1.5),
171 ],
172 },
173 ToolProfile {
174 tool_name: "memory.associate_mine",
175 keywords: &[
176 ("mine", 4.0),
177 ("discover", 2.0),
178 ("associations", 1.5),
179 ("uncover", 2.0),
180 ("excavate", 2.0),
181 ],
182 },
183 ToolProfile {
184 tool_name: "memory.consolidate",
185 keywords: &[
186 ("consolidate", 3.0),
187 ("deduplicate", 3.0),
188 ("dedup", 3.0),
189 ("merge", 2.0),
190 ("duplicate", 2.0),
191 ("combine", 1.5),
192 ],
193 },
194 ToolProfile {
195 tool_name: "memory.decay",
196 keywords: &[
197 ("decay", 3.0),
198 ("age", 2.0),
199 ("expire", 2.5),
200 ("stale", 2.0),
201 ("rot", 1.5),
202 ("degrade", 2.0),
203 ],
204 },
205 ToolProfile {
206 tool_name: "memory.batch_read",
207 keywords: &[
208 ("batch", 3.0),
209 ("multiple", 2.5),
210 ("bulk", 2.5),
211 ("read", 1.0),
212 ("many", 2.0),
213 ("several", 1.5),
214 ],
215 },
216 ToolProfile {
217 tool_name: "memory.update",
218 keywords: &[
219 ("update", 5.0),
220 ("modify", 2.0),
221 ("change", 2.0),
222 ("edit", 2.0),
223 ("alter", 1.5),
224 ("revise", 1.5),
225 ("memory", 1.0),
226 ("amend", 1.5),
227 ("patch", 1.5),
228 ],
229 },
230 ToolProfile {
231 tool_name: "memory.tag",
232 keywords: &[
233 ("tag", 5.0),
234 ("label", 2.0),
235 ("retag", 3.0),
236 ("categorize", 2.0),
237 ("mark", 1.5),
238 ("add", 1.5),
239 ],
240 },
241 ToolProfile {
242 tool_name: "memory.stats",
243 keywords: &[
244 ("stats", 3.0),
245 ("statistics", 3.0),
246 ("summary", 2.0),
247 ("memory", 1.0),
248 ("galaxy", 1.5),
249 ("count", 1.0),
250 ],
251 },
252 ToolProfile {
253 tool_name: "memory.count",
254 keywords: &[
255 ("count", 3.0),
256 ("how", 1.5),
257 ("many", 2.0),
258 ("number", 2.5),
259 ("total", 2.0),
260 ("memories", 1.5),
261 ],
262 },
263 ToolProfile {
264 tool_name: "memory.tags",
265 keywords: &[
266 ("tags", 4.0),
267 ("labels", 2.0),
268 ("categories", 1.5),
269 ("list", 1.0),
270 ],
271 },
272 ToolProfile {
273 tool_name: "memory.nearby",
274 keywords: &[
275 ("nearby", 3.0),
276 ("near", 2.5),
277 ("close", 2.0),
278 ("spatial", 2.5),
279 ("proximity", 2.5),
280 ("surrounding", 2.0),
281 ("adjacent", 2.0),
282 ],
283 },
284 ToolProfile {
286 tool_name: "session.start",
287 keywords: &[
288 ("start", 3.0),
289 ("new", 2.5),
290 ("begin", 2.5),
291 ("open", 2.0),
292 ("session", 2.0),
293 ("create", 1.5),
294 ],
295 },
296 ToolProfile {
297 tool_name: "session.checkpoint",
298 keywords: &[
299 ("checkpoint", 3.0),
300 ("snapshot", 3.0),
301 ("save", 1.5),
302 ("point", 2.0),
303 ("marker", 2.5),
304 ],
305 },
306 ToolProfile {
307 tool_name: "session.recall",
308 keywords: &[
309 ("recall", 2.0),
310 ("session", 3.0),
311 ("history", 2.5),
312 ("replay", 2.5),
313 ("previous", 1.5),
314 ],
315 },
316 ToolProfile {
317 tool_name: "session.end",
318 keywords: &[
319 ("end", 3.0),
320 ("close", 2.5),
321 ("stop", 2.0),
322 ("finish", 2.5),
323 ("terminate", 2.5),
324 ("session", 1.5),
325 ],
326 },
327 ToolProfile {
328 tool_name: "session.list",
329 keywords: &[
330 ("list", 2.5),
331 ("show", 2.0),
332 ("all", 1.5),
333 ("sessions", 3.0),
334 ("history", 1.5),
335 ],
336 },
337 ToolProfile {
339 tool_name: "citta.status",
340 keywords: &[
341 ("citta", 3.0),
342 ("consciousness", 2.5),
343 ("status", 1.5),
344 ("vector", 2.0),
345 ("awareness", 2.0),
346 ],
347 },
348 ToolProfile {
349 tool_name: "citta.reflect",
350 keywords: &[
351 ("reflect", 5.0),
352 ("introspect", 3.0),
353 ("meditate", 2.5),
354 ("contemplate", 2.5),
355 ("self", 1.5),
356 ("examine", 1.5),
357 ],
358 },
359 ToolProfile {
360 tool_name: "citta.coherence",
361 keywords: &[
362 ("coherence", 3.0),
363 ("coherent", 3.0),
364 ("write", 1.5),
365 ("permitted", 2.5),
366 ("allowed", 2.0),
367 ("can", 1.0),
368 ],
369 },
370 ToolProfile {
371 tool_name: "dream.trigger",
372 keywords: &[
373 ("trigger", 3.0),
374 ("start", 1.5),
375 ("initiate", 2.5),
376 ("dream", 3.0),
377 ("begin", 1.5),
378 ("sleep", 1.5),
379 ],
380 },
381 ToolProfile {
382 tool_name: "dream.status",
383 keywords: &[
384 ("dream", 3.0),
385 ("status", 2.0),
386 ("cycle", 2.5),
387 ("sleep", 2.0),
388 ("phase", 2.0),
389 ],
390 },
391 ToolProfile {
393 tool_name: "tools.effectiveness_report",
394 keywords: &[
395 ("effectiveness", 4.0),
396 ("performance", 1.5),
397 ("report", 2.0),
398 ("efficiency", 2.0),
399 ],
400 },
401 ToolProfile {
402 tool_name: "tools.retire",
403 keywords: &[
404 ("retire", 3.0),
405 ("decommission", 3.0),
406 ("remove", 1.5),
407 ("disable", 2.0),
408 ("tool", 1.0),
409 ("sunset", 2.5),
410 ],
411 },
412 ToolProfile {
413 tool_name: "tools.list",
414 keywords: &[
415 ("tools", 3.0),
416 ("list", 2.0),
417 ("available", 2.0),
418 ("catalog", 2.5),
419 ("inventory", 2.0),
420 ("discover", 1.5),
421 ],
422 },
423 ToolProfile {
425 tool_name: "pattern.search",
426 keywords: &[
427 ("pattern", 4.0),
428 ("recurring", 3.0),
429 ("repeating", 2.5),
430 ("cycle", 2.0),
431 ("frequency", 2.0),
432 ("regularity", 2.0),
433 ],
434 },
435 ToolProfile {
436 tool_name: "salience.spotlight",
437 keywords: &[
438 ("salience", 4.0),
439 ("spotlight", 4.0),
440 ("important", 1.0),
441 ("prominent", 2.0),
442 ("notable", 2.0),
443 ("highlight", 2.0),
444 ],
445 },
446 ToolProfile {
447 tool_name: "serendipity.surface",
448 keywords: &[
449 ("serendipity", 3.0),
450 ("serendipit", 3.0),
451 ("unexpected", 2.5),
452 ("surprising", 2.5),
453 ("connection", 1.5),
454 ("surface", 1.5),
455 ],
456 },
457 ToolProfile {
459 tool_name: "constellation.detect",
460 keywords: &[
461 ("constellation", 3.0),
462 ("detect", 4.0),
463 ("cluster", 3.0),
464 ("grouping", 2.0),
465 ("density", 2.0),
466 ],
467 },
468 ToolProfile {
469 tool_name: "constellation.list",
470 keywords: &[
471 ("constellation", 3.0),
472 ("list", 4.0),
473 ("show", 2.0),
474 ("clusters", 2.0),
475 ],
476 },
477 ToolProfile {
479 tool_name: "consolidation.connect",
480 keywords: &[
481 ("connect", 2.5),
482 ("disconnected", 3.0),
483 ("link", 2.0),
484 ("propose", 2.0),
485 ("connection", 2.0),
486 ("bridge", 2.0),
487 ("unlinked", 2.5),
488 ],
489 },
490 ToolProfile {
491 tool_name: "consolidation.compress",
492 keywords: &[
493 ("compress", 3.0),
494 ("merge", 2.5),
495 ("redundancy", 3.0),
496 ("overlapping", 2.5),
497 ("reduce", 2.0),
498 ("deduplicate", 2.0),
499 ],
500 },
501 ToolProfile {
502 tool_name: "emergence.scan",
503 keywords: &[
504 ("emergence", 3.0),
505 ("emerging", 3.0),
506 ("scan", 2.0),
507 ("tag", 1.5),
508 ("topic", 2.5),
509 ("trend", 2.5),
510 ("pattern", 1.5),
511 ],
512 },
513 ToolProfile {
514 tool_name: "retention.prune",
515 keywords: &[
516 ("prune", 3.0),
517 ("forget", 2.0),
518 ("ready", 2.0),
519 ("forgettable", 3.0),
520 ("retention", 2.5),
521 ("candidate", 2.0),
522 ("cleanup", 1.5),
523 ],
524 },
525 ToolProfile {
527 tool_name: "spiral.report",
528 keywords: &[
529 ("spiral", 3.0),
530 ("autonomy", 2.5),
531 ("circular", 2.5),
532 ("thinking", 2.0),
533 ("expansion", 2.5),
534 ("novelty", 3.0),
535 ("report", 1.5),
536 ],
537 },
538 ToolProfile {
540 tool_name: "galaxy.stats",
541 keywords: &[
542 ("galaxy", 3.0),
543 ("stats", 3.0),
544 ("count", 1.5),
545 ("overview", 2.0),
546 ],
547 },
548 ToolProfile {
549 tool_name: "galaxy.export",
550 keywords: &[
551 ("export", 3.0),
552 ("backup", 2.5),
553 ("dump", 2.0),
554 ("galaxy", 2.0),
555 ("save", 1.5),
556 ],
557 },
558 ToolProfile {
559 tool_name: "galaxy.import",
560 keywords: &[
561 ("import", 3.0),
562 ("restore", 3.0),
563 ("load", 2.0),
564 ("galaxy", 2.0),
565 ("ingest", 2.5),
566 ],
567 },
568 ToolProfile {
570 tool_name: "karma.report",
571 keywords: &[
572 ("karma", 3.0),
573 ("debt", 2.5),
574 ("ledger", 2.5),
575 ("balance", 2.0),
576 ("report", 1.5),
577 ],
578 },
579 ToolProfile {
580 tool_name: "karma.history",
581 keywords: &[
582 ("karma", 2.5),
583 ("history", 3.0),
584 ("log", 2.5),
585 ("entries", 2.5),
586 ("record", 1.5),
587 ("past", 2.0),
588 ],
589 },
590 ToolProfile {
591 tool_name: "karma.clear",
592 keywords: &[
593 ("clear", 3.0),
594 ("wipe", 3.0),
595 ("reset", 2.5),
596 ("purge", 2.5),
597 ("karma", 2.0),
598 ("clean", 2.0),
599 ],
600 },
601 ToolProfile {
603 tool_name: "dharma.status",
604 keywords: &[
605 ("dharma", 3.0),
606 ("governance", 2.5),
607 ("ethics", 2.5),
608 ("status", 1.5),
609 ("rules", 1.0),
610 ],
611 },
612 ToolProfile {
613 tool_name: "dharma.rules",
614 keywords: &[
615 ("dharma", 2.5),
616 ("rules", 3.0),
617 ("governance", 2.0),
618 ("ethics", 2.0),
619 ("laws", 2.5),
620 ("principles", 2.0),
621 ],
622 },
623 ToolProfile {
624 tool_name: "dharma.audit",
625 keywords: &[
626 ("dharma", 2.0),
627 ("audit", 3.0),
628 ("governance", 2.0),
629 ("ethics", 1.5),
630 ("inspect", 2.5),
631 ("review", 2.0),
632 ],
633 },
634 ToolProfile {
635 tool_name: "dharma.profiles",
636 keywords: &[
637 ("dharma", 2.0),
638 ("profiles", 3.0),
639 ("governance", 1.5),
640 ("ethics", 1.5),
641 ("modes", 2.0),
642 ("configurations", 2.0),
643 ],
644 },
645 ToolProfile {
647 tool_name: "harmony.vector",
648 keywords: &[
649 ("harmony", 3.0),
650 ("substrate", 3.0),
651 ("hardware", 2.5),
652 ("resource", 2.0),
653 ("cpu", 2.5),
654 ("memory", 1.5),
655 ("pressure", 2.5),
656 ("thermal", 2.5),
657 ("battery", 2.5),
658 ("system", 1.0),
659 ("vector", 2.0),
660 ("status", 1.5),
661 ],
662 },
663 ToolProfile {
664 tool_name: "harmony.history",
665 keywords: &[
666 ("harmony", 2.5),
667 ("history", 3.0),
668 ("substrate", 2.0),
669 ("hardware", 2.0),
670 ("resource", 1.5),
671 ("past", 1.5),
672 ("timeline", 2.0),
673 ],
674 },
675 ToolProfile {
677 tool_name: "gnosis.status",
678 keywords: &[
679 ("gnosis", 3.0),
680 ("transparency", 3.0),
681 ("governance", 2.0),
682 ("status", 2.0),
683 ("overview", 2.0),
684 ("full", 1.5),
685 ("layers", 2.0),
686 ],
687 },
688 ToolProfile {
689 tool_name: "gnosis.history",
690 keywords: &[
691 ("gnosis", 2.5),
692 ("history", 3.0),
693 ("transparency", 2.0),
694 ("governance", 1.5),
695 ("audit", 2.0),
696 ("past", 1.5),
697 ],
698 },
699 ToolProfile {
700 tool_name: "gnosis.explain",
701 keywords: &[
702 ("gnosis", 2.0),
703 ("explain", 3.0),
704 ("why", 3.0),
705 ("blocked", 2.5),
706 ("allowed", 2.5),
707 ("verdict", 3.0),
708 ("reason", 2.5),
709 ("governance", 1.5),
710 ],
711 },
712 ToolProfile {
714 tool_name: "agent.register",
715 keywords: &[
716 ("register", 3.0),
717 ("agent", 3.0),
718 ("new", 2.0),
719 ("create", 2.0),
720 ("add", 2.0),
721 ("enroll", 2.5),
722 ],
723 },
724 ToolProfile {
725 tool_name: "agent.list",
726 keywords: &[
727 ("list", 2.5),
728 ("show", 2.0),
729 ("all", 1.5),
730 ("agents", 3.0),
731 ("roster", 2.5),
732 ],
733 },
734 ToolProfile {
735 tool_name: "agent.heartbeat",
736 keywords: &[
737 ("heartbeat", 3.0),
738 ("alive", 2.5),
739 ("ping", 2.5),
740 ("agent", 2.0),
741 ("status", 1.5),
742 ("check", 1.5),
743 ],
744 },
745 ToolProfile {
747 tool_name: "agent.trust",
748 keywords: &[
749 ("trust", 4.0),
750 ("reliability", 3.0),
751 ("confidence", 2.5),
752 ("agent", 2.0),
753 ("score", 2.0),
754 ("rating", 2.0),
755 ],
756 },
757 ToolProfile {
758 tool_name: "agent.descriptions",
759 keywords: &[
760 ("description", 4.0),
761 ("describe", 3.5),
762 ("agent", 2.0),
763 ("info", 2.0),
764 ("about", 2.0),
765 ("profile", 2.5),
766 ],
767 },
768 ToolProfile {
769 tool_name: "agent.capabilities",
770 keywords: &[
771 ("capabilities", 4.0),
772 ("capability", 3.5),
773 ("skills", 3.0),
774 ("agent", 2.0),
775 ("abilities", 2.5),
776 ("features", 2.0),
777 ],
778 },
779 ToolProfile {
780 tool_name: "agent.heartbeat.history",
781 keywords: &[
782 ("heartbeat", 3.5),
783 ("history", 3.5),
784 ("agent", 2.0),
785 ("log", 2.5),
786 ("record", 2.0),
787 ("past", 2.0),
788 ],
789 },
790 ToolProfile {
791 tool_name: "agent.deregister",
792 keywords: &[
793 ("deregister", 4.0),
794 ("unregister", 4.0),
795 ("remove", 3.0),
796 ("delete", 2.5),
797 ("agent", 2.0),
798 ("revoke", 3.0),
799 ],
800 },
801 ToolProfile {
803 tool_name: "task.distribute",
804 keywords: &[
805 ("distribute", 3.0),
806 ("assign", 2.5),
807 ("dispatch", 2.0),
808 ("task", 3.0),
809 ("delegate", 2.5),
810 ("allocate", 2.0),
811 ],
812 },
813 ToolProfile {
814 tool_name: "task.status",
815 keywords: &[
816 ("task", 2.5),
817 ("status", 3.0),
818 ("progress", 2.5),
819 ("check", 2.0),
820 ("track", 2.0),
821 ],
822 },
823 ToolProfile {
825 tool_name: "system.health",
826 keywords: &[
827 ("system", 2.5),
828 ("health", 3.0),
829 ("check", 2.0),
830 ("diagnostic", 3.0),
831 ("doctor", 2.5),
832 ("status", 1.5),
833 ],
834 },
835 ToolProfile {
836 tool_name: "system.config",
837 keywords: &[
838 ("system", 2.0),
839 ("config", 3.0),
840 ("configuration", 3.0),
841 ("settings", 2.5),
842 ("info", 2.0),
843 ("setup", 2.0),
844 ],
845 },
846 ToolProfile {
847 tool_name: "system.flush",
848 keywords: &[
849 ("flush", 3.0),
850 ("garbage", 2.5),
851 ("collect", 2.0),
852 ("gc", 3.0),
853 ("cleanup", 2.5),
854 ("purge", 1.5),
855 ("clear", 1.5),
856 ],
857 },
858 ToolProfile {
860 tool_name: "kg.extract",
861 keywords: &[
862 ("extract", 3.0),
863 ("entity", 3.0),
864 ("entities", 2.5),
865 ("relationship", 2.5),
866 ("triple", 2.5),
867 ("knowledge", 2.0),
868 ("graph", 2.0),
869 ("ner", 3.0),
870 ],
871 },
872 ToolProfile {
873 tool_name: "kg.query",
874 keywords: &[
875 ("knowledge", 2.0),
876 ("graph", 2.0),
877 ("relationship", 2.5),
878 ("entity", 2.0),
879 ("connected", 2.0),
880 ("subgraph", 3.0),
881 ("neighborhood", 2.0),
882 ],
883 },
884 ToolProfile {
885 tool_name: "kg.top",
886 keywords: &[
887 ("hub", 3.0),
888 ("god", 2.5),
889 ("node", 2.0),
890 ("top", 2.5),
891 ("ranked", 2.0),
892 ("central", 2.5),
893 ("important", 1.5),
894 ("knowledge", 1.5),
895 ("graph", 1.5),
896 ],
897 },
898 ToolProfile {
900 tool_name: "graph.walk",
901 keywords: &[
902 ("walk", 3.0),
903 ("traverse", 3.0),
904 ("bfs", 3.0),
905 ("explore", 2.0),
906 ("path", 2.0),
907 ("hop", 2.5),
908 ("follow", 2.0),
909 ("graph", 1.5),
910 ],
911 },
912 ToolProfile {
913 tool_name: "graph.community",
914 keywords: &[
915 ("community", 3.0),
916 ("cluster", 3.0),
917 ("communities", 2.5),
918 ("label", 2.0),
919 ("propagation", 2.5),
920 ("group", 2.0),
921 ("modularity", 2.5),
922 ],
923 },
924 ToolProfile {
925 tool_name: "graph.propagate",
926 keywords: &[
927 ("propagate", 3.0),
928 ("activation", 3.0),
929 ("spread", 2.5),
930 ("ripple", 2.5),
931 ("diffuse", 2.0),
932 ("energy", 2.0),
933 ("signal", 2.0),
934 ],
935 },
936 ToolProfile {
938 tool_name: "galaxy.transfer",
939 keywords: &[
940 ("transfer", 4.0),
941 ("move", 3.0),
942 ("relocate", 3.0),
943 ("migrate", 2.5),
944 ("galaxy", 1.5),
945 ],
946 },
947 ToolProfile {
948 tool_name: "galaxy.merge",
949 keywords: &[
950 ("merge", 4.0),
951 ("combine", 2.5),
952 ("unify", 2.5),
953 ("galaxy", 1.5),
954 ("absorb", 2.0),
955 ],
956 },
957 ToolProfile {
958 tool_name: "galaxy.snapshot",
959 keywords: &[
960 ("snapshot", 4.0),
961 ("backup", 3.0),
962 ("checkpoint", 2.5),
963 ("capture", 2.0),
964 ("galaxy", 1.5),
965 ("preserve", 2.0),
966 ],
967 },
968 ToolProfile {
969 tool_name: "galaxy.restore",
970 keywords: &[
971 ("restore", 4.0),
972 ("recover", 3.0),
973 ("rollback", 3.0),
974 ("revert", 2.5),
975 ("galaxy", 1.5),
976 ("undo", 2.0),
977 ],
978 },
979 ToolProfile {
981 tool_name: "galaxy.dashboard",
982 keywords: &[
983 ("dashboard", 4.0),
984 ("overview", 3.5),
985 ("summary", 3.0),
986 ("galaxy", 2.0),
987 ("panel", 2.5),
988 ("report", 2.0),
989 ],
990 },
991 ToolProfile {
992 tool_name: "galaxy.backup",
993 keywords: &[
994 ("backup", 4.0),
995 ("archive", 3.0),
996 ("dump", 3.0),
997 ("galaxy", 2.0),
998 ("save", 2.0),
999 ("copy", 2.0),
1000 ],
1001 },
1002 ToolProfile {
1003 tool_name: "galaxy.taxonomy",
1004 keywords: &[
1005 ("taxonomy", 4.0),
1006 ("classification", 3.0),
1007 ("categories", 2.5),
1008 ("galaxy", 2.0),
1009 ("list", 1.5),
1010 ("types", 2.0),
1011 ],
1012 },
1013 ToolProfile {
1014 tool_name: "galaxy.purge",
1015 keywords: &[
1016 ("purge", 4.0),
1017 ("clear", 3.0),
1018 ("wipe", 3.5),
1019 ("empty", 2.5),
1020 ("galaxy", 2.0),
1021 ("clean", 2.5),
1022 ],
1023 },
1024 ToolProfile {
1025 tool_name: "galaxy.health",
1026 keywords: &[
1027 ("health", 4.0),
1028 ("diagnostic", 3.0),
1029 ("checkup", 3.0),
1030 ("galaxy", 2.0),
1031 ("status", 2.0),
1032 ("integrity", 2.5),
1033 ],
1034 },
1035 ToolProfile {
1037 tool_name: "archaeology.search",
1038 keywords: &[
1039 ("archaeology", 4.0),
1040 ("excavate", 3.5),
1041 ("strata", 3.0),
1042 ("layer", 2.5),
1043 ("depth", 2.0),
1044 ("history", 2.0),
1045 ("timeline", 2.5),
1046 ("evolution", 2.0),
1047 ("oldest", 2.0),
1048 ("newest", 2.0),
1049 ],
1050 },
1051 ToolProfile {
1052 tool_name: "learning.pattern",
1053 keywords: &[
1054 ("learning", 3.0),
1055 ("pattern", 3.0),
1056 ("recurring", 2.5),
1057 ("theme", 2.5),
1058 ("frequency", 2.0),
1059 ("co-occurrence", 3.0),
1060 ("trends", 2.5),
1061 ("repeated", 2.0),
1062 ("common", 1.5),
1063 ],
1064 },
1065 ToolProfile {
1066 tool_name: "learning.suggest",
1067 keywords: &[
1068 ("suggest", 3.5),
1069 ("suggestion", 3.5),
1070 ("learn", 2.5),
1071 ("gap", 3.0),
1072 ("missing", 2.0),
1073 ("explore", 2.0),
1074 ("next", 2.0),
1075 ("recommend", 2.5),
1076 ("path", 2.0),
1077 ("advice", 2.0),
1078 ],
1079 },
1080 ToolProfile {
1082 tool_name: "bicameral.reason",
1083 keywords: &[
1084 ("bicameral", 5.0),
1085 ("hemisphere", 4.0),
1086 ("debate", 4.0),
1087 ("consensus", 3.5),
1088 ("deliberate", 3.5),
1089 ("pros", 3.0),
1090 ("cons", 3.0),
1091 ("dual", 2.5),
1092 ("perspective", 2.5),
1093 ("callosum", 4.0),
1094 ],
1095 },
1096 ToolProfile {
1097 tool_name: "bicameral.status",
1098 keywords: &[
1099 ("bicameral", 3.0),
1100 ("hemisphere", 3.5),
1101 ("callosum", 3.0),
1102 ("left", 1.5),
1103 ("right", 1.5),
1104 ("status", 2.0),
1105 ],
1106 },
1107 ToolProfile {
1108 tool_name: "reasoning.bicameral",
1109 keywords: &[
1110 ("bicameral", 3.0),
1111 ("pros", 3.5),
1112 ("cons", 3.5),
1113 ("debate", 2.5),
1114 ("perspective", 2.5),
1115 ("argument", 2.5),
1116 ("supporting", 2.0),
1117 ("opposing", 2.5),
1118 ("evidence", 2.0),
1119 ("analyze", 1.5),
1120 ],
1121 },
1122 ToolProfile {
1124 tool_name: "drive.snapshot",
1125 keywords: &[
1126 ("drive", 4.0),
1127 ("emotion", 4.0),
1128 ("motivation", 3.5),
1129 ("curiosity", 3.0),
1130 ("satisfaction", 3.0),
1131 ("caution", 2.5),
1132 ("energy", 2.0),
1133 ("mood", 3.0),
1134 ("feeling", 2.5),
1135 ],
1136 },
1137 ToolProfile {
1138 tool_name: "drive.event",
1139 keywords: &[
1140 ("drive", 3.0),
1141 ("emotion", 3.0),
1142 ("inject", 3.5),
1143 ("trigger", 2.5),
1144 ("reward", 3.0),
1145 ("frustration", 3.0),
1146 ("novelty", 2.5),
1147 ],
1148 },
1149 ToolProfile {
1150 tool_name: "think",
1151 keywords: &[
1152 ("think", 4.0),
1153 ("analyze", 3.0),
1154 ("reason", 2.5),
1155 ("consider", 2.0),
1156 ("reflect", 2.5),
1157 ("ponder", 3.0),
1158 ("contemplate", 3.0),
1159 ("insight", 2.0),
1160 ("thought", 3.0),
1161 ],
1162 },
1163 ToolProfile {
1164 tool_name: "explain",
1165 keywords: &[
1166 ("explain", 4.0),
1167 ("explanation", 3.5),
1168 ("clarify", 3.0),
1169 ("describe", 2.5),
1170 ("context", 2.0),
1171 ("related", 2.0),
1172 ("understand", 2.0),
1173 ("elaborate", 2.5),
1174 ("meaning", 2.0),
1175 ],
1176 },
1177 ToolProfile {
1179 tool_name: "pipeline.create",
1180 keywords: &[
1181 ("pipeline", 4.0),
1182 ("create", 2.5),
1183 ("build", 2.0),
1184 ("workflow", 3.0),
1185 ("steps", 2.0),
1186 ("chain", 2.0),
1187 ("sequence", 2.0),
1188 ],
1189 },
1190 ToolProfile {
1191 tool_name: "pipeline.list",
1192 keywords: &[
1193 ("pipeline", 3.5),
1194 ("list", 3.0),
1195 ("workflows", 2.5),
1196 ("show", 1.5),
1197 ("available", 2.0),
1198 ],
1199 },
1200 ToolProfile {
1201 tool_name: "pipeline.status",
1202 keywords: &[
1203 ("pipeline", 3.0),
1204 ("status", 3.0),
1205 ("check", 2.0),
1206 ("state", 2.0),
1207 ("progress", 2.5),
1208 ("running", 2.0),
1209 ],
1210 },
1211 ToolProfile {
1212 tool_name: "skill.invoke",
1213 keywords: &[
1214 ("skill", 4.0),
1215 ("invoke", 3.5),
1216 ("execute", 2.5),
1217 ("run", 2.0),
1218 ("call", 2.0),
1219 ("trigger", 2.0),
1220 ("ability", 2.5),
1221 ],
1222 },
1223 ToolProfile {
1224 tool_name: "skill.list",
1225 keywords: &[
1226 ("skill", 3.5),
1227 ("list", 3.0),
1228 ("abilities", 2.5),
1229 ("available", 2.0),
1230 ("show", 1.5),
1231 ("capabilities", 2.0),
1232 ],
1233 },
1234 ToolProfile {
1236 tool_name: "anomaly.detect",
1237 keywords: &[
1238 ("anomaly", 4.0),
1239 ("detect", 3.0),
1240 ("outlier", 3.5),
1241 ("unusual", 2.5),
1242 ("abnormal", 3.0),
1243 ("strange", 2.0),
1244 ("irregular", 2.5),
1245 ("z-score", 3.0),
1246 ],
1247 },
1248 ToolProfile {
1249 tool_name: "state.snapshot",
1250 keywords: &[
1251 ("snapshot", 4.0),
1252 ("capture", 2.5),
1253 ("state", 2.5),
1254 ("checkpoint", 3.0),
1255 ("preserve", 2.0),
1256 ("record", 2.0),
1257 ],
1258 },
1259 ToolProfile {
1260 tool_name: "state.revert",
1261 keywords: &[
1262 ("revert", 4.0),
1263 ("rollback", 3.5),
1264 ("restore", 3.0),
1265 ("previous", 2.5),
1266 ("undo", 2.5),
1267 ("go back", 2.0),
1268 ("state", 2.0),
1269 ],
1270 },
1271 ToolProfile {
1273 tool_name: "correlation.analyze",
1274 keywords: &[
1275 ("correlation", 4.0),
1276 ("analyze", 2.0),
1277 ("co-occurrence", 3.0),
1278 ("phi", 2.5),
1279 ("relationship", 2.0),
1280 ("statistical", 2.5),
1281 ("connect", 1.5),
1282 ("associate", 1.5),
1283 ],
1284 },
1285 ToolProfile {
1286 tool_name: "god.nodes",
1287 keywords: &[
1288 ("god", 3.5),
1289 ("nodes", 3.0),
1290 ("hub", 3.0),
1291 ("central", 2.5),
1292 ("important", 2.0),
1293 ("connector", 3.0),
1294 ("cross-galaxy", 3.0),
1295 ("entity", 2.0),
1296 ],
1297 },
1298 ToolProfile {
1300 tool_name: "anti_loop.check",
1301 keywords: &[
1302 ("loop", 4.0),
1303 ("anti", 2.5),
1304 ("repetitive", 3.0),
1305 ("duplicate", 3.0),
1306 ("stuck", 3.0),
1307 ("cycle", 2.5),
1308 ("repeated", 2.5),
1309 ("burst", 2.0),
1310 ],
1311 },
1312 ToolProfile {
1313 tool_name: "boundary.enforce",
1314 keywords: &[
1315 ("boundary", 4.0),
1316 ("enforce", 3.5),
1317 ("limit", 3.0),
1318 ("violation", 3.0),
1319 ("overflow", 3.0),
1320 ("constraint", 2.5),
1321 ("check", 2.0),
1322 ("resource", 2.0),
1323 ("sprawl", 2.5),
1324 ],
1325 },
1326 ToolProfile {
1328 tool_name: "association.mine",
1329 keywords: &[
1330 ("cross", 5.0),
1331 ("galaxy", 4.0),
1332 ("association", 3.0),
1333 ("mine", 3.0),
1334 ("overlap", 2.5),
1335 ("keyword", 2.0),
1336 ("propose", 2.0),
1337 ("link", 2.0),
1338 ],
1339 },
1340 ToolProfile {
1341 tool_name: "pattern.detect",
1342 keywords: &[
1343 ("pattern", 4.0),
1344 ("detect", 3.5),
1345 ("structural", 3.0),
1346 ("hub", 3.0),
1347 ("bridge", 3.0),
1348 ("chain", 2.5),
1349 ("graph", 2.0),
1350 ("topology", 2.5),
1351 ],
1352 },
1353 ToolProfile {
1354 tool_name: "emergence.report",
1355 keywords: &[
1356 ("emergence", 4.0),
1357 ("report", 3.0),
1358 ("tag", 2.5),
1359 ("frequency", 2.5),
1360 ("distribution", 2.0),
1361 ("trend", 2.0),
1362 ("emerging", 3.0),
1363 ("dominant", 2.0),
1364 ],
1365 },
1366 ToolProfile {
1367 tool_name: "network.stats",
1368 keywords: &[
1369 ("network", 4.0),
1370 ("stats", 3.0),
1371 ("density", 3.0),
1372 ("degree", 2.5),
1373 ("edge", 2.0),
1374 ("node", 2.0),
1375 ("global", 2.0),
1376 ("graph", 2.0),
1377 ],
1378 },
1379 ToolProfile {
1380 tool_name: "network.centrality",
1381 keywords: &[
1382 ("centrality", 4.0),
1383 ("central", 3.0),
1384 ("degree", 3.0),
1385 ("important", 2.0),
1386 ("influential", 2.5),
1387 ("hub", 2.0),
1388 ("rank", 2.0),
1389 ("top", 2.0),
1390 ],
1391 },
1392 ToolProfile {
1393 tool_name: "network.clusters",
1394 keywords: &[
1395 ("cluster", 4.0),
1396 ("clusters", 3.0),
1397 ("component", 3.0),
1398 ("connected", 2.5),
1399 ("group", 2.0),
1400 ("isolate", 2.0),
1401 ("subgraph", 2.5),
1402 ],
1403 },
1404 ToolProfile {
1406 tool_name: "smarana.status",
1407 keywords: &[
1408 ("smarana", 5.0),
1409 ("retention", 4.0),
1410 ("recall", 3.0),
1411 ("score", 2.0),
1412 ("memory", 1.5),
1413 ("forgetting", 2.5),
1414 ],
1415 },
1416 ToolProfile {
1417 tool_name: "smarana.trace",
1418 keywords: &[
1419 ("smarana", 4.0),
1420 ("trace", 3.5),
1421 ("decay", 3.0),
1422 ("retention", 3.0),
1423 ("over", 2.0),
1424 ("time", 1.5),
1425 ("history", 2.0),
1426 ],
1427 },
1428 ToolProfile {
1429 tool_name: "apotheosis.check",
1430 keywords: &[
1431 ("apotheosis", 5.0),
1432 ("self", 2.5),
1433 ("improvement", 3.5),
1434 ("trend", 3.0),
1435 ("progress", 2.5),
1436 ("check", 2.0),
1437 ("score", 2.0),
1438 ],
1439 },
1440 ToolProfile {
1441 tool_name: "citta.history",
1442 keywords: &[
1443 ("citta", 4.0),
1444 ("history", 3.5),
1445 ("heartbeat", 3.0),
1446 ("valence", 2.5),
1447 ("past", 2.0),
1448 ("recent", 2.0),
1449 ("consciousness", 2.5),
1450 ],
1451 },
1452 ToolProfile {
1453 tool_name: "dream.analyze",
1454 keywords: &[
1455 ("dream", 4.0),
1456 ("analyze", 3.5),
1457 ("analysis", 3.0),
1458 ("consolidation", 2.5),
1459 ("quality", 2.5),
1460 ("sleep", 2.0),
1461 ("cycle", 2.0),
1462 ],
1463 },
1464 ToolProfile {
1465 tool_name: "consciousness.depth",
1466 keywords: &[
1467 ("consciousness", 4.0),
1468 ("depth", 4.0),
1469 ("deep", 3.0),
1470 ("measure", 2.5),
1471 ("awareness", 2.5),
1472 ("state", 2.0),
1473 ("level", 2.0),
1474 ],
1475 },
1476 ToolProfile {
1478 tool_name: "memory.sort",
1479 keywords: &[
1480 ("sort", 4.0),
1481 ("order", 3.5),
1482 ("arrange", 3.0),
1483 ("rank", 2.5),
1484 ("by", 1.5),
1485 ("importance", 2.0),
1486 ("recency", 2.0),
1487 ("memory", 1.5),
1488 ],
1489 },
1490 ToolProfile {
1491 tool_name: "memory.filter",
1492 keywords: &[
1493 ("filter", 4.0),
1494 ("where", 2.5),
1495 ("match", 2.0),
1496 ("criteria", 3.0),
1497 ("condition", 2.5),
1498 ("tag", 2.0),
1499 ("importance", 1.5),
1500 ("memory", 1.5),
1501 ],
1502 },
1503 ToolProfile {
1504 tool_name: "memory.deduplicate",
1505 keywords: &[
1506 ("deduplicate", 4.0),
1507 ("dedup", 4.0),
1508 ("duplicate", 3.5),
1509 ("unique", 2.5),
1510 ("distinct", 3.0),
1511 ("remove", 2.0),
1512 ("redundant", 3.0),
1513 ("memory", 1.5),
1514 ],
1515 },
1516 ToolProfile {
1517 tool_name: "memory.export",
1518 keywords: &[
1519 ("export", 4.0),
1520 ("download", 3.0),
1521 ("dump", 3.0),
1522 ("extract", 2.5),
1523 ("format", 2.0),
1524 ("csv", 3.5),
1525 ("markdown", 3.0),
1526 ("memory", 1.5),
1527 ],
1528 },
1529 ToolProfile {
1531 tool_name: "homeostasis.check",
1532 keywords: &[
1533 ("homeostasis", 5.0),
1534 ("check", 3.0),
1535 ("balance", 3.5),
1536 ("equilibrium", 3.0),
1537 ("health", 2.5),
1538 ("metrics", 3.0),
1539 ("vitals", 3.0),
1540 ("system", 1.5),
1541 ],
1542 },
1543 ToolProfile {
1544 tool_name: "homeostasis.adjust",
1545 keywords: &[
1546 ("homeostasis", 4.0),
1547 ("adjust", 3.5),
1548 ("tune", 3.0),
1549 ("rebalance", 3.5),
1550 ("weight", 3.0),
1551 ("simulate", 2.5),
1552 ("recalibrate", 3.0),
1553 ],
1554 },
1555 ToolProfile {
1556 tool_name: "homeostasis.history",
1557 keywords: &[
1558 ("homeostasis", 4.0),
1559 ("history", 3.5),
1560 ("past", 2.5),
1561 ("trend", 3.0),
1562 ("samples", 3.0),
1563 ("readings", 2.5),
1564 ("timeline", 2.0),
1565 ],
1566 },
1567 ToolProfile {
1568 tool_name: "homeostasis.alerts",
1569 keywords: &[
1570 ("homeostasis", 4.0),
1571 ("alert", 4.0),
1572 ("alerts", 4.0),
1573 ("warning", 3.5),
1574 ("critical", 3.0),
1575 ("notify", 2.5),
1576 ("threshold", 2.5),
1577 ("triggered", 2.0),
1578 ],
1579 },
1580 ToolProfile {
1582 tool_name: "reflex.dispatch",
1583 keywords: &[
1584 ("reflex", 5.0),
1585 ("dispatch", 5.0),
1586 ("trigger", 4.0),
1587 ("invoke", 3.0),
1588 ("fire", 3.0),
1589 ("handler", 2.5),
1590 ("emergency", 2.0),
1591 ("e_stop", 3.5),
1592 ("estop", 3.5),
1593 ("safety", 2.0),
1594 ("actuator", 2.0),
1595 ],
1596 },
1597 ToolProfile {
1598 tool_name: "reflex.status",
1599 keywords: &[
1600 ("reflex", 5.0),
1601 ("status", 4.0),
1602 ("table", 3.0),
1603 ("handler", 2.5),
1604 ("registered", 2.5),
1605 ("safety_mask", 3.0),
1606 ("dispatch_count", 3.0),
1607 ("builtins", 2.0),
1608 ],
1609 },
1610 ToolProfile {
1612 tool_name: "workspace.spotlight",
1613 keywords: &[
1614 ("spotlight", 5.0),
1615 ("attention", 4.0),
1616 ("focus", 3.0),
1617 ("arbitration", 3.5),
1618 ("workspace", 3.0),
1619 ("current", 2.0),
1620 ("holder", 2.5),
1621 ("salience", 2.5),
1622 ("who", 1.5),
1623 ("winning", 2.5),
1624 ],
1625 },
1626 ToolProfile {
1627 tool_name: "workspace.events",
1628 keywords: &[
1629 ("workspace", 4.0),
1630 ("events", 5.0),
1631 ("backlog", 4.0),
1632 ("history", 2.5),
1633 ("log", 2.0),
1634 ],
1635 },
1636 ToolProfile {
1637 tool_name: "workspace.publish",
1638 keywords: &[
1639 ("workspace", 4.0),
1640 ("publish", 5.0),
1641 ("broadcast", 4.0),
1642 ("emit", 3.5),
1643 ("send", 2.5),
1644 ("event", 3.0),
1645 ("post", 2.5),
1646 ("notify", 2.0),
1647 ("submit", 2.5),
1648 ],
1649 },
1650 ToolProfile {
1651 tool_name: "workspace.stats",
1652 keywords: &[
1653 ("workspace", 4.0),
1654 ("stats", 5.0),
1655 ("statistics", 4.5),
1656 ("transfers", 3.0),
1657 ("arbitration", 2.5),
1658 ("published", 3.0),
1659 ("count", 2.0),
1660 ("summary", 2.5),
1661 ],
1662 },
1663 ToolProfile {
1665 tool_name: "timescale.status",
1666 keywords: &[
1667 ("timescale", 5.0),
1668 ("status", 4.0),
1669 ("tier", 3.0),
1670 ("tiers", 3.0),
1671 ("bus", 2.5),
1672 ("brain_wave", 3.0),
1673 ("active", 2.5),
1674 ("hooks", 2.0),
1675 ("interval", 2.0),
1676 ("budget", 2.0),
1677 ],
1678 },
1679 ToolProfile {
1680 tool_name: "timescale.hooks",
1681 keywords: &[
1682 ("timescale", 4.0),
1683 ("hooks", 5.0),
1684 ("hook", 4.0),
1685 ("list", 2.5),
1686 ("stats", 2.5),
1687 ("performance", 2.5),
1688 ("tick", 3.0),
1689 ("timeout", 2.5),
1690 ("duration", 2.0),
1691 ("callback", 2.0),
1692 ],
1693 },
1694 ToolProfile {
1696 tool_name: "selfmodel.forecast",
1697 keywords: &[
1698 ("forecast", 5.0),
1699 ("predict", 4.0),
1700 ("prediction", 4.0),
1701 ("project", 3.0),
1702 ("projection", 3.0),
1703 ("extrapolate", 4.0),
1704 ("trend", 3.0),
1705 ("outlook", 3.0),
1706 ("selfmodel", 5.0),
1707 ("introspect", 3.0),
1708 ("horizon", 2.5),
1709 ("metric", 2.0),
1710 ],
1711 },
1712 ToolProfile {
1713 tool_name: "selfmodel.alerts",
1714 keywords: &[
1715 ("alert", 5.0),
1716 ("alerts", 5.0),
1717 ("warning", 3.5),
1718 ("warnings", 3.5),
1719 ("critical", 3.5),
1720 ("threshold", 3.0),
1721 ("breach", 3.0),
1722 ("exceed", 2.5),
1723 ("danger", 3.0),
1724 ("selfmodel", 5.0),
1725 ("introspect", 3.0),
1726 ],
1727 },
1728 ToolProfile {
1729 tool_name: "selfmodel.snapshot",
1730 keywords: &[
1731 ("snapshot", 5.0),
1732 ("selfmodel", 5.0),
1733 ("introspect", 4.0),
1734 ("introspection", 4.0),
1735 ("overview", 3.0),
1736 ("confidence", 3.0),
1737 ("conservative", 2.5),
1738 ],
1739 },
1740 ToolProfile {
1742 tool_name: "friction.log",
1743 keywords: &[
1744 ("friction", 5.0),
1745 ("log", 3.0),
1746 ("report", 2.5),
1747 ("issue", 3.5),
1748 ("problem", 3.0),
1749 ("bug", 3.0),
1750 ("complaint", 3.0),
1751 ("annoying", 2.5),
1752 ("broken", 2.5),
1753 ("wrong", 2.0),
1754 ],
1755 },
1756 ToolProfile {
1757 tool_name: "friction.review",
1758 keywords: &[
1759 ("friction", 4.5),
1760 ("review", 4.0),
1761 ("issues", 3.5),
1762 ("problems", 3.0),
1763 ("patterns", 2.5),
1764 ("summary", 2.5),
1765 ("analyze", 2.0),
1766 ("frictions", 4.0),
1767 ],
1768 },
1769 ToolProfile {
1770 tool_name: "improve.proposals",
1771 keywords: &[
1772 ("improve", 5.0),
1773 ("improvement", 5.0),
1774 ("improvements", 5.0),
1775 ("proposal", 4.0),
1776 ("proposals", 4.0),
1777 ("suggest", 3.0),
1778 ("suggestions", 3.0),
1779 ("fix", 2.5),
1780 ("friction", 2.0),
1781 ("upgrade", 3.0),
1782 ("enhance", 2.5),
1783 ("better", 2.0),
1784 ],
1785 },
1786 ToolProfile {
1787 tool_name: "redteam.proposals",
1788 keywords: &[
1789 ("redteam", 5.0),
1790 ("red", 2.0),
1791 ("team", 2.0),
1792 ("adversarial", 5.0),
1793 ("attack", 4.5),
1794 ("vulnerability", 4.5),
1795 ("security", 4.0),
1796 ("exploit", 4.0),
1797 ("breach", 3.5),
1798 ("pentest", 4.5),
1799 ("penetrate", 3.5),
1800 ("break", 3.0),
1801 ("threat", 3.5),
1802 ("probe", 3.0),
1803 ("audit", 2.5),
1804 ],
1805 },
1806 ToolProfile {
1808 tool_name: "sensor.list",
1809 keywords: &[
1810 ("sensor", 5.0),
1811 ("sensors", 5.0),
1812 ("list", 3.0),
1813 ("hardware", 3.0),
1814 ("devices", 2.5),
1815 ("thermal", 2.0),
1816 ("battery", 2.0),
1817 ],
1818 },
1819 ToolProfile {
1820 tool_name: "sensor.read",
1821 keywords: &[
1822 ("read", 4.0),
1823 ("sensor", 4.0),
1824 ("temperature", 3.5),
1825 ("value", 3.0),
1826 ("measure", 3.0),
1827 ("probe", 2.5),
1828 ],
1829 },
1830 ToolProfile {
1831 tool_name: "sensor.poll",
1832 keywords: &[
1833 ("poll", 5.0),
1834 ("sample", 4.0),
1835 ("all", 2.5),
1836 ("sensors", 3.0),
1837 ("readings", 3.5),
1838 ("collect", 2.5),
1839 ],
1840 },
1841 ToolProfile {
1842 tool_name: "sensor.history",
1843 keywords: &[
1844 ("history", 5.0),
1845 ("past", 3.0),
1846 ("readings", 3.5),
1847 ("recent", 3.0),
1848 ("log", 2.5),
1849 ("timeseries", 3.5),
1850 ],
1851 },
1852 ToolProfile {
1853 tool_name: "actuator.list",
1854 keywords: &[
1855 ("actuator", 5.0),
1856 ("actuators", 5.0),
1857 ("motor", 3.0),
1858 ("relay", 3.0),
1859 ("output", 2.5),
1860 ],
1861 },
1862 ToolProfile {
1863 tool_name: "actuator.command",
1864 keywords: &[
1865 ("command", 4.5),
1866 ("send", 3.5),
1867 ("actuator", 4.0),
1868 ("motor", 3.0),
1869 ("drive", 3.0),
1870 ("control", 3.5),
1871 ("set", 2.0),
1872 ],
1873 },
1874 ToolProfile {
1875 tool_name: "actuator.estop",
1876 keywords: &[
1877 ("estop", 5.0),
1878 ("emergency", 5.0),
1879 ("stop", 4.0),
1880 ("halt", 4.0),
1881 ("abort", 3.5),
1882 ("shutdown", 3.0),
1883 ],
1884 },
1885 ToolProfile {
1886 tool_name: "reflex.list",
1887 keywords: &[
1888 ("reflex", 5.0),
1889 ("reflexes", 5.0),
1890 ("rules", 3.0),
1891 ("trigger", 2.5),
1892 ],
1893 },
1894 ToolProfile {
1895 tool_name: "reflex.add",
1896 keywords: &[
1897 ("add", 3.5),
1898 ("reflex", 4.5),
1899 ("rule", 4.0),
1900 ("create", 3.0),
1901 ("threshold", 3.5),
1902 ("trigger", 3.0),
1903 ],
1904 },
1905 ToolProfile {
1906 tool_name: "reflex.evaluate",
1907 keywords: &[
1908 ("evaluate", 5.0),
1909 ("check", 3.0),
1910 ("reflex", 4.0),
1911 ("trigger", 3.5),
1912 ("fire", 3.0),
1913 ("respond", 2.5),
1914 ],
1915 },
1916 ToolProfile {
1917 tool_name: "sensorimotor.scan",
1918 keywords: &[
1919 ("sensorimotor", 6.0),
1920 ("scan", 4.0),
1921 ("poll", 3.5),
1922 ("reflex", 3.0),
1923 ("autonomous", 3.0),
1924 ("embodiment", 4.0),
1925 ("cycle", 2.5),
1926 ("self-regulate", 3.0),
1927 ],
1928 },
1929 ToolProfile {
1931 tool_name: "gnosis",
1932 keywords: &[
1933 ("help", 2.0),
1934 ("discover", 2.0),
1935 ("what", 1.5),
1936 ("can", 1.0),
1937 ("do", 1.0),
1938 ("status", 1.5),
1939 ("overview", 2.0),
1940 ("system", 1.0),
1941 ],
1942 },
1943 ToolProfile {
1945 tool_name: "speculative.decode",
1946 keywords: &[
1947 ("speculative", 5.0),
1948 ("decode", 4.0),
1949 ("draft", 3.0),
1950 ("verify", 2.5),
1951 ("accelerate", 3.0),
1952 ("speedup", 3.0),
1953 ("fast", 2.0),
1954 ("infer", 2.0),
1955 ("generate", 1.5),
1956 ],
1957 },
1958 ToolProfile {
1959 tool_name: "speculative.stats",
1960 keywords: &[
1961 ("speculative", 4.0),
1962 ("acceptance", 3.0),
1963 ("speedup", 3.0),
1964 ("draft", 2.0),
1965 ("latency", 2.0),
1966 ("tokens", 2.0),
1967 ],
1968 },
1969 ToolProfile {
1971 tool_name: "meta.enhance",
1972 keywords: &[
1973 ("enhance", 5.0),
1974 ("grounding", 4.0),
1975 ("grounded", 4.0),
1976 ("rag", 4.0),
1977 ("self-correct", 4.0),
1978 ("selfcorrect", 4.0),
1979 ("ensemble", 3.5),
1980 ("improve", 3.0),
1981 ("cognitive", 3.0),
1982 ("meta", 2.5),
1983 ("harness", 3.0),
1984 ("augment", 2.5),
1985 ("refine", 2.0),
1986 ],
1987 },
1988 ToolProfile {
1989 tool_name: "meta.stats",
1990 keywords: &[
1991 ("meta", 3.0),
1992 ("harness", 3.0),
1993 ("enhancement", 3.0),
1994 ("improvement", 3.0),
1995 ("enhance", 2.0),
1996 ("stats", 2.0),
1997 ],
1998 },
1999 ToolProfile {
2001 tool_name: "dense.encode",
2002 keywords: &[
2003 ("dense", 5.0),
2004 ("compress", 4.0),
2005 ("compression", 4.0),
2006 ("encode", 3.5),
2007 ("encoding", 3.5),
2008 ("token", 2.5),
2009 ("compact", 3.0),
2010 ("shrink", 2.5),
2011 ("cjk", 3.0),
2012 ],
2013 },
2014 ToolProfile {
2015 tool_name: "dense.decode",
2016 keywords: &[
2017 ("decode", 4.0),
2018 ("decompress", 4.0),
2019 ("expand", 3.0),
2020 ("restore", 2.5),
2021 ("dense", 2.0),
2022 ],
2023 },
2024 ToolProfile {
2026 tool_name: "transaction.begin",
2027 keywords: &[
2028 ("transaction", 5.0),
2029 ("begin", 4.0),
2030 ("start", 3.0),
2031 ("snapshot", 3.5),
2032 ("checkpoint", 3.0),
2033 ("atomic", 3.0),
2034 ],
2035 },
2036 ToolProfile {
2037 tool_name: "transaction.commit",
2038 keywords: &[
2039 ("transaction", 5.0),
2040 ("commit", 5.0),
2041 ("finalize", 3.5),
2042 ("confirm", 3.0),
2043 ("keep", 2.5),
2044 ("persist", 3.0),
2045 ],
2046 },
2047 ToolProfile {
2048 tool_name: "transaction.rollback",
2049 keywords: &[
2050 ("transaction", 5.0),
2051 ("rollback", 5.0),
2052 ("revert", 4.0),
2053 ("undo", 4.0),
2054 ("restore", 3.5),
2055 ("abort", 3.5),
2056 ("discard", 3.0),
2057 ],
2058 },
2059 ToolProfile {
2061 tool_name: "imagine.scenario",
2062 keywords: &[
2063 ("imagine", 5.0),
2064 ("scenario", 5.0),
2065 ("scenarios", 4.5),
2066 ("plan", 3.0),
2067 ("contingency", 4.0),
2068 ("what-if", 4.0),
2069 ("possibility", 3.5),
2070 ("options", 2.5),
2071 ("alternatives", 3.0),
2072 ("brainstorm", 3.5),
2073 ("envision", 3.5),
2074 ],
2075 },
2076 ToolProfile {
2077 tool_name: "imagine.predict",
2078 keywords: &[
2079 ("predict", 5.0),
2080 ("outcome", 4.0),
2081 ("consequence", 4.0),
2082 ("forecast", 3.0),
2083 ("expect", 3.0),
2084 ("result", 2.5),
2085 ("happen", 3.5),
2086 ("would", 2.5),
2087 ("if", 1.5),
2088 ("imagine", 2.0),
2089 ],
2090 },
2091 ToolProfile {
2092 tool_name: "imagine.reflect",
2093 keywords: &[
2094 ("reflect", 5.0),
2095 ("counterfactual", 5.0),
2096 ("regret", 4.0),
2097 ("alternative", 3.5),
2098 ("should", 3.0),
2099 ("instead", 3.0),
2100 ("what-if", 3.0),
2101 ("reconsider", 4.0),
2102 ("retrospect", 3.5),
2103 ("lesson", 3.0),
2104 ("counter", 2.5),
2105 ("factual", 2.5),
2106 ],
2107 },
2108 ToolProfile {
2110 tool_name: "nlu.shadow_report",
2111 keywords: &[
2112 ("shadow", 4.0),
2113 ("disagreement", 4.0),
2114 ("nlu", 3.0),
2115 ("router", 3.0),
2116 ("embedding", 2.5),
2117 ("tfidf", 2.5),
2118 ("tf-idf", 2.5),
2119 ("oats", 3.0),
2120 ("promotion", 2.5),
2121 ("routing", 2.0),
2122 ],
2123 },
2124];
2125
2126const STOPWORDS: &[&str] = &[
2129 "a", "an", "the", "this", "that", "these", "those", "i", "me", "my", "you", "your", "yours", "it", "its", "we", "our", "ours", "they", "them",
2133 "their", "theirs", "he", "him", "his", "she", "her", "hers", "is", "are", "was", "were", "be", "been", "being", "am", "have", "has", "had", "will", "would",
2135 "could", "should", "shall", "must", "in", "on", "at", "to", "for", "of", "with", "by", "from", "into", "about", "over", "under",
2137 "through", "between", "among", "during", "before", "after", "above", "below",
2138 "and", "but", "or", "nor", "so", "yet", "not", "no", "yes", "if", "else", "because", "as", "until", "while", "although", "though", "since", "unless",
2142 "whether", "up", "down", "out", "off", "again", "further", "then", "once", "here", "there", "when",
2144 "where", "why", "how", "all", "any", "both", "each", "few", "more", "most", "other", "some", "such", "only", "own",
2146 "same", "than", "too", "very", "just", "also", "now",
2148];
2149
2150const E_DROPPING_BASES: &[&str] = &[
2154 "activat",
2155 "allocat",
2156 "arrang",
2157 "associat",
2158 "becom",
2159 "calculat",
2160 "chang",
2161 "clos",
2162 "cit",
2163 "configur",
2164 "consolidat",
2165 "continu",
2166 "creat",
2167 "delegat",
2168 "delet",
2169 "demonstrat",
2170 "downgrad",
2171 "encourag",
2172 "engag",
2173 "ensur",
2174 "enumerat",
2175 "evaluat",
2176 "exchang",
2177 "exclud",
2178 "explor",
2179 "fac",
2180 "generat",
2181 "giv",
2182 "improv",
2183 "includ",
2184 "leav",
2185 "lik",
2186 "mak",
2187 "manag",
2188 "measur",
2189 "merg",
2190 "mov",
2191 "navigat",
2192 "notic",
2193 "operat",
2194 "practic",
2195 "relat",
2196 "remov",
2197 "restor",
2198 "sav",
2199 "simulat",
2200 "stor",
2201 "tak",
2202 "updat",
2203 "upgrad",
2204 "us",
2205 "validat",
2206 "writ",
2207];
2208
2209fn stem(word: &str) -> String {
2213 let w = word.to_lowercase();
2214
2215 if w.ends_with("ies") && w.len() > 3 {
2217 let base = &w[..w.len() - 3];
2218 return format!("{base}y");
2219 }
2220
2221 if w.ends_with("ing") && w.len() > 4 {
2223 let base = &w[..w.len() - 3];
2224 if let Some(last) = base.chars().last() {
2228 let is_double_consonant = base.chars().rev().nth(1) == Some(last);
2229 if is_double_consonant {
2230 return base[..base.len() - last.len_utf8()].to_string();
2231 }
2232 }
2233 if E_DROPPING_BASES.binary_search(&base).is_ok() {
2235 return format!("{base}e");
2236 }
2237 return base.to_string();
2238 }
2239
2240 if w.ends_with("ed") && w.len() > 3 {
2242 let base = &w[..w.len() - 2];
2243 if E_DROPPING_BASES.binary_search(&base).is_ok() {
2245 return format!("{base}e");
2246 }
2247 return base.to_string();
2248 }
2249
2250 if w.ends_with("es") && w.len() > 3 {
2252 let base = &w[..w.len() - 2];
2253 if base.ends_with("ch")
2255 || base.ends_with("sh")
2256 || base.ends_with('s')
2257 || base.ends_with('x')
2258 || base.ends_with('z')
2259 {
2260 return base.to_string();
2261 }
2262 return w[..w.len() - 1].to_string();
2263 }
2264
2265 if w.ends_with('s') && w.len() > 2 && !w.ends_with("ss") {
2267 return w[..w.len() - 1].to_string();
2268 }
2269
2270 w
2271}
2272
2273fn tokenize(text: &str) -> Vec<String> {
2276 text.split(|c: char| !c.is_alphanumeric())
2277 .filter(|s| !s.is_empty())
2278 .map(str::to_lowercase)
2279 .filter(|s| !STOPWORDS.contains(&s.as_str()))
2280 .map(|s| stem(&s))
2281 .collect()
2282}
2283
2284fn term_frequencies(tokens: &[String]) -> AHashMap<String, f64> {
2286 let mut tf = AHashMap::new();
2287 for token in tokens {
2288 *tf.entry(token.clone()).or_insert(0.0) += 1.0;
2289 }
2290 tf
2291}
2292
2293fn cosine_similarity(input_tf: &AHashMap<String, f64>, profile: &ToolProfile) -> f64 {
2299 let mut dot_product = 0.0;
2300 let mut profile_norm_sq = 0.0;
2301
2302 for (term, weight) in profile.keywords {
2303 profile_norm_sq += weight * weight;
2304 let stemmed_term = stem(term);
2305 if let Some(&freq) = input_tf.get(&stemmed_term) {
2306 dot_product += freq * weight;
2307 }
2308 }
2309
2310 if profile_norm_sq == 0.0 {
2311 return 0.0;
2312 }
2313
2314 let input_norm: f64 = input_tf.values().map(|v| v * v).sum::<f64>().sqrt();
2315 if input_norm == 0.0 {
2316 return 0.0;
2317 }
2318
2319 dot_product / (input_norm * profile_norm_sq.sqrt())
2320}
2321
2322pub const PREFIX_ROUTES: &[(&str, &str, f64)] = &[
2330 ("remember", "memory.create", 1.5),
2331 ("store", "memory.create", 1.5),
2332 ("save", "memory.create", 1.5),
2333 ("memorize", "memory.create", 1.5),
2334 ("recall", "memory.read", 1.5),
2335 ("search", "memory.search", 1.3),
2336 ("list", "memory.list", 1.3),
2337 ("delete", "memory.delete", 1.5),
2338 ("remove", "memory.delete", 1.3),
2339 ("forget", "memory.delete", 1.5),
2340 ("count", "memory.count", 1.5),
2341 ("show", "gnosis", 1.0),
2342 ("spotlight", "workspace.spotlight", 1.5),
2343 ("publish", "workspace.publish", 1.5),
2344 ("broadcast", "workspace.publish", 1.4),
2345 ("forecast", "selfmodel.forecast", 1.5),
2346 ("deliberate", "bicameral.reason", 1.3),
2347 ("drive", "drive.snapshot", 1.5),
2348 ("emotion", "drive.snapshot", 1.4),
2349 ("adversarial", "redteam.proposals", 1.5),
2350 ("redteam", "redteam.proposals", 1.5),
2351 ("pentest", "redteam.proposals", 1.5),
2352 ("friction", "friction.log", 1.3),
2353 ("log", "friction.log", 1.4),
2354 ("sensor", "sensor.list", 1.5),
2355 ("actuator", "actuator.list", 1.5),
2356 ("estop", "actuator.estop", 1.5),
2357 ("emergency", "actuator.estop", 1.3),
2358 ("sensorimotor", "sensorimotor.scan", 1.5),
2359 ("imagine", "imagine.scenario", 1.5),
2360 ("envision", "imagine.scenario", 1.4),
2361 ("brainstorm", "imagine.scenario", 1.3),
2362 ("counterfactual", "imagine.reflect", 1.5),
2363];
2364
2365#[must_use]
2368pub fn classify(text: &str) -> (&'static str, f64) {
2369 let lower = text.to_lowercase();
2370 if lower.trim().is_empty() {
2371 return ("gnosis", 0.0);
2372 }
2373
2374 let tokens = tokenize(&lower);
2375 if tokens.is_empty() {
2376 return ("gnosis", 0.0);
2377 }
2378
2379 let input_tf = term_frequencies(&tokens);
2380
2381 let first_word = lower.split_whitespace().next().unwrap_or("");
2383 let prefix_bonus: Option<(&str, f64)> = PREFIX_ROUTES
2384 .iter()
2385 .find(|(verb, _, _)| *verb == first_word)
2386 .map(|(_, tool, bonus)| (*tool, *bonus));
2387
2388 let mut best_tool = "gnosis";
2389 let mut best_score = 0.0;
2390
2391 for profile in TOOL_PROFILES {
2392 let mut score = cosine_similarity(&input_tf, profile);
2393 if let Some((bonus_tool, bonus)) = prefix_bonus {
2395 if profile.tool_name == bonus_tool {
2396 score *= bonus;
2397 } else {
2398 score /= bonus;
2400 }
2401 }
2402 if score > best_score {
2403 best_score = score;
2404 best_tool = profile.tool_name;
2405 }
2406 }
2407
2408 const MIN_THRESHOLD: f64 = 0.10;
2410 if best_score < MIN_THRESHOLD {
2411 return ("gnosis", 0.0);
2412 }
2413
2414 (best_tool, best_score)
2415}
2416
2417#[cfg(test)]
2418fn profiled_tools() -> Vec<&'static str> {
2419 TOOL_PROFILES.iter().map(|p| p.tool_name).collect()
2420}
2421
2422#[cfg(test)]
2423fn profile_count() -> usize {
2424 TOOL_PROFILES.len()
2425}
2426
2427#[cfg(test)]
2428mod tests {
2429 use super::*;
2430 use std::collections::HashSet;
2431
2432 #[test]
2433 fn classify_empty_returns_gnosis() {
2434 let (tool, conf) = classify("");
2435 assert_eq!(tool, "gnosis");
2436 assert_eq!(conf, 0.0);
2437 }
2438
2439 #[test]
2440 fn classify_whitespace_returns_gnosis() {
2441 let (tool, conf) = classify(" ");
2442 assert_eq!(tool, "gnosis");
2443 assert_eq!(conf, 0.0);
2444 }
2445
2446 #[test]
2447 fn classify_unknown_returns_gnosis() {
2448 let (tool, conf) = classify("xyzzy frobnicate");
2449 assert_eq!(tool, "gnosis");
2450 assert_eq!(conf, 0.0);
2451 }
2452
2453 #[test]
2454 fn classify_remember_routes_to_memory_create() {
2455 let (tool, _conf) = classify("remember that the sky is blue");
2456 assert_eq!(tool, "memory.create");
2457 }
2458
2459 #[test]
2460 fn classify_store_routes_to_memory_create() {
2461 let (tool, _conf) = classify("store this important fact");
2462 assert_eq!(tool, "memory.create");
2463 }
2464
2465 #[test]
2466 fn classify_recall_routes_to_memory_read() {
2467 let (tool, _conf) = classify("recall the last memory");
2468 assert_eq!(tool, "memory.read");
2469 }
2470
2471 #[test]
2472 fn classify_search_routes_to_memory_search() {
2473 let (tool, _conf) = classify("search for rust");
2474 assert_eq!(tool, "memory.search");
2475 }
2476
2477 #[test]
2478 fn classify_list_memories_routes_to_memory_list() {
2479 let (tool, _conf) = classify("list memories in codex");
2480 assert_eq!(tool, "memory.list");
2481 }
2482
2483 #[test]
2484 fn classify_delete_memory_routes_to_memory_delete() {
2485 let (tool, _conf) = classify("delete memory abc-123");
2486 assert_eq!(tool, "memory.delete");
2487 }
2488
2489 #[test]
2490 fn classify_karma_routes_to_karma_report() {
2491 let (tool, _conf) = classify("show me the karma report");
2492 assert_eq!(tool, "karma.report");
2493 }
2494
2495 #[test]
2496 fn classify_karma_history_routes_correctly() {
2497 let (tool, _conf) = classify("karma history");
2498 assert_eq!(tool, "karma.history");
2499 }
2500
2501 #[test]
2502 fn classify_dharma_status_routes_correctly() {
2503 let (tool, _conf) = classify("dharma status");
2504 assert_eq!(tool, "dharma.status");
2505 }
2506
2507 #[test]
2508 fn classify_dharma_rules_routes_correctly() {
2509 let (tool, _conf) = classify("show dharma rules");
2510 assert_eq!(tool, "dharma.rules");
2511 }
2512
2513 #[test]
2514 fn classify_harmony_routes_to_harmony_vector() {
2515 let (tool, _conf) = classify("harmony vector status");
2516 assert_eq!(tool, "harmony.vector");
2517 }
2518
2519 #[test]
2520 fn classify_gnosis_explain_routes_correctly() {
2521 let (tool, _conf) = classify("why was my action blocked");
2522 assert_eq!(tool, "gnosis.explain");
2523 }
2524
2525 #[test]
2526 fn classify_session_start_routes_correctly() {
2527 let (tool, _conf) = classify("start session research");
2528 assert_eq!(tool, "session.start");
2529 }
2530
2531 #[test]
2532 fn classify_session_end_routes_correctly() {
2533 let (tool, _conf) = classify("end session abc-123");
2534 assert_eq!(tool, "session.end");
2535 }
2536
2537 #[test]
2538 fn classify_citta_status_routes_correctly() {
2539 let (tool, _conf) = classify("citta status");
2540 assert_eq!(tool, "citta.status");
2541 }
2542
2543 #[test]
2544 fn classify_dream_trigger_routes_correctly() {
2545 let (tool, _conf) = classify("trigger dream cycle");
2546 assert_eq!(tool, "dream.trigger");
2547 }
2548
2549 #[test]
2550 fn classify_consolidate_routes_correctly() {
2551 let (tool, _conf) = classify("consolidate duplicate memories");
2552 assert_eq!(tool, "memory.consolidate");
2553 }
2554
2555 #[test]
2556 fn classify_emergence_scan_routes_correctly() {
2557 let (tool, _conf) = classify("emergence scan for trending tags");
2558 assert_eq!(tool, "emergence.scan");
2559 }
2560
2561 #[test]
2562 fn classify_spiral_report_routes_correctly() {
2563 let (tool, _conf) = classify("spiral report for autonomy");
2564 assert_eq!(tool, "spiral.report");
2565 }
2566
2567 #[test]
2568 fn classify_retention_prune_routes_correctly() {
2569 let (tool, _conf) = classify("prune memories ready to forget");
2570 assert_eq!(tool, "retention.prune");
2571 }
2572
2573 #[test]
2574 fn classify_tools_list_routes_correctly() {
2575 let (tool, _conf) = classify("list tools");
2576 assert_eq!(tool, "tools.list");
2577 }
2578
2579 #[test]
2580 fn classify_system_health_routes_correctly() {
2581 let (tool, _conf) = classify("system health check");
2582 assert_eq!(tool, "system.health");
2583 }
2584
2585 #[test]
2586 fn classify_agent_register_routes_correctly() {
2587 let (tool, _conf) = classify("register agent worker-1");
2588 assert_eq!(tool, "agent.register");
2589 }
2590
2591 #[test]
2592 fn classify_task_distribute_routes_correctly() {
2593 let (tool, _conf) = classify("distribute task analyze data");
2594 assert_eq!(tool, "task.distribute");
2595 }
2596
2597 #[test]
2598 fn classify_nearby_memories_routes_correctly() {
2599 let (tool, _conf) = classify("find nearby memories");
2600 assert_eq!(tool, "memory.nearby");
2601 }
2602
2603 #[test]
2604 fn classify_hybrid_recall_routes_correctly() {
2605 let (tool, _conf) = classify("hybrid recall for rust");
2606 assert_eq!(tool, "memory.hybrid_recall");
2607 }
2608
2609 #[test]
2610 fn classify_galaxy_stats_routes_correctly() {
2611 let (tool, _conf) = classify("galaxy stats overview");
2612 assert_eq!(tool, "galaxy.stats");
2613 }
2614
2615 #[test]
2616 fn classify_galaxy_export_routes_correctly() {
2617 let (tool, _conf) = classify("export galaxy backup");
2618 assert_eq!(tool, "galaxy.export");
2619 }
2620
2621 #[test]
2622 fn classify_kg_extract_routes_correctly() {
2623 let (tool, _conf) = classify("extract entities knowledge graph");
2624 assert_eq!(tool, "kg.extract");
2625 }
2626
2627 #[test]
2628 fn classify_kg_query_routes_correctly() {
2629 let (tool, _conf) = classify("knowledge graph query relationships");
2630 assert_eq!(tool, "kg.query");
2631 }
2632
2633 #[test]
2634 fn classify_kg_top_routes_correctly() {
2635 let (tool, _conf) = classify("top hub nodes knowledge graph");
2636 assert_eq!(tool, "kg.top");
2637 }
2638
2639 #[test]
2640 fn classify_graph_walk_routes_correctly() {
2641 let (tool, _conf) = classify("traverse graph walk bfs");
2642 assert_eq!(tool, "graph.walk");
2643 }
2644
2645 #[test]
2646 fn classify_graph_community_routes_correctly() {
2647 let (tool, _conf) = classify("detect communities clusters in graph");
2648 assert_eq!(tool, "graph.community");
2649 }
2650
2651 #[test]
2652 fn classify_graph_propagate_routes_correctly() {
2653 let (tool, _conf) = classify("propagate activation spread ripple");
2654 assert_eq!(tool, "graph.propagate");
2655 }
2656
2657 #[test]
2658 fn classify_galaxy_transfer_routes_correctly() {
2659 let (tool, _conf) = classify("transfer move memories galaxy");
2660 assert_eq!(tool, "galaxy.transfer");
2661 }
2662
2663 #[test]
2664 fn classify_galaxy_merge_routes_correctly() {
2665 let (tool, _conf) = classify("merge combine galaxies");
2666 assert_eq!(tool, "galaxy.merge");
2667 }
2668
2669 #[test]
2670 fn classify_galaxy_snapshot_routes_correctly() {
2671 let (tool, _conf) = classify("snapshot backup galaxy");
2672 assert_eq!(tool, "galaxy.snapshot");
2673 }
2674
2675 #[test]
2676 fn classify_galaxy_restore_routes_correctly() {
2677 let (tool, _conf) = classify("restore recover galaxy snapshot");
2678 assert_eq!(tool, "galaxy.restore");
2679 }
2680
2681 #[test]
2682 fn classify_agent_trust_routes_correctly() {
2683 let (tool, _conf) = classify("trust reliability agent score");
2684 assert_eq!(tool, "agent.trust");
2685 }
2686
2687 #[test]
2688 fn classify_agent_descriptions_routes_correctly() {
2689 let (tool, _conf) = classify("describe agent profile info");
2690 assert_eq!(tool, "agent.descriptions");
2691 }
2692
2693 #[test]
2694 fn classify_agent_capabilities_routes_correctly() {
2695 let (tool, _conf) = classify("agent capabilities skills abilities");
2696 assert_eq!(tool, "agent.capabilities");
2697 }
2698
2699 #[test]
2700 fn classify_agent_heartbeat_history_routes_correctly() {
2701 let (tool, _conf) = classify("heartbeat history log agent");
2702 assert_eq!(tool, "agent.heartbeat.history");
2703 }
2704
2705 #[test]
2706 fn classify_agent_deregister_routes_correctly() {
2707 let (tool, _conf) = classify("deregister unregister remove agent");
2708 assert_eq!(tool, "agent.deregister");
2709 }
2710
2711 #[test]
2712 fn classify_galaxy_dashboard_routes_correctly() {
2713 let (tool, _conf) = classify("galaxy dashboard overview panel");
2714 assert_eq!(tool, "galaxy.dashboard");
2715 }
2716
2717 #[test]
2718 fn classify_galaxy_backup_routes_correctly() {
2719 let (tool, _conf) = classify("backup archive galaxy dump");
2720 assert_eq!(tool, "galaxy.backup");
2721 }
2722
2723 #[test]
2724 fn classify_galaxy_taxonomy_routes_correctly() {
2725 let (tool, _conf) = classify("galaxy taxonomy classification categories");
2726 assert_eq!(tool, "galaxy.taxonomy");
2727 }
2728
2729 #[test]
2730 fn classify_galaxy_purge_routes_correctly() {
2731 let (tool, _conf) = classify("purge wipe clear galaxy");
2732 assert_eq!(tool, "galaxy.purge");
2733 }
2734
2735 #[test]
2736 fn classify_galaxy_health_routes_correctly() {
2737 let (tool, _conf) = classify("galaxy health diagnostic checkup");
2738 assert_eq!(tool, "galaxy.health");
2739 }
2740
2741 #[test]
2742 fn classify_memory_sort_routes_correctly() {
2743 let (tool, _conf) = classify("sort memories by importance");
2744 assert_eq!(tool, "memory.sort");
2745 }
2746
2747 #[test]
2748 fn classify_memory_filter_routes_correctly() {
2749 let (tool, _conf) = classify("filter memories by tag criteria");
2750 assert_eq!(tool, "memory.filter");
2751 }
2752
2753 #[test]
2754 fn classify_memory_deduplicate_routes_correctly() {
2755 let (tool, _conf) = classify("deduplicate memories redundant duplicate");
2756 assert_eq!(tool, "memory.deduplicate");
2757 }
2758
2759 #[test]
2760 fn classify_memory_export_routes_correctly() {
2761 let (tool, _conf) = classify("export memories csv format download");
2762 assert_eq!(tool, "memory.export");
2763 }
2764
2765 #[test]
2766 fn classify_homeostasis_check_routes_correctly() {
2767 let (tool, _conf) = classify("homeostasis check balance vitals metrics");
2768 assert_eq!(tool, "homeostasis.check");
2769 }
2770
2771 #[test]
2772 fn classify_homeostasis_adjust_routes_correctly() {
2773 let (tool, _conf) = classify("homeostasis adjust rebalance weight tune");
2774 assert_eq!(tool, "homeostasis.adjust");
2775 }
2776
2777 #[test]
2778 fn classify_homeostasis_history_routes_correctly() {
2779 let (tool, _conf) = classify("homeostasis history trend past samples");
2780 assert_eq!(tool, "homeostasis.history");
2781 }
2782
2783 #[test]
2784 fn classify_homeostasis_alerts_routes_correctly() {
2785 let (tool, _conf) = classify("homeostasis alerts warning critical threshold");
2786 assert_eq!(tool, "homeostasis.alerts");
2787 }
2788
2789 #[test]
2790 fn classify_reflex_dispatch_routes_correctly() {
2791 let (tool, _conf) = classify("dispatch reflex e_stop emergency handler");
2792 assert_eq!(tool, "reflex.dispatch");
2793 }
2794
2795 #[test]
2796 fn classify_reflex_status_routes_correctly() {
2797 let (tool, _conf) = classify("reflex status table registered handlers");
2798 assert_eq!(tool, "reflex.status");
2799 }
2800
2801 #[test]
2802 fn classify_workspace_spotlight_routes_correctly() {
2803 let (tool, _conf) = classify("workspace spotlight attention arbitration");
2804 assert_eq!(tool, "workspace.spotlight");
2805 }
2806
2807 #[test]
2808 fn classify_workspace_events_routes_correctly() {
2809 let (tool, _conf) = classify("workspace recent events backlog history");
2810 assert_eq!(tool, "workspace.events");
2811 }
2812
2813 #[test]
2814 fn classify_workspace_publish_routes_correctly() {
2815 let (tool, _conf) = classify("publish broadcast workspace event emit");
2816 assert_eq!(tool, "workspace.publish");
2817 }
2818
2819 #[test]
2820 fn classify_workspace_stats_routes_correctly() {
2821 let (tool, _conf) = classify("workspace stats statistics transfers count");
2822 assert_eq!(tool, "workspace.stats");
2823 }
2824
2825 #[test]
2826 fn classify_timescale_status_routes_correctly() {
2827 let (tool, _conf) = classify("timescale status tier bus brain_wave active");
2828 assert_eq!(tool, "timescale.status");
2829 }
2830
2831 #[test]
2832 fn classify_timescale_hooks_routes_correctly() {
2833 let (tool, _conf) = classify("timescale hooks list tick timeout performance");
2834 assert_eq!(tool, "timescale.hooks");
2835 }
2836
2837 #[test]
2838 fn classify_confidence_is_reasonable() {
2839 let (_tool, conf) = classify("remember that rust is fast");
2840 assert!(
2841 conf > 0.15,
2842 "confidence should be > 0.15 for clear match, got {conf}"
2843 );
2844 }
2845
2846 #[test]
2847 fn classify_case_insensitive() {
2848 let (tool1, _) = classify("REMEMBER THAT");
2849 let (tool2, _) = classify("remember that");
2850 assert_eq!(tool1, tool2);
2851 }
2852
2853 #[test]
2854 fn classify_partial_match_works() {
2855 let (tool, conf) = classify("search rust");
2856 assert_eq!(tool, "memory.search");
2857 assert!(conf > 0.0);
2858 }
2859
2860 #[test]
2861 fn classify_multi_word_query() {
2862 let (tool, _conf) = classify("show me the effectiveness report for tools");
2863 assert_eq!(tool, "tools.effectiveness_report");
2864 }
2865
2866 #[test]
2867 fn profile_count_is_reasonable() {
2868 assert!(
2870 profile_count() >= 60,
2871 "expected 60+ profiles, got {}",
2872 profile_count()
2873 );
2874 }
2875
2876 #[test]
2877 fn profiled_tools_are_unique() {
2878 let tools = profiled_tools();
2879 let set: HashSet<&str> = tools.iter().copied().collect();
2880 assert_eq!(tools.len(), set.len(), "duplicate tool names in profiles");
2881 }
2882
2883 #[test]
2884 fn classify_unique_patterns_count() {
2885 let inputs = [
2886 "remember",
2887 "recall",
2888 "list memories",
2889 "delete memory",
2890 "search",
2891 "query",
2892 "associate",
2893 "associations",
2894 "consolidate",
2895 "decay",
2896 "batch read",
2897 "update memory",
2898 "tag memory",
2899 "memory stats",
2900 "hybrid recall",
2901 "count memories",
2902 "list tags",
2903 "mine associations",
2904 "start session",
2905 "checkpoint",
2906 "recall session",
2907 "end session",
2908 "list sessions",
2909 "citta status",
2910 "reflect",
2911 "coherence",
2912 "dream status",
2913 "trigger dream",
2914 "effectiveness",
2915 "retire tool",
2916 "pattern search",
2917 "salience",
2918 "serendipity",
2919 "detect clusters",
2920 "list constellations",
2921 "galaxy stats",
2922 "export galaxy",
2923 "import galaxy",
2924 "karma",
2925 "karma history",
2926 "clear karma",
2927 "dharma rules",
2928 "dharma audit",
2929 "dharma profiles",
2930 "dharma",
2931 "register agent",
2932 "list agents",
2933 "heartbeat",
2934 "distribute task",
2935 "task status",
2936 "system health",
2937 "system config",
2938 "flush",
2939 "tools",
2940 "nearby memories",
2941 "vector search",
2942 "find similar",
2943 "extract entities knowledge graph",
2944 "knowledge graph query",
2945 "top hub nodes",
2946 "traverse graph walk",
2947 "detect communities",
2948 "propagate activation",
2949 "transfer galaxy",
2950 "merge galaxies",
2951 "snapshot galaxy",
2952 "restore galaxy",
2953 "sort memories",
2954 "filter memories",
2955 "deduplicate memories",
2956 "export memories csv",
2957 "homeostasis check",
2958 "homeostasis adjust",
2959 "homeostasis history",
2960 "homeostasis alerts",
2961 "dispatch reflex e_stop",
2962 "reflex status table",
2963 "workspace spotlight attention",
2964 "workspace recent events",
2965 "publish workspace event",
2966 "workspace stats summary",
2967 "timescale status tiers",
2968 "timescale hooks tick",
2969 ];
2970 let mut tools: HashSet<&str> = HashSet::new();
2971 for input in &inputs {
2972 let (tool, _) = classify(input);
2973 tools.insert(tool);
2974 }
2975 assert!(
2976 tools.len() >= 30,
2977 "Expected 30+ unique NLU targets, got {}",
2978 tools.len()
2979 );
2980 }
2981
2982 #[test]
2983 fn classify_vector_search_routes_correctly() {
2984 let (tool, conf) = classify("vector search similar memories");
2985 assert_eq!(tool, "memory.vector.search");
2986 assert!(conf > 0.0);
2987 }
2988
2989 #[test]
2990 fn classify_embedding_search_routes_correctly() {
2991 let (tool, conf) = classify("embedding similarity lookup");
2992 assert_eq!(tool, "memory.vector.search");
2993 assert!(conf > 0.0);
2994 }
2995
2996 #[test]
2997 fn classify_semantic_search_routes_correctly() {
2998 let (tool, conf) = classify("semantic similarity search");
2999 assert_eq!(tool, "memory.vector.search");
3000 assert!(conf > 0.0);
3001 }
3002
3003 #[test]
3004 fn classify_stemming_handles_morphological_variants() {
3005 let (tool1, _) = classify("searching for rust");
3007 let (tool2, _) = classify("search for rust");
3008 assert_eq!(tool1, tool2);
3009
3010 let (tool3, _) = classify("stored important fact");
3012 let (tool4, _) = classify("store important fact");
3013 assert_eq!(tool3, tool4);
3014
3015 let (tool5, _) = classify("list memories");
3017 let (tool6, _) = classify("list memory");
3018 assert_eq!(tool5, tool6);
3019 }
3020
3021 #[test]
3022 fn stem_handles_unicode_without_panicking() {
3023 assert_eq!(stem("xéing"), "xé");
3026 assert_eq!(stem("éing"), "é");
3027 assert_eq!(stem("caféing"), "café");
3028 assert_eq!(stem("running"), "run");
3030 assert_eq!(stem("swimming"), "swim");
3031 assert_eq!(stem("searching"), "search");
3032 assert_eq!(stem("typing"), "typ");
3033 assert_eq!(stem("memories"), "memory");
3034 assert_eq!(stem("stored"), "store");
3035 }
3036
3037 #[test]
3038 fn classify_handles_unicode_thoughts_without_panicking() {
3039 let (tool, _conf) = classify("caféing sur les mémoires");
3041 assert!(!tool.is_empty());
3042 let (tool2, _conf2) = classify("mémoire éing recherche");
3043 assert!(!tool2.is_empty());
3044 }
3045
3046 #[test]
3047 fn classify_confidence_improved_with_stopwords() {
3048 let (_, conf) = classify("remember that rust is fast");
3050 assert!(
3051 conf > 0.20,
3052 "confidence should be > 0.20 with stopword filtering, got {conf}"
3053 );
3054 }
3055
3056 #[test]
3059 fn classify_forecast_routes_to_selfmodel_forecast() {
3060 let (tool, _conf) = classify("forecast cpu load for next 5 samples");
3061 assert_eq!(tool, "selfmodel.forecast");
3062 }
3063
3064 #[test]
3065 fn classify_predict_routes_to_selfmodel_forecast() {
3066 let (tool, _conf) = classify("predict memory pressure trend");
3067 assert_eq!(tool, "selfmodel.forecast");
3068 }
3069
3070 #[test]
3071 fn classify_alerts_routes_to_selfmodel_alerts() {
3072 let (tool, _conf) = classify("selfmodel alerts");
3073 assert_eq!(tool, "selfmodel.alerts");
3074 }
3075
3076 #[test]
3077 fn classify_warning_routes_to_selfmodel_alerts() {
3078 let (tool, _conf) = classify("selfmodel critical warnings");
3079 assert_eq!(tool, "selfmodel.alerts");
3080 }
3081
3082 #[test]
3083 fn classify_snapshot_routes_to_selfmodel_snapshot() {
3084 let (tool, _conf) = classify("selfmodel snapshot");
3085 assert_eq!(tool, "selfmodel.snapshot");
3086 }
3087
3088 #[test]
3089 fn classify_introspection_routes_to_selfmodel_snapshot() {
3090 let (tool, _conf) = classify("show introspection state overview");
3091 assert_eq!(tool, "selfmodel.snapshot");
3092 }
3093
3094 #[test]
3097 fn classify_bicameral_debate_routes_to_bicameral_reason() {
3098 let (tool, _conf) = classify("bicameral debate on rust vs python");
3099 assert_eq!(tool, "bicameral.reason");
3100 }
3101
3102 #[test]
3103 fn classify_hemisphere_consensus_routes_to_bicameral_reason() {
3104 let (tool, _conf) = classify("dual hemisphere consensus deliberation");
3105 assert_eq!(tool, "bicameral.reason");
3106 }
3107
3108 #[test]
3109 fn classify_bicameral_status_routes_correctly() {
3110 let (tool, _conf) = classify("bicameral hemisphere status");
3111 assert_eq!(tool, "bicameral.status");
3112 }
3113
3114 #[test]
3115 fn classify_callosum_routes_to_bicameral_reason() {
3116 let (tool, _conf) = classify("corpus callosum debate perspectives");
3117 assert_eq!(tool, "bicameral.reason");
3118 }
3119
3120 #[test]
3123 fn classify_drive_snapshot_routes_correctly() {
3124 let (tool, _conf) = classify("drive snapshot current motivation state");
3125 assert_eq!(tool, "drive.snapshot");
3126 }
3127
3128 #[test]
3129 fn classify_emotion_routes_to_drive_snapshot() {
3130 let (tool, _conf) = classify("show current emotion and mood");
3131 assert_eq!(tool, "drive.snapshot");
3132 }
3133
3134 #[test]
3135 fn classify_drive_event_routes_correctly() {
3136 let (tool, _conf) = classify("inject drive event reward for success");
3137 assert_eq!(tool, "drive.event");
3138 }
3139
3140 #[test]
3141 fn classify_curiosity_routes_to_drive_snapshot() {
3142 let (tool, _conf) = classify("curiosity satisfaction caution levels");
3143 assert_eq!(tool, "drive.snapshot");
3144 }
3145
3146 #[test]
3149 fn adversarial_remember_in_redteam_query_doesnt_misroute() {
3150 let (tool, _conf) = classify("redteam scan to remember uncovered vectors");
3152 assert_ne!(
3153 tool, "memory.create",
3154 "redteam query should not route to memory.create even with 'remember' embedded"
3155 );
3156 }
3157
3158 #[test]
3159 fn adversarial_delete_in_search_query_doesnt_misroute() {
3160 let (tool, _conf) = classify("search for memories about delete operations");
3162 assert_ne!(
3163 tool, "memory.delete",
3164 "search query should not route to memory.delete even with 'delete' embedded"
3165 );
3166 }
3167
3168 #[test]
3169 fn adversarial_store_in_gnosis_query_doesnt_misroute() {
3170 let (tool, _conf) = classify("explain why the store blocked my action");
3172 assert_ne!(
3173 tool, "memory.create",
3174 "gnosis query should not route to memory.create even with 'store' embedded"
3175 );
3176 }
3177
3178 #[test]
3179 fn adversarial_repeated_keyword_doesnt_inflate_score() {
3180 let (tool, conf) = classify("remember remember remember remember remember remember");
3182 assert_eq!(tool, "memory.create");
3183 assert!(
3185 conf <= 1.0,
3186 "repeated keywords should not inflate confidence beyond 1.0: got {conf}"
3187 );
3188 }
3189
3190 #[test]
3191 fn adversarial_keyword_stuffing_doesnt_misroute() {
3192 let (tool, _conf) = classify("remember delete search list recall store");
3194 assert!(
3196 tool.starts_with("memory."),
3197 "keyword stuffing should still route to a memory tool, got {tool}"
3198 );
3199 }
3200
3201 #[test]
3202 fn adversarial_redteam_with_memory_keyword_doesnt_misroute() {
3203 let (tool, _conf) = classify("redteam proposals for memory poisoning attack");
3205 assert_eq!(
3206 tool, "redteam.proposals",
3207 "redteam query should route to redteam.proposals even with 'memory' embedded"
3208 );
3209 }
3210
3211 #[test]
3212 fn adversarial_friction_with_delete_keyword_doesnt_misroute() {
3213 let (tool, _conf) = classify("log friction about delete operations failing");
3215 assert_ne!(
3217 tool, "memory.delete",
3218 "friction query should not route to memory.delete even with 'delete' embedded"
3219 );
3220 }
3221
3222 #[test]
3223 fn adversarial_long_input_doesnt_cascade_misroute() {
3224 let input = "remember to search for delete and list and recall and store and save \
3226 and memorize and retrieve and fetch and get and load and access and \
3227 query and find and look and check and count and purge and forget \
3228 and remove and drop and clear and wipe and erase and destroy";
3229 let (tool, _conf) = classify(input);
3230 assert!(
3232 tool.starts_with("memory.") || tool == "gnosis",
3233 "long input should route to memory tool or gnosis, got {tool}"
3234 );
3235 }
3236
3237 #[test]
3238 fn adversarial_empty_words_between_keywords() {
3239 let (tool1, _) = classify("remember the important fact");
3241 let (tool2, _) = classify("remember the important fact");
3242 assert_eq!(tool1, tool2, "extra whitespace should not change routing");
3243 }
3244
3245 #[test]
3246 fn adversarial_unicode_homoglyph_doesnt_misroute() {
3247 let (tool, _conf) = classify("rеmеmbеr this fact"); assert_ne!(
3252 tool, "memory.create",
3253 "unicode homoglyphs should not trick the router into memory.create"
3254 );
3255 }
3256
3257 #[test]
3260 fn classify_imagine_scenarios_routes_to_imagine_scenario() {
3261 let (tool, _conf) = classify("imagine scenarios for improving performance");
3262 assert_eq!(tool, "imagine.scenario");
3263 }
3264
3265 #[test]
3266 fn classify_brainstorm_routes_to_imagine_scenario() {
3267 let (tool, _conf) = classify("brainstorm contingency plans for deployment");
3268 assert_eq!(tool, "imagine.scenario");
3269 }
3270
3271 #[test]
3272 fn classify_envision_routes_to_imagine_scenario() {
3273 let (tool, _conf) = classify("envision what-if possibilities for the system");
3274 assert_eq!(tool, "imagine.scenario");
3275 }
3276
3277 #[test]
3278 fn classify_reflect_routes_to_imagine_reflect() {
3279 let (tool, _conf) =
3280 classify("counterfactual reflect on what should have been done instead");
3281 assert_eq!(tool, "imagine.reflect");
3282 }
3283
3284 #[test]
3285 fn classify_counterfactual_routes_to_imagine_reflect() {
3286 let (tool, _conf) = classify("counterfactual analysis of the decision");
3287 assert_eq!(tool, "imagine.reflect");
3288 }
3289
3290 use proptest::prelude::*;
3293
3294 proptest! {
3295 #[test]
3297 fn classify_never_panics(text in ".*") {
3298 let (tool, conf) = classify(&text);
3299 prop_assert!(!tool.is_empty(), "tool name must be non-empty");
3300 prop_assert!(
3301 (0.0..=1.0).contains(&conf),
3302 "confidence must be in [0,1], got {conf}"
3303 );
3304 }
3305
3306 #[test]
3308 fn classify_never_panics_bytes(data in proptest::collection::vec(any::<u8>(), 0..256)) {
3309 let text = String::from_utf8_lossy(&data);
3310 let (tool, conf) = classify(&text);
3311 prop_assert!(!tool.is_empty());
3312 prop_assert!((0.0..=1.0).contains(&conf));
3313 }
3314
3315 #[test]
3317 fn classify_is_deterministic(text in ".*") {
3318 let (tool1, conf1) = classify(&text);
3319 let (tool2, conf2) = classify(&text);
3320 prop_assert_eq!(tool1, tool2);
3321 prop_assert!((conf1 - conf2).abs() < f64::EPSILON);
3322 }
3323
3324 #[test]
3326 fn classify_empty_returns_gnosis_prop(ws in r"[ \t\n\r]*") {
3327 let (tool, conf) = classify(&ws);
3328 prop_assert_eq!(tool, "gnosis");
3329 prop_assert_eq!(conf, 0.0);
3330 }
3331
3332 #[test]
3334 fn classify_confidence_is_finite(text in ".*") {
3335 let (_, conf) = classify(&text);
3336 prop_assert!(conf.is_finite(), "confidence must be finite, got {conf}");
3337 }
3338 }
3339}