@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,364 @@
1
+ """
2
+ Tests for the full Syncthing ↔ consciousness loop comms pipeline.
3
+
4
+ Pipeline under test:
5
+ {shared_root}/sync/comms/inbox/{peer}/*.skc.json ← Syncthing writes here
6
+ → inotify detects file (ConsciousnessLoop._run_inotify)
7
+ → ConsciousnessLoop.process_envelope()
8
+ → skcomm.send(sender, response)
9
+ → {shared_root}/sync/comms/outbox/{peer}/*.skc.json ← Syncthing syncs this out
10
+
11
+ Three test classes:
12
+ TestInboxToOutboxFlow — mock LLM, drop inbox file, verify skcomm.send called
13
+ TestOutboxEnvelopeFormat — verify envelope spec compliance and path layout
14
+ TestSyncStatusInHealth — verify health snapshot includes sync_pipeline key
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ import json
20
+ from pathlib import Path
21
+ from unittest.mock import MagicMock, patch
22
+
23
+ import pytest
24
+
25
+ from skcapstone.sync_engine import (
26
+ ENVELOPE_SUFFIX,
27
+ get_inbox_dir,
28
+ get_outbox_dir,
29
+ get_sync_pipeline_status,
30
+ verify_pipeline_paths,
31
+ write_outbox_envelope,
32
+ )
33
+
34
+
35
+ # ---------------------------------------------------------------------------
36
+ # Fixtures
37
+ # ---------------------------------------------------------------------------
38
+
39
+
40
+ @pytest.fixture
41
+ def shared_root(tmp_path: Path) -> Path:
42
+ """Minimal shared-root with comms inbox/outbox directories pre-created."""
43
+ root = tmp_path / ".skcapstone"
44
+ root.mkdir()
45
+ (root / "sync" / "comms" / "inbox").mkdir(parents=True)
46
+ (root / "sync" / "comms" / "outbox").mkdir(parents=True)
47
+ return root
48
+
49
+
50
+ @pytest.fixture
51
+ def agent_home(shared_root: Path) -> Path:
52
+ """Single-agent mode: home == shared_root. Provides identity.json."""
53
+ home = shared_root
54
+ for d in ("identity", "memory", "trust", "config", "conversations"):
55
+ (home / d).mkdir(exist_ok=True)
56
+ (home / "identity" / "identity.json").write_text(
57
+ json.dumps({"name": "TestAgent", "fingerprint": "AABB1122CCDD3344"}),
58
+ encoding="utf-8",
59
+ )
60
+ return home
61
+
62
+
63
+ @pytest.fixture
64
+ def mock_skcomm() -> MagicMock:
65
+ skcomm = MagicMock()
66
+ skcomm.send.return_value = None
67
+ skcomm.receive.return_value = []
68
+ return skcomm
69
+
70
+
71
+ # ---------------------------------------------------------------------------
72
+ # TestInboxToOutboxFlow
73
+ # ---------------------------------------------------------------------------
74
+
75
+
76
+ class TestInboxToOutboxFlow:
77
+ """Drop a file in the inbox and verify the consciousness loop responds."""
78
+
79
+ def _make_loop(self, agent_home: Path, shared_root: Path, mock_skcomm):
80
+ """Return a ConsciousnessLoop with a mocked LLM bridge."""
81
+ from skcapstone.consciousness_loop import ConsciousnessConfig, ConsciousnessLoop
82
+
83
+ config = ConsciousnessConfig(
84
+ enabled=True,
85
+ use_inotify=False, # manual trigger in tests
86
+ auto_ack=False,
87
+ auto_memory=False,
88
+ desktop_notifications=False,
89
+ )
90
+
91
+ with patch("skcapstone.consciousness_loop.LLMBridge") as MockBridge:
92
+ bridge = MagicMock()
93
+ bridge.generate.return_value = "Hello back from TestAgent"
94
+ bridge.available_backends = {"passthrough": True}
95
+ MockBridge.return_value = bridge
96
+
97
+ loop = ConsciousnessLoop(
98
+ config,
99
+ home=agent_home,
100
+ shared_root=shared_root,
101
+ )
102
+
103
+ loop.set_skcomm(mock_skcomm)
104
+ return loop
105
+
106
+ def test_inbox_to_outbox_flow(
107
+ self, shared_root: Path, agent_home: Path, mock_skcomm: MagicMock
108
+ ):
109
+ """File dropped in inbox triggers process_envelope and skcomm.send."""
110
+ loop = self._make_loop(agent_home, shared_root, mock_skcomm)
111
+
112
+ peer = "alice"
113
+ inbox_peer = get_inbox_dir(shared_root) / peer
114
+ inbox_peer.mkdir(parents=True, exist_ok=True)
115
+
116
+ envelope = {
117
+ "envelope_id": "test-msg-001",
118
+ "sender": peer,
119
+ "recipient": "testagent",
120
+ "timestamp": "2026-03-01T00:00:00Z",
121
+ "payload": {
122
+ "content": "Hey TestAgent, what is happening?",
123
+ "content_type": "text",
124
+ },
125
+ }
126
+ inbox_file = inbox_peer / f"test-msg-001{ENVELOPE_SUFFIX}"
127
+ inbox_file.write_text(json.dumps(envelope), encoding="utf-8")
128
+
129
+ # Simulate inotify trigger
130
+ loop._on_inbox_file(inbox_file)
131
+ loop._executor.shutdown(wait=True)
132
+
133
+ assert mock_skcomm.send.called, "skcomm.send() must be called with the LLM response"
134
+ recipient_arg = mock_skcomm.send.call_args[0][0]
135
+ assert recipient_arg == peer, "Response must be addressed to the original sender"
136
+
137
+ def test_skipped_when_sender_missing(
138
+ self, shared_root: Path, agent_home: Path, mock_skcomm: MagicMock
139
+ ):
140
+ """Envelopes without a sender field are silently dropped."""
141
+ loop = self._make_loop(agent_home, shared_root, mock_skcomm)
142
+
143
+ inbox_peer = get_inbox_dir(shared_root) / "ghost"
144
+ inbox_peer.mkdir(parents=True, exist_ok=True)
145
+ no_sender = {"payload": {"content": "ghost message", "content_type": "text"}}
146
+ inbox_file = inbox_peer / f"no-sender{ENVELOPE_SUFFIX}"
147
+ inbox_file.write_text(json.dumps(no_sender), encoding="utf-8")
148
+
149
+ loop._on_inbox_file(inbox_file)
150
+ loop._executor.shutdown(wait=True)
151
+
152
+ mock_skcomm.send.assert_not_called()
153
+
154
+ def test_duplicate_envelope_not_reprocessed(
155
+ self, shared_root: Path, agent_home: Path, mock_skcomm: MagicMock
156
+ ):
157
+ """The same envelope_id is never processed twice."""
158
+ loop = self._make_loop(agent_home, shared_root, mock_skcomm)
159
+
160
+ peer = "bob"
161
+ inbox_peer = get_inbox_dir(shared_root) / peer
162
+ inbox_peer.mkdir(parents=True, exist_ok=True)
163
+
164
+ envelope = {
165
+ "envelope_id": "dup-001",
166
+ "sender": peer,
167
+ "recipient": "testagent",
168
+ "payload": {"content": "duplicate test", "content_type": "text"},
169
+ }
170
+ inbox_file = inbox_peer / f"dup-001{ENVELOPE_SUFFIX}"
171
+ inbox_file.write_text(json.dumps(envelope), encoding="utf-8")
172
+
173
+ # First call
174
+ loop._on_inbox_file(inbox_file)
175
+ loop._executor.shutdown(wait=True)
176
+ first_count = mock_skcomm.send.call_count
177
+
178
+ # Recreate the loop's executor for a second submission attempt
179
+ from concurrent.futures import ThreadPoolExecutor
180
+ loop._executor = ThreadPoolExecutor(max_workers=1, thread_name_prefix="consciousness")
181
+
182
+ # Second call with the same file (same envelope_id)
183
+ loop._on_inbox_file(inbox_file)
184
+ loop._executor.shutdown(wait=True)
185
+
186
+ # Exactly the same number of sends — second call was deduped
187
+ assert mock_skcomm.send.call_count == first_count
188
+
189
+
190
+ # ---------------------------------------------------------------------------
191
+ # TestOutboxEnvelopeFormat
192
+ # ---------------------------------------------------------------------------
193
+
194
+
195
+ class TestOutboxEnvelopeFormat:
196
+ """Verify that outbox envelopes comply with the SKComm envelope spec."""
197
+
198
+ def test_required_fields_preserved(self, shared_root: Path):
199
+ """write_outbox_envelope writes all envelope fields to the .skc.json."""
200
+ envelope = {
201
+ "envelope_id": "out-001",
202
+ "sender": "opus",
203
+ "recipient": "alice",
204
+ "timestamp": "2026-03-01T00:00:00Z",
205
+ "payload": {
206
+ "content": "Response from Opus",
207
+ "content_type": "text",
208
+ },
209
+ }
210
+ written = write_outbox_envelope(shared_root, "alice", envelope)
211
+
212
+ assert written.exists()
213
+ data = json.loads(written.read_text(encoding="utf-8"))
214
+ assert data["envelope_id"] == "out-001"
215
+ assert data["sender"] == "opus"
216
+ assert data["recipient"] == "alice"
217
+ assert data["payload"]["content"] == "Response from Opus"
218
+ assert data["payload"]["content_type"] == "text"
219
+
220
+ def test_file_placed_in_outbox_subdirectory(self, shared_root: Path):
221
+ """Envelope file lives under outbox/{recipient}/."""
222
+ envelope = {"envelope_id": "dir-test", "payload": {"content": "hi", "content_type": "text"}}
223
+ written = write_outbox_envelope(shared_root, "bob", envelope)
224
+
225
+ expected_parent = get_outbox_dir(shared_root) / "bob"
226
+ assert written.parent == expected_parent
227
+
228
+ def test_file_has_skc_json_suffix(self, shared_root: Path):
229
+ """Written file ends with .skc.json."""
230
+ envelope = {"envelope_id": "suffix-test", "payload": {"content": "x", "content_type": "text"}}
231
+ written = write_outbox_envelope(shared_root, "carol", envelope)
232
+ assert written.name.endswith(ENVELOPE_SUFFIX)
233
+
234
+ def test_atomic_write_leaves_no_tmp_files(self, shared_root: Path):
235
+ """No .tmp files remain after write_outbox_envelope."""
236
+ envelope = {
237
+ "envelope_id": "atomic-001",
238
+ "payload": {"content": "atomic test", "content_type": "text"},
239
+ }
240
+ written = write_outbox_envelope(shared_root, "dave", envelope)
241
+ tmp_files = list(written.parent.glob("*.tmp"))
242
+ assert tmp_files == []
243
+
244
+ def test_path_traversal_in_recipient_neutralized(self, shared_root: Path):
245
+ """Path-traversal characters in recipient are stripped."""
246
+ envelope = {
247
+ "envelope_id": "safe-001",
248
+ "payload": {"content": "test", "content_type": "text"},
249
+ }
250
+ written = write_outbox_envelope(shared_root, "../../../etc/passwd", envelope)
251
+ # Must stay inside shared_root
252
+ assert shared_root in written.parents
253
+
254
+ def test_outbox_pipeline_status_reflects_written_file(self, shared_root: Path):
255
+ """get_sync_pipeline_status counts the newly written outbox file."""
256
+ envelope = {
257
+ "envelope_id": "count-001",
258
+ "payload": {"content": "counting", "content_type": "text"},
259
+ }
260
+ write_outbox_envelope(shared_root, "eve", envelope)
261
+ status = get_sync_pipeline_status(shared_root)
262
+ assert status["outbox_files"] >= 1
263
+ assert "eve" in status["outbox_peers"]
264
+
265
+
266
+ # ---------------------------------------------------------------------------
267
+ # TestSyncStatusInHealth
268
+ # ---------------------------------------------------------------------------
269
+
270
+
271
+ class TestSyncStatusInHealth:
272
+ """Verify that the daemon health snapshot includes sync pipeline status."""
273
+
274
+ def test_get_sync_pipeline_status_keys(self, shared_root: Path):
275
+ """get_sync_pipeline_status returns all required keys."""
276
+ status = get_sync_pipeline_status(shared_root)
277
+ required = {
278
+ "inbox_files",
279
+ "outbox_files",
280
+ "inbox_peers",
281
+ "outbox_peers",
282
+ "inbox_path",
283
+ "outbox_path",
284
+ "inbox_exists",
285
+ "outbox_exists",
286
+ "checked_at",
287
+ }
288
+ assert required.issubset(status.keys())
289
+
290
+ def test_get_sync_pipeline_status_counts_inbox_file(self, shared_root: Path):
291
+ """Status correctly counts a file dropped in the inbox."""
292
+ peer = "frank"
293
+ inbox_dir = get_inbox_dir(shared_root) / peer
294
+ inbox_dir.mkdir(parents=True, exist_ok=True)
295
+ (inbox_dir / f"msg-001{ENVELOPE_SUFFIX}").write_text(
296
+ json.dumps({"payload": {"content": "hi"}}), encoding="utf-8"
297
+ )
298
+
299
+ status = get_sync_pipeline_status(shared_root)
300
+ assert status["inbox_files"] >= 1
301
+ assert peer in status["inbox_peers"]
302
+
303
+ def test_verify_pipeline_paths_ok_when_dirs_exist(self, shared_root: Path):
304
+ """verify_pipeline_paths reports no issues when dirs are present."""
305
+ result = verify_pipeline_paths(shared_root)
306
+ assert result["inbox_ok"] is True
307
+ assert result["outbox_ok"] is True
308
+ assert result["issues"] == []
309
+
310
+ def test_verify_pipeline_paths_reports_missing_inbox(self, tmp_path: Path):
311
+ """verify_pipeline_paths reports missing inbox dir."""
312
+ empty_root = tmp_path / "empty"
313
+ empty_root.mkdir()
314
+ result = verify_pipeline_paths(empty_root)
315
+ assert result["inbox_ok"] is False
316
+ assert any("Inbox" in issue for issue in result["issues"])
317
+
318
+ def test_verify_pipeline_paths_reports_missing_outbox(self, tmp_path: Path):
319
+ """verify_pipeline_paths reports missing outbox dir."""
320
+ root = tmp_path / "partial"
321
+ root.mkdir()
322
+ # create only inbox
323
+ (root / "sync" / "comms" / "inbox").mkdir(parents=True)
324
+ result = verify_pipeline_paths(root)
325
+ assert result["outbox_ok"] is False
326
+ assert any("Outbox" in issue for issue in result["issues"])
327
+
328
+ def test_daemon_state_snapshot_includes_sync_pipeline(self):
329
+ """DaemonState.snapshot() includes sync_pipeline after record_sync_pipeline."""
330
+ from skcapstone.daemon import DaemonState
331
+
332
+ state = DaemonState()
333
+ state.record_sync_pipeline({"inbox_files": 3, "outbox_files": 1})
334
+ snap = state.snapshot()
335
+
336
+ assert "sync_pipeline" in snap
337
+ assert snap["sync_pipeline"]["inbox_files"] == 3
338
+ assert snap["sync_pipeline"]["outbox_files"] == 1
339
+
340
+ def test_daemon_state_sync_pipeline_starts_empty(self):
341
+ """DaemonState starts with an empty sync_pipeline dict."""
342
+ from skcapstone.daemon import DaemonState
343
+
344
+ state = DaemonState()
345
+ snap = state.snapshot()
346
+ assert "sync_pipeline" in snap
347
+ assert snap["sync_pipeline"] == {}
348
+
349
+ def test_verify_pipeline_detects_transport_misalignment(self, shared_root: Path):
350
+ """verify_pipeline_paths flags a SyncthingTransport with a wrong comms_root."""
351
+ # Build a mock SKComm with a Syncthing transport pointing to the wrong path
352
+ wrong_transport = MagicMock()
353
+ wrong_transport.name = "syncthing"
354
+ wrong_transport._root = Path("/tmp/wrong/path")
355
+
356
+ mock_router = MagicMock()
357
+ mock_router.transports = [wrong_transport]
358
+
359
+ mock_skcomm = MagicMock()
360
+ mock_skcomm.router = mock_router
361
+
362
+ result = verify_pipeline_paths(shared_root, skcomm=mock_skcomm)
363
+ assert result["transport_aligned"] is False
364
+ assert any("mismatch" in issue.lower() for issue in result["issues"])