@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.
- package/.agents/skills/omg/AGENTS.fragment.md +2 -2
- package/.agents/skills/omg/algorithms/SKILL.md +1 -1
- package/.agents/skills/omg/algorithms/openai.yaml +1 -1
- package/.agents/skills/omg/api-twin/SKILL.md +1 -1
- package/.agents/skills/omg/api-twin/openai.yaml +1 -1
- package/.agents/skills/omg/claim-judge/SKILL.md +1 -1
- package/.agents/skills/omg/claim-judge/openai.yaml +1 -1
- package/.agents/skills/omg/codex-rules.md +1 -1
- package/.agents/skills/omg/control-plane/SKILL.md +1 -1
- package/.agents/skills/omg/control-plane/openai.yaml +1 -1
- package/.agents/skills/omg/data-lineage/SKILL.md +1 -1
- package/.agents/skills/omg/data-lineage/openai.yaml +1 -1
- package/.agents/skills/omg/delta-classifier/SKILL.md +1 -1
- package/.agents/skills/omg/delta-classifier/openai.yaml +1 -1
- package/.agents/skills/omg/eval-gate/SKILL.md +1 -1
- package/.agents/skills/omg/eval-gate/openai.yaml +1 -1
- package/.agents/skills/omg/health/SKILL.md +1 -1
- package/.agents/skills/omg/health/openai.yaml +1 -1
- package/.agents/skills/omg/hook-governor/SKILL.md +1 -1
- package/.agents/skills/omg/hook-governor/openai.yaml +1 -1
- package/.agents/skills/omg/incident-replay/SKILL.md +1 -1
- package/.agents/skills/omg/incident-replay/openai.yaml +1 -1
- package/.agents/skills/omg/lsp-pack/SKILL.md +1 -1
- package/.agents/skills/omg/lsp-pack/openai.yaml +1 -1
- package/.agents/skills/omg/mcp-fabric/SKILL.md +1 -1
- package/.agents/skills/omg/mcp-fabric/openai.yaml +1 -1
- package/.agents/skills/omg/plan-council/SKILL.md +1 -1
- package/.agents/skills/omg/plan-council/openai.yaml +1 -1
- package/.agents/skills/omg/preflight/SKILL.md +1 -1
- package/.agents/skills/omg/preflight/openai.yaml +1 -1
- package/.agents/skills/omg/proof-gate/SKILL.md +1 -1
- package/.agents/skills/omg/proof-gate/openai.yaml +1 -1
- package/.agents/skills/omg/remote-supervisor/SKILL.md +1 -1
- package/.agents/skills/omg/remote-supervisor/openai.yaml +1 -1
- package/.agents/skills/omg/robotics/SKILL.md +1 -1
- package/.agents/skills/omg/robotics/openai.yaml +1 -1
- package/.agents/skills/omg/secure-worktree-pipeline/SKILL.md +1 -1
- package/.agents/skills/omg/secure-worktree-pipeline/openai.yaml +1 -1
- package/.agents/skills/omg/security-check/SKILL.md +1 -1
- package/.agents/skills/omg/security-check/openai.yaml +1 -1
- package/.agents/skills/omg/test-intent-lock/SKILL.md +1 -1
- package/.agents/skills/omg/test-intent-lock/openai.yaml +1 -1
- package/.agents/skills/omg/tracebank/SKILL.md +1 -1
- package/.agents/skills/omg/tracebank/openai.yaml +1 -1
- package/.agents/skills/omg/vision/SKILL.md +1 -1
- package/.agents/skills/omg/vision/openai.yaml +1 -1
- package/.claude-plugin/marketplace.json +3 -3
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +16 -0
- package/CLI-ADAPTER-MAP.md +3 -3
- package/OMG-setup.sh +114 -1
- package/OMG_COMPAT_CONTRACT.md +1 -1
- package/README.md +2 -1
- package/artifacts/release/.claude-plugin/marketplace.json +3 -3
- package/artifacts/release/.claude-plugin/plugin.json +1 -1
- package/artifacts/release/OMG_COMPAT_CONTRACT.md +1 -1
- package/artifacts/release/dist/enterprise/bundle/.claude-plugin/marketplace.json +3 -3
- package/artifacts/release/dist/enterprise/bundle/.claude-plugin/plugin.json +1 -1
- package/artifacts/release/dist/enterprise/bundle/OMG_COMPAT_CONTRACT.md +1 -1
- package/artifacts/release/dist/enterprise/bundle/plugins/advanced/plugin.json +26 -9
- package/artifacts/release/dist/enterprise/bundle/registry/bundles/algorithms.yaml +1 -1
- package/artifacts/release/dist/enterprise/bundle/registry/bundles/api-twin.yaml +1 -1
- package/artifacts/release/dist/enterprise/bundle/registry/bundles/claim-judge.yaml +1 -1
- package/artifacts/release/dist/enterprise/bundle/registry/bundles/control-plane.yaml +1 -1
- package/artifacts/release/dist/enterprise/bundle/registry/bundles/data-lineage.yaml +1 -1
- package/artifacts/release/dist/enterprise/bundle/registry/bundles/delta-classifier.yaml +1 -1
- package/artifacts/release/dist/enterprise/bundle/registry/bundles/eval-gate.yaml +1 -1
- package/artifacts/release/dist/enterprise/bundle/registry/bundles/health.yaml +1 -1
- package/artifacts/release/dist/enterprise/bundle/registry/bundles/hook-governor.yaml +1 -1
- package/artifacts/release/dist/enterprise/bundle/registry/bundles/incident-replay.yaml +1 -1
- package/artifacts/release/dist/enterprise/bundle/registry/bundles/lsp-pack.yaml +1 -1
- package/artifacts/release/dist/enterprise/bundle/registry/bundles/mcp-fabric.yaml +1 -1
- package/artifacts/release/dist/enterprise/bundle/registry/bundles/plan-council.yaml +1 -1
- package/artifacts/release/dist/enterprise/bundle/registry/bundles/preflight.yaml +1 -1
- package/artifacts/release/dist/enterprise/bundle/registry/bundles/proof-gate.yaml +1 -1
- package/artifacts/release/dist/enterprise/bundle/registry/bundles/remote-supervisor.yaml +1 -1
- package/artifacts/release/dist/enterprise/bundle/registry/bundles/robotics.yaml +1 -1
- package/artifacts/release/dist/enterprise/bundle/registry/bundles/secure-worktree-pipeline.yaml +1 -1
- package/artifacts/release/dist/enterprise/bundle/registry/bundles/security-check.yaml +1 -1
- package/artifacts/release/dist/enterprise/bundle/registry/bundles/test-intent-lock.yaml +1 -1
- package/artifacts/release/dist/enterprise/bundle/registry/bundles/tracebank.yaml +1 -1
- package/artifacts/release/dist/enterprise/bundle/registry/bundles/vision.yaml +1 -1
- package/artifacts/release/dist/enterprise/bundle/registry/omg-capability.schema.json +1 -1
- package/artifacts/release/dist/enterprise/bundle/settings.json +3 -3
- package/artifacts/release/dist/enterprise/manifest.json +30 -40
- package/artifacts/release/dist/public/bundle/.claude-plugin/marketplace.json +3 -3
- package/artifacts/release/dist/public/bundle/.claude-plugin/plugin.json +1 -1
- package/artifacts/release/dist/public/bundle/OMG_COMPAT_CONTRACT.md +1 -1
- package/artifacts/release/dist/public/bundle/plugins/advanced/plugin.json +26 -9
- package/artifacts/release/dist/public/bundle/registry/bundles/algorithms.yaml +1 -1
- package/artifacts/release/dist/public/bundle/registry/bundles/api-twin.yaml +1 -1
- package/artifacts/release/dist/public/bundle/registry/bundles/claim-judge.yaml +1 -1
- package/artifacts/release/dist/public/bundle/registry/bundles/control-plane.yaml +1 -1
- package/artifacts/release/dist/public/bundle/registry/bundles/data-lineage.yaml +1 -1
- package/artifacts/release/dist/public/bundle/registry/bundles/delta-classifier.yaml +1 -1
- package/artifacts/release/dist/public/bundle/registry/bundles/eval-gate.yaml +1 -1
- package/artifacts/release/dist/public/bundle/registry/bundles/health.yaml +1 -1
- package/artifacts/release/dist/public/bundle/registry/bundles/hook-governor.yaml +1 -1
- package/artifacts/release/dist/public/bundle/registry/bundles/incident-replay.yaml +1 -1
- package/artifacts/release/dist/public/bundle/registry/bundles/lsp-pack.yaml +1 -1
- package/artifacts/release/dist/public/bundle/registry/bundles/mcp-fabric.yaml +1 -1
- package/artifacts/release/dist/public/bundle/registry/bundles/plan-council.yaml +1 -1
- package/artifacts/release/dist/public/bundle/registry/bundles/preflight.yaml +1 -1
- package/artifacts/release/dist/public/bundle/registry/bundles/proof-gate.yaml +1 -1
- package/artifacts/release/dist/public/bundle/registry/bundles/remote-supervisor.yaml +1 -1
- package/artifacts/release/dist/public/bundle/registry/bundles/robotics.yaml +1 -1
- package/artifacts/release/dist/public/bundle/registry/bundles/secure-worktree-pipeline.yaml +1 -1
- package/artifacts/release/dist/public/bundle/registry/bundles/security-check.yaml +1 -1
- package/artifacts/release/dist/public/bundle/registry/bundles/test-intent-lock.yaml +1 -1
- package/artifacts/release/dist/public/bundle/registry/bundles/tracebank.yaml +1 -1
- package/artifacts/release/dist/public/bundle/registry/bundles/vision.yaml +1 -1
- package/artifacts/release/dist/public/bundle/registry/omg-capability.schema.json +1 -1
- package/artifacts/release/dist/public/bundle/settings.json +3 -3
- package/artifacts/release/dist/public/manifest.json +30 -40
- package/artifacts/release/plugins/advanced/plugin.json +26 -9
- package/artifacts/release/registry/bundles/algorithms.yaml +1 -1
- package/artifacts/release/registry/bundles/api-twin.yaml +1 -1
- package/artifacts/release/registry/bundles/claim-judge.yaml +1 -1
- package/artifacts/release/registry/bundles/control-plane.yaml +1 -1
- package/artifacts/release/registry/bundles/data-lineage.yaml +1 -1
- package/artifacts/release/registry/bundles/delta-classifier.yaml +1 -1
- package/artifacts/release/registry/bundles/eval-gate.yaml +1 -1
- package/artifacts/release/registry/bundles/health.yaml +1 -1
- package/artifacts/release/registry/bundles/hook-governor.yaml +1 -1
- package/artifacts/release/registry/bundles/incident-replay.yaml +1 -1
- package/artifacts/release/registry/bundles/lsp-pack.yaml +1 -1
- package/artifacts/release/registry/bundles/mcp-fabric.yaml +1 -1
- package/artifacts/release/registry/bundles/plan-council.yaml +1 -1
- package/artifacts/release/registry/bundles/preflight.yaml +1 -1
- package/artifacts/release/registry/bundles/proof-gate.yaml +1 -1
- package/artifacts/release/registry/bundles/remote-supervisor.yaml +1 -1
- package/artifacts/release/registry/bundles/robotics.yaml +1 -1
- package/artifacts/release/registry/bundles/secure-worktree-pipeline.yaml +1 -1
- package/artifacts/release/registry/bundles/security-check.yaml +1 -1
- package/artifacts/release/registry/bundles/test-intent-lock.yaml +1 -1
- package/artifacts/release/registry/bundles/tracebank.yaml +1 -1
- package/artifacts/release/registry/bundles/vision.yaml +1 -1
- package/artifacts/release/registry/omg-capability.schema.json +1 -1
- package/artifacts/release/settings.json +3 -3
- package/build/lib/commands/OMG:profile-review.md +43 -0
- package/build/lib/commands/OMG:validate.md +59 -0
- package/build/lib/control_plane/service.py +40 -1
- package/build/lib/hooks/_agent_registry.py +2 -0
- package/build/lib/hooks/firewall.py +263 -4
- package/build/lib/hooks/intentgate-keyword-detector.py +15 -3
- package/build/lib/hooks/policy_engine.py +77 -0
- package/build/lib/hooks/prompt-enhancer.py +146 -0
- package/build/lib/hooks/session-end-capture.py +374 -6
- package/build/lib/hooks/session-start.py +13 -35
- package/build/lib/hooks/setup_wizard.py +333 -1
- package/build/lib/hooks/shadow_manager.py +111 -2
- package/build/lib/hooks/stop_dispatcher.py +108 -4
- package/build/lib/plugins/advanced/plugin.json +26 -9
- package/build/lib/plugins/core/plugin.json +44 -11
- package/build/lib/registry/bundles/algorithms.yaml +1 -1
- package/build/lib/registry/bundles/api-twin.yaml +1 -1
- package/build/lib/registry/bundles/claim-judge.yaml +1 -1
- package/build/lib/registry/bundles/control-plane.yaml +1 -1
- package/build/lib/registry/bundles/data-lineage.yaml +1 -1
- package/build/lib/registry/bundles/delta-classifier.yaml +1 -1
- package/build/lib/registry/bundles/eval-gate.yaml +1 -1
- package/build/lib/registry/bundles/health.yaml +1 -1
- package/build/lib/registry/bundles/hook-governor.yaml +1 -1
- package/build/lib/registry/bundles/incident-replay.yaml +1 -1
- package/build/lib/registry/bundles/lsp-pack.yaml +1 -1
- package/build/lib/registry/bundles/mcp-fabric.yaml +1 -1
- package/build/lib/registry/bundles/plan-council.yaml +1 -1
- package/build/lib/registry/bundles/preflight.yaml +1 -1
- package/build/lib/registry/bundles/proof-gate.yaml +1 -1
- package/build/lib/registry/bundles/remote-supervisor.yaml +1 -1
- package/build/lib/registry/bundles/robotics.yaml +1 -1
- package/build/lib/registry/bundles/secure-worktree-pipeline.yaml +1 -1
- package/build/lib/registry/bundles/security-check.yaml +1 -1
- package/build/lib/registry/bundles/test-intent-lock.yaml +1 -1
- package/build/lib/registry/bundles/tracebank.yaml +1 -1
- package/build/lib/registry/bundles/vision.yaml +1 -1
- package/build/lib/registry/omg-capability.schema.json +1 -1
- package/build/lib/runtime/adoption.py +1 -1
- package/build/lib/runtime/background_verification.py +62 -0
- package/build/lib/runtime/claim_judge.py +165 -5
- package/build/lib/runtime/compat.py +15 -1
- package/build/lib/runtime/context_engine.py +261 -4
- package/build/lib/runtime/contract_compiler.py +370 -93
- package/build/lib/runtime/defense_state.py +79 -8
- package/build/lib/runtime/delta_classifier.py +80 -2
- package/build/lib/runtime/evidence_query.py +56 -4
- package/build/lib/runtime/evidence_registry.py +16 -0
- package/build/lib/runtime/evidence_requirements.py +47 -0
- package/build/lib/runtime/forge_agents.py +179 -9
- package/build/lib/runtime/forge_contracts.py +208 -2
- package/build/lib/runtime/interaction_journal.py +318 -42
- package/build/lib/runtime/memory_store.py +134 -1
- package/build/lib/runtime/mutation_gate.py +57 -11
- package/build/lib/runtime/omg_compat_contract_snapshot.json +2 -2
- package/build/lib/runtime/omg_mcp_server.py +14 -4
- package/build/lib/runtime/preflight.py +14 -0
- package/build/lib/runtime/profile_io.py +294 -0
- package/build/lib/runtime/proof_gate.py +122 -7
- package/build/lib/runtime/release_run_coordinator.py +339 -0
- package/build/lib/runtime/release_surfaces.py +243 -0
- package/build/lib/runtime/rollback_manifest.py +136 -0
- package/build/lib/runtime/router_critics.py +50 -0
- package/build/lib/runtime/runtime_contracts.py +137 -0
- package/build/lib/runtime/security_check.py +16 -0
- package/build/lib/runtime/session_health.py +60 -16
- package/build/lib/runtime/team_router.py +156 -13
- package/build/lib/runtime/test_intent_lock.py +102 -0
- package/build/lib/runtime/tool_plan_gate.py +249 -24
- package/build/lib/runtime/validate.py +194 -0
- package/build/lib/runtime/verification_controller.py +52 -2
- package/commands/OMG:diagnose-plugins.md +33 -0
- package/commands/OMG:profile-review.md +43 -0
- package/commands/OMG:setup.md +4 -1
- package/commands/OMG:validate.md +59 -0
- package/control_plane/service.py +40 -1
- package/dist/enterprise/bundle/.claude-plugin/marketplace.json +3 -3
- package/dist/enterprise/bundle/.claude-plugin/plugin.json +1 -1
- package/dist/enterprise/bundle/OMG_COMPAT_CONTRACT.md +1 -1
- package/dist/enterprise/bundle/plugins/advanced/plugin.json +26 -9
- package/dist/enterprise/bundle/registry/bundles/algorithms.yaml +1 -1
- package/dist/enterprise/bundle/registry/bundles/api-twin.yaml +1 -1
- package/dist/enterprise/bundle/registry/bundles/claim-judge.yaml +1 -1
- package/dist/enterprise/bundle/registry/bundles/control-plane.yaml +1 -1
- package/dist/enterprise/bundle/registry/bundles/data-lineage.yaml +1 -1
- package/dist/enterprise/bundle/registry/bundles/delta-classifier.yaml +1 -1
- package/dist/enterprise/bundle/registry/bundles/eval-gate.yaml +1 -1
- package/dist/enterprise/bundle/registry/bundles/health.yaml +1 -1
- package/dist/enterprise/bundle/registry/bundles/hook-governor.yaml +1 -1
- package/dist/enterprise/bundle/registry/bundles/incident-replay.yaml +1 -1
- package/dist/enterprise/bundle/registry/bundles/lsp-pack.yaml +1 -1
- package/dist/enterprise/bundle/registry/bundles/mcp-fabric.yaml +1 -1
- package/dist/enterprise/bundle/registry/bundles/plan-council.yaml +1 -1
- package/dist/enterprise/bundle/registry/bundles/preflight.yaml +1 -1
- package/dist/enterprise/bundle/registry/bundles/proof-gate.yaml +1 -1
- package/dist/enterprise/bundle/registry/bundles/remote-supervisor.yaml +1 -1
- package/dist/enterprise/bundle/registry/bundles/robotics.yaml +1 -1
- package/dist/enterprise/bundle/registry/bundles/secure-worktree-pipeline.yaml +1 -1
- package/dist/enterprise/bundle/registry/bundles/security-check.yaml +1 -1
- package/dist/enterprise/bundle/registry/bundles/test-intent-lock.yaml +1 -1
- package/dist/enterprise/bundle/registry/bundles/tracebank.yaml +1 -1
- package/dist/enterprise/bundle/registry/bundles/vision.yaml +1 -1
- package/dist/enterprise/bundle/registry/omg-capability.schema.json +1 -1
- package/dist/enterprise/bundle/settings.json +3 -3
- package/dist/enterprise/manifest.json +30 -40
- package/dist/oh_my_god-2.1.4-py3-none-any.whl +0 -0
- package/dist/oh_my_god-2.1.4.tar.gz +0 -0
- package/dist/public/bundle/.claude-plugin/marketplace.json +3 -3
- package/dist/public/bundle/.claude-plugin/plugin.json +1 -1
- package/dist/public/bundle/OMG_COMPAT_CONTRACT.md +1 -1
- package/dist/public/bundle/plugins/advanced/plugin.json +26 -9
- package/dist/public/bundle/registry/bundles/algorithms.yaml +1 -1
- package/dist/public/bundle/registry/bundles/api-twin.yaml +1 -1
- package/dist/public/bundle/registry/bundles/claim-judge.yaml +1 -1
- package/dist/public/bundle/registry/bundles/control-plane.yaml +1 -1
- package/dist/public/bundle/registry/bundles/data-lineage.yaml +1 -1
- package/dist/public/bundle/registry/bundles/delta-classifier.yaml +1 -1
- package/dist/public/bundle/registry/bundles/eval-gate.yaml +1 -1
- package/dist/public/bundle/registry/bundles/health.yaml +1 -1
- package/dist/public/bundle/registry/bundles/hook-governor.yaml +1 -1
- package/dist/public/bundle/registry/bundles/incident-replay.yaml +1 -1
- package/dist/public/bundle/registry/bundles/lsp-pack.yaml +1 -1
- package/dist/public/bundle/registry/bundles/mcp-fabric.yaml +1 -1
- package/dist/public/bundle/registry/bundles/plan-council.yaml +1 -1
- package/dist/public/bundle/registry/bundles/preflight.yaml +1 -1
- package/dist/public/bundle/registry/bundles/proof-gate.yaml +1 -1
- package/dist/public/bundle/registry/bundles/remote-supervisor.yaml +1 -1
- package/dist/public/bundle/registry/bundles/robotics.yaml +1 -1
- package/dist/public/bundle/registry/bundles/secure-worktree-pipeline.yaml +1 -1
- package/dist/public/bundle/registry/bundles/security-check.yaml +1 -1
- package/dist/public/bundle/registry/bundles/test-intent-lock.yaml +1 -1
- package/dist/public/bundle/registry/bundles/tracebank.yaml +1 -1
- package/dist/public/bundle/registry/bundles/vision.yaml +1 -1
- package/dist/public/bundle/registry/omg-capability.schema.json +1 -1
- package/dist/public/bundle/settings.json +3 -3
- package/dist/public/manifest.json +30 -40
- package/docs/install/opencode.md +30 -0
- package/docs/proof.md +11 -0
- package/docs/release-checklist.md +14 -1
- package/hooks/_agent_registry.py +2 -0
- package/hooks/firewall.py +263 -4
- package/hooks/intentgate-keyword-detector.py +15 -3
- package/hooks/policy_engine.py +77 -0
- package/hooks/prompt-enhancer.py +146 -0
- package/hooks/session-end-capture.py +374 -6
- package/hooks/session-start.py +13 -35
- package/hooks/setup_wizard.py +342 -2
- package/hooks/shadow_manager.py +111 -2
- package/hooks/stop_dispatcher.py +108 -4
- package/hud/omg-hud.mjs +30 -6
- package/lab/pipeline.py +197 -26
- package/package.json +1 -1
- package/plugins/advanced/plugin.json +26 -9
- package/plugins/core/plugin.json +51 -12
- package/pyproject.toml +10 -2
- package/registry/bundles/algorithms.yaml +1 -1
- package/registry/bundles/api-twin.yaml +1 -1
- package/registry/bundles/claim-judge.yaml +1 -1
- package/registry/bundles/control-plane.yaml +1 -1
- package/registry/bundles/data-lineage.yaml +1 -1
- package/registry/bundles/delta-classifier.yaml +1 -1
- package/registry/bundles/eval-gate.yaml +1 -1
- package/registry/bundles/health.yaml +1 -1
- package/registry/bundles/hook-governor.yaml +1 -1
- package/registry/bundles/incident-replay.yaml +1 -1
- package/registry/bundles/lsp-pack.yaml +1 -1
- package/registry/bundles/mcp-fabric.yaml +1 -1
- package/registry/bundles/plan-council.yaml +1 -1
- package/registry/bundles/preflight.yaml +1 -1
- package/registry/bundles/proof-gate.yaml +1 -1
- package/registry/bundles/remote-supervisor.yaml +1 -1
- package/registry/bundles/robotics.yaml +1 -1
- package/registry/bundles/secure-worktree-pipeline.yaml +1 -1
- package/registry/bundles/security-check.yaml +1 -1
- package/registry/bundles/test-intent-lock.yaml +1 -1
- package/registry/bundles/tracebank.yaml +1 -1
- package/registry/bundles/vision.yaml +1 -1
- package/registry/omg-capability.schema.json +1 -1
- package/runtime/adoption.py +7 -5
- package/runtime/background_verification.py +62 -0
- package/runtime/claim_judge.py +165 -5
- package/runtime/compat.py +48 -1
- package/runtime/context_engine.py +261 -4
- package/runtime/contract_compiler.py +370 -93
- package/runtime/defense_state.py +79 -8
- package/runtime/delta_classifier.py +80 -2
- package/runtime/evidence_query.py +56 -4
- package/runtime/evidence_registry.py +16 -0
- package/runtime/evidence_requirements.py +47 -0
- package/runtime/forge_agents.py +179 -9
- package/runtime/forge_contracts.py +208 -2
- package/runtime/hook_governor.py +19 -1
- package/runtime/interaction_journal.py +318 -42
- package/runtime/memory_store.py +134 -1
- package/runtime/mutation_gate.py +57 -11
- package/runtime/omg_compat_contract_snapshot.json +2 -2
- package/runtime/omg_mcp_server.py +14 -4
- package/runtime/plugin_diagnostics.py +248 -0
- package/runtime/plugin_interop.py +1007 -0
- package/runtime/preflight.py +14 -0
- package/runtime/profile_io.py +294 -0
- package/runtime/proof_gate.py +122 -7
- package/runtime/providers/opencode_provider.py +94 -0
- package/runtime/release_run_coordinator.py +339 -0
- package/runtime/release_surfaces.py +243 -0
- package/runtime/rollback_manifest.py +136 -0
- package/runtime/router_critics.py +50 -0
- package/runtime/runtime_contracts.py +137 -0
- package/runtime/security_check.py +16 -0
- package/runtime/session_health.py +60 -16
- package/runtime/team_router.py +156 -13
- package/runtime/test_intent_lock.py +102 -0
- package/runtime/tool_plan_gate.py +218 -19
- package/runtime/validate.py +289 -0
- package/runtime/verification_controller.py +52 -2
- package/scripts/omg.py +306 -3
- package/scripts/prepare-release-proof-fixtures.py +191 -7
- package/scripts/print-canonical-version.py +80 -0
- package/scripts/sync-release-identity.py +476 -0
- package/scripts/validate-release-identity.py +246 -0
- package/scripts/verify-standalone.sh +3 -0
- package/settings.json +3 -3
- package/templates/plugins-allowlist.yaml +19 -0
- package/artifacts/release/dist/enterprise/bundle/.gemini/settings.json +0 -11
- package/artifacts/release/dist/enterprise/bundle/.kimi/mcp.json +0 -11
- package/artifacts/release/dist/public/bundle/.gemini/settings.json +0 -11
- package/artifacts/release/dist/public/bundle/.kimi/mcp.json +0 -11
- package/build/lib/yaml.py +0 -321
- package/dist/enterprise/bundle/.gemini/settings.json +0 -11
- package/dist/enterprise/bundle/.kimi/mcp.json +0 -11
- package/dist/public/bundle/.gemini/settings.json +0 -11
- package/dist/public/bundle/.kimi/mcp.json +0 -11
|
@@ -8,6 +8,10 @@ from uuid import uuid4
|
|
|
8
8
|
|
|
9
9
|
import json
|
|
10
10
|
|
|
11
|
+
from runtime.context_engine import ContextEngine
|
|
12
|
+
from runtime.release_run_coordinator import resolve_current_run_id as resolve_coordinator_run_id
|
|
13
|
+
from runtime.runtime_contracts import read_run_state
|
|
14
|
+
|
|
11
15
|
|
|
12
16
|
_TOOL_KEYWORDS: dict[str, tuple[str, ...]] = {
|
|
13
17
|
"context7": ("doc", "docs", "documentation", "library", "api reference", "reference"),
|
|
@@ -16,22 +20,44 @@ _TOOL_KEYWORDS: dict[str, tuple[str, ...]] = {
|
|
|
16
20
|
"omg-control": ("policy", "governance", "release", "proof", "control plane"),
|
|
17
21
|
}
|
|
18
22
|
|
|
23
|
+
_READ_ONLY_TOOL_HINTS = (
|
|
24
|
+
"read",
|
|
25
|
+
"search",
|
|
26
|
+
"review",
|
|
27
|
+
"grep",
|
|
28
|
+
"glob",
|
|
29
|
+
"list",
|
|
30
|
+
"ls",
|
|
31
|
+
"context7",
|
|
32
|
+
"websearch",
|
|
33
|
+
)
|
|
34
|
+
_MUTATION_TOOLS = frozenset({"write", "edit", "multiedit", "bash"})
|
|
35
|
+
|
|
19
36
|
|
|
20
37
|
def build_tool_plan(
|
|
21
38
|
goal: str,
|
|
22
39
|
available_tools: list[str],
|
|
23
40
|
context_packet: dict[str, object] | None = None,
|
|
41
|
+
run_id: str | None = None,
|
|
24
42
|
) -> dict[str, object]:
|
|
25
43
|
normalized_goal = str(goal or "").strip()
|
|
26
44
|
normalized_tools = _normalize_tools(available_tools)
|
|
27
|
-
|
|
45
|
+
canonical_run_id = run_id or resolve_current_run_id(project_dir=None)
|
|
46
|
+
bounded_context = _resolve_bounded_context_packet(
|
|
47
|
+
project_dir=str(_project_dir()),
|
|
48
|
+
run_id=canonical_run_id,
|
|
49
|
+
fallback_context=context_packet,
|
|
50
|
+
)
|
|
51
|
+
council = _read_council_verdicts(str(_project_dir()), canonical_run_id)
|
|
52
|
+
|
|
53
|
+
project_dir = _project_dir()
|
|
28
54
|
selected_tools: list[dict[str, object]] = []
|
|
29
55
|
for tool_name in normalized_tools:
|
|
30
56
|
if _is_tool_needed(tool_name, normalized_goal):
|
|
31
57
|
selected_tools.append(
|
|
32
58
|
{
|
|
33
59
|
"name": tool_name,
|
|
34
|
-
"args": _default_args(tool_name, normalized_goal,
|
|
60
|
+
"args": _default_args(tool_name, normalized_goal, bounded_context, project_dir=project_dir),
|
|
35
61
|
"rationale": _rationale(tool_name),
|
|
36
62
|
}
|
|
37
63
|
)
|
|
@@ -41,43 +67,34 @@ def build_tool_plan(
|
|
|
41
67
|
selected_tools.append(
|
|
42
68
|
{
|
|
43
69
|
"name": fallback,
|
|
44
|
-
"args": _default_args(fallback, normalized_goal,
|
|
70
|
+
"args": _default_args(fallback, normalized_goal, bounded_context, project_dir=project_dir),
|
|
45
71
|
"rationale": "fallback: no explicit keyword match; keep single minimal tool",
|
|
46
72
|
}
|
|
47
73
|
)
|
|
48
74
|
|
|
49
|
-
|
|
50
|
-
plan_id = _new_plan_id(run_id=
|
|
75
|
+
selected_tools = _apply_context_optimization(selected_tools, bounded_context, council)
|
|
76
|
+
plan_id = _new_plan_id(run_id=canonical_run_id)
|
|
51
77
|
payload: dict[str, object] = {
|
|
52
78
|
"plan_id": plan_id,
|
|
53
79
|
"goal": normalized_goal,
|
|
54
80
|
"tools": selected_tools,
|
|
55
81
|
"budget_estimate": {
|
|
56
82
|
"estimated_calls": len(selected_tools),
|
|
57
|
-
"estimated_context_chars": _estimate_context_chars(
|
|
83
|
+
"estimated_context_chars": _estimate_context_chars(bounded_context),
|
|
58
84
|
"goal_complexity": _goal_complexity(normalized_goal),
|
|
59
85
|
},
|
|
60
|
-
"
|
|
86
|
+
"context_packet": bounded_context,
|
|
87
|
+
"council_verdicts": council.get("verdicts", {}),
|
|
88
|
+
"run_id": canonical_run_id,
|
|
61
89
|
"created_at": datetime.now(timezone.utc).isoformat(),
|
|
62
90
|
}
|
|
63
|
-
_persist_plan(
|
|
91
|
+
_persist_plan(project_dir, plan_id, payload)
|
|
64
92
|
return payload
|
|
65
93
|
|
|
66
94
|
|
|
67
95
|
def resolve_current_run_id(project_dir: str | None = None) -> str | None:
|
|
68
|
-
run_id =
|
|
69
|
-
|
|
70
|
-
return run_id
|
|
71
|
-
|
|
72
|
-
root = _project_dir(project_dir)
|
|
73
|
-
active_run = root / ".omg" / "shadow" / "active-run"
|
|
74
|
-
if not active_run.exists():
|
|
75
|
-
return None
|
|
76
|
-
try:
|
|
77
|
-
value = active_run.read_text(encoding="utf-8").strip()
|
|
78
|
-
except OSError:
|
|
79
|
-
return None
|
|
80
|
-
return value or None
|
|
96
|
+
run_id = resolve_coordinator_run_id(project_dir=project_dir)
|
|
97
|
+
return run_id or None
|
|
81
98
|
|
|
82
99
|
|
|
83
100
|
def has_tool_plan_for_run(project_dir: str, run_id: str | None) -> bool:
|
|
@@ -93,7 +110,45 @@ def has_tool_plan_for_run(project_dir: str, run_id: str | None) -> bool:
|
|
|
93
110
|
def tool_plan_gate_check(project_dir: str, run_id: str | None, tool: str) -> dict[str, object]:
|
|
94
111
|
if not run_id:
|
|
95
112
|
return {"status": "allowed", "reason": "run_id unavailable; skip tool plan gate"}
|
|
113
|
+
|
|
114
|
+
context_packet = _resolve_bounded_context_packet(
|
|
115
|
+
project_dir=project_dir,
|
|
116
|
+
run_id=run_id,
|
|
117
|
+
fallback_context=None,
|
|
118
|
+
)
|
|
119
|
+
clarification = _clarification_status(context_packet)
|
|
120
|
+
if clarification["requires_clarification"]:
|
|
121
|
+
reason = _clarification_reason(str(clarification["clarification_prompt"]))
|
|
122
|
+
if _is_mutation_capable_tool(tool):
|
|
123
|
+
_persist_gate_error(project_dir, run_id, tool, reason)
|
|
124
|
+
return {
|
|
125
|
+
"status": "blocked",
|
|
126
|
+
"reason": reason,
|
|
127
|
+
"run_id": run_id,
|
|
128
|
+
"tool": tool,
|
|
129
|
+
"clarification_status": clarification,
|
|
130
|
+
}
|
|
131
|
+
if _is_read_search_review_tool(tool):
|
|
132
|
+
return {
|
|
133
|
+
"status": "allowed",
|
|
134
|
+
"reason": "clarification pending; read/search/review tool allowed",
|
|
135
|
+
"run_id": run_id,
|
|
136
|
+
"clarification_status": clarification,
|
|
137
|
+
}
|
|
138
|
+
|
|
96
139
|
if has_tool_plan_for_run(project_dir, run_id):
|
|
140
|
+
council = _read_council_verdicts(project_dir, run_id)
|
|
141
|
+
verdict = _council_gate_verdict(council)
|
|
142
|
+
if verdict["blocked"]:
|
|
143
|
+
reason = str(verdict["reason"])
|
|
144
|
+
_persist_gate_error(project_dir, run_id, tool, reason)
|
|
145
|
+
return {
|
|
146
|
+
"status": "blocked",
|
|
147
|
+
"reason": reason,
|
|
148
|
+
"run_id": run_id,
|
|
149
|
+
"tool": tool,
|
|
150
|
+
"council_verdicts": council.get("verdicts", {}),
|
|
151
|
+
}
|
|
97
152
|
return {"status": "allowed", "reason": "tool plan present", "run_id": run_id}
|
|
98
153
|
|
|
99
154
|
reason = "tool plan required before mutation-capable MCP evaluation"
|
|
@@ -120,7 +175,15 @@ def _is_tool_needed(tool_name: str, goal: str) -> bool:
|
|
|
120
175
|
return any(token in lowered_goal for token in keywords)
|
|
121
176
|
|
|
122
177
|
|
|
123
|
-
def _default_args(
|
|
178
|
+
def _default_args(
|
|
179
|
+
tool_name: str,
|
|
180
|
+
goal: str,
|
|
181
|
+
context_packet: dict[str, object] | None,
|
|
182
|
+
*,
|
|
183
|
+
project_dir: Path,
|
|
184
|
+
) -> dict[str, object]:
|
|
185
|
+
token = tool_name.strip().lower()
|
|
186
|
+
|
|
124
187
|
if tool_name == "context7":
|
|
125
188
|
return {"query": goal}
|
|
126
189
|
if tool_name == "websearch":
|
|
@@ -130,6 +193,23 @@ def _default_args(tool_name: str, goal: str, context_packet: dict[str, object] |
|
|
|
130
193
|
if tool_name == "omg-control":
|
|
131
194
|
return {"query": goal}
|
|
132
195
|
|
|
196
|
+
if token in {"todowrite", "proxy_todowrite"}:
|
|
197
|
+
content = goal.strip()[:120] or "Track current task"
|
|
198
|
+
return {
|
|
199
|
+
"todos": [
|
|
200
|
+
{
|
|
201
|
+
"content": content,
|
|
202
|
+
"status": "in_progress",
|
|
203
|
+
"priority": "medium",
|
|
204
|
+
}
|
|
205
|
+
]
|
|
206
|
+
}
|
|
207
|
+
if token in {"read", "proxy_read"}:
|
|
208
|
+
default_target = project_dir / "README.md"
|
|
209
|
+
if not default_target.exists():
|
|
210
|
+
default_target = project_dir
|
|
211
|
+
return {"filePath": str(default_target)}
|
|
212
|
+
|
|
133
213
|
context_hint = ""
|
|
134
214
|
if isinstance(context_packet, dict):
|
|
135
215
|
context_hint = str(context_packet.get("summary", ""))[:120]
|
|
@@ -166,8 +246,8 @@ def _new_plan_id(run_id: str | None) -> str:
|
|
|
166
246
|
|
|
167
247
|
def _project_dir(project_dir: str | None = None) -> Path:
|
|
168
248
|
if project_dir:
|
|
169
|
-
return Path(project_dir)
|
|
170
|
-
return Path(os.environ.get("CLAUDE_PROJECT_DIR", os.getcwd()))
|
|
249
|
+
return Path(project_dir).resolve()
|
|
250
|
+
return Path(os.environ.get("CLAUDE_PROJECT_DIR", os.getcwd())).resolve()
|
|
171
251
|
|
|
172
252
|
|
|
173
253
|
def _persist_plan(project_dir: Path, plan_id: str, payload: dict[str, object]) -> None:
|
|
@@ -197,7 +277,152 @@ def _atomic_write_json(path: Path, payload: Mapping[str, object]) -> None:
|
|
|
197
277
|
_ = os.replace(temp_path, path)
|
|
198
278
|
|
|
199
279
|
|
|
280
|
+
def journal_mutation_bash(
|
|
281
|
+
project_dir: str,
|
|
282
|
+
command: str,
|
|
283
|
+
run_id: str | None = None,
|
|
284
|
+
metadata: dict[str, object] | None = None,
|
|
285
|
+
) -> dict[str, object] | None:
|
|
286
|
+
try:
|
|
287
|
+
from runtime.interaction_journal import InteractionJournal
|
|
288
|
+
from runtime.rollback_manifest import classify_side_effect
|
|
289
|
+
except ImportError:
|
|
290
|
+
return None
|
|
291
|
+
|
|
292
|
+
canonical_run_id = run_id or resolve_current_run_id(project_dir)
|
|
293
|
+
if not canonical_run_id:
|
|
294
|
+
return None
|
|
295
|
+
|
|
296
|
+
meta: dict[str, object] = dict(metadata or {})
|
|
297
|
+
meta["command"] = command
|
|
298
|
+
meta["run_id"] = canonical_run_id
|
|
299
|
+
|
|
300
|
+
side_effect = classify_side_effect("bash", meta)
|
|
301
|
+
meta["side_effect_scope"] = str(side_effect.get("category", "unknown"))
|
|
302
|
+
meta["side_effect_classification"] = side_effect
|
|
303
|
+
|
|
304
|
+
journal = InteractionJournal(project_dir)
|
|
305
|
+
return journal.record_step("bash", meta)
|
|
306
|
+
|
|
307
|
+
|
|
200
308
|
def _safe_token(value: str) -> str:
|
|
201
309
|
chars = [ch if ch.isalnum() or ch in {"-", "_"} else "-" for ch in value.strip()]
|
|
202
310
|
token = "".join(chars).strip("-")
|
|
203
311
|
return token or "run"
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
def _resolve_bounded_context_packet(
|
|
315
|
+
*,
|
|
316
|
+
project_dir: str,
|
|
317
|
+
run_id: str | None,
|
|
318
|
+
fallback_context: dict[str, object] | None,
|
|
319
|
+
) -> dict[str, object]:
|
|
320
|
+
if run_id:
|
|
321
|
+
packet = ContextEngine(project_dir).build_packet(run_id=run_id, delta_only=True)
|
|
322
|
+
if isinstance(fallback_context, dict) and str(fallback_context.get("summary", "")).strip():
|
|
323
|
+
summary = str(packet.get("summary", "")).strip()
|
|
324
|
+
if not summary or summary == "no context signals available":
|
|
325
|
+
packet["summary"] = str(fallback_context.get("summary", ""))
|
|
326
|
+
return packet
|
|
327
|
+
return dict(fallback_context or {"summary": "", "artifact_pointers": []})
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
def _read_council_verdicts(project_dir: str, run_id: str | None) -> dict[str, object]:
|
|
331
|
+
if not run_id:
|
|
332
|
+
return {}
|
|
333
|
+
payload = read_run_state(project_dir, "council_verdicts", run_id)
|
|
334
|
+
if isinstance(payload, dict):
|
|
335
|
+
return dict(payload)
|
|
336
|
+
return {}
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
def _council_gate_verdict(council: dict[str, object]) -> dict[str, object]:
|
|
340
|
+
verdicts = council.get("verdicts")
|
|
341
|
+
if not isinstance(verdicts, dict):
|
|
342
|
+
return {"blocked": False, "reason": ""}
|
|
343
|
+
|
|
344
|
+
for critic_name, critic_payload in verdicts.items():
|
|
345
|
+
if not isinstance(critic_payload, dict):
|
|
346
|
+
continue
|
|
347
|
+
token = str(critic_payload.get("verdict", "")).strip().lower()
|
|
348
|
+
if token == "fail":
|
|
349
|
+
return {
|
|
350
|
+
"blocked": True,
|
|
351
|
+
"reason": f"council critic '{critic_name}' failed; block mutation-capable tool execution",
|
|
352
|
+
}
|
|
353
|
+
return {"blocked": False, "reason": ""}
|
|
354
|
+
|
|
355
|
+
|
|
356
|
+
def _apply_context_optimization(
|
|
357
|
+
tools: list[dict[str, object]],
|
|
358
|
+
context_packet: dict[str, object],
|
|
359
|
+
council: dict[str, object],
|
|
360
|
+
) -> list[dict[str, object]]:
|
|
361
|
+
if len(tools) <= 1:
|
|
362
|
+
return tools
|
|
363
|
+
|
|
364
|
+
budget = context_packet.get("budget")
|
|
365
|
+
used_chars = 0
|
|
366
|
+
max_chars = 0
|
|
367
|
+
if isinstance(budget, dict):
|
|
368
|
+
try:
|
|
369
|
+
used_chars = int(budget.get("used_chars", 0))
|
|
370
|
+
max_chars = int(budget.get("max_chars", 0))
|
|
371
|
+
except (TypeError, ValueError):
|
|
372
|
+
used_chars = 0
|
|
373
|
+
max_chars = 0
|
|
374
|
+
|
|
375
|
+
verdicts = council.get("verdicts")
|
|
376
|
+
evidence_warn = False
|
|
377
|
+
if isinstance(verdicts, dict):
|
|
378
|
+
evidence = verdicts.get("evidence_completeness")
|
|
379
|
+
if isinstance(evidence, dict):
|
|
380
|
+
evidence_warn = str(evidence.get("verdict", "")).strip().lower() in {"warn", "fail"}
|
|
381
|
+
|
|
382
|
+
pressure_high = max_chars > 0 and used_chars >= int(max_chars * 0.9)
|
|
383
|
+
if pressure_high or evidence_warn:
|
|
384
|
+
return tools[:1]
|
|
385
|
+
return tools
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
def _clarification_status(context_packet: dict[str, object]) -> dict[str, object]:
|
|
389
|
+
raw = context_packet.get("clarification_status")
|
|
390
|
+
if not isinstance(raw, dict):
|
|
391
|
+
return {
|
|
392
|
+
"requires_clarification": False,
|
|
393
|
+
"intent_class": "",
|
|
394
|
+
"clarification_prompt": "",
|
|
395
|
+
"confidence": 0.0,
|
|
396
|
+
}
|
|
397
|
+
prompt = str(raw.get("clarification_prompt", "")).strip().replace("\n", " ")
|
|
398
|
+
try:
|
|
399
|
+
confidence = float(raw.get("confidence", 0.0))
|
|
400
|
+
except (TypeError, ValueError):
|
|
401
|
+
confidence = 0.0
|
|
402
|
+
return {
|
|
403
|
+
"requires_clarification": bool(raw.get("requires_clarification") is True),
|
|
404
|
+
"intent_class": str(raw.get("intent_class", "")).strip(),
|
|
405
|
+
"clarification_prompt": prompt,
|
|
406
|
+
"confidence": round(max(0.0, min(1.0, confidence)), 2),
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
|
|
410
|
+
def _clarification_reason(clarification_prompt: str) -> str:
|
|
411
|
+
prompt = " ".join(str(clarification_prompt or "").split())
|
|
412
|
+
if prompt:
|
|
413
|
+
return f"Clarification required before mutation: {prompt}"
|
|
414
|
+
return "Clarification required before mutation: provide the missing intent details."
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
def _is_mutation_capable_tool(tool: str) -> bool:
|
|
418
|
+
token = str(tool or "").strip().lower()
|
|
419
|
+
if token in _MUTATION_TOOLS:
|
|
420
|
+
return True
|
|
421
|
+
return token.startswith("bash:")
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
def _is_read_search_review_tool(tool: str) -> bool:
|
|
425
|
+
token = str(tool or "").strip().lower()
|
|
426
|
+
if not token:
|
|
427
|
+
return False
|
|
428
|
+
return any(hint in token for hint in _READ_ONLY_TOOL_HINTS)
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
"""Canonical validation engine — composes doctor, contract, profile, and install checks.
|
|
2
|
+
|
|
3
|
+
This module is the single entrypoint for ``omg validate``. It delegates to
|
|
4
|
+
existing checkers (``run_doctor``, ``validate_contract_registry``, profile
|
|
5
|
+
governor, install integrity) rather than duplicating their logic.
|
|
6
|
+
"""
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import os
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import Any
|
|
12
|
+
|
|
13
|
+
from runtime.adoption import CANONICAL_VERSION
|
|
14
|
+
from runtime.compat import run_doctor, _doctor_check
|
|
15
|
+
from runtime.contract_compiler import validate_contract_registry
|
|
16
|
+
from runtime.profile_io import load_profile, ensure_governed_preferences
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _check_contract_registry(root_dir: Path) -> dict[str, Any]:
|
|
20
|
+
"""Compose contract registry validation into a single doctor-style check."""
|
|
21
|
+
try:
|
|
22
|
+
result = validate_contract_registry(root_dir)
|
|
23
|
+
except Exception as exc:
|
|
24
|
+
return _doctor_check(
|
|
25
|
+
"contract_registry",
|
|
26
|
+
ok=False,
|
|
27
|
+
message=f"contract validation error: {exc}",
|
|
28
|
+
)
|
|
29
|
+
if result.get("status") == "ok":
|
|
30
|
+
error_count = len(result.get("errors", []))
|
|
31
|
+
return _doctor_check(
|
|
32
|
+
"contract_registry",
|
|
33
|
+
ok=True,
|
|
34
|
+
message=f"contract registry valid ({error_count} errors)",
|
|
35
|
+
)
|
|
36
|
+
errors = result.get("errors", [])
|
|
37
|
+
summary = errors[0] if errors else "unknown error"
|
|
38
|
+
if len(errors) > 1:
|
|
39
|
+
summary += f" (+{len(errors) - 1} more)"
|
|
40
|
+
return _doctor_check(
|
|
41
|
+
"contract_registry",
|
|
42
|
+
ok=False,
|
|
43
|
+
message=f"contract registry invalid: {summary}",
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _check_profile_governor(root_dir: Path) -> dict[str, Any]:
|
|
48
|
+
"""Validate that governed profile state is consistent."""
|
|
49
|
+
profile_path = os.path.join(root_dir, ".omg", "state", "profile.yaml")
|
|
50
|
+
profile = load_profile(profile_path)
|
|
51
|
+
|
|
52
|
+
if not profile:
|
|
53
|
+
return _doctor_check(
|
|
54
|
+
"profile_governor",
|
|
55
|
+
ok=True,
|
|
56
|
+
message="no profile found (optional — run /OMG:init to create)",
|
|
57
|
+
required=False,
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
try:
|
|
61
|
+
ensure_governed_preferences(profile)
|
|
62
|
+
except Exception as exc:
|
|
63
|
+
return _doctor_check(
|
|
64
|
+
"profile_governor",
|
|
65
|
+
ok=False,
|
|
66
|
+
message=f"governed preferences malformed: {exc}",
|
|
67
|
+
required=False,
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
governed = profile.get("governed_preferences", {})
|
|
71
|
+
governed = governed if isinstance(governed, dict) else {}
|
|
72
|
+
style_entries = governed.get("style", [])
|
|
73
|
+
style_entries = style_entries if isinstance(style_entries, list) else []
|
|
74
|
+
safety_entries = governed.get("safety", [])
|
|
75
|
+
safety_entries = safety_entries if isinstance(safety_entries, list) else []
|
|
76
|
+
|
|
77
|
+
pending = sum(
|
|
78
|
+
1 for e in style_entries + safety_entries
|
|
79
|
+
if isinstance(e, dict) and e.get("confirmation_state") == "pending_confirmation"
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
parts = [f"{len(style_entries)} style, {len(safety_entries)} safety"]
|
|
83
|
+
if pending:
|
|
84
|
+
parts.append(f"{pending} pending confirmation")
|
|
85
|
+
|
|
86
|
+
return _doctor_check(
|
|
87
|
+
"profile_governor",
|
|
88
|
+
ok=True,
|
|
89
|
+
message=f"profile governor ok ({', '.join(parts)})",
|
|
90
|
+
required=False,
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def _check_install_integrity(root_dir: Path) -> dict[str, Any]:
|
|
95
|
+
"""Verify critical install paths exist and are coherent."""
|
|
96
|
+
issues: list[str] = []
|
|
97
|
+
|
|
98
|
+
# Check scripts/omg.py exists
|
|
99
|
+
omg_script = root_dir / "scripts" / "omg.py"
|
|
100
|
+
if not omg_script.exists():
|
|
101
|
+
issues.append("scripts/omg.py missing")
|
|
102
|
+
|
|
103
|
+
# Check runtime/ package exists
|
|
104
|
+
runtime_init = root_dir / "runtime" / "__init__.py"
|
|
105
|
+
runtime_dir = root_dir / "runtime"
|
|
106
|
+
if not runtime_dir.exists():
|
|
107
|
+
issues.append("runtime/ directory missing")
|
|
108
|
+
|
|
109
|
+
# Check commands/ directory exists
|
|
110
|
+
commands_dir = root_dir / "commands"
|
|
111
|
+
if not commands_dir.exists():
|
|
112
|
+
issues.append("commands/ directory missing")
|
|
113
|
+
|
|
114
|
+
# Check plugins/core/plugin.json exists
|
|
115
|
+
plugin_json = root_dir / "plugins" / "core" / "plugin.json"
|
|
116
|
+
if not plugin_json.exists():
|
|
117
|
+
issues.append("plugins/core/plugin.json missing")
|
|
118
|
+
|
|
119
|
+
# Check pyproject.toml exists
|
|
120
|
+
pyproject = root_dir / "pyproject.toml"
|
|
121
|
+
if not pyproject.exists():
|
|
122
|
+
issues.append("pyproject.toml missing")
|
|
123
|
+
|
|
124
|
+
if issues:
|
|
125
|
+
return _doctor_check(
|
|
126
|
+
"install_integrity",
|
|
127
|
+
ok=False,
|
|
128
|
+
message=f"install issues: {'; '.join(issues)}",
|
|
129
|
+
)
|
|
130
|
+
return _doctor_check(
|
|
131
|
+
"install_integrity",
|
|
132
|
+
ok=True,
|
|
133
|
+
message="install integrity ok (scripts, runtime, commands, plugins present)",
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def run_validate(*, root_dir: Path | None = None) -> dict[str, Any]:
|
|
138
|
+
"""Run all validation checks and return a structured result.
|
|
139
|
+
|
|
140
|
+
Composes:
|
|
141
|
+
1. ``run_doctor()`` — install and runtime checks
|
|
142
|
+
2. Contract registry validation
|
|
143
|
+
3. Profile governor validation
|
|
144
|
+
4. Install integrity check
|
|
145
|
+
|
|
146
|
+
Returns a dict matching the ``ValidateResult`` schema:
|
|
147
|
+
``{"schema": "ValidateResult", "status": "pass"|"fail", "checks": [...], "version": "..."}``
|
|
148
|
+
"""
|
|
149
|
+
repo_root = root_dir or Path(__file__).resolve().parent.parent
|
|
150
|
+
|
|
151
|
+
checks: list[dict[str, Any]] = []
|
|
152
|
+
|
|
153
|
+
# 1. Compose doctor checks (never duplicate — delegate directly)
|
|
154
|
+
doctor_result = run_doctor(root_dir=repo_root)
|
|
155
|
+
checks.extend(doctor_result.get("checks", []))
|
|
156
|
+
|
|
157
|
+
# 2. Contract registry
|
|
158
|
+
checks.append(_check_contract_registry(repo_root))
|
|
159
|
+
|
|
160
|
+
# 3. Profile governor
|
|
161
|
+
checks.append(_check_profile_governor(repo_root))
|
|
162
|
+
|
|
163
|
+
# 4. Install integrity
|
|
164
|
+
checks.append(_check_install_integrity(repo_root))
|
|
165
|
+
|
|
166
|
+
has_blocker = any(c["status"] == "blocker" for c in checks)
|
|
167
|
+
|
|
168
|
+
return {
|
|
169
|
+
"schema": "ValidateResult",
|
|
170
|
+
"status": "fail" if has_blocker else "pass",
|
|
171
|
+
"checks": checks,
|
|
172
|
+
"version": CANONICAL_VERSION,
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def format_text(result: dict[str, Any]) -> str:
|
|
177
|
+
"""Format a ValidateResult as human-readable text."""
|
|
178
|
+
lines: list[str] = []
|
|
179
|
+
for check in result.get("checks", []):
|
|
180
|
+
if check["status"] == "ok":
|
|
181
|
+
marker = "PASS"
|
|
182
|
+
elif check["status"] == "blocker":
|
|
183
|
+
marker = "BLOCKER"
|
|
184
|
+
else:
|
|
185
|
+
marker = "WARN"
|
|
186
|
+
req_tag = "" if check.get("required", True) else " (optional)"
|
|
187
|
+
lines.append(f" {marker:>7} {check['name']}: {check['message']}{req_tag}")
|
|
188
|
+
|
|
189
|
+
blockers = sum(1 for c in result.get("checks", []) if c["status"] == "blocker")
|
|
190
|
+
warnings = sum(1 for c in result.get("checks", []) if c["status"] == "warning")
|
|
191
|
+
passed = sum(1 for c in result.get("checks", []) if c["status"] == "ok")
|
|
192
|
+
lines.append(f"\nPASS [{passed}] | WARN [{warnings}] | BLOCKER [{blockers}]")
|
|
193
|
+
|
|
194
|
+
return "\n".join(lines)
|
|
@@ -4,7 +4,11 @@ import json
|
|
|
4
4
|
from pathlib import Path
|
|
5
5
|
from typing import cast
|
|
6
6
|
|
|
7
|
-
from runtime.background_verification import
|
|
7
|
+
from runtime.background_verification import (
|
|
8
|
+
publish_verification_state,
|
|
9
|
+
should_skip_validation,
|
|
10
|
+
skipped_stages_for_profile,
|
|
11
|
+
)
|
|
8
12
|
from runtime.runtime_contracts import read_run_state, write_run_state
|
|
9
13
|
|
|
10
14
|
|
|
@@ -80,8 +84,43 @@ class VerificationController:
|
|
|
80
84
|
payload = read_run_state(self.project_dir, "verification_controller", run_id)
|
|
81
85
|
return dict(payload) if isinstance(payload, dict) else {"run_id": run_id, "status": status}
|
|
82
86
|
|
|
87
|
+
def begin_run_with_profile(
|
|
88
|
+
self, run_id: str, evidence_profile: str | None = None
|
|
89
|
+
) -> dict[str, object]:
|
|
90
|
+
"""Start a run with evidence-profile-driven skip logic.
|
|
91
|
+
|
|
92
|
+
Computes which validation stages to skip based on the profile,
|
|
93
|
+
and includes step/total progress for HUD consumption.
|
|
94
|
+
"""
|
|
95
|
+
from runtime.evidence_requirements import requirements_for_profile
|
|
96
|
+
|
|
97
|
+
required = requirements_for_profile(evidence_profile)
|
|
98
|
+
skipped = skipped_stages_for_profile(evidence_profile)
|
|
99
|
+
|
|
100
|
+
state: dict[str, object] = {
|
|
101
|
+
"status": "running",
|
|
102
|
+
"blockers": [],
|
|
103
|
+
"evidence_links": [],
|
|
104
|
+
"progress": self._build_progress(
|
|
105
|
+
run_id,
|
|
106
|
+
step_total={
|
|
107
|
+
"step": 0,
|
|
108
|
+
"total": len(required),
|
|
109
|
+
"current_stage": required[0] if required else "",
|
|
110
|
+
"evidence_profile": evidence_profile or "code-change",
|
|
111
|
+
"skipped_stages": skipped,
|
|
112
|
+
},
|
|
113
|
+
),
|
|
114
|
+
}
|
|
115
|
+
_ = write_run_state(self.project_dir, "verification_controller", run_id, state)
|
|
116
|
+
payload = read_run_state(self.project_dir, "verification_controller", run_id)
|
|
117
|
+
return dict(payload) if isinstance(payload, dict) else {"run_id": run_id, "status": "running"}
|
|
118
|
+
|
|
83
119
|
def _build_progress(
|
|
84
|
-
self,
|
|
120
|
+
self,
|
|
121
|
+
run_id: str,
|
|
122
|
+
prior: dict[str, object] | None = None,
|
|
123
|
+
step_total: dict[str, object] | None = None,
|
|
85
124
|
) -> dict[str, object]:
|
|
86
125
|
progress = dict(prior) if isinstance(prior, dict) else {}
|
|
87
126
|
proof_artifacts = self._collect_run_artifacts("proof-gate", run_id)
|
|
@@ -98,6 +137,17 @@ class VerificationController:
|
|
|
98
137
|
"artifact_paths": proof_artifacts,
|
|
99
138
|
}
|
|
100
139
|
progress["tool_ledger"] = self._collect_tool_ledger(run_id)
|
|
140
|
+
|
|
141
|
+
# Merge step/total from explicit input or preserve prior values
|
|
142
|
+
if isinstance(step_total, dict):
|
|
143
|
+
progress["step"] = step_total.get("step", 0)
|
|
144
|
+
progress["total"] = step_total.get("total", 0)
|
|
145
|
+
if "current_stage" in step_total:
|
|
146
|
+
progress["current_stage"] = step_total["current_stage"]
|
|
147
|
+
if "evidence_profile" in step_total:
|
|
148
|
+
progress["evidence_profile"] = step_total["evidence_profile"]
|
|
149
|
+
if "skipped_stages" in step_total:
|
|
150
|
+
progress["skipped_stages"] = step_total["skipped_stages"]
|
|
101
151
|
return progress
|
|
102
152
|
|
|
103
153
|
def _collect_test_intent_lock(self, run_id: str) -> dict[str, object]:
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Diagnose plugin interoperability and conflict status across OMG-supported hosts
|
|
3
|
+
allowed-tools: Bash(python3:*), Read, Grep, Glob
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /OMG:diagnose-plugins
|
|
7
|
+
|
|
8
|
+
Run `python3 scripts/omg.py diagnose-plugins --format json` and report the diagnostics result.
|
|
9
|
+
|
|
10
|
+
## Output Schema
|
|
11
|
+
|
|
12
|
+
- `schema`: `PluginDiagnosticsResult`
|
|
13
|
+
- `status`: `ok` | `warn` | `error`
|
|
14
|
+
- `records`: discovered plugin records
|
|
15
|
+
- `conflicts`: classified conflict entries
|
|
16
|
+
- `approval_states`: plugin approval states by plugin id
|
|
17
|
+
- `summary`: totals for records, conflicts, and severity buckets
|
|
18
|
+
- `next_actions`: top recommended remediations
|
|
19
|
+
- `elapsed_ms`: total diagnostic runtime
|
|
20
|
+
|
|
21
|
+
## Commands
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
python3 scripts/omg.py diagnose-plugins --format json
|
|
25
|
+
python3 scripts/omg.py diagnose-plugins --format text
|
|
26
|
+
python3 scripts/omg.py diagnose-plugins approve --source mcp:filesystem --host claude --reason "trusted" --format json
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Notes
|
|
30
|
+
|
|
31
|
+
- Base diagnostics command is read-only.
|
|
32
|
+
- Static mode is default; live probing must be explicit via `--live`.
|
|
33
|
+
- `approve` currently returns a pending stub response.
|