@trac3er/oh-my-god 2.0.4 → 2.0.7
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 +57 -4
- package/.agents/skills/omg/algorithms/SKILL.md +11 -0
- package/.agents/skills/omg/algorithms/openai.yaml +11 -0
- package/.agents/skills/omg/api-twin/SKILL.md +11 -0
- package/.agents/skills/omg/api-twin/openai.yaml +12 -0
- package/.agents/skills/omg/claim-judge/SKILL.md +11 -0
- package/.agents/skills/omg/claim-judge/openai.yaml +13 -0
- package/.agents/skills/omg/codex-rules.md +33 -0
- 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 +11 -0
- package/.agents/skills/omg/data-lineage/openai.yaml +12 -0
- package/.agents/skills/omg/delta-classifier/SKILL.md +11 -0
- package/.agents/skills/omg/delta-classifier/openai.yaml +12 -0
- package/.agents/skills/omg/eval-gate/SKILL.md +11 -0
- package/.agents/skills/omg/eval-gate/openai.yaml +12 -0
- package/.agents/skills/omg/health/SKILL.md +11 -0
- package/.agents/skills/omg/health/openai.yaml +11 -0
- 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 +11 -0
- package/.agents/skills/omg/incident-replay/openai.yaml +12 -0
- 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 +11 -0
- package/.agents/skills/omg/plan-council/openai.yaml +12 -0
- package/.agents/skills/omg/preflight/SKILL.md +11 -0
- package/.agents/skills/omg/preflight/openai.yaml +12 -0
- package/.agents/skills/omg/proof-gate/SKILL.md +11 -0
- package/.agents/skills/omg/proof-gate/openai.yaml +13 -0
- package/.agents/skills/omg/remote-supervisor/SKILL.md +11 -0
- package/.agents/skills/omg/remote-supervisor/openai.yaml +12 -0
- package/.agents/skills/omg/robotics/SKILL.md +11 -0
- package/.agents/skills/omg/robotics/openai.yaml +11 -0
- 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 +11 -0
- package/.agents/skills/omg/security-check/openai.yaml +13 -0
- package/.agents/skills/omg/test-intent-lock/SKILL.md +11 -0
- package/.agents/skills/omg/test-intent-lock/openai.yaml +13 -0
- package/.agents/skills/omg/tracebank/SKILL.md +11 -0
- package/.agents/skills/omg/tracebank/openai.yaml +12 -0
- package/.agents/skills/omg/vision/SKILL.md +11 -0
- package/.agents/skills/omg/vision/openai.yaml +11 -0
- package/.claude-plugin/marketplace.json +5 -5
- package/.claude-plugin/plugin.json +1 -1
- package/.claude-plugin/scripts/uninstall.sh +2 -2
- package/.mcp.json +0 -22
- package/CHANGELOG.md +13 -0
- package/OMG-setup.sh +64 -14
- package/OMG_COMPAT_CONTRACT.md +1 -1
- package/README.md +8 -6
- package/agents/omg-security-auditor.md +1 -1
- package/artifacts/release/.agents/skills/omg/AGENTS.fragment.md +52 -0
- package/artifacts/release/.agents/skills/omg/algorithms/SKILL.md +11 -0
- package/artifacts/release/.agents/skills/omg/algorithms/openai.yaml +11 -0
- package/artifacts/release/.agents/skills/omg/api-twin/SKILL.md +11 -0
- package/artifacts/release/.agents/skills/omg/api-twin/openai.yaml +12 -0
- package/artifacts/release/.agents/skills/omg/codex-mcp.toml +4 -0
- package/artifacts/release/.agents/skills/omg/codex-rules.md +29 -0
- package/artifacts/release/.agents/skills/omg/control-plane/SKILL.md +11 -0
- package/artifacts/release/.agents/skills/omg/control-plane/openai.yaml +14 -0
- package/artifacts/release/.agents/skills/omg/data-lineage/SKILL.md +11 -0
- package/artifacts/release/.agents/skills/omg/data-lineage/openai.yaml +12 -0
- package/artifacts/release/.agents/skills/omg/delta-classifier/SKILL.md +11 -0
- package/artifacts/release/.agents/skills/omg/delta-classifier/openai.yaml +12 -0
- package/artifacts/release/.agents/skills/omg/eval-gate/SKILL.md +11 -0
- package/artifacts/release/.agents/skills/omg/eval-gate/openai.yaml +12 -0
- package/artifacts/release/.agents/skills/omg/health/SKILL.md +11 -0
- package/artifacts/release/.agents/skills/omg/health/openai.yaml +11 -0
- package/artifacts/release/.agents/skills/omg/hook-governor/SKILL.md +11 -0
- package/artifacts/release/.agents/skills/omg/hook-governor/openai.yaml +11 -0
- package/artifacts/release/.agents/skills/omg/incident-replay/SKILL.md +11 -0
- package/artifacts/release/.agents/skills/omg/incident-replay/openai.yaml +12 -0
- package/artifacts/release/.agents/skills/omg/lsp-pack/SKILL.md +11 -0
- package/artifacts/release/.agents/skills/omg/lsp-pack/openai.yaml +11 -0
- package/artifacts/release/.agents/skills/omg/mcp-fabric/SKILL.md +11 -0
- package/artifacts/release/.agents/skills/omg/mcp-fabric/openai.yaml +13 -0
- package/artifacts/release/.agents/skills/omg/preflight/SKILL.md +11 -0
- package/artifacts/release/.agents/skills/omg/preflight/openai.yaml +12 -0
- package/artifacts/release/.agents/skills/omg/remote-supervisor/SKILL.md +11 -0
- package/artifacts/release/.agents/skills/omg/remote-supervisor/openai.yaml +12 -0
- package/artifacts/release/.agents/skills/omg/robotics/SKILL.md +11 -0
- package/artifacts/release/.agents/skills/omg/robotics/openai.yaml +11 -0
- package/artifacts/release/.agents/skills/omg/secure-worktree-pipeline/SKILL.md +11 -0
- package/artifacts/release/.agents/skills/omg/secure-worktree-pipeline/openai.yaml +12 -0
- package/artifacts/release/.agents/skills/omg/security-check/SKILL.md +11 -0
- package/artifacts/release/.agents/skills/omg/security-check/openai.yaml +13 -0
- package/artifacts/release/.agents/skills/omg/tracebank/SKILL.md +11 -0
- package/artifacts/release/.agents/skills/omg/tracebank/openai.yaml +12 -0
- package/artifacts/release/.agents/skills/omg/vision/SKILL.md +11 -0
- package/artifacts/release/.agents/skills/omg/vision/openai.yaml +11 -0
- package/artifacts/release/.claude-plugin/marketplace.json +36 -0
- package/artifacts/release/.claude-plugin/plugin.json +23 -0
- package/artifacts/release/.mcp.json +40 -0
- package/artifacts/release/OMG_COMPAT_CONTRACT.md +92 -0
- package/artifacts/release/dist/enterprise/bundle/.agents/skills/omg/AGENTS.fragment.md +52 -0
- package/artifacts/release/dist/enterprise/bundle/.agents/skills/omg/algorithms/SKILL.md +11 -0
- package/artifacts/release/dist/enterprise/bundle/.agents/skills/omg/algorithms/openai.yaml +11 -0
- package/artifacts/release/dist/enterprise/bundle/.agents/skills/omg/api-twin/SKILL.md +11 -0
- package/artifacts/release/dist/enterprise/bundle/.agents/skills/omg/api-twin/openai.yaml +12 -0
- package/artifacts/release/dist/enterprise/bundle/.agents/skills/omg/codex-mcp.toml +4 -0
- package/artifacts/release/dist/enterprise/bundle/.agents/skills/omg/codex-rules.md +29 -0
- package/artifacts/release/dist/enterprise/bundle/.agents/skills/omg/control-plane/SKILL.md +11 -0
- package/artifacts/release/dist/enterprise/bundle/.agents/skills/omg/control-plane/openai.yaml +14 -0
- package/artifacts/release/dist/enterprise/bundle/.agents/skills/omg/data-lineage/SKILL.md +11 -0
- package/artifacts/release/dist/enterprise/bundle/.agents/skills/omg/data-lineage/openai.yaml +12 -0
- package/artifacts/release/dist/enterprise/bundle/.agents/skills/omg/delta-classifier/SKILL.md +11 -0
- package/artifacts/release/dist/enterprise/bundle/.agents/skills/omg/delta-classifier/openai.yaml +12 -0
- package/artifacts/release/dist/enterprise/bundle/.agents/skills/omg/eval-gate/SKILL.md +11 -0
- package/artifacts/release/dist/enterprise/bundle/.agents/skills/omg/eval-gate/openai.yaml +12 -0
- package/artifacts/release/dist/enterprise/bundle/.agents/skills/omg/health/SKILL.md +11 -0
- package/artifacts/release/dist/enterprise/bundle/.agents/skills/omg/health/openai.yaml +11 -0
- package/artifacts/release/dist/enterprise/bundle/.agents/skills/omg/hook-governor/SKILL.md +11 -0
- package/artifacts/release/dist/enterprise/bundle/.agents/skills/omg/hook-governor/openai.yaml +11 -0
- package/artifacts/release/dist/enterprise/bundle/.agents/skills/omg/incident-replay/SKILL.md +11 -0
- package/artifacts/release/dist/enterprise/bundle/.agents/skills/omg/incident-replay/openai.yaml +12 -0
- package/artifacts/release/dist/enterprise/bundle/.agents/skills/omg/lsp-pack/SKILL.md +11 -0
- package/artifacts/release/dist/enterprise/bundle/.agents/skills/omg/lsp-pack/openai.yaml +11 -0
- package/artifacts/release/dist/enterprise/bundle/.agents/skills/omg/mcp-fabric/SKILL.md +11 -0
- package/artifacts/release/dist/enterprise/bundle/.agents/skills/omg/mcp-fabric/openai.yaml +13 -0
- package/artifacts/release/dist/enterprise/bundle/.agents/skills/omg/preflight/SKILL.md +11 -0
- package/artifacts/release/dist/enterprise/bundle/.agents/skills/omg/preflight/openai.yaml +12 -0
- package/artifacts/release/dist/enterprise/bundle/.agents/skills/omg/remote-supervisor/SKILL.md +11 -0
- package/artifacts/release/dist/enterprise/bundle/.agents/skills/omg/remote-supervisor/openai.yaml +12 -0
- package/artifacts/release/dist/enterprise/bundle/.agents/skills/omg/robotics/SKILL.md +11 -0
- package/artifacts/release/dist/enterprise/bundle/.agents/skills/omg/robotics/openai.yaml +11 -0
- package/artifacts/release/dist/enterprise/bundle/.agents/skills/omg/secure-worktree-pipeline/SKILL.md +11 -0
- package/artifacts/release/dist/enterprise/bundle/.agents/skills/omg/secure-worktree-pipeline/openai.yaml +12 -0
- package/artifacts/release/dist/enterprise/bundle/.agents/skills/omg/security-check/SKILL.md +11 -0
- package/artifacts/release/dist/enterprise/bundle/.agents/skills/omg/security-check/openai.yaml +13 -0
- package/artifacts/release/dist/enterprise/bundle/.agents/skills/omg/tracebank/SKILL.md +11 -0
- package/artifacts/release/dist/enterprise/bundle/.agents/skills/omg/tracebank/openai.yaml +12 -0
- package/artifacts/release/dist/enterprise/bundle/.agents/skills/omg/vision/SKILL.md +11 -0
- package/artifacts/release/dist/enterprise/bundle/.agents/skills/omg/vision/openai.yaml +11 -0
- package/artifacts/release/dist/enterprise/bundle/OMG_COMPAT_CONTRACT.md +92 -0
- package/artifacts/release/dist/enterprise/bundle/registry/bundles/algorithms.yaml +45 -0
- package/artifacts/release/dist/enterprise/bundle/registry/bundles/api-twin.yaml +48 -0
- package/artifacts/release/dist/enterprise/bundle/registry/bundles/control-plane.yaml +151 -0
- package/artifacts/release/dist/enterprise/bundle/registry/bundles/data-lineage.yaml +47 -0
- package/artifacts/release/dist/enterprise/bundle/registry/bundles/delta-classifier.yaml +47 -0
- package/artifacts/release/dist/enterprise/bundle/registry/bundles/eval-gate.yaml +47 -0
- package/artifacts/release/dist/enterprise/bundle/registry/bundles/health.yaml +45 -0
- package/artifacts/release/dist/enterprise/bundle/registry/bundles/hook-governor.yaml +97 -0
- package/artifacts/release/dist/enterprise/bundle/registry/bundles/incident-replay.yaml +47 -0
- package/artifacts/release/dist/enterprise/bundle/registry/bundles/lsp-pack.yaml +48 -0
- package/artifacts/release/dist/enterprise/bundle/registry/bundles/mcp-fabric.yaml +53 -0
- package/artifacts/release/dist/enterprise/bundle/registry/bundles/preflight.yaml +48 -0
- package/artifacts/release/dist/enterprise/bundle/registry/bundles/remote-supervisor.yaml +49 -0
- package/artifacts/release/dist/enterprise/bundle/registry/bundles/robotics.yaml +45 -0
- package/artifacts/release/dist/enterprise/bundle/registry/bundles/secure-worktree-pipeline.yaml +54 -0
- package/artifacts/release/dist/enterprise/bundle/registry/bundles/security-check.yaml +50 -0
- package/artifacts/release/dist/enterprise/bundle/registry/bundles/tracebank.yaml +47 -0
- package/artifacts/release/dist/enterprise/bundle/registry/bundles/vision.yaml +45 -0
- package/artifacts/release/dist/enterprise/bundle/registry/omg-capability.schema.json +296 -0
- package/artifacts/release/dist/enterprise/manifest.json +243 -0
- package/artifacts/release/dist/public/bundle/.agents/skills/omg/AGENTS.fragment.md +7 -0
- package/artifacts/release/dist/public/bundle/.agents/skills/omg/algorithms/SKILL.md +11 -0
- package/artifacts/release/dist/public/bundle/.agents/skills/omg/algorithms/openai.yaml +11 -0
- package/artifacts/release/dist/public/bundle/.agents/skills/omg/api-twin/SKILL.md +11 -0
- package/artifacts/release/dist/public/bundle/.agents/skills/omg/api-twin/openai.yaml +12 -0
- package/artifacts/release/dist/public/bundle/.agents/skills/omg/codex-mcp.toml +4 -0
- package/artifacts/release/dist/public/bundle/.agents/skills/omg/control-plane/SKILL.md +11 -0
- package/artifacts/release/dist/public/bundle/.agents/skills/omg/control-plane/openai.yaml +14 -0
- package/artifacts/release/dist/public/bundle/.agents/skills/omg/data-lineage/SKILL.md +11 -0
- package/artifacts/release/dist/public/bundle/.agents/skills/omg/data-lineage/openai.yaml +12 -0
- package/artifacts/release/dist/public/bundle/.agents/skills/omg/delta-classifier/SKILL.md +11 -0
- package/artifacts/release/dist/public/bundle/.agents/skills/omg/delta-classifier/openai.yaml +12 -0
- package/artifacts/release/dist/public/bundle/.agents/skills/omg/eval-gate/SKILL.md +11 -0
- package/artifacts/release/dist/public/bundle/.agents/skills/omg/eval-gate/openai.yaml +12 -0
- package/artifacts/release/dist/public/bundle/.agents/skills/omg/health/SKILL.md +11 -0
- package/artifacts/release/dist/public/bundle/.agents/skills/omg/health/openai.yaml +11 -0
- package/artifacts/release/dist/public/bundle/.agents/skills/omg/hook-governor/SKILL.md +11 -0
- package/artifacts/release/dist/public/bundle/.agents/skills/omg/hook-governor/openai.yaml +11 -0
- package/artifacts/release/dist/public/bundle/.agents/skills/omg/incident-replay/SKILL.md +11 -0
- package/artifacts/release/dist/public/bundle/.agents/skills/omg/incident-replay/openai.yaml +12 -0
- package/artifacts/release/dist/public/bundle/.agents/skills/omg/lsp-pack/SKILL.md +11 -0
- package/artifacts/release/dist/public/bundle/.agents/skills/omg/lsp-pack/openai.yaml +11 -0
- package/artifacts/release/dist/public/bundle/.agents/skills/omg/mcp-fabric/SKILL.md +11 -0
- package/artifacts/release/dist/public/bundle/.agents/skills/omg/mcp-fabric/openai.yaml +13 -0
- package/artifacts/release/dist/public/bundle/.agents/skills/omg/preflight/SKILL.md +11 -0
- package/artifacts/release/dist/public/bundle/.agents/skills/omg/preflight/openai.yaml +12 -0
- package/artifacts/release/dist/public/bundle/.agents/skills/omg/remote-supervisor/SKILL.md +11 -0
- package/artifacts/release/dist/public/bundle/.agents/skills/omg/remote-supervisor/openai.yaml +12 -0
- package/artifacts/release/dist/public/bundle/.agents/skills/omg/robotics/SKILL.md +11 -0
- package/artifacts/release/dist/public/bundle/.agents/skills/omg/robotics/openai.yaml +11 -0
- package/artifacts/release/dist/public/bundle/.agents/skills/omg/secure-worktree-pipeline/SKILL.md +11 -0
- package/artifacts/release/dist/public/bundle/.agents/skills/omg/secure-worktree-pipeline/openai.yaml +12 -0
- package/artifacts/release/dist/public/bundle/.agents/skills/omg/security-check/SKILL.md +11 -0
- package/artifacts/release/dist/public/bundle/.agents/skills/omg/security-check/openai.yaml +13 -0
- package/artifacts/release/dist/public/bundle/.agents/skills/omg/tracebank/SKILL.md +11 -0
- package/artifacts/release/dist/public/bundle/.agents/skills/omg/tracebank/openai.yaml +12 -0
- package/artifacts/release/dist/public/bundle/.agents/skills/omg/vision/SKILL.md +11 -0
- package/artifacts/release/dist/public/bundle/.agents/skills/omg/vision/openai.yaml +11 -0
- package/artifacts/release/dist/public/bundle/.claude-plugin/marketplace.json +36 -0
- package/artifacts/release/dist/public/bundle/.claude-plugin/plugin.json +23 -0
- package/artifacts/release/dist/public/bundle/.mcp.json +40 -0
- package/artifacts/release/dist/public/bundle/OMG_COMPAT_CONTRACT.md +92 -0
- package/artifacts/release/dist/public/bundle/registry/bundles/algorithms.yaml +45 -0
- package/artifacts/release/dist/public/bundle/registry/bundles/api-twin.yaml +48 -0
- package/artifacts/release/dist/public/bundle/registry/bundles/control-plane.yaml +151 -0
- package/artifacts/release/dist/public/bundle/registry/bundles/data-lineage.yaml +47 -0
- package/artifacts/release/dist/public/bundle/registry/bundles/delta-classifier.yaml +47 -0
- package/artifacts/release/dist/public/bundle/registry/bundles/eval-gate.yaml +47 -0
- package/artifacts/release/dist/public/bundle/registry/bundles/health.yaml +45 -0
- package/artifacts/release/dist/public/bundle/registry/bundles/hook-governor.yaml +97 -0
- package/artifacts/release/dist/public/bundle/registry/bundles/incident-replay.yaml +47 -0
- package/artifacts/release/dist/public/bundle/registry/bundles/lsp-pack.yaml +48 -0
- package/artifacts/release/dist/public/bundle/registry/bundles/mcp-fabric.yaml +53 -0
- package/artifacts/release/dist/public/bundle/registry/bundles/preflight.yaml +48 -0
- package/artifacts/release/dist/public/bundle/registry/bundles/remote-supervisor.yaml +49 -0
- package/artifacts/release/dist/public/bundle/registry/bundles/robotics.yaml +45 -0
- package/artifacts/release/dist/public/bundle/registry/bundles/secure-worktree-pipeline.yaml +54 -0
- package/artifacts/release/dist/public/bundle/registry/bundles/security-check.yaml +50 -0
- package/artifacts/release/dist/public/bundle/registry/bundles/tracebank.yaml +47 -0
- package/artifacts/release/dist/public/bundle/registry/bundles/vision.yaml +45 -0
- package/artifacts/release/dist/public/bundle/registry/omg-capability.schema.json +296 -0
- package/artifacts/release/dist/public/bundle/settings.json +526 -0
- package/artifacts/release/dist/public/manifest.json +255 -0
- package/artifacts/release/registry/bundles/algorithms.yaml +45 -0
- package/artifacts/release/registry/bundles/api-twin.yaml +48 -0
- package/artifacts/release/registry/bundles/control-plane.yaml +151 -0
- package/artifacts/release/registry/bundles/data-lineage.yaml +47 -0
- package/artifacts/release/registry/bundles/delta-classifier.yaml +47 -0
- package/artifacts/release/registry/bundles/eval-gate.yaml +47 -0
- package/artifacts/release/registry/bundles/health.yaml +45 -0
- package/artifacts/release/registry/bundles/hook-governor.yaml +97 -0
- package/artifacts/release/registry/bundles/incident-replay.yaml +47 -0
- package/artifacts/release/registry/bundles/lsp-pack.yaml +48 -0
- package/artifacts/release/registry/bundles/mcp-fabric.yaml +53 -0
- package/artifacts/release/registry/bundles/preflight.yaml +48 -0
- package/artifacts/release/registry/bundles/remote-supervisor.yaml +49 -0
- package/artifacts/release/registry/bundles/robotics.yaml +45 -0
- package/artifacts/release/registry/bundles/secure-worktree-pipeline.yaml +54 -0
- package/artifacts/release/registry/bundles/security-check.yaml +50 -0
- package/artifacts/release/registry/bundles/tracebank.yaml +47 -0
- package/artifacts/release/registry/bundles/vision.yaml +45 -0
- package/artifacts/release/registry/omg-capability.schema.json +296 -0
- package/artifacts/release/settings.json +594 -0
- package/build/lib/agents/__init__.py +1 -0
- package/build/lib/agents/designer.md +67 -0
- package/build/lib/agents/explore.md +60 -0
- package/build/lib/agents/model_roles.py +196 -0
- package/build/lib/agents/omg-api-builder.md +23 -0
- package/build/lib/agents/omg-architect-mode.md +41 -0
- package/build/lib/agents/omg-architect.md +13 -0
- package/build/lib/agents/omg-backend-engineer.md +41 -0
- package/build/lib/agents/omg-critic.md +16 -0
- package/build/lib/agents/omg-database-engineer.md +41 -0
- package/build/lib/agents/omg-escalation-router.md +17 -0
- package/build/lib/agents/omg-executor.md +12 -0
- package/build/lib/agents/omg-frontend-designer.md +41 -0
- package/build/lib/agents/omg-implement-mode.md +49 -0
- package/build/lib/agents/omg-infra-engineer.md +41 -0
- package/build/lib/agents/omg-qa-tester.md +16 -0
- package/build/lib/agents/omg-research-mode.md +41 -0
- package/build/lib/agents/omg-security-auditor.md +41 -0
- package/build/lib/agents/omg-testing-engineer.md +41 -0
- package/build/lib/agents/plan.md +80 -0
- package/build/lib/agents/quick_task.md +64 -0
- package/build/lib/agents/reviewer.md +83 -0
- package/build/lib/agents/task.md +71 -0
- package/build/lib/commands/OMG:ai-commit.md +113 -0
- package/build/lib/commands/OMG:api-twin.md +22 -0
- package/build/lib/commands/OMG:arch.md +313 -0
- package/build/lib/commands/OMG:ccg.md +22 -0
- package/build/lib/commands/OMG:compat.md +57 -0
- package/build/lib/commands/OMG:cost.md +181 -0
- package/build/lib/commands/OMG:crazy.md +125 -0
- package/build/lib/commands/OMG:create-agent.md +183 -0
- package/build/lib/commands/OMG:deps.md +248 -0
- package/build/lib/commands/OMG:doctor.md +37 -0
- package/build/lib/commands/OMG:domain-init.md +11 -0
- package/build/lib/commands/OMG:escalate.md +52 -0
- package/build/lib/commands/OMG:health-check.md +45 -0
- package/build/lib/commands/OMG:init.md +134 -0
- package/build/lib/commands/OMG:mode.md +44 -0
- package/build/lib/commands/OMG:preflight.md +26 -0
- package/build/lib/commands/OMG:project-init.md +11 -0
- package/build/lib/commands/OMG:ralph-start.md +43 -0
- package/build/lib/commands/OMG:ralph-stop.md +23 -0
- package/build/lib/commands/OMG:security-check.md +28 -0
- package/build/lib/commands/OMG:session-branch.md +85 -0
- package/build/lib/commands/OMG:session-fork.md +53 -0
- package/build/lib/commands/OMG:session-merge.md +134 -0
- package/build/lib/commands/OMG:setup.md +78 -0
- package/build/lib/commands/OMG:stats.md +225 -0
- package/build/lib/commands/OMG:teams.md +39 -0
- package/build/lib/commands/OMG:theme.md +44 -0
- package/build/lib/commands/__init__.py +1 -0
- package/build/lib/control_plane/__init__.py +2 -0
- package/build/lib/control_plane/openapi.yaml +260 -0
- package/build/lib/control_plane/server.py +147 -0
- package/build/lib/control_plane/service.py +222 -0
- package/build/lib/hooks/__init__.py +0 -0
- package/build/lib/hooks/_agent_registry.py +423 -0
- package/build/lib/hooks/_analytics.py +291 -0
- package/build/lib/hooks/_budget.py +31 -0
- package/build/lib/hooks/_common.py +569 -0
- package/build/lib/hooks/_compression_optimizer.py +119 -0
- package/build/lib/hooks/_cost_ledger.py +176 -0
- package/build/lib/hooks/_learnings.py +126 -0
- package/build/lib/hooks/_memory.py +103 -0
- package/build/lib/hooks/_protected_context.py +150 -0
- package/build/lib/hooks/_token_counter.py +221 -0
- package/build/lib/hooks/branch_manager.py +236 -0
- package/build/lib/hooks/budget_governor.py +232 -0
- package/build/lib/hooks/circuit-breaker.py +270 -0
- package/build/lib/hooks/compression_feedback.py +254 -0
- package/build/lib/hooks/config-guard.py +216 -0
- package/build/lib/hooks/context_pressure.py +53 -0
- package/build/lib/hooks/credential_store.py +1020 -0
- package/build/lib/hooks/fetch-rate-limits.py +212 -0
- package/build/lib/hooks/firewall.py +48 -0
- package/build/lib/hooks/hashline-formatter-bridge.py +224 -0
- package/build/lib/hooks/hashline-injector.py +273 -0
- package/build/lib/hooks/hashline-validator.py +216 -0
- package/build/lib/hooks/idle-detector.py +95 -0
- package/build/lib/hooks/intentgate-keyword-detector.py +188 -0
- package/build/lib/hooks/magic-keyword-router.py +195 -0
- package/build/lib/hooks/policy_engine.py +641 -0
- package/build/lib/hooks/post-tool-failure.py +19 -0
- package/build/lib/hooks/post-write.py +219 -0
- package/build/lib/hooks/post_write.py +46 -0
- package/build/lib/hooks/pre-compact.py +398 -0
- package/build/lib/hooks/pre-tool-inject.py +98 -0
- package/build/lib/hooks/prompt-enhancer.py +672 -0
- package/build/lib/hooks/quality-runner.py +191 -0
- package/build/lib/hooks/query.py +512 -0
- package/build/lib/hooks/secret-guard.py +61 -0
- package/build/lib/hooks/secret_audit.py +144 -0
- package/build/lib/hooks/security_validators.py +75 -0
- package/build/lib/hooks/session-end-capture.py +137 -0
- package/build/lib/hooks/session-start.py +277 -0
- package/build/lib/hooks/setup_wizard.py +646 -0
- package/build/lib/hooks/shadow_manager.py +344 -0
- package/build/lib/hooks/state_migration.py +225 -0
- package/build/lib/hooks/stop-gate.py +7 -0
- package/build/lib/hooks/stop_dispatcher.py +945 -0
- package/build/lib/hooks/test-validator.py +361 -0
- package/build/lib/hooks/test_generator_hook.py +123 -0
- package/build/lib/hooks/todo-state-tracker.py +114 -0
- package/build/lib/hooks/tool-ledger.py +149 -0
- package/build/lib/hooks/trust_review.py +585 -0
- package/build/lib/plugins/README.md +60 -0
- package/build/lib/plugins/__init__.py +1 -0
- package/build/lib/plugins/advanced/commands/OMG:code-review.md +114 -0
- package/build/lib/plugins/advanced/commands/OMG:deep-plan.md +265 -0
- package/build/lib/plugins/advanced/commands/OMG:handoff.md +115 -0
- package/build/lib/plugins/advanced/commands/OMG:learn.md +110 -0
- package/build/lib/plugins/advanced/commands/OMG:maintainer.md +31 -0
- package/build/lib/plugins/advanced/commands/OMG:ralph-start.md +43 -0
- package/build/lib/plugins/advanced/commands/OMG:ralph-stop.md +23 -0
- package/build/lib/plugins/advanced/commands/OMG:security-review.md +16 -0
- package/build/lib/plugins/advanced/commands/OMG:sequential-thinking.md +20 -0
- package/build/lib/plugins/advanced/commands/OMG:ship.md +46 -0
- package/build/lib/plugins/advanced/plugin.json +87 -0
- package/build/lib/plugins/core/plugin.json +145 -0
- package/build/lib/plugins/dephealth/__init__.py +0 -0
- package/build/lib/plugins/dephealth/cve_scanner.py +188 -0
- package/build/lib/plugins/dephealth/license_checker.py +135 -0
- package/build/lib/plugins/dephealth/manifest_detector.py +423 -0
- package/build/lib/plugins/dephealth/vuln_analyzer.py +169 -0
- package/build/lib/plugins/testgen/__init__.py +0 -0
- package/build/lib/plugins/testgen/codamosa_engine.py +402 -0
- package/build/lib/plugins/testgen/edge_case_synthesizer.py +184 -0
- package/build/lib/plugins/testgen/framework_detector.py +271 -0
- package/build/lib/plugins/testgen/skeleton_generator.py +219 -0
- package/build/lib/plugins/viz/__init__.py +0 -0
- package/build/lib/plugins/viz/ast_parser.py +139 -0
- package/build/lib/plugins/viz/diagram_generator.py +192 -0
- package/build/lib/plugins/viz/graph_builder.py +444 -0
- package/build/lib/plugins/viz/native_parsers.py +259 -0
- package/build/lib/plugins/viz/regex_parser.py +112 -0
- package/build/lib/registry/__init__.py +1 -0
- package/build/lib/registry/bundles/algorithms.yaml +45 -0
- package/build/lib/registry/bundles/api-twin.yaml +48 -0
- package/build/lib/registry/bundles/claim-judge.yaml +49 -0
- package/build/lib/registry/bundles/control-plane.yaml +151 -0
- package/build/lib/registry/bundles/data-lineage.yaml +47 -0
- package/build/lib/registry/bundles/delta-classifier.yaml +47 -0
- package/build/lib/registry/bundles/eval-gate.yaml +47 -0
- package/build/lib/registry/bundles/health.yaml +45 -0
- package/build/lib/registry/bundles/hook-governor.yaml +97 -0
- package/build/lib/registry/bundles/incident-replay.yaml +47 -0
- package/build/lib/registry/bundles/lsp-pack.yaml +48 -0
- package/build/lib/registry/bundles/mcp-fabric.yaml +53 -0
- package/build/lib/registry/bundles/plan-council.yaml +51 -0
- package/build/lib/registry/bundles/preflight.yaml +48 -0
- package/build/lib/registry/bundles/proof-gate.yaml +49 -0
- package/build/lib/registry/bundles/remote-supervisor.yaml +49 -0
- package/build/lib/registry/bundles/robotics.yaml +45 -0
- package/build/lib/registry/bundles/secure-worktree-pipeline.yaml +54 -0
- package/build/lib/registry/bundles/security-check.yaml +50 -0
- package/build/lib/registry/bundles/test-intent-lock.yaml +49 -0
- package/build/lib/registry/bundles/tracebank.yaml +47 -0
- package/build/lib/registry/bundles/vision.yaml +45 -0
- package/build/lib/registry/omg-capability.schema.json +296 -0
- package/build/lib/registry/verify_artifact.py +90 -0
- package/build/lib/runtime/__init__.py +32 -0
- package/build/lib/runtime/adapters/__init__.py +13 -0
- package/build/lib/runtime/adapters/claude.py +63 -0
- package/build/lib/runtime/adapters/gpt.py +56 -0
- package/build/lib/runtime/adapters/local.py +56 -0
- package/build/lib/runtime/adoption.py +212 -0
- package/build/lib/runtime/api_twin.py +450 -0
- package/build/lib/runtime/asset_loader.py +62 -0
- package/build/lib/runtime/business_workflow.py +234 -0
- package/build/lib/runtime/claim_judge.py +95 -0
- package/build/lib/runtime/cli_provider.py +85 -0
- package/build/lib/runtime/compat.py +1459 -0
- package/build/lib/runtime/contract_compiler.py +1918 -0
- package/build/lib/runtime/custom_agent_loader.py +366 -0
- package/build/lib/runtime/data_lineage.py +73 -0
- package/build/lib/runtime/delta_classifier.py +81 -0
- package/build/lib/runtime/dispatcher.py +47 -0
- package/build/lib/runtime/domain_packs.py +46 -0
- package/build/lib/runtime/ecosystem.py +371 -0
- package/build/lib/runtime/eval_gate.py +96 -0
- package/build/lib/runtime/guide_assert.py +45 -0
- package/build/lib/runtime/incident_replay.py +47 -0
- package/build/lib/runtime/legacy_compat.py +7 -0
- package/build/lib/runtime/mcp_config_writers.py +233 -0
- package/build/lib/runtime/mcp_lifecycle.py +175 -0
- package/build/lib/runtime/mcp_memory_server.py +135 -0
- package/build/lib/runtime/memory_parsers/__init__.py +0 -0
- package/build/lib/runtime/memory_parsers/chatgpt_parser.py +257 -0
- package/build/lib/runtime/memory_parsers/claude_import.py +107 -0
- package/build/lib/runtime/memory_parsers/export.py +97 -0
- package/build/lib/runtime/memory_parsers/gemini_import.py +91 -0
- package/build/lib/runtime/memory_parsers/kimi_import.py +91 -0
- package/build/lib/runtime/memory_store.py +215 -0
- package/build/lib/runtime/omc_compat.py +7 -0
- package/build/lib/runtime/omg_compat_contract_snapshot.json +916 -0
- package/build/lib/runtime/omg_contract_snapshot.json +916 -0
- package/build/lib/runtime/omg_mcp_server.py +212 -0
- package/build/lib/runtime/playwright_pack.py +169 -0
- package/build/lib/runtime/preflight.py +117 -0
- package/build/lib/runtime/proof_chain.py +228 -0
- package/build/lib/runtime/proof_gate.py +163 -0
- package/build/lib/runtime/providers/__init__.py +0 -0
- package/build/lib/runtime/providers/codex_provider.py +102 -0
- package/build/lib/runtime/providers/gemini_provider.py +109 -0
- package/build/lib/runtime/providers/kimi_provider.py +132 -0
- package/build/lib/runtime/remote_supervisor.py +64 -0
- package/build/lib/runtime/runtime_profile.py +61 -0
- package/build/lib/runtime/security_check.py +965 -0
- package/build/lib/runtime/subagent_dispatcher.py +469 -0
- package/build/lib/runtime/team_router.py +1167 -0
- package/build/lib/runtime/test_intent_lock.py +91 -0
- package/build/lib/runtime/tmux_session_manager.py +169 -0
- package/build/lib/runtime/tracebank.py +95 -0
- package/build/lib/runtime/untrusted_content.py +269 -0
- package/commands/OMG:doctor.md +37 -0
- package/commands/OMG:preflight.md +1 -1
- package/commands/__init__.py +1 -0
- package/control_plane/__init__.py +2 -0
- package/control_plane/openapi.yaml +260 -0
- package/control_plane/server.py +147 -0
- package/control_plane/service.py +222 -0
- package/dist/enterprise/bundle/.agents/skills/omg/AGENTS.fragment.md +50 -3
- package/dist/enterprise/bundle/.agents/skills/omg/algorithms/SKILL.md +11 -0
- package/dist/enterprise/bundle/.agents/skills/omg/algorithms/openai.yaml +11 -0
- package/dist/enterprise/bundle/.agents/skills/omg/api-twin/SKILL.md +11 -0
- package/dist/enterprise/bundle/.agents/skills/omg/api-twin/openai.yaml +12 -0
- package/dist/enterprise/bundle/.agents/skills/omg/codex-rules.md +29 -0
- package/dist/enterprise/bundle/.agents/skills/omg/data-lineage/SKILL.md +11 -0
- package/dist/enterprise/bundle/.agents/skills/omg/data-lineage/openai.yaml +12 -0
- package/dist/enterprise/bundle/.agents/skills/omg/delta-classifier/SKILL.md +11 -0
- package/dist/enterprise/bundle/.agents/skills/omg/delta-classifier/openai.yaml +12 -0
- package/dist/enterprise/bundle/.agents/skills/omg/eval-gate/SKILL.md +11 -0
- package/dist/enterprise/bundle/.agents/skills/omg/eval-gate/openai.yaml +12 -0
- package/dist/enterprise/bundle/.agents/skills/omg/health/SKILL.md +11 -0
- package/dist/enterprise/bundle/.agents/skills/omg/health/openai.yaml +11 -0
- package/dist/enterprise/bundle/.agents/skills/omg/incident-replay/SKILL.md +11 -0
- package/dist/enterprise/bundle/.agents/skills/omg/incident-replay/openai.yaml +12 -0
- package/dist/enterprise/bundle/.agents/skills/omg/preflight/SKILL.md +11 -0
- package/dist/enterprise/bundle/.agents/skills/omg/preflight/openai.yaml +12 -0
- package/dist/enterprise/bundle/.agents/skills/omg/remote-supervisor/SKILL.md +11 -0
- package/dist/enterprise/bundle/.agents/skills/omg/remote-supervisor/openai.yaml +12 -0
- package/dist/enterprise/bundle/.agents/skills/omg/robotics/SKILL.md +11 -0
- package/dist/enterprise/bundle/.agents/skills/omg/robotics/openai.yaml +11 -0
- package/dist/enterprise/bundle/.agents/skills/omg/security-check/SKILL.md +11 -0
- package/dist/enterprise/bundle/.agents/skills/omg/security-check/openai.yaml +13 -0
- package/dist/enterprise/bundle/.agents/skills/omg/tracebank/SKILL.md +11 -0
- package/dist/enterprise/bundle/.agents/skills/omg/tracebank/openai.yaml +12 -0
- package/dist/enterprise/bundle/.agents/skills/omg/vision/SKILL.md +11 -0
- package/dist/enterprise/bundle/.agents/skills/omg/vision/openai.yaml +11 -0
- package/dist/enterprise/bundle/.claude-plugin/marketplace.json +5 -5
- 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/commands/OMG:code-review.md +114 -0
- package/dist/enterprise/bundle/plugins/advanced/commands/OMG:deep-plan.md +221 -0
- package/dist/enterprise/bundle/plugins/advanced/commands/OMG:handoff.md +115 -0
- package/dist/enterprise/bundle/plugins/advanced/commands/OMG:learn.md +110 -0
- package/dist/enterprise/bundle/plugins/advanced/commands/OMG:maintainer.md +31 -0
- package/dist/enterprise/bundle/plugins/advanced/commands/OMG:ralph-start.md +43 -0
- package/dist/enterprise/bundle/plugins/advanced/commands/OMG:ralph-stop.md +23 -0
- package/dist/enterprise/bundle/plugins/advanced/commands/OMG:security-review.md +16 -0
- package/dist/enterprise/bundle/plugins/advanced/commands/OMG:sequential-thinking.md +20 -0
- package/dist/enterprise/bundle/plugins/advanced/commands/OMG:ship.md +46 -0
- package/dist/enterprise/bundle/plugins/advanced/plugin.json +87 -0
- package/dist/enterprise/bundle/registry/bundles/algorithms.yaml +45 -0
- package/dist/enterprise/bundle/registry/bundles/api-twin.yaml +48 -0
- package/dist/enterprise/bundle/registry/bundles/control-plane.yaml +151 -0
- package/dist/enterprise/bundle/registry/bundles/data-lineage.yaml +47 -0
- package/dist/enterprise/bundle/registry/bundles/delta-classifier.yaml +47 -0
- package/dist/enterprise/bundle/registry/bundles/eval-gate.yaml +47 -0
- package/dist/enterprise/bundle/registry/bundles/health.yaml +45 -0
- package/dist/enterprise/bundle/registry/bundles/hook-governor.yaml +97 -0
- package/dist/enterprise/bundle/registry/bundles/incident-replay.yaml +47 -0
- package/dist/enterprise/bundle/registry/bundles/lsp-pack.yaml +48 -0
- package/dist/enterprise/bundle/registry/bundles/mcp-fabric.yaml +53 -0
- package/dist/enterprise/bundle/registry/bundles/preflight.yaml +48 -0
- package/dist/enterprise/bundle/registry/bundles/remote-supervisor.yaml +49 -0
- package/dist/enterprise/bundle/registry/bundles/robotics.yaml +45 -0
- package/dist/enterprise/bundle/registry/bundles/secure-worktree-pipeline.yaml +54 -0
- package/dist/enterprise/bundle/registry/bundles/security-check.yaml +50 -0
- package/dist/enterprise/bundle/registry/bundles/tracebank.yaml +47 -0
- package/dist/enterprise/bundle/registry/bundles/vision.yaml +45 -0
- package/dist/enterprise/bundle/registry/omg-capability.schema.json +296 -0
- package/dist/enterprise/bundle/settings.json +233 -5
- package/dist/enterprise/manifest.json +216 -12
- package/dist/public/bundle/.agents/skills/omg/AGENTS.fragment.md +50 -3
- package/dist/public/bundle/.agents/skills/omg/algorithms/SKILL.md +11 -0
- package/dist/public/bundle/.agents/skills/omg/algorithms/openai.yaml +11 -0
- package/dist/public/bundle/.agents/skills/omg/api-twin/SKILL.md +11 -0
- package/dist/public/bundle/.agents/skills/omg/api-twin/openai.yaml +12 -0
- package/dist/public/bundle/.agents/skills/omg/codex-rules.md +29 -0
- package/dist/public/bundle/.agents/skills/omg/data-lineage/SKILL.md +11 -0
- package/dist/public/bundle/.agents/skills/omg/data-lineage/openai.yaml +12 -0
- package/dist/public/bundle/.agents/skills/omg/delta-classifier/SKILL.md +11 -0
- package/dist/public/bundle/.agents/skills/omg/delta-classifier/openai.yaml +12 -0
- package/dist/public/bundle/.agents/skills/omg/eval-gate/SKILL.md +11 -0
- package/dist/public/bundle/.agents/skills/omg/eval-gate/openai.yaml +12 -0
- package/dist/public/bundle/.agents/skills/omg/health/SKILL.md +11 -0
- package/dist/public/bundle/.agents/skills/omg/health/openai.yaml +11 -0
- package/dist/public/bundle/.agents/skills/omg/incident-replay/SKILL.md +11 -0
- package/dist/public/bundle/.agents/skills/omg/incident-replay/openai.yaml +12 -0
- package/dist/public/bundle/.agents/skills/omg/preflight/SKILL.md +11 -0
- package/dist/public/bundle/.agents/skills/omg/preflight/openai.yaml +12 -0
- package/dist/public/bundle/.agents/skills/omg/remote-supervisor/SKILL.md +11 -0
- package/dist/public/bundle/.agents/skills/omg/remote-supervisor/openai.yaml +12 -0
- package/dist/public/bundle/.agents/skills/omg/robotics/SKILL.md +11 -0
- package/dist/public/bundle/.agents/skills/omg/robotics/openai.yaml +11 -0
- package/dist/public/bundle/.agents/skills/omg/security-check/SKILL.md +11 -0
- package/dist/public/bundle/.agents/skills/omg/security-check/openai.yaml +13 -0
- package/dist/public/bundle/.agents/skills/omg/tracebank/SKILL.md +11 -0
- package/dist/public/bundle/.agents/skills/omg/tracebank/openai.yaml +12 -0
- package/dist/public/bundle/.agents/skills/omg/vision/SKILL.md +11 -0
- package/dist/public/bundle/.agents/skills/omg/vision/openai.yaml +11 -0
- package/dist/public/bundle/.claude-plugin/marketplace.json +5 -5
- 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/commands/OMG:code-review.md +114 -0
- package/dist/public/bundle/plugins/advanced/commands/OMG:deep-plan.md +221 -0
- package/dist/public/bundle/plugins/advanced/commands/OMG:handoff.md +115 -0
- package/dist/public/bundle/plugins/advanced/commands/OMG:learn.md +110 -0
- package/dist/public/bundle/plugins/advanced/commands/OMG:maintainer.md +31 -0
- package/dist/public/bundle/plugins/advanced/commands/OMG:ralph-start.md +43 -0
- package/dist/public/bundle/plugins/advanced/commands/OMG:ralph-stop.md +23 -0
- package/dist/public/bundle/plugins/advanced/commands/OMG:security-review.md +16 -0
- package/dist/public/bundle/plugins/advanced/commands/OMG:sequential-thinking.md +20 -0
- package/dist/public/bundle/plugins/advanced/commands/OMG:ship.md +46 -0
- package/dist/public/bundle/plugins/advanced/plugin.json +87 -0
- package/dist/public/bundle/registry/bundles/algorithms.yaml +45 -0
- package/dist/public/bundle/registry/bundles/api-twin.yaml +48 -0
- package/dist/public/bundle/registry/bundles/control-plane.yaml +151 -0
- package/dist/public/bundle/registry/bundles/data-lineage.yaml +47 -0
- package/dist/public/bundle/registry/bundles/delta-classifier.yaml +47 -0
- package/dist/public/bundle/registry/bundles/eval-gate.yaml +47 -0
- package/dist/public/bundle/registry/bundles/health.yaml +45 -0
- package/dist/public/bundle/registry/bundles/hook-governor.yaml +97 -0
- package/dist/public/bundle/registry/bundles/incident-replay.yaml +47 -0
- package/dist/public/bundle/registry/bundles/lsp-pack.yaml +48 -0
- package/dist/public/bundle/registry/bundles/mcp-fabric.yaml +53 -0
- package/dist/public/bundle/registry/bundles/preflight.yaml +48 -0
- package/dist/public/bundle/registry/bundles/remote-supervisor.yaml +49 -0
- package/dist/public/bundle/registry/bundles/robotics.yaml +45 -0
- package/dist/public/bundle/registry/bundles/secure-worktree-pipeline.yaml +54 -0
- package/dist/public/bundle/registry/bundles/security-check.yaml +50 -0
- package/dist/public/bundle/registry/bundles/tracebank.yaml +47 -0
- package/dist/public/bundle/registry/bundles/vision.yaml +45 -0
- package/dist/public/bundle/registry/omg-capability.schema.json +296 -0
- package/dist/public/bundle/settings.json +232 -4
- package/dist/public/manifest.json +216 -12
- package/docs/assets/omg-hud.svg +32 -0
- package/docs/install/claude-code.md +31 -0
- package/docs/install/codex.md +29 -0
- package/docs/migration/native-adoption.md +57 -0
- package/docs/proof.md +65 -0
- package/docs/release-checklist.md +40 -0
- package/docs/transcripts/crazy.md +17 -0
- package/docs/transcripts/setup.md +25 -0
- package/hooks/policy_engine.py +122 -17
- package/hooks/setup_wizard.py +52 -12
- package/hooks/shadow_manager.py +27 -0
- package/package.json +2 -2
- package/plugins/README.md +5 -1
- package/plugins/__init__.py +1 -0
- package/plugins/advanced/commands/OMG:deep-plan.md +50 -6
- package/plugins/advanced/commands/OMG:ship.md +1 -1
- package/plugins/advanced/plugin.json +1 -10
- package/plugins/core/plugin.json +7 -1
- package/pyproject.toml +39 -3
- package/registry/__init__.py +1 -0
- package/registry/bundles/algorithms.yaml +45 -0
- package/registry/bundles/api-twin.yaml +48 -0
- package/registry/bundles/claim-judge.yaml +49 -0
- package/registry/bundles/control-plane.yaml +151 -0
- package/registry/bundles/data-lineage.yaml +47 -0
- package/registry/bundles/delta-classifier.yaml +47 -0
- package/registry/bundles/eval-gate.yaml +47 -0
- package/registry/bundles/health.yaml +45 -0
- package/registry/bundles/hook-governor.yaml +97 -0
- package/registry/bundles/incident-replay.yaml +47 -0
- package/registry/bundles/lsp-pack.yaml +48 -0
- package/registry/bundles/mcp-fabric.yaml +53 -0
- package/registry/bundles/plan-council.yaml +51 -0
- package/registry/bundles/preflight.yaml +48 -0
- package/registry/bundles/proof-gate.yaml +49 -0
- package/registry/bundles/remote-supervisor.yaml +49 -0
- package/registry/bundles/robotics.yaml +45 -0
- package/registry/bundles/secure-worktree-pipeline.yaml +54 -0
- package/registry/bundles/security-check.yaml +50 -0
- package/registry/bundles/test-intent-lock.yaml +49 -0
- package/registry/bundles/tracebank.yaml +47 -0
- package/registry/bundles/vision.yaml +45 -0
- package/registry/omg-capability.schema.json +296 -0
- package/registry/verify_artifact.py +90 -0
- package/runtime/adapters/claude.py +3 -0
- package/runtime/adapters/gpt.py +3 -0
- package/runtime/adapters/local.py +3 -0
- package/runtime/adoption.py +1 -1
- package/runtime/api_twin.py +334 -14
- package/runtime/asset_loader.py +62 -0
- package/runtime/business_workflow.py +14 -0
- package/runtime/claim_judge.py +95 -0
- package/runtime/compat.py +142 -2
- package/runtime/contract_compiler.py +1270 -50
- package/runtime/data_lineage.py +73 -0
- package/runtime/delta_classifier.py +81 -0
- package/runtime/domain_packs.py +12 -0
- package/runtime/ecosystem.py +1 -1
- package/runtime/eval_gate.py +96 -0
- package/runtime/incident_replay.py +47 -0
- package/runtime/mcp_config_writers.py +12 -0
- package/runtime/mcp_lifecycle.py +31 -9
- package/runtime/mcp_memory_server.py +1 -1
- package/runtime/omg_compat_contract_snapshot.json +1 -1
- package/runtime/omg_contract_snapshot.json +1 -1
- package/runtime/omg_mcp_server.py +16 -9
- package/runtime/playwright_pack.py +169 -0
- package/runtime/preflight.py +66 -1
- package/runtime/proof_chain.py +228 -0
- package/runtime/proof_gate.py +163 -0
- package/runtime/remote_supervisor.py +64 -0
- package/runtime/security_check.py +626 -8
- package/runtime/team_router.py +6 -6
- package/runtime/test_intent_lock.py +91 -0
- package/runtime/tracebank.py +95 -0
- package/runtime/untrusted_content.py +172 -5
- package/scripts/check-omg-public-ready.py +77 -0
- package/scripts/omg.py +207 -3
- package/scripts/verify-standalone.sh +7 -0
- package/settings.json +233 -5
|
@@ -0,0 +1,1167 @@
|
|
|
1
|
+
"""Internal team router for OMG standalone operation."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from dataclasses import dataclass, asdict
|
|
5
|
+
from datetime import datetime, timezone
|
|
6
|
+
from concurrent.futures import ThreadPoolExecutor, as_completed
|
|
7
|
+
import glob
|
|
8
|
+
import json
|
|
9
|
+
import logging
|
|
10
|
+
import os
|
|
11
|
+
import re
|
|
12
|
+
import shlex
|
|
13
|
+
import shutil
|
|
14
|
+
import subprocess
|
|
15
|
+
import threading
|
|
16
|
+
import uuid
|
|
17
|
+
from typing import Any
|
|
18
|
+
|
|
19
|
+
# --- Path resolution (never relies on CWD) ---
|
|
20
|
+
_ROUTER_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
21
|
+
_OMG_ROOT = os.path.dirname(_ROUTER_DIR)
|
|
22
|
+
|
|
23
|
+
_logger = logging.getLogger(__name__)
|
|
24
|
+
|
|
25
|
+
# Import providers to trigger auto-registration in provider registry
|
|
26
|
+
try:
|
|
27
|
+
import runtime.providers.codex_provider # noqa: F401 # pyright: ignore[reportUnusedImport]
|
|
28
|
+
import runtime.providers.gemini_provider # noqa: F401 # pyright: ignore[reportUnusedImport]
|
|
29
|
+
import runtime.providers.kimi_provider # noqa: F401 # pyright: ignore[reportUnusedImport]
|
|
30
|
+
except ImportError:
|
|
31
|
+
pass
|
|
32
|
+
|
|
33
|
+
from runtime.runtime_profile import resolve_parallel_workers
|
|
34
|
+
|
|
35
|
+
@dataclass
|
|
36
|
+
class TeamDispatchRequest:
|
|
37
|
+
target: str # codex | gemini | ccg | auto
|
|
38
|
+
problem: str
|
|
39
|
+
context: str = ""
|
|
40
|
+
files: list[str] | None = None
|
|
41
|
+
expected_outcome: str = ""
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@dataclass
|
|
45
|
+
class TeamDispatchResult:
|
|
46
|
+
status: str
|
|
47
|
+
findings: list[str]
|
|
48
|
+
actions: list[str]
|
|
49
|
+
evidence: dict[str, Any]
|
|
50
|
+
|
|
51
|
+
def to_dict(self) -> dict[str, Any]:
|
|
52
|
+
out = asdict(self)
|
|
53
|
+
out["schema"] = "TeamDispatchResult"
|
|
54
|
+
return out
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _infer_target(problem: str) -> str:
|
|
58
|
+
p = problem.lower()
|
|
59
|
+
# Explicit target keywords should always win.
|
|
60
|
+
ccg_kw = bool(re.search(r"\bccg\b", p)) or "tri-track" in p or "tri track" in p
|
|
61
|
+
gemini_kw = bool(re.search(r"\bgemini\b", p))
|
|
62
|
+
codex_kw = bool(re.search(r"\bcodex\b", p))
|
|
63
|
+
|
|
64
|
+
if ccg_kw or (gemini_kw and codex_kw):
|
|
65
|
+
return "ccg"
|
|
66
|
+
if gemini_kw:
|
|
67
|
+
return "gemini"
|
|
68
|
+
if codex_kw:
|
|
69
|
+
return "codex"
|
|
70
|
+
|
|
71
|
+
ui_signals = ["ui", "ux", "layout", "css", "visual", "responsive", "frontend"]
|
|
72
|
+
code_signals = ["auth", "security", "backend", "debug", "performance", "algorithm"]
|
|
73
|
+
ccg_signals = [
|
|
74
|
+
"full-stack",
|
|
75
|
+
"full stack",
|
|
76
|
+
"front-end and back-end",
|
|
77
|
+
"frontend and backend",
|
|
78
|
+
"backend and frontend",
|
|
79
|
+
"cross-functional",
|
|
80
|
+
"review everything",
|
|
81
|
+
"architecture",
|
|
82
|
+
"system design",
|
|
83
|
+
"e2e",
|
|
84
|
+
"end-to-end",
|
|
85
|
+
]
|
|
86
|
+
|
|
87
|
+
ui_hit = any(k in p for k in ui_signals)
|
|
88
|
+
code_hit = any(k in p for k in code_signals)
|
|
89
|
+
ccg_hit = any(k in p for k in ccg_signals)
|
|
90
|
+
|
|
91
|
+
if ccg_hit or (ui_hit and code_hit):
|
|
92
|
+
return "ccg"
|
|
93
|
+
if ui_hit:
|
|
94
|
+
return "gemini"
|
|
95
|
+
if code_hit:
|
|
96
|
+
return "codex"
|
|
97
|
+
return "codex"
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def _check_tool_available(tool_name: str) -> bool:
|
|
101
|
+
"""Return True if *tool_name* is on PATH, else log a warning."""
|
|
102
|
+
if shutil.which(tool_name) is not None:
|
|
103
|
+
return True
|
|
104
|
+
_logger.warning("Tool %r not found on PATH — skipping %s dispatch", tool_name, tool_name)
|
|
105
|
+
return False
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def _run_tool(cmd: list[str], *, timeout: int = 30) -> subprocess.CompletedProcess[str]:
|
|
109
|
+
"""Run an external tool with a mandatory timeout.
|
|
110
|
+
|
|
111
|
+
Every subprocess call in the team router MUST go through this helper
|
|
112
|
+
to guarantee the ``timeout`` parameter is always set.
|
|
113
|
+
"""
|
|
114
|
+
return subprocess.run(
|
|
115
|
+
cmd,
|
|
116
|
+
capture_output=True,
|
|
117
|
+
text=True,
|
|
118
|
+
check=False,
|
|
119
|
+
timeout=timeout,
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
_TOOL_MAP: dict[str, str] = {
|
|
124
|
+
"codex": "codex",
|
|
125
|
+
"gemini": "gemini",
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
_INSTALL_HINTS: dict[str, str] = {
|
|
129
|
+
"codex": "Install Codex CLI: npm install -g @openai/codex",
|
|
130
|
+
"gemini": "Install Gemini CLI: npm install -g @google/gemini-cli",
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
_tmux_mgr: Any = None
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def _get_tmux_mgr() -> Any:
|
|
138
|
+
"""Return the module-level TmuxSessionManager singleton (lazy init)."""
|
|
139
|
+
global _tmux_mgr
|
|
140
|
+
if _tmux_mgr is None:
|
|
141
|
+
try:
|
|
142
|
+
from runtime.tmux_session_manager import TmuxSessionManager # pyright: ignore[reportMissingImports]
|
|
143
|
+
|
|
144
|
+
_tmux_mgr = TmuxSessionManager()
|
|
145
|
+
except ImportError:
|
|
146
|
+
class _FallbackMgr: # type: ignore[no-redef]
|
|
147
|
+
def is_tmux_available(self):
|
|
148
|
+
return False
|
|
149
|
+
|
|
150
|
+
_tmux_mgr = _FallbackMgr()
|
|
151
|
+
return _tmux_mgr
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def _should_use_tmux() -> bool:
|
|
155
|
+
"""Return True only when tmux is usable in this execution context.
|
|
156
|
+
|
|
157
|
+
Returns False if:
|
|
158
|
+
- tmux is not installed
|
|
159
|
+
- TERM env var is 'dumb' or empty (non-interactive terminal)
|
|
160
|
+
- Running inside a ThreadPoolExecutor worker thread
|
|
161
|
+
"""
|
|
162
|
+
try:
|
|
163
|
+
if not _get_tmux_mgr().is_tmux_available():
|
|
164
|
+
return False
|
|
165
|
+
term = os.environ.get("TERM", "")
|
|
166
|
+
if term in ("dumb", ""):
|
|
167
|
+
return False
|
|
168
|
+
# Detect ThreadPoolExecutor worker threads (named 'ThreadPoolExecutor-N_N')
|
|
169
|
+
thread_name = threading.current_thread().name
|
|
170
|
+
if "ThreadPoolExecutor" in thread_name:
|
|
171
|
+
return False
|
|
172
|
+
return True
|
|
173
|
+
except Exception:
|
|
174
|
+
return False
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def _auth_status_command(tool_name: str) -> list[str] | None:
|
|
178
|
+
if tool_name == "codex":
|
|
179
|
+
return ["codex", "auth", "status"]
|
|
180
|
+
if tool_name == "gemini":
|
|
181
|
+
return ["gemini", "auth", "status"]
|
|
182
|
+
return None
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def _check_tool_auth(tool_name: str) -> tuple[bool | None, str]:
|
|
186
|
+
cmd = _auth_status_command(tool_name)
|
|
187
|
+
if cmd is None:
|
|
188
|
+
return None, "auth status check not supported"
|
|
189
|
+
try:
|
|
190
|
+
probe = _run_tool(cmd, timeout=15)
|
|
191
|
+
except subprocess.TimeoutExpired:
|
|
192
|
+
return None, "auth status check timed out"
|
|
193
|
+
except FileNotFoundError:
|
|
194
|
+
return False, "CLI is not installed"
|
|
195
|
+
except Exception as exc:
|
|
196
|
+
return None, f"auth status check failed: {exc}"
|
|
197
|
+
|
|
198
|
+
output = f"{probe.stdout}\n{probe.stderr}".lower()
|
|
199
|
+
if probe.returncode == 0:
|
|
200
|
+
if "not logged" in output or "not authenticated" in output or "login required" in output:
|
|
201
|
+
return False, "CLI is installed but not authenticated"
|
|
202
|
+
return True, "CLI is authenticated"
|
|
203
|
+
|
|
204
|
+
unsupported_markers = ("unknown command", "unrecognized", "invalid choice", "did you mean")
|
|
205
|
+
if any(marker in output for marker in unsupported_markers):
|
|
206
|
+
return None, "auth status subcommand is unavailable"
|
|
207
|
+
if "not logged" in output or "not authenticated" in output or "login" in output:
|
|
208
|
+
return False, "CLI is installed but not authenticated"
|
|
209
|
+
return None, f"unable to verify auth status (exit={probe.returncode})"
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
def _collect_cli_health(target: str) -> dict[str, dict[str, Any]]:
|
|
213
|
+
if target == "ccg":
|
|
214
|
+
providers = ("codex", "gemini")
|
|
215
|
+
elif target in ("codex", "gemini"):
|
|
216
|
+
providers = (target,)
|
|
217
|
+
else:
|
|
218
|
+
providers = tuple()
|
|
219
|
+
|
|
220
|
+
health: dict[str, dict[str, Any]] = {}
|
|
221
|
+
for provider in providers:
|
|
222
|
+
available = _check_tool_available(provider)
|
|
223
|
+
auth_ok: bool | None = None
|
|
224
|
+
auth_message = "CLI is not installed"
|
|
225
|
+
if available:
|
|
226
|
+
auth_ok, auth_message = _check_tool_auth(provider)
|
|
227
|
+
live_connection = bool(available and auth_ok is True)
|
|
228
|
+
health[provider] = {
|
|
229
|
+
"available": available,
|
|
230
|
+
"auth_ok": auth_ok,
|
|
231
|
+
"live_connection": live_connection,
|
|
232
|
+
"status_message": auth_message,
|
|
233
|
+
"install_hint": _INSTALL_HINTS.get(provider, ""),
|
|
234
|
+
}
|
|
235
|
+
return health
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
def dispatch_team(req: TeamDispatchRequest) -> TeamDispatchResult:
|
|
239
|
+
target = req.target.lower().strip()
|
|
240
|
+
if target == "auto":
|
|
241
|
+
target = _infer_target(req.problem)
|
|
242
|
+
|
|
243
|
+
findings = [f"Target router selected: {target}", f"Problem: {req.problem}"]
|
|
244
|
+
if req.files:
|
|
245
|
+
findings.append(f"Focus files: {', '.join(req.files[:8])}")
|
|
246
|
+
if req.expected_outcome:
|
|
247
|
+
findings.append(f"Expected: {req.expected_outcome}")
|
|
248
|
+
|
|
249
|
+
cli_health = _collect_cli_health(target)
|
|
250
|
+
for provider, info in cli_health.items():
|
|
251
|
+
if info.get("live_connection"):
|
|
252
|
+
findings.append(f"{provider} live connection: ready")
|
|
253
|
+
continue
|
|
254
|
+
if not info.get("available"):
|
|
255
|
+
findings.append(f"{provider} live connection: missing CLI ({info.get('install_hint', '').strip()})")
|
|
256
|
+
continue
|
|
257
|
+
findings.append(f"{provider} live connection: unavailable ({info.get('status_message', 'unknown status')})")
|
|
258
|
+
|
|
259
|
+
actions = []
|
|
260
|
+
if target == "codex":
|
|
261
|
+
actions.extend(
|
|
262
|
+
[
|
|
263
|
+
"Perform deep code-level analysis",
|
|
264
|
+
"Prioritize security and root-cause checks",
|
|
265
|
+
"Return fix strategy with verification commands",
|
|
266
|
+
]
|
|
267
|
+
)
|
|
268
|
+
elif target == "gemini":
|
|
269
|
+
actions.extend(
|
|
270
|
+
[
|
|
271
|
+
"Perform UI/UX and visual structure review",
|
|
272
|
+
"Return accessibility and responsive design improvements",
|
|
273
|
+
"Return component-level edit suggestions",
|
|
274
|
+
]
|
|
275
|
+
)
|
|
276
|
+
else:
|
|
277
|
+
actions.extend(
|
|
278
|
+
[
|
|
279
|
+
"Run parallel backend and frontend review tracks",
|
|
280
|
+
"Synthesize cross-cutting findings",
|
|
281
|
+
"Return merged action plan with dependency order",
|
|
282
|
+
]
|
|
283
|
+
)
|
|
284
|
+
|
|
285
|
+
evidence = {
|
|
286
|
+
"target": target,
|
|
287
|
+
"generated_at": datetime.now(timezone.utc).isoformat(),
|
|
288
|
+
"context_length": len(req.context or ""),
|
|
289
|
+
"file_count": len(req.files or []),
|
|
290
|
+
"cli_health": cli_health,
|
|
291
|
+
"live_connection": all(h.get("live_connection") for h in cli_health.values()) if cli_health else True,
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
return TeamDispatchResult(status="ok", findings=findings, actions=actions, evidence=evidence)
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
def package_prompt(agent_name: str, user_prompt: str, project_dir: str) -> str:
|
|
298
|
+
"""Build structured prompt for external CLI dispatch with rich context.
|
|
299
|
+
|
|
300
|
+
Enriches prompt with:
|
|
301
|
+
- Agent description from registry
|
|
302
|
+
- Working memory excerpt (if .omg/state/working-memory.md exists)
|
|
303
|
+
- Profile context (if .omg/state/profile.yaml exists)
|
|
304
|
+
- Recent failure history (if .omg/state/ledger/ exists)
|
|
305
|
+
|
|
306
|
+
Total prompt capped at 4000 chars (default), configurable via OMG_PROMPT_MAX_CHARS.
|
|
307
|
+
"""
|
|
308
|
+
import sys as _sys
|
|
309
|
+
|
|
310
|
+
_hooks_dir = os.path.join(
|
|
311
|
+
os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
|
|
312
|
+
"hooks",
|
|
313
|
+
)
|
|
314
|
+
if _hooks_dir not in _sys.path:
|
|
315
|
+
_sys.path.insert(0, _hooks_dir)
|
|
316
|
+
|
|
317
|
+
max_chars = int(os.environ.get("OMG_PROMPT_MAX_CHARS", "4000"))
|
|
318
|
+
sections = []
|
|
319
|
+
|
|
320
|
+
try:
|
|
321
|
+
from _agent_registry import AGENT_REGISTRY # pyright: ignore[reportMissingImports]
|
|
322
|
+
|
|
323
|
+
agent = AGENT_REGISTRY.get(agent_name, {})
|
|
324
|
+
description = agent.get("description", f"{agent_name} specialist")
|
|
325
|
+
model_version = agent.get("model_version", "not specified")
|
|
326
|
+
|
|
327
|
+
sections.append(f"You are a {description}")
|
|
328
|
+
sections.append(f"Model: {model_version}")
|
|
329
|
+
|
|
330
|
+
except Exception:
|
|
331
|
+
sections.append(f"Agent: {agent_name}")
|
|
332
|
+
|
|
333
|
+
sections.append(f"Project: {project_dir}")
|
|
334
|
+
|
|
335
|
+
working_memory_excerpt = _read_working_memory(project_dir)
|
|
336
|
+
if working_memory_excerpt:
|
|
337
|
+
sections.append(f"Working Memory:\n{working_memory_excerpt}")
|
|
338
|
+
|
|
339
|
+
profile_context = _read_profile_context(project_dir)
|
|
340
|
+
if profile_context:
|
|
341
|
+
sections.append(f"Profile:\n{profile_context}")
|
|
342
|
+
|
|
343
|
+
failure_history = _read_failure_history(project_dir)
|
|
344
|
+
if failure_history:
|
|
345
|
+
sections.append(f"Recent Failures:\n{failure_history}")
|
|
346
|
+
|
|
347
|
+
sections.append(f"Task: {user_prompt}")
|
|
348
|
+
|
|
349
|
+
sections.append("Constraints: Follow existing patterns. No hardcoded secrets. Verify changes.")
|
|
350
|
+
|
|
351
|
+
result = "\n\n".join(sections)
|
|
352
|
+
|
|
353
|
+
if len(result) > max_chars:
|
|
354
|
+
result = result[:max_chars].rstrip()
|
|
355
|
+
|
|
356
|
+
return result
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
def _read_working_memory(project_dir: str) -> str:
|
|
360
|
+
"""Read working memory excerpt from .omg/state/working-memory.md."""
|
|
361
|
+
working_memory_path = os.path.join(project_dir, ".omg", "state", "working-memory.md")
|
|
362
|
+
if not os.path.exists(working_memory_path):
|
|
363
|
+
return ""
|
|
364
|
+
|
|
365
|
+
try:
|
|
366
|
+
with open(working_memory_path, "r") as f:
|
|
367
|
+
content = f.read()
|
|
368
|
+
if len(content) > 500:
|
|
369
|
+
content = content[:500] + "..."
|
|
370
|
+
return content
|
|
371
|
+
except OSError:
|
|
372
|
+
return ""
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
def _read_profile_context(project_dir: str) -> str:
|
|
376
|
+
"""Read profile context from .omg/state/profile.yaml."""
|
|
377
|
+
profile_path = os.path.join(project_dir, ".omg", "state", "profile.yaml")
|
|
378
|
+
if not os.path.exists(profile_path):
|
|
379
|
+
return ""
|
|
380
|
+
|
|
381
|
+
try:
|
|
382
|
+
with open(profile_path, "r") as f:
|
|
383
|
+
content = f.read()
|
|
384
|
+
if len(content) > 300:
|
|
385
|
+
content = content[:300] + "..."
|
|
386
|
+
return content
|
|
387
|
+
except OSError:
|
|
388
|
+
return ""
|
|
389
|
+
|
|
390
|
+
|
|
391
|
+
def _read_failure_history(project_dir: str) -> str:
|
|
392
|
+
"""Read recent failures from .omg/state/ledger/."""
|
|
393
|
+
ledger_dir = os.path.join(project_dir, ".omg", "state", "ledger")
|
|
394
|
+
if not os.path.exists(ledger_dir):
|
|
395
|
+
return ""
|
|
396
|
+
|
|
397
|
+
try:
|
|
398
|
+
failure_files = sorted(glob.glob(os.path.join(ledger_dir, "failure-*.jsonl")))
|
|
399
|
+
if not failure_files:
|
|
400
|
+
return ""
|
|
401
|
+
|
|
402
|
+
failures = []
|
|
403
|
+
for file_path in failure_files[-5:]:
|
|
404
|
+
try:
|
|
405
|
+
with open(file_path, "r") as f:
|
|
406
|
+
for line in f:
|
|
407
|
+
if line.strip():
|
|
408
|
+
entry = json.loads(line)
|
|
409
|
+
error_msg = entry.get("error", "Unknown error")
|
|
410
|
+
failures.append(f"- {error_msg}")
|
|
411
|
+
if len(failures) >= 5:
|
|
412
|
+
break
|
|
413
|
+
except (OSError, json.JSONDecodeError):
|
|
414
|
+
continue
|
|
415
|
+
|
|
416
|
+
if failures:
|
|
417
|
+
return "\n".join(failures[:5])
|
|
418
|
+
return ""
|
|
419
|
+
except Exception:
|
|
420
|
+
return ""
|
|
421
|
+
|
|
422
|
+
|
|
423
|
+
def invoke_codex(prompt: str, project_dir: str, timeout: int = 120) -> dict[str, Any]:
|
|
424
|
+
"""Invoke codex-cli as subprocess. Returns result dict with model/output/exit_code or error/fallback."""
|
|
425
|
+
if not _check_tool_available("codex"):
|
|
426
|
+
return {"error": "codex-cli not found", "fallback": "claude"}
|
|
427
|
+
try:
|
|
428
|
+
result = _run_tool(
|
|
429
|
+
["codex", "exec", "--json", prompt],
|
|
430
|
+
timeout=timeout,
|
|
431
|
+
)
|
|
432
|
+
return {
|
|
433
|
+
"model": "codex-cli",
|
|
434
|
+
"output": result.stdout,
|
|
435
|
+
"exit_code": result.returncode,
|
|
436
|
+
}
|
|
437
|
+
except subprocess.TimeoutExpired:
|
|
438
|
+
return {"error": "codex-cli timeout", "fallback": "claude"}
|
|
439
|
+
except FileNotFoundError:
|
|
440
|
+
return {"error": "codex-cli not found", "fallback": "claude"}
|
|
441
|
+
except Exception as exc:
|
|
442
|
+
return {"error": str(exc), "fallback": "claude"}
|
|
443
|
+
|
|
444
|
+
|
|
445
|
+
_TMUX_EXIT_MARKER = "__OMG_TMUX_EXIT_CODE__"
|
|
446
|
+
_TMUX_EXIT_CODE_RE = re.compile(r"(?:\r?\n)?__OMG_TMUX_EXIT_CODE__:(\d+)\s*$")
|
|
447
|
+
|
|
448
|
+
|
|
449
|
+
def _parse_tmux_command_result(output: str) -> tuple[str, int]:
|
|
450
|
+
"""Extract exit code marker from tmux output and return cleaned output + exit code."""
|
|
451
|
+
match = _TMUX_EXIT_CODE_RE.search(output)
|
|
452
|
+
if not match:
|
|
453
|
+
raise RuntimeError("tmux output missing exit code marker")
|
|
454
|
+
exit_code = int(match.group(1))
|
|
455
|
+
cleaned = _TMUX_EXIT_CODE_RE.sub("", output).rstrip()
|
|
456
|
+
return cleaned, exit_code
|
|
457
|
+
|
|
458
|
+
|
|
459
|
+
def invoke_codex_tmux(prompt: str, project_dir: str, timeout: int = 120) -> dict[str, Any]:
|
|
460
|
+
"""Invoke codex-cli via persistent tmux session. Falls back to subprocess on error."""
|
|
461
|
+
if not _check_tool_available("codex"):
|
|
462
|
+
return {"error": "codex-cli not found", "fallback": "claude"}
|
|
463
|
+
|
|
464
|
+
mgr = _get_tmux_mgr()
|
|
465
|
+
session: str | None = None
|
|
466
|
+
try:
|
|
467
|
+
session_name = mgr.make_session_name("codex", unique_id=str(uuid.uuid4())[:8])
|
|
468
|
+
session = mgr.get_or_create_session(session_name)
|
|
469
|
+
quoted_prompt = shlex.quote(prompt)
|
|
470
|
+
cmd = f"codex exec --json {quoted_prompt}; printf '\\n{_TMUX_EXIT_MARKER}:%s\\n' \"$?\""
|
|
471
|
+
raw_output = mgr.send_command(session, cmd, timeout=timeout)
|
|
472
|
+
output, exit_code = _parse_tmux_command_result(raw_output)
|
|
473
|
+
return {"model": "codex-cli", "output": output, "exit_code": exit_code}
|
|
474
|
+
except Exception as exc:
|
|
475
|
+
_logger.warning("tmux codex invocation failed, falling back to subprocess: %s", exc)
|
|
476
|
+
return invoke_codex(prompt, project_dir, timeout=timeout)
|
|
477
|
+
finally:
|
|
478
|
+
if session:
|
|
479
|
+
mgr.kill_session(session)
|
|
480
|
+
|
|
481
|
+
|
|
482
|
+
def invoke_gemini(prompt: str, project_dir: str, timeout: int = 120) -> dict[str, Any]:
|
|
483
|
+
"""Invoke gemini-cli as subprocess. Returns result dict with model/output/exit_code or error/fallback."""
|
|
484
|
+
if not _check_tool_available("gemini"):
|
|
485
|
+
return {"error": "gemini-cli not found", "fallback": "claude"}
|
|
486
|
+
try:
|
|
487
|
+
result = _run_tool(
|
|
488
|
+
["gemini", "-p", prompt],
|
|
489
|
+
timeout=timeout,
|
|
490
|
+
)
|
|
491
|
+
return {
|
|
492
|
+
"model": "gemini-cli",
|
|
493
|
+
"output": result.stdout,
|
|
494
|
+
"exit_code": result.returncode,
|
|
495
|
+
}
|
|
496
|
+
except subprocess.TimeoutExpired:
|
|
497
|
+
return {"error": "gemini-cli timeout", "fallback": "claude"}
|
|
498
|
+
except FileNotFoundError:
|
|
499
|
+
return {"error": "gemini-cli not found", "fallback": "claude"}
|
|
500
|
+
except Exception as exc:
|
|
501
|
+
return {"error": str(exc), "fallback": "claude"}
|
|
502
|
+
|
|
503
|
+
|
|
504
|
+
def invoke_gemini_tmux(prompt: str, project_dir: str, timeout: int = 120) -> dict[str, Any]:
|
|
505
|
+
"""Invoke gemini-cli via persistent tmux session. Falls back to subprocess on error."""
|
|
506
|
+
if not _check_tool_available("gemini"):
|
|
507
|
+
return {"error": "gemini-cli not found", "fallback": "claude"}
|
|
508
|
+
|
|
509
|
+
mgr = _get_tmux_mgr()
|
|
510
|
+
session: str | None = None
|
|
511
|
+
try:
|
|
512
|
+
session_name = mgr.make_session_name("gemini", unique_id=str(uuid.uuid4())[:8])
|
|
513
|
+
session = mgr.get_or_create_session(session_name)
|
|
514
|
+
quoted_prompt = shlex.quote(prompt)
|
|
515
|
+
cmd = f"gemini -p {quoted_prompt}; printf '\\n{_TMUX_EXIT_MARKER}:%s\\n' \"$?\""
|
|
516
|
+
raw_output = mgr.send_command(session, cmd, timeout=timeout)
|
|
517
|
+
output, exit_code = _parse_tmux_command_result(raw_output)
|
|
518
|
+
return {"model": "gemini-cli", "output": output, "exit_code": exit_code}
|
|
519
|
+
except Exception as exc:
|
|
520
|
+
_logger.warning("tmux gemini invocation failed, falling back to subprocess: %s", exc)
|
|
521
|
+
return invoke_gemini(prompt, project_dir, timeout=timeout)
|
|
522
|
+
finally:
|
|
523
|
+
if session:
|
|
524
|
+
mgr.kill_session(session)
|
|
525
|
+
|
|
526
|
+
|
|
527
|
+
def dispatch_to_model(agent_name: str, user_prompt: str, project_dir: str) -> dict[str, Any]:
|
|
528
|
+
"""Dispatch a task to the preferred model for this agent.
|
|
529
|
+
|
|
530
|
+
Returns result dict. If preferred model unavailable, returns fallback dict.
|
|
531
|
+
"""
|
|
532
|
+
import sys as _sys
|
|
533
|
+
|
|
534
|
+
_hooks_dir = os.path.join(
|
|
535
|
+
os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
|
|
536
|
+
"hooks",
|
|
537
|
+
)
|
|
538
|
+
if _hooks_dir not in _sys.path:
|
|
539
|
+
_sys.path.insert(0, _hooks_dir)
|
|
540
|
+
try:
|
|
541
|
+
from _agent_registry import AGENT_REGISTRY, detect_available_models # pyright: ignore[reportMissingImports]
|
|
542
|
+
|
|
543
|
+
agent = AGENT_REGISTRY.get(agent_name)
|
|
544
|
+
if not agent:
|
|
545
|
+
return {"error": f"Unknown agent: {agent_name}", "fallback": "claude"}
|
|
546
|
+
|
|
547
|
+
available = detect_available_models()
|
|
548
|
+
preferred = agent.get("preferred_model", "claude")
|
|
549
|
+
packaged = package_prompt(agent_name, user_prompt, project_dir)
|
|
550
|
+
|
|
551
|
+
provider_name_map = {
|
|
552
|
+
"codex-cli": "codex",
|
|
553
|
+
"gemini-cli": "gemini",
|
|
554
|
+
"kimi-cli": "kimi",
|
|
555
|
+
}
|
|
556
|
+
provider_name = provider_name_map.get(preferred)
|
|
557
|
+
|
|
558
|
+
if provider_name and available.get(preferred, True):
|
|
559
|
+
from runtime.cli_provider import get_provider
|
|
560
|
+
|
|
561
|
+
provider = get_provider(provider_name)
|
|
562
|
+
if provider and provider.detect():
|
|
563
|
+
if _should_use_tmux():
|
|
564
|
+
return provider.invoke_tmux(packaged, project_dir)
|
|
565
|
+
return provider.invoke(packaged, project_dir)
|
|
566
|
+
|
|
567
|
+
if preferred == "codex-cli" and available.get("codex-cli"):
|
|
568
|
+
if _should_use_tmux():
|
|
569
|
+
return invoke_codex_tmux(packaged, project_dir)
|
|
570
|
+
return invoke_codex(packaged, project_dir)
|
|
571
|
+
if preferred == "gemini-cli" and available.get("gemini-cli"):
|
|
572
|
+
if _should_use_tmux():
|
|
573
|
+
return invoke_gemini_tmux(packaged, project_dir)
|
|
574
|
+
return invoke_gemini(packaged, project_dir)
|
|
575
|
+
# Fallback: use Claude native task() dispatch
|
|
576
|
+
return {
|
|
577
|
+
"fallback": "claude",
|
|
578
|
+
"category": agent.get("task_category", "deep"),
|
|
579
|
+
"skills": agent.get("skills", []),
|
|
580
|
+
"model_version": agent.get("model_version", "unknown"),
|
|
581
|
+
}
|
|
582
|
+
except Exception as exc:
|
|
583
|
+
return {"error": str(exc), "fallback": "claude"}
|
|
584
|
+
|
|
585
|
+
|
|
586
|
+
def get_core_agent_model(agent_name: str) -> dict[str, Any] | None:
|
|
587
|
+
"""Get model preference for a core (non-keyword-matched) agent."""
|
|
588
|
+
import sys as _sys
|
|
589
|
+
_hooks_dir = os.path.join(
|
|
590
|
+
os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
|
|
591
|
+
"hooks",
|
|
592
|
+
)
|
|
593
|
+
if _hooks_dir not in _sys.path:
|
|
594
|
+
_sys.path.insert(0, _hooks_dir)
|
|
595
|
+
try:
|
|
596
|
+
from _agent_registry import CORE_AGENT_MODELS # pyright: ignore[reportMissingImports]
|
|
597
|
+
return CORE_AGENT_MODELS.get(agent_name)
|
|
598
|
+
except Exception:
|
|
599
|
+
return None
|
|
600
|
+
|
|
601
|
+
|
|
602
|
+
|
|
603
|
+
def execute_agents_sequentially(
|
|
604
|
+
agent_tasks: list[dict[str, Any]],
|
|
605
|
+
project_dir: str,
|
|
606
|
+
timeout_per_agent: int = 120
|
|
607
|
+
) -> list[dict[str, Any]]:
|
|
608
|
+
"""Execute agents sequentially (one at a time) for CRAZY mode.
|
|
609
|
+
|
|
610
|
+
Args:
|
|
611
|
+
agent_tasks: List of {agent_name, prompt, order} dicts
|
|
612
|
+
project_dir: Working directory
|
|
613
|
+
timeout_per_agent: Timeout for each agent invocation
|
|
614
|
+
|
|
615
|
+
Returns:
|
|
616
|
+
List of results in execution order
|
|
617
|
+
"""
|
|
618
|
+
# Sort by order if specified
|
|
619
|
+
sorted_tasks = sorted(agent_tasks, key=lambda x: x.get("order", 0))
|
|
620
|
+
|
|
621
|
+
results: list[dict[str, Any]] = []
|
|
622
|
+
|
|
623
|
+
for task in sorted_tasks:
|
|
624
|
+
agent_name = task.get("agent_name", "executor")
|
|
625
|
+
prompt = task.get("prompt", "")
|
|
626
|
+
|
|
627
|
+
print(f"[CRAZY] Launching {agent_name}...")
|
|
628
|
+
|
|
629
|
+
# Dispatch to the appropriate model
|
|
630
|
+
result = dispatch_to_model(agent_name, prompt, project_dir)
|
|
631
|
+
|
|
632
|
+
if result.get("fallback") == "claude":
|
|
633
|
+
print(f"[CRAZY] {agent_name} using Claude (native)")
|
|
634
|
+
status = "fallback-claude"
|
|
635
|
+
elif "error" in result:
|
|
636
|
+
print(f"[CRAZY] {agent_name} error: {result['error']}")
|
|
637
|
+
status = "error"
|
|
638
|
+
else:
|
|
639
|
+
print(f"[CRAZY] {agent_name} completed (exit={result.get('exit_code', 'unknown')})")
|
|
640
|
+
status = "completed" if result.get("exit_code") == 0 else "failed"
|
|
641
|
+
|
|
642
|
+
results.append({
|
|
643
|
+
"agent": agent_name,
|
|
644
|
+
"order": task.get("order", 0),
|
|
645
|
+
"status": status,
|
|
646
|
+
**result
|
|
647
|
+
})
|
|
648
|
+
|
|
649
|
+
return results
|
|
650
|
+
|
|
651
|
+
|
|
652
|
+
def execute_agents_parallel(
|
|
653
|
+
agent_tasks: list[dict[str, Any]],
|
|
654
|
+
project_dir: str,
|
|
655
|
+
timeout_per_agent: int = 120,
|
|
656
|
+
) -> list[dict[str, Any]]:
|
|
657
|
+
indexed_tasks: list[tuple[int, int, dict[str, Any]]] = [
|
|
658
|
+
(idx, int(task.get("order", 0)), task) for idx, task in enumerate(agent_tasks)
|
|
659
|
+
]
|
|
660
|
+
sorted_tasks = sorted(indexed_tasks, key=lambda x: (x[1], x[0]))
|
|
661
|
+
if not sorted_tasks:
|
|
662
|
+
return []
|
|
663
|
+
|
|
664
|
+
max_workers = resolve_parallel_workers(project_dir, requested_workers=min(len(sorted_tasks), 5))
|
|
665
|
+
results_by_index: dict[int, dict[str, Any]] = {}
|
|
666
|
+
|
|
667
|
+
with ThreadPoolExecutor(max_workers=max_workers) as pool:
|
|
668
|
+
future_map = {
|
|
669
|
+
pool.submit(
|
|
670
|
+
dispatch_to_model,
|
|
671
|
+
str(task_info[2].get("agent_name", "executor")),
|
|
672
|
+
str(task_info[2].get("prompt", "")),
|
|
673
|
+
project_dir,
|
|
674
|
+
): task_info
|
|
675
|
+
for task_info in sorted_tasks
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
for future in as_completed(future_map):
|
|
679
|
+
task_info = future_map[future]
|
|
680
|
+
task = task_info[2]
|
|
681
|
+
order = task_info[1]
|
|
682
|
+
task_index = task_info[0]
|
|
683
|
+
agent_name = str(task.get("agent_name", "executor"))
|
|
684
|
+
|
|
685
|
+
try:
|
|
686
|
+
result = future.result(timeout=timeout_per_agent)
|
|
687
|
+
except Exception as exc:
|
|
688
|
+
result = {"error": str(exc), "fallback": "claude"}
|
|
689
|
+
|
|
690
|
+
if result.get("fallback") == "claude":
|
|
691
|
+
status = "fallback-claude"
|
|
692
|
+
elif "error" in result:
|
|
693
|
+
status = "error"
|
|
694
|
+
else:
|
|
695
|
+
status = "completed" if result.get("exit_code") == 0 else "failed"
|
|
696
|
+
|
|
697
|
+
results_by_index[task_index] = {
|
|
698
|
+
"agent": agent_name,
|
|
699
|
+
"order": order,
|
|
700
|
+
"status": status,
|
|
701
|
+
**result,
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
ordered_results = [results_by_index[task_info[0]] for task_info in sorted_tasks]
|
|
705
|
+
return ordered_results
|
|
706
|
+
|
|
707
|
+
|
|
708
|
+
def execute_crazy_mode(
|
|
709
|
+
problem: str,
|
|
710
|
+
project_dir: str,
|
|
711
|
+
context: str | None = None,
|
|
712
|
+
files: list[str] | None = None
|
|
713
|
+
) -> dict[str, Any]:
|
|
714
|
+
print("[CRAZY] Starting parallel agent execution...")
|
|
715
|
+
print(f"[CRAZY] Problem: {problem[:100]}...")
|
|
716
|
+
|
|
717
|
+
# Build context package
|
|
718
|
+
context_parts = []
|
|
719
|
+
if context:
|
|
720
|
+
context_parts.append(context)
|
|
721
|
+
if files:
|
|
722
|
+
context_parts.append(f"Focus files: {', '.join(files[:8])}")
|
|
723
|
+
full_context = "\n\n".join(context_parts) if context_parts else ""
|
|
724
|
+
|
|
725
|
+
worker_tasks = [
|
|
726
|
+
{
|
|
727
|
+
"agent_name": "architect-mode",
|
|
728
|
+
"prompt": (
|
|
729
|
+
f"Plan decomposition for: {problem}\n\n"
|
|
730
|
+
f"Focus: scope, sequencing, dependency ordering, risk control.\n\n"
|
|
731
|
+
f"Context:\n{full_context}"
|
|
732
|
+
),
|
|
733
|
+
"order": 1,
|
|
734
|
+
},
|
|
735
|
+
{
|
|
736
|
+
"agent_name": "backend-engineer",
|
|
737
|
+
"prompt": (
|
|
738
|
+
f"Backend implementation strategy for: {problem}\n\n"
|
|
739
|
+
f"Focus: APIs, data flow, failure handling, performance.\n\n"
|
|
740
|
+
f"Context:\n{full_context}"
|
|
741
|
+
),
|
|
742
|
+
"order": 2,
|
|
743
|
+
},
|
|
744
|
+
{
|
|
745
|
+
"agent_name": "frontend-designer",
|
|
746
|
+
"prompt": (
|
|
747
|
+
f"Frontend/UI strategy for: {problem}\n\n"
|
|
748
|
+
f"Focus: UX, accessibility, responsive behavior, component structure.\n\n"
|
|
749
|
+
f"Context:\n{full_context}"
|
|
750
|
+
),
|
|
751
|
+
"order": 3,
|
|
752
|
+
},
|
|
753
|
+
{
|
|
754
|
+
"agent_name": "security-auditor",
|
|
755
|
+
"prompt": (
|
|
756
|
+
f"Security review strategy for: {problem}\n\n"
|
|
757
|
+
f"Focus: auth, secrets, input validation, abuse vectors.\n\n"
|
|
758
|
+
f"Context:\n{full_context}"
|
|
759
|
+
),
|
|
760
|
+
"order": 4,
|
|
761
|
+
},
|
|
762
|
+
{
|
|
763
|
+
"agent_name": "testing-engineer",
|
|
764
|
+
"prompt": (
|
|
765
|
+
f"Verification strategy for: {problem}\n\n"
|
|
766
|
+
f"Focus: unit/integration/e2e coverage and failure reproduction.\n\n"
|
|
767
|
+
f"Context:\n{full_context}"
|
|
768
|
+
),
|
|
769
|
+
"order": 5,
|
|
770
|
+
},
|
|
771
|
+
]
|
|
772
|
+
|
|
773
|
+
results = execute_agents_parallel(worker_tasks, project_dir)
|
|
774
|
+
|
|
775
|
+
result_blocks: list[str] = []
|
|
776
|
+
for r in results:
|
|
777
|
+
result_blocks.append(
|
|
778
|
+
f"**{r.get('agent', 'unknown')} [{r.get('status', 'unknown')}]:**\n"
|
|
779
|
+
f"{r.get('output', r.get('error', 'No output'))}"
|
|
780
|
+
)
|
|
781
|
+
|
|
782
|
+
synthesis_prompt = (
|
|
783
|
+
"Synthesize results from five specialized tracks:\n\n"
|
|
784
|
+
+ "\n\n".join(result_blocks)
|
|
785
|
+
+ "\n\nProvide a unified action plan with dependency ordering."
|
|
786
|
+
)
|
|
787
|
+
|
|
788
|
+
model_mix = {
|
|
789
|
+
"gpt": [r.get("agent") for r in results if r.get("model") == "codex-cli"],
|
|
790
|
+
"gemini": [r.get("agent") for r in results if r.get("model") == "gemini-cli"],
|
|
791
|
+
"claude": [r.get("agent") for r in results if r.get("fallback") == "claude"],
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
return {
|
|
795
|
+
"status": "ok",
|
|
796
|
+
"phases": [
|
|
797
|
+
{"phase": 1, "agent": "claude-orchestrator", "status": "completed"},
|
|
798
|
+
*[
|
|
799
|
+
{
|
|
800
|
+
"phase": idx,
|
|
801
|
+
"agent": r.get("agent"),
|
|
802
|
+
"status": r.get("status", "unknown"),
|
|
803
|
+
"model": r.get("model", r.get("fallback", "unknown")),
|
|
804
|
+
"output": r.get("output", ""),
|
|
805
|
+
}
|
|
806
|
+
for idx, r in enumerate(results, start=2)
|
|
807
|
+
],
|
|
808
|
+
{"phase": 7, "agent": "claude-synthesis", "prompt": synthesis_prompt},
|
|
809
|
+
],
|
|
810
|
+
"parallel_execution": True,
|
|
811
|
+
"sequential_execution": False,
|
|
812
|
+
"worker_count": len(results),
|
|
813
|
+
"target_worker_count": 5,
|
|
814
|
+
"model_mix": model_mix,
|
|
815
|
+
"findings": [
|
|
816
|
+
f"Workers launched: {len(results)}/5",
|
|
817
|
+
f"GPT tracks: {len(model_mix['gpt'])}",
|
|
818
|
+
f"Gemini tracks: {len(model_mix['gemini'])}",
|
|
819
|
+
f"Claude tracks: {len(model_mix['claude'])}",
|
|
820
|
+
],
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
|
|
824
|
+
def execute_ccg_mode(
|
|
825
|
+
problem: str,
|
|
826
|
+
project_dir: str,
|
|
827
|
+
context: str | None = None,
|
|
828
|
+
files: list[str] | None = None,
|
|
829
|
+
) -> dict[str, Any]:
|
|
830
|
+
"""CCG (Claude-Codex-Gemini) execution mode — 2-track parallel analysis.
|
|
831
|
+
|
|
832
|
+
Track 1: backend-engineer (Codex path) — backend/code analysis
|
|
833
|
+
Track 2: frontend-designer (Gemini path) — UI/UX analysis
|
|
834
|
+
Then synthesises both tracks into unified output.
|
|
835
|
+
"""
|
|
836
|
+
print("[CCG] Starting 2-track parallel agent execution...")
|
|
837
|
+
print(f"[CCG] Problem: {problem[:100]}...")
|
|
838
|
+
|
|
839
|
+
# Build context package
|
|
840
|
+
context_parts: list[str] = []
|
|
841
|
+
if context:
|
|
842
|
+
context_parts.append(context)
|
|
843
|
+
if files:
|
|
844
|
+
context_parts.append(f"Focus files: {', '.join(files[:8])}")
|
|
845
|
+
full_context = "\n\n".join(context_parts) if context_parts else ""
|
|
846
|
+
|
|
847
|
+
worker_tasks = [
|
|
848
|
+
{
|
|
849
|
+
"agent_name": "backend-engineer",
|
|
850
|
+
"prompt": (
|
|
851
|
+
f"Backend implementation strategy for: {problem}\n\n"
|
|
852
|
+
f"Focus: APIs, data flow, failure handling, performance.\n\n"
|
|
853
|
+
f"Context:\n{full_context}"
|
|
854
|
+
),
|
|
855
|
+
"order": 1,
|
|
856
|
+
},
|
|
857
|
+
{
|
|
858
|
+
"agent_name": "frontend-designer",
|
|
859
|
+
"prompt": (
|
|
860
|
+
f"Frontend/UI strategy for: {problem}\n\n"
|
|
861
|
+
f"Focus: UX, accessibility, responsive behavior, component structure.\n\n"
|
|
862
|
+
f"Context:\n{full_context}"
|
|
863
|
+
),
|
|
864
|
+
"order": 2,
|
|
865
|
+
},
|
|
866
|
+
]
|
|
867
|
+
|
|
868
|
+
results = execute_agents_parallel(worker_tasks, project_dir)
|
|
869
|
+
|
|
870
|
+
result_blocks: list[str] = []
|
|
871
|
+
for r in results:
|
|
872
|
+
result_blocks.append(
|
|
873
|
+
f"**{r.get('agent', 'unknown')} [{r.get('status', 'unknown')}]:**\n"
|
|
874
|
+
f"{r.get('output', r.get('error', 'No output'))}"
|
|
875
|
+
)
|
|
876
|
+
|
|
877
|
+
synthesis_prompt = (
|
|
878
|
+
"Synthesize results from two specialized CCG tracks:\n\n"
|
|
879
|
+
+ "\n\n".join(result_blocks)
|
|
880
|
+
+ "\n\nProvide a unified action plan merging backend and frontend perspectives."
|
|
881
|
+
)
|
|
882
|
+
|
|
883
|
+
model_mix = {
|
|
884
|
+
"gpt": [r.get("agent") for r in results if r.get("model") == "codex-cli"],
|
|
885
|
+
"gemini": [r.get("agent") for r in results if r.get("model") == "gemini-cli"],
|
|
886
|
+
"claude": [r.get("agent") for r in results if r.get("fallback") == "claude"],
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
return {
|
|
890
|
+
"status": "ok",
|
|
891
|
+
"phases": [
|
|
892
|
+
{"phase": 1, "agent": "claude-orchestrator", "status": "completed"},
|
|
893
|
+
*[
|
|
894
|
+
{
|
|
895
|
+
"phase": idx,
|
|
896
|
+
"agent": r.get("agent"),
|
|
897
|
+
"status": r.get("status", "unknown"),
|
|
898
|
+
"model": r.get("model", r.get("fallback", "unknown")),
|
|
899
|
+
"output": r.get("output", ""),
|
|
900
|
+
}
|
|
901
|
+
for idx, r in enumerate(results, start=2)
|
|
902
|
+
],
|
|
903
|
+
{"phase": len(results) + 2, "agent": "claude-synthesis", "prompt": synthesis_prompt},
|
|
904
|
+
],
|
|
905
|
+
"parallel_execution": True,
|
|
906
|
+
"sequential_execution": False,
|
|
907
|
+
"worker_count": len(results),
|
|
908
|
+
"target_worker_count": 2,
|
|
909
|
+
"model_mix": model_mix,
|
|
910
|
+
"findings": [
|
|
911
|
+
f"Workers launched: {len(results)}/2",
|
|
912
|
+
f"GPT tracks: {len(model_mix['gpt'])}",
|
|
913
|
+
f"Gemini tracks: {len(model_mix['gemini'])}",
|
|
914
|
+
f"Claude tracks: {len(model_mix['claude'])}",
|
|
915
|
+
],
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
|
|
919
|
+
# =============================================================================
|
|
920
|
+
# Round-Robin Credential Distribution (Feature: OMG_ROUND_ROBIN_ENABLED)
|
|
921
|
+
# =============================================================================
|
|
922
|
+
|
|
923
|
+
|
|
924
|
+
def _fnv1a_hash(data: str) -> int:
|
|
925
|
+
"""FNV-1a 32-bit hash for session-stable key assignment.
|
|
926
|
+
|
|
927
|
+
Deterministic: same input always produces the same hash.
|
|
928
|
+
Used to pin a session to a consistent starting key index.
|
|
929
|
+
"""
|
|
930
|
+
h = 2166136261
|
|
931
|
+
for c in data.encode():
|
|
932
|
+
h ^= c
|
|
933
|
+
h = (h * 16777619) & 0xFFFFFFFF
|
|
934
|
+
return h
|
|
935
|
+
|
|
936
|
+
|
|
937
|
+
def _get_hooks_imports():
|
|
938
|
+
"""Lazy-import credential_store and get_feature_flag.
|
|
939
|
+
|
|
940
|
+
Returns (credential_store_module, get_feature_flag_func) or (None, None).
|
|
941
|
+
Adds hooks dir to sys.path if needed (same pattern as package_prompt).
|
|
942
|
+
"""
|
|
943
|
+
import sys as _sys
|
|
944
|
+
|
|
945
|
+
_hooks_dir = os.path.join(_OMG_ROOT, "hooks")
|
|
946
|
+
if _hooks_dir not in _sys.path:
|
|
947
|
+
_sys.path.insert(0, _hooks_dir)
|
|
948
|
+
try:
|
|
949
|
+
from _common import get_feature_flag # pyright: ignore[reportMissingImports]
|
|
950
|
+
import credential_store # pyright: ignore[reportMissingImports]
|
|
951
|
+
|
|
952
|
+
return credential_store, get_feature_flag
|
|
953
|
+
except ImportError:
|
|
954
|
+
return None, None
|
|
955
|
+
|
|
956
|
+
|
|
957
|
+
def get_active_credential(provider: str, session_id: str | None = None) -> str | None:
|
|
958
|
+
"""Get active API key for provider via round-robin.
|
|
959
|
+
|
|
960
|
+
Returns key string or None if credential store disabled/unavailable.
|
|
961
|
+
Feature flag: OMG_ROUND_ROBIN_ENABLED
|
|
962
|
+
|
|
963
|
+
Args:
|
|
964
|
+
provider: Provider name (e.g., 'anthropic', 'openai')
|
|
965
|
+
session_id: Optional session ID for deterministic key assignment via FNV-1a hash
|
|
966
|
+
"""
|
|
967
|
+
cred_mod, get_flag = _get_hooks_imports()
|
|
968
|
+
if cred_mod is None or get_flag is None:
|
|
969
|
+
return None
|
|
970
|
+
|
|
971
|
+
if not get_flag("ROUND_ROBIN", default=False):
|
|
972
|
+
return None
|
|
973
|
+
|
|
974
|
+
passphrase = os.environ.get("OMG_CREDENTIAL_PASSPHRASE")
|
|
975
|
+
if not passphrase:
|
|
976
|
+
return None
|
|
977
|
+
|
|
978
|
+
try:
|
|
979
|
+
store = cred_mod.load_store(passphrase)
|
|
980
|
+
except (ValueError, OSError):
|
|
981
|
+
return None
|
|
982
|
+
|
|
983
|
+
providers = store.get("providers", {})
|
|
984
|
+
if provider not in providers:
|
|
985
|
+
return None
|
|
986
|
+
|
|
987
|
+
pdata = providers[provider]
|
|
988
|
+
keys = pdata.get("keys", [])
|
|
989
|
+
if not keys:
|
|
990
|
+
return None
|
|
991
|
+
|
|
992
|
+
# Pick key index: session-stable via FNV-1a or current active_index
|
|
993
|
+
if session_id:
|
|
994
|
+
idx = _fnv1a_hash(session_id) % len(keys)
|
|
995
|
+
else:
|
|
996
|
+
idx = pdata.get("active_index", 0)
|
|
997
|
+
if idx < 0 or idx >= len(keys):
|
|
998
|
+
idx = 0
|
|
999
|
+
|
|
1000
|
+
# Track usage on selected key
|
|
1001
|
+
keys[idx]["usage_count"] = keys[idx].get("usage_count", 0) + 1
|
|
1002
|
+
keys[idx]["last_used"] = datetime.now(timezone.utc).isoformat()
|
|
1003
|
+
|
|
1004
|
+
# Advance active_index for next non-session call (round-robin)
|
|
1005
|
+
if not session_id:
|
|
1006
|
+
pdata["active_index"] = (idx + 1) % len(keys)
|
|
1007
|
+
|
|
1008
|
+
# Persist updated stats (best-effort)
|
|
1009
|
+
try:
|
|
1010
|
+
cred_mod.save_store(store, passphrase)
|
|
1011
|
+
except (ValueError, OSError):
|
|
1012
|
+
pass
|
|
1013
|
+
|
|
1014
|
+
return keys[idx].get("key")
|
|
1015
|
+
|
|
1016
|
+
|
|
1017
|
+
def on_rate_limit(provider: str, session_id: str | None = None) -> str | None:
|
|
1018
|
+
"""Advance to next credential for provider on 429. Returns new active key.
|
|
1019
|
+
|
|
1020
|
+
Called when a rate limit (HTTP 429) is encountered. Advances to the next
|
|
1021
|
+
available key in the rotation and returns it.
|
|
1022
|
+
|
|
1023
|
+
Args:
|
|
1024
|
+
provider: Provider name (e.g., 'anthropic', 'openai')
|
|
1025
|
+
session_id: Optional session ID (currently unused, reserved for future)
|
|
1026
|
+
"""
|
|
1027
|
+
cred_mod, get_flag = _get_hooks_imports()
|
|
1028
|
+
if cred_mod is None or get_flag is None:
|
|
1029
|
+
return None
|
|
1030
|
+
|
|
1031
|
+
if not get_flag("ROUND_ROBIN", default=False):
|
|
1032
|
+
return None
|
|
1033
|
+
|
|
1034
|
+
passphrase = os.environ.get("OMG_CREDENTIAL_PASSPHRASE")
|
|
1035
|
+
if not passphrase:
|
|
1036
|
+
return None
|
|
1037
|
+
|
|
1038
|
+
try:
|
|
1039
|
+
store = cred_mod.load_store(passphrase)
|
|
1040
|
+
except (ValueError, OSError):
|
|
1041
|
+
return None
|
|
1042
|
+
|
|
1043
|
+
providers = store.get("providers", {})
|
|
1044
|
+
if provider not in providers:
|
|
1045
|
+
return None
|
|
1046
|
+
|
|
1047
|
+
pdata = providers[provider]
|
|
1048
|
+
keys = pdata.get("keys", [])
|
|
1049
|
+
if not keys:
|
|
1050
|
+
return None
|
|
1051
|
+
|
|
1052
|
+
current_idx = pdata.get("active_index", 0)
|
|
1053
|
+
if current_idx < 0 or current_idx >= len(keys):
|
|
1054
|
+
current_idx = 0
|
|
1055
|
+
|
|
1056
|
+
# Advance to next key
|
|
1057
|
+
new_idx = (current_idx + 1) % len(keys)
|
|
1058
|
+
pdata["active_index"] = new_idx
|
|
1059
|
+
|
|
1060
|
+
# Persist (best-effort)
|
|
1061
|
+
try:
|
|
1062
|
+
cred_mod.save_store(store, passphrase)
|
|
1063
|
+
except (ValueError, OSError):
|
|
1064
|
+
pass
|
|
1065
|
+
|
|
1066
|
+
return keys[new_idx].get("key")
|
|
1067
|
+
|
|
1068
|
+
|
|
1069
|
+
# =============================================================================
|
|
1070
|
+
# Role-Based Routing (Feature: OMG_ROLE_ROUTING_ENABLED)
|
|
1071
|
+
# =============================================================================
|
|
1072
|
+
|
|
1073
|
+
|
|
1074
|
+
def get_role_from_env() -> str | None:
|
|
1075
|
+
"""Read the active role from OMG_ACTIVE_ROLE environment variable.
|
|
1076
|
+
|
|
1077
|
+
Returns:
|
|
1078
|
+
Role name string (e.g., 'smol', 'slow') or None if not set.
|
|
1079
|
+
"""
|
|
1080
|
+
val = os.environ.get("OMG_ACTIVE_ROLE", "").strip().lower()
|
|
1081
|
+
return val if val else None
|
|
1082
|
+
|
|
1083
|
+
|
|
1084
|
+
def route_with_role(task_text: str, role: str | None = None) -> dict[str, Any]:
|
|
1085
|
+
"""Select model based on role + task classification.
|
|
1086
|
+
|
|
1087
|
+
Resolution order for role:
|
|
1088
|
+
1. Explicit `role` parameter
|
|
1089
|
+
2. OMG_ACTIVE_ROLE env var (via get_role_from_env())
|
|
1090
|
+
3. CLI args (--smol, --slow, --plan, --commit) via parse_role_args()
|
|
1091
|
+
4. None → fall back to existing routing
|
|
1092
|
+
|
|
1093
|
+
Feature flag: OMG_ROLE_ROUTING_ENABLED (default: False)
|
|
1094
|
+
When disabled, returns a baseline dict from existing _infer_target().
|
|
1095
|
+
|
|
1096
|
+
Args:
|
|
1097
|
+
task_text: Description of the task to route.
|
|
1098
|
+
role: Optional explicit role name override.
|
|
1099
|
+
|
|
1100
|
+
Returns:
|
|
1101
|
+
Dict with keys: model, provider, role, reason
|
|
1102
|
+
"""
|
|
1103
|
+
import sys as _sys
|
|
1104
|
+
|
|
1105
|
+
# Baseline: always compute the existing routing target
|
|
1106
|
+
existing_target = _infer_target(task_text)
|
|
1107
|
+
baseline = {
|
|
1108
|
+
"model": None,
|
|
1109
|
+
"provider": existing_target,
|
|
1110
|
+
"role": None,
|
|
1111
|
+
"reason": f"intent-based routing to {existing_target}",
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1114
|
+
# Check feature flag via lazy import
|
|
1115
|
+
_hooks_dir = os.path.join(_OMG_ROOT, "hooks")
|
|
1116
|
+
if _hooks_dir not in _sys.path:
|
|
1117
|
+
_sys.path.insert(0, _hooks_dir)
|
|
1118
|
+
try:
|
|
1119
|
+
from _common import get_feature_flag # pyright: ignore[reportMissingImports]
|
|
1120
|
+
except ImportError:
|
|
1121
|
+
# If _common unavailable, check env var directly
|
|
1122
|
+
env_val = os.environ.get("OMG_ROLE_ROUTING_ENABLED", "").lower()
|
|
1123
|
+
if env_val not in ("1", "true", "yes"):
|
|
1124
|
+
return baseline
|
|
1125
|
+
get_feature_flag = None # type: ignore[assignment]
|
|
1126
|
+
|
|
1127
|
+
if get_feature_flag is not None and not get_feature_flag("ROLE_ROUTING", default=False):
|
|
1128
|
+
return baseline
|
|
1129
|
+
|
|
1130
|
+
# Resolve role: explicit param → env var → CLI args
|
|
1131
|
+
resolved_role = role
|
|
1132
|
+
if resolved_role is None:
|
|
1133
|
+
resolved_role = get_role_from_env()
|
|
1134
|
+
if resolved_role is None:
|
|
1135
|
+
# Lazy import parse_role_args from agents.model_roles
|
|
1136
|
+
_agents_dir = os.path.join(_OMG_ROOT, "agents")
|
|
1137
|
+
if _agents_dir not in _sys.path:
|
|
1138
|
+
_sys.path.insert(0, _agents_dir)
|
|
1139
|
+
try:
|
|
1140
|
+
from model_roles import parse_role_args # pyright: ignore[reportMissingImports]
|
|
1141
|
+
resolved_role = parse_role_args(_sys.argv[1:])
|
|
1142
|
+
except ImportError:
|
|
1143
|
+
pass
|
|
1144
|
+
|
|
1145
|
+
# No role resolved → return baseline
|
|
1146
|
+
if resolved_role is None:
|
|
1147
|
+
return baseline
|
|
1148
|
+
|
|
1149
|
+
# Get role config via lazy import
|
|
1150
|
+
_agents_dir = os.path.join(_OMG_ROOT, "agents")
|
|
1151
|
+
if _agents_dir not in _sys.path:
|
|
1152
|
+
_sys.path.insert(0, _agents_dir)
|
|
1153
|
+
try:
|
|
1154
|
+
from model_roles import get_role # pyright: ignore[reportMissingImports]
|
|
1155
|
+
role_config = get_role(resolved_role)
|
|
1156
|
+
except ImportError:
|
|
1157
|
+
return baseline
|
|
1158
|
+
|
|
1159
|
+
if not role_config:
|
|
1160
|
+
return baseline
|
|
1161
|
+
|
|
1162
|
+
return {
|
|
1163
|
+
"model": role_config.get("model"),
|
|
1164
|
+
"provider": role_config.get("model", existing_target),
|
|
1165
|
+
"role": resolved_role,
|
|
1166
|
+
"reason": f"role-based routing: {resolved_role} → {role_config.get('model', 'unknown')}",
|
|
1167
|
+
}
|