@trac3er/oh-my-god 2.0.2 → 2.0.4
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.
- package/.agents/skills/omg/AGENTS.fragment.md +5 -0
- package/.agents/skills/omg/codex-mcp.toml +4 -0
- package/.agents/skills/omg/control-plane/SKILL.md +11 -0
- package/.agents/skills/omg/control-plane/openai.yaml +14 -0
- package/.agents/skills/omg/hook-governor/SKILL.md +11 -0
- package/.agents/skills/omg/hook-governor/openai.yaml +11 -0
- package/.agents/skills/omg/lsp-pack/SKILL.md +11 -0
- package/.agents/skills/omg/lsp-pack/openai.yaml +11 -0
- package/.agents/skills/omg/mcp-fabric/SKILL.md +11 -0
- package/.agents/skills/omg/mcp-fabric/openai.yaml +13 -0
- package/.agents/skills/omg/secure-worktree-pipeline/SKILL.md +11 -0
- package/.agents/skills/omg/secure-worktree-pipeline/openai.yaml +12 -0
- package/.claude-plugin/marketplace.json +3 -3
- package/.claude-plugin/plugin.json +1 -1
- package/.mcp.json +20 -4
- package/CHANGELOG.md +16 -0
- package/OMG-setup.sh +9 -3
- package/OMG_COMPAT_CONTRACT.md +92 -0
- package/README.md +26 -8
- package/SECURITY.md +6 -0
- package/commands/OMG:api-twin.md +22 -0
- package/commands/OMG:preflight.md +26 -0
- package/commands/OMG:security-check.md +28 -0
- package/commands/OMG:setup.md +1 -2
- package/dist/enterprise/bundle/.agents/skills/omg/AGENTS.fragment.md +5 -0
- package/dist/enterprise/bundle/.agents/skills/omg/codex-mcp.toml +4 -0
- package/dist/enterprise/bundle/.agents/skills/omg/control-plane/SKILL.md +11 -0
- package/dist/enterprise/bundle/.agents/skills/omg/control-plane/openai.yaml +14 -0
- package/dist/enterprise/bundle/.agents/skills/omg/hook-governor/SKILL.md +11 -0
- package/dist/enterprise/bundle/.agents/skills/omg/hook-governor/openai.yaml +11 -0
- package/dist/enterprise/bundle/.agents/skills/omg/lsp-pack/SKILL.md +11 -0
- package/dist/enterprise/bundle/.agents/skills/omg/lsp-pack/openai.yaml +11 -0
- package/dist/enterprise/bundle/.agents/skills/omg/mcp-fabric/SKILL.md +11 -0
- package/dist/enterprise/bundle/.agents/skills/omg/mcp-fabric/openai.yaml +13 -0
- package/dist/enterprise/bundle/.agents/skills/omg/secure-worktree-pipeline/SKILL.md +11 -0
- package/dist/enterprise/bundle/.agents/skills/omg/secure-worktree-pipeline/openai.yaml +12 -0
- package/dist/enterprise/bundle/.claude-plugin/marketplace.json +36 -0
- package/dist/enterprise/bundle/.claude-plugin/plugin.json +23 -0
- package/dist/enterprise/bundle/.mcp.json +40 -0
- package/dist/enterprise/bundle/OMG_COMPAT_CONTRACT.md +92 -0
- package/dist/enterprise/bundle/settings.json +366 -0
- package/dist/enterprise/manifest.json +99 -0
- package/dist/public/bundle/.agents/skills/omg/AGENTS.fragment.md +5 -0
- package/dist/public/bundle/.agents/skills/omg/codex-mcp.toml +4 -0
- package/dist/public/bundle/.agents/skills/omg/control-plane/SKILL.md +11 -0
- package/dist/public/bundle/.agents/skills/omg/control-plane/openai.yaml +14 -0
- package/dist/public/bundle/.agents/skills/omg/hook-governor/SKILL.md +11 -0
- package/dist/public/bundle/.agents/skills/omg/hook-governor/openai.yaml +11 -0
- package/dist/public/bundle/.agents/skills/omg/lsp-pack/SKILL.md +11 -0
- package/dist/public/bundle/.agents/skills/omg/lsp-pack/openai.yaml +11 -0
- package/dist/public/bundle/.agents/skills/omg/mcp-fabric/SKILL.md +11 -0
- package/dist/public/bundle/.agents/skills/omg/mcp-fabric/openai.yaml +13 -0
- package/dist/public/bundle/.agents/skills/omg/secure-worktree-pipeline/SKILL.md +11 -0
- package/dist/public/bundle/.agents/skills/omg/secure-worktree-pipeline/openai.yaml +12 -0
- package/dist/public/bundle/.claude-plugin/marketplace.json +36 -0
- package/dist/public/bundle/.claude-plugin/plugin.json +23 -0
- package/dist/public/bundle/.mcp.json +40 -0
- package/dist/public/bundle/OMG_COMPAT_CONTRACT.md +92 -0
- package/dist/public/bundle/settings.json +366 -0
- package/dist/public/manifest.json +99 -0
- package/hooks/policy_engine.py +38 -7
- package/hooks/post-write.py +1 -1
- package/hooks/prompt-enhancer.py +2 -2
- package/hooks/security_validators.py +75 -0
- package/hooks/setup_wizard.py +44 -20
- package/hooks/shadow_manager.py +22 -2
- package/package.json +1 -1
- package/plugins/README.md +4 -2
- package/plugins/advanced/commands/OMG:deep-plan.md +1 -1
- package/plugins/advanced/commands/OMG:security-review.md +10 -113
- package/plugins/advanced/commands/OMG:ship.md +1 -1
- package/plugins/advanced/plugin.json +1 -10
- package/plugins/core/plugin.json +25 -2
- package/pyproject.toml +1 -1
- package/runtime/adoption.py +1 -1
- package/runtime/api_twin.py +130 -0
- package/runtime/compat.py +21 -1
- package/runtime/contract_compiler.py +698 -0
- package/runtime/domain_packs.py +34 -0
- package/runtime/guide_assert.py +45 -0
- package/runtime/mcp_config_writers.py +145 -39
- package/runtime/omg_compat_contract_snapshot.json +8 -7
- package/runtime/omg_contract_snapshot.json +8 -7
- package/runtime/omg_mcp_server.py +205 -0
- package/runtime/preflight.py +52 -0
- package/runtime/providers/codex_provider.py +2 -12
- package/runtime/providers/gemini_provider.py +2 -21
- package/runtime/providers/kimi_provider.py +2 -21
- package/runtime/runtime_profile.py +61 -0
- package/runtime/security_check.py +347 -0
- package/runtime/subagent_dispatcher.py +117 -10
- package/runtime/team_router.py +3 -3
- package/runtime/untrusted_content.py +102 -0
- package/scripts/omg.py +174 -1
- package/settings.json +66 -18
- package/tools/python_repl.py +33 -3
- package/runtime/providers/opencode_provider.py +0 -144
package/hooks/setup_wizard.py
CHANGED
|
@@ -22,16 +22,18 @@ if _PROJECT_ROOT not in sys.path:
|
|
|
22
22
|
from runtime.cli_provider import get_provider, list_available_providers # noqa: E402
|
|
23
23
|
from runtime.mcp_config_writers import ( # noqa: E402
|
|
24
24
|
write_claude_mcp_config,
|
|
25
|
+
write_claude_mcp_stdio_config,
|
|
25
26
|
write_codex_mcp_config,
|
|
27
|
+
write_codex_mcp_stdio_config,
|
|
26
28
|
write_gemini_mcp_config,
|
|
27
|
-
|
|
29
|
+
write_gemini_mcp_stdio_config,
|
|
28
30
|
write_kimi_mcp_config,
|
|
31
|
+
write_kimi_mcp_stdio_config,
|
|
29
32
|
)
|
|
30
33
|
|
|
31
34
|
# Trigger provider auto-registration on import
|
|
32
35
|
import runtime.providers.codex_provider # noqa: E402, F401
|
|
33
36
|
import runtime.providers.gemini_provider # noqa: E402, F401
|
|
34
|
-
import runtime.providers.opencode_provider # noqa: E402, F401
|
|
35
37
|
import runtime.providers.kimi_provider # noqa: E402, F401
|
|
36
38
|
from runtime.adoption import ( # noqa: E402
|
|
37
39
|
CANONICAL_VERSION,
|
|
@@ -43,10 +45,13 @@ from runtime.adoption import ( # noqa: E402
|
|
|
43
45
|
|
|
44
46
|
_logger = logging.getLogger(__name__)
|
|
45
47
|
|
|
48
|
+
OMG_CONTROL_COMMAND = "python3"
|
|
49
|
+
OMG_CONTROL_ARGS = ["-m", "runtime.omg_mcp_server"]
|
|
50
|
+
OMG_CONTROL_SERVER_NAME = "omg-control"
|
|
51
|
+
|
|
46
52
|
_INSTALL_HINTS: dict[str, str] = {
|
|
47
53
|
"codex": "npm install -g @openai/codex",
|
|
48
54
|
"gemini": "npm install -g @google/gemini-cli",
|
|
49
|
-
"opencode": "npm install -g opencode-ai (or: curl -fsSL https://opencode.ai/install | bash)",
|
|
50
55
|
"kimi": "uv tool install --python 3.13 kimi-cli",
|
|
51
56
|
}
|
|
52
57
|
|
|
@@ -112,6 +117,15 @@ MCP_CATALOG: list[dict[str, Any]] = [
|
|
|
112
117
|
"default": True,
|
|
113
118
|
"category": "memory",
|
|
114
119
|
},
|
|
120
|
+
{
|
|
121
|
+
"id": OMG_CONTROL_SERVER_NAME,
|
|
122
|
+
"name": "OMG Control",
|
|
123
|
+
"description": "OMG control plane MCP server via stdio",
|
|
124
|
+
"command": OMG_CONTROL_COMMAND,
|
|
125
|
+
"args": OMG_CONTROL_ARGS,
|
|
126
|
+
"default": True,
|
|
127
|
+
"category": "control",
|
|
128
|
+
},
|
|
115
129
|
{
|
|
116
130
|
"id": "github",
|
|
117
131
|
"name": "GitHub",
|
|
@@ -325,7 +339,7 @@ def get_cli_auth_instructions(provider: str) -> dict[str, str]:
|
|
|
325
339
|
or store credentials.
|
|
326
340
|
|
|
327
341
|
Args:
|
|
328
|
-
provider: CLI provider name (e.g. "codex", "gemini", "kimi"
|
|
342
|
+
provider: CLI provider name (e.g. "codex", "gemini", or "kimi").
|
|
329
343
|
|
|
330
344
|
Returns:
|
|
331
345
|
Dict with keys: install, auth, verify, subscription.
|
|
@@ -350,12 +364,6 @@ def get_cli_auth_instructions(provider: str) -> dict[str, str]:
|
|
|
350
364
|
"verify": "kimi --version",
|
|
351
365
|
"subscription": "Requires Kimi API key from platform.moonshot.cn",
|
|
352
366
|
},
|
|
353
|
-
"opencode": {
|
|
354
|
-
"install": "npm install -g opencode-ai",
|
|
355
|
-
"auth": "opencode auth login",
|
|
356
|
-
"verify": "opencode --version",
|
|
357
|
-
"subscription": "Requires Anthropic API key or Claude subscription",
|
|
358
|
-
},
|
|
359
367
|
}
|
|
360
368
|
|
|
361
369
|
return instructions.get(provider, {
|
|
@@ -380,8 +388,11 @@ def configure_mcp(
|
|
|
380
388
|
detected_clis: dict[str, Any],
|
|
381
389
|
server_url: str = "http://127.0.0.1:8765/mcp",
|
|
382
390
|
server_name: str = "omg-memory",
|
|
391
|
+
control_command: str = OMG_CONTROL_COMMAND,
|
|
392
|
+
control_args: list[str] | None = None,
|
|
393
|
+
control_server_name: str = OMG_CONTROL_SERVER_NAME,
|
|
383
394
|
) -> dict[str, Any]:
|
|
384
|
-
"""Configure MCP
|
|
395
|
+
"""Configure OMG MCP servers for authenticated CLIs.
|
|
385
396
|
|
|
386
397
|
For each CLI in detected_clis where detected_clis[cli]["detected"] == True,
|
|
387
398
|
calls the appropriate writer from runtime.mcp_config_writers.
|
|
@@ -391,6 +402,9 @@ def configure_mcp(
|
|
|
391
402
|
detected_clis: Dict of CLI detection results from detect_clis().
|
|
392
403
|
server_url: MCP server URL (default: http://127.0.0.1:8765/mcp).
|
|
393
404
|
server_name: MCP server name (default: omg-memory).
|
|
405
|
+
control_command: stdio command for the OMG control MCP server.
|
|
406
|
+
control_args: stdio args for the OMG control MCP server.
|
|
407
|
+
control_server_name: MCP server name for the OMG control surface.
|
|
394
408
|
|
|
395
409
|
Returns:
|
|
396
410
|
Dict with keys:
|
|
@@ -400,29 +414,40 @@ def configure_mcp(
|
|
|
400
414
|
"""
|
|
401
415
|
configured: list[str] = []
|
|
402
416
|
errors: dict[str, str] = {}
|
|
417
|
+
resolved_control_args = list(control_args or OMG_CONTROL_ARGS)
|
|
403
418
|
|
|
404
|
-
# Always write Claude config
|
|
419
|
+
# Always write Claude project config for both memory and control surfaces.
|
|
405
420
|
try:
|
|
406
421
|
write_claude_mcp_config(project_dir, server_url, server_name)
|
|
422
|
+
write_claude_mcp_stdio_config(
|
|
423
|
+
project_dir,
|
|
424
|
+
command=control_command,
|
|
425
|
+
args=resolved_control_args,
|
|
426
|
+
server_name=control_server_name,
|
|
427
|
+
)
|
|
407
428
|
except Exception as exc:
|
|
408
429
|
_logger.warning("Failed to write Claude MCP config: %s", exc)
|
|
409
430
|
errors["claude"] = str(exc)
|
|
410
431
|
|
|
411
|
-
# Write
|
|
432
|
+
# Write both memory and control surfaces for detected external CLIs.
|
|
412
433
|
cli_writers = {
|
|
413
|
-
"codex": write_codex_mcp_config,
|
|
414
|
-
"gemini": write_gemini_mcp_config,
|
|
415
|
-
"
|
|
416
|
-
"kimi": write_kimi_mcp_config,
|
|
434
|
+
"codex": (write_codex_mcp_config, write_codex_mcp_stdio_config),
|
|
435
|
+
"gemini": (write_gemini_mcp_config, write_gemini_mcp_stdio_config),
|
|
436
|
+
"kimi": (write_kimi_mcp_config, write_kimi_mcp_stdio_config),
|
|
417
437
|
}
|
|
418
438
|
|
|
419
|
-
for cli_name,
|
|
439
|
+
for cli_name, (http_writer, stdio_writer) in cli_writers.items():
|
|
420
440
|
cli_info = detected_clis.get(cli_name, {})
|
|
421
441
|
if not cli_info.get("detected", False):
|
|
422
442
|
continue
|
|
423
443
|
|
|
424
444
|
try:
|
|
425
|
-
|
|
445
|
+
http_writer(server_url, server_name)
|
|
446
|
+
stdio_writer(
|
|
447
|
+
command=control_command,
|
|
448
|
+
args=resolved_control_args,
|
|
449
|
+
server_name=control_server_name,
|
|
450
|
+
)
|
|
426
451
|
configured.append(cli_name)
|
|
427
452
|
except Exception as exc:
|
|
428
453
|
_logger.warning("Failed to write %s MCP config: %s", cli_name, exc)
|
|
@@ -460,7 +485,6 @@ def set_preferences(project_dir: str, preferences: dict[str, Any]) -> dict[str,
|
|
|
460
485
|
default_cli_configs: dict[str, Any] = {
|
|
461
486
|
"codex": {"subscription": "free", "max_parallel_agents": 1},
|
|
462
487
|
"gemini": {"subscription": "free", "max_parallel_agents": 1},
|
|
463
|
-
"opencode": {"subscription": "free", "max_parallel_agents": 1},
|
|
464
488
|
"kimi": {"subscription": "free", "max_parallel_agents": 1},
|
|
465
489
|
}
|
|
466
490
|
preset = resolve_preset(cast(str | None, preferences.get("preset")))
|
package/hooks/shadow_manager.py
CHANGED
|
@@ -17,6 +17,7 @@ HOOKS_DIR = os.path.dirname(__file__)
|
|
|
17
17
|
if HOOKS_DIR not in sys.path:
|
|
18
18
|
sys.path.insert(0, HOOKS_DIR)
|
|
19
19
|
from _common import _resolve_project_dir
|
|
20
|
+
from security_validators import ensure_path_within_dir, validate_opaque_identifier
|
|
20
21
|
|
|
21
22
|
|
|
22
23
|
def _project_dir() -> str:
|
|
@@ -43,6 +44,10 @@ def _new_run_id() -> str:
|
|
|
43
44
|
return datetime.now(timezone.utc).strftime("%Y%m%dT%H%M%S%fZ")
|
|
44
45
|
|
|
45
46
|
|
|
47
|
+
def _validated_run_id(run_id: str) -> str:
|
|
48
|
+
return validate_opaque_identifier(run_id, "run_id")
|
|
49
|
+
|
|
50
|
+
|
|
46
51
|
def _hash_file(path: str) -> str:
|
|
47
52
|
h = hashlib.sha256()
|
|
48
53
|
with open(path, "rb") as f:
|
|
@@ -61,6 +66,7 @@ def ensure_shadow_dirs(project_dir: str) -> None:
|
|
|
61
66
|
|
|
62
67
|
def set_active_run_id(project_dir: str, run_id: str) -> None:
|
|
63
68
|
ensure_shadow_dirs(project_dir)
|
|
69
|
+
run_id = _validated_run_id(run_id)
|
|
64
70
|
with open(_active_run_path(project_dir), "w", encoding="utf-8") as f:
|
|
65
71
|
f.write(run_id)
|
|
66
72
|
|
|
@@ -81,7 +87,7 @@ def get_active_run_id(project_dir: str) -> str | None:
|
|
|
81
87
|
|
|
82
88
|
|
|
83
89
|
def begin_shadow_run(project_dir: str, metadata: dict[str, Any] | None = None) -> str:
|
|
84
|
-
run_id = get_active_run_id(project_dir) or _new_run_id()
|
|
90
|
+
run_id = _validated_run_id(get_active_run_id(project_dir) or _new_run_id())
|
|
85
91
|
run_dir = os.path.join(_shadow_root(project_dir), run_id)
|
|
86
92
|
os.makedirs(run_dir, exist_ok=True)
|
|
87
93
|
|
|
@@ -124,12 +130,14 @@ def _save_manifest(run_dir: str, manifest: dict[str, Any]) -> None:
|
|
|
124
130
|
|
|
125
131
|
|
|
126
132
|
def map_shadow_path(project_dir: str, run_id: str, file_path: str) -> str:
|
|
133
|
+
run_id = _validated_run_id(run_id)
|
|
127
134
|
rel = os.path.relpath(os.path.abspath(file_path), os.path.abspath(project_dir))
|
|
128
135
|
rel = rel.replace("..", "_up_")
|
|
129
136
|
return os.path.join(_shadow_root(project_dir), run_id, "overlay", rel)
|
|
130
137
|
|
|
131
138
|
|
|
132
139
|
def record_shadow_write(project_dir: str, run_id: str, file_path: str, source: str = "tool") -> dict[str, Any]:
|
|
140
|
+
run_id = _validated_run_id(run_id)
|
|
133
141
|
run_dir = os.path.join(_shadow_root(project_dir), run_id)
|
|
134
142
|
os.makedirs(run_dir, exist_ok=True)
|
|
135
143
|
|
|
@@ -171,8 +179,12 @@ def create_evidence_pack(
|
|
|
171
179
|
diff_summary: dict[str, Any] | None = None,
|
|
172
180
|
reproducibility: dict[str, Any] | None = None,
|
|
173
181
|
unresolved_risks: list[str] | None = None,
|
|
182
|
+
provenance: list[dict[str, Any]] | None = None,
|
|
183
|
+
trust_scores: dict[str, Any] | None = None,
|
|
184
|
+
api_twin: dict[str, Any] | None = None,
|
|
174
185
|
) -> str:
|
|
175
186
|
ensure_shadow_dirs(project_dir)
|
|
187
|
+
run_id = _validated_run_id(run_id)
|
|
176
188
|
evidence = {
|
|
177
189
|
"schema": "EvidencePack",
|
|
178
190
|
"run_id": run_id,
|
|
@@ -182,8 +194,14 @@ def create_evidence_pack(
|
|
|
182
194
|
"diff_summary": diff_summary or {},
|
|
183
195
|
"reproducibility": reproducibility or {},
|
|
184
196
|
"unresolved_risks": unresolved_risks or [],
|
|
197
|
+
"provenance": provenance or [],
|
|
198
|
+
"trust_scores": trust_scores or {},
|
|
199
|
+
"api_twin": api_twin or {},
|
|
185
200
|
}
|
|
186
|
-
evidence_path =
|
|
201
|
+
evidence_path = ensure_path_within_dir(
|
|
202
|
+
_evidence_root(project_dir),
|
|
203
|
+
os.path.join(_evidence_root(project_dir), f"{run_id}.json"),
|
|
204
|
+
)
|
|
187
205
|
with open(evidence_path, "w", encoding="utf-8") as f:
|
|
188
206
|
json.dump(evidence, f, indent=2)
|
|
189
207
|
return evidence_path
|
|
@@ -211,6 +229,7 @@ def has_recent_evidence(project_dir: str, hours: int = 24) -> bool:
|
|
|
211
229
|
|
|
212
230
|
|
|
213
231
|
def apply_shadow(project_dir: str, run_id: str) -> dict[str, Any]:
|
|
232
|
+
run_id = _validated_run_id(run_id)
|
|
214
233
|
run_dir = os.path.join(_shadow_root(project_dir), run_id)
|
|
215
234
|
manifest = _load_manifest(run_dir)
|
|
216
235
|
applied = []
|
|
@@ -236,6 +255,7 @@ def apply_shadow(project_dir: str, run_id: str) -> dict[str, Any]:
|
|
|
236
255
|
|
|
237
256
|
|
|
238
257
|
def drop_shadow(project_dir: str, run_id: str) -> dict[str, Any]:
|
|
258
|
+
run_id = _validated_run_id(run_id)
|
|
239
259
|
run_dir = os.path.join(_shadow_root(project_dir), run_id)
|
|
240
260
|
if os.path.isdir(run_dir):
|
|
241
261
|
print(f"[OMG] Deleting: {run_dir}", file=sys.stderr)
|
package/package.json
CHANGED
package/plugins/README.md
CHANGED
|
@@ -17,6 +17,9 @@ OMG exposes a small native front door and keeps the rest of the surface availabl
|
|
|
17
17
|
| `/OMG:escalate` | Route to Codex, Gemini, or CCG |
|
|
18
18
|
| `/OMG:teams` | Team routing for internal OMG execution |
|
|
19
19
|
| `/OMG:ccg` | Tri-track synthesis |
|
|
20
|
+
| `/OMG:security-check` | Canonical security pipeline |
|
|
21
|
+
| `/OMG:api-twin` | Contract replay and fixture-based API simulation |
|
|
22
|
+
| `/OMG:preflight` | Structured route selection and evidence planning |
|
|
20
23
|
| `/OMG:compat` | Legacy compatibility routing |
|
|
21
24
|
| `/OMG:health-check` | Verify setup and tool integration |
|
|
22
25
|
| `/OMG:mode` | Set cognitive mode for the session |
|
|
@@ -28,7 +31,6 @@ OMG exposes a small native front door and keeps the rest of the surface availabl
|
|
|
28
31
|
| `/OMG:deep-plan` | Planning | Strategic planning with domain awareness |
|
|
29
32
|
| `/OMG:learn` | Knowledge | Convert patterns into OMG-native instincts and skills |
|
|
30
33
|
| `/OMG:code-review` | Quality | Deep review flow |
|
|
31
|
-
| `/OMG:security-review` | Security | Security-focused review |
|
|
32
34
|
| `/OMG:ship` | Delivery | Idea to evidence to release |
|
|
33
35
|
| `/OMG:handoff` | Collaboration | Session transfer and continuity |
|
|
34
36
|
|
|
@@ -50,5 +52,5 @@ Public migration commands are intentionally avoided. OMG uses `/OMG:setup` and `
|
|
|
50
52
|
|
|
51
53
|
## Public Docs
|
|
52
54
|
|
|
53
|
-
- Install guides live in [docs/install/claude-code.md](../docs/install/claude-code.md)
|
|
55
|
+
- Install guides live in [docs/install/claude-code.md](../docs/install/claude-code.md) and [docs/install/codex.md](../docs/install/codex.md).
|
|
54
56
|
- Proof surface lives in [docs/proof.md](../docs/proof.md).
|
|
@@ -87,7 +87,7 @@ Key interfaces: [list the interfaces/types this touches]
|
|
|
87
87
|
|
|
88
88
|
### Phase 3: Integration + Security [N files, ~M lines]
|
|
89
89
|
5. [ ] [specific action]
|
|
90
|
-
6. [ ] Security review: /OMG:security-
|
|
90
|
+
6. [ ] Security review: /OMG:security-check [affected files]
|
|
91
91
|
|
|
92
92
|
### Phase 4: Verification
|
|
93
93
|
7. [ ] Tests: [what to test, how]
|
|
@@ -1,119 +1,16 @@
|
|
|
1
1
|
---
|
|
2
|
-
description:
|
|
3
|
-
allowed-tools: Read,
|
|
4
|
-
argument-hint: "[
|
|
2
|
+
description: Deprecated alias to OMG's canonical security-check pipeline.
|
|
3
|
+
allowed-tools: Read, Grep, Glob, Bash(python3:*), Bash(rg:*)
|
|
4
|
+
argument-hint: "[path or '.' for the current project]"
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
# /OMG:security-review —
|
|
7
|
+
# /OMG:security-review — Deprecated Alias
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
`/OMG:security-review` remains available only for compatibility.
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
- If argument is a file: scan that file deeply
|
|
13
|
-
- If argument is a directory: scan all source files in it
|
|
14
|
-
- If "all" or no argument: scan git-tracked source files
|
|
11
|
+
Use `/OMG:security-check` instead. The canonical pipeline now owns:
|
|
15
12
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
# Payment
|
|
22
|
-
find . -type f -name "*.{ts,js,py,go}" | xargs grep -li "payment\|billing\|stripe\|checkout\|card\|price" 2>/dev/null
|
|
23
|
-
|
|
24
|
-
# Database
|
|
25
|
-
find . -type f -name "*.{ts,js,py,go}" | xargs grep -li "query\|SELECT\|INSERT\|UPDATE\|DELETE\|migration\|schema" 2>/dev/null
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
## Step 2: Automated Vulnerability Scan
|
|
29
|
-
|
|
30
|
-
For each security-critical file, check LINE-BY-LINE:
|
|
31
|
-
|
|
32
|
-
**2a. Hardcoded Secrets**
|
|
33
|
-
```bash
|
|
34
|
-
grep -rn "AKIA\|sk_live\|sk_test\|ghp_\|github_pat\|xoxb-\|xoxp-\|eyJ.*\.eyJ" [files]
|
|
35
|
-
grep -rn "api[_-]key.*=.*['\"][A-Za-z0-9]" [files]
|
|
36
|
-
grep -rn "password.*=.*['\"]" [files] | grep -v "test\|mock\|example\|placeholder"
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
**2b. SQL Injection**
|
|
40
|
-
```bash
|
|
41
|
-
grep -rn "f\".*SELECT\|f\".*INSERT\|f\".*UPDATE\|f\".*DELETE" [files]
|
|
42
|
-
grep -rn "\\.format.*SELECT\|%s.*SELECT\|\\+.*SELECT" [files]
|
|
43
|
-
grep -rn "query.*\\$\\{" [files] # template literal SQL
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
**2c. XSS / Injection**
|
|
47
|
-
```bash
|
|
48
|
-
grep -rn "innerHTML\|dangerouslySetInnerHTML\|v-html\|\\|safe\b" [files]
|
|
49
|
-
grep -rn "eval(\|exec(\|subprocess.*shell=True" [files]
|
|
50
|
-
grep -rn "document\\.write\|document\\.location" [files]
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
**2d. Auth/Session Issues**
|
|
54
|
-
```bash
|
|
55
|
-
grep -rn "jwt\\.decode.*verify.*false\|verify.*False" [files]
|
|
56
|
-
grep -rn "cors.*\\*\|origin.*\\*" [files]
|
|
57
|
-
grep -rn "httpOnly.*false\|secure.*false\|sameSite.*none" [files]
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
**2e. Path Traversal**
|
|
61
|
-
```bash
|
|
62
|
-
grep -rn "req\\.params\|req\\.query\|req\\.body" [files] | grep -i "path\|file\|dir"
|
|
63
|
-
grep -rn "\\.\\./\|\\.\\.\\\\" [files]
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
**2f. Sensitive Data Exposure**
|
|
67
|
-
```bash
|
|
68
|
-
grep -rn "console\\.log.*password\|console\\.log.*token\|console\\.log.*secret" [files]
|
|
69
|
-
grep -rn "log\\.info.*password\|logger.*token\|print.*secret" [files]
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
## Step 3: Codex Deep Review (for high-risk files)
|
|
73
|
-
|
|
74
|
-
For files with auth, payment, or database logic:
|
|
75
|
-
|
|
76
|
-
```
|
|
77
|
-
/OMG:escalate codex "Security deep review of [file]:
|
|
78
|
-
1. Read every line. Flag any: hardcoded secrets, SQL injection, XSS, CSRF, auth bypass, privilege escalation, insecure deserialization, SSRF.
|
|
79
|
-
2. Check auth flow completeness: does every protected route validate the token? Are permissions checked?
|
|
80
|
-
3. Check payment flow: is card data handled safely? Are amounts validated server-side?
|
|
81
|
-
4. Check database queries: all parameterized? Any raw string concatenation?
|
|
82
|
-
5. Rate this file: SAFE / NEEDS_FIX / CRITICAL with specific line numbers."
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
## Step 4: Report
|
|
86
|
-
|
|
87
|
-
```
|
|
88
|
-
Security Review — [scope]
|
|
89
|
-
━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
90
|
-
|
|
91
|
-
Files scanned: [N]
|
|
92
|
-
Security-critical files: [N]
|
|
93
|
-
|
|
94
|
-
CRITICAL [N]:
|
|
95
|
-
[file:line] Hardcoded API key: [type]
|
|
96
|
-
[file:line] SQL injection: unparameterized query
|
|
97
|
-
|
|
98
|
-
HIGH [N]:
|
|
99
|
-
[file:line] Missing auth check on protected route
|
|
100
|
-
[file:line] CORS wildcard in production config
|
|
101
|
-
|
|
102
|
-
MEDIUM [N]:
|
|
103
|
-
[file:line] Sensitive data in console.log
|
|
104
|
-
[file:line] httpOnly not set on session cookie
|
|
105
|
-
|
|
106
|
-
LOW [N]:
|
|
107
|
-
[file:line] Missing rate limiting on login endpoint
|
|
108
|
-
|
|
109
|
-
Codex Deep Review:
|
|
110
|
-
[file]: [SAFE|NEEDS_FIX|CRITICAL] — [summary]
|
|
111
|
-
|
|
112
|
-
Fix priority: [ordered list of what to fix first]
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
## Anti-patterns
|
|
116
|
-
- Don't just grep and dump raw output — analyze each finding
|
|
117
|
-
- Don't skip test files entirely (they can leak real credentials)
|
|
118
|
-
- Don't claim "looks secure" without running ALL checks above
|
|
119
|
-
- Don't treat this as optional for auth/payment/database changes
|
|
13
|
+
- normalized security findings
|
|
14
|
+
- dependency and AST enrichment
|
|
15
|
+
- evidence-ready provenance and trust scores
|
|
16
|
+
- reuse across CLI, compat routing, control plane, MCP, and ship flows
|
|
@@ -24,7 +24,7 @@ argument-hint: "[goal or optional path to .omg/idea.yml]"
|
|
|
24
24
|
- `tests[]`, `security_scans[]`, `diff_summary`, `reproducibility`, `unresolved_risks[]`.
|
|
25
25
|
|
|
26
26
|
## Step 4: Security and trust checks
|
|
27
|
-
- Run `/OMG:security-
|
|
27
|
+
- Run `/OMG:security-check` for auth/payment/database/sensitive changes.
|
|
28
28
|
- If config/hook/MCP changes are involved, ensure trust manifest is updated at `.omg/trust/manifest.lock.json`.
|
|
29
29
|
|
|
30
30
|
## Step 5: PR-ready output
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "omg-advanced",
|
|
3
3
|
"version": "1.0.5",
|
|
4
|
-
"description": "Advanced OMG commands - deep planning, learning, code review,
|
|
4
|
+
"description": "Advanced OMG commands - deep planning, learning, code review, and specialized workflows",
|
|
5
5
|
"type": "omg-plugin",
|
|
6
6
|
"commands": {
|
|
7
7
|
"deep-plan": {
|
|
@@ -19,11 +19,6 @@
|
|
|
19
19
|
"description": "Deep code review with line-by-line analysis",
|
|
20
20
|
"category": "quality"
|
|
21
21
|
},
|
|
22
|
-
"security-review": {
|
|
23
|
-
"path": "commands/OMG:security-review.md",
|
|
24
|
-
"description": "Security vulnerability scanning",
|
|
25
|
-
"category": "security"
|
|
26
|
-
},
|
|
27
22
|
"ship": {
|
|
28
23
|
"path": "commands/OMG:ship.md",
|
|
29
24
|
"description": "Ship pipeline - idea to PR-ready summary",
|
|
@@ -69,10 +64,6 @@
|
|
|
69
64
|
"description": "Code quality and review",
|
|
70
65
|
"commands": ["code-review"]
|
|
71
66
|
},
|
|
72
|
-
"security": {
|
|
73
|
-
"description": "Security analysis and review",
|
|
74
|
-
"commands": ["security-review"]
|
|
75
|
-
},
|
|
76
67
|
"knowledge": {
|
|
77
68
|
"description": "Learning and skill creation",
|
|
78
69
|
"commands": ["learn"]
|
package/plugins/core/plugin.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "omg-core",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.4",
|
|
4
4
|
"description": "Core OMG commands - native setup, routing, orchestration, and verification surfaces",
|
|
5
5
|
"type": "omg-plugin",
|
|
6
6
|
"commands": {
|
|
@@ -39,6 +39,21 @@
|
|
|
39
39
|
"description": "Legacy skill compatibility dispatcher",
|
|
40
40
|
"category": "compatibility"
|
|
41
41
|
},
|
|
42
|
+
"security-check": {
|
|
43
|
+
"path": "commands/OMG:security-check.md",
|
|
44
|
+
"description": "Canonical security pipeline with normalized findings and evidence",
|
|
45
|
+
"category": "security"
|
|
46
|
+
},
|
|
47
|
+
"api-twin": {
|
|
48
|
+
"path": "commands/OMG:api-twin.md",
|
|
49
|
+
"description": "Contract replay and fixture-based API simulation",
|
|
50
|
+
"category": "contracts"
|
|
51
|
+
},
|
|
52
|
+
"preflight": {
|
|
53
|
+
"path": "commands/OMG:preflight.md",
|
|
54
|
+
"description": "Structured routing and evidence planning before execution",
|
|
55
|
+
"category": "routing"
|
|
56
|
+
},
|
|
42
57
|
"health-check": {
|
|
43
58
|
"path": "commands/OMG:health-check.md",
|
|
44
59
|
"description": "Verify project setup and tool integration",
|
|
@@ -90,7 +105,7 @@
|
|
|
90
105
|
},
|
|
91
106
|
"routing": {
|
|
92
107
|
"description": "Model routing and escalation",
|
|
93
|
-
"commands": ["escalate", "teams", "ccg"]
|
|
108
|
+
"commands": ["escalate", "teams", "ccg", "preflight"]
|
|
94
109
|
},
|
|
95
110
|
"orchestration": {
|
|
96
111
|
"description": "Multi-agent orchestration modes",
|
|
@@ -108,6 +123,14 @@
|
|
|
108
123
|
"description": "Cost tracking and session observability",
|
|
109
124
|
"commands": ["cost", "stats", "deps"]
|
|
110
125
|
},
|
|
126
|
+
"security": {
|
|
127
|
+
"description": "Canonical security and trust checks",
|
|
128
|
+
"commands": ["security-check"]
|
|
129
|
+
},
|
|
130
|
+
"contracts": {
|
|
131
|
+
"description": "Contract replay and API simulation",
|
|
132
|
+
"commands": ["api-twin"]
|
|
133
|
+
},
|
|
111
134
|
"visualization": {
|
|
112
135
|
"description": "Codebase visualization and architecture diagrams",
|
|
113
136
|
"commands": ["arch"]
|
package/pyproject.toml
CHANGED
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "oh-my-god"
|
|
7
|
-
version = "2.0.
|
|
7
|
+
version = "2.0.4"
|
|
8
8
|
description = "OMG (Oh My God) — Multi-agent orchestration, intelligent model routing, and durable session state for Claude Code"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
package/runtime/adoption.py
CHANGED
|
@@ -11,7 +11,7 @@ CANONICAL_REPO_URL = "https://github.com/trac3er00/OMG"
|
|
|
11
11
|
CANONICAL_PACKAGE_NAME = "@trac3er/oh-my-god"
|
|
12
12
|
CANONICAL_PLUGIN_ID = "omg"
|
|
13
13
|
CANONICAL_MARKETPLACE_ID = "omg"
|
|
14
|
-
CANONICAL_VERSION = "2.0.
|
|
14
|
+
CANONICAL_VERSION = "2.0.4"
|
|
15
15
|
|
|
16
16
|
VALID_ADOPTION_MODES = ("omg-only", "coexist")
|
|
17
17
|
VALID_PRESETS = ("safe", "balanced", "interop", "labs")
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"""Fixture-based API twin state and replay helpers."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import json
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
STATE_REL_PATH = Path(".omg") / "state" / "api_twin.json"
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def ingest_contract(project_dir: str, *, name: str, source_path: str) -> dict[str, Any]:
|
|
13
|
+
state = _load_state(project_dir)
|
|
14
|
+
contract_path = Path(source_path)
|
|
15
|
+
contract = {
|
|
16
|
+
"name": name,
|
|
17
|
+
"source_path": str(contract_path),
|
|
18
|
+
"content": contract_path.read_text(encoding="utf-8"),
|
|
19
|
+
"fidelity": "schema-only",
|
|
20
|
+
}
|
|
21
|
+
state.setdefault("contracts", {})[name] = contract
|
|
22
|
+
_save_state(project_dir, state)
|
|
23
|
+
return {
|
|
24
|
+
"schema": "ApiTwinContract",
|
|
25
|
+
"name": name,
|
|
26
|
+
"fidelity": "schema-only",
|
|
27
|
+
"source_path": str(contract_path),
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def record_fixture(
|
|
32
|
+
project_dir: str,
|
|
33
|
+
*,
|
|
34
|
+
name: str,
|
|
35
|
+
request: dict[str, Any],
|
|
36
|
+
response: dict[str, Any],
|
|
37
|
+
validated: bool,
|
|
38
|
+
) -> dict[str, Any]:
|
|
39
|
+
state = _load_state(project_dir)
|
|
40
|
+
fixture = {
|
|
41
|
+
"name": name,
|
|
42
|
+
"request": request,
|
|
43
|
+
"response": response,
|
|
44
|
+
"fidelity": "recorded-validated" if validated else "recorded",
|
|
45
|
+
"validated": validated,
|
|
46
|
+
}
|
|
47
|
+
state.setdefault("fixtures", {})[name] = fixture
|
|
48
|
+
_save_state(project_dir, state)
|
|
49
|
+
return {
|
|
50
|
+
"schema": "ApiTwinFixture",
|
|
51
|
+
"name": name,
|
|
52
|
+
"fidelity": fixture["fidelity"],
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def serve_fixture(
|
|
57
|
+
project_dir: str,
|
|
58
|
+
*,
|
|
59
|
+
name: str,
|
|
60
|
+
latency_ms: int = 0,
|
|
61
|
+
failure_mode: str = "",
|
|
62
|
+
schema_drift: bool = False,
|
|
63
|
+
) -> dict[str, Any]:
|
|
64
|
+
state = _load_state(project_dir)
|
|
65
|
+
fixture = _fixture(state, name)
|
|
66
|
+
response = dict(fixture.get("response", {}))
|
|
67
|
+
fidelity = str(fixture.get("fidelity", "recorded"))
|
|
68
|
+
if schema_drift:
|
|
69
|
+
response["__schema_drift__"] = True
|
|
70
|
+
fidelity = "stale"
|
|
71
|
+
if failure_mode:
|
|
72
|
+
response = {"error": failure_mode}
|
|
73
|
+
fidelity = "stale"
|
|
74
|
+
return {
|
|
75
|
+
"schema": "ApiTwinServeResult",
|
|
76
|
+
"name": name,
|
|
77
|
+
"latency_ms": latency_ms,
|
|
78
|
+
"failure_mode": failure_mode,
|
|
79
|
+
"fidelity": fidelity,
|
|
80
|
+
"response": response,
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def verify_fixture(project_dir: str, *, name: str, live_response: dict[str, Any]) -> dict[str, Any]:
|
|
85
|
+
state = _load_state(project_dir)
|
|
86
|
+
fixture = _fixture(state, name)
|
|
87
|
+
matches_live = fixture.get("response", {}) == live_response
|
|
88
|
+
fidelity = "recorded-validated" if matches_live else "stale"
|
|
89
|
+
fixture["fidelity"] = fidelity
|
|
90
|
+
fixture["validated"] = matches_live
|
|
91
|
+
state.setdefault("fixtures", {})[name] = fixture
|
|
92
|
+
_save_state(project_dir, state)
|
|
93
|
+
return {
|
|
94
|
+
"schema": "ApiTwinVerifyResult",
|
|
95
|
+
"name": name,
|
|
96
|
+
"fidelity": fidelity,
|
|
97
|
+
"matches_live": matches_live,
|
|
98
|
+
"live_verification_required": True,
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def _state_path(project_dir: str) -> Path:
|
|
103
|
+
return Path(project_dir) / STATE_REL_PATH
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def _load_state(project_dir: str) -> dict[str, Any]:
|
|
107
|
+
path = _state_path(project_dir)
|
|
108
|
+
if not path.exists():
|
|
109
|
+
return {"contracts": {}, "fixtures": {}}
|
|
110
|
+
try:
|
|
111
|
+
payload = json.loads(path.read_text(encoding="utf-8"))
|
|
112
|
+
except (OSError, json.JSONDecodeError):
|
|
113
|
+
return {"contracts": {}, "fixtures": {}}
|
|
114
|
+
return payload if isinstance(payload, dict) else {"contracts": {}, "fixtures": {}}
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def _save_state(project_dir: str, payload: dict[str, Any]) -> None:
|
|
118
|
+
path = _state_path(project_dir)
|
|
119
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
120
|
+
path.write_text(json.dumps(payload, indent=2, ensure_ascii=True) + "\n", encoding="utf-8")
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def _fixture(state: dict[str, Any], name: str) -> dict[str, Any]:
|
|
124
|
+
fixtures = state.get("fixtures", {})
|
|
125
|
+
if not isinstance(fixtures, dict) or name not in fixtures:
|
|
126
|
+
raise ValueError(f"Unknown API twin fixture: {name}")
|
|
127
|
+
fixture = fixtures[name]
|
|
128
|
+
if not isinstance(fixture, dict):
|
|
129
|
+
raise ValueError(f"Invalid API twin fixture: {name}")
|
|
130
|
+
return fixture
|