@agentikos/omega-os 0.2.0 → 0.19.5

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 (367) hide show
  1. package/README.md +33 -3
  2. package/bootstrap/lib/__pycache__/claude-code-settings.cpython-313.pyc +0 -0
  3. package/bootstrap/lib/__pycache__/llm-clis.cpython-313.pyc +0 -0
  4. package/bootstrap/lib/__pycache__/manifest-helpers.cpython-313.pyc +0 -0
  5. package/bootstrap/lib/claude-code-settings.py +176 -0
  6. package/bootstrap/lib/common.sh +457 -1
  7. package/bootstrap/lib/llm-clis.py +341 -0
  8. package/bootstrap/lib/manifest-helpers.py +384 -0
  9. package/bootstrap/lib/steps.sh +790 -21
  10. package/bootstrap/manifest.example.yaml +87 -1
  11. package/bootstrap/templates/aisb/CLAUDE.md +305 -0
  12. package/bootstrap/templates/aisb/architect.md +204 -0
  13. package/bootstrap/templates/aisb/checkers/CLAUDE.md +9 -0
  14. package/bootstrap/templates/aisb/checkers/checker-architect.md +151 -0
  15. package/bootstrap/templates/aisb/checkers/checker-common.md +171 -0
  16. package/bootstrap/templates/aisb/checkers/checker-construct.md +129 -0
  17. package/bootstrap/templates/aisb/checkers/checker-keymaker.md +204 -0
  18. package/bootstrap/templates/aisb/checkers/checker-link.md +205 -0
  19. package/bootstrap/templates/aisb/checkers/checker-merovingian.md +219 -0
  20. package/bootstrap/templates/aisb/checkers/checker-morpheus.md +211 -0
  21. package/bootstrap/templates/aisb/checkers/checker-neo.md +177 -0
  22. package/bootstrap/templates/aisb/checkers/checker-niobe.md +156 -0
  23. package/bootstrap/templates/aisb/checkers/checker-oracle.md +164 -0
  24. package/bootstrap/templates/aisb/checkers/checker-seraph.md +187 -0
  25. package/bootstrap/templates/aisb/checkers/checker-smith.md +195 -0
  26. package/bootstrap/templates/aisb/checkers/checker-zion.md +113 -0
  27. package/bootstrap/templates/aisb/construct.md +135 -0
  28. package/bootstrap/templates/aisb/keymaker.md +227 -0
  29. package/bootstrap/templates/aisb/link.md +170 -0
  30. package/bootstrap/templates/aisb/lmc-protocol.md +57 -0
  31. package/bootstrap/templates/aisb/merovingian.md +159 -0
  32. package/bootstrap/templates/aisb/morpheus.md +243 -0
  33. package/bootstrap/templates/aisb/neo.md +147 -0
  34. package/bootstrap/templates/aisb/niobe.md +197 -0
  35. package/bootstrap/templates/aisb/oracle.md +244 -0
  36. package/bootstrap/templates/aisb/protocols/handoff-templates.md +204 -0
  37. package/bootstrap/templates/aisb/protocols/shared-protocol.md +248 -0
  38. package/bootstrap/templates/aisb/pythia.md +153 -0
  39. package/bootstrap/templates/aisb/seraph.md +315 -0
  40. package/bootstrap/templates/aisb/smith.md +202 -0
  41. package/bootstrap/templates/aisb/zion.md +172 -0
  42. package/bootstrap/templates/autonomous/audit-patrol.yaml +41 -0
  43. package/bootstrap/templates/autonomous/smith-reflect.yaml +43 -0
  44. package/bootstrap/templates/autonomous/ssh-key-rotate.yaml +46 -0
  45. package/bootstrap/templates/autonomous/support-agent.yaml +38 -0
  46. package/docs/AUDITS.md +85 -0
  47. package/docs/GAP-ANALYSIS.md +214 -0
  48. package/docs/INSTALL.md +47 -9
  49. package/docs/MCP-AND-PLUGINS.md +31 -4
  50. package/docs/SIMULATION.md +171 -0
  51. package/docs/simulate.sh +211 -0
  52. package/install.sh +164 -17
  53. package/omega/Agentik_Engine/README.md +4 -2
  54. package/omega/Agentik_Engine/omega_engine/__init__.py +147 -1
  55. package/omega/Agentik_Engine/omega_engine/__pycache__/__init__.cpython-313.pyc +0 -0
  56. package/omega/Agentik_Engine/omega_engine/__pycache__/account.cpython-313.pyc +0 -0
  57. package/omega/Agentik_Engine/omega_engine/__pycache__/agent_messages.cpython-313.pyc +0 -0
  58. package/omega/Agentik_Engine/omega_engine/__pycache__/aisb_chat.cpython-313.pyc +0 -0
  59. package/omega/Agentik_Engine/omega_engine/__pycache__/audit.cpython-313.pyc +0 -0
  60. package/omega/Agentik_Engine/omega_engine/__pycache__/audit_arsenal.cpython-313.pyc +0 -0
  61. package/omega/Agentik_Engine/omega_engine/__pycache__/audit_diff.cpython-313.pyc +0 -0
  62. package/omega/Agentik_Engine/omega_engine/__pycache__/audit_gate.cpython-313.pyc +0 -0
  63. package/omega/Agentik_Engine/omega_engine/__pycache__/auto_update.cpython-313.pyc +0 -0
  64. package/omega/Agentik_Engine/omega_engine/__pycache__/autonomous.cpython-313.pyc +0 -0
  65. package/omega/Agentik_Engine/omega_engine/__pycache__/backup.cpython-313.pyc +0 -0
  66. package/omega/Agentik_Engine/omega_engine/__pycache__/barrier.cpython-313.pyc +0 -0
  67. package/omega/Agentik_Engine/omega_engine/__pycache__/bus.cpython-313.pyc +0 -0
  68. package/omega/Agentik_Engine/omega_engine/__pycache__/cadence.cpython-313.pyc +0 -0
  69. package/omega/Agentik_Engine/omega_engine/__pycache__/classifier.cpython-313.pyc +0 -0
  70. package/omega/Agentik_Engine/omega_engine/__pycache__/cleanup.cpython-313.pyc +0 -0
  71. package/omega/Agentik_Engine/omega_engine/__pycache__/cli.cpython-313.pyc +0 -0
  72. package/omega/Agentik_Engine/omega_engine/__pycache__/completions.cpython-313.pyc +0 -0
  73. package/omega/Agentik_Engine/omega_engine/__pycache__/costs.cpython-313.pyc +0 -0
  74. package/omega/Agentik_Engine/omega_engine/__pycache__/done_signal.cpython-313.pyc +0 -0
  75. package/omega/Agentik_Engine/omega_engine/__pycache__/envelope.cpython-313.pyc +0 -0
  76. package/omega/Agentik_Engine/omega_engine/__pycache__/events.cpython-313.pyc +0 -0
  77. package/omega/Agentik_Engine/omega_engine/__pycache__/executor.cpython-313.pyc +0 -0
  78. package/omega/Agentik_Engine/omega_engine/__pycache__/handoff.cpython-313.pyc +0 -0
  79. package/omega/Agentik_Engine/omega_engine/__pycache__/hermes.cpython-313.pyc +0 -0
  80. package/omega/Agentik_Engine/omega_engine/__pycache__/hermes_bootstrap.cpython-313.pyc +0 -0
  81. package/omega/Agentik_Engine/omega_engine/__pycache__/hermes_desktop.cpython-313.pyc +0 -0
  82. package/omega/Agentik_Engine/omega_engine/__pycache__/learning.cpython-313.pyc +0 -0
  83. package/omega/Agentik_Engine/omega_engine/__pycache__/managed_agent.cpython-313.pyc +0 -0
  84. package/omega/Agentik_Engine/omega_engine/__pycache__/memory.cpython-313.pyc +0 -0
  85. package/omega/Agentik_Engine/omega_engine/__pycache__/menu.cpython-313.pyc +0 -0
  86. package/omega/Agentik_Engine/omega_engine/__pycache__/mission.cpython-313.pyc +0 -0
  87. package/omega/Agentik_Engine/omega_engine/__pycache__/plan.cpython-313.pyc +0 -0
  88. package/omega/Agentik_Engine/omega_engine/__pycache__/progress.cpython-313.pyc +0 -0
  89. package/omega/Agentik_Engine/omega_engine/__pycache__/project.cpython-313.pyc +0 -0
  90. package/omega/Agentik_Engine/omega_engine/__pycache__/prompts.cpython-313.pyc +0 -0
  91. package/omega/Agentik_Engine/omega_engine/__pycache__/provider.cpython-313.pyc +0 -0
  92. package/omega/Agentik_Engine/omega_engine/__pycache__/prune.cpython-313.pyc +0 -0
  93. package/omega/Agentik_Engine/omega_engine/__pycache__/pursue.cpython-313.pyc +0 -0
  94. package/omega/Agentik_Engine/omega_engine/__pycache__/reducer.cpython-313.pyc +0 -0
  95. package/omega/Agentik_Engine/omega_engine/__pycache__/report.cpython-313.pyc +0 -0
  96. package/omega/Agentik_Engine/omega_engine/__pycache__/router.cpython-313.pyc +0 -0
  97. package/omega/Agentik_Engine/omega_engine/__pycache__/skill_routing.cpython-313.pyc +0 -0
  98. package/omega/Agentik_Engine/omega_engine/__pycache__/smoke.cpython-313.pyc +0 -0
  99. package/omega/Agentik_Engine/omega_engine/__pycache__/store.cpython-313.pyc +0 -0
  100. package/omega/Agentik_Engine/omega_engine/__pycache__/supervisor.cpython-313.pyc +0 -0
  101. package/omega/Agentik_Engine/omega_engine/__pycache__/sync.cpython-313.pyc +0 -0
  102. package/omega/Agentik_Engine/omega_engine/__pycache__/task.cpython-313.pyc +0 -0
  103. package/omega/Agentik_Engine/omega_engine/__pycache__/telegram.cpython-313.pyc +0 -0
  104. package/omega/Agentik_Engine/omega_engine/__pycache__/telegram_history.cpython-313.pyc +0 -0
  105. package/omega/Agentik_Engine/omega_engine/__pycache__/tmux.cpython-313.pyc +0 -0
  106. package/omega/Agentik_Engine/omega_engine/__pycache__/tools.cpython-313.pyc +0 -0
  107. package/omega/Agentik_Engine/omega_engine/__pycache__/understand_anything.cpython-313.pyc +0 -0
  108. package/omega/Agentik_Engine/omega_engine/__pycache__/updater.cpython-313.pyc +0 -0
  109. package/omega/Agentik_Engine/omega_engine/__pycache__/validate.cpython-313.pyc +0 -0
  110. package/omega/Agentik_Engine/omega_engine/__pycache__/vault.cpython-313.pyc +0 -0
  111. package/omega/Agentik_Engine/omega_engine/__pycache__/webhooks.cpython-313.pyc +0 -0
  112. package/omega/Agentik_Engine/omega_engine/__pycache__/worker.cpython-313.pyc +0 -0
  113. package/omega/Agentik_Engine/omega_engine/account.py +28 -31
  114. package/omega/Agentik_Engine/omega_engine/agent_messages.py +167 -0
  115. package/omega/Agentik_Engine/omega_engine/aisb_chat.py +128 -0
  116. package/omega/Agentik_Engine/omega_engine/audit_diff.py +99 -0
  117. package/omega/Agentik_Engine/omega_engine/audit_gate.py +149 -0
  118. package/omega/Agentik_Engine/omega_engine/audits/__init__.py +60 -0
  119. package/omega/Agentik_Engine/omega_engine/audits/__pycache__/__init__.cpython-313.pyc +0 -0
  120. package/omega/Agentik_Engine/omega_engine/audits/__pycache__/batcher.cpython-313.pyc +0 -0
  121. package/omega/Agentik_Engine/omega_engine/audits/__pycache__/dispatcher.cpython-313.pyc +0 -0
  122. package/omega/Agentik_Engine/omega_engine/audits/__pycache__/generator.cpython-313.pyc +0 -0
  123. package/omega/Agentik_Engine/omega_engine/audits/__pycache__/history.cpython-313.pyc +0 -0
  124. package/omega/Agentik_Engine/omega_engine/audits/__pycache__/pipeline.cpython-313.pyc +0 -0
  125. package/omega/Agentik_Engine/omega_engine/audits/batcher.py +218 -0
  126. package/omega/Agentik_Engine/omega_engine/audits/dispatcher.py +92 -0
  127. package/omega/Agentik_Engine/omega_engine/audits/generator.py +234 -0
  128. package/omega/Agentik_Engine/omega_engine/audits/history.py +168 -0
  129. package/omega/Agentik_Engine/omega_engine/audits/pipeline.py +198 -0
  130. package/omega/Agentik_Engine/omega_engine/auto_update.py +339 -0
  131. package/omega/Agentik_Engine/omega_engine/backup.py +215 -0
  132. package/omega/Agentik_Engine/omega_engine/cadence.py +158 -0
  133. package/omega/Agentik_Engine/omega_engine/classifier.py +215 -0
  134. package/omega/Agentik_Engine/omega_engine/cleanup.py +673 -0
  135. package/omega/Agentik_Engine/omega_engine/cli.py +4156 -86
  136. package/omega/Agentik_Engine/omega_engine/completions.py +260 -0
  137. package/omega/Agentik_Engine/omega_engine/costs.py +100 -0
  138. package/omega/Agentik_Engine/omega_engine/daemons/__pycache__/__init__.cpython-313.pyc +0 -0
  139. package/omega/Agentik_Engine/omega_engine/daemons/__pycache__/autonomous.cpython-313.pyc +0 -0
  140. package/omega/Agentik_Engine/omega_engine/daemons/__pycache__/engine.cpython-313.pyc +0 -0
  141. package/omega/Agentik_Engine/omega_engine/daemons/__pycache__/telegram.cpython-313.pyc +0 -0
  142. package/omega/Agentik_Engine/omega_engine/daemons/engine.py +53 -4
  143. package/omega/Agentik_Engine/omega_engine/daemons/telegram.py +101 -17
  144. package/omega/Agentik_Engine/omega_engine/done_signal.py +154 -0
  145. package/omega/Agentik_Engine/omega_engine/educators/__pycache__/__init__.cpython-313.pyc +0 -0
  146. package/omega/Agentik_Engine/omega_engine/educators/__pycache__/artifact.cpython-313.pyc +0 -0
  147. package/omega/Agentik_Engine/omega_engine/educators/__pycache__/automation.cpython-313.pyc +0 -0
  148. package/omega/Agentik_Engine/omega_engine/educators/__pycache__/base.cpython-313.pyc +0 -0
  149. package/omega/Agentik_Engine/omega_engine/educators/__pycache__/claudecode.cpython-313.pyc +0 -0
  150. package/omega/Agentik_Engine/omega_engine/educators/__pycache__/connection.cpython-313.pyc +0 -0
  151. package/omega/Agentik_Engine/omega_engine/educators/__pycache__/coworker.cpython-313.pyc +0 -0
  152. package/omega/Agentik_Engine/omega_engine/educators/__pycache__/loop.cpython-313.pyc +0 -0
  153. package/omega/Agentik_Engine/omega_engine/educators/__pycache__/prompt.cpython-313.pyc +0 -0
  154. package/omega/Agentik_Engine/omega_engine/educators/__pycache__/skill.cpython-313.pyc +0 -0
  155. package/omega/Agentik_Engine/omega_engine/envelope.py +219 -0
  156. package/omega/Agentik_Engine/omega_engine/executor.py +149 -10
  157. package/omega/Agentik_Engine/omega_engine/genesis/__init__.py +134 -0
  158. package/omega/Agentik_Engine/omega_engine/genesis/__pycache__/__init__.cpython-313.pyc +0 -0
  159. package/omega/Agentik_Engine/omega_engine/genesis/__pycache__/orchestrator.cpython-313.pyc +0 -0
  160. package/omega/Agentik_Engine/omega_engine/genesis/__pycache__/phases.cpython-313.pyc +0 -0
  161. package/omega/Agentik_Engine/omega_engine/genesis/__pycache__/stack.cpython-313.pyc +0 -0
  162. package/omega/Agentik_Engine/omega_engine/genesis/__pycache__/state.cpython-313.pyc +0 -0
  163. package/omega/Agentik_Engine/omega_engine/genesis/orchestrator.py +262 -0
  164. package/omega/Agentik_Engine/omega_engine/genesis/phases.py +950 -0
  165. package/omega/Agentik_Engine/omega_engine/genesis/stack.py +324 -0
  166. package/omega/Agentik_Engine/omega_engine/genesis/state.py +353 -0
  167. package/omega/Agentik_Engine/omega_engine/handoff.py +459 -0
  168. package/omega/Agentik_Engine/omega_engine/hermes.py +426 -0
  169. package/omega/Agentik_Engine/omega_engine/hermes_bootstrap.py +382 -0
  170. package/omega/Agentik_Engine/omega_engine/hermes_desktop.py +469 -0
  171. package/omega/Agentik_Engine/omega_engine/integrations/__init__.py +30 -0
  172. package/omega/Agentik_Engine/omega_engine/integrations/__pycache__/__init__.cpython-313.pyc +0 -0
  173. package/omega/Agentik_Engine/omega_engine/integrations/__pycache__/graphify.cpython-313.pyc +0 -0
  174. package/omega/Agentik_Engine/omega_engine/integrations/graphify.py +234 -0
  175. package/omega/Agentik_Engine/omega_engine/learning.py +268 -0
  176. package/omega/Agentik_Engine/omega_engine/managed_agent.py +467 -0
  177. package/omega/Agentik_Engine/omega_engine/memory.py +271 -0
  178. package/omega/Agentik_Engine/omega_engine/menu.py +1065 -0
  179. package/omega/Agentik_Engine/omega_engine/migrations/__init__.py +144 -0
  180. package/omega/Agentik_Engine/omega_engine/migrations/__pycache__/__init__.cpython-313.pyc +0 -0
  181. package/omega/Agentik_Engine/omega_engine/migrations/__pycache__/v0_14_0.cpython-313.pyc +0 -0
  182. package/omega/Agentik_Engine/omega_engine/migrations/v0_14_0.py +29 -0
  183. package/omega/Agentik_Engine/omega_engine/mission.py +16 -13
  184. package/omega/Agentik_Engine/omega_engine/plan.py +846 -0
  185. package/omega/Agentik_Engine/omega_engine/prompts.py +158 -0
  186. package/omega/Agentik_Engine/omega_engine/provider.py +161 -12
  187. package/omega/Agentik_Engine/omega_engine/prune.py +151 -0
  188. package/omega/Agentik_Engine/omega_engine/pursue.py +205 -0
  189. package/omega/Agentik_Engine/omega_engine/rag/__pycache__/__init__.cpython-313.pyc +0 -0
  190. package/omega/Agentik_Engine/omega_engine/rag/__pycache__/agentic.cpython-313.pyc +0 -0
  191. package/omega/Agentik_Engine/omega_engine/rag/__pycache__/base.cpython-313.pyc +0 -0
  192. package/omega/Agentik_Engine/omega_engine/rag/__pycache__/corrective.cpython-313.pyc +0 -0
  193. package/omega/Agentik_Engine/omega_engine/rag/__pycache__/graph.cpython-313.pyc +0 -0
  194. package/omega/Agentik_Engine/omega_engine/rag/__pycache__/hybrid.cpython-313.pyc +0 -0
  195. package/omega/Agentik_Engine/omega_engine/rag/__pycache__/multimodal.cpython-313.pyc +0 -0
  196. package/omega/Agentik_Engine/omega_engine/rag/__pycache__/router.cpython-313.pyc +0 -0
  197. package/omega/Agentik_Engine/omega_engine/router.py +28 -0
  198. package/omega/Agentik_Engine/omega_engine/skill_discovery/__init__.py +48 -0
  199. package/omega/Agentik_Engine/omega_engine/skill_discovery/__pycache__/__init__.cpython-313.pyc +0 -0
  200. package/omega/Agentik_Engine/omega_engine/skill_discovery/__pycache__/auditor.cpython-313.pyc +0 -0
  201. package/omega/Agentik_Engine/omega_engine/skill_discovery/__pycache__/finder.cpython-313.pyc +0 -0
  202. package/omega/Agentik_Engine/omega_engine/skill_discovery/__pycache__/installer.cpython-313.pyc +0 -0
  203. package/omega/Agentik_Engine/omega_engine/skill_discovery/__pycache__/marketplaces.cpython-313.pyc +0 -0
  204. package/omega/Agentik_Engine/omega_engine/skill_discovery/auditor.py +232 -0
  205. package/omega/Agentik_Engine/omega_engine/skill_discovery/finder.py +94 -0
  206. package/omega/Agentik_Engine/omega_engine/skill_discovery/installer.py +129 -0
  207. package/omega/Agentik_Engine/omega_engine/skill_discovery/marketplaces.py +80 -0
  208. package/omega/Agentik_Engine/omega_engine/skill_routing.py +388 -0
  209. package/omega/Agentik_Engine/omega_engine/smoke.py +81 -0
  210. package/omega/Agentik_Engine/omega_engine/store.py +88 -41
  211. package/omega/Agentik_Engine/omega_engine/sync.py +142 -1
  212. package/omega/Agentik_Engine/omega_engine/telegram_history.py +260 -0
  213. package/omega/Agentik_Engine/omega_engine/tmux.py +526 -0
  214. package/omega/Agentik_Engine/omega_engine/understand_anything.py +275 -0
  215. package/omega/Agentik_Engine/omega_engine/updater.py +70 -0
  216. package/omega/Agentik_Engine/omega_engine/validate.py +186 -0
  217. package/omega/Agentik_Engine/omega_engine/vault.py +342 -0
  218. package/omega/Agentik_Engine/omega_engine/webhooks.py +262 -0
  219. package/omega/Agentik_Engine/omega_engine/worker.py +526 -0
  220. package/omega/Agentik_Engine/pyproject.toml +1 -1
  221. package/omega/Agentik_Engine/tests/__pycache__/test_account.cpython-313-pytest-8.4.2.pyc +0 -0
  222. package/omega/Agentik_Engine/tests/__pycache__/test_account.cpython-313.pyc +0 -0
  223. package/omega/Agentik_Engine/tests/__pycache__/test_adversarial.cpython-313-pytest-8.4.2.pyc +0 -0
  224. package/omega/Agentik_Engine/tests/__pycache__/test_adversarial.cpython-313.pyc +0 -0
  225. package/omega/Agentik_Engine/tests/__pycache__/test_agents_envelope.cpython-313-pytest-8.4.2.pyc +0 -0
  226. package/omega/Agentik_Engine/tests/__pycache__/test_agents_envelope.cpython-313.pyc +0 -0
  227. package/omega/Agentik_Engine/tests/__pycache__/test_audit_arsenal.cpython-313-pytest-8.4.2.pyc +0 -0
  228. package/omega/Agentik_Engine/tests/__pycache__/test_audit_arsenal.cpython-313.pyc +0 -0
  229. package/omega/Agentik_Engine/tests/__pycache__/test_audits_pipeline.cpython-313-pytest-8.4.2.pyc +0 -0
  230. package/omega/Agentik_Engine/tests/__pycache__/test_audits_pipeline.cpython-313.pyc +0 -0
  231. package/omega/Agentik_Engine/tests/__pycache__/test_auto_update_and_migrations.cpython-313-pytest-8.4.2.pyc +0 -0
  232. package/omega/Agentik_Engine/tests/__pycache__/test_auto_update_and_migrations.cpython-313.pyc +0 -0
  233. package/omega/Agentik_Engine/tests/__pycache__/test_autonomous.cpython-313-pytest-8.4.2.pyc +0 -0
  234. package/omega/Agentik_Engine/tests/__pycache__/test_autonomous.cpython-313.pyc +0 -0
  235. package/omega/Agentik_Engine/tests/__pycache__/test_educators.cpython-313-pytest-8.4.2.pyc +0 -0
  236. package/omega/Agentik_Engine/tests/__pycache__/test_educators.cpython-313.pyc +0 -0
  237. package/omega/Agentik_Engine/tests/__pycache__/test_executor.cpython-313-pytest-8.4.2.pyc +0 -0
  238. package/omega/Agentik_Engine/tests/__pycache__/test_executor.cpython-313.pyc +0 -0
  239. package/omega/Agentik_Engine/tests/__pycache__/test_genesis_and_plan.cpython-313-pytest-8.4.2.pyc +0 -0
  240. package/omega/Agentik_Engine/tests/__pycache__/test_genesis_and_plan.cpython-313.pyc +0 -0
  241. package/omega/Agentik_Engine/tests/__pycache__/test_graphify.cpython-313-pytest-8.4.2.pyc +0 -0
  242. package/omega/Agentik_Engine/tests/__pycache__/test_graphify.cpython-313.pyc +0 -0
  243. package/omega/Agentik_Engine/tests/__pycache__/test_handoff.cpython-313-pytest-8.4.2.pyc +0 -0
  244. package/omega/Agentik_Engine/tests/__pycache__/test_handoff.cpython-313.pyc +0 -0
  245. package/omega/Agentik_Engine/tests/__pycache__/test_hermes_and_ua.cpython-313-pytest-8.4.2.pyc +0 -0
  246. package/omega/Agentik_Engine/tests/__pycache__/test_hermes_and_ua.cpython-313.pyc +0 -0
  247. package/omega/Agentik_Engine/tests/__pycache__/test_hermes_bootstrap_and_desktop.cpython-313-pytest-8.4.2.pyc +0 -0
  248. package/omega/Agentik_Engine/tests/__pycache__/test_hermes_bootstrap_and_desktop.cpython-313.pyc +0 -0
  249. package/omega/Agentik_Engine/tests/__pycache__/test_install_steps.cpython-313-pytest-8.4.2.pyc +0 -0
  250. package/omega/Agentik_Engine/tests/__pycache__/test_install_steps.cpython-313.pyc +0 -0
  251. package/omega/Agentik_Engine/tests/__pycache__/test_install_ux.cpython-313-pytest-8.4.2.pyc +0 -0
  252. package/omega/Agentik_Engine/tests/__pycache__/test_install_ux.cpython-313.pyc +0 -0
  253. package/omega/Agentik_Engine/tests/__pycache__/test_installer_wiring.cpython-313-pytest-8.4.2.pyc +0 -0
  254. package/omega/Agentik_Engine/tests/__pycache__/test_installer_wiring.cpython-313.pyc +0 -0
  255. package/omega/Agentik_Engine/tests/__pycache__/test_intelligence.cpython-313-pytest-8.4.2.pyc +0 -0
  256. package/omega/Agentik_Engine/tests/__pycache__/test_intelligence.cpython-313.pyc +0 -0
  257. package/omega/Agentik_Engine/tests/__pycache__/test_llm_clis_and_uninstall.cpython-313-pytest-8.4.2.pyc +0 -0
  258. package/omega/Agentik_Engine/tests/__pycache__/test_llm_clis_and_uninstall.cpython-313.pyc +0 -0
  259. package/omega/Agentik_Engine/tests/__pycache__/test_managed_agent.cpython-313-pytest-8.4.2.pyc +0 -0
  260. package/omega/Agentik_Engine/tests/__pycache__/test_managed_agent.cpython-313.pyc +0 -0
  261. package/omega/Agentik_Engine/tests/__pycache__/test_max_provider_and_menu.cpython-313-pytest-8.4.2.pyc +0 -0
  262. package/omega/Agentik_Engine/tests/__pycache__/test_max_provider_and_menu.cpython-313.pyc +0 -0
  263. package/omega/Agentik_Engine/tests/__pycache__/test_menu_coverage.cpython-313-pytest-8.4.2.pyc +0 -0
  264. package/omega/Agentik_Engine/tests/__pycache__/test_menu_coverage.cpython-313.pyc +0 -0
  265. package/omega/Agentik_Engine/tests/__pycache__/test_mission.cpython-313-pytest-8.4.2.pyc +0 -0
  266. package/omega/Agentik_Engine/tests/__pycache__/test_mission.cpython-313.pyc +0 -0
  267. package/omega/Agentik_Engine/tests/__pycache__/test_progress.cpython-313-pytest-8.4.2.pyc +0 -0
  268. package/omega/Agentik_Engine/tests/__pycache__/test_progress.cpython-313.pyc +0 -0
  269. package/omega/Agentik_Engine/tests/__pycache__/test_project.cpython-313-pytest-8.4.2.pyc +0 -0
  270. package/omega/Agentik_Engine/tests/__pycache__/test_project.cpython-313.pyc +0 -0
  271. package/omega/Agentik_Engine/tests/__pycache__/test_pursue_cadence.cpython-313-pytest-8.4.2.pyc +0 -0
  272. package/omega/Agentik_Engine/tests/__pycache__/test_pursue_cadence.cpython-313.pyc +0 -0
  273. package/omega/Agentik_Engine/tests/__pycache__/test_rag.cpython-313-pytest-8.4.2.pyc +0 -0
  274. package/omega/Agentik_Engine/tests/__pycache__/test_rag.cpython-313.pyc +0 -0
  275. package/omega/Agentik_Engine/tests/__pycache__/test_reducer.cpython-313-pytest-8.4.2.pyc +0 -0
  276. package/omega/Agentik_Engine/tests/__pycache__/test_reducer.cpython-313.pyc +0 -0
  277. package/omega/Agentik_Engine/tests/__pycache__/test_report.cpython-313-pytest-8.4.2.pyc +0 -0
  278. package/omega/Agentik_Engine/tests/__pycache__/test_report.cpython-313.pyc +0 -0
  279. package/omega/Agentik_Engine/tests/__pycache__/test_role_aliases_and_ssot.cpython-313-pytest-8.4.2.pyc +0 -0
  280. package/omega/Agentik_Engine/tests/__pycache__/test_role_aliases_and_ssot.cpython-313.pyc +0 -0
  281. package/omega/Agentik_Engine/tests/__pycache__/test_skill_discovery_and_gate.cpython-313-pytest-8.4.2.pyc +0 -0
  282. package/omega/Agentik_Engine/tests/__pycache__/test_skill_discovery_and_gate.cpython-313.pyc +0 -0
  283. package/omega/Agentik_Engine/tests/__pycache__/test_skill_power.cpython-313-pytest-8.4.2.pyc +0 -0
  284. package/omega/Agentik_Engine/tests/__pycache__/test_skill_power.cpython-313.pyc +0 -0
  285. package/omega/Agentik_Engine/tests/__pycache__/test_skill_routing.cpython-313-pytest-8.4.2.pyc +0 -0
  286. package/omega/Agentik_Engine/tests/__pycache__/test_skill_routing.cpython-313.pyc +0 -0
  287. package/omega/Agentik_Engine/tests/__pycache__/test_snapshot_partial.cpython-313-pytest-8.4.2.pyc +0 -0
  288. package/omega/Agentik_Engine/tests/__pycache__/test_snapshot_partial.cpython-313.pyc +0 -0
  289. package/omega/Agentik_Engine/tests/__pycache__/test_telegram_history.cpython-313-pytest-8.4.2.pyc +0 -0
  290. package/omega/Agentik_Engine/tests/__pycache__/test_telegram_history.cpython-313.pyc +0 -0
  291. package/omega/Agentik_Engine/tests/__pycache__/test_tmux_and_aisb_chat.cpython-313-pytest-8.4.2.pyc +0 -0
  292. package/omega/Agentik_Engine/tests/__pycache__/test_tmux_and_aisb_chat.cpython-313.pyc +0 -0
  293. package/omega/Agentik_Engine/tests/__pycache__/test_tools_and_sync.cpython-313-pytest-8.4.2.pyc +0 -0
  294. package/omega/Agentik_Engine/tests/__pycache__/test_tools_and_sync.cpython-313.pyc +0 -0
  295. package/omega/Agentik_Engine/tests/__pycache__/test_v06_features.cpython-313-pytest-8.4.2.pyc +0 -0
  296. package/omega/Agentik_Engine/tests/__pycache__/test_v06_features.cpython-313.pyc +0 -0
  297. package/omega/Agentik_Engine/tests/__pycache__/test_vault.cpython-313-pytest-8.4.2.pyc +0 -0
  298. package/omega/Agentik_Engine/tests/__pycache__/test_vault.cpython-313.pyc +0 -0
  299. package/omega/Agentik_Engine/tests/__pycache__/test_webhooks_and_readiness.cpython-313-pytest-8.4.2.pyc +0 -0
  300. package/omega/Agentik_Engine/tests/__pycache__/test_webhooks_and_readiness.cpython-313.pyc +0 -0
  301. package/omega/Agentik_Engine/tests/__pycache__/test_worker_and_cleanup.cpython-313-pytest-8.4.2.pyc +0 -0
  302. package/omega/Agentik_Engine/tests/__pycache__/test_worker_and_cleanup.cpython-313.pyc +0 -0
  303. package/omega/Agentik_Engine/tests/test_account.py +8 -3
  304. package/omega/Agentik_Engine/tests/test_adversarial.py +351 -0
  305. package/omega/Agentik_Engine/tests/test_agents_envelope.py +274 -0
  306. package/omega/Agentik_Engine/tests/test_audits_pipeline.py +348 -0
  307. package/omega/Agentik_Engine/tests/test_auto_update_and_migrations.py +394 -0
  308. package/omega/Agentik_Engine/tests/test_genesis_and_plan.py +573 -0
  309. package/omega/Agentik_Engine/tests/test_graphify.py +190 -0
  310. package/omega/Agentik_Engine/tests/test_handoff.py +311 -0
  311. package/omega/Agentik_Engine/tests/test_hermes_and_ua.py +387 -0
  312. package/omega/Agentik_Engine/tests/test_hermes_bootstrap_and_desktop.py +358 -0
  313. package/omega/Agentik_Engine/tests/test_install_steps.py +359 -0
  314. package/omega/Agentik_Engine/tests/test_install_ux.py +151 -0
  315. package/omega/Agentik_Engine/tests/test_installer_wiring.py +496 -0
  316. package/omega/Agentik_Engine/tests/test_intelligence.py +285 -0
  317. package/omega/Agentik_Engine/tests/test_llm_clis_and_uninstall.py +228 -0
  318. package/omega/Agentik_Engine/tests/test_managed_agent.py +363 -0
  319. package/omega/Agentik_Engine/tests/test_max_provider_and_menu.py +231 -0
  320. package/omega/Agentik_Engine/tests/test_menu_coverage.py +72 -0
  321. package/omega/Agentik_Engine/tests/test_pursue_cadence.py +217 -0
  322. package/omega/Agentik_Engine/tests/test_role_aliases_and_ssot.py +207 -0
  323. package/omega/Agentik_Engine/tests/test_skill_discovery_and_gate.py +337 -0
  324. package/omega/Agentik_Engine/tests/test_skill_power.py +259 -0
  325. package/omega/Agentik_Engine/tests/test_skill_routing.py +189 -0
  326. package/omega/Agentik_Engine/tests/test_telegram_history.py +209 -0
  327. package/omega/Agentik_Engine/tests/test_tmux_and_aisb_chat.py +223 -0
  328. package/omega/Agentik_Engine/tests/test_v06_features.py +370 -0
  329. package/omega/Agentik_Engine/tests/test_vault.py +173 -0
  330. package/omega/Agentik_Engine/tests/test_webhooks_and_readiness.py +277 -0
  331. package/omega/Agentik_Engine/tests/test_worker_and_cleanup.py +541 -0
  332. package/omega/Agentik_Extra/etc/secrets/.vault-key +3 -0
  333. package/omega/Agentik_Extra/etc/secrets/.vault-pub +1 -0
  334. package/omega/Agentik_Runtime/audits.db +0 -0
  335. package/omega/Agentik_SSOT/VERSION +1 -1
  336. package/omega/Agentik_SSOT/claude-plugins/claude-plugins.yaml +100 -0
  337. package/omega/Agentik_SSOT/docs/LAYERS.md +90 -0
  338. package/omega/Agentik_SSOT/docs/USER-JOURNEY.md +283 -0
  339. package/omega/Agentik_SSOT/marketplaces/design-discipline.yaml +86 -0
  340. package/omega/Agentik_SSOT/skills/a11yaudit/SKILL.md +161 -0
  341. package/omega/Agentik_SSOT/skills/apiaudit/SKILL.md +157 -0
  342. package/omega/Agentik_SSOT/skills/automationaudit/SKILL.md +161 -0
  343. package/omega/Agentik_SSOT/skills/cadence/SKILL.md +76 -0
  344. package/omega/Agentik_SSOT/skills/codeaudit/SKILL.md +153 -0
  345. package/omega/Agentik_SSOT/skills/copyaudit/SKILL.md +161 -0
  346. package/omega/Agentik_SSOT/skills/dataaudit/SKILL.md +157 -0
  347. package/omega/Agentik_SSOT/skills/debugaudit/SKILL.md +161 -0
  348. package/omega/Agentik_SSOT/skills/dispatch/SKILL.md +79 -0
  349. package/omega/Agentik_SSOT/skills/dxaudit/SKILL.md +161 -0
  350. package/omega/Agentik_SSOT/skills/featureaudit/SKILL.md +161 -0
  351. package/omega/Agentik_SSOT/skills/flowaudit/SKILL.md +165 -0
  352. package/omega/Agentik_SSOT/skills/genesis/SKILL.md +116 -0
  353. package/omega/Agentik_SSOT/skills/handoff/SKILL.md +117 -0
  354. package/omega/Agentik_SSOT/skills/logicaudit/SKILL.md +165 -0
  355. package/omega/Agentik_SSOT/skills/motionaudit/SKILL.md +165 -0
  356. package/omega/Agentik_SSOT/skills/perfaudit/SKILL.md +161 -0
  357. package/omega/Agentik_SSOT/skills/plan/SKILL.md +127 -0
  358. package/omega/Agentik_SSOT/skills/pursue/SKILL.md +68 -0
  359. package/omega/Agentik_SSOT/skills/rag-route.md +9 -0
  360. package/omega/Agentik_SSOT/skills/refontaudit/SKILL.md +165 -0
  361. package/omega/Agentik_SSOT/skills/retentionaudit/SKILL.md +165 -0
  362. package/omega/Agentik_SSOT/skills/secaudit/SKILL.md +157 -0
  363. package/omega/Agentik_SSOT/skills/seoaudit/SKILL.md +161 -0
  364. package/omega/Agentik_SSOT/skills/skill-auditor/SKILL.md +83 -0
  365. package/omega/Agentik_SSOT/skills/skill-finder/SKILL.md +116 -0
  366. package/omega/Agentik_SSOT/skills/uiuxaudit/SKILL.md +165 -0
  367. package/package.json +2 -2
@@ -63,42 +63,85 @@ CREATE INDEX IF NOT EXISTS idx_snapshots_task ON snapshots(task_id, ts DESC);
63
63
 
64
64
 
65
65
  class SQLiteStore(EventStore):
66
- """Append-only event log on SQLite (WAL). The default store for a VPS."""
66
+ """Append-only event log on SQLite (WAL). The default store for a VPS.
67
+
68
+ Thread-safety
69
+ -------------
70
+ The connection is opened with ``check_same_thread=False`` AND every
71
+ write is serialized through ``self._lock``. Background services
72
+ (AutonomousSupervisor, Telegram bot, webhook daemon) all share one
73
+ store from different threads — without this, the first cross-thread
74
+ call raises ``sqlite3.ProgrammingError`` and the supervisor dies.
75
+
76
+ Bug history: pre-v0.13 the lock was missing and a 5-thread fuzz
77
+ raised 5/5 ProgrammingErrors. Test: tests/test_store_concurrency.py.
78
+ """
67
79
 
68
80
  def __init__(self, db_path: str | Path):
81
+ import threading
69
82
  self.db_path = str(db_path)
70
83
  Path(self.db_path).parent.mkdir(parents=True, exist_ok=True)
71
- self._conn = sqlite3.connect(self.db_path, isolation_level=None)
84
+ # check_same_thread=False: we serialise via self._lock so the
85
+ # connection can be safely shared across threads.
86
+ self._conn = sqlite3.connect(
87
+ self.db_path, isolation_level=None, check_same_thread=False,
88
+ )
72
89
  self._conn.row_factory = sqlite3.Row
73
90
  self._conn.execute("PRAGMA journal_mode=WAL;")
74
91
  self._conn.execute("PRAGMA synchronous=NORMAL;")
75
92
  self._conn.executescript(_SCHEMA)
93
+ self._lock = threading.Lock()
94
+
95
+ def close(self) -> None:
96
+ """Explicitly close the SQLite connection (best-effort)."""
97
+ try:
98
+ with self._lock:
99
+ self._conn.close()
100
+ except (sqlite3.Error, AttributeError):
101
+ pass
102
+
103
+ def __del__(self) -> None:
104
+ # Best-effort cleanup — Python may have already torn things down.
105
+ try:
106
+ self.close()
107
+ except Exception: # noqa: BLE001
108
+ pass
76
109
 
77
110
  def append(self, event: Event) -> None:
78
- self._conn.execute(
79
- "INSERT INTO events (id, task_id, type, ts, payload) "
80
- "VALUES (:id, :task_id, :type, :ts, :payload)",
81
- event.to_row(),
82
- )
111
+ with self._lock:
112
+ self._conn.execute(
113
+ "INSERT INTO events (id, task_id, type, ts, payload) "
114
+ "VALUES (:id, :task_id, :type, :ts, :payload)",
115
+ event.to_row(),
116
+ )
83
117
 
84
118
  def events_for(self, task_id: str) -> list[Event]:
85
119
  # ORDER BY rowid = insertion order — the only correct order for a reducer.
86
120
  # Ordering by `ts` is unsafe: rapid emits can share a timestamp.
87
- cur = self._conn.execute(
88
- "SELECT * FROM events WHERE task_id = ? ORDER BY rowid", (task_id,)
89
- )
90
- return [Event.from_row(dict(r)) for r in cur.fetchall()]
121
+ with self._lock:
122
+ cur = self._conn.execute(
123
+ "SELECT * FROM events WHERE task_id = ? ORDER BY rowid",
124
+ (task_id,),
125
+ )
126
+ rows = cur.fetchall()
127
+ return [Event.from_row(dict(r)) for r in rows]
91
128
 
92
129
  def all_events(self, since_ts: float = 0.0) -> Iterator[Event]:
93
- cur = self._conn.execute(
94
- "SELECT * FROM events WHERE ts >= ? ORDER BY rowid", (since_ts,)
95
- )
96
- for r in cur.fetchall():
130
+ # Read all rows under the lock, then yield outside it — long-running
131
+ # consumers must not hold the write lock.
132
+ with self._lock:
133
+ cur = self._conn.execute(
134
+ "SELECT * FROM events WHERE ts >= ? ORDER BY rowid",
135
+ (since_ts,),
136
+ )
137
+ rows = cur.fetchall()
138
+ for r in rows:
97
139
  yield Event.from_row(dict(r))
98
140
 
99
141
  def task_ids(self) -> list[str]:
100
- cur = self._conn.execute("SELECT DISTINCT task_id FROM events")
101
- return [r["task_id"] for r in cur.fetchall()]
142
+ with self._lock:
143
+ cur = self._conn.execute("SELECT DISTINCT task_id FROM events")
144
+ return [r["task_id"] for r in cur.fetchall()]
102
145
 
103
146
  # --- snapshots --------------------------------------------------------
104
147
  # Snapshots are an optional optimisation. Correctness depends only on
@@ -107,11 +150,13 @@ class SQLiteStore(EventStore):
107
150
  def snapshot(self, task_id: str) -> dict | None:
108
151
  """Capture the current reduced state of a task at the latest event.
109
152
  Returns the snapshot row, or None if the task has no events."""
110
- cur = self._conn.execute(
111
- "SELECT rowid FROM events WHERE task_id = ? ORDER BY rowid DESC LIMIT 1",
112
- (task_id,),
113
- )
114
- row = cur.fetchone()
153
+ with self._lock:
154
+ cur = self._conn.execute(
155
+ "SELECT rowid FROM events WHERE task_id = ? "
156
+ "ORDER BY rowid DESC LIMIT 1",
157
+ (task_id,),
158
+ )
159
+ row = cur.fetchone()
115
160
  if not row:
116
161
  return None
117
162
  last_rowid = row[0]
@@ -120,22 +165,24 @@ class SQLiteStore(EventStore):
120
165
  events = self.events_for(task_id)
121
166
  state = reduce_task(events)
122
167
  ts = events[-1].ts
123
- self._conn.execute(
124
- "INSERT OR REPLACE INTO snapshots (task_id, state, ts, last_event_rowid) "
125
- "VALUES (?, ?, ?, ?)",
126
- (task_id, state.value, ts, last_rowid),
127
- )
168
+ with self._lock:
169
+ self._conn.execute(
170
+ "INSERT OR REPLACE INTO snapshots (task_id, state, ts, "
171
+ "last_event_rowid) VALUES (?, ?, ?, ?)",
172
+ (task_id, state.value, ts, last_rowid),
173
+ )
128
174
  return {"task_id": task_id, "state": state, "ts": ts,
129
175
  "last_event_rowid": last_rowid}
130
176
 
131
177
  def latest_snapshot(self, task_id: str) -> dict | None:
132
178
  """Latest snapshot for a task, or None."""
133
- cur = self._conn.execute(
134
- "SELECT state, ts, last_event_rowid FROM snapshots "
135
- "WHERE task_id = ? ORDER BY ts DESC LIMIT 1",
136
- (task_id,),
137
- )
138
- row = cur.fetchone()
179
+ with self._lock:
180
+ cur = self._conn.execute(
181
+ "SELECT state, ts, last_event_rowid FROM snapshots "
182
+ "WHERE task_id = ? ORDER BY ts DESC LIMIT 1",
183
+ (task_id,),
184
+ )
185
+ row = cur.fetchone()
139
186
  if not row:
140
187
  return None
141
188
  from omega_engine.task import TaskState
@@ -147,11 +194,11 @@ class SQLiteStore(EventStore):
147
194
  snap = self.latest_snapshot(task_id)
148
195
  if not snap:
149
196
  return self.events_for(task_id)
150
- cur = self._conn.execute(
151
- "SELECT * FROM events WHERE task_id = ? AND rowid > ? ORDER BY rowid",
152
- (task_id, snap["last_event_rowid"]),
153
- )
154
- return [Event.from_row(dict(r)) for r in cur.fetchall()]
155
-
156
- def close(self) -> None:
157
- self._conn.close()
197
+ with self._lock:
198
+ cur = self._conn.execute(
199
+ "SELECT * FROM events WHERE task_id = ? AND rowid > ? "
200
+ "ORDER BY rowid",
201
+ (task_id, snap["last_event_rowid"]),
202
+ )
203
+ rows = cur.fetchall()
204
+ return [Event.from_row(dict(r)) for r in rows]
@@ -97,11 +97,26 @@ class ClaudeCodeAdapter:
97
97
  out_root: Path,
98
98
  layout: str, # "skill" | "command" | "agent"
99
99
  ) -> list[str]:
100
- """Copy `src/*.md` to the native layout. Returns list of written paths."""
100
+ """Copy `src/*.md` AND `src/<name>/SKILL.md` to the native layout.
101
+
102
+ Both shapes are supported in the SSOT:
103
+ 1. Flat: ``Agentik_SSOT/skills/pursue.md``
104
+ 2. Directory: ``Agentik_SSOT/skills/pursue/SKILL.md`` (+ optional
105
+ supporting files like ``scripts/`` or ``examples/``).
106
+
107
+ Directory-based skills are the Claude Code idiom — supporting files
108
+ sit next to ``SKILL.md`` and the agent can reference them via
109
+ ``${CLAUDE_SKILL_DIR}``. We copy the whole directory verbatim so
110
+ those references resolve at the destination.
111
+
112
+ Returns the list of written paths (relative to ``out_root.parent``).
113
+ """
101
114
  if not src.is_dir():
102
115
  return []
103
116
  out_root = self._ensure(out_root)
104
117
  written: list[str] = []
118
+
119
+ # 1. flat: src/<name>.md
105
120
  for md in sorted(src.glob("*.md")):
106
121
  stem = self._stem(md)
107
122
  if layout == "skill":
@@ -111,6 +126,29 @@ class ClaudeCodeAdapter:
111
126
  dest = out_root / f"{stem}.md"
112
127
  dest.write_text(md.read_text())
113
128
  written.append(str(dest.relative_to(out_root.parent)))
129
+
130
+ # 2. directory: src/<name>/SKILL.md (+ supporting files)
131
+ if layout == "skill":
132
+ import shutil as _sh
133
+ for child in sorted(src.iterdir()):
134
+ if not child.is_dir():
135
+ continue
136
+ skill_md = child / "SKILL.md"
137
+ if not skill_md.exists():
138
+ continue
139
+ dest_dir = self._ensure(out_root / child.name)
140
+ # Copy SKILL.md plus any supporting files (scripts/, etc.)
141
+ for item in child.iterdir():
142
+ target = dest_dir / item.name
143
+ if item.is_dir():
144
+ if target.exists():
145
+ _sh.rmtree(target)
146
+ _sh.copytree(item, target)
147
+ else:
148
+ target.write_text(item.read_text())
149
+ written.append(
150
+ str((dest_dir / "SKILL.md").relative_to(out_root.parent))
151
+ )
114
152
  return written
115
153
 
116
154
  # ----- MCP config (.mcp.json) ---------------------------------------
@@ -230,6 +268,97 @@ class ClaudeCodeAdapter:
230
268
  settings_file.write_text(json.dumps(settings, indent=2) + "\n")
231
269
  return hooks_block
232
270
 
271
+ # ----- bridge to ~/.claude/ (the dir Claude Code actually reads) -----
272
+ #
273
+ # Why this exists
274
+ # ---------------
275
+ # ``project()`` writes the SSOT-derived layout into
276
+ # ``$OMEGA_HOME/Agentik_AI/providers/claude-code/.claude/`` — that tree
277
+ # stays under OmegaOS for portability (vault backup, audit trail, you
278
+ # name it). But the ``claude`` CLI on a real workstation reads skills /
279
+ # commands / agents / .mcp.json from ``~/.claude/`` (user-global) and
280
+ # ``.claude/`` (project-local).
281
+ #
282
+ # Without a bridge, the 24 SSOT skills NEVER become invokable slash
283
+ # commands. ``link_to_user_claude(home)`` is that bridge: for every
284
+ # skill we projected, we create a SYMLINK at
285
+ # ``~/.claude/skills/<id> → $OMEGA_HOME/.../skills/<id>``. This means:
286
+ # - editing the SSOT + re-running ``omega sync`` updates the
287
+ # skill in place (no duplicate copies),
288
+ # - removing the SSOT skill nukes the symlink on the next sync,
289
+ # - the operator's existing ``~/.claude/skills/<other>/`` are
290
+ # untouched (we only manage entries whose targets are inside
291
+ # ``$OMEGA_HOME``).
292
+
293
+ def link_to_user_claude(
294
+ self, omega_home: Path,
295
+ *,
296
+ user_claude: Path | None = None,
297
+ ) -> dict[str, Any]:
298
+ """Bridge the projected tree into ``~/.claude/`` via symlinks.
299
+
300
+ Returns ``{linked_skills, linked_commands, linked_agents,
301
+ removed: [stale_paths]}``. Idempotent.
302
+ """
303
+ import os as _os
304
+ user = Path(user_claude) if user_claude else Path.home() / ".claude"
305
+ target = self.target_dir(omega_home)
306
+ out: dict[str, Any] = {
307
+ "user_claude": str(user),
308
+ "linked_skills": 0,
309
+ "linked_commands": 0,
310
+ "linked_agents": 0,
311
+ "removed": [],
312
+ }
313
+ # The provider-tree target must exist first (project() was called).
314
+ if not target.is_dir():
315
+ return out
316
+
317
+ for layout in ("skills", "commands", "agents"):
318
+ src_root = target / layout
319
+ if not src_root.is_dir():
320
+ continue
321
+ dest_root = self._ensure(user / layout)
322
+
323
+ # Remove stale symlinks we used to manage. A "managed" symlink
324
+ # points anywhere inside `target`. Real dirs and symlinks owned
325
+ # by the user are NEVER touched.
326
+ for child in list(dest_root.iterdir()):
327
+ if not child.is_symlink():
328
+ continue
329
+ try:
330
+ realpath = child.resolve()
331
+ except OSError:
332
+ continue
333
+ # Only nuke our own — points inside the OmegaOS tree.
334
+ if str(realpath).startswith(str(target)) and not (src_root / child.name).exists():
335
+ try:
336
+ child.unlink()
337
+ out["removed"].append(str(child))
338
+ except OSError:
339
+ pass
340
+
341
+ for src in sorted(src_root.iterdir()):
342
+ if not src.is_dir() and not src.suffix == ".md":
343
+ continue
344
+ dest = dest_root / src.name
345
+ if dest.is_symlink():
346
+ try:
347
+ dest.unlink()
348
+ except OSError:
349
+ pass
350
+ elif dest.exists():
351
+ # Don't clobber the user's hand-written content.
352
+ continue
353
+ try:
354
+ _os.symlink(src, dest)
355
+ out[f"linked_{layout}"] += 1
356
+ except OSError:
357
+ # Some filesystems (Windows WSL crossings) refuse symlinks;
358
+ # in that case the user can re-run with --copy.
359
+ pass
360
+ return out
361
+
233
362
  # ----- entry point ---------------------------------------------------
234
363
 
235
364
  def project(self, omega_home: Path) -> dict[str, Any]:
@@ -243,6 +372,17 @@ class ClaudeCodeAdapter:
243
372
  mcp = self._project_mcp(omega_home, target)
244
373
  hooks = self._project_hooks(omega_home, target)
245
374
 
375
+ # Bridge to ~/.claude/ so the projected skills actually become
376
+ # invokable slash-commands. Toggleable via env var (off → only the
377
+ # provider tree is written; user opts in later with `omega skill link`).
378
+ link_info: dict[str, Any] = {}
379
+ import os as _os
380
+ if _os.environ.get("OMEGA_SYNC_NO_LINK") != "1":
381
+ try:
382
+ link_info = self.link_to_user_claude(omega_home)
383
+ except OSError:
384
+ link_info = {}
385
+
246
386
  return {
247
387
  "provider": self.id,
248
388
  "projected": True,
@@ -252,6 +392,7 @@ class ClaudeCodeAdapter:
252
392
  "agents_written": len(agents),
253
393
  "mcp_servers": len(mcp.get("mcpServers", {})) if isinstance(mcp, dict) else 0,
254
394
  "hooks": list(hooks.keys()),
395
+ "linked_to_user_claude": link_info,
255
396
  }
256
397
 
257
398
 
@@ -0,0 +1,260 @@
1
+ """Per-topic conversation history — fixes the "bot has no memory" bug.
2
+
3
+ When the user types in a Telegram topic, the Telegram daemon used to call
4
+ ``run_mission(intent=text)`` with ONLY the new message. The Oracle saw a
5
+ brand-new mission every turn — no idea what the user was actually talking
6
+ about. The user's reply to a follow-up question landed without context.
7
+
8
+ This module is the fix. It persists every inbound + outbound message per
9
+ topic to a SQLite table; the daemon prepends the last N exchanges to the
10
+ envelope's user message so the agent always has the conversation.
11
+
12
+ Layout
13
+ ------
14
+ ``$OMEGA_HOME/Agentik_Runtime/telegram-history.db``
15
+
16
+ ::
17
+
18
+ CREATE TABLE messages (
19
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
20
+ topic_id INTEGER NOT NULL, -- forum topic id (or 0 for DM root)
21
+ role TEXT NOT NULL, -- 'user' | 'bot'
22
+ text TEXT NOT NULL,
23
+ message_id INTEGER, -- Telegram's own message_id
24
+ timestamp INTEGER NOT NULL
25
+ );
26
+
27
+ Two indexes: one for per-topic recency, one for full-text-ish search.
28
+
29
+ Public API
30
+ ----------
31
+ ``record_inbound(home, topic_id, text, message_id=None)``
32
+ ``record_outbound(home, topic_id, text, message_id=None)``
33
+ ``recent_messages(home, topic_id, limit=20) -> list[Message]``
34
+ ``build_context_prompt(home, topic_id, new_intent, limit=10) -> str``
35
+ """
36
+ from __future__ import annotations
37
+
38
+ import os
39
+ import sqlite3
40
+ import time
41
+ from dataclasses import dataclass, field
42
+ from pathlib import Path
43
+ from typing import Iterable
44
+
45
+
46
+ @dataclass
47
+ class Message:
48
+ id: int
49
+ topic_id: int
50
+ role: str # "user" | "bot"
51
+ text: str
52
+ message_id: int | None
53
+ timestamp: int
54
+
55
+
56
+ def _db_path(omega_home: str | Path) -> Path:
57
+ home = Path(omega_home)
58
+ runtime = home / "Agentik_Runtime"
59
+ runtime.mkdir(parents=True, exist_ok=True)
60
+ return runtime / "telegram-history.db"
61
+
62
+
63
+ def _connect(omega_home: str | Path) -> sqlite3.Connection:
64
+ conn = sqlite3.connect(str(_db_path(omega_home)))
65
+ conn.row_factory = sqlite3.Row
66
+ conn.execute("PRAGMA journal_mode=WAL")
67
+ conn.execute("""
68
+ CREATE TABLE IF NOT EXISTS messages (
69
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
70
+ topic_id INTEGER NOT NULL,
71
+ role TEXT NOT NULL CHECK(role IN ('user', 'bot')),
72
+ text TEXT NOT NULL,
73
+ message_id INTEGER,
74
+ timestamp INTEGER NOT NULL
75
+ )
76
+ """)
77
+ conn.execute("""
78
+ CREATE INDEX IF NOT EXISTS idx_messages_topic_time
79
+ ON messages(topic_id, timestamp DESC)
80
+ """)
81
+ return conn
82
+
83
+
84
+ def _record(
85
+ omega_home: str | Path,
86
+ *,
87
+ topic_id: int,
88
+ role: str,
89
+ text: str,
90
+ message_id: int | None,
91
+ ) -> int:
92
+ """Persist one message. Returns the rowid."""
93
+ if role not in ("user", "bot"):
94
+ raise ValueError(f"role must be 'user' or 'bot', got {role!r}")
95
+ conn = _connect(omega_home)
96
+ try:
97
+ cur = conn.execute(
98
+ "INSERT INTO messages (topic_id, role, text, message_id, timestamp) "
99
+ "VALUES (?, ?, ?, ?, ?)",
100
+ (int(topic_id), role, text, message_id, int(time.time())),
101
+ )
102
+ conn.commit()
103
+ return int(cur.lastrowid)
104
+ finally:
105
+ conn.close()
106
+
107
+
108
+ def record_inbound(
109
+ omega_home: str | Path,
110
+ topic_id: int,
111
+ text: str,
112
+ *,
113
+ message_id: int | None = None,
114
+ ) -> int:
115
+ """The user just sent this in the topic. Persist it."""
116
+ return _record(omega_home, topic_id=topic_id, role="user",
117
+ text=text, message_id=message_id)
118
+
119
+
120
+ def record_outbound(
121
+ omega_home: str | Path,
122
+ topic_id: int,
123
+ text: str,
124
+ *,
125
+ message_id: int | None = None,
126
+ ) -> int:
127
+ """The bot just posted this. Persist it so the next turn has context."""
128
+ return _record(omega_home, topic_id=topic_id, role="bot",
129
+ text=text, message_id=message_id)
130
+
131
+
132
+ def recent_messages(
133
+ omega_home: str | Path,
134
+ topic_id: int,
135
+ *,
136
+ limit: int = 20,
137
+ ) -> list[Message]:
138
+ """Return the last ``limit`` messages for this topic, oldest first.
139
+
140
+ The query selects by timestamp DESC then reverses — gives us
141
+ chronological order with a hard cap.
142
+ """
143
+ conn = _connect(omega_home)
144
+ try:
145
+ rows = conn.execute(
146
+ "SELECT * FROM messages WHERE topic_id = ? "
147
+ "ORDER BY timestamp DESC, id DESC LIMIT ?",
148
+ (int(topic_id), int(limit)),
149
+ ).fetchall()
150
+ finally:
151
+ conn.close()
152
+ return [
153
+ Message(
154
+ id=int(r["id"]),
155
+ topic_id=int(r["topic_id"]),
156
+ role=str(r["role"]),
157
+ text=str(r["text"]),
158
+ message_id=(int(r["message_id"])
159
+ if r["message_id"] is not None else None),
160
+ timestamp=int(r["timestamp"]),
161
+ )
162
+ for r in reversed(rows)
163
+ ]
164
+
165
+
166
+ def build_context_prompt(
167
+ omega_home: str | Path,
168
+ topic_id: int,
169
+ new_intent: str,
170
+ *,
171
+ limit: int = 10,
172
+ ) -> str:
173
+ """Compose a context-aware intent for ``run_mission``.
174
+
175
+ Format::
176
+
177
+ [Conversation history in topic <id>]
178
+ user (10 min ago): previous message
179
+ bot (8 min ago): previous reply
180
+ user (just now): ${new_intent}
181
+
182
+ Respond to the user's latest message — the messages above are
183
+ the conversation so far in this topic; keep your answer
184
+ consistent with them.
185
+
186
+ If there's no prior history, returns ``new_intent`` unchanged so a
187
+ cold conversation behaves as before.
188
+ """
189
+ history = recent_messages(omega_home, topic_id, limit=limit)
190
+ if not history:
191
+ return new_intent
192
+
193
+ now = int(time.time())
194
+ lines: list[str] = [
195
+ f"[Conversation history in topic {topic_id}]"
196
+ ]
197
+ for msg in history:
198
+ delta = now - msg.timestamp
199
+ when = _humanise_age(delta)
200
+ lines.append(f" {msg.role} ({when}): {msg.text}")
201
+
202
+ lines.append("")
203
+ lines.append(f"user (just now): {new_intent}")
204
+ lines.append("")
205
+ lines.append(
206
+ "Respond to the user's latest message — the messages above are "
207
+ "the conversation so far in this topic; keep your answer "
208
+ "consistent with them."
209
+ )
210
+ return "\n".join(lines)
211
+
212
+
213
+ def _humanise_age(seconds: int) -> str:
214
+ """Format an age in seconds as a short human string."""
215
+ if seconds < 60:
216
+ return f"{seconds}s ago"
217
+ if seconds < 3600:
218
+ return f"{seconds // 60}m ago"
219
+ if seconds < 86400:
220
+ return f"{seconds // 3600}h ago"
221
+ return f"{seconds // 86400}d ago"
222
+
223
+
224
+ def prune(
225
+ omega_home: str | Path,
226
+ *,
227
+ older_than_days: int = 90,
228
+ ) -> int:
229
+ """Drop messages older than ``older_than_days``. Returns rows removed."""
230
+ cutoff = int(time.time()) - older_than_days * 86400
231
+ conn = _connect(omega_home)
232
+ try:
233
+ cur = conn.execute(
234
+ "DELETE FROM messages WHERE timestamp < ?", (cutoff,)
235
+ )
236
+ conn.commit()
237
+ return int(cur.rowcount)
238
+ finally:
239
+ conn.close()
240
+
241
+
242
+ def topic_stats(omega_home: str | Path) -> list[dict]:
243
+ """For the doctor: a one-row-per-topic summary."""
244
+ conn = _connect(omega_home)
245
+ try:
246
+ rows = conn.execute(
247
+ "SELECT topic_id, COUNT(*) AS n_msgs, "
248
+ " MAX(timestamp) AS last_seen "
249
+ "FROM messages GROUP BY topic_id ORDER BY last_seen DESC"
250
+ ).fetchall()
251
+ finally:
252
+ conn.close()
253
+ return [
254
+ {
255
+ "topic_id": int(r["topic_id"]),
256
+ "messages": int(r["n_msgs"]),
257
+ "last_seen": int(r["last_seen"]),
258
+ }
259
+ for r in rows
260
+ ]