@trac3er/oh-my-god 2.1.0 → 2.1.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.
Files changed (371) hide show
  1. package/.agents/skills/omg/AGENTS.fragment.md +2 -2
  2. package/.agents/skills/omg/algorithms/SKILL.md +1 -1
  3. package/.agents/skills/omg/algorithms/openai.yaml +1 -1
  4. package/.agents/skills/omg/api-twin/SKILL.md +1 -1
  5. package/.agents/skills/omg/api-twin/openai.yaml +1 -1
  6. package/.agents/skills/omg/claim-judge/SKILL.md +1 -1
  7. package/.agents/skills/omg/claim-judge/openai.yaml +1 -1
  8. package/.agents/skills/omg/codex-rules.md +1 -1
  9. package/.agents/skills/omg/control-plane/SKILL.md +1 -1
  10. package/.agents/skills/omg/control-plane/openai.yaml +1 -1
  11. package/.agents/skills/omg/data-lineage/SKILL.md +1 -1
  12. package/.agents/skills/omg/data-lineage/openai.yaml +1 -1
  13. package/.agents/skills/omg/delta-classifier/SKILL.md +1 -1
  14. package/.agents/skills/omg/delta-classifier/openai.yaml +1 -1
  15. package/.agents/skills/omg/eval-gate/SKILL.md +1 -1
  16. package/.agents/skills/omg/eval-gate/openai.yaml +1 -1
  17. package/.agents/skills/omg/health/SKILL.md +1 -1
  18. package/.agents/skills/omg/health/openai.yaml +1 -1
  19. package/.agents/skills/omg/hook-governor/SKILL.md +1 -1
  20. package/.agents/skills/omg/hook-governor/openai.yaml +1 -1
  21. package/.agents/skills/omg/incident-replay/SKILL.md +1 -1
  22. package/.agents/skills/omg/incident-replay/openai.yaml +1 -1
  23. package/.agents/skills/omg/lsp-pack/SKILL.md +1 -1
  24. package/.agents/skills/omg/lsp-pack/openai.yaml +1 -1
  25. package/.agents/skills/omg/mcp-fabric/SKILL.md +1 -1
  26. package/.agents/skills/omg/mcp-fabric/openai.yaml +1 -1
  27. package/.agents/skills/omg/plan-council/SKILL.md +1 -1
  28. package/.agents/skills/omg/plan-council/openai.yaml +1 -1
  29. package/.agents/skills/omg/preflight/SKILL.md +1 -1
  30. package/.agents/skills/omg/preflight/openai.yaml +1 -1
  31. package/.agents/skills/omg/proof-gate/SKILL.md +1 -1
  32. package/.agents/skills/omg/proof-gate/openai.yaml +1 -1
  33. package/.agents/skills/omg/remote-supervisor/SKILL.md +1 -1
  34. package/.agents/skills/omg/remote-supervisor/openai.yaml +1 -1
  35. package/.agents/skills/omg/robotics/SKILL.md +1 -1
  36. package/.agents/skills/omg/robotics/openai.yaml +1 -1
  37. package/.agents/skills/omg/secure-worktree-pipeline/SKILL.md +1 -1
  38. package/.agents/skills/omg/secure-worktree-pipeline/openai.yaml +1 -1
  39. package/.agents/skills/omg/security-check/SKILL.md +1 -1
  40. package/.agents/skills/omg/security-check/openai.yaml +1 -1
  41. package/.agents/skills/omg/test-intent-lock/SKILL.md +1 -1
  42. package/.agents/skills/omg/test-intent-lock/openai.yaml +1 -1
  43. package/.agents/skills/omg/tracebank/SKILL.md +1 -1
  44. package/.agents/skills/omg/tracebank/openai.yaml +1 -1
  45. package/.agents/skills/omg/vision/SKILL.md +1 -1
  46. package/.agents/skills/omg/vision/openai.yaml +1 -1
  47. package/.claude-plugin/marketplace.json +3 -3
  48. package/.claude-plugin/plugin.json +1 -1
  49. package/CHANGELOG.md +16 -0
  50. package/CLI-ADAPTER-MAP.md +3 -3
  51. package/OMG-setup.sh +114 -1
  52. package/OMG_COMPAT_CONTRACT.md +1 -1
  53. package/README.md +2 -1
  54. package/artifacts/release/.claude-plugin/marketplace.json +3 -3
  55. package/artifacts/release/.claude-plugin/plugin.json +1 -1
  56. package/artifacts/release/OMG_COMPAT_CONTRACT.md +1 -1
  57. package/artifacts/release/dist/enterprise/bundle/.claude-plugin/marketplace.json +3 -3
  58. package/artifacts/release/dist/enterprise/bundle/.claude-plugin/plugin.json +1 -1
  59. package/artifacts/release/dist/enterprise/bundle/OMG_COMPAT_CONTRACT.md +1 -1
  60. package/artifacts/release/dist/enterprise/bundle/plugins/advanced/plugin.json +26 -9
  61. package/artifacts/release/dist/enterprise/bundle/registry/bundles/algorithms.yaml +1 -1
  62. package/artifacts/release/dist/enterprise/bundle/registry/bundles/api-twin.yaml +1 -1
  63. package/artifacts/release/dist/enterprise/bundle/registry/bundles/claim-judge.yaml +1 -1
  64. package/artifacts/release/dist/enterprise/bundle/registry/bundles/control-plane.yaml +1 -1
  65. package/artifacts/release/dist/enterprise/bundle/registry/bundles/data-lineage.yaml +1 -1
  66. package/artifacts/release/dist/enterprise/bundle/registry/bundles/delta-classifier.yaml +1 -1
  67. package/artifacts/release/dist/enterprise/bundle/registry/bundles/eval-gate.yaml +1 -1
  68. package/artifacts/release/dist/enterprise/bundle/registry/bundles/health.yaml +1 -1
  69. package/artifacts/release/dist/enterprise/bundle/registry/bundles/hook-governor.yaml +1 -1
  70. package/artifacts/release/dist/enterprise/bundle/registry/bundles/incident-replay.yaml +1 -1
  71. package/artifacts/release/dist/enterprise/bundle/registry/bundles/lsp-pack.yaml +1 -1
  72. package/artifacts/release/dist/enterprise/bundle/registry/bundles/mcp-fabric.yaml +1 -1
  73. package/artifacts/release/dist/enterprise/bundle/registry/bundles/plan-council.yaml +1 -1
  74. package/artifacts/release/dist/enterprise/bundle/registry/bundles/preflight.yaml +1 -1
  75. package/artifacts/release/dist/enterprise/bundle/registry/bundles/proof-gate.yaml +1 -1
  76. package/artifacts/release/dist/enterprise/bundle/registry/bundles/remote-supervisor.yaml +1 -1
  77. package/artifacts/release/dist/enterprise/bundle/registry/bundles/robotics.yaml +1 -1
  78. package/artifacts/release/dist/enterprise/bundle/registry/bundles/secure-worktree-pipeline.yaml +1 -1
  79. package/artifacts/release/dist/enterprise/bundle/registry/bundles/security-check.yaml +1 -1
  80. package/artifacts/release/dist/enterprise/bundle/registry/bundles/test-intent-lock.yaml +1 -1
  81. package/artifacts/release/dist/enterprise/bundle/registry/bundles/tracebank.yaml +1 -1
  82. package/artifacts/release/dist/enterprise/bundle/registry/bundles/vision.yaml +1 -1
  83. package/artifacts/release/dist/enterprise/bundle/registry/omg-capability.schema.json +1 -1
  84. package/artifacts/release/dist/enterprise/bundle/settings.json +3 -3
  85. package/artifacts/release/dist/enterprise/manifest.json +30 -40
  86. package/artifacts/release/dist/public/bundle/.claude-plugin/marketplace.json +3 -3
  87. package/artifacts/release/dist/public/bundle/.claude-plugin/plugin.json +1 -1
  88. package/artifacts/release/dist/public/bundle/OMG_COMPAT_CONTRACT.md +1 -1
  89. package/artifacts/release/dist/public/bundle/plugins/advanced/plugin.json +26 -9
  90. package/artifacts/release/dist/public/bundle/registry/bundles/algorithms.yaml +1 -1
  91. package/artifacts/release/dist/public/bundle/registry/bundles/api-twin.yaml +1 -1
  92. package/artifacts/release/dist/public/bundle/registry/bundles/claim-judge.yaml +1 -1
  93. package/artifacts/release/dist/public/bundle/registry/bundles/control-plane.yaml +1 -1
  94. package/artifacts/release/dist/public/bundle/registry/bundles/data-lineage.yaml +1 -1
  95. package/artifacts/release/dist/public/bundle/registry/bundles/delta-classifier.yaml +1 -1
  96. package/artifacts/release/dist/public/bundle/registry/bundles/eval-gate.yaml +1 -1
  97. package/artifacts/release/dist/public/bundle/registry/bundles/health.yaml +1 -1
  98. package/artifacts/release/dist/public/bundle/registry/bundles/hook-governor.yaml +1 -1
  99. package/artifacts/release/dist/public/bundle/registry/bundles/incident-replay.yaml +1 -1
  100. package/artifacts/release/dist/public/bundle/registry/bundles/lsp-pack.yaml +1 -1
  101. package/artifacts/release/dist/public/bundle/registry/bundles/mcp-fabric.yaml +1 -1
  102. package/artifacts/release/dist/public/bundle/registry/bundles/plan-council.yaml +1 -1
  103. package/artifacts/release/dist/public/bundle/registry/bundles/preflight.yaml +1 -1
  104. package/artifacts/release/dist/public/bundle/registry/bundles/proof-gate.yaml +1 -1
  105. package/artifacts/release/dist/public/bundle/registry/bundles/remote-supervisor.yaml +1 -1
  106. package/artifacts/release/dist/public/bundle/registry/bundles/robotics.yaml +1 -1
  107. package/artifacts/release/dist/public/bundle/registry/bundles/secure-worktree-pipeline.yaml +1 -1
  108. package/artifacts/release/dist/public/bundle/registry/bundles/security-check.yaml +1 -1
  109. package/artifacts/release/dist/public/bundle/registry/bundles/test-intent-lock.yaml +1 -1
  110. package/artifacts/release/dist/public/bundle/registry/bundles/tracebank.yaml +1 -1
  111. package/artifacts/release/dist/public/bundle/registry/bundles/vision.yaml +1 -1
  112. package/artifacts/release/dist/public/bundle/registry/omg-capability.schema.json +1 -1
  113. package/artifacts/release/dist/public/bundle/settings.json +3 -3
  114. package/artifacts/release/dist/public/manifest.json +30 -40
  115. package/artifacts/release/plugins/advanced/plugin.json +26 -9
  116. package/artifacts/release/registry/bundles/algorithms.yaml +1 -1
  117. package/artifacts/release/registry/bundles/api-twin.yaml +1 -1
  118. package/artifacts/release/registry/bundles/claim-judge.yaml +1 -1
  119. package/artifacts/release/registry/bundles/control-plane.yaml +1 -1
  120. package/artifacts/release/registry/bundles/data-lineage.yaml +1 -1
  121. package/artifacts/release/registry/bundles/delta-classifier.yaml +1 -1
  122. package/artifacts/release/registry/bundles/eval-gate.yaml +1 -1
  123. package/artifacts/release/registry/bundles/health.yaml +1 -1
  124. package/artifacts/release/registry/bundles/hook-governor.yaml +1 -1
  125. package/artifacts/release/registry/bundles/incident-replay.yaml +1 -1
  126. package/artifacts/release/registry/bundles/lsp-pack.yaml +1 -1
  127. package/artifacts/release/registry/bundles/mcp-fabric.yaml +1 -1
  128. package/artifacts/release/registry/bundles/plan-council.yaml +1 -1
  129. package/artifacts/release/registry/bundles/preflight.yaml +1 -1
  130. package/artifacts/release/registry/bundles/proof-gate.yaml +1 -1
  131. package/artifacts/release/registry/bundles/remote-supervisor.yaml +1 -1
  132. package/artifacts/release/registry/bundles/robotics.yaml +1 -1
  133. package/artifacts/release/registry/bundles/secure-worktree-pipeline.yaml +1 -1
  134. package/artifacts/release/registry/bundles/security-check.yaml +1 -1
  135. package/artifacts/release/registry/bundles/test-intent-lock.yaml +1 -1
  136. package/artifacts/release/registry/bundles/tracebank.yaml +1 -1
  137. package/artifacts/release/registry/bundles/vision.yaml +1 -1
  138. package/artifacts/release/registry/omg-capability.schema.json +1 -1
  139. package/artifacts/release/settings.json +3 -3
  140. package/build/lib/commands/OMG:profile-review.md +43 -0
  141. package/build/lib/commands/OMG:validate.md +59 -0
  142. package/build/lib/control_plane/service.py +40 -1
  143. package/build/lib/hooks/_agent_registry.py +2 -0
  144. package/build/lib/hooks/firewall.py +263 -4
  145. package/build/lib/hooks/intentgate-keyword-detector.py +15 -3
  146. package/build/lib/hooks/policy_engine.py +77 -0
  147. package/build/lib/hooks/prompt-enhancer.py +146 -0
  148. package/build/lib/hooks/session-end-capture.py +374 -6
  149. package/build/lib/hooks/session-start.py +13 -35
  150. package/build/lib/hooks/setup_wizard.py +333 -1
  151. package/build/lib/hooks/shadow_manager.py +111 -2
  152. package/build/lib/hooks/stop_dispatcher.py +108 -4
  153. package/build/lib/plugins/advanced/plugin.json +26 -9
  154. package/build/lib/plugins/core/plugin.json +44 -11
  155. package/build/lib/registry/bundles/algorithms.yaml +1 -1
  156. package/build/lib/registry/bundles/api-twin.yaml +1 -1
  157. package/build/lib/registry/bundles/claim-judge.yaml +1 -1
  158. package/build/lib/registry/bundles/control-plane.yaml +1 -1
  159. package/build/lib/registry/bundles/data-lineage.yaml +1 -1
  160. package/build/lib/registry/bundles/delta-classifier.yaml +1 -1
  161. package/build/lib/registry/bundles/eval-gate.yaml +1 -1
  162. package/build/lib/registry/bundles/health.yaml +1 -1
  163. package/build/lib/registry/bundles/hook-governor.yaml +1 -1
  164. package/build/lib/registry/bundles/incident-replay.yaml +1 -1
  165. package/build/lib/registry/bundles/lsp-pack.yaml +1 -1
  166. package/build/lib/registry/bundles/mcp-fabric.yaml +1 -1
  167. package/build/lib/registry/bundles/plan-council.yaml +1 -1
  168. package/build/lib/registry/bundles/preflight.yaml +1 -1
  169. package/build/lib/registry/bundles/proof-gate.yaml +1 -1
  170. package/build/lib/registry/bundles/remote-supervisor.yaml +1 -1
  171. package/build/lib/registry/bundles/robotics.yaml +1 -1
  172. package/build/lib/registry/bundles/secure-worktree-pipeline.yaml +1 -1
  173. package/build/lib/registry/bundles/security-check.yaml +1 -1
  174. package/build/lib/registry/bundles/test-intent-lock.yaml +1 -1
  175. package/build/lib/registry/bundles/tracebank.yaml +1 -1
  176. package/build/lib/registry/bundles/vision.yaml +1 -1
  177. package/build/lib/registry/omg-capability.schema.json +1 -1
  178. package/build/lib/runtime/adoption.py +1 -1
  179. package/build/lib/runtime/background_verification.py +62 -0
  180. package/build/lib/runtime/claim_judge.py +165 -5
  181. package/build/lib/runtime/compat.py +15 -1
  182. package/build/lib/runtime/context_engine.py +261 -4
  183. package/build/lib/runtime/contract_compiler.py +370 -93
  184. package/build/lib/runtime/defense_state.py +79 -8
  185. package/build/lib/runtime/delta_classifier.py +80 -2
  186. package/build/lib/runtime/evidence_query.py +56 -4
  187. package/build/lib/runtime/evidence_registry.py +16 -0
  188. package/build/lib/runtime/evidence_requirements.py +47 -0
  189. package/build/lib/runtime/forge_agents.py +179 -9
  190. package/build/lib/runtime/forge_contracts.py +208 -2
  191. package/build/lib/runtime/interaction_journal.py +318 -42
  192. package/build/lib/runtime/memory_store.py +134 -1
  193. package/build/lib/runtime/mutation_gate.py +57 -11
  194. package/build/lib/runtime/omg_compat_contract_snapshot.json +2 -2
  195. package/build/lib/runtime/omg_mcp_server.py +14 -4
  196. package/build/lib/runtime/preflight.py +14 -0
  197. package/build/lib/runtime/profile_io.py +294 -0
  198. package/build/lib/runtime/proof_gate.py +122 -7
  199. package/build/lib/runtime/release_run_coordinator.py +339 -0
  200. package/build/lib/runtime/release_surfaces.py +243 -0
  201. package/build/lib/runtime/rollback_manifest.py +136 -0
  202. package/build/lib/runtime/router_critics.py +50 -0
  203. package/build/lib/runtime/runtime_contracts.py +137 -0
  204. package/build/lib/runtime/security_check.py +16 -0
  205. package/build/lib/runtime/session_health.py +60 -16
  206. package/build/lib/runtime/team_router.py +156 -13
  207. package/build/lib/runtime/test_intent_lock.py +102 -0
  208. package/build/lib/runtime/tool_plan_gate.py +249 -24
  209. package/build/lib/runtime/validate.py +194 -0
  210. package/build/lib/runtime/verification_controller.py +52 -2
  211. package/commands/OMG:diagnose-plugins.md +33 -0
  212. package/commands/OMG:profile-review.md +43 -0
  213. package/commands/OMG:setup.md +4 -1
  214. package/commands/OMG:validate.md +59 -0
  215. package/control_plane/service.py +40 -1
  216. package/dist/enterprise/bundle/.claude-plugin/marketplace.json +3 -3
  217. package/dist/enterprise/bundle/.claude-plugin/plugin.json +1 -1
  218. package/dist/enterprise/bundle/OMG_COMPAT_CONTRACT.md +1 -1
  219. package/dist/enterprise/bundle/plugins/advanced/plugin.json +26 -9
  220. package/dist/enterprise/bundle/registry/bundles/algorithms.yaml +1 -1
  221. package/dist/enterprise/bundle/registry/bundles/api-twin.yaml +1 -1
  222. package/dist/enterprise/bundle/registry/bundles/claim-judge.yaml +1 -1
  223. package/dist/enterprise/bundle/registry/bundles/control-plane.yaml +1 -1
  224. package/dist/enterprise/bundle/registry/bundles/data-lineage.yaml +1 -1
  225. package/dist/enterprise/bundle/registry/bundles/delta-classifier.yaml +1 -1
  226. package/dist/enterprise/bundle/registry/bundles/eval-gate.yaml +1 -1
  227. package/dist/enterprise/bundle/registry/bundles/health.yaml +1 -1
  228. package/dist/enterprise/bundle/registry/bundles/hook-governor.yaml +1 -1
  229. package/dist/enterprise/bundle/registry/bundles/incident-replay.yaml +1 -1
  230. package/dist/enterprise/bundle/registry/bundles/lsp-pack.yaml +1 -1
  231. package/dist/enterprise/bundle/registry/bundles/mcp-fabric.yaml +1 -1
  232. package/dist/enterprise/bundle/registry/bundles/plan-council.yaml +1 -1
  233. package/dist/enterprise/bundle/registry/bundles/preflight.yaml +1 -1
  234. package/dist/enterprise/bundle/registry/bundles/proof-gate.yaml +1 -1
  235. package/dist/enterprise/bundle/registry/bundles/remote-supervisor.yaml +1 -1
  236. package/dist/enterprise/bundle/registry/bundles/robotics.yaml +1 -1
  237. package/dist/enterprise/bundle/registry/bundles/secure-worktree-pipeline.yaml +1 -1
  238. package/dist/enterprise/bundle/registry/bundles/security-check.yaml +1 -1
  239. package/dist/enterprise/bundle/registry/bundles/test-intent-lock.yaml +1 -1
  240. package/dist/enterprise/bundle/registry/bundles/tracebank.yaml +1 -1
  241. package/dist/enterprise/bundle/registry/bundles/vision.yaml +1 -1
  242. package/dist/enterprise/bundle/registry/omg-capability.schema.json +1 -1
  243. package/dist/enterprise/bundle/settings.json +3 -3
  244. package/dist/enterprise/manifest.json +30 -40
  245. package/dist/oh_my_god-2.1.4-py3-none-any.whl +0 -0
  246. package/dist/oh_my_god-2.1.4.tar.gz +0 -0
  247. package/dist/public/bundle/.claude-plugin/marketplace.json +3 -3
  248. package/dist/public/bundle/.claude-plugin/plugin.json +1 -1
  249. package/dist/public/bundle/OMG_COMPAT_CONTRACT.md +1 -1
  250. package/dist/public/bundle/plugins/advanced/plugin.json +26 -9
  251. package/dist/public/bundle/registry/bundles/algorithms.yaml +1 -1
  252. package/dist/public/bundle/registry/bundles/api-twin.yaml +1 -1
  253. package/dist/public/bundle/registry/bundles/claim-judge.yaml +1 -1
  254. package/dist/public/bundle/registry/bundles/control-plane.yaml +1 -1
  255. package/dist/public/bundle/registry/bundles/data-lineage.yaml +1 -1
  256. package/dist/public/bundle/registry/bundles/delta-classifier.yaml +1 -1
  257. package/dist/public/bundle/registry/bundles/eval-gate.yaml +1 -1
  258. package/dist/public/bundle/registry/bundles/health.yaml +1 -1
  259. package/dist/public/bundle/registry/bundles/hook-governor.yaml +1 -1
  260. package/dist/public/bundle/registry/bundles/incident-replay.yaml +1 -1
  261. package/dist/public/bundle/registry/bundles/lsp-pack.yaml +1 -1
  262. package/dist/public/bundle/registry/bundles/mcp-fabric.yaml +1 -1
  263. package/dist/public/bundle/registry/bundles/plan-council.yaml +1 -1
  264. package/dist/public/bundle/registry/bundles/preflight.yaml +1 -1
  265. package/dist/public/bundle/registry/bundles/proof-gate.yaml +1 -1
  266. package/dist/public/bundle/registry/bundles/remote-supervisor.yaml +1 -1
  267. package/dist/public/bundle/registry/bundles/robotics.yaml +1 -1
  268. package/dist/public/bundle/registry/bundles/secure-worktree-pipeline.yaml +1 -1
  269. package/dist/public/bundle/registry/bundles/security-check.yaml +1 -1
  270. package/dist/public/bundle/registry/bundles/test-intent-lock.yaml +1 -1
  271. package/dist/public/bundle/registry/bundles/tracebank.yaml +1 -1
  272. package/dist/public/bundle/registry/bundles/vision.yaml +1 -1
  273. package/dist/public/bundle/registry/omg-capability.schema.json +1 -1
  274. package/dist/public/bundle/settings.json +3 -3
  275. package/dist/public/manifest.json +30 -40
  276. package/docs/install/opencode.md +30 -0
  277. package/docs/proof.md +11 -0
  278. package/docs/release-checklist.md +14 -1
  279. package/hooks/_agent_registry.py +2 -0
  280. package/hooks/firewall.py +263 -4
  281. package/hooks/intentgate-keyword-detector.py +15 -3
  282. package/hooks/policy_engine.py +77 -0
  283. package/hooks/prompt-enhancer.py +146 -0
  284. package/hooks/session-end-capture.py +374 -6
  285. package/hooks/session-start.py +13 -35
  286. package/hooks/setup_wizard.py +342 -2
  287. package/hooks/shadow_manager.py +111 -2
  288. package/hooks/stop_dispatcher.py +108 -4
  289. package/hud/omg-hud.mjs +30 -6
  290. package/lab/pipeline.py +197 -26
  291. package/package.json +1 -1
  292. package/plugins/advanced/plugin.json +26 -9
  293. package/plugins/core/plugin.json +51 -12
  294. package/pyproject.toml +10 -2
  295. package/registry/bundles/algorithms.yaml +1 -1
  296. package/registry/bundles/api-twin.yaml +1 -1
  297. package/registry/bundles/claim-judge.yaml +1 -1
  298. package/registry/bundles/control-plane.yaml +1 -1
  299. package/registry/bundles/data-lineage.yaml +1 -1
  300. package/registry/bundles/delta-classifier.yaml +1 -1
  301. package/registry/bundles/eval-gate.yaml +1 -1
  302. package/registry/bundles/health.yaml +1 -1
  303. package/registry/bundles/hook-governor.yaml +1 -1
  304. package/registry/bundles/incident-replay.yaml +1 -1
  305. package/registry/bundles/lsp-pack.yaml +1 -1
  306. package/registry/bundles/mcp-fabric.yaml +1 -1
  307. package/registry/bundles/plan-council.yaml +1 -1
  308. package/registry/bundles/preflight.yaml +1 -1
  309. package/registry/bundles/proof-gate.yaml +1 -1
  310. package/registry/bundles/remote-supervisor.yaml +1 -1
  311. package/registry/bundles/robotics.yaml +1 -1
  312. package/registry/bundles/secure-worktree-pipeline.yaml +1 -1
  313. package/registry/bundles/security-check.yaml +1 -1
  314. package/registry/bundles/test-intent-lock.yaml +1 -1
  315. package/registry/bundles/tracebank.yaml +1 -1
  316. package/registry/bundles/vision.yaml +1 -1
  317. package/registry/omg-capability.schema.json +1 -1
  318. package/runtime/adoption.py +7 -5
  319. package/runtime/background_verification.py +62 -0
  320. package/runtime/claim_judge.py +165 -5
  321. package/runtime/compat.py +48 -1
  322. package/runtime/context_engine.py +261 -4
  323. package/runtime/contract_compiler.py +370 -93
  324. package/runtime/defense_state.py +79 -8
  325. package/runtime/delta_classifier.py +80 -2
  326. package/runtime/evidence_query.py +56 -4
  327. package/runtime/evidence_registry.py +16 -0
  328. package/runtime/evidence_requirements.py +47 -0
  329. package/runtime/forge_agents.py +179 -9
  330. package/runtime/forge_contracts.py +208 -2
  331. package/runtime/hook_governor.py +19 -1
  332. package/runtime/interaction_journal.py +318 -42
  333. package/runtime/memory_store.py +134 -1
  334. package/runtime/mutation_gate.py +57 -11
  335. package/runtime/omg_compat_contract_snapshot.json +2 -2
  336. package/runtime/omg_mcp_server.py +14 -4
  337. package/runtime/plugin_diagnostics.py +248 -0
  338. package/runtime/plugin_interop.py +1007 -0
  339. package/runtime/preflight.py +14 -0
  340. package/runtime/profile_io.py +294 -0
  341. package/runtime/proof_gate.py +122 -7
  342. package/runtime/providers/opencode_provider.py +94 -0
  343. package/runtime/release_run_coordinator.py +339 -0
  344. package/runtime/release_surfaces.py +243 -0
  345. package/runtime/rollback_manifest.py +136 -0
  346. package/runtime/router_critics.py +50 -0
  347. package/runtime/runtime_contracts.py +137 -0
  348. package/runtime/security_check.py +16 -0
  349. package/runtime/session_health.py +60 -16
  350. package/runtime/team_router.py +156 -13
  351. package/runtime/test_intent_lock.py +102 -0
  352. package/runtime/tool_plan_gate.py +218 -19
  353. package/runtime/validate.py +289 -0
  354. package/runtime/verification_controller.py +52 -2
  355. package/scripts/omg.py +306 -3
  356. package/scripts/prepare-release-proof-fixtures.py +191 -7
  357. package/scripts/print-canonical-version.py +80 -0
  358. package/scripts/sync-release-identity.py +476 -0
  359. package/scripts/validate-release-identity.py +246 -0
  360. package/scripts/verify-standalone.sh +3 -0
  361. package/settings.json +3 -3
  362. package/templates/plugins-allowlist.yaml +19 -0
  363. package/artifacts/release/dist/enterprise/bundle/.gemini/settings.json +0 -11
  364. package/artifacts/release/dist/enterprise/bundle/.kimi/mcp.json +0 -11
  365. package/artifacts/release/dist/public/bundle/.gemini/settings.json +0 -11
  366. package/artifacts/release/dist/public/bundle/.kimi/mcp.json +0 -11
  367. package/build/lib/yaml.py +0 -321
  368. package/dist/enterprise/bundle/.gemini/settings.json +0 -11
  369. package/dist/enterprise/bundle/.kimi/mcp.json +0 -11
  370. package/dist/public/bundle/.gemini/settings.json +0 -11
  371. package/dist/public/bundle/.kimi/mcp.json +0 -11
@@ -1,17 +1,21 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import json
4
+ import os
4
5
  from pathlib import Path
5
6
  from typing import Any
6
7
 
7
8
  from runtime import artifact_parsers
9
+ from runtime.context_engine import load_profile_digest
8
10
  from runtime.evidence_query import get_evidence_pack
11
+ from runtime.evidence_requirements import FULL_REQUIREMENTS, requirements_for_profile
9
12
 
10
13
 
11
14
  def judge_claims(project_dir: str, claims: list[dict[str, Any]]) -> dict[str, Any]:
12
15
  root = Path(project_dir)
13
16
  evidence_dir = root / ".omg" / "evidence"
14
17
  evidence_dir.mkdir(parents=True, exist_ok=True)
18
+ profile_digest = load_profile_digest(project_dir)
15
19
 
16
20
  results: list[dict[str, Any]] = []
17
21
  aggregate_tokens: list[str] = []
@@ -23,16 +27,37 @@ def judge_claims(project_dir: str, claims: list[dict[str, Any]]) -> dict[str, An
23
27
  if run_id:
24
28
  evidence_pack = get_evidence_pack(project_dir, run_id)
25
29
  trace_ids: list[str] = []
30
+ context_checksum = ""
31
+ profile_version = ""
32
+ intent_gate_version = ""
33
+ evidence_profile = ""
26
34
  if isinstance(evidence_pack, dict):
27
35
  trace_ids = _as_non_empty_str_list(evidence_pack.get("trace_ids"))
36
+ context_checksum = str(evidence_pack.get("context_checksum", "")).strip()
37
+ profile_version = str(evidence_pack.get("profile_version", "")).strip()
38
+ intent_gate_version = str(evidence_pack.get("intent_gate_version", "")).strip()
39
+ evidence_profile = str(evidence_pack.get("evidence_profile", "")).strip()
28
40
  resolved_claim = {
29
41
  **claim,
30
42
  "artifacts": [f".omg/evidence/{run_id}.json"],
31
43
  "trace_ids": trace_ids,
44
+ "context_checksum": context_checksum,
45
+ "profile_version": profile_version,
46
+ "intent_gate_version": intent_gate_version,
47
+ "evidence_profile": evidence_profile,
32
48
  }
33
49
 
34
50
  result = judge_claim(resolved_claim)
51
+ council_reasons = _load_council_reasons(project_dir=project_dir, run_id=run_id)
52
+ if council_reasons:
53
+ updated_reasons = list(result.get("reasons", []))
54
+ updated_reasons.extend(council_reasons)
55
+ result = {**result, "reasons": updated_reasons, "verdict": "block"}
35
56
  result_with_run = {**result, "run_id": run_id}
57
+ result_with_run["context_checksum"] = str(resolved_claim.get("context_checksum", "")).strip()
58
+ result_with_run["profile_version"] = str(resolved_claim.get("profile_version", "")).strip()
59
+ result_with_run["intent_gate_version"] = str(resolved_claim.get("intent_gate_version", "")).strip()
60
+ result_with_run["advisory_context"] = {"profile_digest": profile_digest}
36
61
  results.append(result_with_run)
37
62
  aggregate_tokens.append(str(result.get("verdict", "")).strip().lower())
38
63
 
@@ -43,6 +68,10 @@ def judge_claims(project_dir: str, claims: list[dict[str, Any]]) -> dict[str, An
43
68
  "run_id": run_id,
44
69
  "claim": claim,
45
70
  "result": result,
71
+ "context_checksum": str(resolved_claim.get("context_checksum", "")).strip(),
72
+ "profile_version": str(resolved_claim.get("profile_version", "")).strip(),
73
+ "intent_gate_version": str(resolved_claim.get("intent_gate_version", "")).strip(),
74
+ "advisory_context": {"profile_digest": profile_digest},
46
75
  }
47
76
  artifact_path.write_text(json.dumps(artifact_payload, indent=2, sort_keys=True), encoding="utf-8")
48
77
 
@@ -52,7 +81,12 @@ def judge_claims(project_dir: str, claims: list[dict[str, Any]]) -> dict[str, An
52
81
  elif any(token == "block" for token in aggregate_tokens):
53
82
  verdict = "insufficient"
54
83
 
55
- return {"schema": "ClaimJudgeResults", "verdict": verdict, "results": results}
84
+ return {
85
+ "schema": "ClaimJudgeResults",
86
+ "verdict": verdict,
87
+ "results": results,
88
+ "advisory_context": {"profile_digest": profile_digest},
89
+ }
56
90
 
57
91
 
58
92
  def judge_claim(claim: dict[str, Any]) -> dict[str, Any]:
@@ -63,10 +97,15 @@ def judge_claim(claim: dict[str, Any]) -> dict[str, Any]:
63
97
  trace_ids = _as_non_empty_str_list(normalized_claim.get("trace_ids"))
64
98
  security_scans = normalized_claim.get("security_scans")
65
99
  browser_evidence = normalized_claim.get("browser_evidence")
100
+ evidence_profile = str(normalized_claim.get("evidence_profile", "")).strip()
101
+ evidence_requirements = requirements_for_profile(evidence_profile)
102
+ requirement_set = {str(item).strip() for item in evidence_requirements if str(item).strip()}
103
+ causal_chain = _as_dict(normalized_claim.get("causal_chain"))
66
104
 
67
105
  reasons: list[dict[str, Any]] = []
106
+ advisories: list[str] = []
68
107
 
69
- if not artifacts:
108
+ if "tests" in requirement_set and not artifacts:
70
109
  reasons.append(
71
110
  {
72
111
  "code": "missing_artifacts",
@@ -75,7 +114,7 @@ def judge_claim(claim: dict[str, Any]) -> dict[str, Any]:
75
114
  }
76
115
  )
77
116
 
78
- if not trace_ids:
117
+ if "trace_link" in requirement_set and not trace_ids:
79
118
  reasons.append(
80
119
  {
81
120
  "code": "missing_trace_ids",
@@ -84,7 +123,7 @@ def judge_claim(claim: dict[str, Any]) -> dict[str, Any]:
84
123
  }
85
124
  )
86
125
 
87
- if _has_failed_scan(security_scans):
126
+ if "security_scan" in requirement_set and _has_failed_scan(security_scans):
88
127
  reasons.append(
89
128
  {
90
129
  "code": "security_scan_failed",
@@ -93,7 +132,7 @@ def judge_claim(claim: dict[str, Any]) -> dict[str, Any]:
93
132
  }
94
133
  )
95
134
 
96
- if _has_failed_scan(browser_evidence):
135
+ if requirement_set == set(FULL_REQUIREMENTS) and _has_failed_scan(browser_evidence):
97
136
  reasons.append(
98
137
  {
99
138
  "code": "browser_evidence_failed",
@@ -118,6 +157,26 @@ def judge_claim(claim: dict[str, Any]) -> dict[str, Any]:
118
157
  }
119
158
  )
120
159
 
160
+ strict_mode = os.environ.get("OMG_PROOF_CHAIN_STRICT", "0").strip() == "1"
161
+ strict_causal_chain = strict_mode or _claim_type_enforces_strict_causal_chain(
162
+ claim_type=claim_type,
163
+ claim=claim,
164
+ )
165
+
166
+ causal_chain_errors = _validate_causal_chain(causal_chain, require_versions=strict_causal_chain)
167
+ if causal_chain_errors:
168
+ if strict_causal_chain:
169
+ reasons.append(
170
+ {
171
+ "code": "missing_causal_chain",
172
+ "message": "Claim must include lock->delta->verification causal chain evidence: "
173
+ + "; ".join(causal_chain_errors),
174
+ "field": "causal_chain",
175
+ }
176
+ )
177
+ else:
178
+ advisories.append("claim_judge_causal_chain_missing_permissive")
179
+
121
180
  hard_fail_codes = {"missing_artifacts", "missing_trace_ids"}
122
181
  if any(reason.get("code") in hard_fail_codes for reason in reasons):
123
182
  verdict = "fail"
@@ -138,6 +197,10 @@ def judge_claim(claim: dict[str, Any]) -> dict[str, Any]:
138
197
  "lineage": normalized_claim.get("lineage") if isinstance(normalized_claim.get("lineage"), dict) else {},
139
198
  "security_scans": security_scans if isinstance(security_scans, list) else [],
140
199
  "browser_evidence": browser_evidence if isinstance(browser_evidence, list) else [],
200
+ "causal_chain": causal_chain,
201
+ "advisories": advisories,
202
+ "evidence_profile": evidence_profile,
203
+ "evidence_requirements": list(evidence_requirements),
141
204
  },
142
205
  }
143
206
 
@@ -160,6 +223,18 @@ def _normalize_claim(claim: dict[str, Any]) -> dict[str, Any]:
160
223
  claim_browser_evidence = claim.get("browser_evidence")
161
224
  browser_evidence = claim_browser_evidence if isinstance(claim_browser_evidence, list) else _as_non_empty_dict_list(evidence.get("browser_evidence"))
162
225
 
226
+ lock_verification = claim.get("lock_verification") if isinstance(claim.get("lock_verification"), dict) else _as_dict(evidence.get("lock_verification"))
227
+ causal_chain = {
228
+ "lock_id": str(claim.get("lock_id", evidence.get("lock_id", ""))).strip(),
229
+ "delta_summary": claim.get("delta_summary") if isinstance(claim.get("delta_summary"), dict) else _as_dict(evidence.get("delta_summary")),
230
+ "verification_status": str(claim.get("verification_status", evidence.get("verification_status", ""))).strip(),
231
+ "waiver_artifact_path": str(claim.get("waiver_artifact_path", evidence.get("waiver_artifact_path", ""))).strip(),
232
+ "lock_verification": lock_verification,
233
+ "context_checksum": str(claim.get("context_checksum", evidence.get("context_checksum", ""))).strip(),
234
+ "profile_version": str(claim.get("profile_version", evidence.get("profile_version", ""))).strip(),
235
+ "intent_gate_version": str(claim.get("intent_gate_version", evidence.get("intent_gate_version", ""))).strip(),
236
+ }
237
+
163
238
  return {
164
239
  "schema_version": claim.get("schema_version", 1),
165
240
  "claim_type": claim.get("claim_type", ""),
@@ -169,9 +244,62 @@ def _normalize_claim(claim: dict[str, Any]) -> dict[str, Any]:
169
244
  "lineage": lineage,
170
245
  "security_scans": security_scans,
171
246
  "browser_evidence": browser_evidence,
247
+ "causal_chain": causal_chain,
248
+ "evidence_profile": str(claim.get("evidence_profile", evidence.get("evidence_profile", ""))).strip(),
172
249
  }
173
250
 
174
251
 
252
+ def _validate_causal_chain(causal_chain: dict[str, Any], *, require_versions: bool) -> list[str]:
253
+ errors: list[str] = []
254
+ lock_id = str(causal_chain.get("lock_id", "")).strip()
255
+ delta_summary = causal_chain.get("delta_summary")
256
+ verification_status = str(causal_chain.get("verification_status", "")).strip()
257
+ waiver_artifact_path = str(causal_chain.get("waiver_artifact_path", "")).strip()
258
+ context_checksum = str(causal_chain.get("context_checksum", "")).strip()
259
+ profile_version = str(causal_chain.get("profile_version", "")).strip()
260
+ intent_gate_version = str(causal_chain.get("intent_gate_version", "")).strip()
261
+ lock_verification = _as_dict(causal_chain.get("lock_verification"))
262
+
263
+ if not lock_id:
264
+ errors.append("missing_lock_id")
265
+ if not isinstance(delta_summary, dict) or not delta_summary:
266
+ errors.append("missing_delta_summary")
267
+ if not verification_status:
268
+ errors.append("missing_verification_status")
269
+
270
+ lock_status = str(lock_verification.get("status", "")).strip().lower()
271
+ lock_satisfied = lock_status == "ok"
272
+ if not waiver_artifact_path and not lock_satisfied:
273
+ errors.append("missing_waiver_or_lock_satisfied_proof")
274
+
275
+ if require_versions:
276
+ if not context_checksum:
277
+ errors.append("missing_context_checksum")
278
+ if not profile_version:
279
+ errors.append("missing_profile_version")
280
+ if not intent_gate_version:
281
+ errors.append("missing_intent_gate_version")
282
+
283
+ return errors
284
+
285
+
286
+ def _claim_type_enforces_strict_causal_chain(*, claim_type: str, claim: dict[str, Any]) -> bool:
287
+ mode = str(claim.get("causal_chain_mode", "")).strip().lower()
288
+ if mode == "legacy":
289
+ return False
290
+ if mode == "strict":
291
+ return True
292
+
293
+ if isinstance(claim.get("require_causal_chain"), bool):
294
+ return bool(claim.get("require_causal_chain"))
295
+
296
+ normalized = claim_type.strip().lower()
297
+ if not normalized:
298
+ return False
299
+ tokens = {item for item in normalized.replace("-", "_").split("_") if item}
300
+ return bool(tokens & {"runtime", "council"})
301
+
302
+
175
303
  def _normalize_artifact_records(value: Any) -> list[str]:
176
304
  if not isinstance(value, list):
177
305
  return []
@@ -270,3 +398,35 @@ _PARSERS: dict[str, Any] = {
270
398
  def _sanitize_run_id(value: str) -> str:
271
399
  cleaned = "".join(ch if ch.isalnum() or ch in {"-", "_", "."} else "-" for ch in value.strip())
272
400
  return cleaned or "unknown"
401
+
402
+
403
+ def _load_council_reasons(project_dir: str, run_id: str) -> list[dict[str, Any]]:
404
+ if not run_id:
405
+ return []
406
+ path = Path(project_dir) / ".omg" / "state" / "council_verdicts" / f"{run_id}.json"
407
+ if not path.exists():
408
+ return []
409
+ try:
410
+ payload = json.loads(path.read_text(encoding="utf-8"))
411
+ except (OSError, json.JSONDecodeError):
412
+ return []
413
+ if not isinstance(payload, dict):
414
+ return []
415
+
416
+ verdicts = _as_dict(payload.get("verdicts"))
417
+ evidence_completeness = _as_dict(verdicts.get("evidence_completeness"))
418
+ verdict = str(evidence_completeness.get("verdict", "")).strip().lower()
419
+ if verdict not in {"fail", "block", "blocked", "error"}:
420
+ return []
421
+ findings = evidence_completeness.get("findings")
422
+ finding_items = findings if isinstance(findings, list) else []
423
+ message = "council evidence completeness failed"
424
+ if finding_items:
425
+ message = "; ".join(str(item).strip() for item in finding_items if str(item).strip()) or message
426
+ return [
427
+ {
428
+ "code": "council_evidence_incomplete",
429
+ "message": message,
430
+ "field": "council_verdicts.evidence_completeness",
431
+ }
432
+ ]
@@ -603,7 +603,21 @@ def _init_bootstrap(project_dir: str, reason: str) -> list[str]:
603
603
  "name: omg-project\n"
604
604
  "description: initialized by OMG standalone compat bootstrap\n"
605
605
  "language: unknown\n"
606
- "framework: unknown\n",
606
+ "framework: unknown\n"
607
+ "stack: []\n"
608
+ "conventions: {}\n"
609
+ "ai_behavior: {}\n"
610
+ "preferences:\n"
611
+ " architecture_requests: []\n"
612
+ " constraints: {}\n"
613
+ " routing:\n"
614
+ " prefer_clarification: false\n"
615
+ "user_vector:\n"
616
+ " tags: []\n"
617
+ " summary: \"\"\n"
618
+ " confidence: 0.0\n"
619
+ "profile_provenance:\n"
620
+ " recent_updates: []\n",
607
621
  )
608
622
  _write_if_missing(
609
623
  idea_path,
@@ -11,11 +11,22 @@ from __future__ import annotations
11
11
 
12
12
  import json
13
13
  import os
14
+ import re
14
15
  from pathlib import Path
15
16
  from typing import Any
16
17
 
18
+ import yaml
19
+
20
+ from runtime.profile_io import profile_version_from_map
21
+
17
22
  _MAX_SUMMARY_CHARS = 1000
23
+ _MAX_CLARIFICATION_PROMPT_CHARS = 180
24
+ _PROFILE_SUMMARY_MAX_CHARS = 120
25
+ _PROFILE_DIGEST_TAG_MAX = 5
26
+ _PROFILE_DIGEST_ARCH_MAX = 3
27
+ _PROFILE_DIGEST_CONSTRAINT_MAX = 5
18
28
  _PACKET_REL_PATH = Path(".omg") / "state" / "context_engine_packet.json"
29
+ _PROFILE_REL_PATH = Path(".omg") / "state" / "profile.yaml"
19
30
 
20
31
  _STATE_PATHS = {
21
32
  "architecture_signal": Path(".omg") / "state" / "architecture_signal" / "latest.json",
@@ -23,6 +34,203 @@ _STATE_PATHS = {
23
34
  "background_verification": Path(".omg") / "state" / "background-verification.json",
24
35
  "context_pressure": Path(".omg") / "state" / ".context-pressure.json",
25
36
  }
37
+ _COUNCIL_REL_BASE = Path(".omg") / "state" / "council_verdicts"
38
+ _INTENT_GATE_REL_BASE = Path(".omg") / "state" / "intent_gate"
39
+
40
+
41
+ def load_profile_digest(project_dir: str | Path) -> dict[str, Any]:
42
+ root = Path(project_dir)
43
+ profile_path = root / _PROFILE_REL_PATH
44
+ if not profile_path.exists():
45
+ return _empty_profile_digest()
46
+
47
+ raw_profile = ""
48
+ parsed: dict[str, Any] = {}
49
+ try:
50
+ raw_profile = profile_path.read_text(encoding="utf-8")
51
+ except OSError:
52
+ return _empty_profile_digest()
53
+
54
+ try:
55
+ payload = yaml.safe_load(raw_profile)
56
+ except Exception:
57
+ payload = None
58
+ if isinstance(payload, dict):
59
+ parsed = payload
60
+
61
+ digest = _profile_digest_from_map(parsed, raw_profile)
62
+ return digest
63
+
64
+
65
+ def render_profile_digest_text(project_dir: str | Path, *, max_chars: int) -> str:
66
+ digest = load_profile_digest(project_dir)
67
+ arch_items = digest.get("architecture_requests")
68
+ arch_list = arch_items if isinstance(arch_items, list) else []
69
+ arch = ",".join(str(item)[:18] for item in arch_list if str(item).strip())
70
+ constraints_obj = digest.get("constraints", {})
71
+ constraints = constraints_obj if isinstance(constraints_obj, dict) else {}
72
+ constraint_tokens = []
73
+ for key, value in constraints.items():
74
+ if len(constraint_tokens) >= _PROFILE_DIGEST_CONSTRAINT_MAX:
75
+ break
76
+ value_text = str(value).strip()
77
+ if not value_text:
78
+ continue
79
+ constraint_tokens.append(f"{str(key)[:14]}={value_text[:14]}")
80
+ cons = ",".join(constraint_tokens)
81
+ tags_items = digest.get("tags")
82
+ tags_list = tags_items if isinstance(tags_items, list) else []
83
+ tags = ",".join(str(item)[:14] for item in tags_list if str(item).strip())
84
+ try:
85
+ confidence = round(float(digest.get("confidence", 0.0)), 2)
86
+ except (TypeError, ValueError):
87
+ confidence = 0.0
88
+ version = str(digest.get("profile_version", "")).strip()[:24]
89
+ summary = str(digest.get("summary", "")).strip()
90
+
91
+ prefix = f"arch[{arch}]|cons[{cons}]|tags[{tags}]|conf={confidence}|ver={version}|sum="
92
+ if len(prefix) >= max_chars:
93
+ return prefix[:max_chars]
94
+ remaining = max_chars - len(prefix)
95
+ if len(summary) > remaining:
96
+ if remaining <= 3:
97
+ summary = summary[:remaining]
98
+ else:
99
+ summary = summary[: remaining - 3] + "..."
100
+ return prefix + summary
101
+
102
+
103
+ def _empty_profile_digest() -> dict[str, Any]:
104
+ return {
105
+ "architecture_requests": [],
106
+ "constraints": {},
107
+ "tags": [],
108
+ "summary": "",
109
+ "confidence": 0.0,
110
+ "profile_version": "",
111
+ }
112
+
113
+
114
+ def _profile_digest_from_map(profile: dict[str, Any], raw_profile: str) -> dict[str, Any]:
115
+ preferences_obj = profile.get("preferences")
116
+ preferences: dict[str, Any] = preferences_obj if isinstance(preferences_obj, dict) else {}
117
+ user_vector_obj = profile.get("user_vector")
118
+ user_vector: dict[str, Any] = user_vector_obj if isinstance(user_vector_obj, dict) else {}
119
+ provenance_obj = profile.get("profile_provenance")
120
+ provenance: dict[str, Any] = provenance_obj if isinstance(provenance_obj, dict) else {}
121
+
122
+ architecture_obj = preferences.get("architecture_requests")
123
+ architecture_raw: list[Any] = architecture_obj if isinstance(architecture_obj, list) else []
124
+ architecture_requests = [
125
+ _clean_single_line(item)
126
+ for item in architecture_raw
127
+ if _clean_single_line(item)
128
+ ][:_PROFILE_DIGEST_ARCH_MAX]
129
+
130
+ constraints_obj = preferences.get("constraints")
131
+ constraints_raw: dict[str, Any] = constraints_obj if isinstance(constraints_obj, dict) else {}
132
+ constraints = _normalize_constraints(constraints_raw)
133
+
134
+ tags_obj = user_vector.get("tags")
135
+ tags_raw: list[Any] = tags_obj if isinstance(tags_obj, list) else []
136
+ tags = [_normalize_tag(item) for item in tags_raw if _normalize_tag(item)][:_PROFILE_DIGEST_TAG_MAX]
137
+
138
+ summary = _clean_single_line(
139
+ user_vector.get("summary")
140
+ or profile.get("summary")
141
+ or profile.get("name")
142
+ )[:_PROFILE_SUMMARY_MAX_CHARS]
143
+
144
+ confidence = _resolve_profile_confidence(profile, user_vector, provenance)
145
+ profile_version = _resolve_profile_version_pointer(profile, provenance, raw_profile)
146
+
147
+ return {
148
+ "architecture_requests": architecture_requests,
149
+ "constraints": constraints,
150
+ "tags": tags,
151
+ "summary": summary,
152
+ "confidence": confidence,
153
+ "profile_version": profile_version,
154
+ }
155
+
156
+
157
+ def _normalize_constraints(raw: dict[str, Any]) -> dict[str, str | int | float | bool | None]:
158
+ out: dict[str, str | int | float | bool | None] = {}
159
+ for key, value in raw.items():
160
+ if len(out) >= _PROFILE_DIGEST_CONSTRAINT_MAX:
161
+ break
162
+ normalized_key = _normalize_constraint_key(key)
163
+ normalized_value = _normalize_constraint_value(value)
164
+ if not normalized_key or normalized_value is None:
165
+ continue
166
+ out[normalized_key] = normalized_value
167
+ return out
168
+
169
+
170
+ def _normalize_constraint_key(value: object) -> str:
171
+ token = re.sub(r"\s+", "_", str(value).strip().lower())
172
+ token = "".join(ch for ch in token if ch.isalnum() or ch == "_")
173
+ return token[:40]
174
+
175
+
176
+ def _normalize_constraint_value(value: object) -> str | int | float | bool | None:
177
+ if isinstance(value, bool):
178
+ return value
179
+ if isinstance(value, int):
180
+ return value
181
+ if isinstance(value, float):
182
+ return round(value, 3)
183
+ if value is None:
184
+ return None
185
+ text = _clean_single_line(value).lower()
186
+ return text[:80] if text else None
187
+
188
+
189
+ def _normalize_tag(value: object) -> str:
190
+ token = re.sub(r"\s+", "_", str(value).strip().lower())
191
+ token = "".join(ch for ch in token if ch.isalnum() or ch in {"_", "-"})
192
+ return token[:24]
193
+
194
+
195
+ def _clean_single_line(value: object) -> str:
196
+ return " ".join(str(value).strip().split())
197
+
198
+
199
+ def _resolve_profile_confidence(
200
+ profile: dict[str, Any],
201
+ user_vector: dict[str, Any],
202
+ provenance: dict[str, Any],
203
+ ) -> float:
204
+ candidates = [
205
+ profile.get("confidence"),
206
+ user_vector.get("confidence"),
207
+ provenance.get("confidence"),
208
+ ]
209
+ for candidate in candidates:
210
+ if not isinstance(candidate, (int, float, str)):
211
+ continue
212
+ try:
213
+ value = float(candidate)
214
+ except (TypeError, ValueError):
215
+ continue
216
+ return round(max(0.0, min(1.0, value)), 2)
217
+ return 0.0
218
+
219
+
220
+ def _resolve_profile_version_pointer(profile: dict[str, Any], provenance: dict[str, Any], raw_profile: str) -> str:
221
+ for candidate in (
222
+ profile.get("profile_version"),
223
+ profile.get("version"),
224
+ provenance.get("checksum"),
225
+ provenance.get("version"),
226
+ ):
227
+ if candidate is None:
228
+ continue
229
+ text = _clean_single_line(candidate)
230
+ if text:
231
+ return text[:64]
232
+ # Deterministic: hash the parsed dict, not the raw text
233
+ return profile_version_from_map(profile)
26
234
 
27
235
 
28
236
  class ContextEngine:
@@ -61,12 +269,13 @@ class ContextEngine:
61
269
  # ------------------------------------------------------------------
62
270
 
63
271
  def _build(self, run_id: str, *, delta_only: bool) -> dict[str, Any]:
64
- raw = self._read_all_state()
65
- artifact_pointers = self._collect_artifact_pointers()
272
+ raw = self._read_all_state(run_id)
273
+ artifact_pointers = self._collect_artifact_pointers(run_id)
66
274
 
67
275
  if not artifact_pointers and all(v == {} for v in raw.values()):
68
276
  pkt = self._fallback(run_id)
69
277
  pkt["delta_only"] = delta_only
278
+ pkt["profile_digest"] = load_profile_digest(self.project_dir)
70
279
  self._persist_packet(pkt)
71
280
  return pkt
72
281
 
@@ -88,6 +297,8 @@ class ContextEngine:
88
297
  packet: dict[str, Any] = {
89
298
  "summary": summary,
90
299
  "artifact_pointers": artifact_pointers,
300
+ "clarification_status": self._compose_clarification_status(raw),
301
+ "profile_digest": load_profile_digest(self.project_dir),
91
302
  "budget": {
92
303
  "max_chars": _MAX_SUMMARY_CHARS,
93
304
  "used_chars": len(summary),
@@ -99,11 +310,13 @@ class ContextEngine:
99
310
  self._persist_packet(packet)
100
311
  return packet
101
312
 
102
- def _read_all_state(self) -> dict[str, Any]:
313
+ def _read_all_state(self, run_id: str) -> dict[str, Any]:
103
314
  """Read all state files, returning empty dicts for missing ones."""
104
315
  result: dict[str, Any] = {}
105
316
  for name, rel_path in _STATE_PATHS.items():
106
317
  result[name] = self._read_json(self.project_dir / rel_path)
318
+ result["council_verdicts"] = self._read_json(self.project_dir / _COUNCIL_REL_BASE / f"{run_id}.json")
319
+ result["intent_gate"] = self._read_json(self.project_dir / _INTENT_GATE_REL_BASE / f"{run_id}.json")
107
320
  return result
108
321
 
109
322
  def _read_json(self, path: Path) -> dict[str, Any]:
@@ -115,15 +328,43 @@ class ContextEngine:
115
328
  return {}
116
329
  return payload if isinstance(payload, dict) else {}
117
330
 
118
- def _collect_artifact_pointers(self) -> list[str]:
331
+ def _collect_artifact_pointers(self, run_id: str) -> list[str]:
119
332
  """Collect relative paths to existing state artifacts — NO raw content."""
120
333
  pointers: list[str] = []
121
334
  for rel_path in _STATE_PATHS.values():
122
335
  full = self.project_dir / rel_path
123
336
  if full.exists():
124
337
  pointers.append(str(rel_path))
338
+
339
+ council_rel = _COUNCIL_REL_BASE / f"{run_id}.json"
340
+ if (self.project_dir / council_rel).exists():
341
+ pointers.append(str(council_rel))
342
+
343
+ intent_gate_rel = _INTENT_GATE_REL_BASE / f"{run_id}.json"
344
+ if (self.project_dir / intent_gate_rel).exists():
345
+ pointers.append(str(intent_gate_rel))
125
346
  return pointers
126
347
 
348
+ def _compose_clarification_status(self, raw: dict[str, Any]) -> dict[str, Any]:
349
+ intent_gate = raw.get("intent_gate", {})
350
+ if not isinstance(intent_gate, dict):
351
+ intent_gate = {}
352
+
353
+ prompt = str(intent_gate.get("clarification_prompt", "")).strip().replace("\n", " ")
354
+ confidence_raw = intent_gate.get("confidence", 0.0)
355
+ try:
356
+ confidence = float(confidence_raw)
357
+ except (TypeError, ValueError):
358
+ confidence = 0.0
359
+ confidence = max(0.0, min(1.0, confidence))
360
+
361
+ return {
362
+ "requires_clarification": bool(intent_gate.get("requires_clarification") is True),
363
+ "intent_class": str(intent_gate.get("intent_class", "")).strip()[:48],
364
+ "clarification_prompt": prompt[:_MAX_CLARIFICATION_PROMPT_CHARS],
365
+ "confidence": round(confidence, 2),
366
+ }
367
+
127
368
  def _compose_summary(self, raw: dict[str, Any]) -> str:
128
369
  """Compose a bounded summary from state signals."""
129
370
  parts: list[str] = []
@@ -157,6 +398,15 @@ class ContextEngine:
157
398
  if tool_count is not None:
158
399
  parts.append(f"pressure: tools={tool_count} high={is_high}")
159
400
 
401
+ council = raw.get("council_verdicts", {})
402
+ if isinstance(council, dict):
403
+ verdicts = council.get("verdicts")
404
+ if isinstance(verdicts, dict) and verdicts:
405
+ evidence = verdicts.get("evidence_completeness")
406
+ if isinstance(evidence, dict):
407
+ token = str(evidence.get("verdict", "")).strip().lower() or "unknown"
408
+ parts.append(f"council: evidence_completeness={token}")
409
+
160
410
  if not parts:
161
411
  return "no context signals available"
162
412
 
@@ -188,6 +438,13 @@ class ContextEngine:
188
438
  return {
189
439
  "summary": "no context signals available",
190
440
  "artifact_pointers": [],
441
+ "clarification_status": {
442
+ "requires_clarification": False,
443
+ "intent_class": "",
444
+ "clarification_prompt": "",
445
+ "confidence": 0.0,
446
+ },
447
+ "profile_digest": _empty_profile_digest(),
191
448
  "budget": {"max_chars": _MAX_SUMMARY_CHARS, "used_chars": 0},
192
449
  "delta_only": False,
193
450
  "run_id": run_id,