@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,260 @@
1
+ """
2
+ Two-factor memory verification — truth-check gate for short-term → mid-term promotion.
3
+
4
+ Before any SHORT_TERM → MID_TERM promotion this module:
5
+ 1. Calls skseed.skill.truth_check() on the candidate memory content.
6
+ 2. If a contradiction is found (coherence_score < 0.7 or collision_fragments non-empty):
7
+ a. Tags the candidate memory with tag=conflicting (saves it back to short-term).
8
+ b. Stores a conflict-report memory (also tag=conflicting) documenting the issue.
9
+ c. Fires a desktop notification with urgency=critical.
10
+ d. Returns VerificationResult(should_promote=False).
11
+ 3. If truth-aligned, returns VerificationResult(should_promote=True).
12
+
13
+ Promotion is skipped until the conflict is resolved — i.e., the ``conflicting`` tag
14
+ is manually cleared (or via skseed_audit resolution).
15
+
16
+ Fail-open design: if skseed is not installed, or truth_check raises unexpectedly,
17
+ promotion proceeds normally so minimal deployments are unaffected.
18
+ """
19
+
20
+ from __future__ import annotations
21
+
22
+ import logging
23
+ from dataclasses import dataclass, field
24
+ from pathlib import Path
25
+ from typing import Optional
26
+
27
+ logger = logging.getLogger("skcapstone.memory_verifier")
28
+
29
+
30
+ # ---------------------------------------------------------------------------
31
+ # Result type
32
+ # ---------------------------------------------------------------------------
33
+
34
+
35
+ @dataclass
36
+ class VerificationResult:
37
+ """Result of a pre-promotion truth-check gate.
38
+
39
+ Attributes:
40
+ should_promote: Whether the memory may advance to mid-term.
41
+ is_conflicting: True when a contradiction was detected.
42
+ coherence_score: Collider coherence score (0.0–1.0).
43
+ collision_fragments: Contradiction strings found by the collider.
44
+ truth_grade: TruthGrade value string from the collider.
45
+ conflict_report_id: memory_id of the stored conflict-report entry,
46
+ present only when is_conflicting is True.
47
+ """
48
+
49
+ should_promote: bool
50
+ is_conflicting: bool = False
51
+ coherence_score: float = 0.0
52
+ collision_fragments: list[str] = field(default_factory=list)
53
+ truth_grade: str = "ungraded"
54
+ conflict_report_id: Optional[str] = None
55
+
56
+
57
+ # ---------------------------------------------------------------------------
58
+ # Public gate
59
+ # ---------------------------------------------------------------------------
60
+
61
+
62
+ def verify_before_promotion(home: Path, entry) -> VerificationResult:
63
+ """Truth-check gate called before promoting a SHORT_TERM memory to MID_TERM.
64
+
65
+ Args:
66
+ home: Agent home directory (~/.skcapstone).
67
+ entry: MemoryEntry candidate (expected to be in SHORT_TERM layer).
68
+
69
+ Returns:
70
+ VerificationResult — consult .should_promote before proceeding.
71
+ """
72
+ # Only gate SHORT_TERM → MID_TERM transitions
73
+ from .models import MemoryLayer
74
+
75
+ if entry.layer != MemoryLayer.SHORT_TERM:
76
+ return VerificationResult(should_promote=True)
77
+
78
+ # Skip the gate for verifier-generated meta-records (conflict reports).
79
+ # These entries describe the conflict itself and must not be re-checked,
80
+ # which would create an infinite verification cascade.
81
+ if getattr(entry, "source", "") == "memory_verifier":
82
+ return VerificationResult(should_promote=True)
83
+
84
+ # Fail-open if skseed is not installed
85
+ try:
86
+ from skseed.skill import truth_check
87
+ except ImportError:
88
+ logger.debug(
89
+ "skseed not installed — skipping truth-check gate (fail-open) for %s",
90
+ entry.memory_id,
91
+ )
92
+ return VerificationResult(should_promote=True)
93
+
94
+ try:
95
+ result = truth_check(
96
+ belief=entry.content,
97
+ source="model",
98
+ domain="memory-promotion",
99
+ )
100
+ except Exception as exc:
101
+ logger.warning(
102
+ "truth_check raised for memory %s (fail-open): %s",
103
+ entry.memory_id,
104
+ exc,
105
+ )
106
+ return VerificationResult(should_promote=True)
107
+
108
+ is_aligned: bool = result.get("is_aligned", True)
109
+ collider: dict = result.get("collider_result", {})
110
+ fragments: list[str] = collider.get("collision_fragments", [])
111
+ coherence: float = float(collider.get("coherence_score", 1.0))
112
+ grade: str = str(collider.get("truth_grade", "ungraded"))
113
+
114
+ contradiction_found = (not is_aligned) or bool(fragments)
115
+
116
+ if not contradiction_found:
117
+ logger.debug(
118
+ "Memory %s passed truth-check (coherence=%.2f grade=%s) — promotion allowed",
119
+ entry.memory_id,
120
+ coherence,
121
+ grade,
122
+ )
123
+ return VerificationResult(
124
+ should_promote=True,
125
+ coherence_score=coherence,
126
+ truth_grade=grade,
127
+ )
128
+
129
+ # --- Contradiction detected ---
130
+ logger.warning(
131
+ "Memory %s failed truth-check: is_aligned=%s coherence=%.2f grade=%s fragments=%d",
132
+ entry.memory_id,
133
+ is_aligned,
134
+ coherence,
135
+ grade,
136
+ len(fragments),
137
+ )
138
+
139
+ _tag_conflicting(home, entry)
140
+ report_id = _store_conflict_report(home, entry, fragments, coherence, grade)
141
+ _fire_conflict_notification(entry, fragments, coherence)
142
+
143
+ return VerificationResult(
144
+ should_promote=False,
145
+ is_conflicting=True,
146
+ coherence_score=coherence,
147
+ collision_fragments=fragments,
148
+ truth_grade=grade,
149
+ conflict_report_id=report_id,
150
+ )
151
+
152
+
153
+ # ---------------------------------------------------------------------------
154
+ # Helpers
155
+ # ---------------------------------------------------------------------------
156
+
157
+
158
+ def _tag_conflicting(home: Path, entry) -> None:
159
+ """Add tag=conflicting to the candidate entry and re-save it to short-term."""
160
+ if "conflicting" not in entry.tags:
161
+ entry.tags = list(entry.tags) + ["conflicting"]
162
+ try:
163
+ from .memory_engine import _save_entry, _update_index
164
+
165
+ _save_entry(home, entry)
166
+ _update_index(home, entry)
167
+ logger.info(
168
+ "Tagged memory %s as conflicting (stays in short-term)",
169
+ entry.memory_id,
170
+ )
171
+ except Exception as exc:
172
+ logger.error(
173
+ "Failed to persist conflicting tag for %s: %s",
174
+ entry.memory_id,
175
+ exc,
176
+ )
177
+
178
+
179
+ def _store_conflict_report(
180
+ home: Path,
181
+ entry,
182
+ fragments: list[str],
183
+ coherence: float,
184
+ grade: str,
185
+ ) -> Optional[str]:
186
+ """Store a short-term conflict-report memory documenting the failed truth-check.
187
+
188
+ Returns:
189
+ memory_id of the created report, or None on failure.
190
+ """
191
+ if fragments:
192
+ fragment_summary = "; ".join(fragments[:3])
193
+ if len(fragments) > 3:
194
+ fragment_summary += f" … (+{len(fragments) - 3} more)"
195
+ else:
196
+ fragment_summary = "coherence below threshold"
197
+
198
+ preview = entry.content[:120]
199
+ if len(entry.content) > 120:
200
+ preview += "…"
201
+
202
+ report_content = (
203
+ f"[CONFLICT REPORT] Memory {entry.memory_id!r} failed truth-check — "
204
+ f"SHORT_TERM→MID_TERM promotion BLOCKED. "
205
+ f"Coherence: {coherence:.2f}, Grade: {grade}. "
206
+ f"Contradictions: {fragment_summary}. "
207
+ f"Content preview: {preview!r}"
208
+ )
209
+
210
+ try:
211
+ from .memory_engine import store as mem_store
212
+ from .models import MemoryLayer
213
+
214
+ report = mem_store(
215
+ home=home,
216
+ content=report_content,
217
+ tags=["conflicting", "truth-check", "promotion-blocked"],
218
+ source="memory_verifier",
219
+ importance=0.6, # below 0.7: stays in short-term until conflict resolved
220
+ layer=MemoryLayer.SHORT_TERM,
221
+ )
222
+ logger.info(
223
+ "Stored conflict report %s for candidate %s",
224
+ report.memory_id,
225
+ entry.memory_id,
226
+ )
227
+ return report.memory_id
228
+ except Exception as exc:
229
+ logger.error("Failed to store conflict report for %s: %s", entry.memory_id, exc)
230
+ return None
231
+
232
+
233
+ def _fire_conflict_notification(entry, fragments: list[str], coherence: float) -> None:
234
+ """Dispatch a critical desktop notification for a promotion conflict."""
235
+ preview = entry.content[:60]
236
+ if len(entry.content) > 60:
237
+ preview += "…"
238
+
239
+ if fragments:
240
+ hint = f" — {fragments[0][:50]}"
241
+ else:
242
+ hint = f" (coherence {coherence:.2f})"
243
+
244
+ title = "Memory Conflict Detected"
245
+ body = f"Promotion blocked [{entry.memory_id}]: {preview}{hint}"
246
+
247
+ try:
248
+ from .notifications import notify
249
+
250
+ notify(title=title, body=body, urgency="critical")
251
+ logger.info(
252
+ "Fired critical notification for conflicting memory %s",
253
+ entry.memory_id,
254
+ )
255
+ except Exception as exc:
256
+ logger.error(
257
+ "Failed to fire conflict notification for %s: %s",
258
+ entry.memory_id,
259
+ exc,
260
+ )
@@ -0,0 +1,215 @@
1
+ """
2
+ SKChat message encryption — AES-256-GCM content encryption.
3
+
4
+ Provides encrypt/decrypt for chat message content with a key derived
5
+ from the agent's KMS service key (label: 'skchat').
6
+
7
+ Wire format (JSON envelope):
8
+ {
9
+ "skchat_encrypted": true,
10
+ "v": 1,
11
+ "ciphertext": "<base64(nonce_12 || ciphertext+tag_16)>"
12
+ }
13
+
14
+ Key derivation:
15
+ KeyStore.derive_service_key("skchat") → 32-byte AES key
16
+
17
+ Usage:
18
+ from skcapstone.message_crypto import encrypt_content, decrypt_content
19
+
20
+ token = encrypt_content("hello", home) # → JSON envelope str
21
+ plain = decrypt_content(token, home) # → "hello"
22
+ """
23
+
24
+ from __future__ import annotations
25
+
26
+ import base64
27
+ import json
28
+ import logging
29
+ import os
30
+ from pathlib import Path
31
+ from typing import Optional
32
+
33
+ logger = logging.getLogger("skcapstone.message_crypto")
34
+
35
+ # Marker key in the envelope JSON
36
+ _MARKER = "skchat_encrypted"
37
+ _VERSION = 1
38
+
39
+
40
+ # ---------------------------------------------------------------------------
41
+ # Low-level AES-256-GCM primitives (no KMS dependency)
42
+ # ---------------------------------------------------------------------------
43
+
44
+ def encrypt_message(plaintext: str, key: bytes) -> str:
45
+ """Encrypt a plaintext string with AES-256-GCM.
46
+
47
+ Args:
48
+ plaintext: UTF-8 message content.
49
+ key: 32-byte AES key.
50
+
51
+ Returns:
52
+ Base64-encoded bytes: nonce (12) || ciphertext+tag.
53
+
54
+ Raises:
55
+ ValueError: If key is not exactly 32 bytes.
56
+ """
57
+ if len(key) != 32:
58
+ raise ValueError(f"AES-256 requires a 32-byte key, got {len(key)}")
59
+
60
+ from cryptography.hazmat.primitives.ciphers.aead import AESGCM
61
+
62
+ nonce = os.urandom(12)
63
+ aesgcm = AESGCM(key)
64
+ ct = aesgcm.encrypt(nonce, plaintext.encode("utf-8"), None)
65
+ return base64.b64encode(nonce + ct).decode("ascii")
66
+
67
+
68
+ def decrypt_message(token: str, key: bytes) -> str:
69
+ """Decrypt a base64 AES-256-GCM token.
70
+
71
+ Args:
72
+ token: Base64-encoded nonce||ciphertext+tag (from encrypt_message).
73
+ key: 32-byte AES key.
74
+
75
+ Returns:
76
+ Decrypted plaintext string.
77
+
78
+ Raises:
79
+ ValueError: If key is not exactly 32 bytes.
80
+ cryptography.exceptions.InvalidTag: If authentication fails (wrong key
81
+ or tampered ciphertext).
82
+ """
83
+ if len(key) != 32:
84
+ raise ValueError(f"AES-256 requires a 32-byte key, got {len(key)}")
85
+
86
+ from cryptography.hazmat.primitives.ciphers.aead import AESGCM
87
+
88
+ raw = base64.b64decode(token)
89
+ if len(raw) < 12:
90
+ raise ValueError("Ciphertext too short — must be at least 12 bytes (nonce)")
91
+
92
+ nonce, ct = raw[:12], raw[12:]
93
+ aesgcm = AESGCM(key)
94
+ return aesgcm.decrypt(nonce, ct, None).decode("utf-8")
95
+
96
+
97
+ # ---------------------------------------------------------------------------
98
+ # Envelope helpers
99
+ # ---------------------------------------------------------------------------
100
+
101
+ def pack_encrypted(ciphertext_b64: str) -> str:
102
+ """Wrap a base64 ciphertext in the skchat_encrypted JSON envelope.
103
+
104
+ Args:
105
+ ciphertext_b64: Base64 token from encrypt_message.
106
+
107
+ Returns:
108
+ JSON string with the skchat_encrypted envelope.
109
+ """
110
+ return json.dumps({
111
+ _MARKER: True,
112
+ "v": _VERSION,
113
+ "ciphertext": ciphertext_b64,
114
+ })
115
+
116
+
117
+ def unpack_encrypted(content: str) -> Optional[str]:
118
+ """Extract the base64 ciphertext from an encrypted envelope, or None.
119
+
120
+ Args:
121
+ content: Message content string (may or may not be an envelope).
122
+
123
+ Returns:
124
+ Base64 ciphertext if content is an encrypted envelope, else None.
125
+ """
126
+ try:
127
+ data = json.loads(content)
128
+ if data.get(_MARKER) is True and "ciphertext" in data:
129
+ return data["ciphertext"]
130
+ except (json.JSONDecodeError, TypeError, AttributeError):
131
+ pass
132
+ return None
133
+
134
+
135
+ def is_encrypted_content(content: str) -> bool:
136
+ """Return True if content is an skchat_encrypted envelope.
137
+
138
+ Args:
139
+ content: Message content string.
140
+
141
+ Returns:
142
+ bool: True when the content carries an encrypted payload.
143
+ """
144
+ return unpack_encrypted(content) is not None
145
+
146
+
147
+ # ---------------------------------------------------------------------------
148
+ # KMS-backed key derivation
149
+ # ---------------------------------------------------------------------------
150
+
151
+ def derive_chat_key(home: Path) -> bytes:
152
+ """Derive the skchat service key from the agent's KMS.
153
+
154
+ Initializes the KeyStore (creating it if absent) and derives a
155
+ deterministic 32-byte AES key for the 'skchat' service using
156
+ HKDF-SHA256.
157
+
158
+ Args:
159
+ home: Agent home directory (~/.skcapstone).
160
+
161
+ Returns:
162
+ 32-byte key material.
163
+
164
+ Raises:
165
+ RuntimeError: If key derivation fails.
166
+ """
167
+ try:
168
+ from .kms import KeyStore
169
+
170
+ store = KeyStore(home)
171
+ store.initialize()
172
+ record = store.derive_service_key("skchat")
173
+ return store.get_key_material(record.key_id)
174
+ except Exception as exc:
175
+ raise RuntimeError(f"Failed to derive skchat key from KMS: {exc}") from exc
176
+
177
+
178
+ # ---------------------------------------------------------------------------
179
+ # Convenience API (KMS-aware)
180
+ # ---------------------------------------------------------------------------
181
+
182
+ def encrypt_content(plaintext: str, home: Path) -> str:
183
+ """Encrypt message content using the agent's KMS-derived skchat key.
184
+
185
+ Args:
186
+ plaintext: Message text to encrypt.
187
+ home: Agent home directory.
188
+
189
+ Returns:
190
+ JSON envelope string ready to use as message content.
191
+ """
192
+ key = derive_chat_key(home)
193
+ token = encrypt_message(plaintext, key)
194
+ return pack_encrypted(token)
195
+
196
+
197
+ def decrypt_content(content: str, home: Path) -> str:
198
+ """Decrypt an encrypted message envelope using the KMS-derived skchat key.
199
+
200
+ If the content is not an encrypted envelope, returns it unchanged
201
+ (pass-through for plaintext messages).
202
+
203
+ Args:
204
+ content: Message content (envelope or plain).
205
+ home: Agent home directory.
206
+
207
+ Returns:
208
+ Decrypted plaintext (or original content if not encrypted).
209
+ """
210
+ token = unpack_encrypted(content)
211
+ if token is None:
212
+ return content
213
+
214
+ key = derive_chat_key(home)
215
+ return decrypt_message(token, key)