@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
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"""Repo-aware change classification for routing and policy attachment."""
|
|
2
2
|
from __future__ import annotations
|
|
3
3
|
|
|
4
|
-
import json
|
|
5
4
|
from pathlib import Path
|
|
6
5
|
import subprocess
|
|
7
6
|
from typing import Any
|
|
@@ -21,6 +20,51 @@ _CATEGORY_RULES: dict[str, tuple[str, ...]] = {
|
|
|
21
20
|
"algorithms": ("algorithm", "benchmark", "determinism", "complexity"),
|
|
22
21
|
}
|
|
23
22
|
|
|
23
|
+
_DOCS_SUFFIXES: tuple[str, ...] = (
|
|
24
|
+
".md",
|
|
25
|
+
".mdx",
|
|
26
|
+
".rst",
|
|
27
|
+
".txt",
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
_DOCS_PATH_HINTS: tuple[str, ...] = (
|
|
31
|
+
"docs/",
|
|
32
|
+
"readme",
|
|
33
|
+
"changelog",
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
_SECURITY_CATEGORY_HINTS: tuple[str, ...] = (
|
|
37
|
+
"auth",
|
|
38
|
+
"payment",
|
|
39
|
+
"db",
|
|
40
|
+
"infra",
|
|
41
|
+
"compliance",
|
|
42
|
+
"health",
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
_SECURITY_TOKENS: tuple[str, ...] = (
|
|
46
|
+
"security",
|
|
47
|
+
"secret",
|
|
48
|
+
"vulnerability",
|
|
49
|
+
"audit",
|
|
50
|
+
"hardening",
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
_RELEASE_TOKENS: tuple[str, ...] = (
|
|
54
|
+
"release",
|
|
55
|
+
"publish",
|
|
56
|
+
"ship",
|
|
57
|
+
"cut tag",
|
|
58
|
+
"version bump",
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
_FORGE_TOKENS: tuple[str, ...] = (
|
|
62
|
+
"forge",
|
|
63
|
+
"prototype",
|
|
64
|
+
"evaluation run",
|
|
65
|
+
"lab job",
|
|
66
|
+
)
|
|
67
|
+
|
|
24
68
|
|
|
25
69
|
def classify_project_changes(
|
|
26
70
|
project_dir: str,
|
|
@@ -40,17 +84,51 @@ def classify_project_changes(
|
|
|
40
84
|
if not categories:
|
|
41
85
|
categories.add("implementation")
|
|
42
86
|
|
|
87
|
+
sorted_categories = sorted(categories)
|
|
43
88
|
result = {
|
|
44
89
|
"schema": "DeltaClassification",
|
|
45
90
|
"project_dir": project_dir,
|
|
46
91
|
"goal": goal,
|
|
47
|
-
"categories":
|
|
92
|
+
"categories": sorted_categories,
|
|
93
|
+
"evidence_profile": _classify_evidence_profile(goal=goal, touched_files=files, categories=sorted_categories),
|
|
48
94
|
"touched_files": files,
|
|
49
95
|
"manifests": manifest_names,
|
|
50
96
|
}
|
|
51
97
|
return result
|
|
52
98
|
|
|
53
99
|
|
|
100
|
+
def _classify_evidence_profile(*, goal: str, touched_files: list[str], categories: list[str]) -> str:
|
|
101
|
+
lowered_goal = goal.lower()
|
|
102
|
+
lowered_files = [path.lower() for path in touched_files]
|
|
103
|
+
|
|
104
|
+
if _contains_any(lowered_goal, _RELEASE_TOKENS) or any(_contains_any(path, _RELEASE_TOKENS) for path in lowered_files):
|
|
105
|
+
return "release"
|
|
106
|
+
|
|
107
|
+
if _contains_any(lowered_goal, _FORGE_TOKENS) or any(_contains_any(path, _FORGE_TOKENS) for path in lowered_files):
|
|
108
|
+
return "forge-run"
|
|
109
|
+
|
|
110
|
+
if set(categories) & set(_SECURITY_CATEGORY_HINTS):
|
|
111
|
+
return "security-audit"
|
|
112
|
+
if _contains_any(lowered_goal, _SECURITY_TOKENS) or any(_contains_any(path, _SECURITY_TOKENS) for path in lowered_files):
|
|
113
|
+
return "security-audit"
|
|
114
|
+
|
|
115
|
+
if lowered_files and all(_is_docs_file(path) for path in lowered_files):
|
|
116
|
+
return "docs-only"
|
|
117
|
+
|
|
118
|
+
return "code-change"
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def _is_docs_file(path: str) -> bool:
|
|
122
|
+
lowered = path.lower()
|
|
123
|
+
if lowered.endswith(_DOCS_SUFFIXES):
|
|
124
|
+
return True
|
|
125
|
+
return any(hint in lowered for hint in _DOCS_PATH_HINTS)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def _contains_any(haystack: str, needles: tuple[str, ...]) -> bool:
|
|
129
|
+
return any(token in haystack for token in needles)
|
|
130
|
+
|
|
131
|
+
|
|
54
132
|
def _discover_files(project_dir: str) -> list[str]:
|
|
55
133
|
root = Path(project_dir)
|
|
56
134
|
git_dir = root / ".git"
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
|
+
import hashlib
|
|
4
5
|
from pathlib import Path
|
|
5
6
|
from typing import cast
|
|
6
7
|
|
|
8
|
+
from runtime.context_engine import load_profile_digest
|
|
9
|
+
from runtime.evidence_requirements import requirements_for_profile
|
|
10
|
+
|
|
7
11
|
JsonPrimitive = str | int | float | bool | None
|
|
8
12
|
JsonValue = JsonPrimitive | dict[str, "JsonValue"] | list["JsonValue"]
|
|
9
13
|
JsonObject = dict[str, JsonValue]
|
|
@@ -35,6 +39,54 @@ def _load_json(path: Path) -> JsonObject | None:
|
|
|
35
39
|
return cast(JsonObject, payload)
|
|
36
40
|
|
|
37
41
|
|
|
42
|
+
def _json_checksum(payload: JsonObject) -> str:
|
|
43
|
+
encoded = json.dumps(payload, sort_keys=True, ensure_ascii=True, separators=(",", ":"))
|
|
44
|
+
return hashlib.sha256(encoded.encode("utf-8", errors="ignore")).hexdigest()
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _record_copy_with_context_metadata(root: Path, record: JsonObject) -> JsonObject:
|
|
48
|
+
run_id = _record_string(record, "run_id")
|
|
49
|
+
if not run_id:
|
|
50
|
+
return record
|
|
51
|
+
|
|
52
|
+
profile_digest = load_profile_digest(root)
|
|
53
|
+
existing_profile_version = _record_string(record, "profile_version")
|
|
54
|
+
profile_version = existing_profile_version or str(profile_digest.get("profile_version", "")).strip()
|
|
55
|
+
evidence_profile = _record_string(record, "evidence_profile").strip()
|
|
56
|
+
evidence_requirements = requirements_for_profile(evidence_profile)
|
|
57
|
+
|
|
58
|
+
intent_gate_payload = _load_json(root / ".omg" / "state" / "intent_gate" / f"{run_id}.json") or {}
|
|
59
|
+
existing_intent_gate_version = _record_string(record, "intent_gate_version")
|
|
60
|
+
intent_gate_version = existing_intent_gate_version or (
|
|
61
|
+
_record_string(intent_gate_payload, "intent_gate_version")
|
|
62
|
+
or _record_string(intent_gate_payload, "schema_version")
|
|
63
|
+
or _record_string(intent_gate_payload, "version")
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
packet_payload = _load_json(root / ".omg" / "state" / "context_engine_packet.json") or {}
|
|
67
|
+
packet_run_id = _record_string(packet_payload, "run_id")
|
|
68
|
+
scoped_packet = packet_payload if packet_run_id == run_id else {}
|
|
69
|
+
context_material: JsonObject = {
|
|
70
|
+
"run_id": run_id,
|
|
71
|
+
"profile_version": profile_version,
|
|
72
|
+
"intent_gate_version": intent_gate_version,
|
|
73
|
+
}
|
|
74
|
+
if scoped_packet:
|
|
75
|
+
context_material["context_packet"] = scoped_packet
|
|
76
|
+
if intent_gate_payload:
|
|
77
|
+
context_material["intent_gate"] = intent_gate_payload
|
|
78
|
+
|
|
79
|
+
existing_context_checksum = _record_string(record, "context_checksum")
|
|
80
|
+
context_checksum = existing_context_checksum or _json_checksum(context_material)
|
|
81
|
+
enriched = dict(record)
|
|
82
|
+
enriched["context_checksum"] = context_checksum
|
|
83
|
+
enriched["profile_version"] = profile_version
|
|
84
|
+
enriched["intent_gate_version"] = intent_gate_version
|
|
85
|
+
enriched["evidence_profile"] = evidence_profile
|
|
86
|
+
enriched["evidence_requirements"] = cast(JsonValue, [str(item) for item in evidence_requirements])
|
|
87
|
+
return enriched
|
|
88
|
+
|
|
89
|
+
|
|
38
90
|
def _read_jsonl(path: Path) -> list[JsonObject]:
|
|
39
91
|
if not path.exists():
|
|
40
92
|
return []
|
|
@@ -109,7 +161,7 @@ def get_evidence_pack(project_dir: str, run_id: str) -> JsonObject | None:
|
|
|
109
161
|
if payload.get("schema") != "EvidencePack":
|
|
110
162
|
continue
|
|
111
163
|
if _record_string(payload, "run_id") == run_id:
|
|
112
|
-
return payload
|
|
164
|
+
return _record_copy_with_context_metadata(root, payload)
|
|
113
165
|
return None
|
|
114
166
|
|
|
115
167
|
|
|
@@ -136,7 +188,7 @@ def query_evidence(
|
|
|
136
188
|
schema=schema,
|
|
137
189
|
kind=kind,
|
|
138
190
|
):
|
|
139
|
-
records.append(payload)
|
|
191
|
+
records.append(_record_copy_with_context_metadata(root, payload))
|
|
140
192
|
|
|
141
193
|
for row in _read_jsonl(root / rel_dir / "events.jsonl"):
|
|
142
194
|
if _record_matches(
|
|
@@ -146,7 +198,7 @@ def query_evidence(
|
|
|
146
198
|
schema=schema,
|
|
147
199
|
kind=kind,
|
|
148
200
|
):
|
|
149
|
-
records.append(row)
|
|
201
|
+
records.append(_record_copy_with_context_metadata(root, row))
|
|
150
202
|
|
|
151
203
|
return records
|
|
152
204
|
|
|
@@ -164,7 +216,7 @@ def list_evidence_packs(project_dir: str) -> list[JsonObject]:
|
|
|
164
216
|
mtime = path.stat().st_mtime
|
|
165
217
|
except OSError:
|
|
166
218
|
mtime = 0.0
|
|
167
|
-
payloads.append((mtime, payload))
|
|
219
|
+
payloads.append((mtime, _record_copy_with_context_metadata(root, payload)))
|
|
168
220
|
|
|
169
221
|
payloads.sort(key=lambda item: item[0], reverse=True)
|
|
170
222
|
return [payload for _, payload in payloads]
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""Backward-compatible alias for evidence requirements registry."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from importlib import import_module
|
|
5
|
+
|
|
6
|
+
_registry = import_module("runtime.evidence_requirements")
|
|
7
|
+
|
|
8
|
+
EVIDENCE_REQUIREMENTS_BY_PROFILE = getattr(_registry, "EVIDENCE_REQUIREMENTS_BY_PROFILE", {})
|
|
9
|
+
FULL_REQUIREMENTS = getattr(_registry, "FULL_REQUIREMENTS", [])
|
|
10
|
+
requirements_for_profile = getattr(_registry, "requirements_for_profile")
|
|
11
|
+
|
|
12
|
+
__all__ = [
|
|
13
|
+
"EVIDENCE_REQUIREMENTS_BY_PROFILE",
|
|
14
|
+
"FULL_REQUIREMENTS",
|
|
15
|
+
"requirements_for_profile",
|
|
16
|
+
]
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"""Single-source evidence profile requirements registry."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from typing import Final
|
|
5
|
+
|
|
6
|
+
FULL_REQUIREMENTS: Final[list[str]] = [
|
|
7
|
+
"tests",
|
|
8
|
+
"lsp_clean",
|
|
9
|
+
"build",
|
|
10
|
+
"provenance",
|
|
11
|
+
"trust_scores",
|
|
12
|
+
"security_scan",
|
|
13
|
+
"license_scan",
|
|
14
|
+
"sbom",
|
|
15
|
+
"trace_link",
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
EVIDENCE_REQUIREMENTS_BY_PROFILE: Final[dict[str, list[str]]] = {
|
|
19
|
+
"code-change": [
|
|
20
|
+
"tests",
|
|
21
|
+
"lsp_clean",
|
|
22
|
+
"build",
|
|
23
|
+
"provenance",
|
|
24
|
+
"trace_link",
|
|
25
|
+
],
|
|
26
|
+
"docs-only": [
|
|
27
|
+
"lsp_clean",
|
|
28
|
+
"trace_link",
|
|
29
|
+
],
|
|
30
|
+
"forge-run": [
|
|
31
|
+
"tests",
|
|
32
|
+
"lsp_clean",
|
|
33
|
+
"provenance",
|
|
34
|
+
"trace_link",
|
|
35
|
+
],
|
|
36
|
+
"security-audit": list(FULL_REQUIREMENTS),
|
|
37
|
+
"release": list(FULL_REQUIREMENTS),
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def requirements_for_profile(evidence_profile: str | None) -> list[str]:
|
|
42
|
+
if not evidence_profile:
|
|
43
|
+
return list(FULL_REQUIREMENTS)
|
|
44
|
+
requirements = EVIDENCE_REQUIREMENTS_BY_PROFILE.get(evidence_profile)
|
|
45
|
+
if not requirements:
|
|
46
|
+
return list(FULL_REQUIREMENTS)
|
|
47
|
+
return list(requirements)
|
package/runtime/forge_agents.py
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import importlib
|
|
4
|
+
import importlib.util
|
|
3
5
|
import json
|
|
4
6
|
import os
|
|
5
7
|
from datetime import datetime, timezone
|
|
6
8
|
from pathlib import Path
|
|
7
9
|
from typing import Any
|
|
8
10
|
|
|
9
|
-
from runtime.forge_contracts import load_forge_mvp, validate_forge_job
|
|
11
|
+
from runtime.forge_contracts import ADAPTER_REGISTRY, load_forge_mvp, validate_forge_job
|
|
12
|
+
from runtime.runtime_contracts import read_defense_state, read_session_health
|
|
13
|
+
from runtime.security_check import run_security_check
|
|
10
14
|
|
|
11
15
|
|
|
12
16
|
_SPECIALIST_REGISTRY: dict[str, dict[str, object]] = {
|
|
@@ -22,6 +26,10 @@ _SPECIALIST_REGISTRY: dict[str, dict[str, object]] = {
|
|
|
22
26
|
"description": "Builds simulator-backed evaluations through the PyBullet hook contract.",
|
|
23
27
|
"capabilities": ["simulator-scenarios", "pybullet-hook-contract", "regression-replay"],
|
|
24
28
|
},
|
|
29
|
+
"forge-cybersecurity": {
|
|
30
|
+
"description": "Runs labs-bounded cybersecurity hardening and threat-evidence checks.",
|
|
31
|
+
"capabilities": ["threat-modeling", "security-regression", "proof-linked-security-evidence"],
|
|
32
|
+
},
|
|
25
33
|
}
|
|
26
34
|
|
|
27
35
|
_DOMAIN_SPECIALISTS: dict[str, list[str]] = {
|
|
@@ -30,6 +38,7 @@ _DOMAIN_SPECIALISTS: dict[str, list[str]] = {
|
|
|
30
38
|
"robotics": ["training-architect", "simulator-engineer"],
|
|
31
39
|
"algorithms": ["training-architect"],
|
|
32
40
|
"health": ["data-curator", "training-architect"],
|
|
41
|
+
"cybersecurity": ["forge-cybersecurity"],
|
|
33
42
|
}
|
|
34
43
|
|
|
35
44
|
|
|
@@ -42,7 +51,33 @@ def get_specialist_registry() -> dict[str, dict[str, object]]:
|
|
|
42
51
|
return {name: dict(metadata) for name, metadata in _SPECIALIST_REGISTRY.items()}
|
|
43
52
|
|
|
44
53
|
|
|
45
|
-
|
|
54
|
+
|
|
55
|
+
def _execute_cybersecurity_scan(project_dir: str) -> dict[str, Any]:
|
|
56
|
+
"""Run canonical security_check scan for forge-cybersecurity specialist.
|
|
57
|
+
|
|
58
|
+
Reuses runtime/security_check.py engine. Degrades gracefully
|
|
59
|
+
when Semgrep or other external tools are unavailable.
|
|
60
|
+
"""
|
|
61
|
+
try:
|
|
62
|
+
return run_security_check(
|
|
63
|
+
project_dir=project_dir,
|
|
64
|
+
scope=".",
|
|
65
|
+
include_live_enrichment=False,
|
|
66
|
+
)
|
|
67
|
+
except Exception:
|
|
68
|
+
return {
|
|
69
|
+
"schema": "SecurityCheckResult",
|
|
70
|
+
"status": "error",
|
|
71
|
+
"scope": ".",
|
|
72
|
+
"findings": [],
|
|
73
|
+
"security_scans": [],
|
|
74
|
+
"unresolved_risks": [],
|
|
75
|
+
"evidence": {},
|
|
76
|
+
"summary": {"scan_status": "failed", "finding_count": 0},
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def dispatch_specialists(job: dict[str, Any], project_dir: str, run_id: str | None = None) -> dict[str, Any]:
|
|
46
81
|
ok, reason = validate_forge_job(job)
|
|
47
82
|
if not ok:
|
|
48
83
|
return {
|
|
@@ -61,7 +96,7 @@ def dispatch_specialists(job: dict[str, Any], project_dir: str) -> dict[str, Any
|
|
|
61
96
|
"status": "blocked",
|
|
62
97
|
"specialists_dispatched": [],
|
|
63
98
|
"evidence_path": "",
|
|
64
|
-
"reason":
|
|
99
|
+
"reason": "invalid_specialist_domain_combination",
|
|
65
100
|
}
|
|
66
101
|
|
|
67
102
|
if requested_specialists:
|
|
@@ -79,7 +114,7 @@ def dispatch_specialists(job: dict[str, Any], project_dir: str) -> dict[str, Any
|
|
|
79
114
|
"status": "blocked",
|
|
80
115
|
"specialists_dispatched": [],
|
|
81
116
|
"evidence_path": "",
|
|
82
|
-
"reason":
|
|
117
|
+
"reason": "invalid_specialist_domain_combination",
|
|
83
118
|
}
|
|
84
119
|
missing_required = [name for name in expected_specialists if name not in requested_specialists]
|
|
85
120
|
if missing_required:
|
|
@@ -87,27 +122,66 @@ def dispatch_specialists(job: dict[str, Any], project_dir: str) -> dict[str, Any
|
|
|
87
122
|
"status": "blocked",
|
|
88
123
|
"specialists_dispatched": [],
|
|
89
124
|
"evidence_path": "",
|
|
90
|
-
"reason":
|
|
125
|
+
"reason": "invalid_specialist_domain_combination",
|
|
91
126
|
}
|
|
92
127
|
|
|
93
128
|
specialists_dispatched = requested_specialists if requested_specialists else expected_specialists
|
|
94
129
|
status = "ok" if specialists_dispatched else "noop"
|
|
95
|
-
|
|
130
|
+
active_run_id = run_id or _now_run_id()
|
|
131
|
+
|
|
132
|
+
job_with_specialists = dict(job)
|
|
133
|
+
job_with_specialists["specialists"] = specialists_dispatched
|
|
134
|
+
adapter_evidence = resolve_adapters(job_with_specialists)
|
|
135
|
+
|
|
136
|
+
backends_ok, backends_reason = check_required_backends_satisfied(adapter_evidence)
|
|
137
|
+
if not backends_ok:
|
|
138
|
+
return {
|
|
139
|
+
"status": "blocked",
|
|
140
|
+
"specialists_dispatched": specialists_dispatched,
|
|
141
|
+
"evidence_path": "",
|
|
142
|
+
"reason": backends_reason,
|
|
143
|
+
"adapter_evidence": adapter_evidence,
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
security_scan: dict[str, Any] | None = None
|
|
147
|
+
if "forge-cybersecurity" in specialists_dispatched:
|
|
148
|
+
security_scan = _execute_cybersecurity_scan(project_dir)
|
|
149
|
+
|
|
96
150
|
evidence_path = _write_dispatch_evidence(
|
|
97
151
|
project_dir=project_dir,
|
|
98
|
-
run_id=
|
|
152
|
+
run_id=active_run_id,
|
|
153
|
+
snapshot_run_id=run_id,
|
|
99
154
|
status=status,
|
|
100
155
|
domain=domain,
|
|
101
156
|
expected_specialists=expected_specialists,
|
|
102
157
|
requested_specialists=requested_specialists,
|
|
103
158
|
specialists_dispatched=specialists_dispatched,
|
|
104
159
|
job=job,
|
|
160
|
+
security_scan=security_scan,
|
|
105
161
|
)
|
|
106
|
-
|
|
162
|
+
result_payload: dict[str, Any] = {
|
|
107
163
|
"status": status,
|
|
108
164
|
"specialists_dispatched": specialists_dispatched,
|
|
165
|
+
"run_id": active_run_id,
|
|
109
166
|
"evidence_path": evidence_path,
|
|
167
|
+
"adapter_evidence": adapter_evidence,
|
|
110
168
|
}
|
|
169
|
+
if security_scan is not None:
|
|
170
|
+
result_payload["security_scan"] = security_scan
|
|
171
|
+
return result_payload
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def _resolve_specialist_contracts(contract: dict[str, object], specialists: list[str]) -> dict[str, dict[str, object]]:
|
|
175
|
+
raw_contracts = contract.get("specialist_contracts")
|
|
176
|
+
if not isinstance(raw_contracts, dict):
|
|
177
|
+
return {}
|
|
178
|
+
|
|
179
|
+
selected: dict[str, dict[str, object]] = {}
|
|
180
|
+
for name in specialists:
|
|
181
|
+
entry = raw_contracts.get(name)
|
|
182
|
+
if isinstance(entry, dict):
|
|
183
|
+
selected[name] = dict(entry)
|
|
184
|
+
return selected
|
|
111
185
|
|
|
112
186
|
|
|
113
187
|
def _normalize_specialist_list(value: object) -> list[str]:
|
|
@@ -125,27 +199,106 @@ def _now_run_id() -> str:
|
|
|
125
199
|
return datetime.now(timezone.utc).strftime("%Y%m%dT%H%M%S%fZ")
|
|
126
200
|
|
|
127
201
|
|
|
202
|
+
def _check_backend_available(backend_name: str) -> bool:
|
|
203
|
+
entry = ADAPTER_REGISTRY.get(backend_name)
|
|
204
|
+
if entry is None:
|
|
205
|
+
return False
|
|
206
|
+
module_name = str(entry.get("module", ""))
|
|
207
|
+
if not module_name:
|
|
208
|
+
return False
|
|
209
|
+
try:
|
|
210
|
+
return importlib.util.find_spec(module_name) is not None
|
|
211
|
+
except Exception:
|
|
212
|
+
return False
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def _check_axolotl_available() -> bool:
|
|
216
|
+
return _check_backend_available("axolotl")
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def _check_simulator_available(name: str) -> bool:
|
|
220
|
+
return _check_backend_available(name)
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
def resolve_adapters(job: dict[str, Any]) -> list[dict[str, object]]:
|
|
224
|
+
results: list[dict[str, object]] = []
|
|
225
|
+
dispatched_specialists = job.get("specialists", [])
|
|
226
|
+
if not isinstance(dispatched_specialists, list):
|
|
227
|
+
dispatched_specialists = []
|
|
228
|
+
|
|
229
|
+
requested_backend = str(job.get("simulator_backend", "")).strip().lower()
|
|
230
|
+
require_backend = bool(job.get("require_backend", False))
|
|
231
|
+
|
|
232
|
+
if "training-architect" in dispatched_specialists:
|
|
233
|
+
available = _check_axolotl_available()
|
|
234
|
+
results.append({
|
|
235
|
+
"adapter": "axolotl",
|
|
236
|
+
"kind": "training",
|
|
237
|
+
"status": "invoked" if available else "skipped_unavailable_backend",
|
|
238
|
+
"required": require_backend and requested_backend == "axolotl",
|
|
239
|
+
"reason": "" if available else "axolotl not installed",
|
|
240
|
+
"available": available,
|
|
241
|
+
})
|
|
242
|
+
|
|
243
|
+
if "simulator-engineer" in dispatched_specialists:
|
|
244
|
+
simulator_backends = _resolve_simulator_backends(requested_backend)
|
|
245
|
+
for backend in simulator_backends:
|
|
246
|
+
available = _check_simulator_available(backend)
|
|
247
|
+
is_required = require_backend and requested_backend == backend
|
|
248
|
+
results.append({
|
|
249
|
+
"adapter": backend,
|
|
250
|
+
"kind": "simulator",
|
|
251
|
+
"status": "invoked" if available else "skipped_unavailable_backend",
|
|
252
|
+
"required": is_required,
|
|
253
|
+
"reason": "" if available else f"{backend} not installed",
|
|
254
|
+
"available": available,
|
|
255
|
+
})
|
|
256
|
+
|
|
257
|
+
return results
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
def _resolve_simulator_backends(requested: str) -> list[str]:
|
|
261
|
+
if requested and requested in ADAPTER_REGISTRY:
|
|
262
|
+
entry = ADAPTER_REGISTRY[requested]
|
|
263
|
+
if str(entry.get("kind", "")) == "simulator":
|
|
264
|
+
return [requested]
|
|
265
|
+
return ["pybullet"]
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
def check_required_backends_satisfied(adapter_evidence: list[dict[str, object]]) -> tuple[bool, str]:
|
|
269
|
+
for ev in adapter_evidence:
|
|
270
|
+
if ev.get("required") is True and ev.get("status") == "skipped_unavailable_backend":
|
|
271
|
+
adapter_name = str(ev.get("adapter", "unknown"))
|
|
272
|
+
return False, f"required backend unavailable: {adapter_name}"
|
|
273
|
+
return True, "ok"
|
|
274
|
+
|
|
275
|
+
|
|
128
276
|
def _write_dispatch_evidence(
|
|
129
277
|
*,
|
|
130
278
|
project_dir: str,
|
|
131
279
|
run_id: str,
|
|
280
|
+
snapshot_run_id: str | None,
|
|
132
281
|
status: str,
|
|
133
282
|
domain: str,
|
|
134
283
|
expected_specialists: list[str],
|
|
135
284
|
requested_specialists: list[str],
|
|
136
285
|
specialists_dispatched: list[str],
|
|
137
286
|
job: dict[str, Any],
|
|
287
|
+
security_scan: dict[str, Any] | None = None,
|
|
138
288
|
) -> str:
|
|
139
289
|
evidence_dir = Path(project_dir) / ".omg" / "evidence"
|
|
140
290
|
evidence_dir.mkdir(parents=True, exist_ok=True)
|
|
141
291
|
evidence_path = evidence_dir / f"forge-specialists-{run_id}.json"
|
|
142
292
|
contract = load_forge_mvp()
|
|
143
|
-
payload = {
|
|
293
|
+
payload: dict[str, Any] = {
|
|
144
294
|
"schema": "ForgeSpecialistDispatchEvidence",
|
|
145
295
|
"schema_version": "1.0.0",
|
|
146
296
|
"run_id": run_id,
|
|
147
297
|
"generated_at": datetime.now(timezone.utc).isoformat(),
|
|
148
298
|
"status": status,
|
|
299
|
+
"labs_only": True,
|
|
300
|
+
"proof_backed": True,
|
|
301
|
+
"specialist": ",".join(specialists_dispatched),
|
|
149
302
|
"domain": domain,
|
|
150
303
|
"requested_specialists": requested_specialists,
|
|
151
304
|
"expected_specialists": expected_specialists,
|
|
@@ -155,9 +308,26 @@ def _write_dispatch_evidence(
|
|
|
155
308
|
"axolotl_hook": contract.get("axolotl_hook", ""),
|
|
156
309
|
"pybullet_hook": contract.get("pybullet_hook", ""),
|
|
157
310
|
},
|
|
311
|
+
"specialist_contracts": _resolve_specialist_contracts(contract, specialists_dispatched),
|
|
312
|
+
"causal_chain": {
|
|
313
|
+
"lock_id": "",
|
|
314
|
+
"waiver_artifact_path": f".omg/evidence/forge-specialists-{run_id}.json",
|
|
315
|
+
"delta_summary": {"forge_dispatch": domain, "specialists": specialists_dispatched},
|
|
316
|
+
"verification_status": status,
|
|
317
|
+
},
|
|
158
318
|
"job": job,
|
|
159
319
|
}
|
|
160
320
|
|
|
321
|
+
if security_scan is not None:
|
|
322
|
+
payload["security_scan"] = security_scan
|
|
323
|
+
|
|
324
|
+
defense_state = read_defense_state(project_dir, run_id=snapshot_run_id, compat=True)
|
|
325
|
+
session_health = read_session_health(project_dir, run_id=snapshot_run_id, compat=True)
|
|
326
|
+
if isinstance(defense_state, dict):
|
|
327
|
+
payload["defense_state"] = defense_state
|
|
328
|
+
if isinstance(session_health, dict):
|
|
329
|
+
payload["session_health"] = session_health
|
|
330
|
+
|
|
161
331
|
tmp_path = evidence_path.with_name(f"{evidence_path.name}.tmp")
|
|
162
332
|
_ = tmp_path.write_text(json.dumps(payload, indent=2, ensure_ascii=True), encoding="utf-8")
|
|
163
333
|
_ = os.replace(tmp_path, evidence_path)
|