@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,421 @@
1
+ """
2
+ Unified Search — full-text search across all agent data stores.
3
+
4
+ Searches memories, conversations, and SKComm messages in one query.
5
+ Results are ranked by a combined relevance + recency score.
6
+
7
+ Data stores searched:
8
+ memories — ~/.skcapstone/memory/{short,mid,long}-term/*.json
9
+ conversations — ~/.skcapstone/conversations/*.json
10
+ messages — ~/.skcapstone/sync/comms/archive/*.skc.json
11
+ journal — ~/.skcapstone/journal/*.json (if present)
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import json
17
+ import logging
18
+ import re
19
+ from dataclasses import dataclass, field
20
+ from datetime import datetime, timezone
21
+ from pathlib import Path
22
+ from typing import Optional
23
+
24
+ logger = logging.getLogger("skcapstone.unified_search")
25
+
26
+ # Score decay: 1 point per match, multiplied by recency weight (0–1).
27
+ # Recency weight = 1 / (1 + age_days * RECENCY_DECAY)
28
+ RECENCY_DECAY = 0.05 # ~14-day half-life
29
+ MEMORY_LAYER_BOOST = {"long-term": 1.5, "mid-term": 1.2, "short-term": 1.0}
30
+
31
+
32
+ @dataclass
33
+ class SearchResult:
34
+ """A single result from the unified search."""
35
+
36
+ source: str # "memory", "conversation", "message", "journal"
37
+ result_id: str # Unique identifier within the source
38
+ title: str # Human-readable label (peer name, memory ID, etc.)
39
+ preview: str # Short text snippet showing the match context
40
+ score: float # Composite relevance + recency score
41
+ timestamp: Optional[datetime] # When the item was created/last modified
42
+ metadata: dict = field(default_factory=dict) # Source-specific extras
43
+
44
+
45
+ # ---------------------------------------------------------------------------
46
+ # Internal helpers
47
+ # ---------------------------------------------------------------------------
48
+
49
+
50
+ def _recency_weight(ts: Optional[datetime]) -> float:
51
+ """Compute a recency weight in [0, 1] from an ISO timestamp.
52
+
53
+ Newer items score closer to 1.0; older items decay toward 0.
54
+
55
+ Args:
56
+ ts: UTC-aware datetime, or None.
57
+
58
+ Returns:
59
+ Float in (0, 1].
60
+ """
61
+ if ts is None:
62
+ return 0.5 # unknown age — neutral weight
63
+ now = datetime.now(timezone.utc)
64
+ if ts.tzinfo is None:
65
+ ts = ts.replace(tzinfo=timezone.utc)
66
+ age_days = max(0.0, (now - ts).total_seconds() / 86_400)
67
+ return 1.0 / (1.0 + age_days * RECENCY_DECAY)
68
+
69
+
70
+ def _count_matches(pattern: re.Pattern, *texts: str) -> int:
71
+ """Count total regex matches across one or more text strings.
72
+
73
+ Args:
74
+ pattern: Compiled case-insensitive regex.
75
+ *texts: Strings to search.
76
+
77
+ Returns:
78
+ Total match count.
79
+ """
80
+ return sum(len(pattern.findall(t)) for t in texts if t)
81
+
82
+
83
+ def _snippet(text: str, pattern: re.Pattern, window: int = 80) -> str:
84
+ """Extract a context snippet around the first match.
85
+
86
+ Args:
87
+ text: Source text to extract from.
88
+ pattern: Compiled regex to locate.
89
+ window: Characters to show on each side of the match.
90
+
91
+ Returns:
92
+ A clipped snippet string.
93
+ """
94
+ m = pattern.search(text)
95
+ if m is None:
96
+ return text[: window * 2]
97
+ start = max(0, m.start() - window)
98
+ end = min(len(text), m.end() + window)
99
+ snippet = text[start:end].strip()
100
+ if start > 0:
101
+ snippet = "…" + snippet
102
+ if end < len(text):
103
+ snippet = snippet + "…"
104
+ return snippet
105
+
106
+
107
+ def _parse_dt(value: Optional[str]) -> Optional[datetime]:
108
+ """Parse an ISO-8601 datetime string, returning None on failure.
109
+
110
+ Args:
111
+ value: ISO-8601 string or None.
112
+
113
+ Returns:
114
+ Parsed datetime or None.
115
+ """
116
+ if not value:
117
+ return None
118
+ try:
119
+ return datetime.fromisoformat(value)
120
+ except (ValueError, TypeError):
121
+ return None
122
+
123
+
124
+ # ---------------------------------------------------------------------------
125
+ # Per-source search functions
126
+ # ---------------------------------------------------------------------------
127
+
128
+
129
+ def _search_memories(
130
+ home: Path,
131
+ pattern: re.Pattern,
132
+ ) -> list[SearchResult]:
133
+ """Search the three-tier memory store.
134
+
135
+ Args:
136
+ home: Agent home directory.
137
+ pattern: Compiled search pattern.
138
+
139
+ Returns:
140
+ List of SearchResult objects from the memory store.
141
+ """
142
+ results: list[SearchResult] = []
143
+ agent_name = os.environ.get("SKCAPSTONE_AGENT", "lumina")
144
+ mem_dir = home / "agents" / agent_name / "memory"
145
+ if not mem_dir.exists():
146
+ return results
147
+
148
+ for layer_name in ("long-term", "mid-term", "short-term"):
149
+ layer_dir = mem_dir / layer_name
150
+ if not layer_dir.exists():
151
+ continue
152
+ for f in layer_dir.glob("*.json"):
153
+ try:
154
+ data = json.loads(f.read_text(encoding="utf-8"))
155
+ except (json.JSONDecodeError, OSError) as exc:
156
+ logger.debug("Skipping memory %s: %s", f, exc)
157
+ continue
158
+
159
+ content = data.get("content", "")
160
+ tags = " ".join(data.get("tags", []))
161
+ matches = _count_matches(pattern, content, tags)
162
+ if matches == 0:
163
+ continue
164
+
165
+ ts = _parse_dt(data.get("created_at"))
166
+ importance = float(data.get("importance", 0.5))
167
+ layer_boost = MEMORY_LAYER_BOOST.get(layer_name, 1.0)
168
+ score = matches * importance * layer_boost * _recency_weight(ts)
169
+
170
+ memory_id = data.get("memory_id", f.stem)
171
+ preview = _snippet(content, pattern)
172
+ tag_str = ", ".join(data.get("tags", [])) if data.get("tags") else ""
173
+
174
+ results.append(
175
+ SearchResult(
176
+ source="memory",
177
+ result_id=memory_id,
178
+ title=f"{memory_id} [{layer_name}]",
179
+ preview=preview,
180
+ score=score,
181
+ timestamp=ts,
182
+ metadata={
183
+ "layer": layer_name,
184
+ "importance": importance,
185
+ "tags": tag_str,
186
+ "source": data.get("source", ""),
187
+ },
188
+ )
189
+ )
190
+
191
+ return results
192
+
193
+
194
+ def _search_conversations(
195
+ home: Path,
196
+ pattern: re.Pattern,
197
+ ) -> list[SearchResult]:
198
+ """Search conversation history files.
199
+
200
+ Each conversation is stored as a list of {role, content, timestamp}
201
+ dicts in ~/.skcapstone/conversations/<peer>.json.
202
+
203
+ Args:
204
+ home: Agent home directory.
205
+ pattern: Compiled search pattern.
206
+
207
+ Returns:
208
+ List of SearchResult objects from conversations.
209
+ """
210
+ results: list[SearchResult] = []
211
+ conv_dir = home / "conversations"
212
+ if not conv_dir.exists():
213
+ return results
214
+
215
+ for f in conv_dir.glob("*.json"):
216
+ try:
217
+ messages = json.loads(f.read_text(encoding="utf-8"))
218
+ except (json.JSONDecodeError, OSError) as exc:
219
+ logger.debug("Skipping conversation %s: %s", f, exc)
220
+ continue
221
+
222
+ if not isinstance(messages, list):
223
+ continue
224
+
225
+ peer = f.stem
226
+ for idx, msg in enumerate(messages):
227
+ content = msg.get("content", "")
228
+ matches = _count_matches(pattern, content)
229
+ if matches == 0:
230
+ continue
231
+
232
+ ts = _parse_dt(msg.get("timestamp"))
233
+ score = matches * _recency_weight(ts)
234
+ role = msg.get("role", "?")
235
+
236
+ results.append(
237
+ SearchResult(
238
+ source="conversation",
239
+ result_id=f"{peer}:{idx}",
240
+ title=f"Conversation with {peer} [{role}]",
241
+ preview=_snippet(content, pattern),
242
+ score=score,
243
+ timestamp=ts,
244
+ metadata={"peer": peer, "role": role, "message_index": idx},
245
+ )
246
+ )
247
+
248
+ return results
249
+
250
+
251
+ def _search_messages(
252
+ home: Path,
253
+ pattern: re.Pattern,
254
+ ) -> list[SearchResult]:
255
+ """Search archived SKComm envelope files (.skc.json).
256
+
257
+ Handles both the legacy schema (payload.text) and the newer
258
+ schema (payload.content).
259
+
260
+ Args:
261
+ home: Agent home directory.
262
+ pattern: Compiled search pattern.
263
+
264
+ Returns:
265
+ List of SearchResult objects from SKComm messages.
266
+ """
267
+ results: list[SearchResult] = []
268
+
269
+ # Locations where .skc.json files may live
270
+ search_dirs = [
271
+ home / "sync" / "comms" / "archive",
272
+ home / "comms" / "archive",
273
+ ]
274
+
275
+ for base_dir in search_dirs:
276
+ if not base_dir.exists():
277
+ continue
278
+ for f in base_dir.glob("*.skc.json"):
279
+ try:
280
+ data = json.loads(f.read_text(encoding="utf-8"))
281
+ except (json.JSONDecodeError, OSError) as exc:
282
+ logger.debug("Skipping message %s: %s", f, exc)
283
+ continue
284
+
285
+ payload = data.get("payload", {})
286
+ # Support both field names used across schema versions
287
+ text = payload.get("text") or payload.get("content", "")
288
+ metadata_block = data.get("metadata", {})
289
+
290
+ matches = _count_matches(pattern, text)
291
+ if matches == 0:
292
+ continue
293
+
294
+ # Prefer envelope-level timestamp, fall back to metadata
295
+ ts_raw = data.get("created_at") or metadata_block.get("created_at")
296
+ ts = _parse_dt(ts_raw)
297
+ score = matches * _recency_weight(ts)
298
+
299
+ envelope_id = data.get("id") or data.get("envelope_id", f.stem)
300
+ sender = data.get("from_peer") or data.get("sender", "?")
301
+ recipient = data.get("to_peer") or data.get("recipient", "?")
302
+
303
+ results.append(
304
+ SearchResult(
305
+ source="message",
306
+ result_id=str(envelope_id),
307
+ title=f"Message {sender} → {recipient}",
308
+ preview=_snippet(text, pattern),
309
+ score=score,
310
+ timestamp=ts,
311
+ metadata={
312
+ "sender": sender,
313
+ "recipient": recipient,
314
+ "file": f.name,
315
+ },
316
+ )
317
+ )
318
+
319
+ return results
320
+
321
+
322
+ def _search_journal(
323
+ home: Path,
324
+ pattern: re.Pattern,
325
+ ) -> list[SearchResult]:
326
+ """Search journal entries in ~/.skcapstone/journal/*.json.
327
+
328
+ Journal entries are expected to have at least {content, created_at}.
329
+ Missing directory is silently skipped.
330
+
331
+ Args:
332
+ home: Agent home directory.
333
+ pattern: Compiled search pattern.
334
+
335
+ Returns:
336
+ List of SearchResult objects from journal entries.
337
+ """
338
+ results: list[SearchResult] = []
339
+ journal_dir = home / "journal"
340
+ if not journal_dir.exists():
341
+ return results
342
+
343
+ for f in journal_dir.glob("*.json"):
344
+ try:
345
+ data = json.loads(f.read_text(encoding="utf-8"))
346
+ except (json.JSONDecodeError, OSError) as exc:
347
+ logger.debug("Skipping journal %s: %s", f, exc)
348
+ continue
349
+
350
+ content = data.get("content", "") or data.get("text", "")
351
+ title_text = data.get("title", "")
352
+ matches = _count_matches(pattern, content, title_text)
353
+ if matches == 0:
354
+ continue
355
+
356
+ ts = _parse_dt(data.get("created_at"))
357
+ score = matches * _recency_weight(ts)
358
+
359
+ results.append(
360
+ SearchResult(
361
+ source="journal",
362
+ result_id=f.stem,
363
+ title=f"Journal: {title_text or f.stem}",
364
+ preview=_snippet(content, pattern),
365
+ score=score,
366
+ timestamp=ts,
367
+ metadata={"file": f.name},
368
+ )
369
+ )
370
+
371
+ return results
372
+
373
+
374
+ # ---------------------------------------------------------------------------
375
+ # Public API
376
+ # ---------------------------------------------------------------------------
377
+
378
+ SOURCE_ALL = frozenset({"memory", "conversation", "message", "journal"})
379
+
380
+
381
+ def search(
382
+ home: Path,
383
+ query: str,
384
+ sources: Optional[frozenset[str]] = None,
385
+ limit: int = 20,
386
+ ) -> list[SearchResult]:
387
+ """Search across all agent data stores.
388
+
389
+ Performs full-text regex matching against memories, conversations,
390
+ SKComm messages, and journal entries. Results are ranked by a
391
+ combined relevance × recency score, highest first.
392
+
393
+ Args:
394
+ home: Agent home directory (usually ~/.skcapstone).
395
+ query: Search query. Treated as a literal string (not regex).
396
+ sources: Set of source names to include. Defaults to all sources.
397
+ Valid values: "memory", "conversation", "message", "journal".
398
+ limit: Maximum number of results to return.
399
+
400
+ Returns:
401
+ List of SearchResult objects, ranked by score descending.
402
+ """
403
+ if not query.strip():
404
+ return []
405
+
406
+ active_sources = sources if sources is not None else SOURCE_ALL
407
+ pattern = re.compile(re.escape(query.strip()), re.IGNORECASE)
408
+
409
+ all_results: list[SearchResult] = []
410
+
411
+ if "memory" in active_sources:
412
+ all_results.extend(_search_memories(home, pattern))
413
+ if "conversation" in active_sources:
414
+ all_results.extend(_search_conversations(home, pattern))
415
+ if "message" in active_sources:
416
+ all_results.extend(_search_messages(home, pattern))
417
+ if "journal" in active_sources:
418
+ all_results.extend(_search_journal(home, pattern))
419
+
420
+ all_results.sort(key=lambda r: r.score, reverse=True)
421
+ return all_results[:limit]