Skip to content

fix(strix): retry artifact-less provider crashes without weakening exhaustion - #734

Closed
seonghobae wants to merge 3 commits into
mainfrom
fix/strix-gate-provider-crash-fallback
Closed

fix(strix): retry artifact-less provider crashes without weakening exhaustion#734
seonghobae wants to merge 3 commits into
mainfrom
fix/strix-gate-provider-crash-fallback

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Problem

A provider crash can emit fatal/warning text and severity-like console markers without producing a vulnerabilities/*.md report. The gate previously interpreted that crash debris as unmapped vulnerability evidence and returned non-recoverable before trying configured fallback models. Separately, the workflow used to convert exhausted provider failures into a neutral success, leaving the required security context green without completed evidence.

Observed on wardnet #68: the primary NVIDIA NIM model returned HTTP 429, produced no vulnerability artifact, and the fallback chain never ran.

Changes

Retry only the artifact-less infrastructure classification

  • snapshot report run directories before each model attempt;
  • scope report failure-signal attribution to directories created by that attempt, so a crashed primary cannot poison a clean fallback success;
  • classify INFRA_ERROR_DETECTED with no current-run vulnerabilities/*.md artifact as retryable across fallback models;
  • preserve every actual vulnerability report artifact across attempts and fail before accepting a fallback success when a threshold finding exists.

Add bounded same-provider fallbacks

For nvidia_nim mode, try the existing approved Nemotron candidates before degrading to GitHub Models:

  1. nvidia_nim/nvidia/llama-3.1-nemotron-ultra-253b-v1
  2. nvidia_nim/nvidia/nemotron-3-super-120b-a12b
  3. github_models/openai/o3
  4. github_models/openai/gpt-5-chat

No new credentials or unbounded retry path are introduced.

Preserve fail-closed exhaustion

After all configured attempts, any nonzero Strix result remains nonzero. Provider unavailability without a vulnerability report is incomplete security evidence; it is not converted into a neutral success. Artifacts and the exact gate console log are still collected under always() for diagnosis.

Regression contracts

  • artifact-less 429 crash with log-only severity debris → fallback is attempted and a clean fallback may pass;
  • 429 crash with a real CRITICAL report artifact → fails before fallback;
  • later attempts ignore earlier run-directory warning/fatal logs while all vulnerability artifacts remain globally visible;
  • wrapper propagates the exact nonzero gate exit under the same Bash flags used by Actions;
  • quota exhaustion with no report remains a failed required check;
  • host environments without Bash skip only the executable wrapper contracts;
  • the bounded required-path smoke test pins both retry classification and final fail-closed exhaustion.

Scope

Seven files change: the Strix workflow, gate, full and bounded shell contracts, shared Bash-test collection guard, required-workflow contract, and executable workflow-wrapper contract.

Supersession

This PR supersedes #733's fallback-only change and #587's wrapper-only fail-closed change by composing both with the crash-debris retry classifier. It deliberately does not synthesize success or weaken the Medium+ vulnerability threshold.

seonghobae and others added 2 commits August 4, 2026 16:44
When the primary NVIDIA NIM model (nemotron-3-ultra-550b-a55b) is
rate-limited or unavailable, try nvidia_nim/nvidia/llama-3.1-nemotron-
ultra-253b-v1 and nvidia_nim/nvidia/nemotron-3-super-120b-a12b — both
already part of the contract-tested opencode NIM candidate pool — before
degrading to the cross-provider GitHub Models fallbacks (o3, gpt-5-chat).
NIM candidates reuse the already-provisioned NIM key and API base, and
the chain stays bounded by STRIX_TOTAL_TIMEOUT_SECONDS.

Updates the pinned contract assertion in test_strix_quick_gate.sh.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ructure

Observed on wardnet PR #68 run 30879125169 (job 91896495516): the primary
model nvidia_nim/nvidia/nemotron-3-ultra-550b-a55b crashed with a litellm
RateLimitError 429. The crash left warning/fatal markers in report
artifacts and severity-like markers in the console log, but produced no
vulnerabilities/*.md artifact. The gate classified the log-only markers as
block_unmapped and returned non-recoverable BEFORE the fallback loop, so
the configured STRIX_FALLBACK_MODELS chain never ran, and the crash text
also matched reported_vulnerability_signal, bypassing the workflow-level
backend-unavailable neutral skip.

Gate (scripts/ci/strix_quick_gate.sh):
- When INFRA_ERROR_DETECTED is set and no attempt produced a
  vulnerabilities/*.md artifact, the block_changed/block_unmapped/
  block_manifest_unverified decisions are reclassified as retryable
  provider infrastructure: the primary falls through to the fallback
  loop and fallback attempts continue to the next candidate.
- Scope the report-artifact failure-signal check to run directories
  created by the current attempt, so a crashed primary's warning/fatal
  report logs no longer poison a clean fallback success in strict
  provider-signal mode. Earlier-attempt errors stay recorded in the
  sticky INFRA_ERROR_DETECTED flag.
- Invariant preserved: any attempt that produced an actual
  vulnerabilities/*.md artifact at/above STRIX_FAIL_ON_MIN_SEVERITY still
  fails closed (fail_reported_vulnerabilities_before_fallback_success
  runs first, and the reclassification requires artifact absence).

Workflow (.github/workflows/strix.yml):
- Neutral-skip a backend-unavailable failure whose severity markers are
  log-text only: when the backend_unavailable_signal matched but no
  vulnerabilities/*.md artifact exists on disk, skip neutrally instead of
  hard-failing on crash-echoed severity markers. A real report artifact
  on disk keeps failing closed.

Tests:
- test_strix_quick_gate.sh: two new scenarios —
  ratelimit-crash-log-only-severity-no-artifact-fallback-succeeds (429
  crash, FATAL report log, log-only Severity marker, no artifact →
  fallback attempted and succeeds) and
  ratelimit-crash-with-report-artifact-fails-closed (429 crash plus real
  CRITICAL artifact → fails closed before any fallback attempt); synced
  the stale actions/setup-python pin to main (v7.0.0).
- strix_required_workflow_smoke.sh: pin the new gate classification and
  the workflow artifact check on the CI-gated required path.
- test_required_workflow_queue_contract.py: pin the artifact-aware
  neutral-skip block.

Verification: full test_strix_quick_gate.sh suite passes on Linux (0
failures vs 1 stale-pin failure on the pristine baseline); smoke test
passes; pytest contract suite shows no new failures.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@seonghobae, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 3 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: c5c1dc72-ddd3-4e9f-bcac-d0e89abcb454

📥 Commits

Reviewing files that changed from the base of the PR and between 3f65dbe and 269456c.

📒 Files selected for processing (7)
  • .github/workflows/strix.yml
  • scripts/ci/strix_quick_gate.sh
  • scripts/ci/strix_required_workflow_smoke.sh
  • scripts/ci/test_strix_quick_gate.sh
  • tests/conftest.py
  • tests/test_required_workflow_queue_contract.py
  • tests/test_strix_workflow_shell_contract.py

Comment @coderabbitai help to get the list of available commands.

@seonghobae seonghobae changed the title fix(strix): treat artifact-less provider crashes as retryable infrastructure fix(strix): retry artifact-less provider crashes without weakening exhaustion Aug 4, 2026
@seonghobae
seonghobae enabled auto-merge (squash) August 4, 2026 09:29

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@opencode-agent opencode-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

OpenCode cannot approve yet because required coverage evidence did not pass.

Review outcome

1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence

  • Problem: The required coverage-evidence job result was failure, so OpenCode cannot establish approval sufficiency for this head.

  • Root cause: Automated approval is only valid when the same-head coverage-evidence job proves supported repository test suites passed and configured docstring gates passed or were advisory, or reports not applicable because no supported source files or package manifests exist. Missing, failed, skipped, unavailable, or unsupported-tooling test evidence is a blocker.

  • Fix: Install or configure the repository test/docstring evidence tooling when source files or package manifests exist, rerun the current-head coverage-evidence job, and approve only after it reports success with required evidence or explicit no-source not-applicable evidence.

  • Regression test: Keep the approval branch checking needs.coverage-evidence.result == success before posting APPROVE, and publish REQUEST_CHANGES when coverage-evidence blocker states such as cancelled, skipped, failed, unsupported-tooling, or below-100 evidence are present.

  • Result: REQUEST_CHANGES

  • Reason: coverage-evidence result was failure, so required test/docstring evidence was not proven for current head 269456cfe749385f85e1928f3ebd30252d556504.

  • Head SHA: 269456cfe749385f85e1928f3ebd30252d556504

  • Workflow run: 30900198092

  • Workflow attempt: 1

Coverage evidence

Coverage Decision

  • Result: FAIL
  • Test evidence: not proven passing
  • Docstring evidence: not proven passing when configured
  • Failure count: 1

Changed-File Evidence Map

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Workflow: strix.yml"]
  S1 --> I1["GitHub Actions review job"]
  I1 --> R1["Review risk: Workflow: strix.yml"]
  R1 --> V1["actionlint plus required checks"]
  Evidence --> S2["CI script (3 files)"]
  S2 --> I2["review and security gate shell path"]
  I2 --> R2["Review risk: CI script (3 files)"]
  R2 --> V2["bash -n plus Strix self-test"]
  Evidence --> S3["Test (3 files)"]
  S3 --> I3["regression suite"]
  I3 --> R3["Review risk: Test (3 files)"]
  R3 --> V3["targeted test run"]
Loading

@opencode-agent

opencode-agent Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

OpenCode Review Overview

  • Head SHA: 269456cfe749385f85e1928f3ebd30252d556504
  • Workflow run: 30900198092
  • Workflow attempt: 1
  • Gate result: REQUEST_CHANGES (approval step)

Pull request overview

OpenCode cannot approve yet because required coverage evidence did not pass.

Review outcome

1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence

  • Problem: The required coverage-evidence job result was failure, so OpenCode cannot establish approval sufficiency for this head.

  • Root cause: Automated approval is only valid when the same-head coverage-evidence job proves supported repository test suites passed and configured docstring gates passed or were advisory, or reports not applicable because no supported source files or package manifests exist. Missing, failed, skipped, unavailable, or unsupported-tooling test evidence is a blocker.

  • Fix: Install or configure the repository test/docstring evidence tooling when source files or package manifests exist, rerun the current-head coverage-evidence job, and approve only after it reports success with required evidence or explicit no-source not-applicable evidence.

  • Regression test: Keep the approval branch checking needs.coverage-evidence.result == success before posting APPROVE, and publish REQUEST_CHANGES when coverage-evidence blocker states such as cancelled, skipped, failed, unsupported-tooling, or below-100 evidence are present.

  • Result: REQUEST_CHANGES

  • Reason: coverage-evidence result was failure, so required test/docstring evidence was not proven for current head 269456cfe749385f85e1928f3ebd30252d556504.

  • Head SHA: 269456cfe749385f85e1928f3ebd30252d556504

  • Workflow run: 30900198092

  • Workflow attempt: 1

Coverage evidence

Coverage Decision

  • Result: FAIL
  • Test evidence: not proven passing
  • Docstring evidence: not proven passing when configured
  • Failure count: 1

Changed-File Evidence Map

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Workflow: strix.yml"]
  S1 --> I1["GitHub Actions review job"]
  I1 --> R1["Review risk: Workflow: strix.yml"]
  R1 --> V1["actionlint plus required checks"]
  Evidence --> S2["CI script (3 files)"]
  S2 --> I2["review and security gate shell path"]
  I2 --> R2["Review risk: CI script (3 files)"]
  R2 --> V2["bash -n plus Strix self-test"]
  Evidence --> S3["Test (3 files)"]
  S3 --> I3["regression suite"]
  I3 --> R3["Review risk: Test (3 files)"]
  R3 --> V3["targeted test run"]
Loading

@opencode-agent
opencode-agent Bot disabled auto-merge August 4, 2026 10:26
@seonghobae
seonghobae enabled auto-merge (squash) August 4, 2026 10:43
@opencode-agent
opencode-agent Bot disabled auto-merge August 4, 2026 10:48
@seonghobae
seonghobae enabled auto-merge (squash) August 4, 2026 11:02

Copy link
Copy Markdown
Contributor Author

@opencode-agent Please re-review exact head 269456cfe749385f85e1928f3ebd30252d556504 after central baseline PR #731 lands and exact-head coverage evidence reruns. Verify artifact-less infrastructure crashes are retryable only across the bounded model chain, real vulnerability artifacts remain fail-closed, and provider exhaustion never becomes success. Submit APPROVE only if all current-head evidence passes.

Copy link
Copy Markdown
Contributor Author

@cwl-noema-review Please independently review exact head 269456cfe749385f85e1928f3ebd30252d556504 after #731 repairs the central baseline and current-head checks complete. Confirm bounded retry and fail-closed exhaustion semantics; submit APPROVE only if no blocker remains.

@seonghobae seonghobae closed this Aug 4, 2026
auto-merge was automatically disabled August 4, 2026 11:12

Pull request was closed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant