diff --git a/.github/workflows/opencode-review.yml b/.github/workflows/opencode-review.yml index 1091f72f..2385de32 100644 --- a/.github/workflows/opencode-review.yml +++ b/.github/workflows/opencode-review.yml @@ -3299,12 +3299,20 @@ jobs: "apiKey": "{env:OPENROUTER_API_KEY}" }, "models": { - "openrouter/free": { - "name": "OpenRouter Free", + "nvidia/nemotron-3-ultra-550b-a55b:free": { + "name": "NVIDIA Nemotron 3 Ultra 550B (free)", "tool_call": true, "limit": { - "context": 128000, - "output": 4096 + "context": 1000000, + "output": 65536 + } + }, + "poolside/laguna-m.1:free": { + "name": "Poolside Laguna M.1 (free)", + "tool_call": true, + "limit": { + "context": 262144, + "output": 32768 } } } @@ -3537,14 +3545,16 @@ jobs: NO_COLOR: "1" # High-sensitivity review candidates only. DeepSeek V3 has been the # most reliable first-pass reviewer in the org queue, then the pool - # falls through to the direct GPT-5.6 Luna slot, OpenRouter's free - # compatibility endpoint, then the full-size GPT-4.1 long-context + # falls through to the direct GPT-5.6 Luna slot, pinned OpenRouter + # free models (the openrouter/free router routed to weak models that + # never produced a control block, so tool-capable free models are + # pinned explicitly), then the full-size GPT-4.1 long-context # endpoint and provider-specific GPT/o3 fallbacks. # The direct-OpenAI slot runs GPT-5.6 Luna: the newest family's # cost-efficient tier, cheaper than the legacy gpt-5 it replaced # ($1/$6 vs $1.25/$10 per 1M tokens) so the org OpenAI budget # stretches further between top-ups. - OPENCODE_MODEL_CANDIDATES: "github-models/deepseek/deepseek-v3-0324 openai/gpt-5.6-luna openrouter/openrouter/free github-models/openai/gpt-4.1 github-models/openai/gpt-5 github-models/openai/gpt-5-chat github-models/openai/o3 github-models/deepseek/deepseek-r1-0528 github-models/deepseek/deepseek-r1" + OPENCODE_MODEL_CANDIDATES: "github-models/deepseek/deepseek-v3-0324 openai/gpt-5.6-luna openrouter/nvidia/nemotron-3-ultra-550b-a55b:free openrouter/poolside/laguna-m.1:free github-models/openai/gpt-4.1 github-models/openai/gpt-5 github-models/openai/gpt-5-chat github-models/openai/o3 github-models/deepseek/deepseek-r1-0528 github-models/deepseek/deepseek-r1" # One attempt per model, then fall through to the next model. Retrying # the SAME model 5x let a rate-limited/hung leader consume the whole # step, so the pool never reached a healthy fallback model. diff --git a/scripts/ci/test_strix_quick_gate.sh b/scripts/ci/test_strix_quick_gate.sh index d5ff2795..ab959302 100755 --- a/scripts/ci/test_strix_quick_gate.sh +++ b/scripts/ci/test_strix_quick_gate.sh @@ -700,7 +700,7 @@ assert_opencode_review_uses_codegraph_and_gpt5_fallback() { assert_file_contains "$workflow_file" 'OPENCODE_MODEL_ATTEMPTS: "1"' "opencode fallback tries the catalog promptly instead of spending the entire review on one model" assert_file_contains "$workflow_file" "Run OpenCode PR Review model pool" "opencode review includes a broad catalog fallback pool" assert_file_not_contains "$workflow_file" "steps.opencode_review_model_pool.outcome == 'success'" "opencode approval gate still runs after model pool failure to publish a reason" - assert_file_contains "$workflow_file" "github-models/deepseek/deepseek-v3-0324 openai/gpt-5.6-luna openrouter/openrouter/free github-models/openai/gpt-4.1 github-models/openai/gpt-5" "opencode review starts with DeepSeek V3 before full-size GPT fallbacks" + assert_file_contains "$workflow_file" "github-models/deepseek/deepseek-v3-0324 openai/gpt-5.6-luna openrouter/nvidia/nemotron-3-ultra-550b-a55b:free openrouter/poolside/laguna-m.1:free github-models/openai/gpt-4.1 github-models/openai/gpt-5" "opencode review starts with DeepSeek V3 before full-size GPT fallbacks" assert_file_contains "$workflow_file" "The publish gate re-runs source-backed validation against PR-head data" "opencode review publish gate validates model output against the PR-head worktree" assert_file_contains "$workflow_file" '"openai/o3"' "opencode config declares OpenAI o3 fallback" assert_file_contains "$workflow_file" '"openai/o4-mini"' "opencode config declares OpenAI o4-mini fallback" @@ -848,7 +848,7 @@ assert_opencode_review_uses_codegraph_and_gpt5_fallback() { assert_file_contains "$workflow_file" 'OPENCODE_RUN_TIMEOUT_SECONDS: "5400"' "opencode catalog fallback preserves legitimate full-hour provider sessions" assert_file_contains "$REPO_ROOT/scripts/ci/run_opencode_review_model_pool.sh" "OpenCode %s attempt %s/%s failed" "opencode catalog fallback records per-model retry failures" assert_file_contains "$REPO_ROOT/scripts/ci/run_opencode_review_model_pool.sh" "exponential backoff" "opencode model retry paths use exponential backoff instead of fixed sleeps" - assert_file_contains "$workflow_file" "github-models/deepseek/deepseek-v3-0324 openai/gpt-5.6-luna openrouter/openrouter/free github-models/openai/gpt-4.1 github-models/openai/gpt-5" "opencode review tries DeepSeek V3 before OpenAI fallbacks" + assert_file_contains "$workflow_file" "github-models/deepseek/deepseek-v3-0324 openai/gpt-5.6-luna openrouter/nvidia/nemotron-3-ultra-550b-a55b:free openrouter/poolside/laguna-m.1:free github-models/openai/gpt-4.1 github-models/openai/gpt-5" "opencode review tries DeepSeek V3 before OpenAI fallbacks" assert_file_contains "$workflow_file" "github-models/deepseek/deepseek-r1-0528 github-models/deepseek/deepseek-r1" "opencode review keeps DeepSeek reasoning fallback coverage after OpenAI candidates" assert_file_contains "$workflow_file" "coverage-source-tree:" "opencode workflow materializes coverage source before running PR-head tests" assert_file_contains "$workflow_file" "coverage-evidence:" "opencode workflow measures coverage before review" @@ -1165,7 +1165,7 @@ assert_opencode_review_uses_codegraph_and_gpt5_fallback() { assert_file_contains "$workflow_file" 'GH_TOKEN: ${{ secrets.OPENCODE_APPROVE_TOKEN || steps.review_read_app_token.outputs.token || github.token }}' "opencode manual dispatch uses the cross-repo approval token for target PR evidence lookups with app-token fallback" assert_file_contains "$workflow_file" 'repos/${GH_REPOSITORY}' "opencode review workflow uses env-backed repository context in shell commands" assert_file_contains "$workflow_file" "Run OpenCode PR Review model pool" "opencode review starts the central model pool" - assert_file_contains "$workflow_file" "github-models/deepseek/deepseek-v3-0324 openai/gpt-5.6-luna openrouter/openrouter/free github-models/openai/gpt-4.1 github-models/openai/gpt-5" "opencode review starts with DeepSeek V3 before full-size GPT fallbacks" + assert_file_contains "$workflow_file" "github-models/deepseek/deepseek-v3-0324 openai/gpt-5.6-luna openrouter/nvidia/nemotron-3-ultra-550b-a55b:free openrouter/poolside/laguna-m.1:free github-models/openai/gpt-4.1 github-models/openai/gpt-5" "opencode review starts with DeepSeek V3 before full-size GPT fallbacks" assert_file_contains "$workflow_file" "github-models/deepseek/deepseek-r1-0528" "opencode review keeps a reachable DeepSeek R1 reasoning fallback model" assert_file_contains "$workflow_file" "github-models/deepseek/deepseek-v3-0324" "opencode review has a reachable DeepSeek V3 fallback model" assert_file_contains "$workflow_file" "github-models/openai/gpt-5" "opencode review still has a bounded GPT-5 fallback model" diff --git a/tests/test_opencode_agent_contract.py b/tests/test_opencode_agent_contract.py index f2bb8a4a..b9c872d7 100644 --- a/tests/test_opencode_agent_contract.py +++ b/tests/test_opencode_agent_contract.py @@ -108,7 +108,8 @@ def test_opencode_model_pool_sets_high_effort_for_capable_candidates(): assert candidate_pairs == [ ["github-models", "deepseek/deepseek-v3-0324"], ["openai", "gpt-5.6-luna"], - ["openrouter", "openrouter/free"], + ["openrouter", "nvidia/nemotron-3-ultra-550b-a55b:free"], + ["openrouter", "poolside/laguna-m.1:free"], ["github-models", "openai/gpt-4.1"], ["github-models", "openai/gpt-5"], ["github-models", "openai/gpt-5-chat"], @@ -117,7 +118,10 @@ def test_opencode_model_pool_sets_high_effort_for_capable_candidates(): ["github-models", "deepseek/deepseek-r1"], ] assert direct_openai_models == ["gpt-5.6-luna"] - assert openrouter_models == ["openrouter/free"] + assert openrouter_models == [ + "nvidia/nemotron-3-ultra-550b-a55b:free", + "poolside/laguna-m.1:free", + ] assert set(github_candidate_models).issubset(set(github_models)) assert github_candidate_models == [ "deepseek/deepseek-v3-0324", @@ -1099,7 +1103,8 @@ def test_workflow_provisions_sandbox_tool_and_reviewer_agent(): assert ( 'OPENCODE_MODEL_CANDIDATES: "github-models/deepseek/deepseek-v3-0324 ' "openai/gpt-5.6-luna " - "openrouter/openrouter/free " + "openrouter/nvidia/nemotron-3-ultra-550b-a55b:free " + "openrouter/poolside/laguna-m.1:free " "github-models/openai/gpt-4.1 " "github-models/openai/gpt-5 " "github-models/openai/gpt-5-chat " @@ -1223,7 +1228,8 @@ def test_workflow_provisions_sandbox_tool_and_reviewer_agent(): assert ( 'OPENCODE_MODEL_CANDIDATES: "github-models/deepseek/deepseek-v3-0324 ' "openai/gpt-5.6-luna " - "openrouter/openrouter/free " + "openrouter/nvidia/nemotron-3-ultra-550b-a55b:free " + "openrouter/poolside/laguna-m.1:free " "github-models/openai/gpt-4.1 " "github-models/openai/gpt-5 " "github-models/openai/gpt-5-chat "