multi-forge 0.9.0__tar.gz → 0.9.1__tar.gz
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.
- {multi_forge-0.9.0 → multi_forge-0.9.1}/PKG-INFO +1 -1
- {multi_forge-0.9.0 → multi_forge-0.9.1}/pyproject.toml +2 -1
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/extensions.py +135 -21
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/gc.py +1 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/workflow.py +43 -21
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/invoker/__init__.py +2 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/invoker/_lifecycle.py +179 -169
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/invoker/codex.py +6 -2
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/invoker/types.py +4 -5
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/ops/gc.py +217 -2
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/reactive/routing.py +6 -2
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/install/installer.py +93 -15
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/install/models.py +3 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/install/skill_compiler.py +108 -2
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/install/skill_planning.py +58 -4
- multi_forge-0.9.1/src/forge/install/unmanaged.py +1025 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/review/adversarial.py +1 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/review/consensus.py +3 -1
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/review/engine.py +147 -25
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/review/models.py +50 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/review/routing.py +51 -16
- multi_forge-0.9.1/src/skills/analyze/content.md +72 -0
- multi_forge-0.9.1/src/skills/analyze/forge-skill.yaml +11 -0
- multi_forge-0.9.1/src/skills/consensus/content.md +85 -0
- multi_forge-0.9.1/src/skills/consensus/forge-skill.yaml +11 -0
- multi_forge-0.9.1/src/skills/debate/content.md +87 -0
- multi_forge-0.9.1/src/skills/debate/forge-skill.yaml +11 -0
- multi_forge-0.9.1/src/skills/panel/content.md +88 -0
- multi_forge-0.9.1/src/skills/panel/forge-skill.yaml +10 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/qa/resources/checklist/14-workflow.md +50 -9
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/qa/resources/checklist/15-skills.md +10 -6
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/qa/resources/checklist/17-info.md +7 -6
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/qa/resources/checklist/18-disable.md +4 -2
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/qa/resources/checklist/19-uninstall.md +2 -2
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/qa/resources/checklist/2-extension.md +70 -17
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/qa/resources/checklist.md +17 -13
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/walkthrough/resources/checklist.md +15 -14
- multi_forge-0.9.0/src/skills/analyze/SKILL.md +0 -87
- multi_forge-0.9.0/src/skills/consensus/SKILL.md +0 -120
- multi_forge-0.9.0/src/skills/debate/SKILL.md +0 -116
- multi_forge-0.9.0/src/skills/panel/SKILL.md +0 -141
- {multi_forge-0.9.0 → multi_forge-0.9.1}/.gitignore +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/LICENSE +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/NOTICE +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/README.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/agents/.gitkeep +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/commands/.gitkeep +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/__init__.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/backend/__init__.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/backend/adapters/__init__.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/backend/adapters/litellm.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/backend/creation.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/backend/registry.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/backend/remote/__init__.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/backend/remote/base.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/backend/remote/openrouter.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/backend/sources.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/__init__.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/activity.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/auth.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/backend.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/claude.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/codex.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/config_cmd.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/consumer_lane_freeze.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/editor.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/guards.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/hooks/__init__.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/hooks/_group.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/hooks/_helpers.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/hooks/codex_patch.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/hooks/codex_policy.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/hooks/codex_transfer.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/hooks/commands.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/hooks/direct_commands.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/hooks/policy.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/hooks/protocols.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/hooks/read_hygiene.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/hooks/verification.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/logs.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/main.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/memory.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/memory_report.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/memory_writer.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/model.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/output.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/policy.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/proxy.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/proxy_audit.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/proxy_costs.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/runtime.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/search.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/session.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/session_codex.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/session_fork.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/session_lane.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/session_lifecycle.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/session_manage.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/session_memory.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/session_model_pin.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/session_resume_modes.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/session_rewind.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/session_routing.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/session_supervisor_options.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/status_line.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/statusline/__init__.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/statusline/context.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/statusline/names.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/statusline/palette.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/statusline/registry.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/statusline/throttle.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/telemetry.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/trace.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/cli/transfer.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/config/__init__.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/config/dataclass_utils.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/config/defaults/__init__.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/config/defaults/backends/__init__.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/config/defaults/backends/litellm.yaml +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/config/defaults/templates/__init__.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/config/defaults/templates/anthropic-passthrough.yaml +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/config/defaults/templates/codex-responses-local.yaml +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/config/defaults/templates/litellm-anthropic-local.yaml +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/config/defaults/templates/litellm-anthropic.yaml +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/config/defaults/templates/litellm-gemini-flash-local.yaml +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/config/defaults/templates/litellm-gemini-local.yaml +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/config/defaults/templates/litellm-gemini-test.yaml +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/config/defaults/templates/litellm-gemini.yaml +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/config/defaults/templates/litellm-openai-codex-local.yaml +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/config/defaults/templates/litellm-openai-local.yaml +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/config/defaults/templates/litellm-openai.yaml +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/config/defaults/templates/openrouter-anthropic.yaml +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/config/defaults/templates/openrouter-deepseek.yaml +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/config/defaults/templates/openrouter-gemini-flash.yaml +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/config/defaults/templates/openrouter-gemini.yaml +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/config/defaults/templates/openrouter-glm.yaml +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/config/defaults/templates/openrouter-kimi.yaml +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/config/defaults/templates/openrouter-minimax.yaml +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/config/defaults/templates/openrouter-openai-codex.yaml +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/config/defaults/templates/openrouter-openai.yaml +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/config/defaults/templates/openrouter-qwen.yaml +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/config/loader.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/config/schema.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/__init__.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/auth/__init__.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/auth/capabilities.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/auth/credentials_file.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/auth/protocols.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/auth/secrets.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/auth/template_secrets.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/backend_dependency.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/credential_registry.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/data/__init__.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/data/model_catalog.yaml +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/data/system_prompt_addendums/__init__.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/data/system_prompt_addendums/gemini.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/data/system_prompt_addendums/openai.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/effort.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/invoker/claude.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/invoker/codex_stream.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/lanes.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/llm/__init__.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/llm/clients/__init__.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/llm/clients/base.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/llm/clients/litellm.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/llm/clients/openai_compat.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/llm/clients/openrouter.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/llm/credentials.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/llm/detection.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/llm/errors.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/llm/protocols.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/llm/types.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/logging.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/models/__init__.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/models/catalog.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/models/direct_model.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/models/types.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/naming.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/ops/__init__.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/ops/backend_reconcile.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/ops/claude_session.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/ops/codex_bridge.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/ops/codex_enrollment.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/ops/codex_interactive.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/ops/codex_session.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/ops/context.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/ops/policy.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/ops/provider_trace.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/ops/proxy.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/ops/resolution.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/ops/session.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/ops/session_context.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/ops/transfer.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/ops/usage_summary.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/paths.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/process.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/provider_types.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/reactive/__init__.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/reactive/cost_tracking.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/reactive/env.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/reactive/headless_json.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/reactive/proxy.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/reactive/session_runner.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/reactive/structured_output.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/reactive/tagger.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/reactive/throttle.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/run_id.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/runtime/__init__.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/runtime/codex_preflight.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/runtime/codex_preflight_cache.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/runtime/codex_rollouts.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/runtime/registry.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/runtime_vocab.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/state/__init__.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/state/exceptions.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/state/io.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/state/lock.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/state/retention.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/state/timestamps.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/state/versioned_store.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/telemetry/__init__.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/telemetry/caps.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/telemetry/downstream.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/telemetry/jsonl_io.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/telemetry/upstream.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/telemetry/vocabulary.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/tiers.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/transcript.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/typing_helpers.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/usage/__init__.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/usage/billing.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/usage/correlation.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/usage/emit.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/usage/ledger.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/usage/measurement.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/usage/vocabulary.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/workqueue/__init__.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/workqueue/queue.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/core/workqueue/types.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/install/__init__.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/install/cli.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/install/codex_hooks.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/install/doctor.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/install/exceptions.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/install/hook_dispatcher.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/install/hook_migration.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/install/hooks.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/install/preset.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/install/project_compat.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/install/project_registry.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/install/settings_merge.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/install/skill_cache.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/install/skill_validation.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/install/tracking.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/install/version.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/policy/__init__.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/policy/deterministic/__init__.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/policy/deterministic/base.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/policy/deterministic/coding_standards.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/policy/deterministic/registry.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/policy/deterministic/tdd.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/policy/engine.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/policy/protocols.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/policy/queries.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/policy/semantic/__init__.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/policy/semantic/plan_check.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/policy/semantic/shadow.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/policy/semantic/shadow_runner.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/policy/semantic/supervisor.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/policy/semantic/verdict.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/policy/store.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/policy/supervisor_lane_degrade.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/policy/team/__init__.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/policy/team/config.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/policy/team/handlers.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/policy/team/prompts.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/policy/types.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/policy/workflow/__init__.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/policy/workflow/branches.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/policy/workflow/config.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/policy/workflow/divergence.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/policy/workflow/policy.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/policy/workflow/stages.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/proxy/__init__.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/proxy/audit_logger.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/proxy/base_client.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/proxy/client_adapter.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/proxy/client_factory.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/proxy/converters.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/proxy/cost_logger.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/proxy/cost_tracker.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/proxy/data_models.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/proxy/error_hints.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/proxy/intercept.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/proxy/metrics.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/proxy/model_spec.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/proxy/passthrough.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/proxy/ports.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/proxy/provider_trace_logger.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/proxy/proxies.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/proxy/proxy_identity.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/proxy/proxy_orchestrator.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/proxy/proxy_startup.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/proxy/responses_ingress.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/proxy/responses_passthrough.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/proxy/server.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/proxy/stream_relay.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/proxy/utils.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/review/__init__.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/review/resources/__init__.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/review/resources/code_consensus_evaluation.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/review/resources/code_debate_evaluation.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/review/resources/codereview-performance.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/review/resources/codereview-quick.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/review/resources/codereview-security.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/review/resources/codereview.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/review/resources/consensus_evaluation.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/review/resources/debate_evaluation.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/review/resources/docreview-quick.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/review/resources/docreview.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/review/resources/thinkdeep.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/review/synthesis.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/runtime_config.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/search/__init__.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/search/bm25_store.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/search/content_store.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/search/engine.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/search/exceptions.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/search/extractor.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/search/index_state.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/search/store.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/search/tokenizer.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/session/__init__.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/session/active.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/session/addendum.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/session/artifacts.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/session/claude/__init__.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/session/claude/cleanup.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/session/claude/invoke.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/session/claude/paths.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/session/claude/relocate.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/session/cleanup.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/session/codex_handoff.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/session/codex_invoke.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/session/config.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/session/consumer_lanes.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/session/context_limit.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/session/effective.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/session/exceptions.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/session/hooks/__init__.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/session/hooks/models.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/session/hooks/session_start.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/session/identity.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/session/index.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/session/launch.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/session/launch_confirmation.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/session/manager.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/session/memory_inheritance.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/session/memory_writer.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/session/model_pin.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/session/models.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/session/overrides.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/session/passport.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/session/plan_resolution.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/session/prev_sessions.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/session/project_memory.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/session/rewind.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/session/shadow_curation.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/session/store.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/session/transfer.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/session/validation.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/session/worktree/__init__.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/session/worktree/cleanup.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/session/worktree/config_copy.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/session/worktree/create.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/sidecar/__init__.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/sidecar/container.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/forge/sidecar/docker.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/challenge/content.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/challenge/forge-skill.yaml +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/consensus/resources/synthesis.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/panel/resources/synthesis.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/qa/SKILL.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/qa/resources/checklist/0-enable.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/qa/resources/checklist/1-preflight.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/qa/resources/checklist/10-resume.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/qa/resources/checklist/11-config.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/qa/resources/checklist/12-search.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/qa/resources/checklist/13-policy.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/qa/resources/checklist/16-memory.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/qa/resources/checklist/20-cleanup.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/qa/resources/checklist/3-authentication.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/qa/resources/checklist/4-proxy.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/qa/resources/checklist/5-session.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/qa/resources/checklist/6-hook.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/qa/resources/checklist/7-costs.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/qa/resources/checklist/8-status-line.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/qa/resources/checklist/9-direct-commands.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/qa/resources/report-template.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/qa/scripts/start-container.sh +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/qa/scripts/walkthrough-state.py +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/review/content.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/review/forge-skill.yaml +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/review/references/claude-4.6.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/review/references/claude-4.8.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/review/references/gemini-3.1.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/review/references/gpt-5.5.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/review/references/skills-writing-guide.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/review/resources/code-anthropic.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/review/resources/code-gemini.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/review/resources/code-openai.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/review/resources/code.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/review-docs/content.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/review-docs/forge-skill.yaml +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/review-docs/resources/docs-anthropic.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/review-docs/resources/docs-gemini.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/review-docs/resources/docs-openai.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/review-docs/resources/docs.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/smoke-test/content.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/smoke-test/forge-skill.yaml +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/smoke-test/scripts/smoke-test.sh +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/understand/content.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/understand/forge-skill.yaml +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/understand/resources/code-anthropic.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/understand/resources/code-gemini.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/understand/resources/code-openai.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/understand/resources/code.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/understand/resources/docs-anthropic.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/understand/resources/docs-gemini.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/understand/resources/docs-openai.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/understand/resources/docs.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/walkthrough/SKILL.md +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/walkthrough/scripts/run-in-repo.sh +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/walkthrough/scripts/setup-test-repo.sh +0 -0
- {multi_forge-0.9.0 → multi_forge-0.9.1}/src/skills/walkthrough/scripts/walkthrough-state.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: multi-forge
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.1
|
|
4
4
|
Summary: Multi-runtime agent toolkit: proxy routing, cost control, session management, policy enforcement, and workflow orchestration
|
|
5
5
|
Project-URL: Homepage, https://github.com/hapa1i/multi-forge
|
|
6
6
|
Project-URL: Repository, https://github.com/hapa1i/multi-forge
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "multi-forge"
|
|
3
|
-
version = "0.9.
|
|
3
|
+
version = "0.9.1"
|
|
4
4
|
description = "Multi-runtime agent toolkit: proxy routing, cost control, session management, policy enforcement, and workflow orchestration"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = "Apache-2.0"
|
|
@@ -124,6 +124,7 @@ constraint-dependencies = [
|
|
|
124
124
|
"virtualenv>=20.36.1",
|
|
125
125
|
"aiohttp>=3.14.1",
|
|
126
126
|
"cryptography>=48.0.1",
|
|
127
|
+
"mcp>=1.28.1",
|
|
127
128
|
"python-multipart>=0.0.31",
|
|
128
129
|
"Pygments>=2.20.0",
|
|
129
130
|
"PyJWT>=2.13.0",
|
|
@@ -43,17 +43,20 @@ from forge.install.installer import (
|
|
|
43
43
|
Installer,
|
|
44
44
|
find_claude_root,
|
|
45
45
|
find_forge_installation,
|
|
46
|
+
get_extensions_root,
|
|
46
47
|
inspect_skill_package_status,
|
|
47
48
|
)
|
|
48
49
|
from forge.install.models import (
|
|
49
50
|
FILE_MODULES,
|
|
50
51
|
PROFILE_RANK,
|
|
52
|
+
InstalledManifest,
|
|
51
53
|
InstallMode,
|
|
52
54
|
InstallModule,
|
|
53
55
|
InstallPlan,
|
|
54
56
|
InstallProfile,
|
|
55
57
|
InstallScope,
|
|
56
58
|
get_gated_skills,
|
|
59
|
+
parse_installation_key,
|
|
57
60
|
)
|
|
58
61
|
from forge.install.project_compat import (
|
|
59
62
|
ProjectCompatibilityError,
|
|
@@ -61,7 +64,13 @@ from forge.install.project_compat import (
|
|
|
61
64
|
format_project_compatibility_recovery,
|
|
62
65
|
)
|
|
63
66
|
from forge.install.project_registry import EnrollmentSource, ProjectRegistryStore
|
|
67
|
+
from forge.install.skill_compiler import discover_skill_source_names
|
|
64
68
|
from forge.install.tracking import TrackingStore
|
|
69
|
+
from forge.install.unmanaged import (
|
|
70
|
+
runtime_skill_scan_roots,
|
|
71
|
+
scan_unmanaged_skill_state,
|
|
72
|
+
)
|
|
73
|
+
from forge.session.claude.paths import get_claude_home
|
|
65
74
|
|
|
66
75
|
console = Console()
|
|
67
76
|
_log = logging.getLogger(__name__)
|
|
@@ -561,6 +570,11 @@ def _print_plan(plan: InstallPlan, dry_run: bool = False) -> None:
|
|
|
561
570
|
style=style,
|
|
562
571
|
)
|
|
563
572
|
console.print(table)
|
|
573
|
+
for package in plan.skill_packages:
|
|
574
|
+
if package.recovery:
|
|
575
|
+
console.print(
|
|
576
|
+
f" [yellow]{package.runtime}/{package.skill} recovery:[/yellow] {escape(package.recovery)}"
|
|
577
|
+
)
|
|
564
578
|
|
|
565
579
|
if plan.files:
|
|
566
580
|
console.print(f"\n{prefix}[bold]Files:[/bold]")
|
|
@@ -726,14 +740,21 @@ def _can_resolve_project_root(scope: InstallScope, *, anchor: Path | None = None
|
|
|
726
740
|
return False
|
|
727
741
|
|
|
728
742
|
|
|
729
|
-
def _resolve_status_project_root(
|
|
743
|
+
def _resolve_status_project_root(
|
|
744
|
+
scope: InstallScope,
|
|
745
|
+
anchor: Path | None,
|
|
746
|
+
tracking_snapshot: InstalledManifest | None = None,
|
|
747
|
+
) -> Path | None:
|
|
730
748
|
"""Resolve a status lookup root, including tracked installs without ``.claude``."""
|
|
731
749
|
|
|
732
750
|
try:
|
|
733
751
|
return _resolve_project_root(scope, anchor=anchor)
|
|
734
752
|
except NoClaudeDirectoryError:
|
|
735
753
|
try:
|
|
736
|
-
detected_scope, detected_root = find_forge_installation(
|
|
754
|
+
detected_scope, detected_root = find_forge_installation(
|
|
755
|
+
start=anchor,
|
|
756
|
+
tracking_snapshot=tracking_snapshot,
|
|
757
|
+
)
|
|
737
758
|
except NoForgeInstallationError:
|
|
738
759
|
return None
|
|
739
760
|
return detected_root if detected_scope == scope else None
|
|
@@ -1346,7 +1367,10 @@ def status_cmd(scope: str | None, path: str | None, show_all: bool, as_json: boo
|
|
|
1346
1367
|
# A corrupt installed.json raises TrackingCorruptedError (a StateCorruptedError);
|
|
1347
1368
|
# it propagates to the top-level handler for the uniform reset tip.
|
|
1348
1369
|
tracking = TrackingStore()
|
|
1349
|
-
|
|
1370
|
+
manifest = tracking.read()
|
|
1371
|
+
tracked_installations = [
|
|
1372
|
+
(*parse_installation_key(key), installation) for key, installation in manifest.installations.items()
|
|
1373
|
+
]
|
|
1350
1374
|
installations_by_target = {
|
|
1351
1375
|
(tracked_scope, project_path): installation
|
|
1352
1376
|
for tracked_scope, project_path, installation in tracked_installations
|
|
@@ -1363,7 +1387,7 @@ def status_cmd(scope: str | None, path: str | None, show_all: bool, as_json: boo
|
|
|
1363
1387
|
scopes = [InstallScope.USER, InstallScope.PROJECT, InstallScope.LOCAL]
|
|
1364
1388
|
elif scope is None and anchor is None:
|
|
1365
1389
|
try:
|
|
1366
|
-
detected_scope, detected_root = find_forge_installation()
|
|
1390
|
+
detected_scope, detected_root = find_forge_installation(tracking_snapshot=manifest)
|
|
1367
1391
|
detected_scope_name = detected_scope.value
|
|
1368
1392
|
scopes = [detected_scope]
|
|
1369
1393
|
except NoForgeInstallationError:
|
|
@@ -1371,7 +1395,10 @@ def status_cmd(scope: str | None, path: str | None, show_all: bool, as_json: boo
|
|
|
1371
1395
|
elif scope is None and anchor is not None:
|
|
1372
1396
|
# --root without --scope: auto-detect scope at that path
|
|
1373
1397
|
try:
|
|
1374
|
-
detected_scope, detected_root = find_forge_installation(
|
|
1398
|
+
detected_scope, detected_root = find_forge_installation(
|
|
1399
|
+
start=anchor,
|
|
1400
|
+
tracking_snapshot=manifest,
|
|
1401
|
+
)
|
|
1375
1402
|
detected_scope_name = detected_scope.value
|
|
1376
1403
|
scopes = [detected_scope]
|
|
1377
1404
|
except NoForgeInstallationError:
|
|
@@ -1382,12 +1409,59 @@ def status_cmd(scope: str | None, path: str | None, show_all: bool, as_json: boo
|
|
|
1382
1409
|
# Use the detected root (from walk-up) over the raw anchor for lookups.
|
|
1383
1410
|
effective_anchor = detected_root if detected_root is not None else anchor
|
|
1384
1411
|
|
|
1412
|
+
scope_contexts = [
|
|
1413
|
+
(
|
|
1414
|
+
selected_scope,
|
|
1415
|
+
_resolve_status_project_root(
|
|
1416
|
+
selected_scope,
|
|
1417
|
+
effective_anchor,
|
|
1418
|
+
tracking_snapshot=manifest,
|
|
1419
|
+
),
|
|
1420
|
+
)
|
|
1421
|
+
for selected_scope in scopes
|
|
1422
|
+
]
|
|
1423
|
+
non_user_scopes = [selected_scope for selected_scope in scopes if selected_scope != InstallScope.USER]
|
|
1424
|
+
shared_scan_root = next(
|
|
1425
|
+
(
|
|
1426
|
+
project_root
|
|
1427
|
+
for selected_scope, project_root in scope_contexts
|
|
1428
|
+
if selected_scope != InstallScope.USER and project_root
|
|
1429
|
+
),
|
|
1430
|
+
None,
|
|
1431
|
+
)
|
|
1432
|
+
scanner_scope_roots: list[tuple[InstallScope, Path | None]] = []
|
|
1433
|
+
for selected_scope, project_root in scope_contexts:
|
|
1434
|
+
if selected_scope == InstallScope.USER:
|
|
1435
|
+
scanner_scope_roots.append((selected_scope, None))
|
|
1436
|
+
elif project_root is not None:
|
|
1437
|
+
scanner_scope_roots.append((selected_scope, project_root))
|
|
1438
|
+
elif len(non_user_scopes) > 1 and shared_scan_root is not None:
|
|
1439
|
+
# `--all` scans both logical Claude scopes at the effective root
|
|
1440
|
+
# even when only one scope has a tracking/sidecar signal.
|
|
1441
|
+
scanner_scope_roots.append((selected_scope, shared_scan_root))
|
|
1442
|
+
try:
|
|
1443
|
+
current_skill_names = discover_skill_source_names(get_extensions_root() / InstallModule.SKILLS.value)
|
|
1444
|
+
except (OSError, ValueError) as exc:
|
|
1445
|
+
_log.warning("extension status: current skill names unavailable; using historical names only: %s", exc)
|
|
1446
|
+
current_skill_names = ()
|
|
1447
|
+
scan_roots = runtime_skill_scan_roots(
|
|
1448
|
+
scanner_scope_roots,
|
|
1449
|
+
user_home=Path.home(),
|
|
1450
|
+
claude_home=get_claude_home(),
|
|
1451
|
+
)
|
|
1452
|
+
unmanaged_scan = scan_unmanaged_skill_state(
|
|
1453
|
+
scan_roots,
|
|
1454
|
+
current_skill_names=current_skill_names,
|
|
1455
|
+
tracking=manifest,
|
|
1456
|
+
)
|
|
1457
|
+
unmanaged_packages = unmanaged_scan.packages
|
|
1458
|
+
unmanaged_root_issues = unmanaged_scan.root_issues
|
|
1459
|
+
|
|
1385
1460
|
if as_json:
|
|
1386
1461
|
import json
|
|
1387
1462
|
|
|
1388
|
-
|
|
1389
|
-
for s in
|
|
1390
|
-
project_root = _resolve_status_project_root(s, effective_anchor)
|
|
1463
|
+
installations = []
|
|
1464
|
+
for s, project_root in scope_contexts:
|
|
1391
1465
|
project_path_str = str(project_root) if project_root else None
|
|
1392
1466
|
|
|
1393
1467
|
inst = installations_by_target.get((s.value, project_path_str))
|
|
@@ -1399,7 +1473,7 @@ def status_cmd(scope: str | None, path: str | None, show_all: bool, as_json: boo
|
|
|
1399
1473
|
project_root,
|
|
1400
1474
|
tracked_installations=tracked_installations,
|
|
1401
1475
|
)
|
|
1402
|
-
|
|
1476
|
+
installations.append(
|
|
1403
1477
|
{
|
|
1404
1478
|
"scope": s.value,
|
|
1405
1479
|
"profile": inst.profile,
|
|
@@ -1427,7 +1501,17 @@ def status_cmd(scope: str | None, path: str | None, show_all: bool, as_json: boo
|
|
|
1427
1501
|
"updated_at": inst.updated_at,
|
|
1428
1502
|
}
|
|
1429
1503
|
)
|
|
1430
|
-
click.echo(
|
|
1504
|
+
click.echo(
|
|
1505
|
+
json.dumps(
|
|
1506
|
+
{
|
|
1507
|
+
"schema_version": 2,
|
|
1508
|
+
"installations": installations,
|
|
1509
|
+
"unmanaged_skill_packages": [package.to_dict() for package in unmanaged_packages],
|
|
1510
|
+
},
|
|
1511
|
+
indent=2,
|
|
1512
|
+
default=str,
|
|
1513
|
+
)
|
|
1514
|
+
)
|
|
1431
1515
|
return
|
|
1432
1516
|
|
|
1433
1517
|
if detected_scope_name:
|
|
@@ -1437,8 +1521,7 @@ def status_cmd(scope: str | None, path: str | None, show_all: bool, as_json: boo
|
|
|
1437
1521
|
console.print(f"[dim]No extensions detected in {location}[/dim]")
|
|
1438
1522
|
console.print("[dim]Showing all scopes for this location:[/dim]")
|
|
1439
1523
|
|
|
1440
|
-
for s in
|
|
1441
|
-
project_root = _resolve_status_project_root(s, effective_anchor)
|
|
1524
|
+
for s, project_root in scope_contexts:
|
|
1442
1525
|
project_path_str = str(project_root) if project_root else None
|
|
1443
1526
|
|
|
1444
1527
|
installation = installations_by_target.get((s.value, project_path_str))
|
|
@@ -1526,20 +1609,51 @@ def status_cmd(scope: str | None, path: str | None, show_all: bool, as_json: boo
|
|
|
1526
1609
|
for f in installation.files:
|
|
1527
1610
|
console.print(f" - {display_path(f.target_path)}")
|
|
1528
1611
|
|
|
1612
|
+
console.print("\n[bold]Unmanaged runtime skill packages[/bold]")
|
|
1613
|
+
if not unmanaged_packages and not unmanaged_root_issues:
|
|
1614
|
+
console.print(" [dim]None found in the selected runtime roots.[/dim]")
|
|
1615
|
+
elif unmanaged_packages:
|
|
1616
|
+
table = Table(show_header=True, header_style="bold", box=None, padding=(0, 1))
|
|
1617
|
+
table.add_column("RUNTIME")
|
|
1618
|
+
table.add_column("SKILL")
|
|
1619
|
+
table.add_column("SHAPE")
|
|
1620
|
+
table.add_column("PROVENANCE")
|
|
1621
|
+
table.add_column("TARGET")
|
|
1622
|
+
table.add_column("CLEANUP")
|
|
1623
|
+
for package in unmanaged_packages:
|
|
1624
|
+
table.add_row(
|
|
1625
|
+
package.runtime,
|
|
1626
|
+
package.skill,
|
|
1627
|
+
package.shape,
|
|
1628
|
+
package.provenance,
|
|
1629
|
+
display_path(package.target_dir),
|
|
1630
|
+
package.cleanup_scope or "report only",
|
|
1631
|
+
style="yellow" if package.cleanup_eligible else "red",
|
|
1632
|
+
)
|
|
1633
|
+
console.print(table)
|
|
1634
|
+
for package in unmanaged_packages:
|
|
1635
|
+
if package.collision_dirs:
|
|
1636
|
+
console.print(
|
|
1637
|
+
f" [red]{package.runtime}/{package.skill} collisions:[/red] "
|
|
1638
|
+
+ ", ".join(display_path(path) for path in package.collision_dirs)
|
|
1639
|
+
)
|
|
1640
|
+
console.print(f" [dim]{package.runtime}/{package.skill}:[/dim] {package.cleanup_reason}")
|
|
1641
|
+
if package.recovery:
|
|
1642
|
+
console.print(f" [yellow]{package.runtime}/{package.skill}:[/yellow] {package.recovery}")
|
|
1643
|
+
for issue in unmanaged_root_issues:
|
|
1644
|
+
console.print(
|
|
1645
|
+
f" [red]Root not scanned:[/red] {display_path(issue.root_dir)} " f"({issue.runtime}): {issue.reason}"
|
|
1646
|
+
)
|
|
1647
|
+
|
|
1529
1648
|
if scope is None and not show_all and anchor is None:
|
|
1530
1649
|
local_installed = any(
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
str(_resolve_project_root(s)) if s != InstallScope.USER else None,
|
|
1534
|
-
)
|
|
1535
|
-
for s in scopes
|
|
1536
|
-
if s == InstallScope.USER or _can_resolve_project_root(s)
|
|
1650
|
+
(selected_scope.value, str(project_root) if project_root is not None else None) in installations_by_target
|
|
1651
|
+
for selected_scope, project_root in scope_contexts
|
|
1537
1652
|
)
|
|
1538
1653
|
if not local_installed:
|
|
1539
|
-
|
|
1540
|
-
if all_installations:
|
|
1654
|
+
if tracked_installations:
|
|
1541
1655
|
print_tip(
|
|
1542
|
-
f"{len(
|
|
1656
|
+
f"{len(tracked_installations)} installation(s) exist elsewhere. Run 'forge info' to see all.",
|
|
1543
1657
|
console=console,
|
|
1544
1658
|
)
|
|
1545
1659
|
else:
|
|
@@ -208,5 +208,6 @@ def _category_label(category: str) -> str:
|
|
|
208
208
|
"search_docs": "Orphan search docs:",
|
|
209
209
|
"dead_installations": "Dead installations:",
|
|
210
210
|
"corrupt_state": "Corrupt state files:",
|
|
211
|
+
"unmanaged_skill_packages": "Unmanaged skill packages:",
|
|
211
212
|
}
|
|
212
213
|
return labels.get(category, f"{category}:")
|
|
@@ -87,11 +87,12 @@ def _run_preflight(
|
|
|
87
87
|
*,
|
|
88
88
|
as_json: bool = False,
|
|
89
89
|
routing_plan: Any | None = None,
|
|
90
|
+
resume_id: str | None = None,
|
|
90
91
|
) -> None:
|
|
91
92
|
"""Check resolved routing/auth before spawning workers. Exit 1 on failure."""
|
|
92
93
|
from forge.review.engine import preflight_check
|
|
93
94
|
|
|
94
|
-
errors = preflight_check(specs, routing_plan=routing_plan)
|
|
95
|
+
errors = preflight_check(specs, routing_plan=routing_plan, resume_id=resume_id)
|
|
95
96
|
warnings = _routing_plan_warnings(specs, routing_plan)
|
|
96
97
|
if not errors:
|
|
97
98
|
if not as_json:
|
|
@@ -107,12 +108,17 @@ def _run_preflight(
|
|
|
107
108
|
print_error("Workflow preflight failed:")
|
|
108
109
|
for err in errors:
|
|
109
110
|
console.print(f" - {err}")
|
|
111
|
+
runtime_tips: list[str] = []
|
|
112
|
+
if any(spec.runtime == "claude_code" for spec in specs):
|
|
113
|
+
runtime_tips.append("Run 'command -v claude' to check the Claude worker runtime.")
|
|
114
|
+
if any(spec.runtime == "codex" for spec in specs):
|
|
115
|
+
runtime_tips.append("Run 'forge runtime preflight codex' to refresh Codex readiness.")
|
|
110
116
|
print_tip(
|
|
111
117
|
"Run 'forge workflow list-models' to check model availability.",
|
|
112
118
|
"Run 'forge proxy list' to check proxy status.",
|
|
113
119
|
"Run 'forge auth status' to check auth status.",
|
|
114
120
|
"Run 'forge proxy create <template>' to create a proxy.",
|
|
115
|
-
|
|
121
|
+
*runtime_tips,
|
|
116
122
|
console=console,
|
|
117
123
|
)
|
|
118
124
|
sys.exit(1)
|
|
@@ -151,16 +157,20 @@ def _resolved_models_summary(
|
|
|
151
157
|
summary: dict[str, dict[str, Any]] = {}
|
|
152
158
|
for idx, (spec, result) in enumerate(zip(specs, routing_plan.routes)):
|
|
153
159
|
route = result.route
|
|
160
|
+
runtime_native = result.source == "runtime_native"
|
|
154
161
|
worker_id = worker_ids[idx] if worker_ids and idx < len(worker_ids) else spec.effective_worker_id
|
|
155
162
|
entry: dict[str, Any] = {
|
|
156
163
|
"requested_model": spec.name,
|
|
157
164
|
"model_id": spec.model_id,
|
|
158
165
|
"resolved_model": route.model_ref if route else None,
|
|
159
|
-
"provider": route.provider if route else None,
|
|
166
|
+
"provider": "openai" if runtime_native else (route.provider if route else None),
|
|
167
|
+
"runtime": spec.runtime,
|
|
160
168
|
"source": result.source,
|
|
161
169
|
"proxy": result.proxy_id,
|
|
162
170
|
"template": result.template or (route.template_id if route else None),
|
|
163
171
|
}
|
|
172
|
+
if runtime_native:
|
|
173
|
+
entry["model_selection"] = "runtime_default"
|
|
164
174
|
if roles and worker_id in roles:
|
|
165
175
|
entry[role_field] = roles[worker_id]
|
|
166
176
|
if result.warning:
|
|
@@ -176,8 +186,13 @@ def _format_resolved_models(summary: dict[str, dict[str, Any]]) -> str:
|
|
|
176
186
|
|
|
177
187
|
lines = ["Resolved models:"]
|
|
178
188
|
for worker_id, item in summary.items():
|
|
179
|
-
resolved =
|
|
189
|
+
resolved = (
|
|
190
|
+
"(runtime default)"
|
|
191
|
+
if item.get("model_selection") == "runtime_default"
|
|
192
|
+
else item.get("resolved_model") or "(unresolved)"
|
|
193
|
+
)
|
|
180
194
|
provider = item.get("provider") or "unknown"
|
|
195
|
+
runtime = item.get("runtime") or "unknown"
|
|
181
196
|
proxy = item.get("proxy") or "(direct)"
|
|
182
197
|
template = item.get("template") or "(direct)"
|
|
183
198
|
requested = item.get("requested_model") or worker_id
|
|
@@ -185,7 +200,7 @@ def _format_resolved_models(summary: dict[str, dict[str, Any]]) -> str:
|
|
|
185
200
|
stance = f", stance={item['stance']}" if item.get("stance") else ""
|
|
186
201
|
lines.append(
|
|
187
202
|
f"- {worker_id}: requested={requested}, resolved={resolved}, "
|
|
188
|
-
f"provider={provider}, proxy={proxy}, template={template}{role}{stance}"
|
|
203
|
+
f"provider={provider}, runtime={runtime}, proxy={proxy}, template={template}{role}{stance}"
|
|
189
204
|
)
|
|
190
205
|
return "\n".join(lines) + "\n\n"
|
|
191
206
|
|
|
@@ -238,10 +253,10 @@ def workflow_cmd() -> None:
|
|
|
238
253
|
"--available",
|
|
239
254
|
"available_only",
|
|
240
255
|
is_flag=True,
|
|
241
|
-
help="Show only ready
|
|
256
|
+
help="Show only ready workers (runtime prerequisites and routing usable)",
|
|
242
257
|
)
|
|
243
258
|
def list_models(as_json: bool, available_only: bool) -> None:
|
|
244
|
-
"""Show workflow
|
|
259
|
+
"""Show workflow worker readiness."""
|
|
245
260
|
from forge.review.models import available_model_specs, check_model_availability
|
|
246
261
|
|
|
247
262
|
availabilities = check_model_availability(available_model_specs())
|
|
@@ -255,6 +270,7 @@ def list_models(as_json: bool, available_only: bool) -> None:
|
|
|
255
270
|
"name": a.spec.name,
|
|
256
271
|
"model_id": a.spec.model_id,
|
|
257
272
|
"family": a.spec.family,
|
|
273
|
+
"runtime": a.spec.runtime,
|
|
258
274
|
"provider_refs": list(a.spec.provider_refs),
|
|
259
275
|
"preferred_proxy": a.spec.preferred_proxy,
|
|
260
276
|
"description": a.spec.description,
|
|
@@ -284,6 +300,9 @@ def _primary_credential(spec: ModelSpec) -> str:
|
|
|
284
300
|
Uses derive_model_routes() to get the first route's credential,
|
|
285
301
|
which is stable and deterministic (no registry read).
|
|
286
302
|
"""
|
|
303
|
+
if spec.runtime == "codex":
|
|
304
|
+
return "runtime-native"
|
|
305
|
+
|
|
287
306
|
from forge.review.routing import derive_model_routes
|
|
288
307
|
|
|
289
308
|
routes = derive_model_routes(spec)
|
|
@@ -328,11 +347,14 @@ def _print_grouped_models(availabilities: list) -> None:
|
|
|
328
347
|
console.print("\n[bold]Available Models[/bold]\n")
|
|
329
348
|
|
|
330
349
|
for cred_name, items in groups.items():
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
350
|
+
if cred_name == "runtime-native":
|
|
351
|
+
console.print(" [bold]runtime-native[/bold] [[green]runtime preflight[/green]]")
|
|
352
|
+
else:
|
|
353
|
+
env_var = _credential_env_var(cred_name)
|
|
354
|
+
configured = _credential_configured(cred_name)
|
|
355
|
+
config_tag = "[green]configured[/green]" if configured else "[yellow]not configured[/yellow]"
|
|
356
|
+
env_display = f" ({env_var})" if env_var else ""
|
|
357
|
+
console.print(f" [bold]{cred_name}[/bold]{env_display} [{config_tag}]")
|
|
336
358
|
|
|
337
359
|
for a in items:
|
|
338
360
|
style = _STATUS_STYLES.get(a.status, "")
|
|
@@ -364,7 +386,7 @@ def _print_grouped_models(availabilities: list) -> None:
|
|
|
364
386
|
"-m",
|
|
365
387
|
type=str,
|
|
366
388
|
default=None,
|
|
367
|
-
help="Comma-separated
|
|
389
|
+
help="Comma-separated worker names across Claude/Codex runtimes (default: workflow quorum)",
|
|
368
390
|
)
|
|
369
391
|
@click.option("--timeout", "-t", type=int, default=600, help="Per-model timeout in seconds")
|
|
370
392
|
@click.option("--json", "as_json", is_flag=True, help="Output as JSON")
|
|
@@ -405,7 +427,7 @@ def _print_grouped_models(availabilities: list) -> None:
|
|
|
405
427
|
"effort",
|
|
406
428
|
type=click.Choice(list(CLAUDE_EFFORT_LEVELS)),
|
|
407
429
|
default=None,
|
|
408
|
-
help="
|
|
430
|
+
help="Claude workers only: reasoning effort (low/medium/high/xhigh/max)",
|
|
409
431
|
)
|
|
410
432
|
@click.pass_context
|
|
411
433
|
def panel(
|
|
@@ -510,7 +532,7 @@ def panel(
|
|
|
510
532
|
_handle_routing_error(e, as_json=as_json)
|
|
511
533
|
return
|
|
512
534
|
|
|
513
|
-
_run_preflight(specs, as_json=as_json, routing_plan=routing_plan)
|
|
535
|
+
_run_preflight(specs, as_json=as_json, routing_plan=routing_plan, resume_id=resume_id)
|
|
514
536
|
|
|
515
537
|
from forge.core.invoker import Attribution
|
|
516
538
|
|
|
@@ -831,7 +853,7 @@ def _handle_review_output(
|
|
|
831
853
|
"-m",
|
|
832
854
|
type=str,
|
|
833
855
|
default="claude-opus",
|
|
834
|
-
help="Comma-separated
|
|
856
|
+
help="Comma-separated worker names across Claude/Codex runtimes (default: claude-opus)",
|
|
835
857
|
)
|
|
836
858
|
@click.option("--timeout", "-t", type=int, default=600, help="Per-model timeout in seconds")
|
|
837
859
|
@click.option("--json", "as_json", is_flag=True, help="Output as JSON")
|
|
@@ -854,7 +876,7 @@ def _handle_review_output(
|
|
|
854
876
|
"effort",
|
|
855
877
|
type=click.Choice(list(CLAUDE_EFFORT_LEVELS)),
|
|
856
878
|
default=None,
|
|
857
|
-
help="
|
|
879
|
+
help="Claude workers only: reasoning effort (low/medium/high/xhigh/max)",
|
|
858
880
|
)
|
|
859
881
|
@click.pass_context
|
|
860
882
|
def analyze(
|
|
@@ -1036,7 +1058,7 @@ def _resolve_debate_prompt(
|
|
|
1036
1058
|
"-m",
|
|
1037
1059
|
type=str,
|
|
1038
1060
|
default=None,
|
|
1039
|
-
help="Comma-separated
|
|
1061
|
+
help="Comma-separated worker names across Claude/Codex runtimes (default: workflow quorum)",
|
|
1040
1062
|
)
|
|
1041
1063
|
@click.option("--timeout", "-t", type=int, default=600, help="Per-model timeout in seconds")
|
|
1042
1064
|
@click.option("--json", "as_json", is_flag=True, help="Output as JSON")
|
|
@@ -1066,7 +1088,7 @@ def _resolve_debate_prompt(
|
|
|
1066
1088
|
"effort",
|
|
1067
1089
|
type=click.Choice(list(CLAUDE_EFFORT_LEVELS)),
|
|
1068
1090
|
default=None,
|
|
1069
|
-
help="
|
|
1091
|
+
help="Claude workers only: reasoning effort (low/medium/high/xhigh/max)",
|
|
1070
1092
|
)
|
|
1071
1093
|
@click.pass_context
|
|
1072
1094
|
def debate(
|
|
@@ -1567,7 +1589,7 @@ def _print_consensus_text(output: ConsensusOutput, resolved_models: dict[str, di
|
|
|
1567
1589
|
"-m",
|
|
1568
1590
|
type=str,
|
|
1569
1591
|
default=None,
|
|
1570
|
-
help="Comma-separated
|
|
1592
|
+
help="Comma-separated worker names across Claude/Codex runtimes (default: workflow quorum)",
|
|
1571
1593
|
)
|
|
1572
1594
|
@click.option(
|
|
1573
1595
|
"--timeout",
|
|
@@ -1603,7 +1625,7 @@ def _print_consensus_text(output: ConsensusOutput, resolved_models: dict[str, di
|
|
|
1603
1625
|
"effort",
|
|
1604
1626
|
type=click.Choice(list(CLAUDE_EFFORT_LEVELS)),
|
|
1605
1627
|
default=None,
|
|
1606
|
-
help="
|
|
1628
|
+
help="Claude workers only: reasoning effort (low/medium/high/xhigh/max)",
|
|
1607
1629
|
)
|
|
1608
1630
|
@click.pass_context
|
|
1609
1631
|
def consensus(
|
|
@@ -8,6 +8,7 @@ ordered fan-out, timeouts) and per-job usage emission. Phase 5 adds a
|
|
|
8
8
|
|
|
9
9
|
from .claude import ClaudeHeadlessInvoker
|
|
10
10
|
from .codex import CodexHeadlessInvoker, prepare_codex_request
|
|
11
|
+
from ._lifecycle import run_grouped_parallel
|
|
11
12
|
from .types import (
|
|
12
13
|
Attribution,
|
|
13
14
|
HeadlessInvoker,
|
|
@@ -23,4 +24,5 @@ __all__ = [
|
|
|
23
24
|
"HeadlessRequest",
|
|
24
25
|
"HeadlessResult",
|
|
25
26
|
"prepare_codex_request",
|
|
27
|
+
"run_grouped_parallel",
|
|
26
28
|
]
|