@agentikos/omega-os 0.1.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 (379) hide show
  1. package/README.md +56 -14
  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 +1000 -26
  10. package/bootstrap/manifest.example.yaml +93 -2
  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/COMPLETION-PLAN.md +48 -0
  48. package/docs/GAP-ANALYSIS.md +214 -0
  49. package/docs/INSTALL.md +47 -9
  50. package/docs/MCP-AND-PLUGINS.md +31 -4
  51. package/docs/SIMULATION.md +171 -0
  52. package/docs/simulate.sh +211 -0
  53. package/install.sh +164 -17
  54. package/omega/Agentik_Engine/README.md +27 -10
  55. package/omega/Agentik_Engine/omega_engine/__init__.py +212 -2
  56. package/omega/Agentik_Engine/omega_engine/__pycache__/__init__.cpython-313.pyc +0 -0
  57. package/omega/Agentik_Engine/omega_engine/__pycache__/account.cpython-313.pyc +0 -0
  58. package/omega/Agentik_Engine/omega_engine/__pycache__/agent_messages.cpython-313.pyc +0 -0
  59. package/omega/Agentik_Engine/omega_engine/__pycache__/aisb_chat.cpython-313.pyc +0 -0
  60. package/omega/Agentik_Engine/omega_engine/__pycache__/audit_diff.cpython-313.pyc +0 -0
  61. package/omega/Agentik_Engine/omega_engine/__pycache__/audit_gate.cpython-313.pyc +0 -0
  62. package/omega/Agentik_Engine/omega_engine/__pycache__/auto_update.cpython-313.pyc +0 -0
  63. package/omega/Agentik_Engine/omega_engine/__pycache__/autonomous.cpython-313.pyc +0 -0
  64. package/omega/Agentik_Engine/omega_engine/__pycache__/backup.cpython-313.pyc +0 -0
  65. package/omega/Agentik_Engine/omega_engine/__pycache__/cadence.cpython-313.pyc +0 -0
  66. package/omega/Agentik_Engine/omega_engine/__pycache__/classifier.cpython-313.pyc +0 -0
  67. package/omega/Agentik_Engine/omega_engine/__pycache__/cleanup.cpython-313.pyc +0 -0
  68. package/omega/Agentik_Engine/omega_engine/__pycache__/cli.cpython-313.pyc +0 -0
  69. package/omega/Agentik_Engine/omega_engine/__pycache__/completions.cpython-313.pyc +0 -0
  70. package/omega/Agentik_Engine/omega_engine/__pycache__/costs.cpython-313.pyc +0 -0
  71. package/omega/Agentik_Engine/omega_engine/__pycache__/done_signal.cpython-313.pyc +0 -0
  72. package/omega/Agentik_Engine/omega_engine/__pycache__/envelope.cpython-313.pyc +0 -0
  73. package/omega/Agentik_Engine/omega_engine/__pycache__/executor.cpython-313.pyc +0 -0
  74. package/omega/Agentik_Engine/omega_engine/__pycache__/handoff.cpython-313.pyc +0 -0
  75. package/omega/Agentik_Engine/omega_engine/__pycache__/hermes.cpython-313.pyc +0 -0
  76. package/omega/Agentik_Engine/omega_engine/__pycache__/hermes_bootstrap.cpython-313.pyc +0 -0
  77. package/omega/Agentik_Engine/omega_engine/__pycache__/hermes_desktop.cpython-313.pyc +0 -0
  78. package/omega/Agentik_Engine/omega_engine/__pycache__/learning.cpython-313.pyc +0 -0
  79. package/omega/Agentik_Engine/omega_engine/__pycache__/managed_agent.cpython-313.pyc +0 -0
  80. package/omega/Agentik_Engine/omega_engine/__pycache__/memory.cpython-313.pyc +0 -0
  81. package/omega/Agentik_Engine/omega_engine/__pycache__/menu.cpython-313.pyc +0 -0
  82. package/omega/Agentik_Engine/omega_engine/__pycache__/mission.cpython-313.pyc +0 -0
  83. package/omega/Agentik_Engine/omega_engine/__pycache__/plan.cpython-313.pyc +0 -0
  84. package/omega/Agentik_Engine/omega_engine/__pycache__/project.cpython-313.pyc +0 -0
  85. package/omega/Agentik_Engine/omega_engine/__pycache__/prompts.cpython-313.pyc +0 -0
  86. package/omega/Agentik_Engine/omega_engine/__pycache__/provider.cpython-313.pyc +0 -0
  87. package/omega/Agentik_Engine/omega_engine/__pycache__/prune.cpython-313.pyc +0 -0
  88. package/omega/Agentik_Engine/omega_engine/__pycache__/pursue.cpython-313.pyc +0 -0
  89. package/omega/Agentik_Engine/omega_engine/__pycache__/reducer.cpython-313.pyc +0 -0
  90. package/omega/Agentik_Engine/omega_engine/__pycache__/router.cpython-313.pyc +0 -0
  91. package/omega/Agentik_Engine/omega_engine/__pycache__/skill_routing.cpython-313.pyc +0 -0
  92. package/omega/Agentik_Engine/omega_engine/__pycache__/smoke.cpython-313.pyc +0 -0
  93. package/omega/Agentik_Engine/omega_engine/__pycache__/store.cpython-313.pyc +0 -0
  94. package/omega/Agentik_Engine/omega_engine/__pycache__/sync.cpython-313.pyc +0 -0
  95. package/omega/Agentik_Engine/omega_engine/__pycache__/telegram_history.cpython-313.pyc +0 -0
  96. package/omega/Agentik_Engine/omega_engine/__pycache__/tmux.cpython-313.pyc +0 -0
  97. package/omega/Agentik_Engine/omega_engine/__pycache__/tools.cpython-313.pyc +0 -0
  98. package/omega/Agentik_Engine/omega_engine/__pycache__/understand_anything.cpython-313.pyc +0 -0
  99. package/omega/Agentik_Engine/omega_engine/__pycache__/updater.cpython-313.pyc +0 -0
  100. package/omega/Agentik_Engine/omega_engine/__pycache__/validate.cpython-313.pyc +0 -0
  101. package/omega/Agentik_Engine/omega_engine/__pycache__/vault.cpython-313.pyc +0 -0
  102. package/omega/Agentik_Engine/omega_engine/__pycache__/webhooks.cpython-313.pyc +0 -0
  103. package/omega/Agentik_Engine/omega_engine/__pycache__/worker.cpython-313.pyc +0 -0
  104. package/omega/Agentik_Engine/omega_engine/account.py +502 -0
  105. package/omega/Agentik_Engine/omega_engine/agent_messages.py +167 -0
  106. package/omega/Agentik_Engine/omega_engine/aisb_chat.py +128 -0
  107. package/omega/Agentik_Engine/omega_engine/audit_diff.py +99 -0
  108. package/omega/Agentik_Engine/omega_engine/audit_gate.py +149 -0
  109. package/omega/Agentik_Engine/omega_engine/audits/__init__.py +60 -0
  110. package/omega/Agentik_Engine/omega_engine/audits/__pycache__/__init__.cpython-313.pyc +0 -0
  111. package/omega/Agentik_Engine/omega_engine/audits/__pycache__/batcher.cpython-313.pyc +0 -0
  112. package/omega/Agentik_Engine/omega_engine/audits/__pycache__/dispatcher.cpython-313.pyc +0 -0
  113. package/omega/Agentik_Engine/omega_engine/audits/__pycache__/generator.cpython-313.pyc +0 -0
  114. package/omega/Agentik_Engine/omega_engine/audits/__pycache__/history.cpython-313.pyc +0 -0
  115. package/omega/Agentik_Engine/omega_engine/audits/__pycache__/pipeline.cpython-313.pyc +0 -0
  116. package/omega/Agentik_Engine/omega_engine/audits/batcher.py +218 -0
  117. package/omega/Agentik_Engine/omega_engine/audits/dispatcher.py +92 -0
  118. package/omega/Agentik_Engine/omega_engine/audits/generator.py +234 -0
  119. package/omega/Agentik_Engine/omega_engine/audits/history.py +168 -0
  120. package/omega/Agentik_Engine/omega_engine/audits/pipeline.py +198 -0
  121. package/omega/Agentik_Engine/omega_engine/auto_update.py +339 -0
  122. package/omega/Agentik_Engine/omega_engine/autonomous.py +538 -0
  123. package/omega/Agentik_Engine/omega_engine/backup.py +215 -0
  124. package/omega/Agentik_Engine/omega_engine/cadence.py +158 -0
  125. package/omega/Agentik_Engine/omega_engine/classifier.py +215 -0
  126. package/omega/Agentik_Engine/omega_engine/cleanup.py +673 -0
  127. package/omega/Agentik_Engine/omega_engine/cli.py +4564 -56
  128. package/omega/Agentik_Engine/omega_engine/completions.py +260 -0
  129. package/omega/Agentik_Engine/omega_engine/costs.py +100 -0
  130. package/omega/Agentik_Engine/omega_engine/daemons/__init__.py +14 -0
  131. package/omega/Agentik_Engine/omega_engine/daemons/__pycache__/__init__.cpython-313.pyc +0 -0
  132. package/omega/Agentik_Engine/omega_engine/daemons/__pycache__/autonomous.cpython-313.pyc +0 -0
  133. package/omega/Agentik_Engine/omega_engine/daemons/__pycache__/engine.cpython-313.pyc +0 -0
  134. package/omega/Agentik_Engine/omega_engine/daemons/__pycache__/telegram.cpython-313.pyc +0 -0
  135. package/omega/Agentik_Engine/omega_engine/daemons/autonomous.py +56 -0
  136. package/omega/Agentik_Engine/omega_engine/daemons/engine.py +236 -0
  137. package/omega/Agentik_Engine/omega_engine/daemons/telegram.py +315 -0
  138. package/omega/Agentik_Engine/omega_engine/done_signal.py +154 -0
  139. package/omega/Agentik_Engine/omega_engine/educators/__init__.py +51 -0
  140. package/omega/Agentik_Engine/omega_engine/educators/__pycache__/__init__.cpython-313.pyc +0 -0
  141. package/omega/Agentik_Engine/omega_engine/educators/__pycache__/artifact.cpython-313.pyc +0 -0
  142. package/omega/Agentik_Engine/omega_engine/educators/__pycache__/automation.cpython-313.pyc +0 -0
  143. package/omega/Agentik_Engine/omega_engine/educators/__pycache__/base.cpython-313.pyc +0 -0
  144. package/omega/Agentik_Engine/omega_engine/educators/__pycache__/claudecode.cpython-313.pyc +0 -0
  145. package/omega/Agentik_Engine/omega_engine/educators/__pycache__/connection.cpython-313.pyc +0 -0
  146. package/omega/Agentik_Engine/omega_engine/educators/__pycache__/coworker.cpython-313.pyc +0 -0
  147. package/omega/Agentik_Engine/omega_engine/educators/__pycache__/loop.cpython-313.pyc +0 -0
  148. package/omega/Agentik_Engine/omega_engine/educators/__pycache__/prompt.cpython-313.pyc +0 -0
  149. package/omega/Agentik_Engine/omega_engine/educators/__pycache__/skill.cpython-313.pyc +0 -0
  150. package/omega/Agentik_Engine/omega_engine/educators/artifact.py +65 -0
  151. package/omega/Agentik_Engine/omega_engine/educators/automation.py +76 -0
  152. package/omega/Agentik_Engine/omega_engine/educators/base.py +327 -0
  153. package/omega/Agentik_Engine/omega_engine/educators/claudecode.py +71 -0
  154. package/omega/Agentik_Engine/omega_engine/educators/connection.py +75 -0
  155. package/omega/Agentik_Engine/omega_engine/educators/coworker.py +68 -0
  156. package/omega/Agentik_Engine/omega_engine/educators/loop.py +82 -0
  157. package/omega/Agentik_Engine/omega_engine/educators/prompt.py +68 -0
  158. package/omega/Agentik_Engine/omega_engine/educators/skill.py +69 -0
  159. package/omega/Agentik_Engine/omega_engine/envelope.py +219 -0
  160. package/omega/Agentik_Engine/omega_engine/executor.py +195 -16
  161. package/omega/Agentik_Engine/omega_engine/genesis/__init__.py +134 -0
  162. package/omega/Agentik_Engine/omega_engine/genesis/__pycache__/__init__.cpython-313.pyc +0 -0
  163. package/omega/Agentik_Engine/omega_engine/genesis/__pycache__/orchestrator.cpython-313.pyc +0 -0
  164. package/omega/Agentik_Engine/omega_engine/genesis/__pycache__/phases.cpython-313.pyc +0 -0
  165. package/omega/Agentik_Engine/omega_engine/genesis/__pycache__/stack.cpython-313.pyc +0 -0
  166. package/omega/Agentik_Engine/omega_engine/genesis/__pycache__/state.cpython-313.pyc +0 -0
  167. package/omega/Agentik_Engine/omega_engine/genesis/orchestrator.py +262 -0
  168. package/omega/Agentik_Engine/omega_engine/genesis/phases.py +950 -0
  169. package/omega/Agentik_Engine/omega_engine/genesis/stack.py +324 -0
  170. package/omega/Agentik_Engine/omega_engine/genesis/state.py +353 -0
  171. package/omega/Agentik_Engine/omega_engine/handoff.py +459 -0
  172. package/omega/Agentik_Engine/omega_engine/hermes.py +426 -0
  173. package/omega/Agentik_Engine/omega_engine/hermes_bootstrap.py +382 -0
  174. package/omega/Agentik_Engine/omega_engine/hermes_desktop.py +469 -0
  175. package/omega/Agentik_Engine/omega_engine/integrations/__init__.py +30 -0
  176. package/omega/Agentik_Engine/omega_engine/integrations/__pycache__/__init__.cpython-313.pyc +0 -0
  177. package/omega/Agentik_Engine/omega_engine/integrations/__pycache__/graphify.cpython-313.pyc +0 -0
  178. package/omega/Agentik_Engine/omega_engine/integrations/graphify.py +234 -0
  179. package/omega/Agentik_Engine/omega_engine/learning.py +268 -0
  180. package/omega/Agentik_Engine/omega_engine/managed_agent.py +467 -0
  181. package/omega/Agentik_Engine/omega_engine/memory.py +271 -0
  182. package/omega/Agentik_Engine/omega_engine/menu.py +1065 -0
  183. package/omega/Agentik_Engine/omega_engine/migrations/__init__.py +144 -0
  184. package/omega/Agentik_Engine/omega_engine/migrations/__pycache__/__init__.cpython-313.pyc +0 -0
  185. package/omega/Agentik_Engine/omega_engine/migrations/__pycache__/v0_14_0.cpython-313.pyc +0 -0
  186. package/omega/Agentik_Engine/omega_engine/migrations/v0_14_0.py +29 -0
  187. package/omega/Agentik_Engine/omega_engine/mission.py +29 -14
  188. package/omega/Agentik_Engine/omega_engine/plan.py +846 -0
  189. package/omega/Agentik_Engine/omega_engine/prompts.py +158 -0
  190. package/omega/Agentik_Engine/omega_engine/provider.py +408 -13
  191. package/omega/Agentik_Engine/omega_engine/prune.py +151 -0
  192. package/omega/Agentik_Engine/omega_engine/pursue.py +205 -0
  193. package/omega/Agentik_Engine/omega_engine/rag/__init__.py +21 -0
  194. package/omega/Agentik_Engine/omega_engine/rag/__pycache__/__init__.cpython-313.pyc +0 -0
  195. package/omega/Agentik_Engine/omega_engine/rag/__pycache__/agentic.cpython-313.pyc +0 -0
  196. package/omega/Agentik_Engine/omega_engine/rag/__pycache__/base.cpython-313.pyc +0 -0
  197. package/omega/Agentik_Engine/omega_engine/rag/__pycache__/corrective.cpython-313.pyc +0 -0
  198. package/omega/Agentik_Engine/omega_engine/rag/__pycache__/graph.cpython-313.pyc +0 -0
  199. package/omega/Agentik_Engine/omega_engine/rag/__pycache__/hybrid.cpython-313.pyc +0 -0
  200. package/omega/Agentik_Engine/omega_engine/rag/__pycache__/multimodal.cpython-313.pyc +0 -0
  201. package/omega/Agentik_Engine/omega_engine/rag/__pycache__/router.cpython-313.pyc +0 -0
  202. package/omega/Agentik_Engine/omega_engine/rag/agentic.py +83 -0
  203. package/omega/Agentik_Engine/omega_engine/rag/base.py +42 -0
  204. package/omega/Agentik_Engine/omega_engine/rag/corrective.py +119 -0
  205. package/omega/Agentik_Engine/omega_engine/rag/graph.py +169 -0
  206. package/omega/Agentik_Engine/omega_engine/rag/hybrid.py +205 -0
  207. package/omega/Agentik_Engine/omega_engine/rag/multimodal.py +136 -0
  208. package/omega/Agentik_Engine/omega_engine/rag/router.py +110 -0
  209. package/omega/Agentik_Engine/omega_engine/reducer.py +21 -3
  210. package/omega/Agentik_Engine/omega_engine/router.py +28 -0
  211. package/omega/Agentik_Engine/omega_engine/skill_discovery/__init__.py +48 -0
  212. package/omega/Agentik_Engine/omega_engine/skill_discovery/__pycache__/__init__.cpython-313.pyc +0 -0
  213. package/omega/Agentik_Engine/omega_engine/skill_discovery/__pycache__/auditor.cpython-313.pyc +0 -0
  214. package/omega/Agentik_Engine/omega_engine/skill_discovery/__pycache__/finder.cpython-313.pyc +0 -0
  215. package/omega/Agentik_Engine/omega_engine/skill_discovery/__pycache__/installer.cpython-313.pyc +0 -0
  216. package/omega/Agentik_Engine/omega_engine/skill_discovery/__pycache__/marketplaces.cpython-313.pyc +0 -0
  217. package/omega/Agentik_Engine/omega_engine/skill_discovery/auditor.py +232 -0
  218. package/omega/Agentik_Engine/omega_engine/skill_discovery/finder.py +94 -0
  219. package/omega/Agentik_Engine/omega_engine/skill_discovery/installer.py +129 -0
  220. package/omega/Agentik_Engine/omega_engine/skill_discovery/marketplaces.py +80 -0
  221. package/omega/Agentik_Engine/omega_engine/skill_routing.py +388 -0
  222. package/omega/Agentik_Engine/omega_engine/smoke.py +81 -0
  223. package/omega/Agentik_Engine/omega_engine/store.py +132 -25
  224. package/omega/Agentik_Engine/omega_engine/sync.py +445 -0
  225. package/omega/Agentik_Engine/omega_engine/telegram_history.py +260 -0
  226. package/omega/Agentik_Engine/omega_engine/tmux.py +526 -0
  227. package/omega/Agentik_Engine/omega_engine/tools.py +272 -0
  228. package/omega/Agentik_Engine/omega_engine/understand_anything.py +275 -0
  229. package/omega/Agentik_Engine/omega_engine/updater.py +70 -0
  230. package/omega/Agentik_Engine/omega_engine/validate.py +186 -0
  231. package/omega/Agentik_Engine/omega_engine/vault.py +342 -0
  232. package/omega/Agentik_Engine/omega_engine/webhooks.py +262 -0
  233. package/omega/Agentik_Engine/omega_engine/worker.py +526 -0
  234. package/omega/Agentik_Engine/pyproject.toml +1 -1
  235. package/omega/Agentik_Engine/tests/__pycache__/test_account.cpython-313-pytest-8.4.2.pyc +0 -0
  236. package/omega/Agentik_Engine/tests/__pycache__/test_account.cpython-313.pyc +0 -0
  237. package/omega/Agentik_Engine/tests/__pycache__/test_adversarial.cpython-313-pytest-8.4.2.pyc +0 -0
  238. package/omega/Agentik_Engine/tests/__pycache__/test_adversarial.cpython-313.pyc +0 -0
  239. package/omega/Agentik_Engine/tests/__pycache__/test_agents_envelope.cpython-313-pytest-8.4.2.pyc +0 -0
  240. package/omega/Agentik_Engine/tests/__pycache__/test_agents_envelope.cpython-313.pyc +0 -0
  241. package/omega/Agentik_Engine/tests/__pycache__/test_audit_arsenal.cpython-313-pytest-8.4.2.pyc +0 -0
  242. package/omega/Agentik_Engine/tests/__pycache__/test_audits_pipeline.cpython-313-pytest-8.4.2.pyc +0 -0
  243. package/omega/Agentik_Engine/tests/__pycache__/test_audits_pipeline.cpython-313.pyc +0 -0
  244. package/omega/Agentik_Engine/tests/__pycache__/test_auto_update_and_migrations.cpython-313-pytest-8.4.2.pyc +0 -0
  245. package/omega/Agentik_Engine/tests/__pycache__/test_auto_update_and_migrations.cpython-313.pyc +0 -0
  246. package/omega/Agentik_Engine/tests/__pycache__/test_autonomous.cpython-313-pytest-8.4.2.pyc +0 -0
  247. package/omega/Agentik_Engine/tests/__pycache__/test_autonomous.cpython-313.pyc +0 -0
  248. package/omega/Agentik_Engine/tests/__pycache__/test_educators.cpython-313-pytest-8.4.2.pyc +0 -0
  249. package/omega/Agentik_Engine/tests/__pycache__/test_educators.cpython-313.pyc +0 -0
  250. package/omega/Agentik_Engine/tests/__pycache__/test_executor.cpython-313-pytest-8.4.2.pyc +0 -0
  251. package/omega/Agentik_Engine/tests/__pycache__/test_genesis_and_plan.cpython-313-pytest-8.4.2.pyc +0 -0
  252. package/omega/Agentik_Engine/tests/__pycache__/test_genesis_and_plan.cpython-313.pyc +0 -0
  253. package/omega/Agentik_Engine/tests/__pycache__/test_graphify.cpython-313-pytest-8.4.2.pyc +0 -0
  254. package/omega/Agentik_Engine/tests/__pycache__/test_graphify.cpython-313.pyc +0 -0
  255. package/omega/Agentik_Engine/tests/__pycache__/test_handoff.cpython-313-pytest-8.4.2.pyc +0 -0
  256. package/omega/Agentik_Engine/tests/__pycache__/test_handoff.cpython-313.pyc +0 -0
  257. package/omega/Agentik_Engine/tests/__pycache__/test_hermes_and_ua.cpython-313-pytest-8.4.2.pyc +0 -0
  258. package/omega/Agentik_Engine/tests/__pycache__/test_hermes_and_ua.cpython-313.pyc +0 -0
  259. package/omega/Agentik_Engine/tests/__pycache__/test_hermes_bootstrap_and_desktop.cpython-313-pytest-8.4.2.pyc +0 -0
  260. package/omega/Agentik_Engine/tests/__pycache__/test_hermes_bootstrap_and_desktop.cpython-313.pyc +0 -0
  261. package/omega/Agentik_Engine/tests/__pycache__/test_install_steps.cpython-313-pytest-8.4.2.pyc +0 -0
  262. package/omega/Agentik_Engine/tests/__pycache__/test_install_steps.cpython-313.pyc +0 -0
  263. package/omega/Agentik_Engine/tests/__pycache__/test_install_ux.cpython-313-pytest-8.4.2.pyc +0 -0
  264. package/omega/Agentik_Engine/tests/__pycache__/test_install_ux.cpython-313.pyc +0 -0
  265. package/omega/Agentik_Engine/tests/__pycache__/test_installer_wiring.cpython-313-pytest-8.4.2.pyc +0 -0
  266. package/omega/Agentik_Engine/tests/__pycache__/test_installer_wiring.cpython-313.pyc +0 -0
  267. package/omega/Agentik_Engine/tests/__pycache__/test_intelligence.cpython-313-pytest-8.4.2.pyc +0 -0
  268. package/omega/Agentik_Engine/tests/__pycache__/test_intelligence.cpython-313.pyc +0 -0
  269. package/omega/Agentik_Engine/tests/__pycache__/test_llm_clis_and_uninstall.cpython-313-pytest-8.4.2.pyc +0 -0
  270. package/omega/Agentik_Engine/tests/__pycache__/test_llm_clis_and_uninstall.cpython-313.pyc +0 -0
  271. package/omega/Agentik_Engine/tests/__pycache__/test_managed_agent.cpython-313-pytest-8.4.2.pyc +0 -0
  272. package/omega/Agentik_Engine/tests/__pycache__/test_managed_agent.cpython-313.pyc +0 -0
  273. package/omega/Agentik_Engine/tests/__pycache__/test_max_provider_and_menu.cpython-313-pytest-8.4.2.pyc +0 -0
  274. package/omega/Agentik_Engine/tests/__pycache__/test_max_provider_and_menu.cpython-313.pyc +0 -0
  275. package/omega/Agentik_Engine/tests/__pycache__/test_menu_coverage.cpython-313-pytest-8.4.2.pyc +0 -0
  276. package/omega/Agentik_Engine/tests/__pycache__/test_menu_coverage.cpython-313.pyc +0 -0
  277. package/omega/Agentik_Engine/tests/__pycache__/test_mission.cpython-313-pytest-8.4.2.pyc +0 -0
  278. package/omega/Agentik_Engine/tests/__pycache__/test_progress.cpython-313-pytest-8.4.2.pyc +0 -0
  279. package/omega/Agentik_Engine/tests/__pycache__/test_project.cpython-313-pytest-8.4.2.pyc +0 -0
  280. package/omega/Agentik_Engine/tests/__pycache__/test_pursue_cadence.cpython-313-pytest-8.4.2.pyc +0 -0
  281. package/omega/Agentik_Engine/tests/__pycache__/test_pursue_cadence.cpython-313.pyc +0 -0
  282. package/omega/Agentik_Engine/tests/__pycache__/test_rag.cpython-313-pytest-8.4.2.pyc +0 -0
  283. package/omega/Agentik_Engine/tests/__pycache__/test_rag.cpython-313.pyc +0 -0
  284. package/omega/Agentik_Engine/tests/__pycache__/test_reducer.cpython-313-pytest-8.4.2.pyc +0 -0
  285. package/omega/Agentik_Engine/tests/__pycache__/test_report.cpython-313-pytest-8.4.2.pyc +0 -0
  286. package/omega/Agentik_Engine/tests/__pycache__/test_role_aliases_and_ssot.cpython-313-pytest-8.4.2.pyc +0 -0
  287. package/omega/Agentik_Engine/tests/__pycache__/test_role_aliases_and_ssot.cpython-313.pyc +0 -0
  288. package/omega/Agentik_Engine/tests/__pycache__/test_skill_discovery_and_gate.cpython-313-pytest-8.4.2.pyc +0 -0
  289. package/omega/Agentik_Engine/tests/__pycache__/test_skill_discovery_and_gate.cpython-313.pyc +0 -0
  290. package/omega/Agentik_Engine/tests/__pycache__/test_skill_power.cpython-313-pytest-8.4.2.pyc +0 -0
  291. package/omega/Agentik_Engine/tests/__pycache__/test_skill_power.cpython-313.pyc +0 -0
  292. package/omega/Agentik_Engine/tests/__pycache__/test_skill_routing.cpython-313-pytest-8.4.2.pyc +0 -0
  293. package/omega/Agentik_Engine/tests/__pycache__/test_skill_routing.cpython-313.pyc +0 -0
  294. package/omega/Agentik_Engine/tests/__pycache__/test_snapshot_partial.cpython-313-pytest-8.4.2.pyc +0 -0
  295. package/omega/Agentik_Engine/tests/__pycache__/test_snapshot_partial.cpython-313.pyc +0 -0
  296. package/omega/Agentik_Engine/tests/__pycache__/test_telegram_history.cpython-313-pytest-8.4.2.pyc +0 -0
  297. package/omega/Agentik_Engine/tests/__pycache__/test_telegram_history.cpython-313.pyc +0 -0
  298. package/omega/Agentik_Engine/tests/__pycache__/test_tmux_and_aisb_chat.cpython-313-pytest-8.4.2.pyc +0 -0
  299. package/omega/Agentik_Engine/tests/__pycache__/test_tmux_and_aisb_chat.cpython-313.pyc +0 -0
  300. package/omega/Agentik_Engine/tests/__pycache__/test_tools_and_sync.cpython-313-pytest-8.4.2.pyc +0 -0
  301. package/omega/Agentik_Engine/tests/__pycache__/test_tools_and_sync.cpython-313.pyc +0 -0
  302. package/omega/Agentik_Engine/tests/__pycache__/test_v06_features.cpython-313-pytest-8.4.2.pyc +0 -0
  303. package/omega/Agentik_Engine/tests/__pycache__/test_v06_features.cpython-313.pyc +0 -0
  304. package/omega/Agentik_Engine/tests/__pycache__/test_vault.cpython-313-pytest-8.4.2.pyc +0 -0
  305. package/omega/Agentik_Engine/tests/__pycache__/test_vault.cpython-313.pyc +0 -0
  306. package/omega/Agentik_Engine/tests/__pycache__/test_webhooks_and_readiness.cpython-313-pytest-8.4.2.pyc +0 -0
  307. package/omega/Agentik_Engine/tests/__pycache__/test_webhooks_and_readiness.cpython-313.pyc +0 -0
  308. package/omega/Agentik_Engine/tests/__pycache__/test_worker_and_cleanup.cpython-313-pytest-8.4.2.pyc +0 -0
  309. package/omega/Agentik_Engine/tests/__pycache__/test_worker_and_cleanup.cpython-313.pyc +0 -0
  310. package/omega/Agentik_Engine/tests/test_account.py +338 -0
  311. package/omega/Agentik_Engine/tests/test_adversarial.py +351 -0
  312. package/omega/Agentik_Engine/tests/test_agents_envelope.py +274 -0
  313. package/omega/Agentik_Engine/tests/test_audits_pipeline.py +348 -0
  314. package/omega/Agentik_Engine/tests/test_auto_update_and_migrations.py +394 -0
  315. package/omega/Agentik_Engine/tests/test_autonomous.py +361 -0
  316. package/omega/Agentik_Engine/tests/test_educators.py +233 -0
  317. package/omega/Agentik_Engine/tests/test_genesis_and_plan.py +573 -0
  318. package/omega/Agentik_Engine/tests/test_graphify.py +190 -0
  319. package/omega/Agentik_Engine/tests/test_handoff.py +311 -0
  320. package/omega/Agentik_Engine/tests/test_hermes_and_ua.py +387 -0
  321. package/omega/Agentik_Engine/tests/test_hermes_bootstrap_and_desktop.py +358 -0
  322. package/omega/Agentik_Engine/tests/test_install_steps.py +359 -0
  323. package/omega/Agentik_Engine/tests/test_install_ux.py +151 -0
  324. package/omega/Agentik_Engine/tests/test_installer_wiring.py +496 -0
  325. package/omega/Agentik_Engine/tests/test_intelligence.py +285 -0
  326. package/omega/Agentik_Engine/tests/test_llm_clis_and_uninstall.py +228 -0
  327. package/omega/Agentik_Engine/tests/test_managed_agent.py +363 -0
  328. package/omega/Agentik_Engine/tests/test_max_provider_and_menu.py +231 -0
  329. package/omega/Agentik_Engine/tests/test_menu_coverage.py +72 -0
  330. package/omega/Agentik_Engine/tests/test_pursue_cadence.py +217 -0
  331. package/omega/Agentik_Engine/tests/test_rag.py +287 -0
  332. package/omega/Agentik_Engine/tests/test_role_aliases_and_ssot.py +207 -0
  333. package/omega/Agentik_Engine/tests/test_skill_discovery_and_gate.py +337 -0
  334. package/omega/Agentik_Engine/tests/test_skill_power.py +259 -0
  335. package/omega/Agentik_Engine/tests/test_skill_routing.py +189 -0
  336. package/omega/Agentik_Engine/tests/test_snapshot_partial.py +172 -0
  337. package/omega/Agentik_Engine/tests/test_telegram_history.py +209 -0
  338. package/omega/Agentik_Engine/tests/test_tmux_and_aisb_chat.py +223 -0
  339. package/omega/Agentik_Engine/tests/test_tools_and_sync.py +312 -0
  340. package/omega/Agentik_Engine/tests/test_v06_features.py +370 -0
  341. package/omega/Agentik_Engine/tests/test_vault.py +173 -0
  342. package/omega/Agentik_Engine/tests/test_webhooks_and_readiness.py +277 -0
  343. package/omega/Agentik_Engine/tests/test_worker_and_cleanup.py +541 -0
  344. package/omega/Agentik_Extra/etc/secrets/.vault-key +3 -0
  345. package/omega/Agentik_Extra/etc/secrets/.vault-pub +1 -0
  346. package/omega/Agentik_Runtime/audits.db +0 -0
  347. package/omega/Agentik_SSOT/VERSION +1 -1
  348. package/omega/Agentik_SSOT/claude-plugins/claude-plugins.yaml +100 -0
  349. package/omega/Agentik_SSOT/docs/LAYERS.md +90 -0
  350. package/omega/Agentik_SSOT/docs/USER-JOURNEY.md +283 -0
  351. package/omega/Agentik_SSOT/marketplaces/design-discipline.yaml +86 -0
  352. package/omega/Agentik_SSOT/skills/a11yaudit/SKILL.md +161 -0
  353. package/omega/Agentik_SSOT/skills/apiaudit/SKILL.md +157 -0
  354. package/omega/Agentik_SSOT/skills/automationaudit/SKILL.md +161 -0
  355. package/omega/Agentik_SSOT/skills/cadence/SKILL.md +76 -0
  356. package/omega/Agentik_SSOT/skills/codeaudit/SKILL.md +153 -0
  357. package/omega/Agentik_SSOT/skills/copyaudit/SKILL.md +161 -0
  358. package/omega/Agentik_SSOT/skills/dataaudit/SKILL.md +157 -0
  359. package/omega/Agentik_SSOT/skills/debugaudit/SKILL.md +161 -0
  360. package/omega/Agentik_SSOT/skills/dispatch/SKILL.md +79 -0
  361. package/omega/Agentik_SSOT/skills/dxaudit/SKILL.md +161 -0
  362. package/omega/Agentik_SSOT/skills/featureaudit/SKILL.md +161 -0
  363. package/omega/Agentik_SSOT/skills/flowaudit/SKILL.md +165 -0
  364. package/omega/Agentik_SSOT/skills/genesis/SKILL.md +116 -0
  365. package/omega/Agentik_SSOT/skills/handoff/SKILL.md +117 -0
  366. package/omega/Agentik_SSOT/skills/logicaudit/SKILL.md +165 -0
  367. package/omega/Agentik_SSOT/skills/motionaudit/SKILL.md +165 -0
  368. package/omega/Agentik_SSOT/skills/perfaudit/SKILL.md +161 -0
  369. package/omega/Agentik_SSOT/skills/plan/SKILL.md +127 -0
  370. package/omega/Agentik_SSOT/skills/pursue/SKILL.md +68 -0
  371. package/omega/Agentik_SSOT/skills/rag-route.md +82 -0
  372. package/omega/Agentik_SSOT/skills/refontaudit/SKILL.md +165 -0
  373. package/omega/Agentik_SSOT/skills/retentionaudit/SKILL.md +165 -0
  374. package/omega/Agentik_SSOT/skills/secaudit/SKILL.md +157 -0
  375. package/omega/Agentik_SSOT/skills/seoaudit/SKILL.md +161 -0
  376. package/omega/Agentik_SSOT/skills/skill-auditor/SKILL.md +83 -0
  377. package/omega/Agentik_SSOT/skills/skill-finder/SKILL.md +116 -0
  378. package/omega/Agentik_SSOT/skills/uiuxaudit/SKILL.md +165 -0
  379. package/package.json +2 -2
@@ -0,0 +1,173 @@
1
+ """Tests for the encrypted secrets vault.
2
+
3
+ Two backends to exercise:
4
+
5
+ * **plain** — always runs (the fallback when `age` is not installed).
6
+ * **age** — runs only when `age` and `age-keygen` are both on PATH.
7
+ We skip the age-specific cases otherwise so CI on minimal
8
+ hosts doesn't go red.
9
+
10
+ Also exercises the path-traversal refusal and the round-trip invariant
11
+ (write then read returns the same value).
12
+ """
13
+ from __future__ import annotations
14
+
15
+ import os
16
+ import shutil
17
+ import sys
18
+ import tempfile
19
+ import unittest
20
+ from pathlib import Path
21
+ from unittest import mock
22
+
23
+
24
+ HERE = Path(__file__).resolve().parent
25
+ sys.path.insert(0, str(HERE.parent))
26
+
27
+ from omega_engine.vault import ( # noqa: E402
28
+ _safe_ref,
29
+ vault_init,
30
+ vault_read,
31
+ vault_status,
32
+ vault_write,
33
+ )
34
+
35
+
36
+ AGE_AVAILABLE = bool(shutil.which("age")) and bool(shutil.which("age-keygen"))
37
+
38
+
39
+ class TestSafeRef(unittest.TestCase):
40
+ def test_rejects_empty(self):
41
+ with self.assertRaises(ValueError):
42
+ _safe_ref("")
43
+
44
+ def test_rejects_path_traversal(self):
45
+ for bad in ("../escape", "a/b", "x\\y", ".hidden"):
46
+ with self.assertRaises(ValueError):
47
+ _safe_ref(bad)
48
+
49
+ def test_accepts_flat_names(self):
50
+ for good in ("CLAUDE_OAUTH", "max-primary_TOKEN", "abc123"):
51
+ self.assertEqual(_safe_ref(good), good)
52
+
53
+
54
+ class TestPlainBackend(unittest.TestCase):
55
+ """The fallback backend, always available."""
56
+
57
+ def test_init_with_no_age_picks_plain(self):
58
+ with tempfile.TemporaryDirectory() as td:
59
+ with mock.patch("omega_engine.vault._age_available", return_value=False):
60
+ info = vault_init(td)
61
+ self.assertEqual(info["backend"], "plain")
62
+ self.assertFalse(info["age_installed"])
63
+ sec = Path(td) / "Agentik_Extra" / "etc" / "secrets"
64
+ self.assertTrue(sec.is_dir())
65
+ # secrets dir is mode 700
66
+ mode = sec.stat().st_mode & 0o777
67
+ self.assertEqual(mode, 0o700)
68
+
69
+ def test_round_trip_plain(self):
70
+ with tempfile.TemporaryDirectory() as td:
71
+ with mock.patch("omega_engine.vault._age_available", return_value=False):
72
+ path = vault_write(td, "MY_TOKEN", "s3cret-value")
73
+ # mode 600
74
+ mode = path.stat().st_mode & 0o777
75
+ self.assertEqual(mode, 0o600)
76
+ # file is named without .age suffix in plain mode
77
+ self.assertTrue(path.name.endswith("MY_TOKEN"))
78
+ self.assertFalse(path.name.endswith(".age"))
79
+
80
+ got = vault_read(td, "MY_TOKEN")
81
+ self.assertEqual(got, "s3cret-value")
82
+
83
+ def test_read_returns_none_when_missing(self):
84
+ with tempfile.TemporaryDirectory() as td:
85
+ with mock.patch("omega_engine.vault._age_available", return_value=False):
86
+ self.assertIsNone(vault_read(td, "ABSENT"))
87
+
88
+ def test_overwrite_rotates_in_place(self):
89
+ with tempfile.TemporaryDirectory() as td:
90
+ with mock.patch("omega_engine.vault._age_available", return_value=False):
91
+ vault_write(td, "TOK", "v1")
92
+ vault_write(td, "TOK", "v2")
93
+ self.assertEqual(vault_read(td, "TOK"), "v2")
94
+
95
+ def test_status_counts_plain(self):
96
+ with tempfile.TemporaryDirectory() as td:
97
+ with mock.patch("omega_engine.vault._age_available", return_value=False):
98
+ vault_write(td, "A", "1")
99
+ vault_write(td, "B", "2")
100
+ status = vault_status(td)
101
+ self.assertEqual(status["backend"], "plain")
102
+ self.assertEqual(status["plaintext_count"], 2)
103
+ self.assertEqual(status["encrypted_count"], 0)
104
+
105
+
106
+ @unittest.skipUnless(AGE_AVAILABLE, "age + age-keygen not installed on this host")
107
+ class TestAgeBackend(unittest.TestCase):
108
+ """Exercised only when age is installed (CI may or may not have it)."""
109
+
110
+ def test_init_generates_keypair(self):
111
+ with tempfile.TemporaryDirectory() as td:
112
+ info = vault_init(td)
113
+ self.assertEqual(info["backend"], "age")
114
+ key = Path(info["key_path"])
115
+ pub = Path(info["pub_path"])
116
+ self.assertTrue(key.exists())
117
+ self.assertTrue(pub.exists())
118
+ self.assertEqual(key.stat().st_mode & 0o777, 0o600)
119
+ # public key file starts with "age1"
120
+ self.assertTrue(pub.read_text().strip().startswith("age1"))
121
+
122
+ def test_init_is_idempotent(self):
123
+ with tempfile.TemporaryDirectory() as td:
124
+ a = vault_init(td)
125
+ b = vault_init(td)
126
+ self.assertEqual(a["key_path"], b["key_path"])
127
+ self.assertEqual(a["pub_path"], b["pub_path"])
128
+
129
+ def test_round_trip_age(self):
130
+ with tempfile.TemporaryDirectory() as td:
131
+ path = vault_write(td, "OAUTH_X", "abc-DEF-123")
132
+ self.assertTrue(path.name.endswith(".age"))
133
+ mode = path.stat().st_mode & 0o777
134
+ self.assertEqual(mode, 0o600)
135
+ got = vault_read(td, "OAUTH_X")
136
+ self.assertEqual(got, "abc-DEF-123")
137
+
138
+ def test_status_counts_encrypted(self):
139
+ with tempfile.TemporaryDirectory() as td:
140
+ vault_write(td, "A", "1")
141
+ vault_write(td, "B", "2")
142
+ status = vault_status(td)
143
+ self.assertEqual(status["backend"], "age")
144
+ self.assertEqual(status["encrypted_count"], 2)
145
+ self.assertEqual(status["plaintext_count"], 0)
146
+
147
+ def test_write_cleans_up_old_plaintext(self):
148
+ with tempfile.TemporaryDirectory() as td:
149
+ # Pre-seed a plaintext file as if from a legacy install.
150
+ with mock.patch("omega_engine.vault._age_available", return_value=False):
151
+ vault_write(td, "LEGACY", "old")
152
+ # Now write through the age backend.
153
+ vault_write(td, "LEGACY", "new")
154
+ sec = Path(td) / "Agentik_Extra" / "etc" / "secrets"
155
+ self.assertTrue((sec / "LEGACY.age").exists())
156
+ self.assertFalse((sec / "LEGACY").exists(),
157
+ "old plaintext should have been cleaned up")
158
+ self.assertEqual(vault_read(td, "LEGACY"), "new")
159
+
160
+
161
+ class TestAccountUsesVault(unittest.TestCase):
162
+ """`account.write_token` / `read_token` must round-trip through the vault."""
163
+
164
+ def test_account_token_round_trip(self):
165
+ from omega_engine.account import read_token, write_token
166
+
167
+ with tempfile.TemporaryDirectory() as td:
168
+ write_token(td, "MAX_PRIMARY", "claude-token-xyz")
169
+ self.assertEqual(read_token(td, "MAX_PRIMARY"), "claude-token-xyz")
170
+
171
+
172
+ if __name__ == "__main__":
173
+ unittest.main(verbosity=2)
@@ -0,0 +1,277 @@
1
+ """Tests for inbound webhooks (HMAC gate) + the doctor's Ready verdict.
2
+
3
+ Two pieces under test:
4
+
5
+ 1. ``omega_engine.webhooks``
6
+ * ``WebhookRegistry`` loads from the SSOT YAML
7
+ * ``verify_signature`` rejects missing/wrong-format/wrong-value sigs
8
+ * ``handle_webhook`` runs the gate end-to-end + fires the supervisor
9
+ * GitHub + Linear + generic source formats
10
+
11
+ 2. ``omega doctor`` ends with READY / PARTIAL / NOT_READY
12
+ * Empty tree → NOT_READY
13
+ * Full tree with no provider creds → PARTIAL
14
+ """
15
+ from __future__ import annotations
16
+
17
+ import io
18
+ import json
19
+ import sys
20
+ import tempfile
21
+ import unittest
22
+ from pathlib import Path
23
+ from unittest import mock
24
+
25
+ import yaml
26
+
27
+
28
+ HERE = Path(__file__).resolve().parent
29
+ sys.path.insert(0, str(HERE.parent))
30
+
31
+ from omega_engine.webhooks import ( # noqa: E402
32
+ WebhookRegistry,
33
+ WebhookSpec,
34
+ generate_test_signature,
35
+ handle_webhook,
36
+ load_registry,
37
+ signature_header_for,
38
+ verify_signature,
39
+ )
40
+
41
+
42
+ # ---------------------------------------------------------------------------
43
+ # Signature verification — the hard line
44
+ # ---------------------------------------------------------------------------
45
+
46
+
47
+ class TestVerifySignature(unittest.TestCase):
48
+ SECRET = "hunter2"
49
+
50
+ def test_missing_header_rejected(self):
51
+ ok, reason = verify_signature("github", b"body", None, self.SECRET)
52
+ self.assertFalse(ok)
53
+ self.assertIn("missing signature", reason)
54
+
55
+ def test_missing_secret_rejected(self):
56
+ ok, reason = verify_signature("github", b"body",
57
+ "sha256=" + "0" * 64, "")
58
+ self.assertFalse(ok)
59
+ self.assertIn("secret not set", reason)
60
+
61
+ def test_github_correct(self):
62
+ body = b'{"action":"opened"}'
63
+ sig = generate_test_signature("github", body, self.SECRET)
64
+ ok, _ = verify_signature("github", body, sig, self.SECRET)
65
+ self.assertTrue(ok)
66
+
67
+ def test_github_wrong_secret(self):
68
+ body = b'{"action":"opened"}'
69
+ sig = generate_test_signature("github", body, "different")
70
+ ok, reason = verify_signature("github", body, sig, self.SECRET)
71
+ self.assertFalse(ok)
72
+ self.assertIn("mismatch", reason)
73
+
74
+ def test_github_missing_prefix(self):
75
+ ok, reason = verify_signature("github", b"x",
76
+ "0" * 64, # no "sha256=" prefix
77
+ self.SECRET)
78
+ self.assertFalse(ok)
79
+ self.assertIn("prefix", reason)
80
+
81
+ def test_linear_correct(self):
82
+ body = b'{"data":"..."}'
83
+ sig = generate_test_signature("linear", body, self.SECRET)
84
+ ok, _ = verify_signature("linear", body, sig, self.SECRET)
85
+ self.assertTrue(ok)
86
+
87
+ def test_generic_correct(self):
88
+ body = b'arbitrary payload'
89
+ sig = generate_test_signature("generic", body, self.SECRET)
90
+ ok, _ = verify_signature("generic", body, sig, self.SECRET)
91
+ self.assertTrue(ok)
92
+
93
+ def test_unknown_source(self):
94
+ ok, reason = verify_signature("aliens", b"x", "sha256=0", self.SECRET)
95
+ self.assertFalse(ok)
96
+ self.assertIn("unknown source", reason)
97
+
98
+
99
+ # ---------------------------------------------------------------------------
100
+ # Registry
101
+ # ---------------------------------------------------------------------------
102
+
103
+
104
+ class TestRegistry(unittest.TestCase):
105
+ def _seed(self, td: Path) -> Path:
106
+ d = td / "Agentik_SSOT" / "webhooks"
107
+ d.mkdir(parents=True)
108
+ (d / "webhooks.yaml").write_text(yaml.safe_dump({
109
+ "webhooks": [
110
+ {"id": "github-prs", "path": "/webhook/github-prs",
111
+ "source": "github", "secret_ref": "GITHUB_HOOK_SECRET"},
112
+ {"id": "linear-issues", "path": "/webhook/linear-issues",
113
+ "source": "linear", "secret_ref": "LINEAR_HOOK_SECRET"},
114
+ ],
115
+ }))
116
+ return td
117
+
118
+ def test_load(self):
119
+ with tempfile.TemporaryDirectory() as td:
120
+ home = self._seed(Path(td))
121
+ reg = load_registry(home)
122
+ self.assertEqual(len(reg.specs), 2)
123
+ self.assertEqual(reg.by_path("/webhook/github-prs").source, "github")
124
+ self.assertIsNone(reg.by_path("/webhook/nope"))
125
+
126
+ def test_load_missing_file(self):
127
+ with tempfile.TemporaryDirectory() as td:
128
+ reg = load_registry(Path(td))
129
+ self.assertEqual(reg.specs, [])
130
+
131
+
132
+ # ---------------------------------------------------------------------------
133
+ # handle_webhook — end to end
134
+ # ---------------------------------------------------------------------------
135
+
136
+
137
+ class TestHandleWebhook(unittest.TestCase):
138
+ def _seed_with_secret(self, td: Path) -> Path:
139
+ # SSOT + a vault entry for the secret.
140
+ d = td / "Agentik_SSOT" / "webhooks"
141
+ d.mkdir(parents=True)
142
+ (d / "webhooks.yaml").write_text(yaml.safe_dump({
143
+ "webhooks": [{
144
+ "id": "github-prs",
145
+ "path": "/webhook/github-prs",
146
+ "source": "github",
147
+ "secret_ref": "GITHUB_HOOK_SECRET",
148
+ }],
149
+ }))
150
+ from omega_engine.vault import vault_write
151
+ vault_write(td, "GITHUB_HOOK_SECRET", "hunter2")
152
+ return td
153
+
154
+ def test_unknown_path_404(self):
155
+ with tempfile.TemporaryDirectory() as td:
156
+ self._seed_with_secret(Path(td))
157
+ r = handle_webhook(
158
+ td, path="/webhook/does-not-exist",
159
+ headers={}, body=b"",
160
+ )
161
+ self.assertEqual(r["status"], 404)
162
+ self.assertFalse(r["ok"])
163
+
164
+ def test_bad_signature_401(self):
165
+ with tempfile.TemporaryDirectory() as td:
166
+ self._seed_with_secret(Path(td))
167
+ r = handle_webhook(
168
+ td, path="/webhook/github-prs",
169
+ headers={"X-Hub-Signature-256": "sha256=" + "0" * 64},
170
+ body=b'{"action":"opened"}',
171
+ )
172
+ self.assertEqual(r["status"], 401)
173
+ self.assertFalse(r["ok"])
174
+
175
+ def test_valid_signature_no_supervisor_returns_200(self):
176
+ with tempfile.TemporaryDirectory() as td:
177
+ self._seed_with_secret(Path(td))
178
+ body = b'{"action":"opened"}'
179
+ sig = generate_test_signature("github", body, "hunter2")
180
+ r = handle_webhook(
181
+ td, path="/webhook/github-prs",
182
+ headers={"X-Hub-Signature-256": sig},
183
+ body=body,
184
+ )
185
+ self.assertEqual(r["status"], 200)
186
+ self.assertTrue(r["ok"])
187
+ self.assertEqual(r["fired"], [])
188
+
189
+ def test_valid_signature_fires_supervisor(self):
190
+ with tempfile.TemporaryDirectory() as td:
191
+ self._seed_with_secret(Path(td))
192
+ body = b'{"action":"opened"}'
193
+ sig = generate_test_signature("github", body, "hunter2")
194
+
195
+ class _FakeSupervisor:
196
+ def __init__(self): self.calls = []
197
+ def wake_webhook(self, path, payload):
198
+ self.calls.append((path, payload))
199
+ return ["fake-charter-1"]
200
+
201
+ sup = _FakeSupervisor()
202
+ r = handle_webhook(
203
+ td, path="/webhook/github-prs",
204
+ headers={"X-Hub-Signature-256": sig},
205
+ body=body, supervisor=sup,
206
+ )
207
+ self.assertEqual(r["status"], 202)
208
+ self.assertEqual(r["fired"], ["fake-charter-1"])
209
+ self.assertEqual(sup.calls[0][0], "/webhook/github-prs")
210
+ self.assertEqual(sup.calls[0][1]["action"], "opened")
211
+
212
+
213
+ # ---------------------------------------------------------------------------
214
+ # Doctor's Ready / Partial / Not Ready verdict
215
+ # ---------------------------------------------------------------------------
216
+
217
+
218
+ class TestDoctorReadiness(unittest.TestCase):
219
+ """We don't run the full doctor here (it touches dozens of subsystems);
220
+ we exercise the verdict logic by feeding it controlled results."""
221
+
222
+ def _verdict_from_results(self, results):
223
+ """Replicate the in-cli verdict logic against a controlled list."""
224
+ CRITICAL = {
225
+ "structure", "event store", "vault", "providers",
226
+ "accounts", "aisb suite", "educators",
227
+ }
228
+ IMPORTANT = {
229
+ "24/7 services", "telegram", "llm clis",
230
+ "claude code settings", "audit history", "mcp",
231
+ }
232
+ critical_fails = []
233
+ important_warns = []
234
+ for r in results:
235
+ if r["status"] == "FAIL":
236
+ critical_fails.append(r)
237
+ elif r["status"] == "warn" and r["section"] in IMPORTANT:
238
+ important_warns.append(r)
239
+ if critical_fails:
240
+ return "NOT_READY"
241
+ if important_warns:
242
+ return "PARTIAL"
243
+ return "READY"
244
+
245
+ def test_all_ok_is_ready(self):
246
+ results = [
247
+ {"section": "structure", "status": "ok", "msg": "..."},
248
+ {"section": "vault", "status": "ok", "msg": "..."},
249
+ {"section": "providers", "status": "ok", "msg": "..."},
250
+ ]
251
+ self.assertEqual(self._verdict_from_results(results), "READY")
252
+
253
+ def test_one_fail_is_not_ready(self):
254
+ results = [
255
+ {"section": "vault", "status": "FAIL", "msg": "no backend"},
256
+ {"section": "structure", "status": "ok", "msg": "..."},
257
+ ]
258
+ self.assertEqual(self._verdict_from_results(results), "NOT_READY")
259
+
260
+ def test_warns_on_important_is_partial(self):
261
+ results = [
262
+ {"section": "structure", "status": "ok", "msg": "..."},
263
+ {"section": "telegram", "status": "warn", "msg": "no token"},
264
+ ]
265
+ self.assertEqual(self._verdict_from_results(results), "PARTIAL")
266
+
267
+ def test_warns_only_on_optional_is_ready(self):
268
+ results = [
269
+ {"section": "structure", "status": "ok", "msg": "..."},
270
+ {"section": "event store", "status": "warn", "msg": "empty"},
271
+ ]
272
+ # "event store" is NOT in IMPORTANT — empty is fine on a fresh install.
273
+ self.assertEqual(self._verdict_from_results(results), "READY")
274
+
275
+
276
+ if __name__ == "__main__":
277
+ unittest.main(verbosity=2)