Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
5dbf903
fix: separate Strix baseline provider exhaustion
seonghobae Aug 22, 2026
d065e69
fix(strix): neutralize empty Caido bootstrap outages
seonghobae Aug 22, 2026
b9dd912
Merge branch 'main' into fix/strix-baseline-provider-exhaustion
seonghobae Aug 22, 2026
6b03822
Merge latest main into Strix provider fallback branch
seonghobae Aug 22, 2026
7179abb
fix(strix): preserve primary-only baseline result
seonghobae Aug 22, 2026
94eafa4
refactor(strix): remove obsolete fallback probe
seonghobae Aug 22, 2026
51a4aa7
fix(strix): fallback on unsupported sampling defaults
seonghobae Aug 22, 2026
b1ab66f
Merge remote-tracking branch 'origin/main' into fix/strix-baseline-pr…
seonghobae Aug 22, 2026
d1a5a1e
Merge remote-tracking branch 'origin/main' into fix/strix-baseline-pr…
seonghobae Aug 22, 2026
8646703
Merge current main into Strix provider exhaustion fix
seonghobae Aug 22, 2026
a3b149b
fix(strix): align manifest finding decisions
seonghobae Aug 22, 2026
97e283e
Merge branch 'main' into fix/strix-baseline-provider-exhaustion
opencode-agent[bot] Aug 22, 2026
d3246d0
Merge branch 'main' into fix/strix-baseline-provider-exhaustion
opencode-agent[bot] Aug 22, 2026
60f5150
docs(strix): clarify provider exhaustion exits
seonghobae Aug 22, 2026
3205c3e
merge: reconcile Strix provider failure signals
seonghobae Aug 22, 2026
4452244
Merge remote-tracking branch 'origin/main' into HEAD
seonghobae Aug 22, 2026
8063b7b
Merge branch 'main' into fix/strix-baseline-provider-exhaustion
opencode-agent[bot] Aug 22, 2026
99ed4ce
Merge branch 'main' into fix/strix-baseline-provider-exhaustion
opencode-agent[bot] Aug 22, 2026
f915928
Merge branch 'main' into fix/strix-baseline-provider-exhaustion
opencode-agent[bot] Aug 22, 2026
d006293
Merge remote-tracking branch 'refs/remotes/origin/main' into HEAD
seonghobae Aug 23, 2026
94db1b8
Merge remote-tracking branch 'refs/remotes/origin/fix/organization-lo…
seonghobae Aug 23, 2026
83c2944
Merge parent and repair Azure sampling fallback routing
seonghobae Aug 23, 2026
6f6e507
Merge remote-tracking branch 'origin/fix/organization-loop-oidc-fallb…
seonghobae Aug 23, 2026
a675dac
fix(strix): accept clean fallback model advisory
seonghobae Aug 23, 2026
32543e0
fix(strix): accept clean HF advisory
seonghobae Aug 23, 2026
86408ba
docs(strix): record clean fallback advisories
seonghobae Aug 23, 2026
9dcd1d6
fix(strix): preserve fail-closed warning scan
seonghobae Aug 23, 2026
3868a21
fix(strix): isolate cross-provider OpenAI fallback transport
seonghobae Aug 23, 2026
6493023
Merge remote-tracking branch 'origin/fix/strix-baseline-provider-exha…
seonghobae Aug 23, 2026
5edaf36
fix(strix): bound clean advisory filtering
seonghobae Aug 23, 2026
5ab5834
fix(strix): normalize the fallback model before dispatch, not just cr…
seonghobae Aug 23, 2026
8d0f7ca
fix(strix): ignore exact optional web search advisory
seonghobae Aug 23, 2026
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
17 changes: 17 additions & 0 deletions .github/workflows/strix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -696,6 +696,22 @@ jobs:
printf '%s' 'https://models.github.ai/inference' > "$github_models_api_base_file"
echo "STRIX_GITHUB_MODELS_API_BASE_FILE=$github_models_api_base_file" >> "$GITHUB_ENV"

- name: Prepare direct OpenAI fallback credentials
if: steps.gate.outputs.provider_mode == 'github_models' || steps.gate.outputs.provider_mode == 'openrouter' || steps.gate.outputs.provider_mode == 'nvidia_nim'
env:
OPENAI_FALLBACK_API_KEY: ${{ secrets.STRIX_OPENAI_API_KEY || secrets.OPENAI_API_KEY }}
run: |
umask 077
sanitized="$(printf '%s' "$OPENAI_FALLBACK_API_KEY" | tr -d '\r\n')"
trimmed="$(printf '%s' "$sanitized" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')"
if [ -z "$trimmed" ]; then
echo '::notice::No direct OpenAI key available; cross-provider Strix scans run without that fallback.'
exit 0
fi
openai_fallback_key_file="$RUNNER_TEMP/openai_fallback_key.txt"
printf '%s' "$trimmed" > "$openai_fallback_key_file"
echo "STRIX_OPENAI_FALLBACK_KEY_FILE=$openai_fallback_key_file" >> "$GITHUB_ENV"

- name: Prepare Vertex AI credentials
if: steps.gate.outputs.provider_mode == 'vertex_ai'
env:
Expand Down Expand Up @@ -825,6 +841,7 @@ jobs:
STRIX_FALLBACK_MODELS: ${{ steps.gate.outputs.provider_mode == 'github_models' && 'openai-direct/gpt-5.6-luna' || steps.gate.outputs.provider_mode == 'openai_direct' && 'openai-direct/gpt-5.6-luna' || steps.gate.outputs.provider_mode == 'openrouter' && 'openai-direct/gpt-5.6-luna' || steps.gate.outputs.provider_mode == 'nvidia_nim' && 'nvidia_nim/nvidia/llama-3.3-nemotron-super-49b-v1.5 openai-direct/gpt-5.6-luna' || '' }}
Comment thread
seonghobae marked this conversation as resolved.
STRIX_GITHUB_MODELS_API_BASE_FILE: ${{ env.STRIX_GITHUB_MODELS_API_BASE_FILE }}
STRIX_GITHUB_MODELS_KEY_FILE: ${{ env.STRIX_GITHUB_MODELS_KEY_FILE }}
STRIX_OPENAI_FALLBACK_KEY_FILE: ${{ env.STRIX_OPENAI_FALLBACK_KEY_FILE }}
STRIX_FAIL_ON_PROVIDER_SIGNAL: "1"
STRIX_VERTEX_FALLBACK_MODELS: ""
NPM_CONFIG_IGNORE_SCRIPTS: "true"
Expand Down
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,16 @@ Semantic Versioning where the repository publishes a release.

### Changed

- Route the exact single-line LiteLLM/Azure unsupported-temperature failure to
an already-configured distinct Strix fallback without accepting split-line
imitations, and normalize the workflow's `openai-direct/` fallback alias to
LiteLLM's `openai_direct/` provider prefix before dispatch. Cross-provider
attempts now switch to the trusted OpenAI credential and clear the primary
provider API base, without turning an incomplete provider scan into passing
evidence. Exact clean model-quality and Hugging Face advisories are filtered
consistently from console and report logs, while any appended warning text
remains fail closed. The incident and fail-closed boundary are recorded in
`docs/doctoring/strix-unsupported-sampling-fallback.md`.
- Emit completed repository pull-list requests as they finish in the five-minute
agent-mention sweep, while retaining the four-worker ceiling, rotation, and
exact-name dispatch ledger, so one slow repository cannot hide ready sibling
Expand Down
12 changes: 11 additions & 1 deletion docs/doctoring/strix-nvidia-nim-not-found-fallback.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ combining with an unrelated application `404` to spoof infrastructure fallback.
Provider-side failure also remains a fail-closed incomplete scan until a distinct
fallback produces complete evidence.

A completed zero-vulnerability fallback may emit Strix's model-quality banner
and Hugging Face's exact unauthenticated-download advisory while loading public
scanner assets. The trusted gate removes only those two complete lines from both
console and structured report logs. A suffix, prefix, or any other warning text
remains fail-closed provider-failure evidence.

Exhausted provider infrastructure remains fail-closed even when the trusted
gate has classified every observed threshold finding as outside the pull
request's changed files. That classification scopes authoritative findings; it
Expand All @@ -53,7 +59,11 @@ Regression evidence proves that:
8. provider exhaustion remains non-passing after unchanged baseline findings;
9. changed, unmapped, and changed-manifest findings also block after provider
exhaustion; and
10. the required-workflow smoke contract pins these properties.
10. the exact model-quality and Hugging Face download advisories do not reject
an otherwise complete zero-vulnerability fallback when they appear in
console or report logs;
11. appended warning text is not hidden by either exact advisory filter; and
12. the required-workflow smoke contract pins these properties.

## Limitations

Expand Down
67 changes: 67 additions & 0 deletions docs/doctoring/strix-unsupported-sampling-fallback.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Strix unsupported sampling-parameter fallback

## Observed failure

An Azure `gpt-5.6-sol` Strix run failed before vulnerability analysis because
LiteLLM sent `temperature=0.2`. Azure accepts only the model default of `1`,
and LiteLLM had no fallback group for the selected model. Microsoft documents
`temperature` as unsupported for GPT-5 reasoning models (Microsoft, 2026),
while the pinned Strix configuration surface exposes no generation-parameter
control (usestrix, n.d.).

## Root cause and repair

The preferred request-boundary repair is to omit a sampling parameter that a
caller did not explicitly provide. `contextual-orchestrator` owns that provider
boundary for organization software. The pinned Strix integration cannot yet
express the omission through its documented configuration, so the trusted
quick gate recognizes only one physical error line containing all of these
signals:

- a LiteLLM `BadRequestError`;
- Azure or OpenAI exception context;
- the unsupported `temperature` value and supported default; and
- the missing LiteLLM fallback model group.

That exact capability failure is infrastructure evidence and may move directly
to an already-configured distinct outer fallback. It is not eligible for a
same-model retry. The shared model normalizer also translates the workflow's
human-readable `openai-direct/` selector into LiteLLM's `openai_direct/`
provider prefix before dispatch. A cross-provider direct OpenAI fallback reads
the established OpenAI secret from a trusted runtime file and clears the
primary provider's API base; otherwise a NVIDIA or OpenRouter run would send
the fallback to the wrong endpoint with the wrong credential. If the fallback
credential is unavailable, the attempted fallback fails configuration closed.
If no distinct fallback exists or every fallback fails, the required Strix
check remains non-passing. Existing changed, unmapped, manifest,
`ModelBehaviorError`, and vulnerability-report boundaries remain fail closed.

Cross-line signal assembly is deliberately rejected so unrelated target output
cannot manufacture a provider capability error from separate log lines.

## Verification

- The reproduced single-line Azure failure reaches the configured GitHub
Models fallback exactly once and succeeds only when that scan completes.
- The configured `openai-direct/gpt-5.6-luna` fallback normalizes to the
LiteLLM-compatible `openai_direct/gpt-5.6-luna` selector.
- A NVIDIA-primary run dispatches that fallback with the OpenAI credential and
no inherited NVIDIA API base.
- A split-line imitation is non-recoverable and never dispatches the fallback.
- The full Python suite, native workflow validation, Bash syntax checks, and
complete Strix shell regression suite run on the final tree.

## References

AkikoOrenji. (2026, June 4). *[Feature] Expose LLM generation parameters to
control local/OpenAI-compatible model behaviour and prevent runaway tool-call
loops* (Issue No. 514) [GitHub issue]. GitHub.
https://github.com/usestrix/strix/issues/514

Microsoft. (2026, August 20). *Azure OpenAI reasoning models—GPT-5 series,
o3-mini, o1, o1-mini*. Microsoft Learn.
https://learn.microsoft.com/en-us/azure/foundry/openai/how-to/reasoning

usestrix. (n.d.). *Configuration* [Computer software documentation]. GitHub.
Retrieved August 23, 2026, from
https://github.com/usestrix/strix/blob/main/docs/advanced/configuration.mdx
4 changes: 4 additions & 0 deletions scripts/ci/strix_model_utils.sh
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,10 @@ normalize_model() {
printf '%s\n' "$model"
return 0
;;
openai-direct/?*)
printf 'openai_direct/%s\n' "${model#openai-direct/}"
return 0
;;
Comment thread
seonghobae marked this conversation as resolved.
*/*)
printf '%s\n' "$model"
return 0
Expand Down
83 changes: 78 additions & 5 deletions scripts/ci/strix_quick_gate.sh
Comment thread
seonghobae marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,16 @@ known_internal_warning = re.compile(
r"|ended a turn without a lifecycle tool call \(interactive=False\)"
r"); forcing tool continuation \(\d+/\d+\): "
)
known_clean_advisory = re.compile(
r"^(?:[ \t│]*MODEL QUALITY WARNING[ \t│]*"
r"|Warning: You are sending unauthenticated requests to the HF Hub\. "
r"Please set a HF_TOKEN to enable higher rate limits and faster downloads\.)$"
)
known_optional_web_search_advisory = re.compile(
r"^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+ WARNING "
r"[^ ]+ - strix\.tools\.web_search\.tool: "
r"web_search invoked without PERPLEXITY_API_KEY configured$"
)


def iter_report_logs(root: Path):
Expand All @@ -194,7 +204,13 @@ for log_path in iter_report_logs(root):
lines = log_path.read_text(encoding="utf-8").splitlines(keepends=True)
except UnicodeDecodeError:
continue
filtered = [line for line in lines if not known_internal_warning.match(line)]
filtered = [
line
for line in lines
if not known_internal_warning.match(line)
and not known_clean_advisory.fullmatch(line.rstrip("\r\n"))
and not known_optional_web_search_advisory.fullmatch(line.rstrip("\r\n"))
]
if filtered != lines:
log_path.write_text("".join(filtered), encoding="utf-8")
PY
Expand Down Expand Up @@ -380,6 +396,23 @@ if [ -n "$STRIX_GITHUB_MODELS_KEY_FILE" ]; then
fi
fi

STRIX_OPENAI_FALLBACK_KEY_FILE="${STRIX_OPENAI_FALLBACK_KEY_FILE:-}"
if [ -n "$STRIX_OPENAI_FALLBACK_KEY_FILE" ] && { [ ! -f "$STRIX_OPENAI_FALLBACK_KEY_FILE" ] || [ -L "$STRIX_OPENAI_FALLBACK_KEY_FILE" ]; }; then
echo "ERROR: STRIX_OPENAI_FALLBACK_KEY_FILE must reference a regular file containing the API key." >&2
exit 2
fi
if [ -n "$STRIX_OPENAI_FALLBACK_KEY_FILE" ] && ! STRIX_OPENAI_FALLBACK_KEY_FILE="$(resolve_trusted_input_file "STRIX_OPENAI_FALLBACK_KEY_FILE" "$STRIX_OPENAI_FALLBACK_KEY_FILE")"; then
exit 2
fi
STRIX_OPENAI_FALLBACK_KEY=""
if [ -n "$STRIX_OPENAI_FALLBACK_KEY_FILE" ]; then
STRIX_OPENAI_FALLBACK_KEY="$(trim_whitespace "$(cat -- "$STRIX_OPENAI_FALLBACK_KEY_FILE")")"
if [ -z "$STRIX_OPENAI_FALLBACK_KEY" ]; then
echo "ERROR: STRIX_OPENAI_FALLBACK_KEY_FILE must contain a non-empty API key." >&2
exit 2
fi
fi

require_non_negative_integer() {
local value="$1"
local label="$2"
Expand Down Expand Up @@ -2380,6 +2413,12 @@ resolved_llm_api_base_for_model() {
if is_vertex_model "$model"; then
return 0
fi
case "$(normalize_model "$model"):$PRIMARY_MODEL" in
openai_direct/*:openai_direct/*) ;;
openai_direct/*:*)
return 0
;;
esac

local api_base_file="$LLM_API_BASE_FILE"
local api_base_file_name="LLM_API_BASE_FILE"
Expand Down Expand Up @@ -2490,20 +2529,32 @@ run_strix_once() {
if ! llm_api_base_value="$(resolved_llm_api_base_for_model "$model")"; then
return 2
fi
child_model="$(child_model_for_api_base "$model" "$llm_api_base_value")"
local normalized_model
normalized_model="$(normalize_model "$model")"
child_model="$(child_model_for_api_base "$normalized_model" "$llm_api_base_value")"
Comment thread
seonghobae marked this conversation as resolved.
if ! resolved_target_path="$(resolve_current_target_path "$TARGET_PATH")"; then
return 1
fi
local start_epoch
start_epoch="$(date +%s)"
local child_llm_api_key=""
if ! is_vertex_model "$(normalize_model "$model")"; then
if ! is_vertex_model "$normalized_model"; then
child_llm_api_key="$LLM_API_KEY"
if is_github_models_model "$(normalize_model "$model")" && [ -n "$STRIX_GITHUB_MODELS_KEY" ]; then
if is_github_models_model "$normalized_model" && [ -n "$STRIX_GITHUB_MODELS_KEY" ]; then
# Cross-provider fallback: github_models/* models authenticate
# with the GitHub Models token, not the direct-OpenAI key.
child_llm_api_key="$STRIX_GITHUB_MODELS_KEY"
fi
case "$normalized_model:$PRIMARY_MODEL" in
openai_direct/*:openai_direct/*) ;;
openai_direct/*:*)
if [ -z "$STRIX_OPENAI_FALLBACK_KEY" ]; then
echo "ERROR: direct OpenAI fallback requires STRIX_OPENAI_FALLBACK_KEY_FILE." >&2
return 2
fi
child_llm_api_key="$STRIX_OPENAI_FALLBACK_KEY"
;;
esac
Comment thread
seonghobae marked this conversation as resolved.
fi
set -o pipefail
set +e
Expand Down Expand Up @@ -2821,6 +2872,19 @@ is_nvidia_nim_not_found_error() {
return 1
}

is_unsupported_model_parameter_error() {
# Strix currently has no generation-parameter override. Match the exact
# single-line LiteLLM/Azure capability failure so a reasoning model that
# rejects Strix's temperature can move to the already-configured fallback.
if grep -Ei 'litellm(\.exceptions)?\.BadRequestError' "$STRIX_LOG" |
grep -Ei '(AzureException|OpenAIException)' |
grep -Eiq "Unsupported value:[[:space:]]*['\"]temperature['\"].*Only the default[[:space:]]*\\(1\\)[[:space:]]*value is supported.*No fallback model group found"; then
return 0
fi

return 1
}
Comment thread
seonghobae marked this conversation as resolved.

is_model_behavior_error() {
# Classify only a module-qualified Strix/Agents SDK protocol exception.
# A bare source-file mention of ModelBehaviorError is not retryable.
Expand Down Expand Up @@ -3151,7 +3215,8 @@ is_llm_token_limit_error() {
# was interrupted or incomplete. Used as a guard to prevent the
# below-threshold override from silently passing an aborted scan.
has_detected_infrastructure_error() {
if grep -Eiq '(^|[^[:alpha:]])(Fatal|Denied|Warn|Warning)([^[:alpha:]]|$)' "$STRIX_LOG"; then
if grep -Eiq '(^|[^[:alpha:]])(Fatal|Denied|Warn|Warning)([^[:alpha:]]|$)' \
< <(grep -Eiv '^[[:space:]│]*MODEL QUALITY WARNING[[:space:]│]*$|^Warning: You are sending unauthenticated requests to the HF Hub\. Please set a HF_TOKEN to enable higher rate limits and faster downloads\.$' "$STRIX_LOG"); then
Comment thread
seonghobae marked this conversation as resolved.
return 0
fi
Comment thread
seonghobae marked this conversation as resolved.

Expand Down Expand Up @@ -3183,6 +3248,10 @@ has_detected_infrastructure_error() {
return 0
fi

if is_unsupported_model_parameter_error; then
return 0
fi

if is_model_behavior_error; then
return 0
fi
Expand Down Expand Up @@ -4076,6 +4145,10 @@ is_model_retryable_error() {
return 0
fi

if is_unsupported_model_parameter_error; then
return 0
fi

# A provider failure can be recorded only in Strix's structured report log.
# run_strix_once already marks that evidence as infrastructure failure, but
# the child stdout log used by the classifiers may not contain the provider
Expand Down
Loading
Loading