@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
@@ -0,0 +1,80 @@
1
+ #!/usr/bin/env python3
2
+ """Zero-dependency canonical version extractor using AST parsing.
3
+
4
+ Reads CANONICAL_VERSION from runtime/adoption.py without importing it.
5
+ Prints the semver string (e.g. "2.1.1") with trailing newline.
6
+ Exit code 0 on success, non-zero on parse failure.
7
+ """
8
+ from __future__ import annotations
9
+
10
+ import ast
11
+ import sys
12
+ from pathlib import Path
13
+ from typing import cast
14
+
15
+
16
+ def extract_canonical_version(source_file: Path) -> str | None:
17
+ """Extract CANONICAL_VERSION from source file using AST parsing.
18
+
19
+ Args:
20
+ source_file: Path to runtime/adoption.py
21
+
22
+ Returns:
23
+ The version string (e.g. "2.1.1") or None if not found/invalid
24
+ """
25
+ try:
26
+ source_code = source_file.read_text(encoding="utf-8")
27
+ except (OSError, UnicodeDecodeError) as e:
28
+ print(f"Error reading {source_file}: {e}", file=sys.stderr)
29
+ return None
30
+
31
+ try:
32
+ tree = ast.parse(source_code)
33
+ except SyntaxError as e:
34
+ print(f"Syntax error in {source_file}: {e}", file=sys.stderr)
35
+ return None
36
+
37
+ # Walk the AST looking for CANONICAL_VERSION assignment
38
+ for node in ast.walk(tree):
39
+ if isinstance(node, ast.Assign):
40
+ for target in node.targets:
41
+ if isinstance(target, ast.Name) and target.id == "CANONICAL_VERSION":
42
+ if isinstance(node.value, ast.Constant):
43
+ val = node.value.value
44
+ if isinstance(val, str):
45
+ return cast(str, val)
46
+ elif isinstance(node.value, ast.Str):
47
+ return cast(str, node.value.s)
48
+
49
+ return None
50
+
51
+
52
+ def main() -> int:
53
+ """Main entry point."""
54
+ # Resolve path relative to repo root (where script is called from)
55
+ # First try: relative to script location (normal case)
56
+ scripts_dir = Path(__file__).resolve().parent
57
+ repo_root = scripts_dir.parent
58
+ adoption_file = repo_root / "runtime" / "adoption.py"
59
+
60
+ # Fallback: if not found, try current working directory
61
+ if not adoption_file.exists():
62
+ adoption_file = Path.cwd() / "runtime" / "adoption.py"
63
+
64
+ if not adoption_file.exists():
65
+ print(f"Error: {adoption_file} not found", file=sys.stderr)
66
+ return 1
67
+
68
+ version = extract_canonical_version(adoption_file)
69
+
70
+ if version is None:
71
+ print(f"Error: CANONICAL_VERSION not found in {adoption_file}", file=sys.stderr)
72
+ return 1
73
+
74
+ # Print the version with trailing newline
75
+ print(version)
76
+ return 0
77
+
78
+
79
+ if __name__ == "__main__":
80
+ sys.exit(main())
@@ -0,0 +1,476 @@
1
+ #!/usr/bin/env python3
2
+ """Sync/check flow for tracked source identity surfaces.
3
+
4
+ Reads CANONICAL_VERSION from runtime/adoption.py via AST and updates
5
+ or validates all tracked source surfaces defined in runtime/release_surfaces.py.
6
+
7
+ Usage:
8
+ python3 scripts/sync-release-identity.py # write mode (default)
9
+ python3 scripts/sync-release-identity.py --check # check mode (exits non-zero on drift)
10
+ """
11
+ from __future__ import annotations
12
+
13
+ import argparse
14
+ import ast
15
+ import json
16
+ import re
17
+ import sys
18
+ from pathlib import Path
19
+ from typing import Any, Union, cast
20
+
21
+ # Ensure repo root is importable
22
+ _REPO_ROOT = Path(__file__).resolve().parent.parent
23
+ if str(_REPO_ROOT) not in sys.path:
24
+ sys.path.insert(0, str(_REPO_ROOT))
25
+
26
+ from runtime.release_surfaces import (
27
+ AUTHORED_SURFACES,
28
+ DERIVED_SURFACE_DIRS,
29
+ AuthoredSurface,
30
+ )
31
+
32
+ KeyPath = list[Union[str, int]]
33
+
34
+ # Derived directories that must never be mutated
35
+ _DERIVED_DIRS = frozenset(DERIVED_SURFACE_DIRS)
36
+
37
+
38
+ # ── Version extraction (AST-based, zero-dependency) ────────────────────────
39
+
40
+
41
+ def extract_canonical_version(source_file: Path) -> str | None:
42
+ try:
43
+ source_code = source_file.read_text(encoding="utf-8")
44
+ except (OSError, UnicodeDecodeError) as e:
45
+ print(f"Error reading {source_file}: {e}", file=sys.stderr)
46
+ return None
47
+
48
+ try:
49
+ tree = ast.parse(source_code)
50
+ except SyntaxError as e:
51
+ print(f"Syntax error in {source_file}: {e}", file=sys.stderr)
52
+ return None
53
+
54
+ for node in ast.walk(tree):
55
+ if isinstance(node, ast.Assign):
56
+ for target in node.targets:
57
+ if isinstance(target, ast.Name) and target.id == "CANONICAL_VERSION":
58
+ if isinstance(node.value, ast.Constant):
59
+ val = node.value.value
60
+ if isinstance(val, str):
61
+ return cast(str, val)
62
+ elif isinstance(node.value, ast.Str): # Python 3.7 compat
63
+ return cast(str, node.value.s)
64
+
65
+ return None
66
+
67
+
68
+ # ── JSON helpers ────────────────────────────────────────────────────────────
69
+
70
+
71
+ def _get_nested(data: Any, key_path: KeyPath) -> Any:
72
+ current = data
73
+ for key in key_path:
74
+ if isinstance(current, dict) and isinstance(key, str):
75
+ current = current.get(key)
76
+ elif isinstance(current, list) and isinstance(key, int):
77
+ if 0 <= key < len(current):
78
+ current = current[key]
79
+ else:
80
+ return None
81
+ else:
82
+ return None
83
+ if current is None:
84
+ return None
85
+ return current
86
+
87
+
88
+ def _set_nested(data: Any, key_path: KeyPath, value: Any) -> None:
89
+ current = data
90
+ for key in key_path[:-1]:
91
+ if isinstance(current, dict) and isinstance(key, str):
92
+ current = current[key]
93
+ elif isinstance(current, list) and isinstance(key, int):
94
+ current = current[key]
95
+ last = key_path[-1]
96
+ if isinstance(current, dict) and isinstance(last, str):
97
+ current[last] = value
98
+ elif isinstance(current, list) and isinstance(last, int):
99
+ current[last] = value
100
+
101
+
102
+ def _format_key_path(kp: KeyPath) -> str:
103
+ parts: list[str] = []
104
+ for k in kp:
105
+ if isinstance(k, int):
106
+ parts.append(f"[{k}]")
107
+ else:
108
+ if parts:
109
+ parts.append(f".{k}")
110
+ else:
111
+ parts.append(k)
112
+ return "".join(parts)
113
+
114
+
115
+ # ── Guard ───────────────────────────────────────────────────────────────────
116
+
117
+
118
+ def _guard_derived(surface: AuthoredSurface) -> None:
119
+ """Raise if surface targets a derived/generated directory."""
120
+ for d in _DERIVED_DIRS:
121
+ if surface.file_path.startswith(d):
122
+ raise ValueError(
123
+ f"Refusing to mutate derived directory: {surface.file_path}"
124
+ )
125
+
126
+
127
+ def _surface_label(surface: AuthoredSurface) -> str:
128
+ """Human-readable label for a surface."""
129
+ if surface.surface_type == "json_key_path" and isinstance(surface.field, list):
130
+ return f"{surface.file_path} {_format_key_path(surface.field)}"
131
+ return surface.file_path
132
+
133
+
134
+ def _replace_group1(m: re.Match[str], new_version: str) -> str:
135
+ """Replace captured group 1 in a regex match, preserving surrounding text."""
136
+ prefix = m.group(0)[: m.start(1) - m.start(0)]
137
+ suffix = m.group(0)[m.end(1) - m.start(0) :]
138
+ return prefix + new_version + suffix
139
+
140
+
141
+ # ── Check handlers ──────────────────────────────────────────────────────────
142
+
143
+
144
+ def _check_json_key_path(
145
+ repo_root: Path, surface: AuthoredSurface, canonical: str,
146
+ ) -> list[tuple[str, str | None]]:
147
+ label = _surface_label(surface)
148
+ file_path = repo_root / surface.file_path
149
+ key_path = cast(KeyPath, surface.field)
150
+ try:
151
+ data = json.loads(file_path.read_text(encoding="utf-8"))
152
+ except (OSError, json.JSONDecodeError) as e:
153
+ return [(label, f"<error: {e}>")]
154
+ current = _get_nested(data, key_path)
155
+ if current != canonical:
156
+ return [(label, str(current) if current is not None else None)]
157
+ return []
158
+
159
+
160
+ def _check_regex(
161
+ repo_root: Path, surface: AuthoredSurface, canonical: str,
162
+ ) -> list[tuple[str, str | None]]:
163
+ """Generic check for regex_line, shell_literal, js_literal, banner_literal."""
164
+ label = _surface_label(surface)
165
+ pattern = cast(str, surface.field)
166
+ try:
167
+ content = (repo_root / surface.file_path).read_text(encoding="utf-8")
168
+ except OSError as e:
169
+ return [(label, f"<error: {e}>")]
170
+ match = re.search(pattern, content, re.MULTILINE)
171
+ if match:
172
+ current = match.group(1)
173
+ if current != canonical:
174
+ return [(label, current)]
175
+ return []
176
+ return [(label, "<pattern not found>")]
177
+
178
+
179
+ def _check_yaml_line(
180
+ repo_root: Path, surface: AuthoredSurface, canonical: str,
181
+ ) -> list[tuple[str, str | None]]:
182
+ label = _surface_label(surface)
183
+ try:
184
+ content = (repo_root / surface.file_path).read_text(encoding="utf-8")
185
+ except OSError as e:
186
+ return [(label, f"<error: {e}>")]
187
+ match = re.search(r"^version:\s+(.+)$", content, re.MULTILINE)
188
+ if match:
189
+ current = match.group(1).strip()
190
+ if current != canonical:
191
+ return [(label, current)]
192
+ return []
193
+ return [(label, "<pattern not found>")]
194
+
195
+
196
+ def _check_frontmatter_field(
197
+ repo_root: Path, surface: AuthoredSurface, canonical: str,
198
+ ) -> list[tuple[str, str | None]]:
199
+ label = _surface_label(surface)
200
+ field_name = cast(str, surface.field)
201
+ try:
202
+ content = (repo_root / surface.file_path).read_text(encoding="utf-8")
203
+ except OSError as e:
204
+ return [(label, f"<error: {e}>")]
205
+ fm_match = re.match(r"^---\n(.*?)\n---", content, re.DOTALL)
206
+ if not fm_match:
207
+ return [(label, "<no frontmatter found>")]
208
+ field_match = re.search(
209
+ rf"^{re.escape(field_name)}:\s+(.+)$", fm_match.group(1), re.MULTILINE,
210
+ )
211
+ if field_match:
212
+ current = field_match.group(1).strip()
213
+ if current != canonical:
214
+ return [(label, current)]
215
+ return []
216
+ return [(label, f"<field '{field_name}' not found in frontmatter>")]
217
+
218
+
219
+ def _check_changelog_header(
220
+ repo_root: Path, surface: AuthoredSurface, canonical: str,
221
+ ) -> list[tuple[str, str | None]]:
222
+ label = _surface_label(surface)
223
+ pattern = cast(str, surface.field)
224
+ try:
225
+ content = (repo_root / surface.file_path).read_text(encoding="utf-8")
226
+ except OSError as e:
227
+ return [(label, f"<error: {e}>")]
228
+ match = re.search(pattern, content, re.MULTILINE)
229
+ if match:
230
+ current = match.group(1)
231
+ if current != canonical:
232
+ return [(label, current)]
233
+ return []
234
+ return [(label, "<no version header found>")]
235
+
236
+
237
+ # ── Update handlers ─────────────────────────────────────────────────────────
238
+
239
+
240
+ def _update_json_key_path(
241
+ repo_root: Path, surface: AuthoredSurface, canonical: str,
242
+ ) -> list[str]:
243
+ label = _surface_label(surface)
244
+ file_path = repo_root / surface.file_path
245
+ key_path = cast(KeyPath, surface.field)
246
+ try:
247
+ data = json.loads(file_path.read_text(encoding="utf-8"))
248
+ except (OSError, json.JSONDecodeError) as e:
249
+ print(f" WARNING: Could not read {surface.file_path}: {e}", file=sys.stderr)
250
+ return []
251
+ current = _get_nested(data, key_path)
252
+ if current != canonical:
253
+ _set_nested(data, key_path, canonical)
254
+ file_path.write_text(
255
+ json.dumps(data, indent=2, ensure_ascii=False) + "\n",
256
+ encoding="utf-8",
257
+ )
258
+ return [label]
259
+ return []
260
+
261
+
262
+ def _update_regex(
263
+ repo_root: Path, surface: AuthoredSurface, canonical: str,
264
+ ) -> list[str]:
265
+ """Generic update for regex_line, shell_literal, js_literal, banner_literal."""
266
+ label = _surface_label(surface)
267
+ pattern = cast(str, surface.field)
268
+ file_path = repo_root / surface.file_path
269
+ try:
270
+ content = file_path.read_text(encoding="utf-8")
271
+ except OSError as e:
272
+ print(f" WARNING: Could not read {surface.file_path}: {e}", file=sys.stderr)
273
+ return []
274
+ new_content = re.sub(
275
+ pattern,
276
+ lambda m: _replace_group1(m, canonical),
277
+ content,
278
+ count=1,
279
+ flags=re.MULTILINE,
280
+ )
281
+ if new_content != content:
282
+ file_path.write_text(new_content, encoding="utf-8")
283
+ return [label]
284
+ return []
285
+
286
+
287
+ def _update_yaml_line(
288
+ repo_root: Path, surface: AuthoredSurface, canonical: str,
289
+ ) -> list[str]:
290
+ label = _surface_label(surface)
291
+ file_path = repo_root / surface.file_path
292
+ try:
293
+ content = file_path.read_text(encoding="utf-8")
294
+ except OSError as e:
295
+ print(f" WARNING: Could not read {surface.file_path}: {e}", file=sys.stderr)
296
+ return []
297
+ replacement = f"version: {canonical}"
298
+ new_content, count = re.subn(
299
+ r"^version: .*$", replacement, content, count=1, flags=re.MULTILINE,
300
+ )
301
+ if count > 0 and new_content != content:
302
+ file_path.write_text(new_content, encoding="utf-8")
303
+ return [label]
304
+ return []
305
+
306
+
307
+ def _update_frontmatter_field(
308
+ repo_root: Path, surface: AuthoredSurface, canonical: str,
309
+ ) -> list[str]:
310
+ label = _surface_label(surface)
311
+ file_path = repo_root / surface.file_path
312
+ try:
313
+ content = file_path.read_text(encoding="utf-8")
314
+ except OSError as e:
315
+ print(f" WARNING: Could not read {surface.file_path}: {e}", file=sys.stderr)
316
+ return []
317
+ fm_match = re.match(r"^---\n(.*?)\n---", content, re.DOTALL)
318
+ if not fm_match:
319
+ print(f" WARNING: No frontmatter in {surface.file_path}", file=sys.stderr)
320
+ return []
321
+ field_name = cast(str, surface.field)
322
+ old_fm = fm_match.group(1)
323
+ new_fm = re.sub(
324
+ rf"^({re.escape(field_name)}:\s+)(.+)$",
325
+ rf"\g<1>{canonical}",
326
+ old_fm,
327
+ count=1,
328
+ flags=re.MULTILINE,
329
+ )
330
+ if new_fm != old_fm:
331
+ new_content = content[: fm_match.start(1)] + new_fm + content[fm_match.end(1) :]
332
+ file_path.write_text(new_content, encoding="utf-8")
333
+ return [label]
334
+ return []
335
+
336
+
337
+ def _update_changelog_header(
338
+ repo_root: Path, surface: AuthoredSurface, canonical: str,
339
+ ) -> list[str]:
340
+ label = _surface_label(surface)
341
+ file_path = repo_root / surface.file_path
342
+ try:
343
+ content = file_path.read_text(encoding="utf-8")
344
+ except OSError as e:
345
+ print(f" WARNING: Could not read {surface.file_path}: {e}", file=sys.stderr)
346
+ return []
347
+
348
+ def _replace_version(m: re.Match[str]) -> str:
349
+ return f"{m.group(1)}{canonical}{m.group(3)}"
350
+
351
+ new_content, count = re.subn(
352
+ r"^(## \[?)(\d+\.\d+\.\d+)(\]?.*)",
353
+ _replace_version,
354
+ content,
355
+ count=1,
356
+ flags=re.MULTILINE,
357
+ )
358
+ if count > 0 and new_content != content:
359
+ file_path.write_text(new_content, encoding="utf-8")
360
+ return [label]
361
+ return []
362
+
363
+
364
+ # ── Dispatch tables ─────────────────────────────────────────────────────────
365
+
366
+ _CHECK_DISPATCH = {
367
+ "json_key_path": _check_json_key_path,
368
+ "regex_line": _check_regex,
369
+ "yaml_line": _check_yaml_line,
370
+ "frontmatter_field": _check_frontmatter_field,
371
+ "changelog_header": _check_changelog_header,
372
+ "shell_literal": _check_regex,
373
+ "js_literal": _check_regex,
374
+ "banner_literal": _check_regex,
375
+ }
376
+
377
+ _UPDATE_DISPATCH = {
378
+ "json_key_path": _update_json_key_path,
379
+ "regex_line": _update_regex,
380
+ "yaml_line": _update_yaml_line,
381
+ "frontmatter_field": _update_frontmatter_field,
382
+ "changelog_header": _update_changelog_header,
383
+ "shell_literal": _update_regex,
384
+ "js_literal": _update_regex,
385
+ "banner_literal": _update_regex,
386
+ }
387
+
388
+
389
+ # ── Public API ──────────────────────────────────────────────────────────────
390
+
391
+
392
+ def check_surface(
393
+ repo_root: Path, surface: AuthoredSurface, canonical: str,
394
+ ) -> list[tuple[str, str | None]]:
395
+ """Check a single surface for version drift."""
396
+ _guard_derived(surface)
397
+ handler = _CHECK_DISPATCH.get(surface.surface_type)
398
+ if handler is None:
399
+ return [(_surface_label(surface), f"<unknown type: {surface.surface_type}>")]
400
+ return handler(repo_root, surface, canonical)
401
+
402
+
403
+ def update_surface(
404
+ repo_root: Path, surface: AuthoredSurface, canonical: str,
405
+ ) -> list[str]:
406
+ """Update a single surface to canonical version."""
407
+ _guard_derived(surface)
408
+ handler = _UPDATE_DISPATCH.get(surface.surface_type)
409
+ if handler is None:
410
+ return []
411
+ return handler(repo_root, surface, canonical)
412
+
413
+
414
+ # ── CLI entry point ─────────────────────────────────────────────────────────
415
+
416
+
417
+ def main() -> int:
418
+ parser = argparse.ArgumentParser(
419
+ description="Sync or check tracked source identity surfaces.",
420
+ )
421
+ parser.add_argument(
422
+ "--check",
423
+ action="store_true",
424
+ help="Check mode: exit non-zero if any surface drifts",
425
+ )
426
+ args = parser.parse_args()
427
+
428
+ scripts_dir = Path(__file__).resolve().parent
429
+ repo_root = scripts_dir.parent
430
+ adoption_file = repo_root / "runtime" / "adoption.py"
431
+
432
+ if not adoption_file.exists():
433
+ repo_root = Path.cwd()
434
+ adoption_file = repo_root / "runtime" / "adoption.py"
435
+
436
+ if not adoption_file.exists():
437
+ print(f"Error: {adoption_file} not found", file=sys.stderr)
438
+ return 1
439
+
440
+ canonical = extract_canonical_version(adoption_file)
441
+ if canonical is None:
442
+ print("Error: CANONICAL_VERSION not found", file=sys.stderr)
443
+ return 1
444
+
445
+ print(f"Canonical version: {canonical}")
446
+
447
+ if args.check:
448
+ all_drifts: list[tuple[str, str | None]] = []
449
+ for surface in AUTHORED_SURFACES:
450
+ all_drifts.extend(check_surface(repo_root, surface, canonical))
451
+
452
+ if all_drifts:
453
+ print(f"\nDrift detected in {len(all_drifts)} surface(s):\n")
454
+ for surf, current in all_drifts:
455
+ cur = current if current is not None else "<not found>"
456
+ print(f" DRIFT {surf}: {cur} (expected {canonical})")
457
+ return 1
458
+ else:
459
+ print("\nAll tracked surfaces in sync.")
460
+ return 0
461
+ else:
462
+ all_updated: list[str] = []
463
+ for surface in AUTHORED_SURFACES:
464
+ all_updated.extend(update_surface(repo_root, surface, canonical))
465
+
466
+ if all_updated:
467
+ print(f"\nUpdated {len(all_updated)} surface(s):\n")
468
+ for u in all_updated:
469
+ print(f" UPDATED {u}")
470
+ else:
471
+ print("\nAll tracked surfaces already at canonical version.")
472
+ return 0
473
+
474
+
475
+ if __name__ == "__main__":
476
+ sys.exit(main())