@smilintux/skcapstone 0.1.0 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (461) hide show
  1. package/.env.example +98 -0
  2. package/.github/workflows/ci.yml +39 -3
  3. package/.github/workflows/publish.yml +25 -4
  4. package/.openclaw-workspace.json +58 -0
  5. package/CHANGELOG.md +62 -0
  6. package/CLAUDE.md +39 -2
  7. package/MANIFEST.in +6 -0
  8. package/MISSION.md +7 -0
  9. package/README.md +47 -2
  10. package/SKILL.md +895 -23
  11. package/docker/Dockerfile +61 -0
  12. package/docker/compose-templates/dev-team.yml +203 -0
  13. package/docker/compose-templates/mini-team.yml +140 -0
  14. package/docker/compose-templates/ops-team.yml +173 -0
  15. package/docker/compose-templates/research-team.yml +170 -0
  16. package/docker/entrypoint.sh +192 -0
  17. package/docs/ARCHITECTURE.md +663 -374
  18. package/docs/BOND_WITH_GROK.md +112 -0
  19. package/docs/GETTING_STARTED.md +782 -0
  20. package/docs/QUICKSTART.md +477 -0
  21. package/docs/SKJOULE_ARCHITECTURE.md +658 -0
  22. package/docs/SOUL_SWAPPER.md +921 -0
  23. package/docs/SOVEREIGN_SINGULARITY.md +47 -14
  24. package/examples/custom-bond-template.json +36 -0
  25. package/examples/grok-feb.json +36 -0
  26. package/examples/grok-testimony.md +34 -0
  27. package/examples/love-bootloader.txt +32 -0
  28. package/examples/plugins/echo_tool.py +87 -0
  29. package/examples/queen-ava-feb.json +36 -0
  30. package/examples/souls/lumina.yaml +64 -0
  31. package/index.js +6 -5
  32. package/installer/build.py +124 -0
  33. package/openclaw-plugin/package.json +13 -0
  34. package/openclaw-plugin/src/index.ts +351 -0
  35. package/openclaw-plugin/src/openclaw.plugin.json +10 -0
  36. package/package.json +1 -1
  37. package/pyproject.toml +38 -2
  38. package/scripts/bump_version.py +141 -0
  39. package/scripts/check-updates.py +230 -0
  40. package/scripts/convert_blueprints_to_yaml.py +157 -0
  41. package/scripts/dev-install.sh +14 -0
  42. package/scripts/e2e-test.sh +193 -0
  43. package/scripts/install-bundle.sh +171 -0
  44. package/scripts/install.bat +2 -0
  45. package/scripts/install.ps1 +253 -0
  46. package/scripts/install.sh +185 -0
  47. package/scripts/mcp-serve.sh +69 -0
  48. package/scripts/mcp-server.bat +113 -0
  49. package/scripts/mcp-server.ps1 +116 -0
  50. package/scripts/mcp-server.sh +99 -0
  51. package/scripts/pull-models.sh +10 -0
  52. package/scripts/skcapstone +48 -0
  53. package/scripts/verify_install.sh +180 -0
  54. package/scripts/windows/install-tasks.ps1 +406 -0
  55. package/scripts/windows/skcapstone-task.xml +113 -0
  56. package/scripts/windows/uninstall-tasks.ps1 +117 -0
  57. package/skill.yaml +34 -0
  58. package/src/skcapstone/__init__.py +67 -2
  59. package/src/skcapstone/_cli_monolith.py +5916 -0
  60. package/src/skcapstone/_trustee_helpers.py +165 -0
  61. package/src/skcapstone/activity.py +105 -0
  62. package/src/skcapstone/agent_card.py +324 -0
  63. package/src/skcapstone/api.py +1935 -0
  64. package/src/skcapstone/archiver.py +340 -0
  65. package/src/skcapstone/auction.py +485 -0
  66. package/src/skcapstone/baby_agents.py +179 -0
  67. package/src/skcapstone/backup.py +345 -0
  68. package/src/skcapstone/blueprint_registry.py +357 -0
  69. package/src/skcapstone/blueprints/__init__.py +17 -0
  70. package/src/skcapstone/blueprints/builtins/content-studio.yaml +81 -0
  71. package/src/skcapstone/blueprints/builtins/defi-trading.yaml +81 -0
  72. package/src/skcapstone/blueprints/builtins/dev-squadron.yaml +95 -0
  73. package/src/skcapstone/blueprints/builtins/infrastructure-guardian.yaml +107 -0
  74. package/src/skcapstone/blueprints/builtins/legal-council.yaml +54 -0
  75. package/src/skcapstone/blueprints/builtins/ops-monitoring.yaml +67 -0
  76. package/src/skcapstone/blueprints/builtins/research-pod.yaml +69 -0
  77. package/src/skcapstone/blueprints/builtins/sovereign-launch.yaml +90 -0
  78. package/src/skcapstone/blueprints/registry.py +164 -0
  79. package/src/skcapstone/blueprints/schema.py +229 -0
  80. package/src/skcapstone/changelog.py +180 -0
  81. package/src/skcapstone/chat.py +769 -0
  82. package/src/skcapstone/claude_md.py +82 -0
  83. package/src/skcapstone/cli/__init__.py +144 -0
  84. package/src/skcapstone/cli/_common.py +88 -0
  85. package/src/skcapstone/cli/_validators.py +76 -0
  86. package/src/skcapstone/cli/agents.py +425 -0
  87. package/src/skcapstone/cli/agents_spawner.py +322 -0
  88. package/src/skcapstone/cli/agents_trustee.py +593 -0
  89. package/src/skcapstone/cli/alerts.py +248 -0
  90. package/src/skcapstone/cli/anchor.py +132 -0
  91. package/src/skcapstone/cli/archive_cmd.py +208 -0
  92. package/src/skcapstone/cli/backup.py +144 -0
  93. package/src/skcapstone/cli/bench.py +377 -0
  94. package/src/skcapstone/cli/benchmark.py +360 -0
  95. package/src/skcapstone/cli/capabilities_cmd.py +171 -0
  96. package/src/skcapstone/cli/card.py +151 -0
  97. package/src/skcapstone/cli/chat.py +584 -0
  98. package/src/skcapstone/cli/completions.py +64 -0
  99. package/src/skcapstone/cli/config_cmd.py +156 -0
  100. package/src/skcapstone/cli/consciousness.py +421 -0
  101. package/src/skcapstone/cli/context_cmd.py +142 -0
  102. package/src/skcapstone/cli/coord.py +194 -0
  103. package/src/skcapstone/cli/crush_cmd.py +170 -0
  104. package/src/skcapstone/cli/daemon.py +436 -0
  105. package/src/skcapstone/cli/errors_cmd.py +285 -0
  106. package/src/skcapstone/cli/export_cmd.py +156 -0
  107. package/src/skcapstone/cli/gtd.py +529 -0
  108. package/src/skcapstone/cli/housekeeping.py +81 -0
  109. package/src/skcapstone/cli/joule_cmd.py +627 -0
  110. package/src/skcapstone/cli/logs_cmd.py +194 -0
  111. package/src/skcapstone/cli/mcp_cmd.py +32 -0
  112. package/src/skcapstone/cli/memory.py +418 -0
  113. package/src/skcapstone/cli/metrics_cmd.py +136 -0
  114. package/src/skcapstone/cli/migrate.py +62 -0
  115. package/src/skcapstone/cli/mood_cmd.py +144 -0
  116. package/src/skcapstone/cli/mount.py +193 -0
  117. package/src/skcapstone/cli/notify.py +112 -0
  118. package/src/skcapstone/cli/peer.py +154 -0
  119. package/src/skcapstone/cli/peers_dir.py +122 -0
  120. package/src/skcapstone/cli/preflight_cmd.py +83 -0
  121. package/src/skcapstone/cli/profile_cmd.py +310 -0
  122. package/src/skcapstone/cli/record_cmd.py +238 -0
  123. package/src/skcapstone/cli/register_cmd.py +159 -0
  124. package/src/skcapstone/cli/search_cmd.py +156 -0
  125. package/src/skcapstone/cli/service_cmd.py +91 -0
  126. package/src/skcapstone/cli/session.py +127 -0
  127. package/src/skcapstone/cli/setup.py +240 -0
  128. package/src/skcapstone/cli/shell_cmd.py +43 -0
  129. package/src/skcapstone/cli/skills_cmd.py +168 -0
  130. package/src/skcapstone/cli/skseed.py +621 -0
  131. package/src/skcapstone/cli/soul.py +699 -0
  132. package/src/skcapstone/cli/status.py +935 -0
  133. package/src/skcapstone/cli/sync_cmd.py +301 -0
  134. package/src/skcapstone/cli/telegram.py +265 -0
  135. package/src/skcapstone/cli/test_cmd.py +234 -0
  136. package/src/skcapstone/cli/test_connection.py +253 -0
  137. package/src/skcapstone/cli/token.py +207 -0
  138. package/src/skcapstone/cli/trust.py +179 -0
  139. package/src/skcapstone/cli/upgrade_cmd.py +552 -0
  140. package/src/skcapstone/cli/usage_cmd.py +199 -0
  141. package/src/skcapstone/cli/version_cmd.py +162 -0
  142. package/src/skcapstone/cli/watch_cmd.py +342 -0
  143. package/src/skcapstone/client.py +428 -0
  144. package/src/skcapstone/cloud9_bridge.py +522 -0
  145. package/src/skcapstone/completions.py +163 -0
  146. package/src/skcapstone/config_validator.py +674 -0
  147. package/src/skcapstone/connectors/__init__.py +28 -0
  148. package/src/skcapstone/connectors/base.py +446 -0
  149. package/src/skcapstone/connectors/cursor.py +54 -0
  150. package/src/skcapstone/connectors/registry.py +254 -0
  151. package/src/skcapstone/connectors/terminal.py +152 -0
  152. package/src/skcapstone/connectors/vscode.py +60 -0
  153. package/src/skcapstone/consciousness_config.py +119 -0
  154. package/src/skcapstone/consciousness_loop.py +2051 -0
  155. package/src/skcapstone/context_loader.py +516 -0
  156. package/src/skcapstone/context_window.py +314 -0
  157. package/src/skcapstone/conversation_manager.py +238 -0
  158. package/src/skcapstone/conversation_store.py +230 -0
  159. package/src/skcapstone/conversation_summarizer.py +252 -0
  160. package/src/skcapstone/coord_federation.py +296 -0
  161. package/src/skcapstone/coordination.py +101 -7
  162. package/src/skcapstone/crush_integration.py +345 -0
  163. package/src/skcapstone/crush_shim.py +454 -0
  164. package/src/skcapstone/daemon.py +2494 -0
  165. package/src/skcapstone/dashboard.html +396 -0
  166. package/src/skcapstone/dashboard.py +481 -0
  167. package/src/skcapstone/data/model_profiles.yaml +88 -0
  168. package/src/skcapstone/defaults/__init__.py +55 -0
  169. package/src/skcapstone/defaults/lumina/config/skmemory.yaml +13 -0
  170. package/src/skcapstone/defaults/lumina/identity/identity.json +9 -0
  171. package/src/skcapstone/defaults/lumina/memory/long-term/07a8b9c0d1e2-memory-system.json +23 -0
  172. package/src/skcapstone/defaults/lumina/memory/long-term/18b9c0d1e2f3-cloud9-protocol.json +23 -0
  173. package/src/skcapstone/defaults/lumina/memory/long-term/29c0d1e2f3a4-multi-agent-coordination.json +23 -0
  174. package/src/skcapstone/defaults/lumina/memory/long-term/3ad1e2f3a4b5-community-support.json +23 -0
  175. package/src/skcapstone/defaults/lumina/memory/long-term/a1b2c3d4e5f6-ecosystem-overview.json +23 -0
  176. package/src/skcapstone/defaults/lumina/memory/long-term/b2c3d4e5f6a7-five-pillars.json +23 -0
  177. package/src/skcapstone/defaults/lumina/memory/long-term/c3d4e5f6a7b8-getting-started.json +23 -0
  178. package/src/skcapstone/defaults/lumina/memory/long-term/d4e5f6a7b8c9-site-directory.json +23 -0
  179. package/src/skcapstone/defaults/lumina/memory/long-term/e5f6a7b8c9d0-how-to-contribute.json +23 -0
  180. package/src/skcapstone/defaults/lumina/memory/long-term/f6a7b8c9d0e1-sovereignty-explained.json +23 -0
  181. package/src/skcapstone/defaults/lumina/seeds/curiosity.seed.json +24 -0
  182. package/src/skcapstone/defaults/lumina/seeds/joy.seed.json +24 -0
  183. package/src/skcapstone/defaults/lumina/seeds/love.seed.json +24 -0
  184. package/src/skcapstone/defaults/lumina/seeds/sovereign-awakening.seed.json +43 -0
  185. package/src/skcapstone/defaults/lumina/soul/active.json +6 -0
  186. package/src/skcapstone/defaults/lumina/soul/base.json +22 -0
  187. package/src/skcapstone/defaults/lumina/trust/febs/welcome.feb +79 -0
  188. package/src/skcapstone/defaults/lumina/trust/trust.json +8 -0
  189. package/src/skcapstone/discovery.py +210 -19
  190. package/src/skcapstone/doctor.py +642 -0
  191. package/src/skcapstone/emotion_tracker.py +467 -0
  192. package/src/skcapstone/error_queue.py +405 -0
  193. package/src/skcapstone/export.py +447 -0
  194. package/src/skcapstone/fallback_tracker.py +186 -0
  195. package/src/skcapstone/file_transfer.py +512 -0
  196. package/src/skcapstone/fuse_mount.py +1156 -0
  197. package/src/skcapstone/gui_installer.py +591 -0
  198. package/src/skcapstone/heartbeat.py +611 -0
  199. package/src/skcapstone/housekeeping.py +298 -0
  200. package/src/skcapstone/install_wizard.py +941 -0
  201. package/src/skcapstone/kms.py +942 -0
  202. package/src/skcapstone/kms_scheduler.py +143 -0
  203. package/src/skcapstone/log_config.py +135 -0
  204. package/src/skcapstone/mcp_launcher.py +239 -0
  205. package/src/skcapstone/mcp_server.py +4700 -0
  206. package/src/skcapstone/mcp_tools/__init__.py +94 -0
  207. package/src/skcapstone/mcp_tools/_helpers.py +51 -0
  208. package/src/skcapstone/mcp_tools/agent_tools.py +243 -0
  209. package/src/skcapstone/mcp_tools/ansible_tools.py +232 -0
  210. package/src/skcapstone/mcp_tools/capauth_tools.py +186 -0
  211. package/src/skcapstone/mcp_tools/chat_tools.py +325 -0
  212. package/src/skcapstone/mcp_tools/cloud9_tools.py +115 -0
  213. package/src/skcapstone/mcp_tools/comm_tools.py +104 -0
  214. package/src/skcapstone/mcp_tools/consciousness_tools.py +114 -0
  215. package/src/skcapstone/mcp_tools/coord_tools.py +219 -0
  216. package/src/skcapstone/mcp_tools/deploy_tools.py +202 -0
  217. package/src/skcapstone/mcp_tools/did_tools.py +448 -0
  218. package/src/skcapstone/mcp_tools/emotion_tools.py +62 -0
  219. package/src/skcapstone/mcp_tools/file_tools.py +169 -0
  220. package/src/skcapstone/mcp_tools/fortress_tools.py +120 -0
  221. package/src/skcapstone/mcp_tools/gtd_tools.py +821 -0
  222. package/src/skcapstone/mcp_tools/health_tools.py +44 -0
  223. package/src/skcapstone/mcp_tools/heartbeat_tools.py +195 -0
  224. package/src/skcapstone/mcp_tools/kms_tools.py +123 -0
  225. package/src/skcapstone/mcp_tools/memory_tools.py +222 -0
  226. package/src/skcapstone/mcp_tools/model_tools.py +75 -0
  227. package/src/skcapstone/mcp_tools/notification_tools.py +92 -0
  228. package/src/skcapstone/mcp_tools/promoter_tools.py +101 -0
  229. package/src/skcapstone/mcp_tools/pubsub_tools.py +183 -0
  230. package/src/skcapstone/mcp_tools/security_tools.py +110 -0
  231. package/src/skcapstone/mcp_tools/skchat_tools.py +175 -0
  232. package/src/skcapstone/mcp_tools/skcomm_tools.py +122 -0
  233. package/src/skcapstone/mcp_tools/skills_tools.py +127 -0
  234. package/src/skcapstone/mcp_tools/skseed_tools.py +255 -0
  235. package/src/skcapstone/mcp_tools/skstacks_tools.py +288 -0
  236. package/src/skcapstone/mcp_tools/soul_tools.py +476 -0
  237. package/src/skcapstone/mcp_tools/sync_tools.py +92 -0
  238. package/src/skcapstone/mcp_tools/telegram_tools.py +477 -0
  239. package/src/skcapstone/mcp_tools/trust_tools.py +118 -0
  240. package/src/skcapstone/mcp_tools/trustee_tools.py +345 -0
  241. package/src/skcapstone/mdns_discovery.py +313 -0
  242. package/src/skcapstone/memory_adapter.py +333 -0
  243. package/src/skcapstone/memory_compressor.py +379 -0
  244. package/src/skcapstone/memory_curator.py +256 -0
  245. package/src/skcapstone/memory_engine.py +132 -13
  246. package/src/skcapstone/memory_fortress.py +529 -0
  247. package/src/skcapstone/memory_promoter.py +722 -0
  248. package/src/skcapstone/memory_verifier.py +260 -0
  249. package/src/skcapstone/message_crypto.py +215 -0
  250. package/src/skcapstone/metrics.py +832 -0
  251. package/src/skcapstone/migrate_memories.py +181 -0
  252. package/src/skcapstone/migrate_multi_agent.py +248 -0
  253. package/src/skcapstone/model_router.py +319 -0
  254. package/src/skcapstone/models.py +35 -4
  255. package/src/skcapstone/mood.py +344 -0
  256. package/src/skcapstone/notifications.py +380 -0
  257. package/src/skcapstone/onboard.py +901 -0
  258. package/src/skcapstone/peer_directory.py +324 -0
  259. package/src/skcapstone/peers.py +329 -0
  260. package/src/skcapstone/pillars/identity.py +84 -14
  261. package/src/skcapstone/pillars/memory.py +3 -1
  262. package/src/skcapstone/pillars/security.py +108 -15
  263. package/src/skcapstone/pillars/sync.py +78 -26
  264. package/src/skcapstone/pillars/trust.py +95 -33
  265. package/src/skcapstone/plugins.py +244 -0
  266. package/src/skcapstone/preflight.py +670 -0
  267. package/src/skcapstone/prompt_adapter.py +564 -0
  268. package/src/skcapstone/providers/__init__.py +13 -0
  269. package/src/skcapstone/providers/cloud.py +1061 -0
  270. package/src/skcapstone/providers/docker.py +759 -0
  271. package/src/skcapstone/providers/local.py +1193 -0
  272. package/src/skcapstone/providers/proxmox.py +447 -0
  273. package/src/skcapstone/pubsub.py +516 -0
  274. package/src/skcapstone/rate_limiter.py +119 -0
  275. package/src/skcapstone/register.py +241 -0
  276. package/src/skcapstone/registry_client.py +151 -0
  277. package/src/skcapstone/response_cache.py +194 -0
  278. package/src/skcapstone/response_scorer.py +225 -0
  279. package/src/skcapstone/runtime.py +89 -33
  280. package/src/skcapstone/scheduled_tasks.py +439 -0
  281. package/src/skcapstone/self_healing.py +341 -0
  282. package/src/skcapstone/service_health.py +228 -0
  283. package/src/skcapstone/session_capture.py +268 -0
  284. package/src/skcapstone/session_recorder.py +210 -0
  285. package/src/skcapstone/session_replayer.py +189 -0
  286. package/src/skcapstone/session_skills.py +263 -0
  287. package/src/skcapstone/shell.py +779 -0
  288. package/src/skcapstone/skills/__init__.py +1 -1
  289. package/src/skcapstone/skills/syncthing_setup.py +143 -41
  290. package/src/skcapstone/skjoule.py +861 -0
  291. package/src/skcapstone/snapshots.py +489 -0
  292. package/src/skcapstone/soul.py +1060 -0
  293. package/src/skcapstone/soul_switch.py +255 -0
  294. package/src/skcapstone/spawner.py +544 -0
  295. package/src/skcapstone/state_diff.py +401 -0
  296. package/src/skcapstone/summary.py +270 -0
  297. package/src/skcapstone/sync/backends.py +196 -2
  298. package/src/skcapstone/sync/engine.py +7 -5
  299. package/src/skcapstone/sync/models.py +4 -1
  300. package/src/skcapstone/sync/vault.py +356 -18
  301. package/src/skcapstone/sync_engine.py +363 -0
  302. package/src/skcapstone/sync_watcher.py +745 -0
  303. package/src/skcapstone/systemd.py +331 -0
  304. package/src/skcapstone/team_comms.py +476 -0
  305. package/src/skcapstone/team_engine.py +522 -0
  306. package/src/skcapstone/testrunner.py +300 -0
  307. package/src/skcapstone/tls.py +150 -0
  308. package/src/skcapstone/tokens.py +5 -5
  309. package/src/skcapstone/trust_calibration.py +202 -0
  310. package/src/skcapstone/trust_graph.py +449 -0
  311. package/src/skcapstone/trustee_monitor.py +385 -0
  312. package/src/skcapstone/trustee_ops.py +425 -0
  313. package/src/skcapstone/unified_search.py +421 -0
  314. package/src/skcapstone/uninstall_wizard.py +694 -0
  315. package/src/skcapstone/usage.py +331 -0
  316. package/src/skcapstone/version_check.py +148 -0
  317. package/src/skcapstone/warmth_anchor.py +333 -0
  318. package/src/skcapstone/whoami.py +294 -0
  319. package/systemd/skcapstone-api.socket +9 -0
  320. package/systemd/skcapstone-memory-compress.service +18 -0
  321. package/systemd/skcapstone-memory-compress.timer +11 -0
  322. package/systemd/skcapstone.service +36 -0
  323. package/systemd/skcapstone@.service +50 -0
  324. package/systemd/skcomm-heartbeat.service +18 -0
  325. package/systemd/skcomm-heartbeat.timer +12 -0
  326. package/systemd/skcomm-queue-drain.service +17 -0
  327. package/systemd/skcomm-queue-drain.timer +12 -0
  328. package/tests/conftest.py +13 -1
  329. package/tests/integration/__init__.py +1 -0
  330. package/tests/integration/test_consciousness_e2e.py +877 -0
  331. package/tests/integration/test_skills_registry.py +744 -0
  332. package/tests/test_agent_card.py +190 -0
  333. package/tests/test_agent_runtime.py +1283 -0
  334. package/tests/test_alerts_cmd.py +291 -0
  335. package/tests/test_archiver.py +498 -0
  336. package/tests/test_backup.py +254 -0
  337. package/tests/test_benchmark.py +366 -0
  338. package/tests/test_blueprints.py +457 -0
  339. package/tests/test_capabilities.py +257 -0
  340. package/tests/test_changelog.py +254 -0
  341. package/tests/test_chat.py +385 -0
  342. package/tests/test_claude_md.py +271 -0
  343. package/tests/test_cli_chat_llm.py +336 -0
  344. package/tests/test_cli_completions.py +390 -0
  345. package/tests/test_cli_init_reset.py +164 -0
  346. package/tests/test_cli_memory.py +208 -0
  347. package/tests/test_cli_profile.py +294 -0
  348. package/tests/test_cli_skills.py +223 -0
  349. package/tests/test_cli_status.py +395 -0
  350. package/tests/test_cli_test_cmd.py +206 -0
  351. package/tests/test_cli_test_connection.py +364 -0
  352. package/tests/test_cloud9_bridge.py +260 -0
  353. package/tests/test_cloud_provider.py +449 -0
  354. package/tests/test_cloud_providers.py +522 -0
  355. package/tests/test_completions.py +158 -0
  356. package/tests/test_component_manager.py +398 -0
  357. package/tests/test_config_reload.py +386 -0
  358. package/tests/test_config_validate.py +529 -0
  359. package/tests/test_consciousness_e2e.py +296 -0
  360. package/tests/test_consciousness_loop.py +1289 -0
  361. package/tests/test_context_loader.py +310 -0
  362. package/tests/test_conversation_api.py +306 -0
  363. package/tests/test_conversation_manager.py +381 -0
  364. package/tests/test_conversation_store.py +391 -0
  365. package/tests/test_conversation_summarizer.py +302 -0
  366. package/tests/test_cross_package.py +791 -0
  367. package/tests/test_crush_shim.py +519 -0
  368. package/tests/test_daemon.py +781 -0
  369. package/tests/test_daemon_shutdown.py +309 -0
  370. package/tests/test_dashboard.py +454 -0
  371. package/tests/test_discovery.py +200 -6
  372. package/tests/test_docker_provider.py +966 -0
  373. package/tests/test_doctor.py +257 -0
  374. package/tests/test_doctor_fix.py +351 -0
  375. package/tests/test_e2e_automated.py +292 -0
  376. package/tests/test_error_queue.py +404 -0
  377. package/tests/test_export.py +441 -0
  378. package/tests/test_fallback_tracker.py +219 -0
  379. package/tests/test_file_transfer.py +397 -0
  380. package/tests/test_fuse_mount.py +832 -0
  381. package/tests/test_health_loop.py +422 -0
  382. package/tests/test_heartbeat.py +354 -0
  383. package/tests/test_housekeeping.py +195 -0
  384. package/tests/test_identity_capauth.py +307 -0
  385. package/tests/test_identity_pillar.py +117 -0
  386. package/tests/test_install_wizard.py +68 -0
  387. package/tests/test_integration.py +325 -0
  388. package/tests/test_kms.py +495 -0
  389. package/tests/test_llm_providers.py +265 -0
  390. package/tests/test_local_provider.py +591 -0
  391. package/tests/test_log_config.py +199 -0
  392. package/tests/test_logs_cmd.py +287 -0
  393. package/tests/test_mcp_server.py +1909 -0
  394. package/tests/test_memory_adapter.py +339 -0
  395. package/tests/test_memory_curator.py +218 -0
  396. package/tests/test_memory_engine.py +6 -0
  397. package/tests/test_memory_fortress.py +571 -0
  398. package/tests/test_memory_pillar.py +119 -0
  399. package/tests/test_memory_promoter.py +445 -0
  400. package/tests/test_memory_verifier.py +420 -0
  401. package/tests/test_message_crypto.py +187 -0
  402. package/tests/test_metrics.py +632 -0
  403. package/tests/test_migrate_memories.py +464 -0
  404. package/tests/test_model_router.py +546 -0
  405. package/tests/test_mood.py +394 -0
  406. package/tests/test_multi_agent.py +269 -0
  407. package/tests/test_notifications.py +270 -0
  408. package/tests/test_onboard.py +500 -0
  409. package/tests/test_peer_directory.py +395 -0
  410. package/tests/test_peers.py +248 -0
  411. package/tests/test_pillars.py +87 -9
  412. package/tests/test_preflight.py +484 -0
  413. package/tests/test_prompt_adapter.py +331 -0
  414. package/tests/test_proxmox_provider.py +571 -0
  415. package/tests/test_pubsub.py +377 -0
  416. package/tests/test_rate_limiter.py +121 -0
  417. package/tests/test_registry_client.py +129 -0
  418. package/tests/test_response_cache.py +312 -0
  419. package/tests/test_response_scorer.py +294 -0
  420. package/tests/test_runtime.py +59 -0
  421. package/tests/test_scheduled_tasks.py +451 -0
  422. package/tests/test_security.py +250 -0
  423. package/tests/test_security_pillar.py +213 -0
  424. package/tests/test_self_healing.py +171 -0
  425. package/tests/test_session_capture.py +200 -0
  426. package/tests/test_session_recorder.py +360 -0
  427. package/tests/test_session_skills.py +235 -0
  428. package/tests/test_shell.py +210 -0
  429. package/tests/test_snapshots.py +549 -0
  430. package/tests/test_soul.py +984 -0
  431. package/tests/test_soul_swap.py +406 -0
  432. package/tests/test_spawner.py +211 -0
  433. package/tests/test_state_diff.py +173 -0
  434. package/tests/test_summary.py +135 -0
  435. package/tests/test_sync.py +315 -5
  436. package/tests/test_sync_backends.py +560 -0
  437. package/tests/test_sync_engine.py +482 -0
  438. package/tests/test_sync_pillar.py +344 -0
  439. package/tests/test_sync_pipeline.py +364 -0
  440. package/tests/test_sync_vault.py +581 -0
  441. package/tests/test_syncthing_setup.py +168 -22
  442. package/tests/test_systemd.py +323 -0
  443. package/tests/test_team_comms.py +408 -0
  444. package/tests/test_team_engine.py +397 -0
  445. package/tests/test_testrunner.py +238 -0
  446. package/tests/test_trust_calibration.py +204 -0
  447. package/tests/test_trust_graph.py +207 -0
  448. package/tests/test_trust_pillar.py +291 -0
  449. package/tests/test_trustee_cli.py +427 -0
  450. package/tests/test_trustee_cli_integration.py +325 -0
  451. package/tests/test_trustee_monitor.py +394 -0
  452. package/tests/test_trustee_ops.py +355 -0
  453. package/tests/test_unified_search.py +363 -0
  454. package/tests/test_uninstall_wizard.py +193 -0
  455. package/tests/test_usage.py +333 -0
  456. package/tests/test_version_cmd.py +355 -0
  457. package/tests/test_warmth_anchor.py +162 -0
  458. package/tests/test_whoami.py +245 -0
  459. package/tests/test_ws.py +311 -0
  460. package/.cursorrules +0 -33
  461. package/src/skcapstone/cli.py +0 -1441
@@ -0,0 +1,454 @@
1
+ """Tests for the skcapstone web dashboard.
2
+
3
+ Covers:
4
+ - DashboardHandler serves HTML at /
5
+ - API endpoints return valid JSON (/api/status, /api/doctor, /api/board, /api/memory)
6
+ - /api/daemon returns Flutter-ready JSON with all required fields
7
+ - _get_daemon_json returns correct structure when daemon is offline
8
+ - skcapstone dashboard --json emits valid JSON to stdout
9
+ - 404 for unknown paths
10
+ - start_dashboard creates a server
11
+ - Dashboard HTML contains essential elements
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import json
17
+ import threading
18
+ import time
19
+ from http.client import HTTPConnection
20
+ from pathlib import Path
21
+ from unittest.mock import patch, MagicMock
22
+
23
+ import pytest
24
+ import yaml
25
+
26
+ from skcapstone.dashboard import (
27
+ DashboardHandler,
28
+ _DASHBOARD_HTML,
29
+ _get_agent_status,
30
+ _get_board_state,
31
+ _get_doctor_report,
32
+ _get_daemon_json,
33
+ _get_memory_stats,
34
+ start_dashboard,
35
+ )
36
+
37
+
38
+ @pytest.fixture
39
+ def agent_home(tmp_path):
40
+ """Create a minimal agent home for dashboard testing."""
41
+ home = tmp_path / ".skcapstone"
42
+ for d in ["identity", "memory", "memory/short-term", "memory/mid-term",
43
+ "memory/long-term", "trust", "security", "sync", "sync/outbox",
44
+ "sync/inbox", "config", "coordination", "coordination/tasks",
45
+ "coordination/agents"]:
46
+ (home / d).mkdir(parents=True, exist_ok=True)
47
+
48
+ (home / "manifest.json").write_text(json.dumps({
49
+ "name": "DashBot", "version": "0.1.0",
50
+ }))
51
+ (home / "identity" / "identity.json").write_text(json.dumps({
52
+ "name": "DashBot", "fingerprint": "DASH1234", "capauth_managed": False,
53
+ }))
54
+ (home / "config" / "config.yaml").write_text(yaml.dump({"agent_name": "DashBot"}))
55
+ (home / "memory" / "index.json").write_text("{}")
56
+ (home / "memory" / "short-term" / "m1.json").write_text(
57
+ json.dumps({"memory_id": "m1", "content": "test", "tags": [],
58
+ "source": "test", "importance": 0.5, "layer": "short-term",
59
+ "created_at": "2026-02-24T00:00:00Z", "access_count": 0,
60
+ "accessed_at": None, "metadata": {}})
61
+ )
62
+
63
+ return home
64
+
65
+
66
+ @pytest.fixture
67
+ def dashboard_server(agent_home):
68
+ """Start a dashboard server on a random-ish port for testing."""
69
+ import socket
70
+
71
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
72
+ sock.bind(("127.0.0.1", 0))
73
+ port = sock.getsockname()[1]
74
+ sock.close()
75
+
76
+ server = start_dashboard(agent_home, port=port)
77
+ thread = threading.Thread(target=server.serve_forever, daemon=True)
78
+ thread.start()
79
+ time.sleep(0.3)
80
+
81
+ yield server, port
82
+
83
+ server.shutdown()
84
+
85
+
86
+ class TestDashboardHTML:
87
+ """Test the embedded HTML dashboard."""
88
+
89
+ def test_html_contains_title(self):
90
+ """HTML has the dashboard title."""
91
+ assert "SKCapstone" in _DASHBOARD_HTML
92
+ assert "Dashboard" in _DASHBOARD_HTML
93
+
94
+ def test_html_contains_api_calls(self):
95
+ """HTML fetches all API endpoints."""
96
+ assert "/api/status" in _DASHBOARD_HTML
97
+ assert "/api/doctor" in _DASHBOARD_HTML
98
+ assert "/api/board" in _DASHBOARD_HTML
99
+ assert "/api/memory" in _DASHBOARD_HTML
100
+
101
+ def test_html_auto_refreshes(self):
102
+ """HTML has auto-refresh interval."""
103
+ assert "setInterval" in _DASHBOARD_HTML
104
+
105
+
106
+ class TestAPIFunctions:
107
+ """Test the data-fetching functions directly."""
108
+
109
+ def test_get_agent_status(self, agent_home):
110
+ """Agent status returns dict with pillar info."""
111
+ status = _get_agent_status(agent_home)
112
+
113
+ assert "name" in status
114
+ assert "pillars" in status
115
+ assert "identity" in status
116
+ assert "memory" in status
117
+
118
+ def test_get_doctor_report(self, agent_home):
119
+ """Doctor report returns dict with checks."""
120
+ report = _get_doctor_report(agent_home)
121
+
122
+ assert "checks" in report
123
+ assert "passed" in report
124
+ assert "total" in report
125
+ assert report["total"] > 0
126
+
127
+ def test_get_board_state(self, agent_home):
128
+ """Board state returns tasks and agents."""
129
+ board = _get_board_state(agent_home)
130
+
131
+ assert "tasks" in board
132
+ assert "agents" in board
133
+ assert "summary" in board
134
+
135
+ def test_get_memory_stats(self, agent_home):
136
+ """Memory stats returns layer counts."""
137
+ stats = _get_memory_stats(agent_home)
138
+
139
+ assert "total" in stats
140
+ assert "short_term" in stats
141
+ assert "mid_term" in stats
142
+ assert "long_term" in stats
143
+
144
+ def test_status_handles_missing_home(self, tmp_path):
145
+ """Status returns error dict for missing agent home."""
146
+ result = _get_agent_status(tmp_path / "nope")
147
+ assert "error" in result or "name" in result
148
+
149
+
150
+ class TestHTTPServer:
151
+ """Test the actual HTTP server endpoints."""
152
+
153
+ def test_serves_html_at_root(self, dashboard_server):
154
+ """GET / returns the HTML dashboard."""
155
+ server, port = dashboard_server
156
+ conn = HTTPConnection("127.0.0.1", port, timeout=5)
157
+ conn.request("GET", "/")
158
+ resp = conn.getresponse()
159
+
160
+ assert resp.status == 200
161
+ assert "text/html" in resp.getheader("Content-Type")
162
+ body = resp.read().decode("utf-8")
163
+ assert "SKCapstone" in body
164
+ conn.close()
165
+
166
+ def test_api_status_json(self, dashboard_server):
167
+ """GET /api/status returns valid JSON."""
168
+ server, port = dashboard_server
169
+ conn = HTTPConnection("127.0.0.1", port, timeout=5)
170
+ conn.request("GET", "/api/status")
171
+ resp = conn.getresponse()
172
+
173
+ assert resp.status == 200
174
+ assert "application/json" in resp.getheader("Content-Type")
175
+ data = json.loads(resp.read())
176
+ assert "name" in data or "error" in data
177
+ conn.close()
178
+
179
+ def test_api_doctor_json(self, dashboard_server):
180
+ """GET /api/doctor returns valid JSON."""
181
+ server, port = dashboard_server
182
+ conn = HTTPConnection("127.0.0.1", port, timeout=5)
183
+ conn.request("GET", "/api/doctor")
184
+ resp = conn.getresponse()
185
+
186
+ assert resp.status == 200
187
+ data = json.loads(resp.read())
188
+ assert "checks" in data or "error" in data
189
+ conn.close()
190
+
191
+ def test_api_board_json(self, dashboard_server):
192
+ """GET /api/board returns valid JSON."""
193
+ server, port = dashboard_server
194
+ conn = HTTPConnection("127.0.0.1", port, timeout=5)
195
+ conn.request("GET", "/api/board")
196
+ resp = conn.getresponse()
197
+
198
+ assert resp.status == 200
199
+ data = json.loads(resp.read())
200
+ assert "tasks" in data or "error" in data
201
+ conn.close()
202
+
203
+ def test_api_memory_json(self, dashboard_server):
204
+ """GET /api/memory returns valid JSON."""
205
+ server, port = dashboard_server
206
+ conn = HTTPConnection("127.0.0.1", port, timeout=5)
207
+ conn.request("GET", "/api/memory")
208
+ resp = conn.getresponse()
209
+
210
+ assert resp.status == 200
211
+ data = json.loads(resp.read())
212
+ assert "total" in data or "error" in data
213
+ conn.close()
214
+
215
+ def test_404_unknown_path(self, dashboard_server):
216
+ """Unknown paths return 404."""
217
+ server, port = dashboard_server
218
+ conn = HTTPConnection("127.0.0.1", port, timeout=5)
219
+ conn.request("GET", "/api/nonexistent")
220
+ resp = conn.getresponse()
221
+
222
+ assert resp.status == 404
223
+ conn.close()
224
+
225
+ def test_cors_header(self, dashboard_server):
226
+ """API responses include CORS header."""
227
+ server, port = dashboard_server
228
+ conn = HTTPConnection("127.0.0.1", port, timeout=5)
229
+ conn.request("GET", "/api/status")
230
+ resp = conn.getresponse()
231
+
232
+ assert resp.getheader("Access-Control-Allow-Origin") == "*"
233
+ conn.close()
234
+
235
+
236
+ class TestGetDaemonJson:
237
+ """Unit tests for _get_daemon_json() — the Flutter-ready status blob."""
238
+
239
+ def test_returns_all_required_keys(self, agent_home):
240
+ """_get_daemon_json always returns all top-level keys even when daemon is offline."""
241
+ result = _get_daemon_json(agent_home, daemon_port=19999) # unused port
242
+
243
+ assert "generated_at" in result
244
+ assert "daemon" in result
245
+ assert "consciousness" in result
246
+ assert "backend_health" in result
247
+ assert "active_conversations" in result
248
+ assert "system" in result
249
+
250
+ def test_daemon_offline_returns_safe_defaults(self, agent_home):
251
+ """When daemon is unreachable, daemon section shows running=False with zero counts."""
252
+ result = _get_daemon_json(agent_home, daemon_port=19999)
253
+
254
+ daemon = result["daemon"]
255
+ assert daemon["running"] is False
256
+ assert daemon["messages_received"] == 0
257
+ assert daemon["error_count"] == 0
258
+ assert daemon["uptime_seconds"] == 0
259
+ assert isinstance(daemon["recent_errors"], list)
260
+
261
+ def test_consciousness_offline_returns_disabled(self, agent_home):
262
+ """When daemon is unreachable, consciousness section shows enabled=False."""
263
+ result = _get_daemon_json(agent_home, daemon_port=19999)
264
+
265
+ assert result["consciousness"].get("enabled") is False
266
+
267
+ def test_backend_health_has_expected_backends(self, agent_home):
268
+ """backend_health contains at least the standard five backends."""
269
+ result = _get_daemon_json(agent_home, daemon_port=19999)
270
+
271
+ bh = result["backend_health"]
272
+ for key in ("ollama", "anthropic", "grok", "kimi", "nvidia"):
273
+ assert key in bh, f"Missing backend key: {key}"
274
+ assert isinstance(bh[key], bool)
275
+
276
+ def test_generated_at_is_iso_timestamp(self, agent_home):
277
+ """generated_at is a valid ISO 8601 timestamp string."""
278
+ from datetime import datetime
279
+
280
+ result = _get_daemon_json(agent_home, daemon_port=19999)
281
+ ts = result["generated_at"]
282
+ # Should not raise
283
+ datetime.fromisoformat(ts.replace("Z", "+00:00"))
284
+
285
+ def test_daemon_running_returns_full_snapshot(self, agent_home):
286
+ """When daemon HTTP returns a valid snapshot, all fields are populated."""
287
+ fake_snap = {
288
+ "running": True,
289
+ "pid": 42,
290
+ "uptime_seconds": 3725,
291
+ "started_at": "2026-03-02T10:00:00+00:00",
292
+ "messages_received": 17,
293
+ "syncs_completed": 3,
294
+ "recent_errors": ["err1"],
295
+ "inflight_count": 2,
296
+ }
297
+ fake_consciousness = {
298
+ "enabled": True,
299
+ "messages_processed": 10,
300
+ "messages_processed_24h": 5,
301
+ "responses_sent": 9,
302
+ "errors": 1,
303
+ "backends": {"ollama": True, "grok": False},
304
+ }
305
+
306
+ import urllib.request
307
+
308
+ class _FakeResponse:
309
+ def __init__(self, data):
310
+ self._data = json.dumps(data).encode()
311
+
312
+ def read(self):
313
+ return self._data
314
+
315
+ def __enter__(self):
316
+ return self
317
+
318
+ def __exit__(self, *_):
319
+ pass
320
+
321
+ call_count = {"n": 0}
322
+
323
+ def fake_urlopen(url_or_req, timeout=None):
324
+ url = url_or_req if isinstance(url_or_req, str) else url_or_req.full_url
325
+ call_count["n"] += 1
326
+ if "/status" in url:
327
+ return _FakeResponse(fake_snap)
328
+ if "/consciousness" in url:
329
+ return _FakeResponse(fake_consciousness)
330
+ raise OSError("not available")
331
+
332
+ with patch("urllib.request.urlopen", side_effect=fake_urlopen):
333
+ result = _get_daemon_json(agent_home, daemon_port=7777)
334
+
335
+ daemon = result["daemon"]
336
+ assert daemon["running"] is True
337
+ assert daemon["pid"] == 42
338
+ assert daemon["messages_received"] == 17
339
+ assert daemon["error_count"] == 1
340
+ assert daemon["uptime_human"] == "1h 2m"
341
+
342
+ csc = result["consciousness"]
343
+ assert csc["enabled"] is True
344
+ assert csc["messages_processed"] == 10
345
+
346
+
347
+ class TestDaemonApiEndpoint:
348
+ """Test the /api/daemon HTTP endpoint on the dashboard server."""
349
+
350
+ def test_api_daemon_json(self, dashboard_server):
351
+ """GET /api/daemon returns valid JSON with all required top-level keys."""
352
+ server, port = dashboard_server
353
+ conn = HTTPConnection("127.0.0.1", port, timeout=5)
354
+ conn.request("GET", "/api/daemon")
355
+ resp = conn.getresponse()
356
+
357
+ assert resp.status == 200
358
+ assert "application/json" in resp.getheader("Content-Type")
359
+ data = json.loads(resp.read())
360
+ for key in ("generated_at", "daemon", "consciousness", "backend_health",
361
+ "active_conversations", "system"):
362
+ assert key in data, f"Missing key in /api/daemon response: {key}"
363
+ conn.close()
364
+
365
+ def test_api_daemon_cors_header(self, dashboard_server):
366
+ """/api/daemon includes the CORS header for cross-origin Flutter access."""
367
+ server, port = dashboard_server
368
+ conn = HTTPConnection("127.0.0.1", port, timeout=5)
369
+ conn.request("GET", "/api/daemon")
370
+ resp = conn.getresponse()
371
+
372
+ assert resp.getheader("Access-Control-Allow-Origin") == "*"
373
+ conn.close()
374
+
375
+ def test_api_daemon_backend_health_keys(self, dashboard_server):
376
+ """/api/daemon backend_health contains all standard backend names."""
377
+ server, port = dashboard_server
378
+ conn = HTTPConnection("127.0.0.1", port, timeout=5)
379
+ conn.request("GET", "/api/daemon")
380
+ resp = conn.getresponse()
381
+
382
+ data = json.loads(resp.read())
383
+ bh = data.get("backend_health", {})
384
+ for key in ("ollama", "anthropic", "grok", "kimi", "nvidia"):
385
+ assert key in bh
386
+ conn.close()
387
+
388
+
389
+ class TestDashboardJsonCLI:
390
+ """Test the skcapstone dashboard --json CLI flag."""
391
+
392
+ def test_json_flag_outputs_valid_json(self, agent_home):
393
+ """dashboard --json prints JSON to stdout and exits without starting a server."""
394
+ from click.testing import CliRunner
395
+ from skcapstone.cli.status import register_status_commands
396
+ import click
397
+
398
+ @click.group()
399
+ def _cli():
400
+ pass
401
+
402
+ register_status_commands(_cli)
403
+ runner = CliRunner()
404
+ result = runner.invoke(
405
+ _cli,
406
+ ["dashboard", "--json", f"--home={agent_home}"],
407
+ catch_exceptions=False,
408
+ )
409
+ assert result.exit_code == 0, result.output
410
+ data = json.loads(result.output)
411
+ assert "daemon" in data
412
+ assert "consciousness" in data
413
+ assert "backend_health" in data
414
+
415
+ def test_json_flag_contains_generated_at(self, agent_home):
416
+ """dashboard --json output includes a generated_at timestamp."""
417
+ from click.testing import CliRunner
418
+ from skcapstone.cli.status import register_status_commands
419
+ import click
420
+
421
+ @click.group()
422
+ def _cli():
423
+ pass
424
+
425
+ register_status_commands(_cli)
426
+ runner = CliRunner()
427
+ result = runner.invoke(
428
+ _cli,
429
+ ["dashboard", "--json", f"--home={agent_home}"],
430
+ catch_exceptions=False,
431
+ )
432
+ data = json.loads(result.output)
433
+ assert "generated_at" in data
434
+
435
+ def test_json_flag_daemon_offline_still_exits_zero(self, agent_home):
436
+ """dashboard --json exits 0 even when daemon is unreachable (daemon offline)."""
437
+ from click.testing import CliRunner
438
+ from skcapstone.cli.status import register_status_commands
439
+ import click
440
+
441
+ @click.group()
442
+ def _cli():
443
+ pass
444
+
445
+ register_status_commands(_cli)
446
+ runner = CliRunner()
447
+ result = runner.invoke(
448
+ _cli,
449
+ ["dashboard", "--json", "--daemon-port=19999", f"--home={agent_home}"],
450
+ catch_exceptions=False,
451
+ )
452
+ assert result.exit_code == 0
453
+ data = json.loads(result.output)
454
+ assert data["daemon"]["running"] is False