@trac3r/oh-my-god 2.2.11

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 (638) hide show
  1. package/CHANGELOG.md +188 -0
  2. package/INSTALL-VERIFICATION-INDEX.md +51 -0
  3. package/LICENSE +21 -0
  4. package/OMG-setup.sh +2549 -0
  5. package/QUICK-REFERENCE.md +58 -0
  6. package/README.md +207 -0
  7. package/agents/__init__.py +1 -0
  8. package/agents/__pycache__/model_roles.cpython-313.pyc +0 -0
  9. package/agents/_model_roles.yaml +26 -0
  10. package/agents/designer.md +67 -0
  11. package/agents/explore.md +60 -0
  12. package/agents/model_roles.py +196 -0
  13. package/agents/omg-api-builder.md +23 -0
  14. package/agents/omg-architect-mode.md +41 -0
  15. package/agents/omg-architect.md +13 -0
  16. package/agents/omg-backend-engineer.md +41 -0
  17. package/agents/omg-critic.md +16 -0
  18. package/agents/omg-database-engineer.md +41 -0
  19. package/agents/omg-escalation-router.md +17 -0
  20. package/agents/omg-executor.md +12 -0
  21. package/agents/omg-frontend-designer.md +41 -0
  22. package/agents/omg-implement-mode.md +49 -0
  23. package/agents/omg-infra-engineer.md +41 -0
  24. package/agents/omg-qa-tester.md +16 -0
  25. package/agents/omg-research-mode.md +41 -0
  26. package/agents/omg-security-auditor.md +41 -0
  27. package/agents/omg-testing-engineer.md +41 -0
  28. package/agents/plan.md +80 -0
  29. package/agents/quick_task.md +64 -0
  30. package/agents/reviewer.md +83 -0
  31. package/agents/task.md +71 -0
  32. package/bin/omg +41 -0
  33. package/commands/OMG:ai-commit.md +113 -0
  34. package/commands/OMG:api-twin.md +22 -0
  35. package/commands/OMG:arch.md +313 -0
  36. package/commands/OMG:browser.md +29 -0
  37. package/commands/OMG:ccg.md +22 -0
  38. package/commands/OMG:compat.md +57 -0
  39. package/commands/OMG:cost.md +181 -0
  40. package/commands/OMG:crazy.md +125 -0
  41. package/commands/OMG:create-agent.md +183 -0
  42. package/commands/OMG:deep-plan.md +18 -0
  43. package/commands/OMG:deps.md +248 -0
  44. package/commands/OMG:diagnose-plugins.md +33 -0
  45. package/commands/OMG:doctor.md +37 -0
  46. package/commands/OMG:domain-init.md +11 -0
  47. package/commands/OMG:escalate.md +52 -0
  48. package/commands/OMG:forge.md +103 -0
  49. package/commands/OMG:health-check.md +48 -0
  50. package/commands/OMG:init.md +134 -0
  51. package/commands/OMG:issue.md +56 -0
  52. package/commands/OMG:mode.md +44 -0
  53. package/commands/OMG:playwright.md +17 -0
  54. package/commands/OMG:preflight.md +26 -0
  55. package/commands/OMG:preset.md +49 -0
  56. package/commands/OMG:profile-review.md +58 -0
  57. package/commands/OMG:project-init.md +11 -0
  58. package/commands/OMG:ralph-start.md +43 -0
  59. package/commands/OMG:ralph-stop.md +23 -0
  60. package/commands/OMG:security-check.md +28 -0
  61. package/commands/OMG:session-branch.md +101 -0
  62. package/commands/OMG:session-fork.md +57 -0
  63. package/commands/OMG:session-merge.md +138 -0
  64. package/commands/OMG:setup.md +82 -0
  65. package/commands/OMG:ship.md +18 -0
  66. package/commands/OMG:stats.md +225 -0
  67. package/commands/OMG:teams.md +54 -0
  68. package/commands/OMG:theme.md +44 -0
  69. package/commands/OMG:validate.md +59 -0
  70. package/commands/__init__.py +1 -0
  71. package/docs/command-surface.md +55 -0
  72. package/docs/install/claude-code.md +53 -0
  73. package/docs/install/codex.md +45 -0
  74. package/docs/install/gemini.md +43 -0
  75. package/docs/install/github-action.md +81 -0
  76. package/docs/install/github-app-required-checks.md +107 -0
  77. package/docs/install/github-app.md +161 -0
  78. package/docs/install/kimi.md +43 -0
  79. package/docs/install/opencode.md +38 -0
  80. package/docs/proof.md +182 -0
  81. package/hooks/__init__.py +0 -0
  82. package/hooks/__pycache__/__init__.cpython-313.pyc +0 -0
  83. package/hooks/__pycache__/_agent_registry.cpython-313.pyc +0 -0
  84. package/hooks/__pycache__/_analytics.cpython-313.pyc +0 -0
  85. package/hooks/__pycache__/_budget.cpython-313.pyc +0 -0
  86. package/hooks/__pycache__/_common.cpython-313.pyc +0 -0
  87. package/hooks/__pycache__/_compression_optimizer.cpython-313.pyc +0 -0
  88. package/hooks/__pycache__/_cost_ledger.cpython-313.pyc +0 -0
  89. package/hooks/__pycache__/_learnings.cpython-313.pyc +0 -0
  90. package/hooks/__pycache__/_memory.cpython-313.pyc +0 -0
  91. package/hooks/__pycache__/_post_write.cpython-313.pyc +0 -0
  92. package/hooks/__pycache__/_protected_context.cpython-313.pyc +0 -0
  93. package/hooks/__pycache__/_token_counter.cpython-313.pyc +0 -0
  94. package/hooks/__pycache__/branch_manager.cpython-313.pyc +0 -0
  95. package/hooks/__pycache__/budget_governor.cpython-313.pyc +0 -0
  96. package/hooks/__pycache__/circuit-breaker.cpython-313.pyc +0 -0
  97. package/hooks/__pycache__/compression_feedback.cpython-313.pyc +0 -0
  98. package/hooks/__pycache__/config-guard.cpython-313.pyc +0 -0
  99. package/hooks/__pycache__/context_pressure.cpython-313.pyc +0 -0
  100. package/hooks/__pycache__/credential_store.cpython-313.pyc +0 -0
  101. package/hooks/__pycache__/fetch-rate-limits.cpython-313.pyc +0 -0
  102. package/hooks/__pycache__/firewall.cpython-313.pyc +0 -0
  103. package/hooks/__pycache__/hashline-formatter-bridge.cpython-313.pyc +0 -0
  104. package/hooks/__pycache__/hashline-injector.cpython-313.pyc +0 -0
  105. package/hooks/__pycache__/hashline-validator.cpython-313.pyc +0 -0
  106. package/hooks/__pycache__/idle-detector.cpython-313.pyc +0 -0
  107. package/hooks/__pycache__/instructions-loaded.cpython-313.pyc +0 -0
  108. package/hooks/__pycache__/intentgate-keyword-detector.cpython-313.pyc +0 -0
  109. package/hooks/__pycache__/magic-keyword-router.cpython-313.pyc +0 -0
  110. package/hooks/__pycache__/policy_engine.cpython-313.pyc +0 -0
  111. package/hooks/__pycache__/post-tool-failure.cpython-313.pyc +0 -0
  112. package/hooks/__pycache__/post-write.cpython-313.pyc +0 -0
  113. package/hooks/__pycache__/post_write.cpython-313.pyc +0 -0
  114. package/hooks/__pycache__/pre-compact.cpython-313.pyc +0 -0
  115. package/hooks/__pycache__/pre-tool-inject.cpython-313.pyc +0 -0
  116. package/hooks/__pycache__/prompt-enhancer.cpython-313.pyc +0 -0
  117. package/hooks/__pycache__/quality-runner.cpython-313.pyc +0 -0
  118. package/hooks/__pycache__/query.cpython-313.pyc +0 -0
  119. package/hooks/__pycache__/secret-guard.cpython-313.pyc +0 -0
  120. package/hooks/__pycache__/secret_audit.cpython-313.pyc +0 -0
  121. package/hooks/__pycache__/security_validators.cpython-313.pyc +0 -0
  122. package/hooks/__pycache__/session-end-capture.cpython-313.pyc +0 -0
  123. package/hooks/__pycache__/session-start.cpython-313.pyc +0 -0
  124. package/hooks/__pycache__/setup_wizard.cpython-313.pyc +0 -0
  125. package/hooks/__pycache__/shadow_manager.cpython-313.pyc +0 -0
  126. package/hooks/__pycache__/state_migration.cpython-313.pyc +0 -0
  127. package/hooks/__pycache__/stop-gate.cpython-313.pyc +0 -0
  128. package/hooks/__pycache__/stop_dispatcher.cpython-313.pyc +0 -0
  129. package/hooks/__pycache__/tdd-gate.cpython-313.pyc +0 -0
  130. package/hooks/__pycache__/terms-guard.cpython-313.pyc +0 -0
  131. package/hooks/__pycache__/test-validator.cpython-313.pyc +0 -0
  132. package/hooks/__pycache__/test_generator_hook.cpython-313.pyc +0 -0
  133. package/hooks/__pycache__/todo-state-tracker.cpython-313.pyc +0 -0
  134. package/hooks/__pycache__/tool-ledger.cpython-313.pyc +0 -0
  135. package/hooks/__pycache__/trust_review.cpython-313.pyc +0 -0
  136. package/hooks/__pycache__/user-prompt-submit.cpython-313.pyc +0 -0
  137. package/hooks/_agent_registry.py +481 -0
  138. package/hooks/_analytics.py +291 -0
  139. package/hooks/_budget.py +31 -0
  140. package/hooks/_common.py +761 -0
  141. package/hooks/_compression_optimizer.py +119 -0
  142. package/hooks/_cost_ledger.py +176 -0
  143. package/hooks/_learnings.py +126 -0
  144. package/hooks/_memory.py +103 -0
  145. package/hooks/_post_write.py +46 -0
  146. package/hooks/_protected_context.py +150 -0
  147. package/hooks/_token_counter.py +221 -0
  148. package/hooks/branch_manager.py +255 -0
  149. package/hooks/budget_governor.py +326 -0
  150. package/hooks/circuit-breaker.py +270 -0
  151. package/hooks/compression_feedback.py +254 -0
  152. package/hooks/config-guard.py +193 -0
  153. package/hooks/context_pressure.py +119 -0
  154. package/hooks/credential_store.py +970 -0
  155. package/hooks/fetch-rate-limits.py +212 -0
  156. package/hooks/firewall.py +323 -0
  157. package/hooks/hashline-formatter-bridge.py +224 -0
  158. package/hooks/hashline-injector.py +273 -0
  159. package/hooks/hashline-validator.py +216 -0
  160. package/hooks/idle-detector.py +97 -0
  161. package/hooks/instructions-loaded.py +26 -0
  162. package/hooks/intentgate-keyword-detector.py +200 -0
  163. package/hooks/magic-keyword-router.py +195 -0
  164. package/hooks/policy_engine.py +767 -0
  165. package/hooks/post-tool-failure.py +19 -0
  166. package/hooks/post-write.py +233 -0
  167. package/hooks/pre-compact.py +470 -0
  168. package/hooks/pre-tool-inject.py +98 -0
  169. package/hooks/prompt-enhancer.py +879 -0
  170. package/hooks/quality-runner.py +191 -0
  171. package/hooks/query.py +512 -0
  172. package/hooks/secret-guard.py +120 -0
  173. package/hooks/secret_audit.py +144 -0
  174. package/hooks/security_validators.py +93 -0
  175. package/hooks/session-end-capture.py +505 -0
  176. package/hooks/session-start.py +261 -0
  177. package/hooks/setup_wizard.py +1101 -0
  178. package/hooks/shadow_manager.py +476 -0
  179. package/hooks/state_migration.py +228 -0
  180. package/hooks/stop-gate.py +7 -0
  181. package/hooks/stop_dispatcher.py +1259 -0
  182. package/hooks/tdd-gate.py +10 -0
  183. package/hooks/terms-guard.py +98 -0
  184. package/hooks/test-validator.py +462 -0
  185. package/hooks/test_generator_hook.py +123 -0
  186. package/hooks/todo-state-tracker.py +114 -0
  187. package/hooks/tool-ledger.py +165 -0
  188. package/hooks/trust_review.py +662 -0
  189. package/hooks/user-prompt-submit.py +12 -0
  190. package/hud/omg-hud.mjs +1571 -0
  191. package/lab/__init__.py +1 -0
  192. package/lab/__pycache__/__init__.cpython-313.pyc +0 -0
  193. package/lab/__pycache__/axolotl_adapter.cpython-313.pyc +0 -0
  194. package/lab/__pycache__/forge_runner.cpython-313.pyc +0 -0
  195. package/lab/__pycache__/gazebo_adapter.cpython-313.pyc +0 -0
  196. package/lab/__pycache__/isaac_gym_adapter.cpython-313.pyc +0 -0
  197. package/lab/__pycache__/mock_isaac_env.cpython-313.pyc +0 -0
  198. package/lab/__pycache__/pipeline.cpython-313.pyc +0 -0
  199. package/lab/__pycache__/policies.cpython-313.pyc +0 -0
  200. package/lab/__pycache__/pybullet_adapter.cpython-313.pyc +0 -0
  201. package/lab/axolotl_adapter.py +531 -0
  202. package/lab/forge_runner.py +103 -0
  203. package/lab/gazebo_adapter.py +168 -0
  204. package/lab/isaac_gym_adapter.py +190 -0
  205. package/lab/mock_isaac_env.py +47 -0
  206. package/lab/pipeline.py +712 -0
  207. package/lab/policies.py +52 -0
  208. package/lab/pybullet_adapter.py +192 -0
  209. package/package.json +61 -0
  210. package/plugins/README.md +78 -0
  211. package/plugins/__init__.py +1 -0
  212. package/plugins/__pycache__/__init__.cpython-313.pyc +0 -0
  213. package/plugins/advanced/commands/OMG-code-review.md +114 -0
  214. package/plugins/advanced/commands/OMG-deep-plan.md +266 -0
  215. package/plugins/advanced/commands/OMG-handoff.md +115 -0
  216. package/plugins/advanced/commands/OMG-learn.md +110 -0
  217. package/plugins/advanced/commands/OMG-maintainer.md +31 -0
  218. package/plugins/advanced/commands/OMG-ralph-start.md +43 -0
  219. package/plugins/advanced/commands/OMG-ralph-stop.md +23 -0
  220. package/plugins/advanced/commands/OMG-security-review.md +16 -0
  221. package/plugins/advanced/commands/OMG-sequential-thinking.md +20 -0
  222. package/plugins/advanced/commands/OMG-ship.md +46 -0
  223. package/plugins/advanced/commands/OMG:code-review.md +114 -0
  224. package/plugins/advanced/commands/OMG:deep-plan.md +266 -0
  225. package/plugins/advanced/commands/OMG:handoff.md +115 -0
  226. package/plugins/advanced/commands/OMG:learn.md +110 -0
  227. package/plugins/advanced/commands/OMG:maintainer.md +31 -0
  228. package/plugins/advanced/commands/OMG:ralph-start.md +43 -0
  229. package/plugins/advanced/commands/OMG:ralph-stop.md +23 -0
  230. package/plugins/advanced/commands/OMG:security-review.md +16 -0
  231. package/plugins/advanced/commands/OMG:sequential-thinking.md +20 -0
  232. package/plugins/advanced/commands/OMG:ship.md +46 -0
  233. package/plugins/advanced/plugin.json +104 -0
  234. package/plugins/core/plugin.json +204 -0
  235. package/plugins/dephealth/__init__.py +0 -0
  236. package/plugins/dephealth/__pycache__/__init__.cpython-313.pyc +0 -0
  237. package/plugins/dephealth/__pycache__/cve_scanner.cpython-313.pyc +0 -0
  238. package/plugins/dephealth/__pycache__/license_checker.cpython-313.pyc +0 -0
  239. package/plugins/dephealth/__pycache__/manifest_detector.cpython-313.pyc +0 -0
  240. package/plugins/dephealth/__pycache__/vuln_analyzer.cpython-313.pyc +0 -0
  241. package/plugins/dephealth/cve_scanner.py +279 -0
  242. package/plugins/dephealth/license_checker.py +135 -0
  243. package/plugins/dephealth/manifest_detector.py +423 -0
  244. package/plugins/dephealth/vuln_analyzer.py +176 -0
  245. package/plugins/testgen/__init__.py +0 -0
  246. package/plugins/testgen/__pycache__/__init__.cpython-313.pyc +0 -0
  247. package/plugins/testgen/__pycache__/codamosa_engine.cpython-313.pyc +0 -0
  248. package/plugins/testgen/__pycache__/edge_case_synthesizer.cpython-313.pyc +0 -0
  249. package/plugins/testgen/__pycache__/framework_detector.cpython-313.pyc +0 -0
  250. package/plugins/testgen/__pycache__/skeleton_generator.cpython-313.pyc +0 -0
  251. package/plugins/testgen/codamosa_engine.py +402 -0
  252. package/plugins/testgen/edge_case_synthesizer.py +184 -0
  253. package/plugins/testgen/framework_detector.py +271 -0
  254. package/plugins/testgen/skeleton_generator.py +219 -0
  255. package/plugins/viz/__init__.py +0 -0
  256. package/plugins/viz/__pycache__/__init__.cpython-313.pyc +0 -0
  257. package/plugins/viz/__pycache__/ast_parser.cpython-313.pyc +0 -0
  258. package/plugins/viz/__pycache__/diagram_generator.cpython-313.pyc +0 -0
  259. package/plugins/viz/__pycache__/graph_builder.cpython-313.pyc +0 -0
  260. package/plugins/viz/__pycache__/native_parsers.cpython-313.pyc +0 -0
  261. package/plugins/viz/__pycache__/regex_parser.cpython-313.pyc +0 -0
  262. package/plugins/viz/ast_parser.py +139 -0
  263. package/plugins/viz/diagram_generator.py +192 -0
  264. package/plugins/viz/graph_builder.py +444 -0
  265. package/plugins/viz/native_parsers.py +259 -0
  266. package/plugins/viz/regex_parser.py +112 -0
  267. package/pyproject.toml +143 -0
  268. package/registry/__init__.py +1 -0
  269. package/registry/__pycache__/__init__.cpython-313.pyc +0 -0
  270. package/registry/__pycache__/approval_artifact.cpython-313.pyc +0 -0
  271. package/registry/__pycache__/verify_artifact.cpython-313.pyc +0 -0
  272. package/registry/approval_artifact.py +236 -0
  273. package/registry/bundles/algorithms.yaml +45 -0
  274. package/registry/bundles/api-twin.yaml +48 -0
  275. package/registry/bundles/ast-pack.yaml +80 -0
  276. package/registry/bundles/claim-judge.yaml +49 -0
  277. package/registry/bundles/control-plane.yaml +192 -0
  278. package/registry/bundles/data-lineage.yaml +47 -0
  279. package/registry/bundles/delta-classifier.yaml +47 -0
  280. package/registry/bundles/eval-gate.yaml +47 -0
  281. package/registry/bundles/hash-edit.yaml +73 -0
  282. package/registry/bundles/health.yaml +45 -0
  283. package/registry/bundles/hook-governor.yaml +101 -0
  284. package/registry/bundles/incident-replay.yaml +47 -0
  285. package/registry/bundles/lsp-pack.yaml +80 -0
  286. package/registry/bundles/mcp-fabric.yaml +53 -0
  287. package/registry/bundles/plan-council.yaml +56 -0
  288. package/registry/bundles/preflight.yaml +48 -0
  289. package/registry/bundles/proof-gate.yaml +49 -0
  290. package/registry/bundles/remote-supervisor.yaml +49 -0
  291. package/registry/bundles/robotics.yaml +45 -0
  292. package/registry/bundles/secure-worktree-pipeline.yaml +69 -0
  293. package/registry/bundles/security-check.yaml +50 -0
  294. package/registry/bundles/terminal-lane.yaml +61 -0
  295. package/registry/bundles/test-intent-lock.yaml +49 -0
  296. package/registry/bundles/tracebank.yaml +47 -0
  297. package/registry/bundles/vision.yaml +45 -0
  298. package/registry/omg-capability.schema.json +378 -0
  299. package/registry/policy-packs/airgapped.lock.json +11 -0
  300. package/registry/policy-packs/airgapped.signature.json +10 -0
  301. package/registry/policy-packs/airgapped.yaml +16 -0
  302. package/registry/policy-packs/fintech.lock.json +11 -0
  303. package/registry/policy-packs/fintech.signature.json +10 -0
  304. package/registry/policy-packs/fintech.yaml +15 -0
  305. package/registry/policy-packs/locked-prod.lock.json +11 -0
  306. package/registry/policy-packs/locked-prod.signature.json +10 -0
  307. package/registry/policy-packs/locked-prod.yaml +18 -0
  308. package/registry/trusted_signers.json +44 -0
  309. package/registry/verify_artifact.py +493 -0
  310. package/runtime/__init__.py +36 -0
  311. package/runtime/__pycache__/__init__.cpython-313.pyc +0 -0
  312. package/runtime/__pycache__/adoption.cpython-313.pyc +0 -0
  313. package/runtime/__pycache__/agent_selector.cpython-313.pyc +0 -0
  314. package/runtime/__pycache__/api_twin.cpython-313.pyc +0 -0
  315. package/runtime/__pycache__/architecture_signal.cpython-313.pyc +0 -0
  316. package/runtime/__pycache__/artifact_parsers.cpython-313.pyc +0 -0
  317. package/runtime/__pycache__/asset_loader.cpython-313.pyc +0 -0
  318. package/runtime/__pycache__/background_verification.cpython-313.pyc +0 -0
  319. package/runtime/__pycache__/budget_envelopes.cpython-313.pyc +0 -0
  320. package/runtime/__pycache__/business_workflow.cpython-313.pyc +0 -0
  321. package/runtime/__pycache__/canonical_surface.cpython-313.pyc +0 -0
  322. package/runtime/__pycache__/canonical_taxonomy.cpython-313.pyc +0 -0
  323. package/runtime/__pycache__/claim_judge.cpython-313.pyc +0 -0
  324. package/runtime/__pycache__/cli_provider.cpython-313.pyc +0 -0
  325. package/runtime/__pycache__/compat.cpython-313.pyc +0 -0
  326. package/runtime/__pycache__/complexity_scorer.cpython-313.pyc +0 -0
  327. package/runtime/__pycache__/compliance_governor.cpython-313.pyc +0 -0
  328. package/runtime/__pycache__/config_transaction.cpython-313.pyc +0 -0
  329. package/runtime/__pycache__/context_compiler.cpython-313.pyc +0 -0
  330. package/runtime/__pycache__/context_engine.cpython-313.pyc +0 -0
  331. package/runtime/__pycache__/context_limits.cpython-313.pyc +0 -0
  332. package/runtime/__pycache__/contract_compiler.cpython-313.pyc +0 -0
  333. package/runtime/__pycache__/custom_agent_loader.cpython-313.pyc +0 -0
  334. package/runtime/__pycache__/data_lineage.cpython-313.pyc +0 -0
  335. package/runtime/__pycache__/defense_state.cpython-313.pyc +0 -0
  336. package/runtime/__pycache__/delta_classifier.cpython-313.pyc +0 -0
  337. package/runtime/__pycache__/dispatcher.cpython-313.pyc +0 -0
  338. package/runtime/__pycache__/doc_generator.cpython-313.pyc +0 -0
  339. package/runtime/__pycache__/domain_packs.cpython-313.pyc +0 -0
  340. package/runtime/__pycache__/ecosystem.cpython-313.pyc +0 -0
  341. package/runtime/__pycache__/equalizer.cpython-313.pyc +0 -0
  342. package/runtime/__pycache__/eval_gate.cpython-313.pyc +0 -0
  343. package/runtime/__pycache__/evidence_narrator.cpython-313.pyc +0 -0
  344. package/runtime/__pycache__/evidence_query.cpython-313.pyc +0 -0
  345. package/runtime/__pycache__/evidence_registry.cpython-313.pyc +0 -0
  346. package/runtime/__pycache__/evidence_requirements.cpython-313.pyc +0 -0
  347. package/runtime/__pycache__/exec_kernel.cpython-313.pyc +0 -0
  348. package/runtime/__pycache__/explainer_formatter.cpython-313.pyc +0 -0
  349. package/runtime/__pycache__/feature_registry.cpython-313.pyc +0 -0
  350. package/runtime/__pycache__/forge_agents.cpython-313.pyc +0 -0
  351. package/runtime/__pycache__/forge_contracts.cpython-313.pyc +0 -0
  352. package/runtime/__pycache__/forge_domains.cpython-313.pyc +0 -0
  353. package/runtime/__pycache__/forge_run_id.cpython-313.pyc +0 -0
  354. package/runtime/__pycache__/github_integration.cpython-313.pyc +0 -0
  355. package/runtime/__pycache__/github_review_bot.cpython-313.pyc +0 -0
  356. package/runtime/__pycache__/github_review_contract.cpython-313.pyc +0 -0
  357. package/runtime/__pycache__/github_review_formatter.cpython-313.pyc +0 -0
  358. package/runtime/__pycache__/guide_assert.cpython-313.pyc +0 -0
  359. package/runtime/__pycache__/hook_governor.cpython-313.pyc +0 -0
  360. package/runtime/__pycache__/host_parity.cpython-313.pyc +0 -0
  361. package/runtime/__pycache__/incident_replay.cpython-313.pyc +0 -0
  362. package/runtime/__pycache__/install_planner.cpython-313.pyc +0 -0
  363. package/runtime/__pycache__/interaction_journal.cpython-313.pyc +0 -0
  364. package/runtime/__pycache__/issue_surface.cpython-313.pyc +0 -0
  365. package/runtime/__pycache__/legacy_compat.cpython-313.pyc +0 -0
  366. package/runtime/__pycache__/mcp_config_writers.cpython-313.pyc +0 -0
  367. package/runtime/__pycache__/mcp_lifecycle.cpython-313.pyc +0 -0
  368. package/runtime/__pycache__/mcp_memory_server.cpython-313.pyc +0 -0
  369. package/runtime/__pycache__/memory_store.cpython-313.pyc +0 -0
  370. package/runtime/__pycache__/merge_writer.cpython-313.pyc +0 -0
  371. package/runtime/__pycache__/music_omr_testbed.cpython-313.pyc +0 -0
  372. package/runtime/__pycache__/mutation_gate.cpython-313.pyc +0 -0
  373. package/runtime/__pycache__/omc_compat.cpython-313.pyc +0 -0
  374. package/runtime/__pycache__/omg_browser_cli.cpython-313.pyc +0 -0
  375. package/runtime/__pycache__/omg_mcp_server.cpython-313.pyc +0 -0
  376. package/runtime/__pycache__/opus_plan.cpython-313.pyc +0 -0
  377. package/runtime/__pycache__/playwright_adapter.cpython-313.pyc +0 -0
  378. package/runtime/__pycache__/playwright_pack.cpython-313.pyc +0 -0
  379. package/runtime/__pycache__/plugin_diagnostics.cpython-313.pyc +0 -0
  380. package/runtime/__pycache__/plugin_interop.cpython-313.pyc +0 -0
  381. package/runtime/__pycache__/policy_pack_loader.cpython-313.pyc +0 -0
  382. package/runtime/__pycache__/preflight.cpython-313.pyc +0 -0
  383. package/runtime/__pycache__/profile_io.cpython-313.pyc +0 -0
  384. package/runtime/__pycache__/prompt_compiler.cpython-313.pyc +0 -0
  385. package/runtime/__pycache__/proof_chain.cpython-313.pyc +0 -0
  386. package/runtime/__pycache__/proof_gate.cpython-313.pyc +0 -0
  387. package/runtime/__pycache__/provider_parity_eval.cpython-313.pyc +0 -0
  388. package/runtime/__pycache__/release_artifact_audit.cpython-313.pyc +0 -0
  389. package/runtime/__pycache__/release_run_coordinator.cpython-313.pyc +0 -0
  390. package/runtime/__pycache__/release_surface_compiler.cpython-313.pyc +0 -0
  391. package/runtime/__pycache__/release_surface_registry.cpython-313.pyc +0 -0
  392. package/runtime/__pycache__/release_surfaces.cpython-313.pyc +0 -0
  393. package/runtime/__pycache__/remote_supervisor.cpython-313.pyc +0 -0
  394. package/runtime/__pycache__/repro_pack.cpython-313.pyc +0 -0
  395. package/runtime/__pycache__/rollback_manifest.cpython-313.pyc +0 -0
  396. package/runtime/__pycache__/router_critics.cpython-313.pyc +0 -0
  397. package/runtime/__pycache__/router_executor.cpython-313.pyc +0 -0
  398. package/runtime/__pycache__/router_selector.cpython-313.pyc +0 -0
  399. package/runtime/__pycache__/runtime_contracts.cpython-313.pyc +0 -0
  400. package/runtime/__pycache__/runtime_profile.cpython-313.pyc +0 -0
  401. package/runtime/__pycache__/security_check.cpython-313.pyc +0 -0
  402. package/runtime/__pycache__/session_health.cpython-313.pyc +0 -0
  403. package/runtime/__pycache__/skill_evolution.cpython-313.pyc +0 -0
  404. package/runtime/__pycache__/skill_registry.cpython-313.pyc +0 -0
  405. package/runtime/__pycache__/subagent_dispatcher.cpython-313.pyc +0 -0
  406. package/runtime/__pycache__/subscription_tiers.cpython-313.pyc +0 -0
  407. package/runtime/__pycache__/team_router.cpython-313.pyc +0 -0
  408. package/runtime/__pycache__/test_intent_lock.cpython-313-pytest-9.0.2.pyc +0 -0
  409. package/runtime/__pycache__/test_intent_lock.cpython-313.pyc +0 -0
  410. package/runtime/__pycache__/tmux_session_manager.cpython-313.pyc +0 -0
  411. package/runtime/__pycache__/tool_fabric.cpython-313.pyc +0 -0
  412. package/runtime/__pycache__/tool_plan_gate.cpython-313.pyc +0 -0
  413. package/runtime/__pycache__/tool_relevance.cpython-313.pyc +0 -0
  414. package/runtime/__pycache__/tracebank.cpython-313.pyc +0 -0
  415. package/runtime/__pycache__/untrusted_content.cpython-313.pyc +0 -0
  416. package/runtime/__pycache__/validate.cpython-313.pyc +0 -0
  417. package/runtime/__pycache__/verdict_schema.cpython-313.pyc +0 -0
  418. package/runtime/__pycache__/verification_controller.cpython-313.pyc +0 -0
  419. package/runtime/__pycache__/verification_loop.cpython-313.pyc +0 -0
  420. package/runtime/__pycache__/vision_artifacts.cpython-313.pyc +0 -0
  421. package/runtime/__pycache__/vision_cache.cpython-313.pyc +0 -0
  422. package/runtime/__pycache__/vision_jobs.cpython-313.pyc +0 -0
  423. package/runtime/__pycache__/worker_watchdog.cpython-313.pyc +0 -0
  424. package/runtime/adapters/__init__.py +13 -0
  425. package/runtime/adapters/__pycache__/__init__.cpython-313.pyc +0 -0
  426. package/runtime/adapters/__pycache__/claude.cpython-313.pyc +0 -0
  427. package/runtime/adapters/__pycache__/gpt.cpython-313.pyc +0 -0
  428. package/runtime/adapters/__pycache__/local.cpython-313.pyc +0 -0
  429. package/runtime/adapters/claude.py +63 -0
  430. package/runtime/adapters/gpt.py +56 -0
  431. package/runtime/adapters/local.py +56 -0
  432. package/runtime/adoption.py +280 -0
  433. package/runtime/api_twin.py +450 -0
  434. package/runtime/architecture_signal.py +226 -0
  435. package/runtime/artifact_parsers.py +161 -0
  436. package/runtime/asset_loader.py +62 -0
  437. package/runtime/background_verification.py +178 -0
  438. package/runtime/budget_envelopes.py +398 -0
  439. package/runtime/business_workflow.py +234 -0
  440. package/runtime/canonical_surface.py +53 -0
  441. package/runtime/canonical_taxonomy.py +27 -0
  442. package/runtime/claim_judge.py +648 -0
  443. package/runtime/cli_provider.py +105 -0
  444. package/runtime/compat.py +2222 -0
  445. package/runtime/complexity_scorer.py +148 -0
  446. package/runtime/compliance_governor.py +505 -0
  447. package/runtime/config_transaction.py +304 -0
  448. package/runtime/context_compiler.py +131 -0
  449. package/runtime/context_engine.py +708 -0
  450. package/runtime/context_limits.py +363 -0
  451. package/runtime/contract_compiler.py +3664 -0
  452. package/runtime/custom_agent_loader.py +366 -0
  453. package/runtime/data_lineage.py +244 -0
  454. package/runtime/defense_state.py +261 -0
  455. package/runtime/delta_classifier.py +231 -0
  456. package/runtime/dispatcher.py +47 -0
  457. package/runtime/doc_generator.py +319 -0
  458. package/runtime/domain_packs.py +75 -0
  459. package/runtime/ecosystem.py +371 -0
  460. package/runtime/equalizer.py +268 -0
  461. package/runtime/eval_gate.py +96 -0
  462. package/runtime/evidence_narrator.py +147 -0
  463. package/runtime/evidence_query.py +303 -0
  464. package/runtime/evidence_registry.py +16 -0
  465. package/runtime/evidence_requirements.py +157 -0
  466. package/runtime/exec_kernel.py +267 -0
  467. package/runtime/explainer_formatter.py +82 -0
  468. package/runtime/feature_registry.py +109 -0
  469. package/runtime/forge_agents.py +915 -0
  470. package/runtime/forge_contracts.py +519 -0
  471. package/runtime/forge_domains.py +68 -0
  472. package/runtime/forge_run_id.py +86 -0
  473. package/runtime/guide_assert.py +135 -0
  474. package/runtime/hook_governor.py +156 -0
  475. package/runtime/host_parity.py +373 -0
  476. package/runtime/incident_replay.py +310 -0
  477. package/runtime/install_planner.py +617 -0
  478. package/runtime/interaction_journal.py +566 -0
  479. package/runtime/issue_surface.py +472 -0
  480. package/runtime/legacy_compat.py +7 -0
  481. package/runtime/mcp_config_writers.py +360 -0
  482. package/runtime/mcp_lifecycle.py +175 -0
  483. package/runtime/mcp_memory_server.py +220 -0
  484. package/runtime/memory_parsers/__init__.py +0 -0
  485. package/runtime/memory_parsers/__pycache__/__init__.cpython-313.pyc +0 -0
  486. package/runtime/memory_parsers/__pycache__/chatgpt_parser.cpython-313.pyc +0 -0
  487. package/runtime/memory_parsers/__pycache__/claude_import.cpython-313.pyc +0 -0
  488. package/runtime/memory_parsers/__pycache__/export.cpython-313.pyc +0 -0
  489. package/runtime/memory_parsers/__pycache__/gemini_import.cpython-313.pyc +0 -0
  490. package/runtime/memory_parsers/__pycache__/kimi_import.cpython-313.pyc +0 -0
  491. package/runtime/memory_parsers/chatgpt_parser.py +257 -0
  492. package/runtime/memory_parsers/claude_import.py +107 -0
  493. package/runtime/memory_parsers/export.py +97 -0
  494. package/runtime/memory_parsers/gemini_import.py +91 -0
  495. package/runtime/memory_parsers/kimi_import.py +91 -0
  496. package/runtime/memory_store.py +1182 -0
  497. package/runtime/merge_writer.py +445 -0
  498. package/runtime/music_omr_testbed.py +336 -0
  499. package/runtime/mutation_gate.py +320 -0
  500. package/runtime/omc_compat.py +7 -0
  501. package/runtime/omg_browser_cli.py +95 -0
  502. package/runtime/omg_compat_contract_snapshot.json +936 -0
  503. package/runtime/omg_contract_snapshot.json +936 -0
  504. package/runtime/omg_mcp_server.py +306 -0
  505. package/runtime/playwright_adapter.py +39 -0
  506. package/runtime/playwright_pack.py +253 -0
  507. package/runtime/plugin_diagnostics.py +308 -0
  508. package/runtime/plugin_interop.py +1060 -0
  509. package/runtime/policy_pack_loader.py +147 -0
  510. package/runtime/preflight.py +135 -0
  511. package/runtime/profile_io.py +328 -0
  512. package/runtime/proof_chain.py +472 -0
  513. package/runtime/proof_gate.py +442 -0
  514. package/runtime/provider_parity_eval.py +109 -0
  515. package/runtime/providers/__init__.py +0 -0
  516. package/runtime/providers/__pycache__/__init__.cpython-313.pyc +0 -0
  517. package/runtime/providers/__pycache__/codex_provider.cpython-313.pyc +0 -0
  518. package/runtime/providers/__pycache__/gemini_provider.cpython-313.pyc +0 -0
  519. package/runtime/providers/__pycache__/kimi_provider.cpython-313.pyc +0 -0
  520. package/runtime/providers/__pycache__/opencode_provider.cpython-313.pyc +0 -0
  521. package/runtime/providers/codex_provider.py +129 -0
  522. package/runtime/providers/gemini_provider.py +143 -0
  523. package/runtime/providers/kimi_provider.py +167 -0
  524. package/runtime/providers/opencode_provider.py +99 -0
  525. package/runtime/release_artifact_audit.py +556 -0
  526. package/runtime/release_run_coordinator.py +574 -0
  527. package/runtime/release_surface_compiler.py +643 -0
  528. package/runtime/release_surface_registry.py +283 -0
  529. package/runtime/release_surfaces.py +320 -0
  530. package/runtime/remote_supervisor.py +79 -0
  531. package/runtime/repro_pack.py +398 -0
  532. package/runtime/rollback_manifest.py +143 -0
  533. package/runtime/router_critics.py +229 -0
  534. package/runtime/router_executor.py +142 -0
  535. package/runtime/router_selector.py +99 -0
  536. package/runtime/runtime_contracts.py +292 -0
  537. package/runtime/runtime_profile.py +133 -0
  538. package/runtime/security_check.py +1094 -0
  539. package/runtime/session_health.py +546 -0
  540. package/runtime/skill_evolution.py +221 -0
  541. package/runtime/skill_registry.py +53 -0
  542. package/runtime/subagent_dispatcher.py +604 -0
  543. package/runtime/subscription_tiers.py +258 -0
  544. package/runtime/team_router.py +1399 -0
  545. package/runtime/test_intent_lock.py +543 -0
  546. package/runtime/tmux_session_manager.py +172 -0
  547. package/runtime/tool_fabric.py +570 -0
  548. package/runtime/tool_plan_gate.py +460 -0
  549. package/runtime/tracebank.py +125 -0
  550. package/runtime/untrusted_content.py +360 -0
  551. package/runtime/validate.py +293 -0
  552. package/runtime/verdict_schema.py +198 -0
  553. package/runtime/verification_controller.py +235 -0
  554. package/runtime/verification_loop.py +73 -0
  555. package/runtime/vision_artifacts.py +31 -0
  556. package/runtime/vision_cache.py +38 -0
  557. package/runtime/vision_jobs.py +92 -0
  558. package/runtime/worker_watchdog.py +526 -0
  559. package/scripts/__pycache__/audit-published-artifact.cpython-313.pyc +0 -0
  560. package/scripts/__pycache__/check-doc-parity.cpython-313.pyc +0 -0
  561. package/scripts/__pycache__/check-omg-standalone-clean.cpython-313.pyc +0 -0
  562. package/scripts/__pycache__/github_review_helpers.cpython-313.pyc +0 -0
  563. package/scripts/__pycache__/omg.cpython-313.pyc +0 -0
  564. package/scripts/__pycache__/prepare-release-proof-fixtures.cpython-313.pyc +0 -0
  565. package/scripts/__pycache__/sync-release-identity.cpython-313.pyc +0 -0
  566. package/scripts/__pycache__/validate-release-identity.cpython-313.pyc +0 -0
  567. package/scripts/audit-published-artifact.py +59 -0
  568. package/scripts/check-omg-compat-contract-snapshot.py +137 -0
  569. package/scripts/check-omg-contract-snapshot.py +12 -0
  570. package/scripts/check-omg-public-ready.py +273 -0
  571. package/scripts/check-omg-standalone-clean.py +133 -0
  572. package/scripts/emit_host_parity.py +72 -0
  573. package/scripts/legacy_to_omg_migrate.py +29 -0
  574. package/scripts/migrate-legacy.py +464 -0
  575. package/scripts/omc_to_omg_migrate.py +12 -0
  576. package/scripts/omg.py +2962 -0
  577. package/scripts/pre-release-check.sh +38 -0
  578. package/scripts/prepare-release-proof-fixtures.py +602 -0
  579. package/scripts/print-canonical-version.py +80 -0
  580. package/scripts/settings-merge.py +289 -0
  581. package/scripts/sync-release-identity.py +481 -0
  582. package/scripts/validate-release-identity.py +632 -0
  583. package/scripts/verify-no-omc.sh +5 -0
  584. package/scripts/verify-standalone.sh +35 -0
  585. package/settings.json +751 -0
  586. package/tools/__init__.py +2 -0
  587. package/tools/__pycache__/__init__.cpython-313.pyc +0 -0
  588. package/tools/__pycache__/browser_consent.cpython-313.pyc +0 -0
  589. package/tools/__pycache__/browser_stealth.cpython-313.pyc +0 -0
  590. package/tools/__pycache__/browser_tool.cpython-313.pyc +0 -0
  591. package/tools/__pycache__/changelog_generator.cpython-313.pyc +0 -0
  592. package/tools/__pycache__/commit_splitter.cpython-313.pyc +0 -0
  593. package/tools/__pycache__/config_discovery.cpython-313.pyc +0 -0
  594. package/tools/__pycache__/config_merger.cpython-313.pyc +0 -0
  595. package/tools/__pycache__/dashboard_generator.cpython-313.pyc +0 -0
  596. package/tools/__pycache__/git_inspector.cpython-313.pyc +0 -0
  597. package/tools/__pycache__/lsp_client.cpython-313.pyc +0 -0
  598. package/tools/__pycache__/lsp_operations.cpython-313.pyc +0 -0
  599. package/tools/__pycache__/pr_generator.cpython-313.pyc +0 -0
  600. package/tools/__pycache__/python_repl.cpython-313.pyc +0 -0
  601. package/tools/__pycache__/python_sandbox.cpython-313.pyc +0 -0
  602. package/tools/__pycache__/session_snapshot.cpython-313.pyc +0 -0
  603. package/tools/__pycache__/ssh_manager.cpython-313.pyc +0 -0
  604. package/tools/__pycache__/theme_engine.cpython-313.pyc +0 -0
  605. package/tools/__pycache__/theme_selector.cpython-313.pyc +0 -0
  606. package/tools/__pycache__/web_search.cpython-313.pyc +0 -0
  607. package/tools/browser_consent.py +289 -0
  608. package/tools/browser_stealth.py +481 -0
  609. package/tools/browser_tool.py +448 -0
  610. package/tools/changelog_generator.py +347 -0
  611. package/tools/commit_splitter.py +749 -0
  612. package/tools/config_discovery.py +151 -0
  613. package/tools/config_merger.py +449 -0
  614. package/tools/dashboard_generator.py +300 -0
  615. package/tools/git_inspector.py +298 -0
  616. package/tools/lsp_client.py +275 -0
  617. package/tools/lsp_discovery.py +231 -0
  618. package/tools/lsp_operations.py +392 -0
  619. package/tools/pr_generator.py +404 -0
  620. package/tools/python_repl.py +712 -0
  621. package/tools/python_sandbox.py +768 -0
  622. package/tools/search_providers/__init__.py +77 -0
  623. package/tools/search_providers/__pycache__/__init__.cpython-313.pyc +0 -0
  624. package/tools/search_providers/__pycache__/brave.cpython-313.pyc +0 -0
  625. package/tools/search_providers/__pycache__/exa.cpython-313.pyc +0 -0
  626. package/tools/search_providers/__pycache__/jina.cpython-313.pyc +0 -0
  627. package/tools/search_providers/__pycache__/perplexity.cpython-313.pyc +0 -0
  628. package/tools/search_providers/__pycache__/synthetic.cpython-313.pyc +0 -0
  629. package/tools/search_providers/brave.py +115 -0
  630. package/tools/search_providers/exa.py +116 -0
  631. package/tools/search_providers/jina.py +104 -0
  632. package/tools/search_providers/perplexity.py +139 -0
  633. package/tools/search_providers/synthetic.py +74 -0
  634. package/tools/session_snapshot.py +851 -0
  635. package/tools/ssh_manager.py +912 -0
  636. package/tools/theme_engine.py +296 -0
  637. package/tools/theme_selector.py +137 -0
  638. package/tools/web_search.py +675 -0
@@ -0,0 +1,712 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ IPython Kernel Integration for OMG
4
+
5
+ Provides persistent REPL sessions with IPython kernel support (optional)
6
+ and stdlib fallback via code.InteractiveConsole.
7
+
8
+ Feature flag: OMG_PYTHON_REPL_ENABLED (default: False)
9
+ """
10
+
11
+ import ast
12
+ import code
13
+ import contextlib
14
+ import io
15
+ import json
16
+ import os
17
+ import sys
18
+ import traceback
19
+ import uuid
20
+ from datetime import datetime, timezone
21
+ from typing import Any, Dict, Generator, List, Optional, Union, cast
22
+
23
+
24
+ # --- Lazy imports for hooks/_common.py ---
25
+
26
+ _get_feature_flag = None
27
+ _atomic_json_write = None
28
+ _validate_opaque_identifier = None
29
+ _ensure_path_within_dir = None
30
+
31
+
32
+ def _ensure_imports():
33
+ """Lazy import feature flag and atomic write from hooks/_common.py."""
34
+ global _get_feature_flag, _atomic_json_write, _validate_opaque_identifier, _ensure_path_within_dir
35
+ if _get_feature_flag is not None:
36
+ return
37
+ repo_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
38
+ if repo_root not in sys.path:
39
+ sys.path.insert(0, repo_root)
40
+ try:
41
+ from hooks._common import get_feature_flag as _gff
42
+ from hooks._common import atomic_json_write as _ajw
43
+ from hooks.security_validators import ensure_path_within_dir as _epwd
44
+ from hooks.security_validators import validate_opaque_identifier as _voi
45
+ _get_feature_flag = _gff
46
+ _atomic_json_write = _ajw
47
+ _validate_opaque_identifier = _voi
48
+ _ensure_path_within_dir = _epwd
49
+ except ImportError:
50
+ pass
51
+
52
+
53
+ # --- Optional jupyter_client ---
54
+
55
+ _jupyter_client = None
56
+ _HAS_JUPYTER: Optional[bool] = None
57
+
58
+
59
+ def _check_jupyter() -> bool:
60
+ """Check if jupyter_client is available (cached after first check)."""
61
+ global _HAS_JUPYTER, _jupyter_client
62
+ if _HAS_JUPYTER is None:
63
+ try:
64
+ import jupyter_client as _jc # pyright: ignore[reportMissingImports]
65
+ _jupyter_client = _jc
66
+ _HAS_JUPYTER = True # pyright: ignore[reportConstantRedefinition]
67
+ except ImportError:
68
+ _HAS_JUPYTER = False # pyright: ignore[reportConstantRedefinition]
69
+ return _HAS_JUPYTER
70
+
71
+
72
+ # --- Feature flag ---
73
+
74
+ def _is_enabled() -> bool:
75
+ """Check if Python REPL feature is enabled."""
76
+ # Fast path: check env var directly
77
+ env_val = os.environ.get("OMG_PYTHON_REPL_ENABLED", "").lower()
78
+ if env_val in ("0", "false", "no"):
79
+ return False
80
+ if env_val in ("1", "true", "yes"):
81
+ return True
82
+ # Fallback to hooks/_common.get_feature_flag
83
+ _ensure_imports()
84
+ if _get_feature_flag is not None:
85
+ return _get_feature_flag("PYTHON_REPL", default=False)
86
+ return False
87
+
88
+
89
+ def _get_sandbox_flag() -> bool:
90
+ """Check if sandbox mode is enabled for the REPL."""
91
+ env_val = os.environ.get("OMG_REPL_SANDBOX_ENABLED", "").lower()
92
+ if env_val in ("0", "false", "no"):
93
+ return False
94
+ if env_val in ("1", "true", "yes"):
95
+ return True
96
+ _ensure_imports()
97
+ if _get_feature_flag is not None:
98
+ return _get_feature_flag("REPL_SANDBOX", default=False)
99
+ return False
100
+
101
+
102
+ def _get_helpers_flag() -> bool:
103
+ """Check if REPL prelude helpers are enabled."""
104
+ env_val = os.environ.get("OMG_REPL_HELPERS_ENABLED", "").lower()
105
+ if env_val in ("0", "false", "no"):
106
+ return False
107
+ if env_val in ("1", "true", "yes"):
108
+ return True
109
+ _ensure_imports()
110
+ if _get_feature_flag is not None:
111
+ return _get_feature_flag("REPL_HELPERS", default=False)
112
+ return False
113
+
114
+
115
+ def _build_prelude_namespace() -> dict[str, Any]:
116
+ """Build the prelude namespace with helper functions for REPL sessions.
117
+
118
+ Returns a dict of helper functions injected into every session when
119
+ OMG_REPL_HELPERS_ENABLED=true. All helpers use stdlib only and handle
120
+ exceptions gracefully.
121
+ """
122
+ import re as _re
123
+
124
+ def read_file(path: str) -> str:
125
+ """Read file content. Returns empty string on error."""
126
+ try:
127
+ with open(path, "r") as f:
128
+ return f.read()
129
+ except Exception:
130
+ return ""
131
+
132
+ def write_file(path: str, content: str) -> bool:
133
+ """Write content to file. Blocked in sandbox mode. Returns False on error."""
134
+ if _get_sandbox_flag():
135
+ return False
136
+ try:
137
+ with open(path, "w") as f:
138
+ f.write(content)
139
+ return True
140
+ except Exception:
141
+ return False
142
+
143
+ def lines(path: str) -> list[str]:
144
+ """Read file lines as list. Returns empty list on error."""
145
+ try:
146
+ with open(path, "r") as f:
147
+ return f.read().splitlines()
148
+ except Exception:
149
+ return []
150
+
151
+ def search_code(pattern: str, path: str = ".", ext: str | None = None) -> list[dict[str, Any]]:
152
+ """Grep-like search across files. Returns list of {file, line, match} dicts."""
153
+ results = []
154
+ try:
155
+ compiled = _re.compile(pattern)
156
+ for root, _dirs, files in os.walk(path):
157
+ for fname in files:
158
+ if ext is not None and not fname.endswith(ext):
159
+ continue
160
+ fpath = os.path.join(root, fname)
161
+ try:
162
+ with open(fpath, "r", errors="ignore") as f:
163
+ for lineno, line_text in enumerate(f, 1):
164
+ if compiled.search(line_text):
165
+ results.append({
166
+ "file": fpath,
167
+ "line": lineno,
168
+ "match": line_text.rstrip(),
169
+ })
170
+ except Exception:
171
+ continue
172
+ except Exception:
173
+ pass
174
+ return results
175
+
176
+ def grep(pattern: str, text: str) -> list[str]:
177
+ """Regex grep on a string. Returns matching lines."""
178
+ try:
179
+ compiled = _re.compile(pattern)
180
+ return [line for line in text.splitlines() if compiled.search(line)]
181
+ except Exception:
182
+ return []
183
+
184
+ def insert_at(lines_list: list[str], index: int, new_line: str) -> list[str]:
185
+ """Insert a line at index. Returns new list."""
186
+ try:
187
+ result = list(lines_list)
188
+ result.insert(index, new_line)
189
+ return result
190
+ except Exception:
191
+ return list(lines_list)
192
+
193
+ def delete_lines(lines_list: list[str], start: int, end: int) -> list[str]:
194
+ """Delete lines from start to end (exclusive). Returns new list."""
195
+ try:
196
+ result = list(lines_list)
197
+ del result[start:end]
198
+ return result
199
+ except Exception:
200
+ return list(lines_list)
201
+
202
+ return {
203
+ "read_file": read_file,
204
+ "write_file": write_file,
205
+ "lines": lines,
206
+ "search_code": search_code,
207
+ "grep": grep,
208
+ "insert_at": insert_at,
209
+ "delete_lines": delete_lines,
210
+ }
211
+
212
+ _DISABLED_MSG = "Python REPL feature is disabled. Set OMG_PYTHON_REPL_ENABLED=true"
213
+
214
+
215
+ # --- Session storage ---
216
+
217
+ _sessions: Dict[str, Dict[str, Any]] = {}
218
+ _STATE_DIR = ".omg/state/repl_sessions"
219
+
220
+
221
+ def _now_iso() -> str:
222
+ """Current UTC time as ISO-8601 string."""
223
+ return datetime.now(timezone.utc).isoformat()
224
+
225
+
226
+ def _exec_kernel_metadata() -> Dict[str, Any]:
227
+ try:
228
+ from runtime.exec_kernel import get_exec_kernel
229
+ from runtime.release_run_coordinator import resolve_current_run_id
230
+
231
+ project_dir = os.environ.get("CLAUDE_PROJECT_DIR", os.getcwd())
232
+ run_id = resolve_current_run_id(project_dir)
233
+ kernel = get_exec_kernel(project_dir)
234
+ return {
235
+ "run_id": run_id,
236
+ "enabled": kernel.enabled,
237
+ "attach_log": kernel.attach_log(run_id) if run_id else "",
238
+ "evidence_hooks": [".omg/evidence/subagents"],
239
+ }
240
+ except Exception:
241
+ return {"run_id": None, "enabled": False, "attach_log": "", "evidence_hooks": []}
242
+
243
+
244
+ def _validate_session_id(session_id: str) -> str:
245
+ """Validate a caller-supplied session identifier."""
246
+ _ensure_imports()
247
+ if _validate_opaque_identifier is None:
248
+ raise ValueError("Invalid session_id: validator unavailable")
249
+ return _validate_opaque_identifier(session_id, "session_id")
250
+
251
+
252
+ def _resolve_session_path(session_id: str) -> str:
253
+ """Resolve the on-disk session path and reject directory escapes."""
254
+ _ensure_imports()
255
+ if _ensure_path_within_dir is None:
256
+ raise ValueError("Invalid session_id: path validator unavailable")
257
+ state_dir = os.path.abspath(_STATE_DIR)
258
+ return _ensure_path_within_dir(state_dir, os.path.join(state_dir, f"{session_id}.json"))
259
+
260
+
261
+ def _persist_session(session_id: str) -> None:
262
+ """Persist session metadata to disk (best-effort)."""
263
+ if session_id not in _sessions:
264
+ return
265
+ _ensure_imports()
266
+ if _atomic_json_write is None:
267
+ return
268
+ session = _sessions[session_id]
269
+ meta = {
270
+ "session_id": session["session_id"],
271
+ "created_at": session["created_at"],
272
+ "last_used": session["last_used"],
273
+ "exec_count": session["exec_count"],
274
+ "backend": session.get("backend", "stdlib"),
275
+ }
276
+ try:
277
+ safe_session_id = _validate_session_id(session_id)
278
+ path = _resolve_session_path(safe_session_id)
279
+ _atomic_json_write(path, meta)
280
+ except (OSError, ValueError):
281
+ pass # best-effort
282
+
283
+
284
+ def _session_info(session: Dict[str, Any]) -> Dict[str, Any]:
285
+ """Extract public session info (no internal _backend key)."""
286
+ return {
287
+ "session_id": session["session_id"],
288
+ "created_at": session["created_at"],
289
+ "last_used": session["last_used"],
290
+ "exec_count": session["exec_count"],
291
+ "backend": session.get("backend", "stdlib"),
292
+ }
293
+
294
+
295
+ # --- IPython Kernel Backend ---
296
+
297
+ class _IPythonSession:
298
+ """Wraps a jupyter_client kernel for code execution."""
299
+
300
+ def __init__(self):
301
+ if _jupyter_client is None:
302
+ raise RuntimeError("jupyter_client unavailable")
303
+ km, kc = _jupyter_client.manager.start_new_kernel(kernel_name="python3")
304
+ self.kernel_manager = km
305
+ self.kernel_client = kc
306
+ self.kernel_client.start_channels()
307
+ self.kernel_client.wait_for_ready(timeout=30)
308
+
309
+ def execute(self, code_str: str) -> Dict[str, Any]:
310
+ """Execute code on the IPython kernel and collect output."""
311
+ msg_id = self.kernel_client.execute(code_str)
312
+ stdout_parts: List[str] = []
313
+ stderr_parts: List[str] = []
314
+ result = None
315
+ error = None
316
+
317
+ while True:
318
+ try:
319
+ msg = self.kernel_client.get_iopub_msg(timeout=30)
320
+ except Exception:
321
+ break
322
+ if msg["parent_header"].get("msg_id") != msg_id:
323
+ continue
324
+ msg_type = msg["msg_type"]
325
+ content = msg["content"]
326
+ if msg_type == "stream":
327
+ if content["name"] == "stdout":
328
+ stdout_parts.append(content["text"])
329
+ elif content["name"] == "stderr":
330
+ stderr_parts.append(content["text"])
331
+ elif msg_type in ("execute_result", "display_data"):
332
+ result = content["data"].get("text/plain", "")
333
+ elif msg_type == "error":
334
+ tb = content.get("traceback", [content.get("evalue", "")])
335
+ error = "\n".join(tb)
336
+ elif msg_type == "status" and content.get("execution_state") == "idle":
337
+ break
338
+
339
+ return {
340
+ "stdout": "".join(stdout_parts),
341
+ "stderr": "".join(stderr_parts),
342
+ "result": result,
343
+ "error": error,
344
+ }
345
+
346
+ def stream_execute(self, code_str: str) -> Generator[Dict[str, str], None, None]:
347
+ """Execute code on the kernel and yield output chunks."""
348
+ msg_id = self.kernel_client.execute(code_str)
349
+ while True:
350
+ try:
351
+ msg = self.kernel_client.get_iopub_msg(timeout=30)
352
+ except Exception:
353
+ break
354
+ if msg["parent_header"].get("msg_id") != msg_id:
355
+ continue
356
+ msg_type = msg["msg_type"]
357
+ content = msg["content"]
358
+ if msg_type == "stream":
359
+ yield {"type": content["name"], "data": content["text"]}
360
+ elif msg_type in ("execute_result", "display_data"):
361
+ yield {"type": "result", "data": content["data"].get("text/plain", "")}
362
+ elif msg_type == "error":
363
+ tb = content.get("traceback", [content.get("evalue", "")])
364
+ yield {"type": "error", "data": "\n".join(tb)}
365
+ elif msg_type == "status" and content.get("execution_state") == "idle":
366
+ break
367
+
368
+ def close(self):
369
+ """Shutdown kernel and cleanup."""
370
+ try:
371
+ self.kernel_client.stop_channels()
372
+ except Exception:
373
+ pass
374
+ try:
375
+ self.kernel_manager.shutdown_kernel(now=True)
376
+ except Exception:
377
+ pass
378
+
379
+
380
+ # --- Stdlib Fallback Backend ---
381
+
382
+ class _StdlibSession:
383
+ """Uses code.InteractiveConsole with stdout/stderr capture."""
384
+
385
+ def __init__(self):
386
+ self.namespace: Dict[str, Any] = {"__builtins__": __builtins__}
387
+ self._console = code.InteractiveConsole(locals=self.namespace)
388
+
389
+ def execute(self, code_str: str) -> Dict[str, Any]:
390
+ """Execute code with stdout/stderr capture via contextlib."""
391
+ stdout_buf = io.StringIO()
392
+ stderr_buf = io.StringIO()
393
+ result = None
394
+ error = None
395
+
396
+ try:
397
+ with contextlib.redirect_stdout(stdout_buf), \
398
+ contextlib.redirect_stderr(stderr_buf):
399
+ # Try to evaluate as single expression first
400
+ try:
401
+ tree = ast.parse(code_str, mode="eval")
402
+ compiled = compile(tree, "<repl>", "eval")
403
+ result_val = eval(compiled, self.namespace) # noqa: S307
404
+ if result_val is not None:
405
+ result = repr(result_val)
406
+ except SyntaxError:
407
+ # Fall back to exec for statements
408
+ tree = ast.parse(code_str, mode="exec")
409
+ compiled = compile(tree, "<repl>", "exec")
410
+ exec(compiled, self.namespace) # noqa: S102
411
+ except Exception:
412
+ error = traceback.format_exc()
413
+
414
+ return {
415
+ "stdout": stdout_buf.getvalue(),
416
+ "stderr": stderr_buf.getvalue(),
417
+ "result": result,
418
+ "error": error,
419
+ }
420
+
421
+ def stream_execute(self, code_str: str) -> Generator[Dict[str, str], None, None]:
422
+ """Execute code and yield output chunks.
423
+
424
+ Note: stdlib backend doesn't support true streaming —
425
+ executes fully then yields collected output.
426
+ """
427
+ output = self.execute(code_str)
428
+ if output["stdout"]:
429
+ yield {"type": "stdout", "data": output["stdout"]}
430
+ if output["stderr"]:
431
+ yield {"type": "stderr", "data": output["stderr"]}
432
+ if output["result"] is not None:
433
+ yield {"type": "result", "data": output["result"]}
434
+ if output["error"]:
435
+ yield {"type": "error", "data": output["error"]}
436
+
437
+ def close(self):
438
+ """Cleanup namespace."""
439
+ self.namespace.clear()
440
+
441
+
442
+ # --- Public API ---
443
+
444
+ def start_repl_session(session_id: Optional[str] = None) -> Dict[str, Any]:
445
+ """Start or resume a persistent REPL session.
446
+
447
+ Args:
448
+ session_id: Optional ID to resume an existing session.
449
+ If None, creates a new session with a UUID.
450
+
451
+ Returns:
452
+ Session info dict: {session_id, created_at, last_used, exec_count, backend}
453
+ or {"error": "..."} if feature flag is disabled.
454
+ """
455
+ if not _is_enabled():
456
+ return {"error": _DISABLED_MSG}
457
+
458
+ if session_id is not None:
459
+ try:
460
+ session_id = _validate_session_id(session_id)
461
+ except ValueError as exc:
462
+ return {"error": str(exc)}
463
+
464
+ # Resume existing session
465
+ if session_id and session_id in _sessions:
466
+ session = _sessions[session_id]
467
+ session["last_used"] = _now_iso()
468
+ _persist_session(session_id)
469
+ return _session_info(session)
470
+
471
+ # Create new session
472
+ new_id = session_id or str(uuid.uuid4())
473
+
474
+ # Try IPython kernel first, fall back to stdlib
475
+ _check_jupyter()
476
+ backend_name = "stdlib"
477
+ backend = None
478
+
479
+ if _HAS_JUPYTER:
480
+ try:
481
+ backend = _IPythonSession()
482
+ backend_name = "ipython"
483
+ except Exception:
484
+ backend = _StdlibSession()
485
+ else:
486
+ backend = _StdlibSession()
487
+
488
+ now = _now_iso()
489
+ _sessions[new_id] = {
490
+ "session_id": new_id,
491
+ "created_at": now,
492
+ "last_used": now,
493
+ "exec_count": 0,
494
+ "backend": backend_name,
495
+ "_backend": backend,
496
+ }
497
+
498
+ # Inject prelude helpers if enabled
499
+ if _get_helpers_flag():
500
+ prelude = _build_prelude_namespace()
501
+ backend_any = backend
502
+ namespace_obj = getattr(backend_any, "namespace", None)
503
+ if isinstance(namespace_obj, dict):
504
+ namespace_obj.update(prelude)
505
+ _persist_session(new_id)
506
+
507
+ return _session_info(_sessions[new_id])
508
+
509
+
510
+ def execute_code(session_id: str, code_str: str) -> Dict[str, Any]:
511
+ """Execute code in a session.
512
+
513
+ Args:
514
+ session_id: Session ID from start_repl_session()
515
+ code_str: Python code to execute
516
+
517
+ Returns:
518
+ {stdout, stderr, result, error, exec_count}
519
+ or {"error": "..."} if feature flag is disabled or session not found.
520
+ """
521
+ if not _is_enabled():
522
+ return {"error": _DISABLED_MSG}
523
+
524
+ if session_id not in _sessions:
525
+ return {"error": f"Session not found: {session_id}"}
526
+
527
+ # Sandbox integration: if sandbox enabled, route through sandboxed executor
528
+ if _get_sandbox_flag():
529
+ from tools.python_sandbox import execute_sandboxed
530
+ session = _sessions[session_id]
531
+ backend_any = session.get("_backend")
532
+ namespace_obj = getattr(backend_any, "namespace", None)
533
+ ns = namespace_obj if isinstance(namespace_obj, dict) else None
534
+ output = execute_sandboxed(code_str, namespace=ns)
535
+ session["exec_count"] += 1
536
+ session["last_used"] = _now_iso()
537
+ output["exec_count"] = session["exec_count"]
538
+ output["exec_kernel"] = _exec_kernel_metadata()
539
+ _persist_session(session_id)
540
+ return output
541
+
542
+ session = _sessions[session_id]
543
+ backend = session["_backend"]
544
+ output: Dict[str, Any]
545
+
546
+ try:
547
+ output = cast(Dict[str, Any], backend.execute(code_str))
548
+ except Exception as e:
549
+ output = {
550
+ "stdout": "",
551
+ "stderr": "",
552
+ "result": None,
553
+ "error": f"{type(e).__name__}: {e}",
554
+ }
555
+
556
+ session["exec_count"] += 1
557
+ session["last_used"] = _now_iso()
558
+ output["exec_count"] = session["exec_count"]
559
+ output["exec_kernel"] = _exec_kernel_metadata()
560
+
561
+ _persist_session(session_id)
562
+ return output
563
+
564
+
565
+ def get_session(session_id: str) -> Optional[Dict[str, Any]]:
566
+ """Get session info by ID.
567
+
568
+ Args:
569
+ session_id: Session ID to look up
570
+
571
+ Returns:
572
+ Session info dict, None if not found,
573
+ or {"error": "..."} if feature flag is disabled.
574
+ """
575
+ if not _is_enabled():
576
+ return {"error": _DISABLED_MSG}
577
+
578
+ if session_id not in _sessions:
579
+ return None
580
+
581
+ return _session_info(_sessions[session_id])
582
+
583
+
584
+ def close_session(session_id: str) -> Union[bool, Dict[str, Any]]:
585
+ """Close and cleanup a session.
586
+
587
+ Args:
588
+ session_id: Session ID to close
589
+
590
+ Returns:
591
+ True if closed, False if not found,
592
+ or {"error": "..."} if feature flag is disabled.
593
+ """
594
+ if not _is_enabled():
595
+ return {"error": _DISABLED_MSG}
596
+
597
+ if session_id not in _sessions:
598
+ return False
599
+
600
+ session = _sessions.pop(session_id)
601
+ backend = session.get("_backend")
602
+ if backend is not None:
603
+ try:
604
+ backend.close()
605
+ except Exception:
606
+ pass
607
+
608
+ return True
609
+
610
+
611
+ def list_sessions() -> Union[List[Dict[str, Any]], Dict[str, Any]]:
612
+ """List all active sessions.
613
+
614
+ Returns:
615
+ List of session info dicts,
616
+ or {"error": "..."} if feature flag is disabled.
617
+ """
618
+ if not _is_enabled():
619
+ return {"error": _DISABLED_MSG}
620
+
621
+ return [_session_info(s) for s in _sessions.values()]
622
+
623
+
624
+ def stream_execute(
625
+ session_id: str, code_str: str
626
+ ) -> Generator[Dict[str, str], None, None]:
627
+ """Execute code and stream output chunks.
628
+
629
+ Args:
630
+ session_id: Session ID from start_repl_session()
631
+ code_str: Python code to execute
632
+
633
+ Yields:
634
+ Dicts with keys: type ("stdout"|"stderr"|"result"|"error"), data (str)
635
+ """
636
+ if not _is_enabled():
637
+ yield {"type": "error", "data": _DISABLED_MSG}
638
+ return
639
+
640
+ if session_id not in _sessions:
641
+ yield {"type": "error", "data": f"Session not found: {session_id}"}
642
+ return
643
+
644
+ session = _sessions[session_id]
645
+ backend = session["_backend"]
646
+
647
+ try:
648
+ for chunk in backend.stream_execute(code_str):
649
+ yield chunk
650
+ except Exception as e:
651
+ yield {"type": "error", "data": f"{type(e).__name__}: {e}"}
652
+
653
+ session["exec_count"] += 1
654
+ session["last_used"] = _now_iso()
655
+ _persist_session(session_id)
656
+
657
+
658
+ # --- CLI Interface ---
659
+
660
+ def _cli_main():
661
+ """CLI entry point for python_repl.py."""
662
+ import argparse
663
+
664
+ parser = argparse.ArgumentParser(
665
+ description="OMG Python REPL Tool — persistent sessions with IPython or stdlib",
666
+ formatter_class=argparse.RawDescriptionHelpFormatter,
667
+ )
668
+ parser.add_argument("--exec", dest="code", help="Execute Python code")
669
+ parser.add_argument("--session-id", dest="session_id", help="Session ID to use")
670
+ parser.add_argument(
671
+ "--list-sessions", action="store_true", help="List active sessions"
672
+ )
673
+ parser.add_argument(
674
+ "--close-session", dest="close_id", help="Close a session by ID"
675
+ )
676
+ parser.add_argument(
677
+ "--stream", action="store_true", help="Stream output (with --exec)"
678
+ )
679
+
680
+ args = parser.parse_args()
681
+
682
+ if args.list_sessions:
683
+ result = list_sessions()
684
+ print(json.dumps(result, indent=2))
685
+ return
686
+
687
+ if args.close_id:
688
+ result = close_session(args.close_id)
689
+ print(json.dumps({"closed": result}))
690
+ return
691
+
692
+ if args.code:
693
+ session = start_repl_session(session_id=args.session_id)
694
+ if "error" in session:
695
+ print(json.dumps(session))
696
+ sys.exit(1)
697
+
698
+ sid = session["session_id"]
699
+
700
+ if args.stream:
701
+ for chunk in stream_execute(sid, args.code):
702
+ print(json.dumps(chunk))
703
+ else:
704
+ result = execute_code(sid, args.code)
705
+ print(json.dumps(result, indent=2))
706
+ return
707
+
708
+ parser.print_help()
709
+
710
+
711
+ if __name__ == "__main__":
712
+ _cli_main()