@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,496 @@
1
+ """Tests that the installer actually wires v0.19.x features that the engine
2
+ already exposes. Without this guard the engine ships modules nobody calls,
3
+ which is exactly the v0.19.2 bug:
4
+
5
+ * `omega_engine.tmux.install_into_home_tmux_conf(profile="pro")` existed
6
+ but `step_engine` only wrote the "minimal" bundled config and never
7
+ touched ~/.tmux.conf.
8
+ * `omega_engine.hermes_bootstrap.write_brief()` existed but no install
9
+ step called it, so Hermès booted blind.
10
+ * `tmux.spawn_aisb_chat()` existed but install never created the always-on
11
+ session, so a user without Telegram had no entry point.
12
+
13
+ This test reads `bootstrap/lib/steps.sh` and `install.sh` directly — the
14
+ shell files are the source of truth, and `unittest` is cheap enough to keep
15
+ in the suite that already runs on every commit.
16
+ """
17
+ from __future__ import annotations
18
+
19
+ import os
20
+ import re
21
+ import sys
22
+ import tempfile
23
+ import textwrap
24
+ import unittest
25
+ from pathlib import Path
26
+
27
+
28
+ HERE = Path(__file__).resolve().parent
29
+ sys.path.insert(0, str(HERE.parent))
30
+
31
+ REPO_ROOT = Path(__file__).resolve().parents[3]
32
+ INSTALL_SH = REPO_ROOT / "install.sh"
33
+ STEPS_SH = REPO_ROOT / "bootstrap" / "lib" / "steps.sh"
34
+ COMMON_SH = REPO_ROOT / "bootstrap" / "lib" / "common.sh"
35
+
36
+
37
+ # ---------------------------------------------------------------------------
38
+ # Plan-mode wiring (the STEPS array drives the entire UX)
39
+ # ---------------------------------------------------------------------------
40
+
41
+
42
+ class TestInstallerStepList(unittest.TestCase):
43
+ """The STEPS array in install.sh MUST mention each new step name.
44
+ If the engine ships a new step function but install.sh never registers
45
+ it, the plan-mode display + the run loop both miss it."""
46
+
47
+ REQUIRED_ENTRIES = [
48
+ # name (the human label) → step function name
49
+ ("36-tmux-config", "step_tmux_config"),
50
+ ("37-hermes-brief", "step_hermes_brief"),
51
+ ("59-hermes-session", "step_hermes_session"),
52
+ ]
53
+
54
+ def setUp(self):
55
+ if not INSTALL_SH.is_file():
56
+ self.skipTest("install.sh not in repo")
57
+ if not STEPS_SH.is_file():
58
+ self.skipTest("bootstrap/lib/steps.sh not in repo")
59
+ self.install_text = INSTALL_SH.read_text()
60
+ self.steps_text = STEPS_SH.read_text()
61
+
62
+ def test_install_sh_registers_each_new_step(self):
63
+ for label, fn in self.REQUIRED_ENTRIES:
64
+ entry = f'"{label}:{fn}"'
65
+ self.assertIn(entry, self.install_text,
66
+ f"install.sh STEPS array missing {entry!r} — "
67
+ f"plan-mode will not show it and run loop will skip it")
68
+
69
+ def test_steps_sh_defines_each_step_function(self):
70
+ for _, fn in self.REQUIRED_ENTRIES:
71
+ pattern = re.compile(rf"^{fn}\(\) \{{", re.MULTILINE)
72
+ self.assertRegex(self.steps_text, pattern,
73
+ f"{fn} is referenced by install.sh but not defined in steps.sh")
74
+
75
+ def test_step_engine_no_longer_inlines_tmux_block(self):
76
+ """We moved tmux config out of step_engine into step_tmux_config so
77
+ plan-mode shows it as its own line. Guard against accidental
78
+ re-inlining."""
79
+ # Find the body of step_engine
80
+ m = re.search(r"^step_engine\(\) \{(.+?)^\}", self.steps_text,
81
+ re.DOTALL | re.MULTILINE)
82
+ self.assertIsNotNone(m, "step_engine function not found")
83
+ body = m.group(1)
84
+ self.assertNotIn("write_default_config", body,
85
+ "step_engine must NOT call write_default_config directly anymore "
86
+ "— that's step_tmux_config's job")
87
+
88
+
89
+ # ---------------------------------------------------------------------------
90
+ # Step semantics — exercise the same Python the heredocs run, against a
91
+ # temp HOME, so we don't touch the live ~/Omega or ~/.tmux.conf.
92
+ # ---------------------------------------------------------------------------
93
+
94
+
95
+ class TestStepTmuxConfigBehavior(unittest.TestCase):
96
+ """step_tmux_config writes the pro bundled config AND wires ~/.tmux.conf
97
+ with backup-on-difference. Re-runs with identical content must be silent
98
+ no-ops (no extra backups)."""
99
+
100
+ def test_pro_profile_lands_and_is_idempotent(self):
101
+ with tempfile.TemporaryDirectory() as tmp:
102
+ tmp = Path(tmp)
103
+ fake_home = tmp / "fake-home"
104
+ fake_home.mkdir()
105
+ omega_home = tmp / "Omega"
106
+ omega_home.mkdir()
107
+
108
+ os.environ["OMEGA_HOME"] = str(omega_home)
109
+ os.environ["HOME"] = str(fake_home)
110
+ try:
111
+ from omega_engine.tmux import (
112
+ write_default_config,
113
+ install_into_home_tmux_conf,
114
+ )
115
+
116
+ # First pass — writes both files.
117
+ bundled = write_default_config(profile="pro")
118
+ bundled_content = Path(bundled).read_text()
119
+ self.assertGreater(len(bundled_content), 1000,
120
+ "pro profile should be substantially larger than minimal")
121
+ # Pro-only sentinels (paste fix + kill log).
122
+ self.assertIn("assume-paste-time", bundled_content,
123
+ "pro profile missing Termius paste-fix sentinel")
124
+ self.assertIn("buffer-limit", bundled_content,
125
+ "pro profile missing tmux buffer-limit sentinel")
126
+
127
+ res1 = install_into_home_tmux_conf(profile="pro", backup=True)
128
+ self.assertEqual(res1["profile"], "pro")
129
+ home_conf = fake_home / ".tmux.conf"
130
+ self.assertEqual(home_conf.read_text(), bundled_content)
131
+
132
+ # Second pass — content matches, the step's heredoc skips the
133
+ # rewrite. We simulate that gate here (the heredoc compares
134
+ # existing vs bundled_content before calling install_into_*).
135
+ existing = home_conf.read_text()
136
+ self.assertEqual(existing, bundled_content,
137
+ "second-pass content drifted — idempotency broken")
138
+ finally:
139
+ os.environ.pop("OMEGA_HOME", None)
140
+
141
+
142
+ class TestStepHermesBriefBehavior(unittest.TestCase):
143
+ """step_hermes_brief writes ~/.hermes/skills/omega/SKILL.md so Hermès
144
+ knows about OmegaOS at install time. Atomic + idempotent."""
145
+
146
+ def test_brief_lands_and_is_atomic(self):
147
+ with tempfile.TemporaryDirectory() as tmp:
148
+ tmp = Path(tmp)
149
+ fake_home = tmp / "fake-home"
150
+ fake_home.mkdir()
151
+ omega_home = tmp / "Omega"
152
+ omega_home.mkdir()
153
+ os.environ["OMEGA_HOME"] = str(omega_home)
154
+ os.environ["HOME"] = str(fake_home)
155
+ try:
156
+ from omega_engine import hermes_bootstrap as HB
157
+ res = HB.write_brief()
158
+ self.assertTrue(res.written)
159
+ brief = Path(res.path)
160
+ self.assertTrue(brief.is_file())
161
+ content = brief.read_text()
162
+ # The brief must teach Hermès the L1-L5 architecture + the
163
+ # no-API-key principle — those are the two non-negotiable
164
+ # seed facts.
165
+ self.assertIn("OmegaOS", content)
166
+ self.assertIn("Hermès", content)
167
+ memlog = HB.memory_log_path()
168
+ # Memory log path is computed (file may not exist yet —
169
+ # observe_outcome creates it lazily).
170
+ self.assertTrue(str(memlog).endswith(
171
+ ".hermes/memory/omega_observations.jsonl"))
172
+ finally:
173
+ os.environ.pop("OMEGA_HOME", None)
174
+
175
+
176
+ # ---------------------------------------------------------------------------
177
+ # UX wiring — the post-install card must announce the always-on session.
178
+ # ---------------------------------------------------------------------------
179
+
180
+
181
+ # ---------------------------------------------------------------------------
182
+ # State drift — installer must NOT skip new steps after an upgrade.
183
+ # This was the v0.19.x Mac regression: a stale state file from v0.2.0
184
+ # silently skipped every step on a v0.19.x re-run, so the user got "se
185
+ # passe rien" and no new card.
186
+ # ---------------------------------------------------------------------------
187
+
188
+
189
+ class TestInstallerStateDrift(unittest.TestCase):
190
+ """state_version_drift / record_state_version must:
191
+ 1. Detect a missing version marker as drift (legacy state files).
192
+ 2. Detect a recorded version different from $OMEGA_BUNDLED_VERSION.
193
+ 3. Treat a matching marker as "no drift" (idempotent re-run is silent)."""
194
+
195
+ def _run(self, *, recorded: str | None, current: str,
196
+ have_state: bool = True) -> int:
197
+ """Source common.sh, set env, call state_version_drift,
198
+ return its exit code (0 = drift, 1 = no drift).
199
+
200
+ common.sh derives STATE_DIR from OMEGA_HOME at source time, so we
201
+ export OMEGA_HOME (not STATE_DIR) and let common.sh build the
202
+ right path. Sourcing later override of STATE_DIR is then safe.
203
+ """
204
+ with tempfile.TemporaryDirectory() as tmp:
205
+ tmp = Path(tmp)
206
+ omega_home = tmp / "Omega"
207
+ state_dir = omega_home / "Agentik_Extra" / "var"
208
+ state_dir.mkdir(parents=True)
209
+ if have_state:
210
+ (state_dir / ".install-state").write_text("00-preflight\n")
211
+ if recorded is not None:
212
+ (state_dir / ".install-version").write_text(recorded + "\n")
213
+ script = (
214
+ f"set -e\n"
215
+ f"export OMEGA_HOME={omega_home!s}\n"
216
+ f"export OMEGA_BUNDLED_VERSION={current!r}\n"
217
+ f". {COMMON_SH!s}\n"
218
+ f"if state_version_drift; then exit 0; else exit 1; fi\n"
219
+ )
220
+ import subprocess
221
+ rc = subprocess.run(["bash", "-c", script],
222
+ capture_output=True).returncode
223
+ return rc
224
+
225
+ def test_missing_marker_is_drift(self):
226
+ rc = self._run(recorded=None, current="0.19.4")
227
+ self.assertEqual(rc, 0,
228
+ "stale state with no version marker MUST be treated as drift")
229
+
230
+ def test_version_mismatch_is_drift(self):
231
+ rc = self._run(recorded="0.2.0", current="0.19.4")
232
+ self.assertEqual(rc, 0,
233
+ "0.2.0 state under 0.19.4 installer MUST be treated as drift")
234
+
235
+ def test_matching_version_is_no_drift(self):
236
+ rc = self._run(recorded="0.19.4", current="0.19.4")
237
+ self.assertEqual(rc, 1,
238
+ "matching versions MUST be treated as a clean idempotent re-run")
239
+
240
+ def test_record_state_version_writes_marker(self):
241
+ with tempfile.TemporaryDirectory() as tmp:
242
+ tmp = Path(tmp)
243
+ omega_home = tmp / "Omega"
244
+ state_dir = omega_home / "Agentik_Extra" / "var"
245
+ script = (
246
+ f"set -e\n"
247
+ f"export OMEGA_HOME={omega_home!s}\n"
248
+ f"export OMEGA_BUNDLED_VERSION='0.19.4'\n"
249
+ f". {COMMON_SH!s}\n"
250
+ f"record_state_version\n"
251
+ )
252
+ import subprocess
253
+ subprocess.run(["bash", "-c", script], check=True,
254
+ capture_output=True)
255
+ marker = state_dir / ".install-version"
256
+ self.assertTrue(marker.exists(),
257
+ ".install-version marker must be created")
258
+ self.assertEqual(marker.read_text().strip(), "0.19.4")
259
+
260
+
261
+ class TestInstallShWiresDriftCheck(unittest.TestCase):
262
+ """The install.sh entry point MUST source OMEGA_BUNDLED_VERSION and call
263
+ state_version_drift / record_state_version. Without those, the engine-side
264
+ drift detection is dead code."""
265
+
266
+ def test_install_sh_exports_bundled_version(self):
267
+ text = INSTALL_SH.read_text()
268
+ self.assertIn("OMEGA_BUNDLED_VERSION", text,
269
+ "install.sh must read the bundled version for drift detection")
270
+ self.assertIn("state_version_drift", text,
271
+ "install.sh must call state_version_drift before run_step loop")
272
+ self.assertIn("record_state_version", text,
273
+ "install.sh must call record_state_version after path setup")
274
+
275
+
276
+ # ---------------------------------------------------------------------------
277
+ # whiptail / newt — the bare `omega` command MUST work on macOS too.
278
+ # ---------------------------------------------------------------------------
279
+
280
+
281
+ class TestSystemDepsCoversMenuDep(unittest.TestCase):
282
+ """`omega` (no args) shows the menu. On Linux apt/dnf, on macOS brew —
283
+ all three branches MUST install the package that provides `whiptail`."""
284
+
285
+ def test_apt_branch_installs_whiptail(self):
286
+ text = STEPS_SH.read_text()
287
+ # apt installs the 'whiptail' package
288
+ self.assertRegex(text, r"apt\)[^;]*whiptail",
289
+ "apt branch must install whiptail")
290
+
291
+ def test_dnf_branch_installs_newt(self):
292
+ text = STEPS_SH.read_text()
293
+ # dnf installs 'newt' which provides /usr/bin/whiptail
294
+ self.assertRegex(text, r"dnf\)[^;]*newt",
295
+ "dnf branch must install newt (provides whiptail)")
296
+
297
+ def test_brew_branch_installs_newt(self):
298
+ text = STEPS_SH.read_text()
299
+ # macOS brew package is 'newt'
300
+ self.assertRegex(text, r"brew\)[^;]*newt",
301
+ "brew branch must install newt (provides whiptail on macOS)")
302
+
303
+
304
+ # ---------------------------------------------------------------------------
305
+ # Text-mode menu — `omega` must NEVER silently exit when whiptail is missing.
306
+ # ---------------------------------------------------------------------------
307
+
308
+
309
+ class TestTextMenuFallback(unittest.TestCase):
310
+ """When whiptail is unavailable, `omega` must print a visible numbered
311
+ list and accept stdin input. Silent exit was the v0.19.x Mac symptom
312
+ ("se passe rien")."""
313
+
314
+ def test_text_menu_prints_items_and_quits_cleanly(self):
315
+ import io, contextlib
316
+ from omega_engine import menu as M
317
+ # Force the no-whiptail path by monkeypatching _have.
318
+ orig = M._have
319
+ M._have = lambda b: False if b == "whiptail" else orig(b)
320
+ try:
321
+ # Feed "0\n" so it quits on the first prompt.
322
+ stdin_buf = io.StringIO("0\n")
323
+ stdout_buf = io.StringIO()
324
+ with contextlib.redirect_stdout(stdout_buf):
325
+ from unittest.mock import patch
326
+ with patch("builtins.input", side_effect=["0"]):
327
+ rc = M.run_menu()
328
+ finally:
329
+ M._have = orig
330
+ self.assertEqual(rc, 0)
331
+ out = stdout_buf.getvalue()
332
+ self.assertIn("Omega OS v", out, "header must include version")
333
+ # Each main item label must appear at least once.
334
+ for tag, label in M._MAIN_ITEMS:
335
+ if tag == "quit":
336
+ continue
337
+ self.assertIn(label, out,
338
+ f"text menu missing item: {label!r}")
339
+
340
+ def test_text_menu_unknown_input_does_not_exit(self):
341
+ """Garbage input loops back, doesn't crash the menu."""
342
+ import io, contextlib
343
+ from omega_engine import menu as M
344
+ orig = M._have
345
+ M._have = lambda b: False if b == "whiptail" else orig(b)
346
+ try:
347
+ from unittest.mock import patch
348
+ with patch("builtins.input", side_effect=["abc", "99", "0"]):
349
+ with contextlib.redirect_stdout(io.StringIO()):
350
+ rc = M.run_menu()
351
+ finally:
352
+ M._have = orig
353
+ self.assertEqual(rc, 0)
354
+
355
+
356
+ # ---------------------------------------------------------------------------
357
+ # Helper functions defined in common.sh — used by install.sh in plan-mode.
358
+ # `prompt_yes_no` was missing in v0.19.1..0.19.4 and aborted the first install
359
+ # on macOS ("command not found"). This guards the regression.
360
+ # ---------------------------------------------------------------------------
361
+
362
+
363
+ class TestPromptYesNoDefined(unittest.TestCase):
364
+ """install.sh's plan-mode gate calls `prompt_yes_no` to confirm the run.
365
+ The helper MUST be defined in common.sh, or the install aborts before
366
+ a single step executes."""
367
+
368
+ def test_prompt_yes_no_is_a_shell_function(self):
369
+ import subprocess
370
+ rc = subprocess.run(
371
+ ["bash", "-c", f". {COMMON_SH!s} && type prompt_yes_no"],
372
+ capture_output=True, text=True,
373
+ )
374
+ self.assertEqual(rc.returncode, 0,
375
+ "prompt_yes_no must be defined in common.sh — without it the "
376
+ "plan-mode prompt aborts every interactive install")
377
+ self.assertIn("function", rc.stdout,
378
+ "prompt_yes_no must be a bash function, not an alias")
379
+
380
+ def test_prompt_yes_no_default_yes_accepts_empty_stdin(self):
381
+ """Just hitting Enter must accept the default."""
382
+ import subprocess
383
+ script = (
384
+ f". {COMMON_SH!s}\n"
385
+ f"prompt_yes_no 'install?' yes && echo YES || echo NO\n"
386
+ )
387
+ rc = subprocess.run(
388
+ ["bash", "-c", script],
389
+ input="\n", capture_output=True, text=True,
390
+ )
391
+ self.assertIn("YES", rc.stdout)
392
+
393
+ def test_prompt_yes_no_n_rejects(self):
394
+ """Typing 'n' returns non-zero so install aborts cleanly."""
395
+ import subprocess
396
+ script = (
397
+ f". {COMMON_SH!s}\n"
398
+ f"prompt_yes_no 'install?' yes && echo YES || echo NO\n"
399
+ )
400
+ rc = subprocess.run(
401
+ ["bash", "-c", script],
402
+ input="n\n", capture_output=True, text=True,
403
+ )
404
+ self.assertIn("NO", rc.stdout)
405
+
406
+
407
+ # ---------------------------------------------------------------------------
408
+ # Banner — the OMEGA ascii art must read OMEGA, not OMEBA.
409
+ # Position 4 (the G) was rendering as a B in some terminals because row 3
410
+ # closed the upper-right with `█▀` (looked like the top loop of B) and the
411
+ # bottom used a flat `████████▀` instead of the canonical arc.
412
+ # ---------------------------------------------------------------------------
413
+
414
+
415
+ class TestBannerReadsOmega(unittest.TestCase):
416
+ """The hand-tuned colossal-font OMEGA banner has specific row signatures
417
+ that distinguish G from B. We assert both signatures directly."""
418
+
419
+ def test_g_row3_does_not_close_upper_right(self):
420
+ text = COMMON_SH.read_text()
421
+ # The fixed G row 3 has just `███` for left side then spaces.
422
+ # The old broken-G row 3 had `███ █▀` closing the upper right.
423
+ # We check the actual line in the banner:
424
+ # 'row 3' in the printf list is the third printf after install_banner.
425
+ # Easiest: assert the broken-G row sentinel does NOT appear in the
426
+ # banner block.
427
+ broken_row3 = '███ █▀ ███ ███'
428
+ # That's the OLD row3 with E+G+A — find the install_banner block.
429
+ import re
430
+ m = re.search(r"install_banner\(\) \{.*?^\}", text, re.S | re.M)
431
+ self.assertIsNotNone(m, "install_banner not found in common.sh")
432
+ block = m.group(0)
433
+ # OLD signature (E and G both close upper-right): three repetitions
434
+ # of `█▀` separated by spaces on the SAME row.
435
+ old_sig = "███ █▀ ███ █▀ ███ ███"
436
+ self.assertNotIn(old_sig, block,
437
+ "banner row 3 still has the old G-as-B signature "
438
+ "(closes upper-right with █▀)")
439
+
440
+ def test_g_has_clean_arc_bottom(self):
441
+ text = COMMON_SH.read_text()
442
+ # Fixed bottom row has ` ▀██████▀ ` for G (arc), not `████████▀`.
443
+ # Search for the BOTTOM row in install_banner.
444
+ import re
445
+ m = re.search(r"install_banner\(\) \{.*?^\}", text, re.S | re.M)
446
+ block = m.group(0)
447
+ # OLD signature on bottom row: `██████████ ████████▀`
448
+ old_bottom = "██████████ ████████▀"
449
+ self.assertNotIn(old_bottom, block,
450
+ "banner bottom row still uses the flat G base — should be arc")
451
+
452
+
453
+ # ---------------------------------------------------------------------------
454
+ # Brand colour — Claude-Code orange. The truecolor escape must be exported.
455
+ # ---------------------------------------------------------------------------
456
+
457
+
458
+ class TestBrandColourIsOrange(unittest.TestCase):
459
+ def test_c_orange_is_truecolor_d97757(self):
460
+ text = COMMON_SH.read_text()
461
+ self.assertIn("38;2;217;119;87", text,
462
+ "C_ORANGE must be the Claude-Code brand truecolor "
463
+ "(\\033[38;2;217;119;87m)")
464
+ self.assertIn("C_ORANGE=", text)
465
+
466
+ def test_banner_uses_c_orange(self):
467
+ text = COMMON_SH.read_text()
468
+ # Count how many times the banner printf uses C_ORANGE.
469
+ # Banner has 8 rows — each row must use C_ORANGE.
470
+ import re
471
+ m = re.search(r"install_banner\(\) \{.*?^\}", text, re.S | re.M)
472
+ block = m.group(0)
473
+ n = block.count("$C_ORANGE")
474
+ self.assertGreaterEqual(n, 8,
475
+ f"banner should use C_ORANGE on each of 8 rows (got {n})")
476
+
477
+
478
+ class TestPostInstallCardMentionsAISBChat(unittest.TestCase):
479
+ """The 'AISB-chat' tmux session is the conversational entry point when
480
+ Telegram isn't wired. The post-install card MUST tell the operator how
481
+ to attach to it; otherwise they finish the install with no UI."""
482
+
483
+ def test_card_shows_attach_command(self):
484
+ if not COMMON_SH.is_file():
485
+ self.skipTest("common.sh not in repo")
486
+ text = COMMON_SH.read_text()
487
+ self.assertIn("tmux attach -t AISB-chat", text,
488
+ "post_install_card must include the AISB-chat attach line — "
489
+ "otherwise the operator has no way to discover their always-on "
490
+ "Hermès session")
491
+ # Also surface the "every session in tmux" expectation.
492
+ self.assertIn("tmux", text)
493
+
494
+
495
+ if __name__ == "__main__":
496
+ unittest.main()