-
Notifications
You must be signed in to change notification settings - Fork 0
fix(strix): bounded retry for typed provider outages without findings #1322
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
1ec0be1
e61dd47
51446e8
04755fe
285d661
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -863,6 +863,17 @@ jobs: | |
| export "STRIX_PROCESS_${budget_suffix}_SECONDS=$process_budget_seconds" | ||
| export "STRIX_TOTAL_${budget_suffix}_SECONDS=5700" | ||
|
|
||
| # Recognized signals that the LLM backend was unavailable / starved. | ||
| # Defined before the gate loop so the bounded retry decision below | ||
| # can classify outcomes without duplicating the patterns later. | ||
| backend_unavailable_signal='RateLimitError|Too many requests\. For more on scraping GitHub|exceeded your current quota|insufficient_quota|billing details|"status"[[:space:]]*:[[:space:]]*"RESOURCE_EXHAUSTED"|tokens_limit_reached|Request body too large|Max size:[[:space:]]*[0-9]+[[:space:]]+tokens|Error code:[[:space:]]*413|LLM CONNECTION FAILED|Could not establish connection to the language model|LLM warm-up failed|Configured model and fallback models were unavailable|Configured Vertex model and fallback models were unavailable|emitted provider infrastructure or failure-signal output|before provider infrastructure failure|litellm(\.exceptions)?\.NotFoundError[^[:cntrl:]]*Nvidia_nimException[^[:cntrl:]]*Error code:[[:space:]]*404|Error during penetration test: loginAsGuest failed after [0-9]+ attempts: curl exit 7: curl: \(7\) Failed to connect to 127\.0\.0\.1 port 48080' | ||
| model_behavior_error_signal='(^|[^A-Za-z0-9_])(agents|pydantic_ai|strix)(\.[A-Za-z_][A-Za-z0-9_]*)*\.ModelBehaviorError([^A-Za-z0-9_]|$)' | ||
| # Any evidence that a vulnerability was actually reported. Its presence | ||
| # forces a hard failure so real findings are NEVER downgraded. Keep the | ||
| # severity branch anchored away from identifiers so environment lines | ||
| # such as STRIX_FAIL_ON_MIN_SEVERITY do not look like findings. | ||
| reported_vulnerability_signal='Vulnerabilities[[:space:]]+[1-9]|(^|[^A-Za-z0-9_])severity[[:space:]]*:' | ||
|
|
||
| # Capture the gate exit code plus its console output. The gate returns | ||
| # exit 1 both for genuine blocking vulnerabilities AND for | ||
| # LLM-backend-unavailable outcomes (GitHub Models "Too many requests" | ||
|
|
@@ -871,11 +882,60 @@ jobs: | |
| # could not complete a scan. Provider failure is typed infrastructure | ||
| # evidence, but remains non-passing because no authoritative complete | ||
| # vulnerability result exists. | ||
| # | ||
| # A typed provider outage with no reported vulnerability finding is | ||
| # retried with bounded linear backoff inside this step so transient | ||
| # provider failures do not fail the required check on the first | ||
| # attempt. Genuine findings, configuration failures, and unexpected | ||
| # exit codes never retry; the deadline keeps every path inside the | ||
| # deterministic 120-minute job budget, and all-terminal outcomes | ||
| # remain fail-closed. | ||
| strix_run_log="$RUNNER_TEMP/strix_gate_console.log" | ||
| strix_rc=0 | ||
| strix_gate_attempt=1 | ||
| strix_gate_deadline=$(( SECONDS + 6000 )) | ||
| set +e | ||
| bash "$TRUSTED_STRIX_GATE" 2>&1 | tee "$strix_run_log" | ||
| strix_rc="${PIPESTATUS[0]}" | ||
| while : ; do | ||
| : > "$strix_run_log" | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📝 Info: Earlier retry attempts' logs are discarded
Was this helpful? React with 👍 or 👎 to provide feedback. |
||
| bash "$TRUSTED_STRIX_GATE" 2>&1 | tee "$strix_run_log" | ||
| strix_rc="${PIPESTATUS[0]}" | ||
| if [ "$strix_rc" -eq 0 ]; then | ||
| break | ||
| fi | ||
| # Only exit-code 1 scan failures can be infrastructure outcomes. | ||
| if [ "$strix_rc" -ne 1 ]; then | ||
| break | ||
| fi | ||
| # Scope this attempt's retry decision to the log tail after the | ||
| # last pipeline-continuation marker, exactly like the terminal | ||
| # classification below: an already-exempted finding before the | ||
| # marker must not mask a retryable outage after it. | ||
| strix_retry_scope_log="$strix_run_log" | ||
| if grep -Fq 'allowing pipeline continuation' "$strix_run_log"; then | ||
| strix_retry_scope_log="$RUNNER_TEMP/strix_gate_console_tail.log" | ||
| awk '/allowing pipeline continuation/{buf=""; next} {buf=buf $0 "\n"} END{printf "%s", buf}' \ | ||
| "$strix_run_log" > "$strix_retry_scope_log" | ||
| fi | ||
| # A reported vulnerability is authoritative evidence: never retry | ||
| # and never risk downgrading it. | ||
| if grep -Eiq "$reported_vulnerability_signal" "$strix_retry_scope_log"; then | ||
| break | ||
| fi | ||
| # Retry only recognized provider-outage / model-behavior classes. | ||
| if ! grep -Eiq "$backend_unavailable_signal" "$strix_retry_scope_log" \ | ||
| && ! grep -Eq "$model_behavior_error_signal" "$strix_retry_scope_log"; then | ||
| break | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| fi | ||
|
devin-ai-integration[bot] marked this conversation as resolved.
|
||
| remaining_seconds=$(( strix_gate_deadline - SECONDS )) | ||
| if [ "$strix_gate_attempt" -ge 3 ] || [ "$remaining_seconds" -lt 600 ]; then | ||
| echo "Provider-unavailable Strix attempt ${strix_gate_attempt} reached the bounded retry limit or the remaining job time budget (${remaining_seconds}s) is too small to retry; failing closed." >&2 | ||
| break | ||
| fi | ||
|
Comment on lines
+929
to
+933
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📝 Info: Retry can start with too little step budget The retry gate permits a new attempt whenever Was this helpful? React with 👍 or 👎 to provide feedback. |
||
| backoff_seconds=$(( ${STRIX_GATE_RETRY_BACKOFF_SECONDS:-90} * strix_gate_attempt )) | ||
| echo "Strix provider outage on attempt ${strix_gate_attempt}; retrying after ${backoff_seconds}s backoff." >&2 | ||
| sleep "$backoff_seconds" | ||
| strix_gate_attempt=$(( strix_gate_attempt + 1 )) | ||
| done | ||
|
Comment on lines
+898
to
+938
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📝 Info: Retry gating preserves fail-closed semantics Retries occur only for exit code 1 with no vulnerability signal in the tail-scoped log and a matching outage/model-behavior signal; findings, exit 2, and unexpected codes break and propagate. Tail-scoping (strix.yml) mirrors the terminal classification, so an earlier exempted finding cannot mask a later outage and a real finding after the continuation marker still blocks. Attempts cap at 3 gate runs. Was this helpful? React with 👍 or 👎 to provide feedback. |
||
| set -e | ||
|
|
||
| if [ "$strix_rc" -eq 0 ]; then | ||
|
|
@@ -889,15 +949,6 @@ jobs: | |
| exit "$strix_rc" | ||
| fi | ||
|
|
||
| # Recognized signals that the LLM backend was unavailable / starved. | ||
| backend_unavailable_signal='RateLimitError|Too many requests\. For more on scraping GitHub|exceeded your current quota|insufficient_quota|billing details|"status"[[:space:]]*:[[:space:]]*"RESOURCE_EXHAUSTED"|tokens_limit_reached|Request body too large|Max size:[[:space:]]*[0-9]+[[:space:]]+tokens|Error code:[[:space:]]*413|LLM CONNECTION FAILED|Could not establish connection to the language model|LLM warm-up failed|Configured model and fallback models were unavailable|Configured Vertex model and fallback models were unavailable|emitted provider infrastructure or failure-signal output|before provider infrastructure failure|litellm(\.exceptions)?\.NotFoundError[^[:cntrl:]]*Nvidia_nimException[^[:cntrl:]]*Error code:[[:space:]]*404|Error during penetration test: loginAsGuest failed after [0-9]+ attempts: curl exit 7: curl: \(7\) Failed to connect to 127\.0\.0\.1 port 48080' | ||
| model_behavior_error_signal='(^|[^A-Za-z0-9_])(agents|pydantic_ai|strix)(\.[A-Za-z_][A-Za-z0-9_]*)*\.ModelBehaviorError([^A-Za-z0-9_]|$)' | ||
| # Any evidence that a vulnerability was actually reported. Its presence | ||
| # forces a hard failure so real findings are NEVER downgraded. Keep the | ||
| # severity branch anchored away from identifiers so environment lines | ||
| # such as STRIX_FAIL_ON_MIN_SEVERITY do not look like findings. | ||
| reported_vulnerability_signal='Vulnerabilities[[:space:]]+[1-9]|(^|[^A-Za-z0-9_])severity[[:space:]]*:' | ||
|
|
||
| # An earlier out-of-scope/below-threshold finding may already have | ||
| # been exempted by the trusted gate. Classify a later provider | ||
| # outage from the tail after the last continuation marker, but keep | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.