@trac3er/oh-my-god 1.0.2

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 (229) hide show
  1. package/.claude-plugin/marketplace.json +36 -0
  2. package/.claude-plugin/plugin.json +23 -0
  3. package/.claude-plugin/scripts/install.sh +49 -0
  4. package/.claude-plugin/scripts/uninstall.sh +80 -0
  5. package/.claude-plugin/scripts/update.sh +84 -0
  6. package/.mcp.json +20 -0
  7. package/LICENSE +21 -0
  8. package/OMG-setup.sh +1093 -0
  9. package/README.md +335 -0
  10. package/THIRD_PARTY_NOTICES.md +24 -0
  11. package/UPSTREAM_DIFF.md +20 -0
  12. package/agents/__init__.py +1 -0
  13. package/agents/_model_roles.yaml +26 -0
  14. package/agents/designer.md +67 -0
  15. package/agents/explore.md +60 -0
  16. package/agents/model_roles.py +196 -0
  17. package/agents/omg-api-builder.md +23 -0
  18. package/agents/omg-architect-mode.md +43 -0
  19. package/agents/omg-architect.md +13 -0
  20. package/agents/omg-backend-engineer.md +43 -0
  21. package/agents/omg-critic.md +16 -0
  22. package/agents/omg-database-engineer.md +43 -0
  23. package/agents/omg-escalation-router.md +17 -0
  24. package/agents/omg-executor.md +12 -0
  25. package/agents/omg-frontend-designer.md +42 -0
  26. package/agents/omg-implement-mode.md +50 -0
  27. package/agents/omg-infra-engineer.md +43 -0
  28. package/agents/omg-qa-tester.md +16 -0
  29. package/agents/omg-research-mode.md +43 -0
  30. package/agents/omg-security-auditor.md +43 -0
  31. package/agents/omg-testing-engineer.md +43 -0
  32. package/agents/plan.md +80 -0
  33. package/agents/quick_task.md +64 -0
  34. package/agents/reviewer.md +83 -0
  35. package/agents/task.md +71 -0
  36. package/commands/OMG:ccg.md +22 -0
  37. package/commands/OMG:compat.md +57 -0
  38. package/commands/OMG:crazy.md +125 -0
  39. package/commands/OMG:domain-init.md +11 -0
  40. package/commands/OMG:escalate.md +52 -0
  41. package/commands/OMG:health-check.md +45 -0
  42. package/commands/OMG:init.md +134 -0
  43. package/commands/OMG:mode.md +44 -0
  44. package/commands/OMG:project-init.md +11 -0
  45. package/commands/OMG:ralph-start.md +43 -0
  46. package/commands/OMG:ralph-stop.md +23 -0
  47. package/commands/OMG:teams.md +39 -0
  48. package/commands/ai-commit.md +113 -0
  49. package/commands/ccg.md +9 -0
  50. package/commands/create-agent.md +183 -0
  51. package/commands/omc-teams.md +9 -0
  52. package/commands/session-branch.md +85 -0
  53. package/commands/session-fork.md +53 -0
  54. package/commands/session-merge.md +134 -0
  55. package/commands/theme.md +44 -0
  56. package/config/lsp_languages.yaml +324 -0
  57. package/config/themes/catppuccin-frappe.yaml +14 -0
  58. package/config/themes/catppuccin-latte.yaml +14 -0
  59. package/config/themes/catppuccin-macchiato.yaml +14 -0
  60. package/config/themes/catppuccin-mocha.yaml +14 -0
  61. package/config/themes/dracula.yaml +14 -0
  62. package/config/themes/gruvbox-dark.yaml +14 -0
  63. package/config/themes/nord.yaml +14 -0
  64. package/config/themes/one-dark.yaml +14 -0
  65. package/config/themes/solarized-dark.yaml +14 -0
  66. package/config/themes/tokyo-night.yaml +14 -0
  67. package/control_plane/__init__.py +2 -0
  68. package/control_plane/openapi.yaml +109 -0
  69. package/control_plane/server.py +107 -0
  70. package/control_plane/service.py +148 -0
  71. package/crates/omg-natives/Cargo.toml +17 -0
  72. package/crates/omg-natives/src/clipboard.rs +5 -0
  73. package/crates/omg-natives/src/glob.rs +15 -0
  74. package/crates/omg-natives/src/grep.rs +15 -0
  75. package/crates/omg-natives/src/highlight.rs +15 -0
  76. package/crates/omg-natives/src/html.rs +14 -0
  77. package/crates/omg-natives/src/image.rs +5 -0
  78. package/crates/omg-natives/src/keys.rs +5 -0
  79. package/crates/omg-natives/src/lib.rs +36 -0
  80. package/crates/omg-natives/src/prof.rs +5 -0
  81. package/crates/omg-natives/src/ps.rs +5 -0
  82. package/crates/omg-natives/src/shell.rs +5 -0
  83. package/crates/omg-natives/src/task.rs +5 -0
  84. package/crates/omg-natives/src/text.rs +14 -0
  85. package/hooks/_agent_registry.py +421 -0
  86. package/hooks/_budget.py +31 -0
  87. package/hooks/_common.py +476 -0
  88. package/hooks/_learnings.py +126 -0
  89. package/hooks/_memory.py +103 -0
  90. package/hooks/circuit-breaker.py +270 -0
  91. package/hooks/config-guard.py +163 -0
  92. package/hooks/context_pressure.py +53 -0
  93. package/hooks/credential_store.py +801 -0
  94. package/hooks/fetch-rate-limits.py +212 -0
  95. package/hooks/firewall.py +48 -0
  96. package/hooks/hashline-formatter-bridge.py +224 -0
  97. package/hooks/hashline-injector.py +273 -0
  98. package/hooks/hashline-validator.py +216 -0
  99. package/hooks/idle-detector.py +95 -0
  100. package/hooks/intentgate-keyword-detector.py +188 -0
  101. package/hooks/magic-keyword-router.py +195 -0
  102. package/hooks/policy_engine.py +310 -0
  103. package/hooks/post-tool-failure.py +19 -0
  104. package/hooks/post-write.py +199 -0
  105. package/hooks/pre-compact.py +204 -0
  106. package/hooks/pre-tool-inject.py +98 -0
  107. package/hooks/prompt-enhancer.py +672 -0
  108. package/hooks/quality-runner.py +191 -0
  109. package/hooks/secret-guard.py +47 -0
  110. package/hooks/session-end-capture.py +137 -0
  111. package/hooks/session-start.py +275 -0
  112. package/hooks/shadow_manager.py +297 -0
  113. package/hooks/state_migration.py +209 -0
  114. package/hooks/stop-gate.py +7 -0
  115. package/hooks/stop_dispatcher.py +929 -0
  116. package/hooks/test-validator.py +138 -0
  117. package/hooks/todo-state-tracker.py +114 -0
  118. package/hooks/tool-ledger.py +126 -0
  119. package/hooks/trust_review.py +524 -0
  120. package/install.sh +9 -0
  121. package/omg_natives/__init__.py +186 -0
  122. package/omg_natives/_bindings.py +165 -0
  123. package/omg_natives/clipboard.py +36 -0
  124. package/omg_natives/glob.py +42 -0
  125. package/omg_natives/grep.py +61 -0
  126. package/omg_natives/highlight.py +54 -0
  127. package/omg_natives/html.py +157 -0
  128. package/omg_natives/image.py +51 -0
  129. package/omg_natives/keys.py +46 -0
  130. package/omg_natives/prof.py +39 -0
  131. package/omg_natives/ps.py +93 -0
  132. package/omg_natives/shell.py +58 -0
  133. package/omg_natives/task.py +41 -0
  134. package/omg_natives/text.py +50 -0
  135. package/package.json +26 -0
  136. package/plugins/README.md +82 -0
  137. package/plugins/advanced/commands/OMG:code-review.md +114 -0
  138. package/plugins/advanced/commands/OMG:deep-plan.md +221 -0
  139. package/plugins/advanced/commands/OMG:handoff.md +115 -0
  140. package/plugins/advanced/commands/OMG:learn.md +110 -0
  141. package/plugins/advanced/commands/OMG:maintainer.md +31 -0
  142. package/plugins/advanced/commands/OMG:ralph-start.md +43 -0
  143. package/plugins/advanced/commands/OMG:ralph-stop.md +23 -0
  144. package/plugins/advanced/commands/OMG:security-review.md +119 -0
  145. package/plugins/advanced/commands/OMG:sequential-thinking.md +20 -0
  146. package/plugins/advanced/commands/OMG:ship.md +46 -0
  147. package/plugins/advanced/plugin.json +96 -0
  148. package/plugins/core/plugin.json +82 -0
  149. package/pytest.ini +5 -0
  150. package/registry/__init__.py +1 -0
  151. package/registry/verify_artifact.py +90 -0
  152. package/rules/contextual/architect-mode.md +9 -0
  153. package/rules/contextual/big-picture.md +20 -0
  154. package/rules/contextual/code-hygiene.md +26 -0
  155. package/rules/contextual/context-management.md +19 -0
  156. package/rules/contextual/context-minimization.md +32 -0
  157. package/rules/contextual/ddd-sdd.md +28 -0
  158. package/rules/contextual/dependency-safety.md +16 -0
  159. package/rules/contextual/doc-check.md +13 -0
  160. package/rules/contextual/implement-mode.md +9 -0
  161. package/rules/contextual/infra-safety.md +14 -0
  162. package/rules/contextual/outside-in.md +13 -0
  163. package/rules/contextual/persistent-mode.md +24 -0
  164. package/rules/contextual/research-mode.md +9 -0
  165. package/rules/contextual/security-domains.md +25 -0
  166. package/rules/contextual/vision-detection.md +27 -0
  167. package/rules/contextual/web-search.md +25 -0
  168. package/rules/contextual/write-verify.md +23 -0
  169. package/rules/core/00-truth.md +20 -0
  170. package/rules/core/01-surgical.md +19 -0
  171. package/rules/core/02-circuit-breaker.md +22 -0
  172. package/rules/core/03-ensemble.md +28 -0
  173. package/rules/core/04-testing.md +30 -0
  174. package/runtime/__init__.py +32 -0
  175. package/runtime/adapters/__init__.py +13 -0
  176. package/runtime/adapters/claude.py +60 -0
  177. package/runtime/adapters/gpt.py +53 -0
  178. package/runtime/adapters/local.py +53 -0
  179. package/runtime/business_workflow.py +220 -0
  180. package/runtime/compat.py +1299 -0
  181. package/runtime/custom_agent_loader.py +366 -0
  182. package/runtime/dispatcher.py +47 -0
  183. package/runtime/ecosystem.py +371 -0
  184. package/runtime/legacy_compat.py +7 -0
  185. package/runtime/omc_compat.py +7 -0
  186. package/runtime/omc_contract_snapshot.json +916 -0
  187. package/runtime/omg_compat_contract_snapshot.json +916 -0
  188. package/runtime/subagent_dispatcher.py +362 -0
  189. package/runtime/team_router.py +838 -0
  190. package/scripts/check-omc-contract-snapshot.py +12 -0
  191. package/scripts/check-omg-compat-contract-snapshot.py +137 -0
  192. package/scripts/check-omg-standalone-clean.py +102 -0
  193. package/scripts/legacy_to_omg_migrate.py +29 -0
  194. package/scripts/migrate-omc.py +464 -0
  195. package/scripts/omc_to_omg_migrate.py +12 -0
  196. package/scripts/omg.py +493 -0
  197. package/scripts/settings-merge.py +224 -0
  198. package/scripts/verify-no-omc.sh +5 -0
  199. package/scripts/verify-standalone.sh +21 -0
  200. package/templates/idea.yml +30 -0
  201. package/templates/policy.yaml +15 -0
  202. package/templates/profile.yaml +25 -0
  203. package/templates/runtime.yaml +12 -0
  204. package/templates/working-memory.md +17 -0
  205. package/tools/__init__.py +2 -0
  206. package/tools/browser_consent.py +289 -0
  207. package/tools/browser_stealth.py +481 -0
  208. package/tools/browser_tool.py +448 -0
  209. package/tools/changelog_generator.py +268 -0
  210. package/tools/commit_splitter.py +361 -0
  211. package/tools/config_discovery.py +151 -0
  212. package/tools/config_merger.py +449 -0
  213. package/tools/git_inspector.py +298 -0
  214. package/tools/lsp_client.py +275 -0
  215. package/tools/lsp_discovery.py +231 -0
  216. package/tools/lsp_operations.py +392 -0
  217. package/tools/python_repl.py +656 -0
  218. package/tools/python_sandbox.py +609 -0
  219. package/tools/search_providers/__init__.py +77 -0
  220. package/tools/search_providers/brave.py +115 -0
  221. package/tools/search_providers/exa.py +116 -0
  222. package/tools/search_providers/jina.py +104 -0
  223. package/tools/search_providers/perplexity.py +139 -0
  224. package/tools/search_providers/synthetic.py +74 -0
  225. package/tools/session_snapshot.py +736 -0
  226. package/tools/ssh_manager.py +912 -0
  227. package/tools/theme_engine.py +294 -0
  228. package/tools/theme_selector.py +137 -0
  229. package/tools/web_search.py +622 -0
package/scripts/omg.py ADDED
@@ -0,0 +1,493 @@
1
+ #!/usr/bin/env python3
2
+ """OMG v1 CLI entrypoint.
3
+
4
+ Implements practical command-line flows for:
5
+ - omg ship
6
+ - omg fix --issue
7
+ - omg secure
8
+ - omg maintainer
9
+ - omg trust review
10
+ - omg runtime dispatch
11
+ - omg lab train / omg lab eval
12
+ """
13
+ from __future__ import annotations
14
+
15
+ import argparse
16
+ from datetime import datetime, timezone
17
+ import json
18
+ import os
19
+ from pathlib import Path
20
+ import sys
21
+ from typing import Any
22
+
23
+ # --- Path resolution (never relies on CWD) ---
24
+ SCRIPTS_DIR = os.path.dirname(os.path.abspath(__file__))
25
+ ROOT_DIR = Path(SCRIPTS_DIR).resolve().parent
26
+ if str(ROOT_DIR) not in sys.path:
27
+ sys.path.insert(0, str(ROOT_DIR))
28
+
29
+ from hooks.policy_engine import evaluate_bash_command
30
+ from hooks.shadow_manager import create_evidence_pack
31
+ from hooks.trust_review import review_config_change, write_trust_manifest
32
+ from lab.pipeline import publish_artifact, run_pipeline
33
+ from runtime.dispatcher import dispatch_runtime
34
+ from runtime.compat import (
35
+ DEFAULT_CONTRACT_SNAPSHOT_PATH,
36
+ DEFAULT_GAP_REPORT_PATH,
37
+ build_contract_snapshot_payload,
38
+ build_compat_gap_report,
39
+ dispatch_compat_skill,
40
+ get_compat_skill_contract,
41
+ list_compat_skill_contracts,
42
+ list_compat_skills,
43
+ )
44
+ from runtime.ecosystem import ecosystem_status, list_ecosystem_repos, sync_ecosystem_repos
45
+ from runtime.team_router import TeamDispatchRequest, dispatch_team, execute_crazy_mode
46
+
47
+
48
+ def _now_run_id() -> str:
49
+ return datetime.now(timezone.utc).strftime("%Y%m%dT%H%M%S%fZ")
50
+
51
+
52
+ def _parse_simple_idea_yaml(path: str) -> dict[str, Any]:
53
+ """Minimal parser for `.omg/idea.yml` template shape."""
54
+ idea: dict[str, Any] = {
55
+ "goal": "",
56
+ "constraints": [],
57
+ "acceptance": [],
58
+ "risk": {"security": [], "performance": [], "compatibility": []},
59
+ "evidence_required": {"tests": [], "security_scans": [], "reproducibility": [], "artifacts": []},
60
+ }
61
+ section: str | None = None
62
+ subsection: str | None = None
63
+
64
+ with open(path, "r", encoding="utf-8") as f:
65
+ for raw in f:
66
+ line = raw.rstrip("\n")
67
+ stripped = line.strip()
68
+ if not stripped or stripped.startswith("#"):
69
+ continue
70
+
71
+ if stripped.startswith("goal:"):
72
+ idea["goal"] = stripped.split(":", 1)[1].strip().strip("\"'")
73
+ section = None
74
+ subsection = None
75
+ continue
76
+
77
+ if stripped in {"constraints:", "acceptance:", "risk:", "evidence_required:"}:
78
+ section = stripped[:-1]
79
+ subsection = None
80
+ continue
81
+
82
+ if section in {"risk", "evidence_required"} and stripped.endswith(":") and not stripped.startswith("- "):
83
+ subsection = stripped[:-1]
84
+ continue
85
+
86
+ if stripped.startswith("- "):
87
+ value = stripped[2:].strip().strip("\"'")
88
+ if section in {"constraints", "acceptance"}:
89
+ idea[section].append(value)
90
+ elif section in {"risk", "evidence_required"} and subsection:
91
+ idea[section].setdefault(subsection, []).append(value)
92
+
93
+ return idea
94
+
95
+
96
+ def _load_json(path: str) -> dict[str, Any]:
97
+ with open(path, "r", encoding="utf-8") as f:
98
+ data = json.load(f)
99
+ if not isinstance(data, dict):
100
+ raise ValueError(f"Expected object JSON in {path}")
101
+ return data
102
+
103
+
104
+ def _ensure_project_dir() -> str:
105
+ return os.environ.get("CLAUDE_PROJECT_DIR", os.getcwd())
106
+
107
+
108
+ def cmd_ship(args: argparse.Namespace) -> int:
109
+ project_dir = _ensure_project_dir()
110
+ idea_path = args.idea
111
+ idea = _parse_simple_idea_yaml(idea_path) if idea_path.endswith((".yml", ".yaml")) else _load_json(idea_path)
112
+
113
+ runtime = args.runtime
114
+ dispatched = dispatch_runtime(runtime, idea)
115
+ if dispatched.get("status") != "ok":
116
+ print(json.dumps(dispatched, indent=2))
117
+ return 2
118
+
119
+ run_id = args.run_id or _now_run_id()
120
+ verification = dispatched.get("verification", {})
121
+ checks = verification.get("checks", []) if isinstance(verification, dict) else []
122
+ evidence_path = create_evidence_pack(
123
+ project_dir,
124
+ run_id,
125
+ tests=checks if isinstance(checks, list) else [],
126
+ security_scans=[],
127
+ diff_summary={"runtime": runtime, "goal": idea.get("goal", "")},
128
+ reproducibility={"command": f"omg ship --runtime {runtime} --idea {idea_path}"},
129
+ unresolved_risks=[],
130
+ )
131
+
132
+ out = {
133
+ "status": "ok",
134
+ "command": "ship",
135
+ "runtime": runtime,
136
+ "run_id": run_id,
137
+ "goal": idea.get("goal", ""),
138
+ "evidence_path": os.path.relpath(evidence_path, project_dir),
139
+ }
140
+ print(json.dumps(out, indent=2))
141
+ return 0
142
+
143
+
144
+ def cmd_fix(args: argparse.Namespace) -> int:
145
+ goal = f"Fix issue {args.issue}"
146
+ dispatched = dispatch_runtime(args.runtime, {"goal": goal, "acceptance": [f"issue-{args.issue}-resolved"]})
147
+ print(json.dumps(dispatched, indent=2))
148
+ return 0 if dispatched.get("status") == "ok" else 2
149
+
150
+
151
+ def cmd_secure(args: argparse.Namespace) -> int:
152
+ decision = evaluate_bash_command(args.command)
153
+ print(json.dumps(decision.to_dict(), indent=2))
154
+ return 0 if decision.action != "deny" else 3
155
+
156
+
157
+ def cmd_maintainer(args: argparse.Namespace) -> int:
158
+ project_dir = _ensure_project_dir()
159
+ out_dir = Path(project_dir) / ".omg" / "evidence"
160
+ out_dir.mkdir(parents=True, exist_ok=True)
161
+ out_file = out_dir / "oss-impact.json"
162
+ payload = {
163
+ "generated_at": datetime.now(timezone.utc).isoformat(),
164
+ "mode": args.mode,
165
+ "activity": {"commits": "unverified", "reviews": "unverified", "releases": "unverified"},
166
+ "dependents": {"direct": "unverified", "transitive": "unverified"},
167
+ "adoption_signals": {"downloads": "unverified", "stars": "unverified"},
168
+ "summary_500_words": "",
169
+ "integrity": {"metric_manipulation": "forbidden"},
170
+ }
171
+ out_file.write_text(json.dumps(payload, indent=2), encoding="utf-8")
172
+ print(json.dumps({"status": "ok", "path": str(out_file)}, indent=2))
173
+ return 0
174
+
175
+
176
+ def cmd_trust_review(args: argparse.Namespace) -> int:
177
+ old_cfg = _load_json(args.old)
178
+ new_cfg = _load_json(args.new)
179
+ review = review_config_change(args.file, old_cfg, new_cfg)
180
+ manifest = write_trust_manifest(_ensure_project_dir(), review)
181
+ print(json.dumps({"review": review, "manifest": manifest}, indent=2))
182
+ return 0
183
+
184
+
185
+ def cmd_runtime_dispatch(args: argparse.Namespace) -> int:
186
+ if args.idea_json:
187
+ idea = json.loads(args.idea_json)
188
+ elif args.idea:
189
+ idea = _load_json(args.idea)
190
+ else:
191
+ idea = {"goal": "unspecified"}
192
+ result = dispatch_runtime(args.runtime, idea)
193
+ print(json.dumps(result, indent=2))
194
+ return 0 if result.get("status") == "ok" else 2
195
+
196
+
197
+ def cmd_lab_train(args: argparse.Namespace) -> int:
198
+ job = json.loads(args.job_json) if args.job_json else _load_json(args.job)
199
+ result = run_pipeline(job)
200
+ print(json.dumps(result, indent=2))
201
+ return 0 if result.get("status") in {"ready", "failed_evaluation"} else 2
202
+
203
+
204
+ def cmd_lab_eval(args: argparse.Namespace) -> int:
205
+ result = json.loads(args.result_json) if args.result_json else _load_json(args.result)
206
+ out = publish_artifact(result)
207
+ print(json.dumps(out, indent=2))
208
+ return 0 if out.get("status") == "published" else 2
209
+
210
+
211
+ def cmd_teams(args: argparse.Namespace) -> int:
212
+ files = [f.strip() for f in args.files.split(",") if f.strip()] if args.files else []
213
+ req = TeamDispatchRequest(
214
+ target=args.target,
215
+ problem=args.problem,
216
+ context=args.context,
217
+ files=files,
218
+ expected_outcome=args.expected_outcome,
219
+ )
220
+ result = dispatch_team(req).to_dict()
221
+ print(json.dumps(result, indent=2))
222
+ return 0
223
+
224
+
225
+ def cmd_ccg(args: argparse.Namespace) -> int:
226
+ files = [f.strip() for f in args.files.split(",") if f.strip()] if args.files else []
227
+ req = TeamDispatchRequest(
228
+ target="ccg",
229
+ problem=args.problem,
230
+ context=args.context,
231
+ files=files,
232
+ expected_outcome=args.expected_outcome,
233
+ )
234
+ result = dispatch_team(req).to_dict()
235
+ print(json.dumps(result, indent=2))
236
+ return 0
237
+
238
+
239
+ def cmd_crazy(args: argparse.Namespace) -> int:
240
+ files = [f.strip() for f in args.files.split(",") if f.strip()] if args.files else []
241
+ result = execute_crazy_mode(
242
+ problem=args.problem,
243
+ project_dir=_ensure_project_dir(),
244
+ context=args.context,
245
+ files=files,
246
+ )
247
+ print(json.dumps(result, indent=2))
248
+ return 0
249
+
250
+
251
+ def cmd_compat_list(args: argparse.Namespace) -> int:
252
+ skills = list_compat_skills()
253
+ print(json.dumps({"status": "ok", "count": len(skills), "skills": skills}, indent=2))
254
+ return 0
255
+
256
+
257
+ def cmd_compat_contract(args: argparse.Namespace) -> int:
258
+ if args.all:
259
+ contracts = list_compat_skill_contracts()
260
+ print(json.dumps({"status": "ok", "count": len(contracts), "contracts": contracts}, indent=2))
261
+ return 0
262
+ if not args.skill:
263
+ print(json.dumps({"status": "error", "message": "Provide --skill or --all"}, indent=2))
264
+ return 2
265
+ contract = get_compat_skill_contract(args.skill)
266
+ if not contract:
267
+ print(json.dumps({"status": "error", "message": f"Unknown skill: {args.skill}"}, indent=2))
268
+ return 2
269
+ print(json.dumps({"status": "ok", "contract": contract}, indent=2))
270
+ return 0
271
+
272
+
273
+ def cmd_compat_gap_report(args: argparse.Namespace) -> int:
274
+ report = build_compat_gap_report(_ensure_project_dir())
275
+ if args.output:
276
+ with open(args.output, "w", encoding="utf-8") as f:
277
+ json.dump(report, f, indent=2)
278
+ print(json.dumps({"status": "ok", "report": report}, indent=2))
279
+ return 0
280
+
281
+
282
+ def cmd_compat_snapshot(args: argparse.Namespace) -> int:
283
+ payload = build_contract_snapshot_payload(include_generated_at=True)
284
+ out_path = args.output or DEFAULT_CONTRACT_SNAPSHOT_PATH
285
+ with open(out_path, "w", encoding="utf-8") as f:
286
+ json.dump(payload, f, indent=2)
287
+ print(json.dumps({"status": "ok", "output": out_path, "count": payload["count"]}, indent=2))
288
+ return 0
289
+
290
+
291
+ def cmd_compat_gate(args: argparse.Namespace) -> int:
292
+ report = build_compat_gap_report(_ensure_project_dir())
293
+ if args.output:
294
+ with open(args.output, "w", encoding="utf-8") as f:
295
+ json.dump(report, f, indent=2)
296
+ bridge_count = int(report.get("maturity_counts", {}).get("bridge", 0))
297
+ if bridge_count > args.max_bridge:
298
+ print(
299
+ json.dumps(
300
+ {
301
+ "status": "error",
302
+ "message": f"OMG compat gate failed: bridge={bridge_count} > max_bridge={args.max_bridge}",
303
+ "report": report,
304
+ },
305
+ indent=2,
306
+ )
307
+ )
308
+ return 3
309
+ print(
310
+ json.dumps(
311
+ {
312
+ "status": "ok",
313
+ "message": f"OMG compat gate passed: bridge={bridge_count} <= max_bridge={args.max_bridge}",
314
+ "report": report,
315
+ },
316
+ indent=2,
317
+ )
318
+ )
319
+ return 0
320
+
321
+
322
+ def cmd_compat_run(args: argparse.Namespace) -> int:
323
+ files = [f.strip() for f in args.files.split(",") if f.strip()] if args.files else []
324
+ result = dispatch_compat_skill(
325
+ skill=args.skill,
326
+ problem=args.problem,
327
+ context=args.context,
328
+ files=files,
329
+ expected_outcome=args.expected_outcome,
330
+ project_dir=_ensure_project_dir(),
331
+ )
332
+ print(json.dumps(result, indent=2))
333
+ return 0 if result.get("status") == "ok" else 2
334
+
335
+
336
+ def cmd_ecosystem_list(args: argparse.Namespace) -> int:
337
+ repos = list_ecosystem_repos()
338
+ print(json.dumps({"status": "ok", "count": len(repos), "repos": repos}, indent=2))
339
+ return 0
340
+
341
+
342
+ def cmd_ecosystem_status(args: argparse.Namespace) -> int:
343
+ result = ecosystem_status(project_dir=_ensure_project_dir())
344
+ print(json.dumps(result, indent=2))
345
+ return 0
346
+
347
+
348
+ def cmd_ecosystem_sync(args: argparse.Namespace) -> int:
349
+ names = [name.strip() for name in args.names.split(",") if name.strip()] if args.names else []
350
+ result = sync_ecosystem_repos(
351
+ project_dir=_ensure_project_dir(),
352
+ names=names,
353
+ update=bool(args.update),
354
+ depth=int(args.depth),
355
+ )
356
+ print(json.dumps(result, indent=2))
357
+ errors = [entry for entry in result.get("entries", []) if entry.get("status") == "error"]
358
+ return 0 if not errors else 2
359
+
360
+
361
+ def _add_compat_subcommands(parent: argparse.ArgumentParser, *, dest: str) -> None:
362
+ compat_sub = parent.add_subparsers(dest=dest, required=True)
363
+ compat_list = compat_sub.add_parser("list", help="List supported legacy skill names")
364
+ compat_list.set_defaults(func=cmd_compat_list)
365
+ compat_contract = compat_sub.add_parser("contract", help="Show skill contract schema")
366
+ compat_contract.add_argument("--skill", default="")
367
+ compat_contract.add_argument("--all", action="store_true")
368
+ compat_contract.set_defaults(func=cmd_compat_contract)
369
+ compat_gap = compat_sub.add_parser("gap-report", help="Write compatibility maturity report")
370
+ compat_gap.add_argument("--output", default=DEFAULT_GAP_REPORT_PATH)
371
+ compat_gap.set_defaults(func=cmd_compat_gap_report)
372
+ compat_snapshot = compat_sub.add_parser("snapshot", help="Write current skill contracts snapshot")
373
+ compat_snapshot.add_argument("--output", default=DEFAULT_CONTRACT_SNAPSHOT_PATH)
374
+ compat_snapshot.set_defaults(func=cmd_compat_snapshot)
375
+ compat_gate = compat_sub.add_parser("gate", help="Fail if bridge skill count exceeds threshold")
376
+ compat_gate.add_argument("--max-bridge", type=int, default=0)
377
+ compat_gate.add_argument("--output", default=DEFAULT_GAP_REPORT_PATH)
378
+ compat_gate.set_defaults(func=cmd_compat_gate)
379
+ compat_run = compat_sub.add_parser("run", help="Run a legacy skill through OMG router")
380
+ compat_run.add_argument("--skill", required=True)
381
+ compat_run.add_argument("--problem", default="")
382
+ compat_run.add_argument("--context", default="")
383
+ compat_run.add_argument("--files", default="")
384
+ compat_run.add_argument("--expected-outcome", default="")
385
+ compat_run.set_defaults(func=cmd_compat_run)
386
+
387
+
388
+ def _add_ecosystem_subcommands(parent: argparse.ArgumentParser, *, dest: str) -> None:
389
+ ecosystem_sub = parent.add_subparsers(dest=dest, required=True)
390
+ ecosystem_list = ecosystem_sub.add_parser("list", help="List OMG ecosystem integration targets")
391
+ ecosystem_list.set_defaults(func=cmd_ecosystem_list)
392
+
393
+ ecosystem_status_cmd = ecosystem_sub.add_parser("status", help="Show current ecosystem install status")
394
+ ecosystem_status_cmd.set_defaults(func=cmd_ecosystem_status)
395
+
396
+ ecosystem_sync = ecosystem_sub.add_parser("sync", help="Clone or refresh ecosystem repositories")
397
+ ecosystem_sync.add_argument("--names", default="", help="Comma-separated repo names or aliases")
398
+ ecosystem_sync.add_argument("--update", action="store_true", help="Fetch latest refs for existing clones")
399
+ ecosystem_sync.add_argument("--depth", type=int, default=1, help="Git depth for shallow clone/fetch")
400
+ ecosystem_sync.set_defaults(func=cmd_ecosystem_sync)
401
+
402
+
403
+ def build_parser() -> argparse.ArgumentParser:
404
+ parser = argparse.ArgumentParser(prog="omg", description="OMG v1 CLI")
405
+ sub = parser.add_subparsers(dest="command", required=True)
406
+
407
+ ship = sub.add_parser("ship", help="Idea -> Evidence -> PR flow")
408
+ ship.add_argument("--idea", default=".omg/idea.yml")
409
+ ship.add_argument("--runtime", default="claude", choices=["claude", "gpt", "local"])
410
+ ship.add_argument("--run-id", default="")
411
+ ship.set_defaults(func=cmd_ship)
412
+
413
+ fix = sub.add_parser("fix", help="Issue-driven fix flow")
414
+ fix.add_argument("--issue", required=True)
415
+ fix.add_argument("--runtime", default="claude", choices=["claude", "gpt", "local"])
416
+ fix.set_defaults(func=cmd_fix)
417
+
418
+ secure = sub.add_parser("secure", help="Evaluate command risk")
419
+ secure.add_argument("--command", required=True)
420
+ secure.set_defaults(func=cmd_secure)
421
+
422
+ maintainer = sub.add_parser("maintainer", help="OSS maintainer evidence helper")
423
+ maintainer.add_argument("--mode", default="impact", choices=["triage", "release", "review", "impact"])
424
+ maintainer.set_defaults(func=cmd_maintainer)
425
+
426
+ trust = sub.add_parser("trust", help="Trust review operations")
427
+ trust_sub = trust.add_subparsers(dest="trust_command", required=True)
428
+ trust_review = trust_sub.add_parser("review", help="Review config change")
429
+ trust_review.add_argument("--file", default="settings.json")
430
+ trust_review.add_argument("--old", required=True, help="Path to old config json")
431
+ trust_review.add_argument("--new", required=True, help="Path to new config json")
432
+ trust_review.set_defaults(func=cmd_trust_review)
433
+
434
+ runtime = sub.add_parser("runtime", help="Runtime operations")
435
+ runtime_sub = runtime.add_subparsers(dest="runtime_command", required=True)
436
+ runtime_dispatch = runtime_sub.add_parser("dispatch", help="Dispatch runtime job")
437
+ runtime_dispatch.add_argument("--runtime", required=True, choices=["claude", "gpt", "local"])
438
+ runtime_dispatch.add_argument("--idea", default="", help="Path to idea json")
439
+ runtime_dispatch.add_argument("--idea-json", default="", help="Inline idea json")
440
+ runtime_dispatch.set_defaults(func=cmd_runtime_dispatch)
441
+
442
+ lab = sub.add_parser("lab", help="Lab pipeline operations")
443
+ lab_sub = lab.add_subparsers(dest="lab_command", required=True)
444
+ lab_train = lab_sub.add_parser("train", help="Run lab pipeline job")
445
+ lab_train.add_argument("--job", default="", help="Path to job json")
446
+ lab_train.add_argument("--job-json", default="", help="Inline job json")
447
+ lab_train.set_defaults(func=cmd_lab_train)
448
+ lab_eval = lab_sub.add_parser("eval", help="Publish lab result when eligible")
449
+ lab_eval.add_argument("--result", default="", help="Path to result json")
450
+ lab_eval.add_argument("--result-json", default="", help="Inline result json")
451
+ lab_eval.set_defaults(func=cmd_lab_eval)
452
+
453
+ teams = sub.add_parser("teams", help="Internal OMG team routing")
454
+ teams.add_argument("--target", default="auto", choices=["auto", "codex", "gemini", "ccg"])
455
+ teams.add_argument("--problem", required=True)
456
+ teams.add_argument("--context", default="")
457
+ teams.add_argument("--files", default="")
458
+ teams.add_argument("--expected-outcome", default="")
459
+ teams.set_defaults(func=cmd_teams)
460
+
461
+ ccg = sub.add_parser("ccg", help="OMG CCG (tri-track) routing")
462
+ ccg.add_argument("--problem", required=True)
463
+ ccg.add_argument("--context", default="")
464
+ ccg.add_argument("--files", default="")
465
+ ccg.add_argument("--expected-outcome", default="")
466
+ ccg.set_defaults(func=cmd_ccg)
467
+
468
+ crazy = sub.add_parser("crazy", help="OMG CRAZY mode - parallel multi-agent orchestration")
469
+ crazy.add_argument("--problem", required=True, help="Task description")
470
+ crazy.add_argument("--context", default="", help="Additional context")
471
+ crazy.add_argument("--files", default="", help="Comma-separated focus files")
472
+ crazy.set_defaults(func=cmd_crazy)
473
+
474
+ compat = sub.add_parser("compat", help="OMG legacy compatibility bridge")
475
+ _add_compat_subcommands(compat, dest="compat_command")
476
+
477
+ omc = sub.add_parser("omc", help="Alias of `compat` for legacy scripts")
478
+ _add_compat_subcommands(omc, dest="omc_command")
479
+
480
+ ecosystem = sub.add_parser("ecosystem", help="Upstream ecosystem sync and status")
481
+ _add_ecosystem_subcommands(ecosystem, dest="ecosystem_command")
482
+
483
+ return parser
484
+
485
+
486
+ def main(argv: list[str] | None = None) -> int:
487
+ parser = build_parser()
488
+ args = parser.parse_args(argv)
489
+ return int(args.func(args))
490
+
491
+
492
+ if __name__ == "__main__":
493
+ raise SystemExit(main())