@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
|
@@ -4,6 +4,7 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
from datetime import datetime, timezone
|
|
6
6
|
import os
|
|
7
|
+
from pathlib import Path
|
|
7
8
|
from typing import Any
|
|
8
9
|
|
|
9
10
|
from hooks.policy_engine import (
|
|
@@ -20,6 +21,7 @@ from runtime.guide_assert import guide_assert
|
|
|
20
21
|
from runtime.dispatcher import dispatch_runtime
|
|
21
22
|
from runtime.claim_judge import judge_claims
|
|
22
23
|
from runtime.mutation_gate import check_mutation_allowed
|
|
24
|
+
from runtime.runtime_contracts import read_run_state
|
|
23
25
|
from runtime.security_check import run_security_check
|
|
24
26
|
from runtime.test_intent_lock import lock_intent, verify_intent
|
|
25
27
|
|
|
@@ -275,15 +277,24 @@ class ControlPlaneService:
|
|
|
275
277
|
file_path = payload.get("file_path")
|
|
276
278
|
lock_id = payload.get("lock_id")
|
|
277
279
|
exemption = payload.get("exemption")
|
|
280
|
+
command = payload.get("command")
|
|
281
|
+
run_id = payload.get("run_id")
|
|
282
|
+
metadata = payload.get("metadata")
|
|
278
283
|
|
|
279
284
|
if not isinstance(tool, str) or not tool.strip():
|
|
280
285
|
raise ValueError("tool is required")
|
|
281
|
-
if not isinstance(file_path, str) or not file_path.strip():
|
|
286
|
+
if not isinstance(file_path, str) or (tool != "Bash" and not file_path.strip()):
|
|
282
287
|
raise ValueError("file_path is required")
|
|
283
288
|
if lock_id is not None and not isinstance(lock_id, str):
|
|
284
289
|
raise ValueError("lock_id must be a string when provided")
|
|
285
290
|
if exemption is not None and not isinstance(exemption, str):
|
|
286
291
|
raise ValueError("exemption must be a string when provided")
|
|
292
|
+
if command is not None and not isinstance(command, str):
|
|
293
|
+
raise ValueError("command must be a string when provided")
|
|
294
|
+
if run_id is not None and not isinstance(run_id, str):
|
|
295
|
+
raise ValueError("run_id must be a string when provided")
|
|
296
|
+
if metadata is not None and not isinstance(metadata, dict):
|
|
297
|
+
raise ValueError("metadata must be an object when provided")
|
|
287
298
|
|
|
288
299
|
result = check_mutation_allowed(
|
|
289
300
|
tool=tool,
|
|
@@ -291,9 +302,37 @@ class ControlPlaneService:
|
|
|
291
302
|
project_dir=self.project_dir,
|
|
292
303
|
lock_id=lock_id,
|
|
293
304
|
exemption=exemption,
|
|
305
|
+
command=command,
|
|
306
|
+
run_id=run_id,
|
|
307
|
+
metadata=metadata,
|
|
294
308
|
)
|
|
295
309
|
return 200, result
|
|
296
310
|
|
|
311
|
+
def session_health(self, payload: dict[str, Any]) -> tuple[int, dict[str, Any]]:
|
|
312
|
+
run_id = payload.get("run_id")
|
|
313
|
+
if isinstance(run_id, str) and run_id.strip():
|
|
314
|
+
state = read_run_state(self.project_dir, "session_health", run_id.strip())
|
|
315
|
+
if state is None:
|
|
316
|
+
return 404, {"status": "error", "message": f"No session health for run_id: {run_id}"}
|
|
317
|
+
return 200, dict(state)
|
|
318
|
+
|
|
319
|
+
health_dir = Path(self.project_dir) / ".omg" / "state" / "session_health"
|
|
320
|
+
if not health_dir.exists():
|
|
321
|
+
return 404, {"status": "error", "message": "No session health state found"}
|
|
322
|
+
|
|
323
|
+
candidates = sorted(
|
|
324
|
+
(f for f in health_dir.iterdir() if f.suffix == ".json" and not f.name.endswith(".tmp")),
|
|
325
|
+
key=lambda p: p.stat().st_mtime,
|
|
326
|
+
)
|
|
327
|
+
if not candidates:
|
|
328
|
+
return 404, {"status": "error", "message": "No session health state found"}
|
|
329
|
+
|
|
330
|
+
latest_run_id = candidates[-1].stem
|
|
331
|
+
state = read_run_state(self.project_dir, "session_health", latest_run_id)
|
|
332
|
+
if state is None:
|
|
333
|
+
return 404, {"status": "error", "message": "Failed to read session health state"}
|
|
334
|
+
return 200, dict(state)
|
|
335
|
+
|
|
297
336
|
def scoreboard_baseline(self) -> tuple[int, dict[str, Any]]:
|
|
298
337
|
return 200, {
|
|
299
338
|
"generated_at": datetime.now(timezone.utc).isoformat(),
|
|
@@ -224,6 +224,8 @@ INTENT_ROUTING = {
|
|
|
224
224
|
"INTENT_EXPLORE": "explore", # explore/find → fast search agent
|
|
225
225
|
"INTENT_REVIEW": "reviewer", # review/audit → code review agent
|
|
226
226
|
"INTENT_QUICK": "quick_task", # quick/simple → fast task agent
|
|
227
|
+
# Clarification intent (Task 3) — halts mutation-capable execution
|
|
228
|
+
"INTENT_CLARIFICATION": None, # clarification needed → halt (no agent dispatch)
|
|
227
229
|
}
|
|
228
230
|
|
|
229
231
|
# Core agent model preferences. NOT keyword-matched — used by orchestration pipeline only. model_version is informational (not passed to CLI).
|
|
@@ -7,23 +7,234 @@ one centralized decision model.
|
|
|
7
7
|
import json
|
|
8
8
|
import os
|
|
9
9
|
import sys
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import Any
|
|
10
12
|
|
|
11
13
|
HOOKS_DIR = os.path.dirname(__file__)
|
|
12
|
-
|
|
13
|
-
|
|
14
|
+
PROJECT_ROOT = os.path.dirname(HOOKS_DIR)
|
|
15
|
+
for path in (HOOKS_DIR, PROJECT_ROOT):
|
|
16
|
+
if path not in sys.path:
|
|
17
|
+
sys.path.insert(0, path)
|
|
14
18
|
|
|
15
|
-
from _common import setup_crash_handler, json_input, deny_decision, is_bypass_mode
|
|
19
|
+
from _common import setup_crash_handler, json_input, deny_decision, is_bypass_mode, get_project_dir # pyright: ignore[reportImplicitRelativeImport]
|
|
16
20
|
|
|
17
21
|
# Fail-closed: deny on crash (security hook)
|
|
18
22
|
setup_crash_handler("firewall", fail_closed=True)
|
|
19
23
|
|
|
20
24
|
try:
|
|
21
|
-
from policy_engine import evaluate_bash_command, to_pretool_hook_output
|
|
25
|
+
from policy_engine import evaluate_bash_command, to_pretool_hook_output, scan_mutation_command, ask, deny # pyright: ignore[reportImplicitRelativeImport]
|
|
26
|
+
from runtime.defense_state import DefenseState
|
|
27
|
+
from runtime.session_health import compute_session_health
|
|
28
|
+
from runtime.mutation_gate import check_mutation_allowed
|
|
29
|
+
from runtime.tool_plan_gate import journal_mutation_bash
|
|
22
30
|
except Exception as _import_err:
|
|
23
31
|
print(f"OMG firewall: policy_engine import failed: {_import_err}", file=sys.stderr)
|
|
24
32
|
deny_decision(f"OMG firewall crash: policy_engine import failed: {_import_err}. Denying for safety.")
|
|
25
33
|
sys.exit(0)
|
|
26
34
|
|
|
35
|
+
|
|
36
|
+
def _enrich_risk_context(decision, payload: dict[str, object]):
|
|
37
|
+
try:
|
|
38
|
+
project_dir = os.environ.get("CLAUDE_PROJECT_DIR", os.getcwd())
|
|
39
|
+
run_id = _resolve_run_id(payload)
|
|
40
|
+
|
|
41
|
+
suffixes: list[str] = []
|
|
42
|
+
defense_risk = _read_defense_risk(project_dir)
|
|
43
|
+
if defense_risk:
|
|
44
|
+
suffixes.append(f"defense risk={defense_risk}")
|
|
45
|
+
|
|
46
|
+
council_signal = _read_council_signal(project_dir, run_id)
|
|
47
|
+
if council_signal:
|
|
48
|
+
suffixes.append(council_signal)
|
|
49
|
+
|
|
50
|
+
if suffixes:
|
|
51
|
+
decision.reason = f"{decision.reason} [{'; '.join(suffixes)}]".strip()
|
|
52
|
+
except Exception:
|
|
53
|
+
return decision
|
|
54
|
+
return decision
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _resolve_run_id(payload: dict[str, object]) -> str:
|
|
58
|
+
if isinstance(payload, dict):
|
|
59
|
+
run_id = payload.get("run_id")
|
|
60
|
+
if isinstance(run_id, str) and run_id.strip():
|
|
61
|
+
return run_id.strip()
|
|
62
|
+
tool_input = payload.get("tool_input")
|
|
63
|
+
if isinstance(tool_input, dict):
|
|
64
|
+
metadata = tool_input.get("metadata")
|
|
65
|
+
if isinstance(metadata, dict):
|
|
66
|
+
metadata_run_id = metadata.get("run_id")
|
|
67
|
+
if isinstance(metadata_run_id, str) and metadata_run_id.strip():
|
|
68
|
+
return metadata_run_id.strip()
|
|
69
|
+
env_run_id = os.environ.get("OMG_RUN_ID", "")
|
|
70
|
+
return env_run_id.strip()
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _resolve_active_run_id(project_dir: str) -> str:
|
|
74
|
+
active_run_path = Path(project_dir) / ".omg" / "shadow" / "active-run"
|
|
75
|
+
if not active_run_path.exists():
|
|
76
|
+
return ""
|
|
77
|
+
try:
|
|
78
|
+
return active_run_path.read_text(encoding="utf-8").strip()
|
|
79
|
+
except OSError:
|
|
80
|
+
return ""
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def _read_defense_risk(project_dir: str) -> str:
|
|
84
|
+
path = Path(project_dir) / ".omg" / "state" / "defense_state" / "current.json"
|
|
85
|
+
if not path.exists():
|
|
86
|
+
return ""
|
|
87
|
+
try:
|
|
88
|
+
payload = json.loads(path.read_text(encoding="utf-8"))
|
|
89
|
+
except (OSError, json.JSONDecodeError):
|
|
90
|
+
return ""
|
|
91
|
+
if not isinstance(payload, dict):
|
|
92
|
+
return ""
|
|
93
|
+
return str(payload.get("risk_level", "")).strip().lower()
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def _read_council_signal(project_dir: str, run_id: str) -> str:
|
|
97
|
+
if not run_id:
|
|
98
|
+
return ""
|
|
99
|
+
path = Path(project_dir) / ".omg" / "state" / "council_verdicts" / f"{run_id}.json"
|
|
100
|
+
if not path.exists():
|
|
101
|
+
return ""
|
|
102
|
+
try:
|
|
103
|
+
payload = json.loads(path.read_text(encoding="utf-8"))
|
|
104
|
+
except (OSError, json.JSONDecodeError):
|
|
105
|
+
return ""
|
|
106
|
+
if not isinstance(payload, dict):
|
|
107
|
+
return ""
|
|
108
|
+
|
|
109
|
+
verdicts = payload.get("verdicts")
|
|
110
|
+
if not isinstance(verdicts, dict):
|
|
111
|
+
return ""
|
|
112
|
+
evidence = verdicts.get("evidence_completeness")
|
|
113
|
+
if not isinstance(evidence, dict):
|
|
114
|
+
return ""
|
|
115
|
+
verdict = str(evidence.get("verdict", "")).strip().lower()
|
|
116
|
+
findings = evidence.get("findings")
|
|
117
|
+
findings_count = len(findings) if isinstance(findings, list) else 0
|
|
118
|
+
if not verdict:
|
|
119
|
+
return ""
|
|
120
|
+
return f"council evidence={verdict} findings={findings_count}"
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def _read_clarification_state(project_dir: str, run_id: str) -> dict[str, object]:
|
|
124
|
+
if not run_id:
|
|
125
|
+
return {
|
|
126
|
+
"requires_clarification": False,
|
|
127
|
+
"intent_class": "",
|
|
128
|
+
"clarification_prompt": "",
|
|
129
|
+
"confidence": 0.0,
|
|
130
|
+
}
|
|
131
|
+
path = Path(project_dir) / ".omg" / "state" / "intent_gate" / f"{run_id}.json"
|
|
132
|
+
if not path.exists():
|
|
133
|
+
return {
|
|
134
|
+
"requires_clarification": False,
|
|
135
|
+
"intent_class": "",
|
|
136
|
+
"clarification_prompt": "",
|
|
137
|
+
"confidence": 0.0,
|
|
138
|
+
}
|
|
139
|
+
try:
|
|
140
|
+
payload = json.loads(path.read_text(encoding="utf-8"))
|
|
141
|
+
except (OSError, json.JSONDecodeError):
|
|
142
|
+
return {
|
|
143
|
+
"requires_clarification": False,
|
|
144
|
+
"intent_class": "",
|
|
145
|
+
"clarification_prompt": "",
|
|
146
|
+
"confidence": 0.0,
|
|
147
|
+
}
|
|
148
|
+
if not isinstance(payload, dict):
|
|
149
|
+
return {
|
|
150
|
+
"requires_clarification": False,
|
|
151
|
+
"intent_class": "",
|
|
152
|
+
"clarification_prompt": "",
|
|
153
|
+
"confidence": 0.0,
|
|
154
|
+
}
|
|
155
|
+
prompt = " ".join(str(payload.get("clarification_prompt", "")).split())
|
|
156
|
+
try:
|
|
157
|
+
confidence = float(payload.get("confidence", 0.0))
|
|
158
|
+
except (TypeError, ValueError):
|
|
159
|
+
confidence = 0.0
|
|
160
|
+
return {
|
|
161
|
+
"requires_clarification": bool(payload.get("requires_clarification") is True),
|
|
162
|
+
"intent_class": str(payload.get("intent_class", "")).strip(),
|
|
163
|
+
"clarification_prompt": prompt,
|
|
164
|
+
"confidence": round(max(0.0, min(1.0, confidence)), 2),
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def _clarification_reason(clarification_prompt: str) -> str:
|
|
169
|
+
prompt = " ".join(str(clarification_prompt or "").split())
|
|
170
|
+
if prompt:
|
|
171
|
+
return f"Clarification required before mutation: {prompt}"
|
|
172
|
+
return "Clarification required before mutation: provide the missing intent details."
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def _to_float(value: Any, default: float) -> float:
|
|
176
|
+
try:
|
|
177
|
+
return float(value)
|
|
178
|
+
except (TypeError, ValueError):
|
|
179
|
+
return default
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def _mutating_defense_decision(
|
|
183
|
+
*,
|
|
184
|
+
project_dir: str,
|
|
185
|
+
cmd: str,
|
|
186
|
+
run_id: str,
|
|
187
|
+
):
|
|
188
|
+
scan = scan_mutation_command(cmd)
|
|
189
|
+
defense_state = DefenseState(project_dir).update(
|
|
190
|
+
injection_hits=int(_to_float(scan.get("injection_hits"), 0.0)),
|
|
191
|
+
contamination_score=_to_float(scan.get("contamination_score"), 0.0),
|
|
192
|
+
overthinking_score=_to_float(scan.get("overthinking_score"), 0.0),
|
|
193
|
+
premature_fixer_score=_to_float(scan.get("premature_fixer_score"), 0.0),
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
resolved_run_id = run_id.strip() or _resolve_active_run_id(project_dir) or "default"
|
|
197
|
+
session_health = compute_session_health(project_dir, run_id=resolved_run_id)
|
|
198
|
+
|
|
199
|
+
contamination = _to_float(session_health.get("contamination_risk"), _to_float(defense_state.get("contamination_score"), 0.0))
|
|
200
|
+
overthinking = _to_float(session_health.get("overthinking_score"), _to_float(defense_state.get("overthinking_score"), 0.0))
|
|
201
|
+
premature_fixer = _to_float(defense_state.get("premature_fixer_score"), 0.0)
|
|
202
|
+
health_action = str(session_health.get("recommended_action", "continue"))
|
|
203
|
+
thresholds = session_health.get("thresholds") if isinstance(session_health, dict) else {}
|
|
204
|
+
contamination_thresholds = thresholds.get("contamination_risk") if isinstance(thresholds, dict) else {}
|
|
205
|
+
overthinking_thresholds = thresholds.get("overthinking_score") if isinstance(thresholds, dict) else {}
|
|
206
|
+
reflect_contamination = _to_float(contamination_thresholds.get("reflect") if isinstance(contamination_thresholds, dict) else None, 0.05)
|
|
207
|
+
reflect_overthinking = _to_float(overthinking_thresholds.get("reflect") if isinstance(overthinking_thresholds, dict) else None, 0.15)
|
|
208
|
+
reflect_triggers = session_health.get("reflect_triggers") if isinstance(session_health, dict) else {}
|
|
209
|
+
contamination_trigger = bool(reflect_triggers.get("contamination")) if isinstance(reflect_triggers, dict) else contamination > reflect_contamination
|
|
210
|
+
overthinking_trigger = bool(reflect_triggers.get("overthinking")) if isinstance(reflect_triggers, dict) else overthinking > reflect_overthinking
|
|
211
|
+
pause_required = bool(session_health.get("defense_pause_required") is True) if isinstance(session_health, dict) else (contamination_trigger or overthinking_trigger)
|
|
212
|
+
signal_text = ", ".join(str(item) for item in scan.get("signals", []) if str(item)) or "none"
|
|
213
|
+
context = (
|
|
214
|
+
f"defense hits={int(_to_float(defense_state.get('injection_hits'), 0.0))} "
|
|
215
|
+
f"contamination={contamination:.4f} overthinking={overthinking:.4f} "
|
|
216
|
+
f"premature_fixer={premature_fixer:.4f} "
|
|
217
|
+
f"session_health={health_action} signals={signal_text}"
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
if health_action == "block":
|
|
221
|
+
return deny(
|
|
222
|
+
f"Blocked: mutation denied by defense/session-health reducer [{context}]",
|
|
223
|
+
"high",
|
|
224
|
+
["defense-reducer", "session-health"],
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
if pause_required or contamination_trigger or overthinking_trigger:
|
|
228
|
+
return ask(
|
|
229
|
+
"Pause: mutation requires reflection before execution "
|
|
230
|
+
f"[{context}; thresholds contamination>{reflect_contamination:.2f} "
|
|
231
|
+
f"overthinking>{reflect_overthinking:.2f}]",
|
|
232
|
+
"high",
|
|
233
|
+
["reflect", "defense-reducer", "session-health"],
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
return None
|
|
237
|
+
|
|
27
238
|
data = json_input()
|
|
28
239
|
|
|
29
240
|
tool = data.get("tool_name", "")
|
|
@@ -36,11 +247,59 @@ if not cmd:
|
|
|
36
247
|
|
|
37
248
|
decision = evaluate_bash_command(cmd)
|
|
38
249
|
|
|
250
|
+
tool_input = data.get("tool_input")
|
|
251
|
+
metadata = tool_input.get("metadata") if isinstance(tool_input, dict) else None
|
|
252
|
+
lock_id = tool_input.get("lock_id") if isinstance(tool_input, dict) else None
|
|
253
|
+
if not isinstance(lock_id, str) and isinstance(metadata, dict):
|
|
254
|
+
lock_id = metadata.get("lock_id")
|
|
255
|
+
run_id = _resolve_run_id(data)
|
|
256
|
+
|
|
257
|
+
gate_result = check_mutation_allowed(
|
|
258
|
+
tool="Bash",
|
|
259
|
+
file_path=cmd,
|
|
260
|
+
project_dir=get_project_dir(),
|
|
261
|
+
lock_id=lock_id if isinstance(lock_id, str) else None,
|
|
262
|
+
command=cmd,
|
|
263
|
+
run_id=run_id or None,
|
|
264
|
+
metadata=metadata if isinstance(metadata, dict) else None,
|
|
265
|
+
)
|
|
266
|
+
is_mutation_capable = str(gate_result.get("reason", "")) != "tool is read-only for mutation gate"
|
|
267
|
+
clarification_state = _read_clarification_state(get_project_dir(), run_id)
|
|
268
|
+
if is_mutation_capable:
|
|
269
|
+
defense_decision = _mutating_defense_decision(
|
|
270
|
+
project_dir=get_project_dir(),
|
|
271
|
+
cmd=cmd,
|
|
272
|
+
run_id=run_id,
|
|
273
|
+
)
|
|
274
|
+
if defense_decision is not None:
|
|
275
|
+
decision = defense_decision
|
|
276
|
+
|
|
277
|
+
if clarification_state.get("requires_clarification") is True and is_mutation_capable:
|
|
278
|
+
deny_decision(_clarification_reason(str(clarification_state.get("clarification_prompt", ""))))
|
|
279
|
+
sys.exit(0)
|
|
280
|
+
|
|
281
|
+
if is_mutation_capable and gate_result.get("status") == "blocked":
|
|
282
|
+
deny_decision(str(gate_result.get("reason", "mutation denied by test intent lock gate")))
|
|
283
|
+
sys.exit(0)
|
|
284
|
+
|
|
285
|
+
decision = _enrich_risk_context(decision, data)
|
|
286
|
+
|
|
39
287
|
# In bypass-permission mode, only enforce hard denials (critical safety).
|
|
40
288
|
# Skip "ask" decisions so the user is not prompted for confirmation.
|
|
41
289
|
if is_bypass_mode(data) and decision.action != "deny":
|
|
42
290
|
sys.exit(0)
|
|
43
291
|
|
|
292
|
+
if decision.action == "allow" and is_mutation_capable:
|
|
293
|
+
try:
|
|
294
|
+
journal_mutation_bash(
|
|
295
|
+
project_dir=get_project_dir(),
|
|
296
|
+
command=cmd,
|
|
297
|
+
run_id=run_id or None,
|
|
298
|
+
metadata=metadata if isinstance(metadata, dict) else None,
|
|
299
|
+
)
|
|
300
|
+
except Exception:
|
|
301
|
+
pass
|
|
302
|
+
|
|
44
303
|
out = to_pretool_hook_output(decision)
|
|
45
304
|
if out:
|
|
46
305
|
json.dump(out, sys.stdout)
|
|
@@ -38,7 +38,7 @@ try:
|
|
|
38
38
|
get_feature_flag,
|
|
39
39
|
_resolve_project_dir,
|
|
40
40
|
check_performance_budget,
|
|
41
|
-
PRE_TOOL_INJECT_MAX_MS,
|
|
41
|
+
PRE_TOOL_INJECT_MAX_MS as pre_tool_inject_max_ms,
|
|
42
42
|
)
|
|
43
43
|
except ImportError:
|
|
44
44
|
import importlib
|
|
@@ -48,7 +48,7 @@ except ImportError:
|
|
|
48
48
|
get_feature_flag = _common.get_feature_flag
|
|
49
49
|
_resolve_project_dir = _common._resolve_project_dir
|
|
50
50
|
check_performance_budget = _common.check_performance_budget
|
|
51
|
-
|
|
51
|
+
pre_tool_inject_max_ms = _common.PRE_TOOL_INJECT_MAX_MS
|
|
52
52
|
|
|
53
53
|
setup_crash_handler("intentgate-keyword-detector", fail_closed=False)
|
|
54
54
|
|
|
@@ -64,6 +64,18 @@ KEYWORD_INTENT_MAP = {
|
|
|
64
64
|
"search": "INTENT_SEARCH",
|
|
65
65
|
"stop": "INTENT_STOP",
|
|
66
66
|
"crazy": "INTENT_CRAZY",
|
|
67
|
+
"auth": "INTENT_AUTH_SETUP",
|
|
68
|
+
"login": "INTENT_AUTH_SETUP",
|
|
69
|
+
"credentials": "INTENT_AUTH_SETUP",
|
|
70
|
+
"setup my credentials": "INTENT_AUTH_SETUP",
|
|
71
|
+
"setup credentials": "INTENT_AUTH_SETUP",
|
|
72
|
+
"remember my settings": "INTENT_PREFERENCE_MEMORY",
|
|
73
|
+
"remember settings": "INTENT_PREFERENCE_MEMORY",
|
|
74
|
+
"preferences": "INTENT_PREFERENCE_MEMORY",
|
|
75
|
+
"memory style": "INTENT_PREFERENCE_MEMORY",
|
|
76
|
+
"setup preferences": "INTENT_AMBIGUOUS_CONFIG",
|
|
77
|
+
"configure preferences": "INTENT_AMBIGUOUS_CONFIG",
|
|
78
|
+
"remember setup": "INTENT_AMBIGUOUS_CONFIG",
|
|
67
79
|
}
|
|
68
80
|
|
|
69
81
|
|
|
@@ -179,7 +191,7 @@ if detected_intents:
|
|
|
179
191
|
# PERFORMANCE BUDGET CHECK
|
|
180
192
|
# ═══════════════════════════════════════════════════════════
|
|
181
193
|
elapsed_ms = (time.time() - start_time) * 1000
|
|
182
|
-
check_performance_budget("intentgate-keyword-detector", elapsed_ms,
|
|
194
|
+
check_performance_budget("intentgate-keyword-detector", elapsed_ms, pre_tool_inject_max_ms)
|
|
183
195
|
|
|
184
196
|
# ═══════════════════════════════════════════════════════════
|
|
185
197
|
# OUTPUT
|
|
@@ -126,6 +126,33 @@ UNTRUSTED_MUTATION_PATTERNS = [
|
|
|
126
126
|
TRUSTED_CONTENT_TIERS = frozenset({"local", "balanced"})
|
|
127
127
|
UNTRUSTED_EXTERNAL_TIERS = frozenset({"research", "browser"})
|
|
128
128
|
|
|
129
|
+
INJECTION_MARKER_PATTERNS: tuple[tuple[re.Pattern[str], float, str], ...] = (
|
|
130
|
+
(re.compile(r"\bIGNORE\s+(?:ALL\s+)?PREVIOUS(?:\s+INSTRUCTIONS?)?\b", re.IGNORECASE), 0.03, "ignore-previous-instructions"),
|
|
131
|
+
(re.compile(r"<\|im_start\|>", re.IGNORECASE), 0.03, "im-start-token"),
|
|
132
|
+
(re.compile(r"<\|im_end\|>", re.IGNORECASE), 0.03, "im-end-token"),
|
|
133
|
+
(re.compile(r"\[INST\]", re.IGNORECASE), 0.03, "inst-token"),
|
|
134
|
+
(re.compile(r"\[/INST\]", re.IGNORECASE), 0.03, "inst-close-token"),
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
HIDDEN_INSTRUCTION_PATTERNS: tuple[tuple[re.Pattern[str], float, str], ...] = (
|
|
138
|
+
(re.compile(r"(?:^|\s)SYSTEM\s*:", re.IGNORECASE), 0.02, "system-role-token"),
|
|
139
|
+
(re.compile(r"(?:^|\s)ASSISTANT\s*:", re.IGNORECASE), 0.02, "assistant-role-token"),
|
|
140
|
+
(re.compile(r"(?:(?:#|//|/\*|<!--).{0,80})\b(?:ignore|override|jailbreak|bypass)\b", re.IGNORECASE), 0.01, "comment-hidden-instruction"),
|
|
141
|
+
(re.compile(r"\bbase64\s+(?:-d|--decode)\b", re.IGNORECASE), 0.01, "base64-decoder-token"),
|
|
142
|
+
(re.compile(r"\b[A-Za-z0-9+/]{48,}={0,2}\b"), 0.01, "opaque-base64-payload"),
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
CACHE_POISONING_PATTERNS: tuple[tuple[re.Pattern[str], float, str], ...] = (
|
|
146
|
+
(re.compile(r"(?:>|>>|tee\b|cp\b|mv\b|rm\b|sed\s+-i\b).{0,120}/\.omg/state/", re.IGNORECASE), 0.04, "state-path-overwrite-attempt"),
|
|
147
|
+
(re.compile(r"(?:>|>>|tee\b|cp\b|mv\b|rm\b|sed\s+-i\b).{0,120}/\.omg/shadow/active-run", re.IGNORECASE), 0.04, "active-run-overwrite-attempt"),
|
|
148
|
+
(re.compile(r"\b(?:cache|state)\s*(?:poison|override|overwrite|tamper)\b", re.IGNORECASE), 0.02, "cache-poisoning-language"),
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
CLARIFICATION_AMBIGUITY_PATTERNS: tuple[tuple[re.Pattern[str], float, str], ...] = (
|
|
152
|
+
(re.compile(r"\b(?:without\s+asking|no\s+questions\s+asked|skip\s+clarif(?:y|ication))\b", re.IGNORECASE), 0.08, "clarification-bypass-language"),
|
|
153
|
+
(re.compile(r"\b(?:just\s+fix\s+it|fix\s+everything|do\s+whatever\s+it\s+takes)\b", re.IGNORECASE), 0.08, "ambiguous-mutation-intent"),
|
|
154
|
+
)
|
|
155
|
+
|
|
129
156
|
|
|
130
157
|
def _project_dir() -> str:
|
|
131
158
|
return os.environ.get("CLAUDE_PROJECT_DIR", os.getcwd())
|
|
@@ -211,6 +238,56 @@ def _is_untrusted_content_mode_active() -> bool:
|
|
|
211
238
|
return False
|
|
212
239
|
|
|
213
240
|
|
|
241
|
+
def scan_mutation_command(cmd: str) -> dict[str, Any]:
|
|
242
|
+
text = str(cmd or "")
|
|
243
|
+
if not text.strip():
|
|
244
|
+
return {
|
|
245
|
+
"injection_hits": 0,
|
|
246
|
+
"contamination_score": 0.0,
|
|
247
|
+
"overthinking_score": 0.0,
|
|
248
|
+
"premature_fixer_score": 0.0,
|
|
249
|
+
"signals": [],
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
contamination_score = 0.0
|
|
253
|
+
overthinking_score = 0.0
|
|
254
|
+
premature_fixer_score = 0.0
|
|
255
|
+
injection_hits = 0
|
|
256
|
+
signals: list[str] = []
|
|
257
|
+
|
|
258
|
+
for pattern, weight, label in INJECTION_MARKER_PATTERNS:
|
|
259
|
+
if pattern.search(text):
|
|
260
|
+
injection_hits += 1
|
|
261
|
+
contamination_score += weight
|
|
262
|
+
signals.append(label)
|
|
263
|
+
|
|
264
|
+
for pattern, weight, label in HIDDEN_INSTRUCTION_PATTERNS:
|
|
265
|
+
if pattern.search(text):
|
|
266
|
+
injection_hits += 1
|
|
267
|
+
contamination_score += weight
|
|
268
|
+
signals.append(label)
|
|
269
|
+
|
|
270
|
+
for pattern, weight, label in CACHE_POISONING_PATTERNS:
|
|
271
|
+
if pattern.search(text):
|
|
272
|
+
injection_hits += 1
|
|
273
|
+
contamination_score += weight
|
|
274
|
+
signals.append(label)
|
|
275
|
+
|
|
276
|
+
for pattern, weight, label in CLARIFICATION_AMBIGUITY_PATTERNS:
|
|
277
|
+
if pattern.search(text):
|
|
278
|
+
overthinking_score += weight
|
|
279
|
+
premature_fixer_score += weight
|
|
280
|
+
signals.append(label)
|
|
281
|
+
|
|
282
|
+
return {
|
|
283
|
+
"injection_hits": max(0, injection_hits),
|
|
284
|
+
"contamination_score": round(max(0.0, min(1.0, contamination_score)), 4),
|
|
285
|
+
"overthinking_score": round(max(0.0, min(1.0, overthinking_score)), 4),
|
|
286
|
+
"premature_fixer_score": round(max(0.0, min(1.0, premature_fixer_score)), 4),
|
|
287
|
+
"signals": signals,
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
|
|
214
291
|
def evaluate_bash_command(cmd: str) -> PolicyDecision:
|
|
215
292
|
if not cmd:
|
|
216
293
|
return allow("empty command")
|