@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,230 @@
1
+ """
2
+ ConversationStore — focused, stateless per-peer conversation history.
3
+
4
+ Stores conversations as JSON arrays in {home}/conversations/{peer}.json.
5
+ Each entry: {"role": str, "content": str, "timestamp": ISO-8601}.
6
+
7
+ Unlike ConversationManager this module is stateless — every call reads
8
+ from / writes to disk directly, making it suitable for CLI tools and
9
+ processes that need to see the latest on-disk state rather than a
10
+ snapshot loaded at init time.
11
+
12
+ Compatible with ConversationManager: both use the same JSON file format
13
+ so files written by one can be read by the other without migration.
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ import json
19
+ import logging
20
+ import re
21
+ from datetime import datetime, timezone
22
+ from pathlib import Path
23
+ from typing import Optional
24
+
25
+ logger = logging.getLogger("skcapstone.conversation_store")
26
+
27
+ # Allowlist for peer name characters (alphanumeric + safe punctuation)
28
+ _PEER_NAME_SAFE_RE = re.compile(r"[^a-zA-Z0-9_\-@\.]")
29
+
30
+
31
+ def _sanitize_peer_name(peer: str) -> str:
32
+ """Sanitize a peer name for safe use as a filesystem key.
33
+
34
+ Strips path separators, null bytes, and any character not in the
35
+ alphanumeric + ``-_@.`` set. Caps length at 64 characters.
36
+ Returns ``"unknown"`` if the result would be empty.
37
+
38
+ Args:
39
+ peer: Raw peer name.
40
+
41
+ Returns:
42
+ Filesystem-safe peer name, at most 64 characters long.
43
+ """
44
+ if not peer or not isinstance(peer, str):
45
+ return "unknown"
46
+ sanitized = peer.replace("\x00", "").replace("/", "").replace("\\", "")
47
+ sanitized = _PEER_NAME_SAFE_RE.sub("", sanitized)
48
+ sanitized = sanitized.strip(".")
49
+ return sanitized[:64] or "unknown"
50
+
51
+
52
+ class ConversationStore:
53
+ """Lightweight, stateless per-peer conversation history store.
54
+
55
+ Reads and writes ``{home}/conversations/{peer}.json`` files directly
56
+ with atomic rename-based updates. No in-memory caching — every call
57
+ reflects the current on-disk state.
58
+
59
+ Compatible with :class:`~skcapstone.conversation_manager.ConversationManager`:
60
+ both use the same JSON list format, so files are interchangeable.
61
+
62
+ Args:
63
+ home: Agent home directory (e.g. ``~/.skcapstone``).
64
+ """
65
+
66
+ def __init__(self, home: Path) -> None:
67
+ self._home = Path(home)
68
+ self._dir = self._home / "conversations"
69
+
70
+ # ------------------------------------------------------------------
71
+ # Write
72
+ # ------------------------------------------------------------------
73
+
74
+ def append(
75
+ self,
76
+ peer: str,
77
+ role: str,
78
+ content: str,
79
+ *,
80
+ thread_id: Optional[str] = None,
81
+ in_reply_to: Optional[str] = None,
82
+ ) -> dict:
83
+ """Append one message to the peer's history file.
84
+
85
+ Reads the existing file (if any), appends the new entry, and
86
+ atomically writes back. Creates the file and parent directory
87
+ if absent.
88
+
89
+ Args:
90
+ peer: Peer agent name.
91
+ role: ``"user"`` or ``"assistant"``.
92
+ content: Message text.
93
+ thread_id: Optional thread identifier for grouping messages.
94
+ in_reply_to: Optional message ID this message replies to.
95
+
96
+ Returns:
97
+ The message dict that was stored (always includes
98
+ ``role``, ``content``, and ``timestamp``).
99
+ """
100
+ peer = _sanitize_peer_name(peer)
101
+ msg: dict = {
102
+ "role": role,
103
+ "content": content,
104
+ "timestamp": datetime.now(timezone.utc).isoformat(),
105
+ }
106
+ if thread_id:
107
+ msg["thread_id"] = thread_id
108
+ if in_reply_to:
109
+ msg["in_reply_to"] = in_reply_to
110
+
111
+ history = self._read(peer)
112
+ history.append(msg)
113
+ self._write(peer, history)
114
+ return msg
115
+
116
+ # ------------------------------------------------------------------
117
+ # Read
118
+ # ------------------------------------------------------------------
119
+
120
+ def get_last(self, peer: str, n: int = 10) -> list[dict]:
121
+ """Return the last *n* messages for a peer.
122
+
123
+ Args:
124
+ peer: Peer agent name.
125
+ n: Maximum number of messages to return (default 10).
126
+
127
+ Returns:
128
+ List of message dicts, oldest first. Empty list if peer
129
+ unknown or *n* is zero.
130
+ """
131
+ peer = _sanitize_peer_name(peer)
132
+ history = self._read(peer)
133
+ return history[-n:] if n > 0 else []
134
+
135
+ def load(self, peer: str) -> list[dict]:
136
+ """Return the full conversation history for a peer.
137
+
138
+ Args:
139
+ peer: Peer agent name.
140
+
141
+ Returns:
142
+ List of all stored message dicts, oldest first.
143
+ """
144
+ peer = _sanitize_peer_name(peer)
145
+ return self._read(peer)
146
+
147
+ def all_peers(self) -> list[str]:
148
+ """Return names of all peers that have a saved conversation file.
149
+
150
+ Returns:
151
+ Sorted list of peer names (file stems without extension).
152
+ """
153
+ if not self._dir.exists():
154
+ return []
155
+ return sorted(p.stem for p in self._dir.glob("*.json"))
156
+
157
+ # ------------------------------------------------------------------
158
+ # Delete
159
+ # ------------------------------------------------------------------
160
+
161
+ def clear(self, peer: str) -> bool:
162
+ """Delete a peer's conversation file.
163
+
164
+ Args:
165
+ peer: Peer agent name.
166
+
167
+ Returns:
168
+ ``True`` if the file existed and was deleted, ``False``
169
+ if the peer had no saved history.
170
+ """
171
+ peer = _sanitize_peer_name(peer)
172
+ target = self._dir / f"{peer}.json"
173
+ if target.exists():
174
+ target.unlink()
175
+ return True
176
+ return False
177
+
178
+ # ------------------------------------------------------------------
179
+ # Prompt helpers
180
+ # ------------------------------------------------------------------
181
+
182
+ def format_for_prompt(self, peer: str, n: int = 10) -> str:
183
+ """Format the last *n* messages as a prompt-ready string.
184
+
185
+ Args:
186
+ peer: Peer agent name.
187
+ n: Maximum messages to include.
188
+
189
+ Returns:
190
+ Human-readable history block, or empty string if no history.
191
+ """
192
+ messages = self.get_last(peer, n)
193
+ if not messages:
194
+ return ""
195
+ lines = [f"Recent conversation with {peer}:"]
196
+ for msg in messages:
197
+ role = msg.get("role", "?")
198
+ content = msg.get("content", "")[:200]
199
+ lines.append(f" [{role}] {content}")
200
+ return "\n".join(lines)
201
+
202
+ # ------------------------------------------------------------------
203
+ # Private helpers
204
+ # ------------------------------------------------------------------
205
+
206
+ def _read(self, peer: str) -> list[dict]:
207
+ """Read the peer's conversation file, returning [] on any error."""
208
+ target = self._dir / f"{peer}.json"
209
+ if not target.exists():
210
+ return []
211
+ try:
212
+ data = json.loads(target.read_text(encoding="utf-8"))
213
+ return data if isinstance(data, list) else []
214
+ except Exception as exc:
215
+ logger.debug("Failed to read conversation for %s: %s", peer, exc)
216
+ return []
217
+
218
+ def _write(self, peer: str, history: list[dict]) -> None:
219
+ """Atomically write *history* to the peer's conversation file."""
220
+ try:
221
+ self._dir.mkdir(parents=True, exist_ok=True)
222
+ target = self._dir / f"{peer}.json"
223
+ tmp = target.with_suffix(".json.tmp")
224
+ tmp.write_text(
225
+ json.dumps(history, ensure_ascii=False, indent=2),
226
+ encoding="utf-8",
227
+ )
228
+ tmp.replace(target)
229
+ except Exception as exc:
230
+ logger.debug("Failed to write conversation for %s: %s", peer, exc)
@@ -0,0 +1,252 @@
1
+ """
2
+ ConversationSummarizer — LLM-powered peer conversation summarization.
3
+
4
+ Reads the last N messages from a peer conversation file, sends them to
5
+ the local LLM via LLMBridge, and stores the resulting 2-3 sentence
6
+ summary in ~/.skcapstone/summaries/{peer}.json.
7
+
8
+ Usage:
9
+ summarizer = ConversationSummarizer(home=Path("~/.skcapstone"))
10
+ summary = summarizer.summarize("lumina", n=20)
11
+ print(summary.text)
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import json
17
+ import logging
18
+ import re
19
+ from datetime import datetime, timezone
20
+ from pathlib import Path
21
+ from typing import Optional
22
+
23
+ logger = logging.getLogger("skcapstone.conversation_summarizer")
24
+
25
+ # Allowlist for peer name characters (mirrors conversation_manager)
26
+ _PEER_NAME_SAFE_RE = re.compile(r"[^a-zA-Z0-9_\-@\.]")
27
+
28
+
29
+ def _sanitize_peer_name(peer: str) -> str:
30
+ """Sanitize peer name for safe filesystem use.
31
+
32
+ Args:
33
+ peer: Raw peer name.
34
+
35
+ Returns:
36
+ Safe peer name capped at 64 characters, or ``"unknown"``.
37
+ """
38
+ if not peer or not isinstance(peer, str):
39
+ return "unknown"
40
+ sanitized = peer.replace("\x00", "").replace("/", "").replace("\\", "")
41
+ sanitized = _PEER_NAME_SAFE_RE.sub("", sanitized)
42
+ sanitized = sanitized.strip(".")
43
+ return sanitized[:64] or "unknown"
44
+
45
+
46
+ class ConversationSummary:
47
+ """Result of a conversation summarization.
48
+
49
+ Attributes:
50
+ peer: The peer agent that was summarized.
51
+ text: The 2-3 sentence summary text.
52
+ message_count: Number of messages that were summarized.
53
+ generated_at: UTC ISO timestamp when the summary was produced.
54
+ """
55
+
56
+ def __init__(self, peer: str, text: str, message_count: int, generated_at: str) -> None:
57
+ self.peer = peer
58
+ self.text = text
59
+ self.message_count = message_count
60
+ self.generated_at = generated_at
61
+
62
+ def to_dict(self) -> dict:
63
+ """Serialize to a plain dict for JSON storage."""
64
+ return {
65
+ "peer": self.peer,
66
+ "text": self.text,
67
+ "message_count": self.message_count,
68
+ "generated_at": self.generated_at,
69
+ }
70
+
71
+ @classmethod
72
+ def from_dict(cls, data: dict) -> "ConversationSummary":
73
+ """Deserialize from a stored dict."""
74
+ return cls(
75
+ peer=data.get("peer", ""),
76
+ text=data.get("text", ""),
77
+ message_count=data.get("message_count", 0),
78
+ generated_at=data.get("generated_at", ""),
79
+ )
80
+
81
+
82
+ class ConversationSummarizer:
83
+ """Summarize peer conversations using the agent's LLM.
84
+
85
+ Reads conversation history from ``{home}/conversations/{peer}.json``,
86
+ builds a summarization prompt, calls :class:`LLMBridge`, and persists
87
+ the result to ``{home}/summaries/{peer}.json``.
88
+
89
+ Args:
90
+ home: Agent home directory (e.g. ``~/.skcapstone``).
91
+ """
92
+
93
+ _SYSTEM_PROMPT = (
94
+ "You are a concise summarization assistant for a sovereign agent framework. "
95
+ "When given a conversation transcript, produce exactly 2-3 sentences that capture: "
96
+ "(1) the main topics discussed, (2) any decisions or outcomes reached, and "
97
+ "(3) the overall tone or relationship dynamic. "
98
+ "Be direct and factual. Do not use bullet points or headers."
99
+ )
100
+
101
+ def __init__(self, home: Path) -> None:
102
+ self._home = Path(home)
103
+ self._conversations_dir = self._home / "conversations"
104
+ self._summaries_dir = self._home / "summaries"
105
+
106
+ # ------------------------------------------------------------------
107
+ # Public API
108
+ # ------------------------------------------------------------------
109
+
110
+ def summarize(self, peer: str, n: int = 20, bridge=None) -> ConversationSummary:
111
+ """Summarize the last *n* messages with *peer* using the LLM.
112
+
113
+ Reads conversation history from disk, formats the messages into a
114
+ summarization prompt, calls :class:`LLMBridge`, and stores the
115
+ result in ``{home}/summaries/{peer}.json``.
116
+
117
+ Args:
118
+ peer: Peer agent name.
119
+ n: Maximum number of recent messages to include (default: 20).
120
+ bridge: Optional pre-constructed :class:`LLMBridge` instance.
121
+ If ``None`` a fresh one is created from defaults.
122
+
123
+ Returns:
124
+ :class:`ConversationSummary` with the generated text.
125
+
126
+ Raises:
127
+ ValueError: If there are no messages to summarize.
128
+ """
129
+ peer = _sanitize_peer_name(peer)
130
+ messages = self._load_messages(peer, n)
131
+
132
+ if not messages:
133
+ raise ValueError(f"No conversation history found for peer '{peer}'.")
134
+
135
+ llm_bridge = bridge or self._make_bridge()
136
+ prompt_text = self._format_prompt(peer, messages)
137
+
138
+ try:
139
+ from .model_router import TaskSignal
140
+ signal = TaskSignal(
141
+ description="Summarize a peer conversation",
142
+ tags=["summary", "conversation"],
143
+ estimated_tokens=len(prompt_text) // 4,
144
+ )
145
+ summary_text = llm_bridge.generate(
146
+ self._SYSTEM_PROMPT, prompt_text, signal
147
+ )
148
+ except Exception as exc:
149
+ logger.warning("LLM summarization failed: %s", exc)
150
+ summary_text = f"[Summary unavailable: {exc}]"
151
+
152
+ result = ConversationSummary(
153
+ peer=peer,
154
+ text=summary_text,
155
+ message_count=len(messages),
156
+ generated_at=datetime.now(timezone.utc).isoformat(),
157
+ )
158
+ self._persist(result)
159
+ return result
160
+
161
+ def load_summary(self, peer: str) -> Optional[ConversationSummary]:
162
+ """Load the most recently stored summary for *peer*.
163
+
164
+ Args:
165
+ peer: Peer agent name.
166
+
167
+ Returns:
168
+ :class:`ConversationSummary` if one has been stored, else ``None``.
169
+ """
170
+ peer = _sanitize_peer_name(peer)
171
+ path = self._summaries_dir / f"{peer}.json"
172
+ if not path.exists():
173
+ return None
174
+ try:
175
+ data = json.loads(path.read_text(encoding="utf-8"))
176
+ return ConversationSummary.from_dict(data)
177
+ except Exception as exc:
178
+ logger.debug("Failed to load summary for %s: %s", peer, exc)
179
+ return None
180
+
181
+ # ------------------------------------------------------------------
182
+ # Private helpers
183
+ # ------------------------------------------------------------------
184
+
185
+ def _load_messages(self, peer: str, n: int) -> list[dict]:
186
+ """Load last *n* messages for *peer* from disk.
187
+
188
+ Args:
189
+ peer: Sanitized peer name.
190
+ n: Max messages to return.
191
+
192
+ Returns:
193
+ List of message dicts (may be empty).
194
+ """
195
+ conv_file = self._conversations_dir / f"{peer}.json"
196
+ if not conv_file.exists():
197
+ return []
198
+ try:
199
+ data = json.loads(conv_file.read_text(encoding="utf-8"))
200
+ if isinstance(data, list):
201
+ return data[-n:] if n > 0 else data
202
+ except Exception as exc:
203
+ logger.debug("Failed to load conversation for %s: %s", peer, exc)
204
+ return []
205
+
206
+ def _format_prompt(self, peer: str, messages: list[dict]) -> str:
207
+ """Format messages into a summarization request.
208
+
209
+ Args:
210
+ peer: Peer name (for context label).
211
+ messages: List of message dicts with ``role`` and ``content``.
212
+
213
+ Returns:
214
+ Formatted prompt string.
215
+ """
216
+ lines = [f"Conversation with {peer} ({len(messages)} messages):"]
217
+ lines.append("")
218
+ for msg in messages:
219
+ role = msg.get("role", "unknown")
220
+ content = str(msg.get("content", "")).strip()
221
+ label = "Agent" if role == "assistant" else peer.capitalize()
222
+ lines.append(f"{label}: {content}")
223
+ lines.append("")
224
+ lines.append("Please summarize this conversation in 2-3 sentences.")
225
+ return "\n".join(lines)
226
+
227
+ def _make_bridge(self):
228
+ """Instantiate a default :class:`LLMBridge`.
229
+
230
+ Returns:
231
+ A configured :class:`LLMBridge` instance.
232
+ """
233
+ from .consciousness_loop import ConsciousnessConfig, LLMBridge
234
+ config = ConsciousnessConfig()
235
+ return LLMBridge(config)
236
+
237
+ def _persist(self, summary: ConversationSummary) -> None:
238
+ """Write summary to ``{home}/summaries/{peer}.json``.
239
+
240
+ Uses a temp file + rename for atomic updates.
241
+
242
+ Args:
243
+ summary: The summary to persist.
244
+ """
245
+ try:
246
+ self._summaries_dir.mkdir(parents=True, exist_ok=True)
247
+ target = self._summaries_dir / f"{summary.peer}.json"
248
+ tmp = target.with_suffix(".json.tmp")
249
+ tmp.write_text(json.dumps(summary.to_dict(), ensure_ascii=False, indent=2), encoding="utf-8")
250
+ tmp.replace(target)
251
+ except Exception as exc:
252
+ logger.warning("Failed to persist summary for %s: %s", summary.peer, exc)