@trac3er/oh-my-god 2.0.4 → 2.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (206) hide show
  1. package/.agents/skills/omg/AGENTS.fragment.md +1 -1
  2. package/.agents/skills/omg/algorithms/SKILL.md +11 -0
  3. package/.agents/skills/omg/algorithms/openai.yaml +11 -0
  4. package/.agents/skills/omg/api-twin/SKILL.md +11 -0
  5. package/.agents/skills/omg/api-twin/openai.yaml +12 -0
  6. package/.agents/skills/omg/control-plane/SKILL.md +1 -1
  7. package/.agents/skills/omg/control-plane/openai.yaml +1 -1
  8. package/.agents/skills/omg/data-lineage/SKILL.md +11 -0
  9. package/.agents/skills/omg/data-lineage/openai.yaml +12 -0
  10. package/.agents/skills/omg/delta-classifier/SKILL.md +11 -0
  11. package/.agents/skills/omg/delta-classifier/openai.yaml +12 -0
  12. package/.agents/skills/omg/eval-gate/SKILL.md +11 -0
  13. package/.agents/skills/omg/eval-gate/openai.yaml +12 -0
  14. package/.agents/skills/omg/health/SKILL.md +11 -0
  15. package/.agents/skills/omg/health/openai.yaml +11 -0
  16. package/.agents/skills/omg/hook-governor/SKILL.md +1 -1
  17. package/.agents/skills/omg/hook-governor/openai.yaml +1 -1
  18. package/.agents/skills/omg/incident-replay/SKILL.md +11 -0
  19. package/.agents/skills/omg/incident-replay/openai.yaml +12 -0
  20. package/.agents/skills/omg/lsp-pack/SKILL.md +1 -1
  21. package/.agents/skills/omg/lsp-pack/openai.yaml +1 -1
  22. package/.agents/skills/omg/mcp-fabric/SKILL.md +1 -1
  23. package/.agents/skills/omg/mcp-fabric/openai.yaml +1 -1
  24. package/.agents/skills/omg/preflight/SKILL.md +11 -0
  25. package/.agents/skills/omg/preflight/openai.yaml +12 -0
  26. package/.agents/skills/omg/remote-supervisor/SKILL.md +11 -0
  27. package/.agents/skills/omg/remote-supervisor/openai.yaml +12 -0
  28. package/.agents/skills/omg/robotics/SKILL.md +11 -0
  29. package/.agents/skills/omg/robotics/openai.yaml +11 -0
  30. package/.agents/skills/omg/secure-worktree-pipeline/SKILL.md +1 -1
  31. package/.agents/skills/omg/secure-worktree-pipeline/openai.yaml +1 -1
  32. package/.agents/skills/omg/security-check/SKILL.md +11 -0
  33. package/.agents/skills/omg/security-check/openai.yaml +13 -0
  34. package/.agents/skills/omg/tracebank/SKILL.md +11 -0
  35. package/.agents/skills/omg/tracebank/openai.yaml +12 -0
  36. package/.agents/skills/omg/vision/SKILL.md +11 -0
  37. package/.agents/skills/omg/vision/openai.yaml +11 -0
  38. package/.claude-plugin/marketplace.json +3 -3
  39. package/.claude-plugin/plugin.json +1 -1
  40. package/.claude-plugin/scripts/uninstall.sh +2 -2
  41. package/OMG-setup.sh +1 -1
  42. package/OMG_COMPAT_CONTRACT.md +1 -1
  43. package/README.md +2 -2
  44. package/commands/__init__.py +1 -0
  45. package/control_plane/__init__.py +2 -0
  46. package/control_plane/openapi.yaml +228 -0
  47. package/control_plane/server.py +123 -0
  48. package/control_plane/service.py +185 -0
  49. package/dist/enterprise/bundle/.agents/skills/omg/algorithms/SKILL.md +11 -0
  50. package/dist/enterprise/bundle/.agents/skills/omg/algorithms/openai.yaml +11 -0
  51. package/dist/enterprise/bundle/.agents/skills/omg/api-twin/SKILL.md +11 -0
  52. package/dist/enterprise/bundle/.agents/skills/omg/api-twin/openai.yaml +12 -0
  53. package/dist/enterprise/bundle/.agents/skills/omg/data-lineage/SKILL.md +11 -0
  54. package/dist/enterprise/bundle/.agents/skills/omg/data-lineage/openai.yaml +12 -0
  55. package/dist/enterprise/bundle/.agents/skills/omg/delta-classifier/SKILL.md +11 -0
  56. package/dist/enterprise/bundle/.agents/skills/omg/delta-classifier/openai.yaml +12 -0
  57. package/dist/enterprise/bundle/.agents/skills/omg/eval-gate/SKILL.md +11 -0
  58. package/dist/enterprise/bundle/.agents/skills/omg/eval-gate/openai.yaml +12 -0
  59. package/dist/enterprise/bundle/.agents/skills/omg/health/SKILL.md +11 -0
  60. package/dist/enterprise/bundle/.agents/skills/omg/health/openai.yaml +11 -0
  61. package/dist/enterprise/bundle/.agents/skills/omg/incident-replay/SKILL.md +11 -0
  62. package/dist/enterprise/bundle/.agents/skills/omg/incident-replay/openai.yaml +12 -0
  63. package/dist/enterprise/bundle/.agents/skills/omg/preflight/SKILL.md +11 -0
  64. package/dist/enterprise/bundle/.agents/skills/omg/preflight/openai.yaml +12 -0
  65. package/dist/enterprise/bundle/.agents/skills/omg/remote-supervisor/SKILL.md +11 -0
  66. package/dist/enterprise/bundle/.agents/skills/omg/remote-supervisor/openai.yaml +12 -0
  67. package/dist/enterprise/bundle/.agents/skills/omg/robotics/SKILL.md +11 -0
  68. package/dist/enterprise/bundle/.agents/skills/omg/robotics/openai.yaml +11 -0
  69. package/dist/enterprise/bundle/.agents/skills/omg/security-check/SKILL.md +11 -0
  70. package/dist/enterprise/bundle/.agents/skills/omg/security-check/openai.yaml +13 -0
  71. package/dist/enterprise/bundle/.agents/skills/omg/tracebank/SKILL.md +11 -0
  72. package/dist/enterprise/bundle/.agents/skills/omg/tracebank/openai.yaml +12 -0
  73. package/dist/enterprise/bundle/.agents/skills/omg/vision/SKILL.md +11 -0
  74. package/dist/enterprise/bundle/.agents/skills/omg/vision/openai.yaml +11 -0
  75. package/dist/enterprise/bundle/.claude-plugin/marketplace.json +3 -3
  76. package/dist/enterprise/bundle/.claude-plugin/plugin.json +1 -1
  77. package/dist/enterprise/bundle/OMG_COMPAT_CONTRACT.md +1 -1
  78. package/dist/enterprise/bundle/registry/bundles/algorithms.yaml +45 -0
  79. package/dist/enterprise/bundle/registry/bundles/api-twin.yaml +48 -0
  80. package/dist/enterprise/bundle/registry/bundles/control-plane.yaml +61 -0
  81. package/dist/enterprise/bundle/registry/bundles/data-lineage.yaml +47 -0
  82. package/dist/enterprise/bundle/registry/bundles/delta-classifier.yaml +47 -0
  83. package/dist/enterprise/bundle/registry/bundles/eval-gate.yaml +47 -0
  84. package/dist/enterprise/bundle/registry/bundles/health.yaml +45 -0
  85. package/dist/enterprise/bundle/registry/bundles/hook-governor.yaml +97 -0
  86. package/dist/enterprise/bundle/registry/bundles/incident-replay.yaml +47 -0
  87. package/dist/enterprise/bundle/registry/bundles/lsp-pack.yaml +48 -0
  88. package/dist/enterprise/bundle/registry/bundles/mcp-fabric.yaml +53 -0
  89. package/dist/enterprise/bundle/registry/bundles/preflight.yaml +48 -0
  90. package/dist/enterprise/bundle/registry/bundles/remote-supervisor.yaml +49 -0
  91. package/dist/enterprise/bundle/registry/bundles/robotics.yaml +45 -0
  92. package/dist/enterprise/bundle/registry/bundles/secure-worktree-pipeline.yaml +54 -0
  93. package/dist/enterprise/bundle/registry/bundles/security-check.yaml +50 -0
  94. package/dist/enterprise/bundle/registry/bundles/tracebank.yaml +47 -0
  95. package/dist/enterprise/bundle/registry/bundles/vision.yaml +45 -0
  96. package/dist/enterprise/bundle/registry/omg-capability.schema.json +80 -0
  97. package/dist/enterprise/bundle/settings.json +21 -6
  98. package/dist/enterprise/manifest.json +167 -11
  99. package/dist/public/bundle/.agents/skills/omg/algorithms/SKILL.md +11 -0
  100. package/dist/public/bundle/.agents/skills/omg/algorithms/openai.yaml +11 -0
  101. package/dist/public/bundle/.agents/skills/omg/api-twin/SKILL.md +11 -0
  102. package/dist/public/bundle/.agents/skills/omg/api-twin/openai.yaml +12 -0
  103. package/dist/public/bundle/.agents/skills/omg/data-lineage/SKILL.md +11 -0
  104. package/dist/public/bundle/.agents/skills/omg/data-lineage/openai.yaml +12 -0
  105. package/dist/public/bundle/.agents/skills/omg/delta-classifier/SKILL.md +11 -0
  106. package/dist/public/bundle/.agents/skills/omg/delta-classifier/openai.yaml +12 -0
  107. package/dist/public/bundle/.agents/skills/omg/eval-gate/SKILL.md +11 -0
  108. package/dist/public/bundle/.agents/skills/omg/eval-gate/openai.yaml +12 -0
  109. package/dist/public/bundle/.agents/skills/omg/health/SKILL.md +11 -0
  110. package/dist/public/bundle/.agents/skills/omg/health/openai.yaml +11 -0
  111. package/dist/public/bundle/.agents/skills/omg/incident-replay/SKILL.md +11 -0
  112. package/dist/public/bundle/.agents/skills/omg/incident-replay/openai.yaml +12 -0
  113. package/dist/public/bundle/.agents/skills/omg/preflight/SKILL.md +11 -0
  114. package/dist/public/bundle/.agents/skills/omg/preflight/openai.yaml +12 -0
  115. package/dist/public/bundle/.agents/skills/omg/remote-supervisor/SKILL.md +11 -0
  116. package/dist/public/bundle/.agents/skills/omg/remote-supervisor/openai.yaml +12 -0
  117. package/dist/public/bundle/.agents/skills/omg/robotics/SKILL.md +11 -0
  118. package/dist/public/bundle/.agents/skills/omg/robotics/openai.yaml +11 -0
  119. package/dist/public/bundle/.agents/skills/omg/security-check/SKILL.md +11 -0
  120. package/dist/public/bundle/.agents/skills/omg/security-check/openai.yaml +13 -0
  121. package/dist/public/bundle/.agents/skills/omg/tracebank/SKILL.md +11 -0
  122. package/dist/public/bundle/.agents/skills/omg/tracebank/openai.yaml +12 -0
  123. package/dist/public/bundle/.agents/skills/omg/vision/SKILL.md +11 -0
  124. package/dist/public/bundle/.agents/skills/omg/vision/openai.yaml +11 -0
  125. package/dist/public/bundle/.claude-plugin/marketplace.json +3 -3
  126. package/dist/public/bundle/.claude-plugin/plugin.json +1 -1
  127. package/dist/public/bundle/OMG_COMPAT_CONTRACT.md +1 -1
  128. package/dist/public/bundle/registry/bundles/algorithms.yaml +45 -0
  129. package/dist/public/bundle/registry/bundles/api-twin.yaml +48 -0
  130. package/dist/public/bundle/registry/bundles/control-plane.yaml +61 -0
  131. package/dist/public/bundle/registry/bundles/data-lineage.yaml +47 -0
  132. package/dist/public/bundle/registry/bundles/delta-classifier.yaml +47 -0
  133. package/dist/public/bundle/registry/bundles/eval-gate.yaml +47 -0
  134. package/dist/public/bundle/registry/bundles/health.yaml +45 -0
  135. package/dist/public/bundle/registry/bundles/hook-governor.yaml +97 -0
  136. package/dist/public/bundle/registry/bundles/incident-replay.yaml +47 -0
  137. package/dist/public/bundle/registry/bundles/lsp-pack.yaml +48 -0
  138. package/dist/public/bundle/registry/bundles/mcp-fabric.yaml +53 -0
  139. package/dist/public/bundle/registry/bundles/preflight.yaml +48 -0
  140. package/dist/public/bundle/registry/bundles/remote-supervisor.yaml +49 -0
  141. package/dist/public/bundle/registry/bundles/robotics.yaml +45 -0
  142. package/dist/public/bundle/registry/bundles/secure-worktree-pipeline.yaml +54 -0
  143. package/dist/public/bundle/registry/bundles/security-check.yaml +50 -0
  144. package/dist/public/bundle/registry/bundles/tracebank.yaml +47 -0
  145. package/dist/public/bundle/registry/bundles/vision.yaml +45 -0
  146. package/dist/public/bundle/registry/omg-capability.schema.json +80 -0
  147. package/dist/public/bundle/settings.json +17 -4
  148. package/dist/public/manifest.json +167 -11
  149. package/docs/assets/omg-hud.svg +32 -0
  150. package/docs/install/claude-code.md +31 -0
  151. package/docs/install/codex.md +29 -0
  152. package/docs/migration/native-adoption.md +57 -0
  153. package/docs/proof.md +55 -0
  154. package/docs/release-checklist.md +38 -0
  155. package/docs/transcripts/crazy.md +17 -0
  156. package/docs/transcripts/setup.md +25 -0
  157. package/hooks/shadow_manager.py +6 -0
  158. package/package.json +1 -1
  159. package/plugins/__init__.py +1 -0
  160. package/plugins/core/plugin.json +1 -1
  161. package/pyproject.toml +38 -2
  162. package/registry/__init__.py +1 -0
  163. package/registry/bundles/algorithms.yaml +45 -0
  164. package/registry/bundles/api-twin.yaml +48 -0
  165. package/registry/bundles/control-plane.yaml +61 -0
  166. package/registry/bundles/data-lineage.yaml +47 -0
  167. package/registry/bundles/delta-classifier.yaml +47 -0
  168. package/registry/bundles/eval-gate.yaml +47 -0
  169. package/registry/bundles/health.yaml +45 -0
  170. package/registry/bundles/hook-governor.yaml +97 -0
  171. package/registry/bundles/incident-replay.yaml +47 -0
  172. package/registry/bundles/lsp-pack.yaml +48 -0
  173. package/registry/bundles/mcp-fabric.yaml +53 -0
  174. package/registry/bundles/preflight.yaml +48 -0
  175. package/registry/bundles/remote-supervisor.yaml +49 -0
  176. package/registry/bundles/robotics.yaml +45 -0
  177. package/registry/bundles/secure-worktree-pipeline.yaml +54 -0
  178. package/registry/bundles/security-check.yaml +50 -0
  179. package/registry/bundles/tracebank.yaml +47 -0
  180. package/registry/bundles/vision.yaml +45 -0
  181. package/registry/omg-capability.schema.json +80 -0
  182. package/registry/verify_artifact.py +90 -0
  183. package/runtime/adapters/claude.py +3 -0
  184. package/runtime/adapters/gpt.py +3 -0
  185. package/runtime/adapters/local.py +3 -0
  186. package/runtime/adoption.py +1 -1
  187. package/runtime/api_twin.py +60 -11
  188. package/runtime/asset_loader.py +62 -0
  189. package/runtime/compat.py +3 -2
  190. package/runtime/contract_compiler.py +171 -22
  191. package/runtime/data_lineage.py +73 -0
  192. package/runtime/delta_classifier.py +81 -0
  193. package/runtime/domain_packs.py +12 -0
  194. package/runtime/ecosystem.py +1 -1
  195. package/runtime/eval_gate.py +50 -0
  196. package/runtime/incident_replay.py +47 -0
  197. package/runtime/mcp_memory_server.py +1 -1
  198. package/runtime/omg_compat_contract_snapshot.json +1 -1
  199. package/runtime/omg_contract_snapshot.json +1 -1
  200. package/runtime/omg_mcp_server.py +3 -1
  201. package/runtime/preflight.py +22 -1
  202. package/runtime/remote_supervisor.py +64 -0
  203. package/runtime/security_check.py +119 -2
  204. package/runtime/tracebank.py +53 -0
  205. package/scripts/omg.py +187 -2
  206. package/settings.json +21 -6
@@ -7,10 +7,15 @@ import json
7
7
  import os
8
8
  from pathlib import Path
9
9
  import shutil
10
+ import subprocess
11
+ import sys
12
+ import tempfile
10
13
  from typing import Any, Iterable
14
+ import zipfile
11
15
 
12
16
  import yaml
13
17
 
18
+ from runtime.asset_loader import resolve_asset, resolve_assets
14
19
  from runtime.adoption import (
15
20
  CANONICAL_MARKETPLACE_ID,
16
21
  CANONICAL_PACKAGE_NAME,
@@ -31,6 +36,19 @@ DEFAULT_REQUIRED_BUNDLES = (
31
36
  "mcp-fabric",
32
37
  "lsp-pack",
33
38
  "secure-worktree-pipeline",
39
+ "security-check",
40
+ "api-twin",
41
+ "preflight",
42
+ "robotics",
43
+ "vision",
44
+ "algorithms",
45
+ "health",
46
+ "tracebank",
47
+ "eval-gate",
48
+ "delta-classifier",
49
+ "incident-replay",
50
+ "data-lineage",
51
+ "remote-supervisor",
34
52
  )
35
53
  REQUIRED_DOC_TOKENS = (
36
54
  "execution_contract",
@@ -96,24 +114,36 @@ def _sha256_file(path: Path) -> str:
96
114
 
97
115
 
98
116
  def load_contract_doc(root_dir: str | Path | None = None) -> str:
99
- root = _resolve_root(root_dir)
100
- return (root / CONTRACT_DOC_PATH).read_text(encoding="utf-8")
117
+ if root_dir is not None:
118
+ root = _resolve_root(root_dir)
119
+ candidate = root / CONTRACT_DOC_PATH
120
+ if candidate.exists():
121
+ return candidate.read_text(encoding="utf-8")
122
+ return resolve_asset(CONTRACT_DOC_PATH).read_text(encoding="utf-8")
101
123
 
102
124
 
103
125
  def load_contract_schema(root_dir: str | Path | None = None) -> dict[str, Any]:
104
- root = _resolve_root(root_dir)
105
- return _load_json(root / SCHEMA_PATH)
126
+ if root_dir is not None:
127
+ root = _resolve_root(root_dir)
128
+ candidate = root / SCHEMA_PATH
129
+ if candidate.exists():
130
+ return _load_json(candidate)
131
+ return _load_json(resolve_asset(SCHEMA_PATH))
106
132
 
107
133
 
108
134
  def load_contract_bundles(root_dir: str | Path | None = None) -> list[dict[str, Any]]:
109
135
  root = _resolve_root(root_dir)
110
136
  bundles: list[dict[str, Any]] = []
111
- for path in sorted((root / BUNDLES_DIR).glob("*.yaml")):
137
+ paths = sorted((root / BUNDLES_DIR).glob("*.yaml")) if (root / BUNDLES_DIR).exists() else resolve_assets(BUNDLES_DIR, suffix=".yaml")
138
+ for path in paths:
112
139
  parsed = yaml.safe_load(path.read_text(encoding="utf-8"))
113
140
  if not isinstance(parsed, dict):
114
141
  raise ValueError(f"Expected mapping bundle manifest in {path}")
115
142
  bundle = dict(parsed)
116
- bundle["_path"] = str(path.relative_to(root))
143
+ try:
144
+ bundle["_path"] = str(path.relative_to(root))
145
+ except ValueError:
146
+ bundle["_path"] = str(Path(BUNDLES_DIR) / path.name)
117
147
  bundles.append(bundle)
118
148
  return bundles
119
149
 
@@ -133,34 +163,30 @@ def validate_contract_registry(root_dir: str | Path | None = None) -> dict[str,
133
163
  root = _resolve_root(root_dir)
134
164
  errors: list[str] = []
135
165
 
136
- doc_path = root / CONTRACT_DOC_PATH
137
- schema_path = root / SCHEMA_PATH
138
- bundles_path = root / BUNDLES_DIR
139
-
140
- if not doc_path.exists():
166
+ try:
167
+ doc_text = load_contract_doc(root)
168
+ except FileNotFoundError:
141
169
  errors.append(f"missing contract doc: {CONTRACT_DOC_PATH}")
142
170
  doc_text = ""
143
171
  else:
144
- doc_text = doc_path.read_text(encoding="utf-8")
145
172
  for token in REQUIRED_DOC_TOKENS:
146
173
  if token not in doc_text:
147
174
  errors.append(f"contract doc missing token: {token}")
148
175
  if CANONICAL_VERSION not in doc_text:
149
176
  errors.append(f"contract doc missing version: {CANONICAL_VERSION}")
150
177
 
151
- if not schema_path.exists():
178
+ try:
179
+ schema_payload = load_contract_schema(root)
180
+ except FileNotFoundError:
152
181
  errors.append(f"missing contract schema: {SCHEMA_PATH}")
153
182
  schema_payload: dict[str, Any] = {}
154
183
  else:
155
- schema_payload = _load_json(schema_path)
156
184
  if str(schema_payload.get("version", "")) != CANONICAL_VERSION:
157
185
  errors.append(f"contract schema version drift: {schema_payload.get('version')!r}")
158
186
 
159
- if not bundles_path.exists():
187
+ bundles = load_contract_bundles(root)
188
+ if not bundles:
160
189
  errors.append(f"missing bundles directory: {BUNDLES_DIR}")
161
- bundles: list[dict[str, Any]] = []
162
- else:
163
- bundles = load_contract_bundles(root)
164
190
 
165
191
  bundle_ids = set()
166
192
  bundle_summaries: list[dict[str, Any]] = []
@@ -208,14 +234,15 @@ def validate_contract_registry(root_dir: str | Path | None = None) -> dict[str,
208
234
  def _copy_contract_inputs(root: Path, output_root: Path) -> list[Path]:
209
235
  copied: list[Path] = []
210
236
  for rel_path in [CONTRACT_DOC_PATH, SCHEMA_PATH]:
211
- src = root / rel_path
237
+ src = resolve_asset(rel_path)
212
238
  dst = output_root / rel_path
213
239
  _write_text(dst, src.read_text(encoding="utf-8"))
214
240
  copied.append(dst)
215
- for path in sorted((root / BUNDLES_DIR).glob("*.yaml")):
216
- rel_path = path.relative_to(root)
241
+ for bundle in load_contract_bundles(root):
242
+ rel_path = Path(str(bundle["_path"]))
243
+ src = resolve_asset(rel_path)
217
244
  dst = output_root / rel_path
218
- _write_text(dst, path.read_text(encoding="utf-8"))
245
+ _write_text(dst, src.read_text(encoding="utf-8"))
219
246
  copied.append(dst)
220
247
  return copied
221
248
 
@@ -368,6 +395,8 @@ def _compile_claude_outputs(
368
395
  artifacts.append(output_root / ".mcp.json")
369
396
 
370
397
  settings_path = root / "settings.json"
398
+ if not settings_path.exists():
399
+ settings_path = resolve_asset("settings.json")
371
400
  settings = _load_json(settings_path)
372
401
  hook_bundle = _bundle_map(bundles)["hook-governor"]
373
402
  settings["hooks"] = _compile_hook_settings(hook_bundle)
@@ -673,6 +702,31 @@ def build_release_readiness(
673
702
  blockers.append(f"missing compiled outputs: {', '.join(missing_outputs)}")
674
703
  checks["compiled_outputs"] = {"missing": missing_outputs}
675
704
 
705
+ required_bundle_outputs: list[Path] = []
706
+ for bundle_id in DEFAULT_REQUIRED_BUNDLES:
707
+ required_bundle_outputs.extend(
708
+ [
709
+ output / ".agents" / "skills" / "omg" / bundle_id / "SKILL.md",
710
+ output / ".agents" / "skills" / "omg" / bundle_id / "openai.yaml",
711
+ ]
712
+ )
713
+ missing_bundle_outputs = [str(path.relative_to(output)) for path in required_bundle_outputs if not path.exists()]
714
+ if missing_bundle_outputs:
715
+ blockers.append(f"missing bundle outputs: {', '.join(missing_bundle_outputs)}")
716
+ checks["bundle_outputs"] = {"missing": missing_bundle_outputs}
717
+
718
+ evidence_check = _check_recent_evidence(output)
719
+ checks["evidence"] = evidence_check
720
+ blockers.extend(evidence_check.get("blockers", []))
721
+
722
+ eval_check = _check_eval_gate(output)
723
+ checks["eval_gate"] = eval_check
724
+ blockers.extend(eval_check.get("blockers", []))
725
+
726
+ package_check = _check_packaged_install_smoke(root)
727
+ checks["package_smoke"] = package_check
728
+ blockers.extend(package_check.get("blockers", []))
729
+
676
730
  providers = _provider_statuses()
677
731
  checks["providers"] = providers
678
732
  for provider_name, status in providers.items():
@@ -696,3 +750,98 @@ def build_release_readiness(
696
750
  "blockers": blockers,
697
751
  "checks": checks,
698
752
  }
753
+
754
+
755
+ def _check_recent_evidence(output_root: Path) -> dict[str, Any]:
756
+ evidence_dir = output_root / ".omg" / "evidence"
757
+ if not evidence_dir.exists():
758
+ return {"status": "missing", "blockers": []}
759
+
760
+ evidence_files = sorted(path for path in evidence_dir.glob("*.json") if path.is_file())
761
+ if not evidence_files:
762
+ return {"status": "missing", "blockers": []}
763
+
764
+ evidence_payloads: list[tuple[Path, dict[str, Any]]] = []
765
+ for path in evidence_files:
766
+ try:
767
+ payload = _load_json(path)
768
+ except Exception:
769
+ continue
770
+ if payload.get("schema") == "EvidencePack":
771
+ evidence_payloads.append((path, payload))
772
+
773
+ if not evidence_payloads:
774
+ return {"status": "missing", "blockers": []}
775
+
776
+ evidence_path, payload = evidence_payloads[-1]
777
+ blockers: list[str] = []
778
+ if not payload.get("security_scans"):
779
+ blockers.append("cosmetic evidence: security_scans is empty")
780
+ if not payload.get("provenance"):
781
+ blockers.append("cosmetic evidence: provenance is empty")
782
+ if not payload.get("trace_ids"):
783
+ blockers.append("missing trace ids in evidence")
784
+ if not payload.get("lineage"):
785
+ blockers.append("missing lineage in evidence")
786
+ tests = payload.get("tests", [])
787
+ if isinstance(tests, list):
788
+ for item in tests:
789
+ if isinstance(item, dict) and item.get("name") == "worker_implementation" and not item.get("passed", False):
790
+ blockers.append("simulated worker evidence detected")
791
+ break
792
+ return {
793
+ "status": "ok" if not blockers else "error",
794
+ "evidence_file": str(evidence_path.relative_to(output_root)),
795
+ "blockers": blockers,
796
+ }
797
+
798
+
799
+ def _check_eval_gate(output_root: Path) -> dict[str, Any]:
800
+ latest_path = output_root / ".omg" / "evals" / "latest.json"
801
+ if not latest_path.exists():
802
+ return {"status": "missing", "blockers": []}
803
+ payload = _load_json(latest_path)
804
+ blockers: list[str] = []
805
+ if payload.get("status") != "ok" or bool(payload.get("summary", {}).get("regressed")):
806
+ blockers.append("eval regression detected")
807
+ return {
808
+ "status": "ok" if not blockers else "error",
809
+ "path": str(latest_path.relative_to(output_root)),
810
+ "blockers": blockers,
811
+ }
812
+
813
+
814
+ def _check_packaged_install_smoke(root: Path) -> dict[str, Any]:
815
+ blockers: list[str] = []
816
+ with tempfile.TemporaryDirectory(prefix="omg-wheel-") as tmp_dir:
817
+ proc = subprocess.run(
818
+ [sys.executable, "-m", "pip", "wheel", ".", "--no-deps", "-w", tmp_dir],
819
+ cwd=str(root),
820
+ capture_output=True,
821
+ text=True,
822
+ check=False,
823
+ timeout=120,
824
+ )
825
+ if proc.returncode != 0:
826
+ return {
827
+ "status": "error",
828
+ "blockers": ["package smoke failed to build wheel"],
829
+ "stdout": proc.stdout,
830
+ "stderr": proc.stderr,
831
+ }
832
+ wheels = sorted(Path(tmp_dir).glob("*.whl"))
833
+ if not wheels:
834
+ return {"status": "error", "blockers": ["package smoke did not produce a wheel"]}
835
+ with zipfile.ZipFile(wheels[-1]) as archive:
836
+ names = set(archive.namelist())
837
+ required_suffixes = (
838
+ "control_plane/service.py",
839
+ "registry/verify_artifact.py",
840
+ "plugins/dephealth/cve_scanner.py",
841
+ "OMG_COMPAT_CONTRACT.md",
842
+ ".agents/skills/omg/security-check/SKILL.md",
843
+ )
844
+ for suffix in required_suffixes:
845
+ if not any(name.endswith(suffix) for name in names):
846
+ blockers.append(f"package parity missing {suffix}")
847
+ return {"status": "ok" if not blockers else "error", "blockers": blockers}
@@ -0,0 +1,73 @@
1
+ """Lineage manifests for generated OMG artifacts."""
2
+ from __future__ import annotations
3
+
4
+ from datetime import datetime, timezone
5
+ import json
6
+ from pathlib import Path
7
+ from typing import Any
8
+ from uuid import uuid4
9
+
10
+
11
+ def _now() -> str:
12
+ return datetime.now(timezone.utc).isoformat()
13
+
14
+
15
+ def build_lineage_manifest(
16
+ project_dir: str,
17
+ *,
18
+ artifact_type: str,
19
+ sources: list[dict[str, Any]],
20
+ privacy: str,
21
+ license: str,
22
+ derivation: dict[str, Any],
23
+ trace_id: str | None = None,
24
+ ) -> dict[str, Any]:
25
+ lineage_id = f"lineage-{uuid4().hex}"
26
+ payload = {
27
+ "schema": "DataLineageManifest",
28
+ "lineage_id": lineage_id,
29
+ "generated_at": _now(),
30
+ "artifact_type": artifact_type,
31
+ "sources": sources,
32
+ "privacy": privacy,
33
+ "license": license,
34
+ "derivation": derivation,
35
+ "trace_id": trace_id or "",
36
+ }
37
+ validation = validate_lineage_manifest(payload)
38
+ payload["status"] = validation["status"]
39
+ payload["errors"] = validation["errors"]
40
+
41
+ rel_path = Path(".omg") / "lineage" / f"{lineage_id}.json"
42
+ path = Path(project_dir) / rel_path
43
+ path.parent.mkdir(parents=True, exist_ok=True)
44
+ path.write_text(json.dumps(payload, indent=2, ensure_ascii=True) + "\n", encoding="utf-8")
45
+ payload["path"] = rel_path.as_posix()
46
+ return payload
47
+
48
+
49
+ def validate_lineage_manifest(payload: dict[str, Any]) -> dict[str, Any]:
50
+ errors: list[str] = []
51
+ if not payload.get("artifact_type"):
52
+ errors.append("artifact_type is required")
53
+ if not payload.get("privacy"):
54
+ errors.append("privacy is required")
55
+ if not payload.get("license"):
56
+ errors.append("license is required")
57
+ sources = payload.get("sources", [])
58
+ if not isinstance(sources, list) or not sources:
59
+ errors.append("sources are required")
60
+ else:
61
+ for idx, source in enumerate(sources):
62
+ if not isinstance(source, dict):
63
+ errors.append(f"source {idx} must be an object")
64
+ continue
65
+ if not source.get("license"):
66
+ errors.append(f"source {idx} missing license")
67
+ if not source.get("path"):
68
+ errors.append(f"source {idx} missing path")
69
+ return {
70
+ "schema": "DataLineageValidationResult",
71
+ "status": "ok" if not errors else "error",
72
+ "errors": errors,
73
+ }
@@ -0,0 +1,81 @@
1
+ """Repo-aware change classification for routing and policy attachment."""
2
+ from __future__ import annotations
3
+
4
+ import json
5
+ from pathlib import Path
6
+ import subprocess
7
+ from typing import Any
8
+
9
+
10
+ _CATEGORY_RULES: dict[str, tuple[str, ...]] = {
11
+ "auth": ("auth", "token", "secret", "login", "credential"),
12
+ "payment": ("payment", "billing", "invoice", "stripe", "checkout"),
13
+ "db": ("migration", "schema", "database", "sql", "postgres", "mysql"),
14
+ "infra": ("terraform", ".tf", "deploy", "helm", "k8s", "docker"),
15
+ "api": ("openapi", "swagger", "postman", "endpoint", "api"),
16
+ "data": ("dataset", "lineage", "privacy", "warehouse", "etl"),
17
+ "compliance": ("gdpr", "hipaa", "pci", "soc2", "privacy"),
18
+ "robotics": ("robot", "actuator", "sensor", "simulator"),
19
+ "vision": ("vision", "image", "camera", "cv"),
20
+ "health": ("health", "patient", "clinical", "medical"),
21
+ "algorithms": ("algorithm", "benchmark", "determinism", "complexity"),
22
+ }
23
+
24
+
25
+ def classify_project_changes(
26
+ project_dir: str,
27
+ *,
28
+ touched_files: list[str] | None = None,
29
+ goal: str = "",
30
+ ) -> dict[str, Any]:
31
+ files = touched_files if touched_files is not None else _discover_files(project_dir)
32
+ manifest_names = sorted(path.name for path in Path(project_dir).glob("*") if path.is_file())
33
+ haystacks = [goal.lower(), *[file.lower() for file in files], *[name.lower() for name in manifest_names]]
34
+
35
+ categories = {
36
+ category
37
+ for category, tokens in _CATEGORY_RULES.items()
38
+ if any(token in haystack for token in tokens for haystack in haystacks)
39
+ }
40
+ if not categories:
41
+ categories.add("implementation")
42
+
43
+ result = {
44
+ "schema": "DeltaClassification",
45
+ "project_dir": project_dir,
46
+ "goal": goal,
47
+ "categories": sorted(categories),
48
+ "touched_files": files,
49
+ "manifests": manifest_names,
50
+ }
51
+ return result
52
+
53
+
54
+ def _discover_files(project_dir: str) -> list[str]:
55
+ root = Path(project_dir)
56
+ git_dir = root / ".git"
57
+ if git_dir.exists():
58
+ proc = subprocess.run(
59
+ ["git", "diff", "--name-only", "HEAD"],
60
+ cwd=str(root),
61
+ capture_output=True,
62
+ text=True,
63
+ check=False,
64
+ timeout=10,
65
+ )
66
+ if proc.returncode == 0:
67
+ files = [line.strip() for line in proc.stdout.splitlines() if line.strip()]
68
+ if files:
69
+ return files
70
+
71
+ discovered: list[str] = []
72
+ for path in sorted(root.rglob("*")):
73
+ if not path.is_file():
74
+ continue
75
+ rel = path.relative_to(root).as_posix()
76
+ if rel.startswith(".omg/"):
77
+ continue
78
+ discovered.append(rel)
79
+ if len(discovered) >= 32:
80
+ break
81
+ return discovered
@@ -9,21 +9,33 @@ DOMAIN_PACKS: dict[str, dict[str, Any]] = {
9
9
  "name": "robotics",
10
10
  "required_approvals": ["actuation-approval"],
11
11
  "required_evidence": ["simulator-replay", "kill-switch-check"],
12
+ "policy_modules": ["safe-actuation", "simulator-gate"],
13
+ "eval_hooks": ["robotics-sim"],
14
+ "replay_hooks": ["incident-replay"],
12
15
  },
13
16
  "vision": {
14
17
  "name": "vision",
15
18
  "required_approvals": [],
16
19
  "required_evidence": ["dataset-provenance", "drift-check"],
20
+ "policy_modules": ["dataset-lineage", "drift-gate"],
21
+ "eval_hooks": ["vision-regression"],
22
+ "replay_hooks": ["incident-replay"],
17
23
  },
18
24
  "algorithms": {
19
25
  "name": "algorithms",
20
26
  "required_approvals": [],
21
27
  "required_evidence": ["benchmark-harness", "determinism-check"],
28
+ "policy_modules": ["benchmark-gate", "determinism-gate"],
29
+ "eval_hooks": ["algorithm-benchmarks"],
30
+ "replay_hooks": ["incident-replay"],
22
31
  },
23
32
  "health": {
24
33
  "name": "health",
25
34
  "required_approvals": ["human-review"],
26
35
  "required_evidence": ["audit-trail", "restricted-tools", "provenance"],
36
+ "policy_modules": ["human-review", "privacy-gate"],
37
+ "eval_hooks": ["health-safety"],
38
+ "replay_hooks": ["incident-replay"],
27
39
  },
28
40
  }
29
41
 
@@ -8,7 +8,7 @@ import subprocess
8
8
  from typing import Any
9
9
 
10
10
  ECOSYSTEM_SCHEMA = "OmgEcosystemCatalog"
11
- ECOSYSTEM_CATALOG_VERSION = "1.0.0"
11
+ ECOSYSTEM_CATALOG_VERSION = "2.0.5"
12
12
  ECOSYSTEM_LOCK_SCHEMA = "OmgEcosystemLock"
13
13
  DEFAULT_ECOSYSTEM_REPO_DIR = ".omg/ecosystem/repos"
14
14
  DEFAULT_ECOSYSTEM_LOCK_PATH = ".omg/state/ecosystem-lock.json"
@@ -0,0 +1,50 @@
1
+ """Reproducible evaluation results for release gating."""
2
+ from __future__ import annotations
3
+
4
+ from datetime import datetime, timezone
5
+ import json
6
+ from pathlib import Path
7
+ from typing import Any
8
+
9
+
10
+ EVAL_GATE_LATEST_REL_PATH = Path(".omg") / "evals" / "latest.json"
11
+ EVAL_GATE_HISTORY_REL_PATH = Path(".omg") / "evals" / "history.jsonl"
12
+
13
+
14
+ def _now() -> str:
15
+ return datetime.now(timezone.utc).isoformat()
16
+
17
+
18
+ def evaluate_trace(
19
+ project_dir: str,
20
+ *,
21
+ trace_id: str,
22
+ suites: list[str],
23
+ metrics: dict[str, float],
24
+ regression_threshold: float = 0.95,
25
+ ) -> dict[str, Any]:
26
+ scorecard = {name: float(metrics.get(name, 0.0)) for name in suites}
27
+ regressed = any(score < regression_threshold for score in scorecard.values())
28
+ result = {
29
+ "schema": "EvalGateResult",
30
+ "trace_id": trace_id,
31
+ "evaluated_at": _now(),
32
+ "status": "fail" if regressed else "ok",
33
+ "suites": suites,
34
+ "metrics": scorecard,
35
+ "summary": {
36
+ "regressed": regressed,
37
+ "regression_threshold": regression_threshold,
38
+ },
39
+ }
40
+
41
+ latest_path = Path(project_dir) / EVAL_GATE_LATEST_REL_PATH
42
+ latest_path.parent.mkdir(parents=True, exist_ok=True)
43
+ latest_path.write_text(json.dumps(result, indent=2, ensure_ascii=True) + "\n", encoding="utf-8")
44
+
45
+ history_path = Path(project_dir) / EVAL_GATE_HISTORY_REL_PATH
46
+ with history_path.open("a", encoding="utf-8") as handle:
47
+ handle.write(json.dumps(result, ensure_ascii=True) + "\n")
48
+
49
+ result["path"] = EVAL_GATE_LATEST_REL_PATH.as_posix()
50
+ return result
@@ -0,0 +1,47 @@
1
+ """Replayable incident pack generation."""
2
+ from __future__ import annotations
3
+
4
+ from datetime import datetime, timezone
5
+ import json
6
+ from pathlib import Path
7
+ from typing import Any
8
+ from uuid import uuid4
9
+
10
+
11
+ def _now() -> str:
12
+ return datetime.now(timezone.utc).isoformat()
13
+
14
+
15
+ def build_incident_pack(
16
+ project_dir: str,
17
+ *,
18
+ title: str,
19
+ failing_tests: list[str],
20
+ logs: list[str],
21
+ diff_summary: dict[str, Any],
22
+ trace_id: str | None = None,
23
+ ) -> dict[str, Any]:
24
+ incident_id = f"incident-{uuid4().hex}"
25
+ payload = {
26
+ "schema": "IncidentReplayPack",
27
+ "incident_id": incident_id,
28
+ "title": title,
29
+ "generated_at": _now(),
30
+ "trace_id": trace_id or "",
31
+ "failing_tests": failing_tests,
32
+ "logs": logs,
33
+ "diff_summary": diff_summary,
34
+ "reproduction_steps": [
35
+ "Replay the failing tests.",
36
+ "Inspect the attached logs.",
37
+ "Validate the diff summary before patching.",
38
+ ],
39
+ "regression_guards": failing_tests,
40
+ }
41
+
42
+ rel_path = Path(".omg") / "incidents" / f"{incident_id}.json"
43
+ path = Path(project_dir) / rel_path
44
+ path.parent.mkdir(parents=True, exist_ok=True)
45
+ path.write_text(json.dumps(payload, indent=2, ensure_ascii=True) + "\n", encoding="utf-8")
46
+ payload["path"] = rel_path.as_posix()
47
+ return payload
@@ -66,7 +66,7 @@ mcp = FastMCP("OMG Memory Server", lifespan=lifespan)
66
66
 
67
67
  @mcp.custom_route("/health", methods=["GET"])
68
68
  async def health(_: Request) -> JSONResponse:
69
- return JSONResponse({"status": "ok", "version": "1.0.0"})
69
+ return JSONResponse({"status": "ok", "version": "2.0.5"})
70
70
 
71
71
 
72
72
  @mcp.tool()
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schema": "OmgCompatContractSnapshot",
3
- "contract_version": "1.0.0",
3
+ "contract_version": "2.0.5",
4
4
  "count": 47,
5
5
  "contracts": [
6
6
  {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schema": "OmgCompatContractSnapshot",
3
- "contract_version": "1.0.0",
3
+ "contract_version": "2.0.5",
4
4
  "count": 47,
5
5
  "contracts": [
6
6
  {
@@ -7,6 +7,8 @@ from dataclasses import dataclass
7
7
  from pathlib import Path
8
8
  from typing import Any
9
9
 
10
+ from runtime.asset_loader import resolve_asset
11
+
10
12
  _MCP_IMPORT_ERROR: ModuleNotFoundError | None = None
11
13
 
12
14
  try:
@@ -112,7 +114,7 @@ def _service() -> ControlPlaneService:
112
114
 
113
115
 
114
116
  def _read_repo_text(rel_path: str) -> str:
115
- return (_root_dir() / rel_path).read_text(encoding="utf-8")
117
+ return resolve_asset(rel_path).read_text(encoding="utf-8")
116
118
 
117
119
 
118
120
  @mcp.tool()
@@ -1,6 +1,8 @@
1
1
  """Structured preflight routing for OMG."""
2
2
  from __future__ import annotations
3
3
 
4
+ from runtime.delta_classifier import classify_project_changes
5
+ from runtime.tracebank import record_trace
4
6
  from typing import Any
5
7
 
6
8
 
@@ -9,8 +11,15 @@ def run_preflight(project_dir: str, *, goal: str) -> dict[str, Any]:
9
11
  task_class = "implementation"
10
12
  risk_class = "medium"
11
13
  route = "teams"
14
+ delta = classify_project_changes(project_dir, goal=goal)
15
+ categories = set(delta["categories"])
16
+ domain_packs = [category for category in delta["categories"] if category in {"robotics", "vision", "algorithms", "health"}]
12
17
 
13
- if any(token in lowered for token in ("openapi", "swagger", "postman", "contract", "fixture", "replay")):
18
+ if categories & {"auth", "payment", "health", "compliance"}:
19
+ task_class = "security"
20
+ risk_class = "high"
21
+ route = "security-check"
22
+ elif categories & {"api"} or any(token in lowered for token in ("openapi", "swagger", "postman", "contract", "fixture", "replay")):
14
23
  task_class = "contract"
15
24
  route = "api-twin"
16
25
  elif any(token in lowered for token in ("auth", "secret", "security", "token", "injection")):
@@ -22,6 +31,15 @@ def run_preflight(project_dir: str, *, goal: str) -> dict[str, Any]:
22
31
  risk_class = "high"
23
32
  route = "crazy"
24
33
 
34
+ trace = record_trace(
35
+ project_dir,
36
+ trace_type="preflight",
37
+ route=route,
38
+ status="ok",
39
+ plan={"goal": goal, "delta_categories": delta["categories"]},
40
+ verify={"risk_class": risk_class},
41
+ )
42
+
25
43
  return {
26
44
  "schema": "PreflightResult",
27
45
  "project_dir": project_dir,
@@ -33,6 +51,9 @@ def run_preflight(project_dir: str, *, goal: str) -> dict[str, Any]:
33
51
  "required_mcps": ["omg-control"] if route in {"security-check", "api-twin", "crazy"} else [],
34
52
  "missing_constraints": [],
35
53
  "evidence_plan": _evidence_plan(route),
54
+ "delta_classification": delta,
55
+ "domain_packs": domain_packs,
56
+ "trace": {"trace_id": trace["trace_id"], "path": trace["path"]},
36
57
  }
37
58
 
38
59