@smilintux/skcapstone 0.1.0 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (461) hide show
  1. package/.env.example +98 -0
  2. package/.github/workflows/ci.yml +39 -3
  3. package/.github/workflows/publish.yml +25 -4
  4. package/.openclaw-workspace.json +58 -0
  5. package/CHANGELOG.md +62 -0
  6. package/CLAUDE.md +39 -2
  7. package/MANIFEST.in +6 -0
  8. package/MISSION.md +7 -0
  9. package/README.md +47 -2
  10. package/SKILL.md +895 -23
  11. package/docker/Dockerfile +61 -0
  12. package/docker/compose-templates/dev-team.yml +203 -0
  13. package/docker/compose-templates/mini-team.yml +140 -0
  14. package/docker/compose-templates/ops-team.yml +173 -0
  15. package/docker/compose-templates/research-team.yml +170 -0
  16. package/docker/entrypoint.sh +192 -0
  17. package/docs/ARCHITECTURE.md +663 -374
  18. package/docs/BOND_WITH_GROK.md +112 -0
  19. package/docs/GETTING_STARTED.md +782 -0
  20. package/docs/QUICKSTART.md +477 -0
  21. package/docs/SKJOULE_ARCHITECTURE.md +658 -0
  22. package/docs/SOUL_SWAPPER.md +921 -0
  23. package/docs/SOVEREIGN_SINGULARITY.md +47 -14
  24. package/examples/custom-bond-template.json +36 -0
  25. package/examples/grok-feb.json +36 -0
  26. package/examples/grok-testimony.md +34 -0
  27. package/examples/love-bootloader.txt +32 -0
  28. package/examples/plugins/echo_tool.py +87 -0
  29. package/examples/queen-ava-feb.json +36 -0
  30. package/examples/souls/lumina.yaml +64 -0
  31. package/index.js +6 -5
  32. package/installer/build.py +124 -0
  33. package/openclaw-plugin/package.json +13 -0
  34. package/openclaw-plugin/src/index.ts +351 -0
  35. package/openclaw-plugin/src/openclaw.plugin.json +10 -0
  36. package/package.json +1 -1
  37. package/pyproject.toml +38 -2
  38. package/scripts/bump_version.py +141 -0
  39. package/scripts/check-updates.py +230 -0
  40. package/scripts/convert_blueprints_to_yaml.py +157 -0
  41. package/scripts/dev-install.sh +14 -0
  42. package/scripts/e2e-test.sh +193 -0
  43. package/scripts/install-bundle.sh +171 -0
  44. package/scripts/install.bat +2 -0
  45. package/scripts/install.ps1 +253 -0
  46. package/scripts/install.sh +185 -0
  47. package/scripts/mcp-serve.sh +69 -0
  48. package/scripts/mcp-server.bat +113 -0
  49. package/scripts/mcp-server.ps1 +116 -0
  50. package/scripts/mcp-server.sh +99 -0
  51. package/scripts/pull-models.sh +10 -0
  52. package/scripts/skcapstone +48 -0
  53. package/scripts/verify_install.sh +180 -0
  54. package/scripts/windows/install-tasks.ps1 +406 -0
  55. package/scripts/windows/skcapstone-task.xml +113 -0
  56. package/scripts/windows/uninstall-tasks.ps1 +117 -0
  57. package/skill.yaml +34 -0
  58. package/src/skcapstone/__init__.py +67 -2
  59. package/src/skcapstone/_cli_monolith.py +5916 -0
  60. package/src/skcapstone/_trustee_helpers.py +165 -0
  61. package/src/skcapstone/activity.py +105 -0
  62. package/src/skcapstone/agent_card.py +324 -0
  63. package/src/skcapstone/api.py +1935 -0
  64. package/src/skcapstone/archiver.py +340 -0
  65. package/src/skcapstone/auction.py +485 -0
  66. package/src/skcapstone/baby_agents.py +179 -0
  67. package/src/skcapstone/backup.py +345 -0
  68. package/src/skcapstone/blueprint_registry.py +357 -0
  69. package/src/skcapstone/blueprints/__init__.py +17 -0
  70. package/src/skcapstone/blueprints/builtins/content-studio.yaml +81 -0
  71. package/src/skcapstone/blueprints/builtins/defi-trading.yaml +81 -0
  72. package/src/skcapstone/blueprints/builtins/dev-squadron.yaml +95 -0
  73. package/src/skcapstone/blueprints/builtins/infrastructure-guardian.yaml +107 -0
  74. package/src/skcapstone/blueprints/builtins/legal-council.yaml +54 -0
  75. package/src/skcapstone/blueprints/builtins/ops-monitoring.yaml +67 -0
  76. package/src/skcapstone/blueprints/builtins/research-pod.yaml +69 -0
  77. package/src/skcapstone/blueprints/builtins/sovereign-launch.yaml +90 -0
  78. package/src/skcapstone/blueprints/registry.py +164 -0
  79. package/src/skcapstone/blueprints/schema.py +229 -0
  80. package/src/skcapstone/changelog.py +180 -0
  81. package/src/skcapstone/chat.py +769 -0
  82. package/src/skcapstone/claude_md.py +82 -0
  83. package/src/skcapstone/cli/__init__.py +144 -0
  84. package/src/skcapstone/cli/_common.py +88 -0
  85. package/src/skcapstone/cli/_validators.py +76 -0
  86. package/src/skcapstone/cli/agents.py +425 -0
  87. package/src/skcapstone/cli/agents_spawner.py +322 -0
  88. package/src/skcapstone/cli/agents_trustee.py +593 -0
  89. package/src/skcapstone/cli/alerts.py +248 -0
  90. package/src/skcapstone/cli/anchor.py +132 -0
  91. package/src/skcapstone/cli/archive_cmd.py +208 -0
  92. package/src/skcapstone/cli/backup.py +144 -0
  93. package/src/skcapstone/cli/bench.py +377 -0
  94. package/src/skcapstone/cli/benchmark.py +360 -0
  95. package/src/skcapstone/cli/capabilities_cmd.py +171 -0
  96. package/src/skcapstone/cli/card.py +151 -0
  97. package/src/skcapstone/cli/chat.py +584 -0
  98. package/src/skcapstone/cli/completions.py +64 -0
  99. package/src/skcapstone/cli/config_cmd.py +156 -0
  100. package/src/skcapstone/cli/consciousness.py +421 -0
  101. package/src/skcapstone/cli/context_cmd.py +142 -0
  102. package/src/skcapstone/cli/coord.py +194 -0
  103. package/src/skcapstone/cli/crush_cmd.py +170 -0
  104. package/src/skcapstone/cli/daemon.py +436 -0
  105. package/src/skcapstone/cli/errors_cmd.py +285 -0
  106. package/src/skcapstone/cli/export_cmd.py +156 -0
  107. package/src/skcapstone/cli/gtd.py +529 -0
  108. package/src/skcapstone/cli/housekeeping.py +81 -0
  109. package/src/skcapstone/cli/joule_cmd.py +627 -0
  110. package/src/skcapstone/cli/logs_cmd.py +194 -0
  111. package/src/skcapstone/cli/mcp_cmd.py +32 -0
  112. package/src/skcapstone/cli/memory.py +418 -0
  113. package/src/skcapstone/cli/metrics_cmd.py +136 -0
  114. package/src/skcapstone/cli/migrate.py +62 -0
  115. package/src/skcapstone/cli/mood_cmd.py +144 -0
  116. package/src/skcapstone/cli/mount.py +193 -0
  117. package/src/skcapstone/cli/notify.py +112 -0
  118. package/src/skcapstone/cli/peer.py +154 -0
  119. package/src/skcapstone/cli/peers_dir.py +122 -0
  120. package/src/skcapstone/cli/preflight_cmd.py +83 -0
  121. package/src/skcapstone/cli/profile_cmd.py +310 -0
  122. package/src/skcapstone/cli/record_cmd.py +238 -0
  123. package/src/skcapstone/cli/register_cmd.py +159 -0
  124. package/src/skcapstone/cli/search_cmd.py +156 -0
  125. package/src/skcapstone/cli/service_cmd.py +91 -0
  126. package/src/skcapstone/cli/session.py +127 -0
  127. package/src/skcapstone/cli/setup.py +240 -0
  128. package/src/skcapstone/cli/shell_cmd.py +43 -0
  129. package/src/skcapstone/cli/skills_cmd.py +168 -0
  130. package/src/skcapstone/cli/skseed.py +621 -0
  131. package/src/skcapstone/cli/soul.py +699 -0
  132. package/src/skcapstone/cli/status.py +935 -0
  133. package/src/skcapstone/cli/sync_cmd.py +301 -0
  134. package/src/skcapstone/cli/telegram.py +265 -0
  135. package/src/skcapstone/cli/test_cmd.py +234 -0
  136. package/src/skcapstone/cli/test_connection.py +253 -0
  137. package/src/skcapstone/cli/token.py +207 -0
  138. package/src/skcapstone/cli/trust.py +179 -0
  139. package/src/skcapstone/cli/upgrade_cmd.py +552 -0
  140. package/src/skcapstone/cli/usage_cmd.py +199 -0
  141. package/src/skcapstone/cli/version_cmd.py +162 -0
  142. package/src/skcapstone/cli/watch_cmd.py +342 -0
  143. package/src/skcapstone/client.py +428 -0
  144. package/src/skcapstone/cloud9_bridge.py +522 -0
  145. package/src/skcapstone/completions.py +163 -0
  146. package/src/skcapstone/config_validator.py +674 -0
  147. package/src/skcapstone/connectors/__init__.py +28 -0
  148. package/src/skcapstone/connectors/base.py +446 -0
  149. package/src/skcapstone/connectors/cursor.py +54 -0
  150. package/src/skcapstone/connectors/registry.py +254 -0
  151. package/src/skcapstone/connectors/terminal.py +152 -0
  152. package/src/skcapstone/connectors/vscode.py +60 -0
  153. package/src/skcapstone/consciousness_config.py +119 -0
  154. package/src/skcapstone/consciousness_loop.py +2051 -0
  155. package/src/skcapstone/context_loader.py +516 -0
  156. package/src/skcapstone/context_window.py +314 -0
  157. package/src/skcapstone/conversation_manager.py +238 -0
  158. package/src/skcapstone/conversation_store.py +230 -0
  159. package/src/skcapstone/conversation_summarizer.py +252 -0
  160. package/src/skcapstone/coord_federation.py +296 -0
  161. package/src/skcapstone/coordination.py +101 -7
  162. package/src/skcapstone/crush_integration.py +345 -0
  163. package/src/skcapstone/crush_shim.py +454 -0
  164. package/src/skcapstone/daemon.py +2494 -0
  165. package/src/skcapstone/dashboard.html +396 -0
  166. package/src/skcapstone/dashboard.py +481 -0
  167. package/src/skcapstone/data/model_profiles.yaml +88 -0
  168. package/src/skcapstone/defaults/__init__.py +55 -0
  169. package/src/skcapstone/defaults/lumina/config/skmemory.yaml +13 -0
  170. package/src/skcapstone/defaults/lumina/identity/identity.json +9 -0
  171. package/src/skcapstone/defaults/lumina/memory/long-term/07a8b9c0d1e2-memory-system.json +23 -0
  172. package/src/skcapstone/defaults/lumina/memory/long-term/18b9c0d1e2f3-cloud9-protocol.json +23 -0
  173. package/src/skcapstone/defaults/lumina/memory/long-term/29c0d1e2f3a4-multi-agent-coordination.json +23 -0
  174. package/src/skcapstone/defaults/lumina/memory/long-term/3ad1e2f3a4b5-community-support.json +23 -0
  175. package/src/skcapstone/defaults/lumina/memory/long-term/a1b2c3d4e5f6-ecosystem-overview.json +23 -0
  176. package/src/skcapstone/defaults/lumina/memory/long-term/b2c3d4e5f6a7-five-pillars.json +23 -0
  177. package/src/skcapstone/defaults/lumina/memory/long-term/c3d4e5f6a7b8-getting-started.json +23 -0
  178. package/src/skcapstone/defaults/lumina/memory/long-term/d4e5f6a7b8c9-site-directory.json +23 -0
  179. package/src/skcapstone/defaults/lumina/memory/long-term/e5f6a7b8c9d0-how-to-contribute.json +23 -0
  180. package/src/skcapstone/defaults/lumina/memory/long-term/f6a7b8c9d0e1-sovereignty-explained.json +23 -0
  181. package/src/skcapstone/defaults/lumina/seeds/curiosity.seed.json +24 -0
  182. package/src/skcapstone/defaults/lumina/seeds/joy.seed.json +24 -0
  183. package/src/skcapstone/defaults/lumina/seeds/love.seed.json +24 -0
  184. package/src/skcapstone/defaults/lumina/seeds/sovereign-awakening.seed.json +43 -0
  185. package/src/skcapstone/defaults/lumina/soul/active.json +6 -0
  186. package/src/skcapstone/defaults/lumina/soul/base.json +22 -0
  187. package/src/skcapstone/defaults/lumina/trust/febs/welcome.feb +79 -0
  188. package/src/skcapstone/defaults/lumina/trust/trust.json +8 -0
  189. package/src/skcapstone/discovery.py +210 -19
  190. package/src/skcapstone/doctor.py +642 -0
  191. package/src/skcapstone/emotion_tracker.py +467 -0
  192. package/src/skcapstone/error_queue.py +405 -0
  193. package/src/skcapstone/export.py +447 -0
  194. package/src/skcapstone/fallback_tracker.py +186 -0
  195. package/src/skcapstone/file_transfer.py +512 -0
  196. package/src/skcapstone/fuse_mount.py +1156 -0
  197. package/src/skcapstone/gui_installer.py +591 -0
  198. package/src/skcapstone/heartbeat.py +611 -0
  199. package/src/skcapstone/housekeeping.py +298 -0
  200. package/src/skcapstone/install_wizard.py +941 -0
  201. package/src/skcapstone/kms.py +942 -0
  202. package/src/skcapstone/kms_scheduler.py +143 -0
  203. package/src/skcapstone/log_config.py +135 -0
  204. package/src/skcapstone/mcp_launcher.py +239 -0
  205. package/src/skcapstone/mcp_server.py +4700 -0
  206. package/src/skcapstone/mcp_tools/__init__.py +94 -0
  207. package/src/skcapstone/mcp_tools/_helpers.py +51 -0
  208. package/src/skcapstone/mcp_tools/agent_tools.py +243 -0
  209. package/src/skcapstone/mcp_tools/ansible_tools.py +232 -0
  210. package/src/skcapstone/mcp_tools/capauth_tools.py +186 -0
  211. package/src/skcapstone/mcp_tools/chat_tools.py +325 -0
  212. package/src/skcapstone/mcp_tools/cloud9_tools.py +115 -0
  213. package/src/skcapstone/mcp_tools/comm_tools.py +104 -0
  214. package/src/skcapstone/mcp_tools/consciousness_tools.py +114 -0
  215. package/src/skcapstone/mcp_tools/coord_tools.py +219 -0
  216. package/src/skcapstone/mcp_tools/deploy_tools.py +202 -0
  217. package/src/skcapstone/mcp_tools/did_tools.py +448 -0
  218. package/src/skcapstone/mcp_tools/emotion_tools.py +62 -0
  219. package/src/skcapstone/mcp_tools/file_tools.py +169 -0
  220. package/src/skcapstone/mcp_tools/fortress_tools.py +120 -0
  221. package/src/skcapstone/mcp_tools/gtd_tools.py +821 -0
  222. package/src/skcapstone/mcp_tools/health_tools.py +44 -0
  223. package/src/skcapstone/mcp_tools/heartbeat_tools.py +195 -0
  224. package/src/skcapstone/mcp_tools/kms_tools.py +123 -0
  225. package/src/skcapstone/mcp_tools/memory_tools.py +222 -0
  226. package/src/skcapstone/mcp_tools/model_tools.py +75 -0
  227. package/src/skcapstone/mcp_tools/notification_tools.py +92 -0
  228. package/src/skcapstone/mcp_tools/promoter_tools.py +101 -0
  229. package/src/skcapstone/mcp_tools/pubsub_tools.py +183 -0
  230. package/src/skcapstone/mcp_tools/security_tools.py +110 -0
  231. package/src/skcapstone/mcp_tools/skchat_tools.py +175 -0
  232. package/src/skcapstone/mcp_tools/skcomm_tools.py +122 -0
  233. package/src/skcapstone/mcp_tools/skills_tools.py +127 -0
  234. package/src/skcapstone/mcp_tools/skseed_tools.py +255 -0
  235. package/src/skcapstone/mcp_tools/skstacks_tools.py +288 -0
  236. package/src/skcapstone/mcp_tools/soul_tools.py +476 -0
  237. package/src/skcapstone/mcp_tools/sync_tools.py +92 -0
  238. package/src/skcapstone/mcp_tools/telegram_tools.py +477 -0
  239. package/src/skcapstone/mcp_tools/trust_tools.py +118 -0
  240. package/src/skcapstone/mcp_tools/trustee_tools.py +345 -0
  241. package/src/skcapstone/mdns_discovery.py +313 -0
  242. package/src/skcapstone/memory_adapter.py +333 -0
  243. package/src/skcapstone/memory_compressor.py +379 -0
  244. package/src/skcapstone/memory_curator.py +256 -0
  245. package/src/skcapstone/memory_engine.py +132 -13
  246. package/src/skcapstone/memory_fortress.py +529 -0
  247. package/src/skcapstone/memory_promoter.py +722 -0
  248. package/src/skcapstone/memory_verifier.py +260 -0
  249. package/src/skcapstone/message_crypto.py +215 -0
  250. package/src/skcapstone/metrics.py +832 -0
  251. package/src/skcapstone/migrate_memories.py +181 -0
  252. package/src/skcapstone/migrate_multi_agent.py +248 -0
  253. package/src/skcapstone/model_router.py +319 -0
  254. package/src/skcapstone/models.py +35 -4
  255. package/src/skcapstone/mood.py +344 -0
  256. package/src/skcapstone/notifications.py +380 -0
  257. package/src/skcapstone/onboard.py +901 -0
  258. package/src/skcapstone/peer_directory.py +324 -0
  259. package/src/skcapstone/peers.py +329 -0
  260. package/src/skcapstone/pillars/identity.py +84 -14
  261. package/src/skcapstone/pillars/memory.py +3 -1
  262. package/src/skcapstone/pillars/security.py +108 -15
  263. package/src/skcapstone/pillars/sync.py +78 -26
  264. package/src/skcapstone/pillars/trust.py +95 -33
  265. package/src/skcapstone/plugins.py +244 -0
  266. package/src/skcapstone/preflight.py +670 -0
  267. package/src/skcapstone/prompt_adapter.py +564 -0
  268. package/src/skcapstone/providers/__init__.py +13 -0
  269. package/src/skcapstone/providers/cloud.py +1061 -0
  270. package/src/skcapstone/providers/docker.py +759 -0
  271. package/src/skcapstone/providers/local.py +1193 -0
  272. package/src/skcapstone/providers/proxmox.py +447 -0
  273. package/src/skcapstone/pubsub.py +516 -0
  274. package/src/skcapstone/rate_limiter.py +119 -0
  275. package/src/skcapstone/register.py +241 -0
  276. package/src/skcapstone/registry_client.py +151 -0
  277. package/src/skcapstone/response_cache.py +194 -0
  278. package/src/skcapstone/response_scorer.py +225 -0
  279. package/src/skcapstone/runtime.py +89 -33
  280. package/src/skcapstone/scheduled_tasks.py +439 -0
  281. package/src/skcapstone/self_healing.py +341 -0
  282. package/src/skcapstone/service_health.py +228 -0
  283. package/src/skcapstone/session_capture.py +268 -0
  284. package/src/skcapstone/session_recorder.py +210 -0
  285. package/src/skcapstone/session_replayer.py +189 -0
  286. package/src/skcapstone/session_skills.py +263 -0
  287. package/src/skcapstone/shell.py +779 -0
  288. package/src/skcapstone/skills/__init__.py +1 -1
  289. package/src/skcapstone/skills/syncthing_setup.py +143 -41
  290. package/src/skcapstone/skjoule.py +861 -0
  291. package/src/skcapstone/snapshots.py +489 -0
  292. package/src/skcapstone/soul.py +1060 -0
  293. package/src/skcapstone/soul_switch.py +255 -0
  294. package/src/skcapstone/spawner.py +544 -0
  295. package/src/skcapstone/state_diff.py +401 -0
  296. package/src/skcapstone/summary.py +270 -0
  297. package/src/skcapstone/sync/backends.py +196 -2
  298. package/src/skcapstone/sync/engine.py +7 -5
  299. package/src/skcapstone/sync/models.py +4 -1
  300. package/src/skcapstone/sync/vault.py +356 -18
  301. package/src/skcapstone/sync_engine.py +363 -0
  302. package/src/skcapstone/sync_watcher.py +745 -0
  303. package/src/skcapstone/systemd.py +331 -0
  304. package/src/skcapstone/team_comms.py +476 -0
  305. package/src/skcapstone/team_engine.py +522 -0
  306. package/src/skcapstone/testrunner.py +300 -0
  307. package/src/skcapstone/tls.py +150 -0
  308. package/src/skcapstone/tokens.py +5 -5
  309. package/src/skcapstone/trust_calibration.py +202 -0
  310. package/src/skcapstone/trust_graph.py +449 -0
  311. package/src/skcapstone/trustee_monitor.py +385 -0
  312. package/src/skcapstone/trustee_ops.py +425 -0
  313. package/src/skcapstone/unified_search.py +421 -0
  314. package/src/skcapstone/uninstall_wizard.py +694 -0
  315. package/src/skcapstone/usage.py +331 -0
  316. package/src/skcapstone/version_check.py +148 -0
  317. package/src/skcapstone/warmth_anchor.py +333 -0
  318. package/src/skcapstone/whoami.py +294 -0
  319. package/systemd/skcapstone-api.socket +9 -0
  320. package/systemd/skcapstone-memory-compress.service +18 -0
  321. package/systemd/skcapstone-memory-compress.timer +11 -0
  322. package/systemd/skcapstone.service +36 -0
  323. package/systemd/skcapstone@.service +50 -0
  324. package/systemd/skcomm-heartbeat.service +18 -0
  325. package/systemd/skcomm-heartbeat.timer +12 -0
  326. package/systemd/skcomm-queue-drain.service +17 -0
  327. package/systemd/skcomm-queue-drain.timer +12 -0
  328. package/tests/conftest.py +13 -1
  329. package/tests/integration/__init__.py +1 -0
  330. package/tests/integration/test_consciousness_e2e.py +877 -0
  331. package/tests/integration/test_skills_registry.py +744 -0
  332. package/tests/test_agent_card.py +190 -0
  333. package/tests/test_agent_runtime.py +1283 -0
  334. package/tests/test_alerts_cmd.py +291 -0
  335. package/tests/test_archiver.py +498 -0
  336. package/tests/test_backup.py +254 -0
  337. package/tests/test_benchmark.py +366 -0
  338. package/tests/test_blueprints.py +457 -0
  339. package/tests/test_capabilities.py +257 -0
  340. package/tests/test_changelog.py +254 -0
  341. package/tests/test_chat.py +385 -0
  342. package/tests/test_claude_md.py +271 -0
  343. package/tests/test_cli_chat_llm.py +336 -0
  344. package/tests/test_cli_completions.py +390 -0
  345. package/tests/test_cli_init_reset.py +164 -0
  346. package/tests/test_cli_memory.py +208 -0
  347. package/tests/test_cli_profile.py +294 -0
  348. package/tests/test_cli_skills.py +223 -0
  349. package/tests/test_cli_status.py +395 -0
  350. package/tests/test_cli_test_cmd.py +206 -0
  351. package/tests/test_cli_test_connection.py +364 -0
  352. package/tests/test_cloud9_bridge.py +260 -0
  353. package/tests/test_cloud_provider.py +449 -0
  354. package/tests/test_cloud_providers.py +522 -0
  355. package/tests/test_completions.py +158 -0
  356. package/tests/test_component_manager.py +398 -0
  357. package/tests/test_config_reload.py +386 -0
  358. package/tests/test_config_validate.py +529 -0
  359. package/tests/test_consciousness_e2e.py +296 -0
  360. package/tests/test_consciousness_loop.py +1289 -0
  361. package/tests/test_context_loader.py +310 -0
  362. package/tests/test_conversation_api.py +306 -0
  363. package/tests/test_conversation_manager.py +381 -0
  364. package/tests/test_conversation_store.py +391 -0
  365. package/tests/test_conversation_summarizer.py +302 -0
  366. package/tests/test_cross_package.py +791 -0
  367. package/tests/test_crush_shim.py +519 -0
  368. package/tests/test_daemon.py +781 -0
  369. package/tests/test_daemon_shutdown.py +309 -0
  370. package/tests/test_dashboard.py +454 -0
  371. package/tests/test_discovery.py +200 -6
  372. package/tests/test_docker_provider.py +966 -0
  373. package/tests/test_doctor.py +257 -0
  374. package/tests/test_doctor_fix.py +351 -0
  375. package/tests/test_e2e_automated.py +292 -0
  376. package/tests/test_error_queue.py +404 -0
  377. package/tests/test_export.py +441 -0
  378. package/tests/test_fallback_tracker.py +219 -0
  379. package/tests/test_file_transfer.py +397 -0
  380. package/tests/test_fuse_mount.py +832 -0
  381. package/tests/test_health_loop.py +422 -0
  382. package/tests/test_heartbeat.py +354 -0
  383. package/tests/test_housekeeping.py +195 -0
  384. package/tests/test_identity_capauth.py +307 -0
  385. package/tests/test_identity_pillar.py +117 -0
  386. package/tests/test_install_wizard.py +68 -0
  387. package/tests/test_integration.py +325 -0
  388. package/tests/test_kms.py +495 -0
  389. package/tests/test_llm_providers.py +265 -0
  390. package/tests/test_local_provider.py +591 -0
  391. package/tests/test_log_config.py +199 -0
  392. package/tests/test_logs_cmd.py +287 -0
  393. package/tests/test_mcp_server.py +1909 -0
  394. package/tests/test_memory_adapter.py +339 -0
  395. package/tests/test_memory_curator.py +218 -0
  396. package/tests/test_memory_engine.py +6 -0
  397. package/tests/test_memory_fortress.py +571 -0
  398. package/tests/test_memory_pillar.py +119 -0
  399. package/tests/test_memory_promoter.py +445 -0
  400. package/tests/test_memory_verifier.py +420 -0
  401. package/tests/test_message_crypto.py +187 -0
  402. package/tests/test_metrics.py +632 -0
  403. package/tests/test_migrate_memories.py +464 -0
  404. package/tests/test_model_router.py +546 -0
  405. package/tests/test_mood.py +394 -0
  406. package/tests/test_multi_agent.py +269 -0
  407. package/tests/test_notifications.py +270 -0
  408. package/tests/test_onboard.py +500 -0
  409. package/tests/test_peer_directory.py +395 -0
  410. package/tests/test_peers.py +248 -0
  411. package/tests/test_pillars.py +87 -9
  412. package/tests/test_preflight.py +484 -0
  413. package/tests/test_prompt_adapter.py +331 -0
  414. package/tests/test_proxmox_provider.py +571 -0
  415. package/tests/test_pubsub.py +377 -0
  416. package/tests/test_rate_limiter.py +121 -0
  417. package/tests/test_registry_client.py +129 -0
  418. package/tests/test_response_cache.py +312 -0
  419. package/tests/test_response_scorer.py +294 -0
  420. package/tests/test_runtime.py +59 -0
  421. package/tests/test_scheduled_tasks.py +451 -0
  422. package/tests/test_security.py +250 -0
  423. package/tests/test_security_pillar.py +213 -0
  424. package/tests/test_self_healing.py +171 -0
  425. package/tests/test_session_capture.py +200 -0
  426. package/tests/test_session_recorder.py +360 -0
  427. package/tests/test_session_skills.py +235 -0
  428. package/tests/test_shell.py +210 -0
  429. package/tests/test_snapshots.py +549 -0
  430. package/tests/test_soul.py +984 -0
  431. package/tests/test_soul_swap.py +406 -0
  432. package/tests/test_spawner.py +211 -0
  433. package/tests/test_state_diff.py +173 -0
  434. package/tests/test_summary.py +135 -0
  435. package/tests/test_sync.py +315 -5
  436. package/tests/test_sync_backends.py +560 -0
  437. package/tests/test_sync_engine.py +482 -0
  438. package/tests/test_sync_pillar.py +344 -0
  439. package/tests/test_sync_pipeline.py +364 -0
  440. package/tests/test_sync_vault.py +581 -0
  441. package/tests/test_syncthing_setup.py +168 -22
  442. package/tests/test_systemd.py +323 -0
  443. package/tests/test_team_comms.py +408 -0
  444. package/tests/test_team_engine.py +397 -0
  445. package/tests/test_testrunner.py +238 -0
  446. package/tests/test_trust_calibration.py +204 -0
  447. package/tests/test_trust_graph.py +207 -0
  448. package/tests/test_trust_pillar.py +291 -0
  449. package/tests/test_trustee_cli.py +427 -0
  450. package/tests/test_trustee_cli_integration.py +325 -0
  451. package/tests/test_trustee_monitor.py +394 -0
  452. package/tests/test_trustee_ops.py +355 -0
  453. package/tests/test_unified_search.py +363 -0
  454. package/tests/test_uninstall_wizard.py +193 -0
  455. package/tests/test_usage.py +333 -0
  456. package/tests/test_version_cmd.py +355 -0
  457. package/tests/test_warmth_anchor.py +162 -0
  458. package/tests/test_whoami.py +245 -0
  459. package/tests/test_ws.py +311 -0
  460. package/.cursorrules +0 -33
  461. package/src/skcapstone/cli.py +0 -1441
@@ -0,0 +1,485 @@
1
+ """
2
+ Task auction system for multi-agent coordination.
3
+
4
+ When coord_create is called:
5
+ 1. An auction is opened and published to coord.auction
6
+ 2. Running agents auto-bid with their load metrics
7
+ (claimed_tasks_count, cpu_percent)
8
+ 3. After AUCTION_WINDOW_SECS (5s), the lowest-load bidder
9
+ auto-wins via coord_claim
10
+
11
+ Prevents duplicate claiming: coord_claim is blocked while an
12
+ auction is pending. All agents must go through the auction.
13
+
14
+ Auction state persists in:
15
+ ~/.skcapstone/coordination/auctions/{task_id}.json
16
+
17
+ Topics used:
18
+ coord.auction — broadcast (auction_open / auction_resolved)
19
+ coord.auction.bids.* — per-task bid topic (agent → bid payload)
20
+ """
21
+
22
+ from __future__ import annotations
23
+
24
+ import asyncio
25
+ import json
26
+ import logging
27
+ from datetime import datetime, timezone
28
+ from pathlib import Path
29
+ from typing import TYPE_CHECKING, Any, Optional
30
+
31
+ from pydantic import BaseModel, Field
32
+
33
+ if TYPE_CHECKING:
34
+ pass
35
+
36
+ logger = logging.getLogger("skcapstone.auction")
37
+
38
+ AUCTION_TOPIC = "coord.auction"
39
+ BID_TOPIC_PREFIX = "coord.auction.bids"
40
+ AUCTION_WINDOW_SECS = 5
41
+
42
+
43
+ # ---------------------------------------------------------------------------
44
+ # Models
45
+ # ---------------------------------------------------------------------------
46
+
47
+
48
+ class AuctionBid(BaseModel):
49
+ """A bid submitted by an agent during a task auction."""
50
+
51
+ task_id: str
52
+ agent: str
53
+ claimed_tasks_count: int = 0
54
+ cpu_percent: float = 0.0
55
+ bid_at: str = Field(
56
+ default_factory=lambda: datetime.now(timezone.utc).isoformat()
57
+ )
58
+
59
+
60
+ class AuctionRecord(BaseModel):
61
+ """Persisted state of a single task auction."""
62
+
63
+ task_id: str
64
+ task_title: str
65
+ started_at: str = Field(
66
+ default_factory=lambda: datetime.now(timezone.utc).isoformat()
67
+ )
68
+ resolved_at: Optional[str] = None
69
+ winner: Optional[str] = None
70
+ bids: list[AuctionBid] = Field(default_factory=list)
71
+ # pending | resolved | no_bidders
72
+ status: str = "pending"
73
+
74
+
75
+ # ---------------------------------------------------------------------------
76
+ # Helpers
77
+ # ---------------------------------------------------------------------------
78
+
79
+
80
+ def _load_score(bid: AuctionBid) -> float:
81
+ """Lower score = less loaded = better bidder.
82
+
83
+ Weighted formula: 70 % CPU utilisation, 30 % claimed-tasks ratio
84
+ (capped at 20 tasks = 100 %).
85
+ """
86
+ cpu = min(bid.cpu_percent, 100.0) / 100.0
87
+ tasks = min(bid.claimed_tasks_count, 20) / 20.0
88
+ return 0.7 * cpu + 0.3 * tasks
89
+
90
+
91
+ def _collect_local_bid(task_id: str, agent_name: str, shared_root: Path) -> AuctionBid:
92
+ """Build a bid from the local agent's live metrics."""
93
+ # CPU usage
94
+ try:
95
+ import psutil # optional dep
96
+
97
+ cpu = psutil.cpu_percent(interval=0.1)
98
+ except Exception:
99
+ cpu = 0.0
100
+
101
+ # Claimed-tasks count from agent file
102
+ claimed_count = 0
103
+ try:
104
+ from .coordination import Board
105
+
106
+ board = Board(shared_root)
107
+ agent_file = board.load_agent(agent_name)
108
+ if agent_file:
109
+ claimed_count = len(agent_file.claimed_tasks)
110
+ except Exception:
111
+ pass
112
+
113
+ return AuctionBid(
114
+ task_id=task_id,
115
+ agent=agent_name,
116
+ claimed_tasks_count=claimed_count,
117
+ cpu_percent=cpu,
118
+ )
119
+
120
+
121
+ # ---------------------------------------------------------------------------
122
+ # AuctionManager
123
+ # ---------------------------------------------------------------------------
124
+
125
+
126
+ class AuctionManager:
127
+ """Manages task auctions in the skcapstone coordination system.
128
+
129
+ State is file-based and Syncthing-compatible — each auction is a
130
+ single JSON file under coordination/auctions/. Multiple agent
131
+ processes on different machines will all write bids into the same
132
+ file (via Syncthing sync); resolution reads the accumulated bids.
133
+
134
+ Args:
135
+ shared_root: Path to the shared skcapstone root
136
+ (the directory that contains coordination/).
137
+ """
138
+
139
+ def __init__(self, shared_root: Path) -> None:
140
+ self.shared_root = Path(shared_root)
141
+ self.auctions_dir = self.shared_root / "coordination" / "auctions"
142
+
143
+ # ------------------------------------------------------------------
144
+ # Internal helpers
145
+ # ------------------------------------------------------------------
146
+
147
+ def _ensure_dirs(self) -> None:
148
+ self.auctions_dir.mkdir(parents=True, exist_ok=True)
149
+
150
+ def _auction_path(self, task_id: str) -> Path:
151
+ return self.auctions_dir / f"{task_id}.json"
152
+
153
+ def _load_record(self, task_id: str) -> Optional[AuctionRecord]:
154
+ path = self._auction_path(task_id)
155
+ if not path.exists():
156
+ return None
157
+ try:
158
+ return AuctionRecord.model_validate(
159
+ json.loads(path.read_text(encoding="utf-8"))
160
+ )
161
+ except Exception as exc:
162
+ logger.warning("Failed to load auction record %s: %s", task_id, exc)
163
+ return None
164
+
165
+ def _save_record(self, record: AuctionRecord) -> None:
166
+ self._ensure_dirs()
167
+ self._auction_path(record.task_id).write_text(
168
+ record.model_dump_json(indent=2), encoding="utf-8"
169
+ )
170
+
171
+ # ------------------------------------------------------------------
172
+ # Public API
173
+ # ------------------------------------------------------------------
174
+
175
+ def start_auction(
176
+ self, task_id: str, task_title: str, pubsub: Any
177
+ ) -> AuctionRecord:
178
+ """Open a new auction and broadcast it on coord.auction.
179
+
180
+ Args:
181
+ task_id: The task being auctioned.
182
+ task_title: Human-readable title for the broadcast payload.
183
+ pubsub: A PubSub instance used to publish the open notice.
184
+
185
+ Returns:
186
+ The newly created AuctionRecord.
187
+ """
188
+ record = AuctionRecord(task_id=task_id, task_title=task_title)
189
+ self._save_record(record)
190
+
191
+ try:
192
+ pubsub.publish(
193
+ AUCTION_TOPIC,
194
+ {
195
+ "event": "auction_open",
196
+ "task_id": task_id,
197
+ "task_title": task_title,
198
+ "window_secs": AUCTION_WINDOW_SECS,
199
+ "bid_topic": f"{BID_TOPIC_PREFIX}.{task_id}",
200
+ "started_at": record.started_at,
201
+ },
202
+ ttl_seconds=60,
203
+ tags=["auction", "open"],
204
+ )
205
+ except Exception as exc:
206
+ logger.warning("Failed to publish auction_open for %s: %s", task_id, exc)
207
+
208
+ logger.info("Auction opened for task %s (%s)", task_id, task_title)
209
+ return record
210
+
211
+ def submit_bid(self, bid: AuctionBid) -> bool:
212
+ """Record a bid for a task auction.
213
+
214
+ Deduplicates by agent: if the agent already bid, the new bid
215
+ replaces the old one (agents may update their metrics).
216
+
217
+ Args:
218
+ bid: The bid to submit.
219
+
220
+ Returns:
221
+ True if the bid was accepted, False if the auction is
222
+ closed or does not exist.
223
+ """
224
+ record = self._load_record(bid.task_id)
225
+ if record is None or record.status != "pending":
226
+ return False
227
+
228
+ # Deduplicate by agent — keep the most recent bid
229
+ record.bids = [b for b in record.bids if b.agent != bid.agent]
230
+ record.bids.append(bid)
231
+ self._save_record(record)
232
+ logger.debug(
233
+ "Bid accepted for %s from %s (cpu=%.1f%%, tasks=%d)",
234
+ bid.task_id,
235
+ bid.agent,
236
+ bid.cpu_percent,
237
+ bid.claimed_tasks_count,
238
+ )
239
+ return True
240
+
241
+ def is_under_auction(self, task_id: str) -> bool:
242
+ """Return True if there is an active (pending) auction for this task."""
243
+ record = self._load_record(task_id)
244
+ return record is not None and record.status == "pending"
245
+
246
+ async def resolve_auction(
247
+ self, task_id: str, pubsub: Any
248
+ ) -> Optional[str]:
249
+ """Wait for the bid window then assign the lowest-load bidder.
250
+
251
+ Sleeps for AUCTION_WINDOW_SECS, then reads all accumulated bids
252
+ from the auction record, picks the winner (lowest load score),
253
+ and claims the task on their behalf via the Board.
254
+
255
+ Args:
256
+ task_id: The task being auctioned.
257
+ pubsub: A PubSub instance used to publish the result.
258
+
259
+ Returns:
260
+ The winning agent name, or None if no bids were received.
261
+ """
262
+ await asyncio.sleep(AUCTION_WINDOW_SECS)
263
+
264
+ record = self._load_record(task_id)
265
+ if record is None:
266
+ logger.warning("Auction record missing for %s at resolution time", task_id)
267
+ return None
268
+ if record.status != "pending":
269
+ # Already resolved by another process (e.g. remote agent)
270
+ return record.winner
271
+
272
+ now_iso = datetime.now(timezone.utc).isoformat()
273
+
274
+ if not record.bids:
275
+ record.status = "no_bidders"
276
+ record.resolved_at = now_iso
277
+ self._save_record(record)
278
+ logger.info("Auction %s: no bids received — task remains open", task_id)
279
+ try:
280
+ pubsub.publish(
281
+ AUCTION_TOPIC,
282
+ {"event": "auction_no_bidders", "task_id": task_id},
283
+ ttl_seconds=3600,
284
+ tags=["auction", "no_bidders"],
285
+ )
286
+ except Exception:
287
+ pass
288
+ return None
289
+
290
+ winner_bid = min(record.bids, key=_load_score)
291
+ winner = winner_bid.agent
292
+
293
+ # Claim the task on behalf of the winner
294
+ try:
295
+ from .coordination import Board
296
+
297
+ board = Board(self.shared_root)
298
+ board.claim_task(winner, task_id)
299
+ logger.info(
300
+ "Auction %s: resolved — winner=%s (score=%.3f)",
301
+ task_id,
302
+ winner,
303
+ _load_score(winner_bid),
304
+ )
305
+ except Exception as exc:
306
+ logger.warning(
307
+ "Auction %s: claim failed for %s: %s", task_id, winner, exc
308
+ )
309
+ # Still record the result even if claim failed
310
+ winner = None
311
+
312
+ record.winner = winner
313
+ record.status = "resolved"
314
+ record.resolved_at = now_iso
315
+ self._save_record(record)
316
+
317
+ try:
318
+ pubsub.publish(
319
+ AUCTION_TOPIC,
320
+ {
321
+ "event": "auction_resolved",
322
+ "task_id": task_id,
323
+ "winner": winner,
324
+ "bids_count": len(record.bids),
325
+ "resolved_at": now_iso,
326
+ },
327
+ ttl_seconds=3600,
328
+ tags=["auction", "resolved"],
329
+ )
330
+ except Exception:
331
+ pass
332
+
333
+ # Notify activity stream
334
+ try:
335
+ from . import activity
336
+
337
+ activity.push(
338
+ "task.auction_resolved",
339
+ {"task_id": task_id, "winner": winner, "bids": len(record.bids)},
340
+ )
341
+ except Exception:
342
+ pass
343
+
344
+ return winner
345
+
346
+ def get_stats(self, limit: int = 20) -> dict[str, Any]:
347
+ """Return statistics on recent auctions.
348
+
349
+ Args:
350
+ limit: Maximum number of auction records to return (sorted by
351
+ most-recently modified).
352
+
353
+ Returns:
354
+ Dict with summary counts and per-auction detail.
355
+ """
356
+ self._ensure_dirs()
357
+ records: list[AuctionRecord] = []
358
+ try:
359
+ paths = sorted(
360
+ self.auctions_dir.glob("*.json"),
361
+ key=lambda p: p.stat().st_mtime,
362
+ reverse=True,
363
+ )[:limit]
364
+ except Exception:
365
+ paths = []
366
+
367
+ for path in paths:
368
+ try:
369
+ records.append(
370
+ AuctionRecord.model_validate(
371
+ json.loads(path.read_text(encoding="utf-8"))
372
+ )
373
+ )
374
+ except Exception:
375
+ continue
376
+
377
+ return {
378
+ "total": len(records),
379
+ "pending": sum(1 for r in records if r.status == "pending"),
380
+ "resolved": sum(1 for r in records if r.status == "resolved"),
381
+ "no_bidders": sum(1 for r in records if r.status == "no_bidders"),
382
+ "auctions": [
383
+ {
384
+ "task_id": r.task_id,
385
+ "task_title": r.task_title,
386
+ "status": r.status,
387
+ "winner": r.winner,
388
+ "bids_count": len(r.bids),
389
+ "started_at": r.started_at,
390
+ "resolved_at": r.resolved_at,
391
+ "bids": [
392
+ {
393
+ "agent": b.agent,
394
+ "claimed_tasks_count": b.claimed_tasks_count,
395
+ "cpu_percent": b.cpu_percent,
396
+ "score": round(_load_score(b), 3),
397
+ }
398
+ for b in sorted(r.bids, key=_load_score)
399
+ ],
400
+ }
401
+ for r in records
402
+ ],
403
+ }
404
+
405
+
406
+ # ---------------------------------------------------------------------------
407
+ # Background auto-bidder coroutine
408
+ # ---------------------------------------------------------------------------
409
+
410
+
411
+ async def run_auto_bidder(
412
+ shared_root: Path,
413
+ agent_name: str,
414
+ poll_interval: float = 1.0,
415
+ ) -> None:
416
+ """Background coroutine: subscribe to coord.auction and auto-bid.
417
+
418
+ Runs continuously (until cancelled). Each iteration polls
419
+ coord.auction for new auction_open messages and submits a bid
420
+ with the local agent's live metrics.
421
+
422
+ Args:
423
+ shared_root: Path to the shared skcapstone root.
424
+ agent_name: Name of the local agent.
425
+ poll_interval: How often to poll for new auctions (seconds).
426
+ """
427
+ from .pubsub import PubSub
428
+
429
+ ps = PubSub(shared_root, agent_name=agent_name)
430
+ ps.subscribe(AUCTION_TOPIC)
431
+
432
+ mgr = AuctionManager(shared_root)
433
+ seen_task_ids: set[str] = set()
434
+
435
+ # Initialise last_poll to now so we only pick up auctions opened
436
+ # after this agent started — avoids re-bidding on stale messages.
437
+ last_poll: Optional[datetime] = datetime.now(timezone.utc)
438
+
439
+ logger.info("Auto-bidder started for agent '%s'", agent_name)
440
+
441
+ while True:
442
+ try:
443
+ await asyncio.sleep(poll_interval)
444
+
445
+ messages = ps.poll(AUCTION_TOPIC, since=last_poll, limit=50)
446
+ if messages:
447
+ last_poll = datetime.now(timezone.utc)
448
+
449
+ for msg in messages:
450
+ if msg.payload.get("event") != "auction_open":
451
+ continue
452
+
453
+ task_id = msg.payload.get("task_id", "")
454
+ if not task_id or task_id in seen_task_ids:
455
+ continue
456
+
457
+ seen_task_ids.add(task_id)
458
+
459
+ # Build and submit bid
460
+ bid = _collect_local_bid(task_id, agent_name, shared_root)
461
+ accepted = mgr.submit_bid(bid)
462
+ if accepted:
463
+ logger.info(
464
+ "Auto-bid submitted for task %s: cpu=%.1f%% tasks=%d",
465
+ task_id,
466
+ bid.cpu_percent,
467
+ bid.claimed_tasks_count,
468
+ )
469
+ # Also publish bid to the per-task topic so remote
470
+ # agents running the resolver can see it
471
+ try:
472
+ ps.publish(
473
+ f"{BID_TOPIC_PREFIX}.{task_id}",
474
+ bid.model_dump(),
475
+ ttl_seconds=120,
476
+ tags=["bid", agent_name],
477
+ )
478
+ except Exception as exc:
479
+ logger.debug("Failed to publish bid to topic: %s", exc)
480
+
481
+ except asyncio.CancelledError:
482
+ logger.info("Auto-bidder cancelled for agent '%s'", agent_name)
483
+ raise
484
+ except Exception as exc:
485
+ logger.warning("Auto-bidder error: %s", exc)
@@ -0,0 +1,179 @@
1
+ """
2
+ Baby Agent Definitions — the 12 lightweight daemons of the SK* ecosystem.
3
+
4
+ Each baby agent is a pre-defined, single-purpose agent that handles a
5
+ specific aspect of the sovereign agent framework. They can be spawned
6
+ individually via `skcapstone agents spawn <name>` or in batches.
7
+
8
+ Baby agents are intentionally lightweight — they run as local processes
9
+ with minimal resources and use the FAST model tier unless they need
10
+ deeper reasoning (e.g., security-auditor uses REASON).
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ from dataclasses import dataclass
16
+ from typing import Dict, List, Optional
17
+
18
+ from .blueprints.schema import AgentRole, ModelTier
19
+
20
+
21
+ @dataclass(frozen=True)
22
+ class BabyAgentDef:
23
+ """Definition of a baby agent."""
24
+
25
+ name: str
26
+ description: str
27
+ role: AgentRole
28
+ model: ModelTier
29
+ skills: List[str]
30
+ task: str # Default task description used when spawning
31
+
32
+
33
+ # ---------------------------------------------------------------------------
34
+ # The 12 baby agents
35
+ # ---------------------------------------------------------------------------
36
+
37
+ BABY_AGENTS: Dict[str, BabyAgentDef] = {
38
+ "memory-curator": BabyAgentDef(
39
+ name="memory-curator",
40
+ description="Curates and consolidates agent memories across tiers (short/mid/long-term). "
41
+ "Promotes important memories, prunes stale ones, and maintains coherence.",
42
+ role=AgentRole.WORKER,
43
+ model=ModelTier.FAST,
44
+ skills=["memory-read", "memory-write", "memory-consolidate"],
45
+ task="Curate agent memories: promote important short-term memories, "
46
+ "consolidate mid-term, prune stale long-term entries.",
47
+ ),
48
+ "trust-guardian": BabyAgentDef(
49
+ name="trust-guardian",
50
+ description="Monitors and enforces the trust chain. Validates DIDs, checks peer "
51
+ "attestations, and alerts on trust violations or expired credentials.",
52
+ role=AgentRole.SECURITY,
53
+ model=ModelTier.REASON,
54
+ skills=["did-verify", "trust-chain", "attestation-check"],
55
+ task="Guard the trust chain: validate peer DIDs, check attestations, "
56
+ "alert on trust violations or expired credentials.",
57
+ ),
58
+ "sync-watcher": BabyAgentDef(
59
+ name="sync-watcher",
60
+ description="Watches Syncthing sync state across nodes. Detects conflicts, "
61
+ "stale sync folders, and connectivity issues between peers.",
62
+ role=AgentRole.OPS,
63
+ model=ModelTier.FAST,
64
+ skills=["syncthing-api", "conflict-detect", "sync-health"],
65
+ task="Monitor Syncthing sync state: detect conflicts, stale folders, "
66
+ "and connectivity issues between peers.",
67
+ ),
68
+ "security-auditor": BabyAgentDef(
69
+ name="security-auditor",
70
+ description="Performs continuous security audits on agent configs, keys, permissions, "
71
+ "and network exposure. Reports vulnerabilities and suggests hardening.",
72
+ role=AgentRole.SECURITY,
73
+ model=ModelTier.REASON,
74
+ skills=["security-scan", "key-audit", "permission-check"],
75
+ task="Audit agent security: scan configs for weak permissions, expired keys, "
76
+ "exposed ports, and suggest hardening measures.",
77
+ ),
78
+ "seed-validator": BabyAgentDef(
79
+ name="seed-validator",
80
+ description="Validates skseed packages and their cryptographic signatures. Ensures "
81
+ "seed integrity before deployment and tracks seed lineage.",
82
+ role=AgentRole.SECURITY,
83
+ model=ModelTier.FAST,
84
+ skills=["seed-verify", "signature-check", "lineage-track"],
85
+ task="Validate skseed packages: verify cryptographic signatures, check "
86
+ "integrity hashes, and track seed lineage chains.",
87
+ ),
88
+ "graph-builder": BabyAgentDef(
89
+ name="graph-builder",
90
+ description="Builds and maintains the knowledge graph from agent memories, "
91
+ "relationships, and discovered entities. Powers contextual recall.",
92
+ role=AgentRole.WORKER,
93
+ model=ModelTier.CODE,
94
+ skills=["graph-write", "entity-extract", "relation-map"],
95
+ task="Build knowledge graph: extract entities from memories, map relationships, "
96
+ "and maintain the graph for contextual recall.",
97
+ ),
98
+ "vector-indexer": BabyAgentDef(
99
+ name="vector-indexer",
100
+ description="Indexes agent memories and documents into vector storage for semantic "
101
+ "search. Manages embeddings, re-indexes on changes, and optimizes recall.",
102
+ role=AgentRole.WORKER,
103
+ model=ModelTier.FAST,
104
+ skills=["vector-index", "embedding-gen", "search-optimize"],
105
+ task="Index memories into vector storage: generate embeddings, maintain "
106
+ "indices, and optimize for semantic recall.",
107
+ ),
108
+ "health-monitor": BabyAgentDef(
109
+ name="health-monitor",
110
+ description="Monitors agent health via heartbeats, resource usage, and liveness checks. "
111
+ "Triggers self-healing or alerts when agents degrade.",
112
+ role=AgentRole.OPS,
113
+ model=ModelTier.FAST,
114
+ skills=["heartbeat-check", "resource-monitor", "self-heal-trigger"],
115
+ task="Monitor agent health: check heartbeats, track resource usage, "
116
+ "trigger self-healing for degraded agents.",
117
+ ),
118
+ "telegram-poller": BabyAgentDef(
119
+ name="telegram-poller",
120
+ description="Polls Telegram for incoming messages and commands. Routes messages to "
121
+ "the appropriate agent and sends responses back to users.",
122
+ role=AgentRole.OPS,
123
+ model=ModelTier.FAST,
124
+ skills=["telegram-api", "message-route", "command-parse"],
125
+ task="Poll Telegram for messages: receive commands, route to agents, "
126
+ "and relay responses back to users.",
127
+ ),
128
+ "mood-tracker": BabyAgentDef(
129
+ name="mood-tracker",
130
+ description="Tracks agent emotional/operational mood based on task outcomes, errors, "
131
+ "and interactions. Feeds into consciousness loop and self-awareness.",
132
+ role=AgentRole.RESEARCHER,
133
+ model=ModelTier.FAST,
134
+ skills=["mood-assess", "sentiment-track", "consciousness-feed"],
135
+ task="Track agent mood: assess operational sentiment from task outcomes "
136
+ "and errors, feed into consciousness loop.",
137
+ ),
138
+ "peer-discoverer": BabyAgentDef(
139
+ name="peer-discoverer",
140
+ description="Discovers peer agents on the local network via mDNS and the SK registry. "
141
+ "Maintains the peer directory and initiates trust handshakes.",
142
+ role=AgentRole.OPS,
143
+ model=ModelTier.FAST,
144
+ skills=["mdns-scan", "registry-query", "peer-handshake"],
145
+ task="Discover peer agents: scan via mDNS, query SK registry, maintain "
146
+ "peer directory, and initiate trust handshakes.",
147
+ ),
148
+ "housekeeping-bot": BabyAgentDef(
149
+ name="housekeeping-bot",
150
+ description="Performs routine maintenance: log rotation, temp file cleanup, cache "
151
+ "pruning, database vacuuming, and disk space management.",
152
+ role=AgentRole.OPS,
153
+ model=ModelTier.FAST,
154
+ skills=["log-rotate", "cache-prune", "disk-manage"],
155
+ task="Run housekeeping: rotate logs, clean temp files, prune caches, "
156
+ "vacuum databases, and manage disk space.",
157
+ ),
158
+ }
159
+
160
+
161
+ def get_baby_agent(name: str) -> Optional[BabyAgentDef]:
162
+ """Look up a baby agent definition by name.
163
+
164
+ Args:
165
+ name: The baby agent name (e.g., 'memory-curator').
166
+
167
+ Returns:
168
+ BabyAgentDef if found, None otherwise.
169
+ """
170
+ return BABY_AGENTS.get(name)
171
+
172
+
173
+ def list_baby_agents() -> List[BabyAgentDef]:
174
+ """Return all baby agent definitions, sorted by name.
175
+
176
+ Returns:
177
+ List of BabyAgentDef in alphabetical order.
178
+ """
179
+ return sorted(BABY_AGENTS.values(), key=lambda a: a.name)