@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,454 @@
1
+ """Crush shim — daemon entry point that bridges the crush CLI interface to claude.
2
+
3
+ Registered as the ``crush`` console_scripts entry point so that
4
+ ``LocalProvider._find_crush_binary()`` discovers it on PATH. When invoked
5
+ as ``crush run --session <path> --config <path> --headless --state-file <path>``
6
+ it:
7
+
8
+ 1. Parses the crush-compatible CLI arguments.
9
+ 2. Reads ``session.json`` for agent identity (name, model, soul, skills).
10
+ 3. Reads ``crush.json`` for permissions, context paths, and MCP config.
11
+ 4. Writes ``{"status": "running", ...}`` to the state file.
12
+ 5. Enters a daemon loop that:
13
+ - Polls the team comms inbox for incoming messages.
14
+ - For each task: dispatches to ``claude -p`` with the correct model and
15
+ system prompt derived from the soul blueprint.
16
+ - Writes results to the agent outbox.
17
+ - Updates the heartbeat in the state file every iteration.
18
+ 6. On SIGTERM/SIGINT: writes stopped state and exits cleanly.
19
+ """
20
+
21
+ from __future__ import annotations
22
+
23
+ import argparse
24
+ import json
25
+ import logging
26
+ import os
27
+ import signal
28
+ import subprocess
29
+ import sys
30
+ import time
31
+ from pathlib import Path
32
+ from typing import Any, Dict, List, Optional
33
+
34
+ logger = logging.getLogger(__name__)
35
+
36
+ _POLL_INTERVAL_SECONDS = 5
37
+ _CLAUDE_BINARY = "claude"
38
+
39
+
40
+ # ---------------------------------------------------------------------------
41
+ # Argument parsing
42
+ # ---------------------------------------------------------------------------
43
+
44
+
45
+ def build_arg_parser() -> argparse.ArgumentParser:
46
+ """Build the crush-compatible argument parser.
47
+
48
+ Returns:
49
+ Configured ArgumentParser supporting ``crush run`` sub-command.
50
+ """
51
+ parser = argparse.ArgumentParser(
52
+ prog="crush",
53
+ description="Crush shim — bridges crush CLI interface to claude backend",
54
+ )
55
+ sub = parser.add_subparsers(dest="command")
56
+
57
+ run_parser = sub.add_parser("run", help="Run an agent session")
58
+ run_parser.add_argument(
59
+ "--session",
60
+ required=True,
61
+ help="Path to session.json",
62
+ )
63
+ run_parser.add_argument(
64
+ "--config",
65
+ required=True,
66
+ help="Path to crush.json",
67
+ )
68
+ run_parser.add_argument(
69
+ "--headless",
70
+ action="store_true",
71
+ default=False,
72
+ help="Run in headless daemon mode",
73
+ )
74
+ run_parser.add_argument(
75
+ "--state-file",
76
+ required=True,
77
+ help="Path to session state file",
78
+ )
79
+ return parser
80
+
81
+
82
+ def parse_args(argv: Optional[List[str]] = None) -> argparse.Namespace:
83
+ """Parse crush CLI arguments.
84
+
85
+ Args:
86
+ argv: Argument list (defaults to sys.argv[1:]).
87
+
88
+ Returns:
89
+ Parsed namespace.
90
+ """
91
+ parser = build_arg_parser()
92
+ return parser.parse_args(argv)
93
+
94
+
95
+ # ---------------------------------------------------------------------------
96
+ # Config loading
97
+ # ---------------------------------------------------------------------------
98
+
99
+
100
+ def load_session_config(path: str) -> Dict[str, Any]:
101
+ """Load and return the session.json configuration.
102
+
103
+ Args:
104
+ path: Path to session.json.
105
+
106
+ Returns:
107
+ Parsed session configuration dict.
108
+
109
+ Raises:
110
+ SystemExit: If the file cannot be read or parsed.
111
+ """
112
+ try:
113
+ return json.loads(Path(path).read_text(encoding="utf-8"))
114
+ except (json.JSONDecodeError, OSError) as exc:
115
+ logger.error("Failed to load session config from %s: %s", path, exc)
116
+ sys.exit(1)
117
+
118
+
119
+ def load_crush_config(path: str) -> Dict[str, Any]:
120
+ """Load and return the crush.json configuration.
121
+
122
+ Args:
123
+ path: Path to crush.json.
124
+
125
+ Returns:
126
+ Parsed crush configuration dict.
127
+
128
+ Raises:
129
+ SystemExit: If the file cannot be read or parsed.
130
+ """
131
+ try:
132
+ return json.loads(Path(path).read_text(encoding="utf-8"))
133
+ except (json.JSONDecodeError, OSError) as exc:
134
+ logger.error("Failed to load crush config from %s: %s", path, exc)
135
+ sys.exit(1)
136
+
137
+
138
+ # ---------------------------------------------------------------------------
139
+ # State file management
140
+ # ---------------------------------------------------------------------------
141
+
142
+
143
+ def write_state(state_file: str, state: Dict[str, Any]) -> None:
144
+ """Write the session state to disk.
145
+
146
+ Args:
147
+ state_file: Absolute path to the state file.
148
+ state: State dictionary to persist.
149
+ """
150
+ try:
151
+ Path(state_file).write_text(
152
+ json.dumps(state, indent=2), encoding="utf-8"
153
+ )
154
+ except OSError as exc:
155
+ logger.warning("Failed to write state file %s: %s", state_file, exc)
156
+
157
+
158
+ def _now_iso() -> str:
159
+ """Return the current UTC time as an ISO 8601 string."""
160
+ from datetime import datetime, timezone
161
+
162
+ return datetime.now(timezone.utc).isoformat()
163
+
164
+
165
+ # ---------------------------------------------------------------------------
166
+ # Soul blueprint reader
167
+ # ---------------------------------------------------------------------------
168
+
169
+
170
+ def build_system_prompt(session_config: Dict[str, Any]) -> str:
171
+ """Construct a system prompt from the soul blueprint and agent context.
172
+
173
+ Args:
174
+ session_config: Parsed session.json.
175
+
176
+ Returns:
177
+ System prompt string for ``claude -p --system-prompt``.
178
+ """
179
+ parts: List[str] = []
180
+ soul_path = session_config.get("soul_blueprint")
181
+
182
+ if soul_path:
183
+ sp = Path(soul_path)
184
+ if sp.is_file():
185
+ try:
186
+ parts.append(sp.read_text(encoding="utf-8"))
187
+ except OSError:
188
+ parts.append(f"Soul blueprint: {soul_path}")
189
+ elif sp.is_dir():
190
+ for ext in ("*.md", "*.txt", "*.yaml"):
191
+ for f in sorted(sp.glob(ext)):
192
+ try:
193
+ parts.append(f.read_text(encoding="utf-8"))
194
+ except OSError:
195
+ pass
196
+ if not parts:
197
+ parts.append(f"Soul blueprint: {soul_path}")
198
+ else:
199
+ parts.append(f"Soul blueprint: {soul_path}")
200
+
201
+ agent_name = session_config.get("agent_name", "agent")
202
+ parts.append(
203
+ f"\nAgent: {agent_name}\n"
204
+ f"Role: {session_config.get('role', 'worker')}\n"
205
+ f"Team: {session_config.get('team_name', '')}\n"
206
+ f"Skills: {json.dumps(session_config.get('skills', []))}\n"
207
+ )
208
+ return "\n".join(parts)
209
+
210
+
211
+ # ---------------------------------------------------------------------------
212
+ # Claude dispatch
213
+ # ---------------------------------------------------------------------------
214
+
215
+
216
+ def dispatch_to_claude(
217
+ prompt: str,
218
+ model: str,
219
+ system_prompt: str,
220
+ claude_binary: str = _CLAUDE_BINARY,
221
+ ) -> Optional[str]:
222
+ """Call ``claude -p`` with the given prompt and return the output.
223
+
224
+ Args:
225
+ prompt: The user prompt to send.
226
+ model: Model name (e.g. ``claude-opus-4-6``).
227
+ system_prompt: System prompt for context.
228
+ claude_binary: Path to the claude CLI binary.
229
+
230
+ Returns:
231
+ Claude's response text, or None on failure.
232
+ """
233
+ cmd = [
234
+ claude_binary,
235
+ "-p",
236
+ "--model", model,
237
+ "--system-prompt", system_prompt,
238
+ "--dangerously-skip-permissions",
239
+ prompt,
240
+ ]
241
+
242
+ try:
243
+ result = subprocess.run(
244
+ cmd,
245
+ capture_output=True,
246
+ text=True,
247
+ timeout=300,
248
+ )
249
+ if result.returncode == 0:
250
+ return result.stdout.strip()
251
+ logger.warning(
252
+ "Claude returned exit code %d: %s", result.returncode, result.stderr
253
+ )
254
+ return None
255
+ except subprocess.TimeoutExpired:
256
+ logger.warning("Claude call timed out for prompt: %s...", prompt[:80])
257
+ return None
258
+ except OSError as exc:
259
+ logger.error("Failed to invoke claude: %s", exc)
260
+ return None
261
+
262
+
263
+ # ---------------------------------------------------------------------------
264
+ # Inbox / outbox
265
+ # ---------------------------------------------------------------------------
266
+
267
+
268
+ def _comms_root() -> Path:
269
+ """Return the skcapstone comms root directory."""
270
+ from . import SHARED_ROOT
271
+ return Path(SHARED_ROOT).expanduser() / "sync" / "comms"
272
+
273
+
274
+ def poll_inbox(team_name: str, agent_name: str) -> List[Path]:
275
+ """Check the agent's inbox for pending message files.
276
+
277
+ Args:
278
+ team_name: Team name for comms routing.
279
+ agent_name: Agent instance name.
280
+
281
+ Returns:
282
+ List of message file paths found in the inbox (sorted by name).
283
+ """
284
+ inbox = _comms_root() / team_name / agent_name / "inbox"
285
+ if not inbox.is_dir():
286
+ return []
287
+ return sorted(inbox.iterdir())
288
+
289
+
290
+ def write_outbox(team_name: str, agent_name: str, message: Dict[str, Any]) -> None:
291
+ """Write a response message to the agent's outbox.
292
+
293
+ Args:
294
+ team_name: Team name for comms routing.
295
+ agent_name: Agent instance name.
296
+ message: Message dict to write as JSON.
297
+ """
298
+ outbox = _comms_root() / team_name / agent_name / "outbox"
299
+ outbox.mkdir(parents=True, exist_ok=True)
300
+ filename = f"{_now_iso().replace(':', '-')}.json"
301
+ (outbox / filename).write_text(
302
+ json.dumps(message, indent=2), encoding="utf-8"
303
+ )
304
+
305
+
306
+ # ---------------------------------------------------------------------------
307
+ # Daemon loop
308
+ # ---------------------------------------------------------------------------
309
+
310
+
311
+ _running = True
312
+
313
+
314
+ def _handle_signal(signum: int, frame: Any) -> None:
315
+ """Signal handler for graceful shutdown."""
316
+ global _running
317
+ _running = False
318
+
319
+
320
+ def daemon_loop(
321
+ session_config: Dict[str, Any],
322
+ crush_config: Dict[str, Any],
323
+ state_file: str,
324
+ ) -> None:
325
+ """Main daemon loop: poll inbox, dispatch to claude, write results.
326
+
327
+ Args:
328
+ session_config: Parsed session.json.
329
+ crush_config: Parsed crush.json.
330
+ state_file: Path to the session state file.
331
+ """
332
+ global _running
333
+
334
+ agent_name = session_config.get("agent_name", "agent")
335
+ team_name = session_config.get("team_name", "default")
336
+ model = session_config.get("model", "fast")
337
+ system_prompt = build_system_prompt(session_config)
338
+
339
+ iteration = 0
340
+ while _running:
341
+ iteration += 1
342
+
343
+ # Poll inbox
344
+ messages = poll_inbox(team_name, agent_name)
345
+ for msg_path in messages:
346
+ if not _running:
347
+ break
348
+ try:
349
+ msg_data = json.loads(msg_path.read_text(encoding="utf-8"))
350
+ prompt = msg_data.get("prompt") or msg_data.get("task") or str(msg_data)
351
+ except (json.JSONDecodeError, OSError):
352
+ prompt = None
353
+
354
+ if prompt:
355
+ response = dispatch_to_claude(prompt, model, system_prompt)
356
+ if response:
357
+ write_outbox(team_name, agent_name, {
358
+ "source": str(msg_path.name),
359
+ "response": response,
360
+ "timestamp": _now_iso(),
361
+ })
362
+
363
+ # Remove processed message
364
+ try:
365
+ msg_path.unlink()
366
+ except OSError:
367
+ pass
368
+
369
+ # Update heartbeat
370
+ write_state(state_file, {
371
+ "status": "running",
372
+ "pid": os.getpid(),
373
+ "agent_name": agent_name,
374
+ "heartbeat": _now_iso(),
375
+ "iteration": iteration,
376
+ "binary": "crush-shim",
377
+ })
378
+
379
+ # Sleep between polls
380
+ for _ in range(int(_POLL_INTERVAL_SECONDS * 10)):
381
+ if not _running:
382
+ break
383
+ time.sleep(0.1)
384
+
385
+
386
+ # ---------------------------------------------------------------------------
387
+ # Entry point
388
+ # ---------------------------------------------------------------------------
389
+
390
+
391
+ def main(argv: Optional[List[str]] = None) -> None:
392
+ """Crush shim entry point.
393
+
394
+ Parses arguments, loads configs, registers signal handlers, and enters
395
+ the daemon loop.
396
+
397
+ Args:
398
+ argv: Argument list (defaults to sys.argv[1:]).
399
+ """
400
+ logging.basicConfig(
401
+ level=logging.INFO,
402
+ format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
403
+ )
404
+
405
+ args = parse_args(argv)
406
+
407
+ if args.command != "run":
408
+ logger.error("Unknown command: %s (expected 'run')", args.command)
409
+ sys.exit(1)
410
+
411
+ session_config = load_session_config(args.session)
412
+ crush_config = load_crush_config(args.config)
413
+
414
+ agent_name = session_config.get("agent_name", "unknown")
415
+ logger.info("Starting crush shim for agent %s", agent_name)
416
+
417
+ # Write initial running state
418
+ write_state(args.state_file, {
419
+ "status": "running",
420
+ "pid": os.getpid(),
421
+ "agent_name": agent_name,
422
+ "started_at": _now_iso(),
423
+ "binary": "crush-shim",
424
+ })
425
+
426
+ # Register signal handlers
427
+ signal.signal(signal.SIGTERM, _handle_signal)
428
+ signal.signal(signal.SIGINT, _handle_signal)
429
+
430
+ try:
431
+ daemon_loop(session_config, crush_config, args.state_file)
432
+ except Exception:
433
+ logger.exception("Daemon loop crashed")
434
+ write_state(args.state_file, {
435
+ "status": "error",
436
+ "pid": os.getpid(),
437
+ "agent_name": agent_name,
438
+ "error_at": _now_iso(),
439
+ "binary": "crush-shim",
440
+ })
441
+ sys.exit(1)
442
+
443
+ # Clean shutdown
444
+ write_state(args.state_file, {
445
+ "status": "stopped",
446
+ "agent_name": agent_name,
447
+ "stopped_at": _now_iso(),
448
+ "binary": "crush-shim",
449
+ })
450
+ logger.info("Crush shim for %s stopped cleanly", agent_name)
451
+
452
+
453
+ if __name__ == "__main__":
454
+ main()