Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 5 additions & 52 deletions .github/workflows/strix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -920,9 +920,6 @@ jobs:
# The gateway auto pool is provider-diverse. Strix function tools
# must not send a provider-specific reasoning setting to every route.
STRIX_REASONING_EFFORT: none
STRIX_LLM_MAX_RETRIES: 1
STRIX_TRANSIENT_RETRY_PER_MODEL: 2
STRIX_TRANSIENT_RETRY_BACKOFF_SECONDS: 60
# The gateway owns discovery and provider failover; Strix must not
# bypass its ZDR/privacy policy with an external fallback model.
STRIX_FALLBACK_MODELS: ""
Expand Down Expand Up @@ -968,60 +965,16 @@ jobs:
# evidence, but remains non-passing because no authoritative complete
# vulnerability result exists.
#
# A typed provider outage with no reported vulnerability finding is
# retried with 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, and all-terminal outcomes remain fail-closed.
# The gateway owns provider discovery, repair, and failover. Invoke
# the trusted gate once so repository-side retries cannot multiply a
# single PR scan into hours of shared-runner occupancy.
strix_run_log="$RUNNER_TEMP/strix_gate_console.log"
: > "$strix_run_log"
strix_terminal_log="$strix_run_log"
strix_rc=0
strix_gate_attempt=1
set +e
while : ; do
strix_attempt_log="$RUNNER_TEMP/strix_gate_console_attempt_${strix_gate_attempt}.log"
: > "$strix_attempt_log"
bash "$TRUSTED_STRIX_GATE" 2>&1 | tee "$strix_attempt_log"
strix_rc="${PIPESTATUS[0]}"
cat "$strix_attempt_log" >> "$strix_run_log"
strix_terminal_log="$strix_attempt_log"
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_terminal_log"
if grep -Fq 'allowing pipeline continuation' "$strix_terminal_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_terminal_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
fi
backoff_seconds=$(( ${STRIX_GATE_RETRY_BACKOFF_SECONDS:-90} * strix_gate_attempt ))
if [ "$strix_gate_attempt" -ge 3 ]; then
echo "Provider-unavailable Strix attempt ${strix_gate_attempt} reached the retry limit; failing closed." >&2
break
fi
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
bash "$TRUSTED_STRIX_GATE" 2>&1 | tee "$strix_terminal_log"
strix_rc="${PIPESTATUS[0]}"
set -e

if [ "$strix_rc" -eq 0 ]; then
Expand Down
30 changes: 6 additions & 24 deletions tests/test_strix_backend_unavailable_after_exempted_finding.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,26 +240,6 @@ def test_bare_backend_outage_with_no_finding_is_non_passing(

self.assertEqual(_run_gate_tail(GITHUB_MODELS_BROWNOUT), 1)

def test_exempted_finding_then_outage_recovers_on_second_attempt(self) -> None:
"""An exempt finding before continuation must not block outage retry."""

gate = r"""#!/usr/bin/env bash
calls=$(( $(cat __COUNTER__) + 1 ))
echo "$calls" > __COUNTER__
if [ "$calls" -le 1 ]; then
printf '%s\n' \
"Strix findings are limited to unchanged files in this pull request; allowing pipeline continuation." \
"LLM CONNECTION FAILED" \
"Configured model and fallback models were unavailable."
exit 1
fi
echo "scan complete"
exit 0
"""
returncode, calls = _run_gate_retry(gate)
self.assertEqual(returncode, 0)
self.assertEqual(calls, 2)

def test_real_finding_after_continuation_never_retries(self) -> None:
"""A tail-scoped real finding is authoritative: zero retries, fail closed."""

Expand All @@ -276,12 +256,14 @@ def test_real_finding_after_continuation_never_retries(self) -> None:
self.assertEqual(returncode, 1)
self.assertEqual(calls, 1)

def test_retry_contract_preserves_logs_without_wall_clock_budget(self) -> None:
"""Retries retain every attempt without imposing an inference deadline."""
def test_workflow_uses_one_gateway_owned_attempt_without_wall_clock_budget(self) -> None:
"""The workflow does not add retries or a repository-authored deadline."""

workflow = STRIX_WORKFLOW.read_text(encoding="utf-8")
self.assertIn('strix_attempt_log="$RUNNER_TEMP/strix_gate_console_attempt_', workflow)
self.assertIn('cat "$strix_attempt_log" >> "$strix_run_log"', workflow)
self.assertNotIn("strix_gate_attempt", workflow)
self.assertNotIn("STRIX_GATE_RETRY_BACKOFF_SECONDS", workflow)
self.assertNotIn("STRIX_TRANSIENT_RETRY_PER_MODEL:", workflow)
self.assertNotIn("STRIX_LLM_MAX_RETRIES:", workflow)
self.assertNotIn("strix_gate_attempt_budget_seconds", workflow)
self.assertNotIn("STRIX_PROCESS_TIMEOUT_SECONDS:", workflow)
self.assertNotIn("STRIX_TOTAL_TIMEOUT_SECONDS:", workflow)
Expand Down
Loading