@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,408 @@
1
+ """
2
+ Tests for skcapstone.team_comms — agent-to-agent communication layer.
3
+
4
+ Covers:
5
+ - Channel bootstrapping (directory creation)
6
+ - send_to_teammate happy path
7
+ - send_to_teammate with unknown recipient raises ValueError
8
+ - receive_messages drains inbox and archives files
9
+ - broadcast_to_team from queen delivers to all members
10
+ - broadcast_to_team from non-queen raises PermissionError
11
+ - receive_broadcast returns queen messages for non-queen members
12
+ - Board logging is invoked when a board is provided
13
+ - TeamEngine.deploy() populates comms_channel
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ import json
19
+ from pathlib import Path
20
+ from typing import List, Optional
21
+ from unittest.mock import MagicMock, patch
22
+
23
+ import pytest
24
+
25
+ from skcapstone.team_comms import (
26
+ TeamChannel,
27
+ bootstrap_team_channel,
28
+ broadcast_to_team,
29
+ receive_broadcast,
30
+ receive_messages,
31
+ send_to_teammate,
32
+ _ENVELOPE_SUFFIX,
33
+ _build_envelope,
34
+ )
35
+
36
+
37
+ # ---------------------------------------------------------------------------
38
+ # Fixtures
39
+ # ---------------------------------------------------------------------------
40
+
41
+
42
+ @pytest.fixture
43
+ def comms_root(tmp_path: Path) -> Path:
44
+ """Return a temporary comms root directory."""
45
+ root = tmp_path / "comms"
46
+ root.mkdir()
47
+ return root
48
+
49
+
50
+ @pytest.fixture
51
+ def channel(comms_root: Path) -> TeamChannel:
52
+ """A bootstrapped three-agent channel with 'alpha' as queen."""
53
+ return bootstrap_team_channel(
54
+ team_slug="test-team",
55
+ agent_names=["alpha", "beta", "gamma"],
56
+ comms_root=comms_root,
57
+ queen="alpha",
58
+ )
59
+
60
+
61
+ # ---------------------------------------------------------------------------
62
+ # bootstrap_team_channel
63
+ # ---------------------------------------------------------------------------
64
+
65
+
66
+ class TestBootstrapTeamChannel:
67
+ """Tests for bootstrap_team_channel()."""
68
+
69
+ def test_creates_inbox_and_archive_for_each_agent(
70
+ self, comms_root: Path
71
+ ) -> None:
72
+ """Inbox and archive directories are created for every agent."""
73
+ channel = bootstrap_team_channel(
74
+ team_slug="myteam",
75
+ agent_names=["worker1", "worker2"],
76
+ comms_root=comms_root,
77
+ )
78
+ for agent in ["worker1", "worker2"]:
79
+ assert channel.inbox_for(agent).is_dir()
80
+ assert channel.archive_for(agent).is_dir()
81
+
82
+ def test_broadcast_dir_created_when_queen_set(
83
+ self, comms_root: Path
84
+ ) -> None:
85
+ """Broadcast directory exists when queen is specified."""
86
+ channel = bootstrap_team_channel(
87
+ team_slug="queenteam",
88
+ agent_names=["queen", "minion"],
89
+ comms_root=comms_root,
90
+ queen="queen",
91
+ )
92
+ assert channel.broadcast_dir.is_dir()
93
+
94
+ def test_broadcast_dir_not_created_without_queen(
95
+ self, comms_root: Path
96
+ ) -> None:
97
+ """No broadcast directory when no queen is set."""
98
+ channel = bootstrap_team_channel(
99
+ team_slug="peerteam",
100
+ agent_names=["a", "b"],
101
+ comms_root=comms_root,
102
+ queen=None,
103
+ )
104
+ assert not channel.broadcast_dir.exists()
105
+
106
+ def test_idempotent(self, comms_root: Path) -> None:
107
+ """Calling bootstrap twice does not raise or corrupt state."""
108
+ bootstrap_team_channel("idempotent", ["x"], comms_root, queen="x")
109
+ channel = bootstrap_team_channel("idempotent", ["x"], comms_root, queen="x")
110
+ assert channel.inbox_for("x").is_dir()
111
+
112
+ def test_channel_members_and_queen(self, comms_root: Path) -> None:
113
+ """Channel reports correct members and queen."""
114
+ channel = bootstrap_team_channel(
115
+ team_slug="t",
116
+ agent_names=["a", "b", "c"],
117
+ comms_root=comms_root,
118
+ queen="a",
119
+ )
120
+ assert channel.members == ["a", "b", "c"]
121
+ assert channel.queen == "a"
122
+
123
+
124
+ # ---------------------------------------------------------------------------
125
+ # send_to_teammate
126
+ # ---------------------------------------------------------------------------
127
+
128
+
129
+ class TestSendToTeammate:
130
+ """Tests for send_to_teammate()."""
131
+
132
+ def test_happy_path_writes_envelope(self, channel: TeamChannel) -> None:
133
+ """A valid send writes exactly one .skc.json file to the inbox."""
134
+ send_to_teammate("alpha", "beta", "Hello beta!", channel)
135
+ inbox = channel.inbox_for("beta")
136
+ files = list(inbox.glob(f"*{_ENVELOPE_SUFFIX}"))
137
+ assert len(files) == 1
138
+
139
+ def test_envelope_content_is_valid_json(self, channel: TeamChannel) -> None:
140
+ """The written file is parseable and has correct sender/recipient."""
141
+ eid = send_to_teammate("alpha", "gamma", "Hi gamma", channel)
142
+ inbox = channel.inbox_for("gamma")
143
+ files = list(inbox.glob(f"*{_ENVELOPE_SUFFIX}"))
144
+ data = json.loads(files[0].read_text())
145
+ assert data["sender"] == "alpha"
146
+ assert data["recipient"] == "gamma"
147
+ assert data["payload"]["content"] == "Hi gamma"
148
+ assert data["envelope_id"] == eid
149
+
150
+ def test_thread_id_propagated(self, channel: TeamChannel) -> None:
151
+ """thread_id is stored in envelope metadata."""
152
+ send_to_teammate("beta", "gamma", "msg", channel, thread_id="t-001")
153
+ files = list(channel.inbox_for("gamma").glob(f"*{_ENVELOPE_SUFFIX}"))
154
+ data = json.loads(files[0].read_text())
155
+ assert data["metadata"]["thread_id"] == "t-001"
156
+
157
+ def test_unknown_recipient_raises(self, channel: TeamChannel) -> None:
158
+ """Sending to a non-member raises ValueError."""
159
+ with pytest.raises(ValueError, match="not a member"):
160
+ send_to_teammate("alpha", "unknown-bot", "hi", channel)
161
+
162
+ def test_board_log_called(self, channel: TeamChannel) -> None:
163
+ """Board.save_agent is called when board is provided."""
164
+ mock_board = MagicMock()
165
+ mock_board.load_agent.return_value = None
166
+ send_to_teammate("alpha", "beta", "msg", channel, board=mock_board)
167
+ mock_board.save_agent.assert_called_once()
168
+
169
+ def test_board_failure_does_not_raise(self, channel: TeamChannel) -> None:
170
+ """A broken board never prevents message delivery."""
171
+ broken_board = MagicMock()
172
+ broken_board.load_agent.side_effect = RuntimeError("db down")
173
+ # Should not raise
174
+ eid = send_to_teammate("alpha", "beta", "msg", channel, board=broken_board)
175
+ assert eid
176
+
177
+
178
+ # ---------------------------------------------------------------------------
179
+ # receive_messages
180
+ # ---------------------------------------------------------------------------
181
+
182
+
183
+ class TestReceiveMessages:
184
+ """Tests for receive_messages()."""
185
+
186
+ def test_returns_empty_when_no_messages(self, channel: TeamChannel) -> None:
187
+ """Empty inbox returns empty list."""
188
+ assert receive_messages("beta", channel) == []
189
+
190
+ def test_drains_all_messages(self, channel: TeamChannel) -> None:
191
+ """All messages in inbox are returned and then archived."""
192
+ send_to_teammate("alpha", "beta", "msg1", channel)
193
+ send_to_teammate("gamma", "beta", "msg2", channel)
194
+ received = receive_messages("beta", channel)
195
+ assert len(received) == 2
196
+ # Inbox now empty
197
+ assert receive_messages("beta", channel) == []
198
+
199
+ def test_messages_moved_to_archive(self, channel: TeamChannel) -> None:
200
+ """Processed messages are moved to archive, not deleted."""
201
+ send_to_teammate("alpha", "beta", "archived?", channel)
202
+ receive_messages("beta", channel)
203
+ archive = channel.archive_for("beta")
204
+ files = list(archive.glob(f"*{_ENVELOPE_SUFFIX}"))
205
+ assert len(files) == 1
206
+
207
+ def test_returns_correct_content(self, channel: TeamChannel) -> None:
208
+ """Returned envelopes contain the correct message content."""
209
+ send_to_teammate("alpha", "beta", "specific content", channel)
210
+ msgs = receive_messages("beta", channel)
211
+ assert msgs[0]["payload"]["content"] == "specific content"
212
+
213
+ def test_corrupted_file_skipped(self, channel: TeamChannel) -> None:
214
+ """A malformed envelope file is skipped without crashing."""
215
+ inbox = channel.inbox_for("beta")
216
+ inbox.mkdir(parents=True, exist_ok=True)
217
+ bad_file = inbox / f"corrupt{_ENVELOPE_SUFFIX}"
218
+ bad_file.write_text("not valid json")
219
+ # Valid message also present
220
+ send_to_teammate("alpha", "beta", "valid", channel)
221
+ msgs = receive_messages("beta", channel)
222
+ assert len(msgs) == 1
223
+ assert msgs[0]["payload"]["content"] == "valid"
224
+
225
+
226
+ # ---------------------------------------------------------------------------
227
+ # broadcast_to_team
228
+ # ---------------------------------------------------------------------------
229
+
230
+
231
+ class TestBroadcastToTeam:
232
+ """Tests for broadcast_to_team()."""
233
+
234
+ def test_queen_can_broadcast(self, channel: TeamChannel) -> None:
235
+ """Queen can broadcast; all non-queen members receive the message."""
236
+ eids = broadcast_to_team("alpha", "All hands!", channel)
237
+ assert len(eids) == 2 # beta and gamma
238
+ assert len(receive_messages("beta", channel)) == 1
239
+ assert len(receive_messages("gamma", channel)) == 1
240
+
241
+ def test_queen_does_not_receive_own_broadcast(
242
+ self, channel: TeamChannel
243
+ ) -> None:
244
+ """The queen's inbox is not written to during a broadcast."""
245
+ broadcast_to_team("alpha", "Hello team", channel)
246
+ assert receive_messages("alpha", channel) == []
247
+
248
+ def test_broadcast_written_to_audit_dir(self, channel: TeamChannel) -> None:
249
+ """Broadcast envelope is also written to the broadcast directory."""
250
+ broadcast_to_team("alpha", "Audit this", channel)
251
+ files = list(channel.broadcast_dir.glob(f"*{_ENVELOPE_SUFFIX}"))
252
+ assert len(files) == 1
253
+
254
+ def test_non_queen_broadcast_raises(self, channel: TeamChannel) -> None:
255
+ """Non-queen agent attempting broadcast raises PermissionError."""
256
+ with pytest.raises(PermissionError, match="queen"):
257
+ broadcast_to_team("beta", "I am not the queen", channel)
258
+
259
+ def test_no_queen_allows_any_broadcast(self, comms_root: Path) -> None:
260
+ """When channel has no queen, any member may broadcast."""
261
+ ch = bootstrap_team_channel(
262
+ "open-team", ["x", "y", "z"], comms_root, queen=None
263
+ )
264
+ eids = broadcast_to_team("x", "peer broadcast", ch)
265
+ # y and z each get one message
266
+ assert len(eids) == 2
267
+
268
+
269
+ # ---------------------------------------------------------------------------
270
+ # receive_broadcast
271
+ # ---------------------------------------------------------------------------
272
+
273
+
274
+ class TestReceiveBroadcast:
275
+ """Tests for receive_broadcast()."""
276
+
277
+ def test_non_queen_reads_broadcast(self, channel: TeamChannel) -> None:
278
+ """A member agent can read broadcast messages."""
279
+ broadcast_to_team("alpha", "Broadcast content", channel)
280
+ msgs = receive_broadcast("beta", channel)
281
+ assert len(msgs) == 1
282
+ assert msgs[0]["payload"]["content"] == "Broadcast content"
283
+
284
+ def test_sender_filtered_from_broadcast(self, channel: TeamChannel) -> None:
285
+ """The queen's own broadcast is not returned to herself."""
286
+ broadcast_to_team("alpha", "self-filter test", channel)
287
+ msgs = receive_broadcast("alpha", channel)
288
+ assert msgs == []
289
+
290
+ def test_empty_when_no_broadcasts(self, channel: TeamChannel) -> None:
291
+ """Returns empty list when broadcast directory is empty."""
292
+ assert receive_broadcast("beta", channel) == []
293
+
294
+
295
+ # ---------------------------------------------------------------------------
296
+ # _build_envelope
297
+ # ---------------------------------------------------------------------------
298
+
299
+
300
+ class TestBuildEnvelope:
301
+ """Tests for the internal _build_envelope helper."""
302
+
303
+ def test_required_fields_present(self) -> None:
304
+ """Envelope dict has all required SKComm fields."""
305
+ env = _build_envelope("agent-a", "agent-b", "hello")
306
+ assert env["skcomm_version"] == "1.0.0"
307
+ assert env["sender"] == "agent-a"
308
+ assert env["recipient"] == "agent-b"
309
+ assert env["payload"]["content"] == "hello"
310
+ assert "envelope_id" in env
311
+
312
+ def test_unique_ids(self) -> None:
313
+ """Two envelopes have distinct envelope_ids."""
314
+ e1 = _build_envelope("a", "b", "msg")
315
+ e2 = _build_envelope("a", "b", "msg")
316
+ assert e1["envelope_id"] != e2["envelope_id"]
317
+
318
+
319
+ # ---------------------------------------------------------------------------
320
+ # TeamEngine integration
321
+ # ---------------------------------------------------------------------------
322
+
323
+
324
+ class TestTeamEngineCommsIntegration:
325
+ """Verify TeamEngine.deploy() wires comms correctly."""
326
+
327
+ def test_deploy_populates_comms_channel(self, tmp_path: Path) -> None:
328
+ """After deploy(), TeamDeployment.comms_channel is a TeamChannel."""
329
+ from skcapstone.blueprints.schema import (
330
+ AgentRole,
331
+ AgentSpec,
332
+ BlueprintManifest,
333
+ CoordinationConfig,
334
+ )
335
+ from skcapstone.team_engine import TeamEngine
336
+
337
+ blueprint = BlueprintManifest(
338
+ name="Test Team",
339
+ slug="test-team",
340
+ description="Unit test team",
341
+ agents={
342
+ "queen": AgentSpec(role=AgentRole.MANAGER),
343
+ "worker": AgentSpec(role=AgentRole.WORKER),
344
+ },
345
+ coordination=CoordinationConfig(queen="queen"),
346
+ )
347
+
348
+ engine = TeamEngine(
349
+ home=tmp_path / ".skcapstone",
350
+ comms_root=tmp_path / "comms",
351
+ )
352
+ deployment = engine.deploy(blueprint)
353
+
354
+ assert deployment.comms_channel is not None
355
+ assert isinstance(deployment.comms_channel, TeamChannel)
356
+ assert len(deployment.comms_channel.members) == 2
357
+
358
+ def test_deploy_without_comms_root_skips_channel(
359
+ self, tmp_path: Path
360
+ ) -> None:
361
+ """When comms_root is explicitly None, comms_channel stays None."""
362
+ from skcapstone.blueprints.schema import AgentSpec, BlueprintManifest
363
+ from skcapstone.team_engine import TeamEngine
364
+
365
+ blueprint = BlueprintManifest(
366
+ name="No Comms",
367
+ slug="no-comms",
368
+ description="Team without comms",
369
+ agents={"solo": AgentSpec()},
370
+ )
371
+
372
+ # Monkeypatch: set _comms_root to None directly after construction
373
+ engine = TeamEngine(home=tmp_path / ".skcapstone")
374
+ engine._comms_root = None
375
+ deployment = engine.deploy(blueprint)
376
+
377
+ assert deployment.comms_channel is None
378
+
379
+ def test_deploy_queen_identified_from_role(self, tmp_path: Path) -> None:
380
+ """Queen is detected from AgentRole.MANAGER when coordination.queen unset."""
381
+ from skcapstone.blueprints.schema import (
382
+ AgentRole,
383
+ AgentSpec,
384
+ BlueprintManifest,
385
+ CoordinationConfig,
386
+ )
387
+ from skcapstone.team_engine import TeamEngine
388
+
389
+ blueprint = BlueprintManifest(
390
+ name="Role Team",
391
+ slug="role-team",
392
+ description="Queen via role",
393
+ agents={
394
+ "boss": AgentSpec(role=AgentRole.MANAGER),
395
+ "minion": AgentSpec(role=AgentRole.WORKER),
396
+ },
397
+ coordination=CoordinationConfig(queen=None),
398
+ )
399
+
400
+ engine = TeamEngine(
401
+ home=tmp_path / ".skcapstone",
402
+ comms_root=tmp_path / "comms",
403
+ )
404
+ deployment = engine.deploy(blueprint)
405
+ channel = deployment.comms_channel
406
+ assert channel is not None
407
+ assert channel.queen is not None
408
+ assert "boss" in channel.queen