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
21 changes: 21 additions & 0 deletions scripts/ci/strix_quick_gate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2651,6 +2651,20 @@ run_strix_once() {
if ! resolved_target_path="$(resolve_current_target_path "$TARGET_PATH")"; then
return 1
fi
# contextual-orchestrator's gateway deliberately rejects any request that
# combines stream_options.include_usage=true with tools (a correctness
# guarantee against silently-incomplete usage accounting; out of scope to
# change here). Strix's agent loop always streams and always sends tools,
# so every call through that gateway hits the rejection immediately.
# Strix itself ships an opt-in for exactly this: LLM_DISABLE_STREAMING=true
# makes each turn a single non-streaming get_response (stream:false on the
# wire, so stream_options is never sent) replayed as one terminal stream
# event; nothing else about the run loop changes. Scope it narrowly to the
# contextual-orchestrator loopback so other providers keep real streaming.
local strix_disable_streaming="false"
if is_contextual_orchestrator_api_base "$llm_api_base_value"; then
strix_disable_streaming="true"
fi
Comment thread
seonghobae marked this conversation as resolved.
local start_epoch
start_epoch="$(date +%s)"
local child_llm_api_key=""
Expand Down Expand Up @@ -2682,6 +2696,7 @@ run_strix_once() {
STRIX_CHILD_EXECUTABLE_ROOT="$STRIX_EXECUTABLE_ROOT" \
STRIX_CHILD_EXECUTABLE_SHA256="$STRIX_EXECUTABLE_SHA256" \
STRIX_CHILD_REQUIRE_EXECUTABLE_INTEGRITY="${IS_PR_EVIDENCE_RUN:-false}" \
STRIX_CHILD_DISABLE_STREAMING="$strix_disable_streaming" \
python3 - "$timeout_seconds" "$resolved_target_path" "$SCAN_MODE" "$STRIX_LOG" "$STRIX_SCAN_WORKING_DIR" <<'PY'
import hashlib
import hmac
Expand Down Expand Up @@ -2736,6 +2751,12 @@ child_env["LLM_MODEL"] = os.environ["STRIX_CHILD_MODEL"]
if os.environ.get("STRIX_CHILD_LLM_API_KEY"):
child_env["LLM_API_KEY"] = os.environ["STRIX_CHILD_LLM_API_KEY"]
child_env["STRIX_REPORTS_DIR"] = os.environ["STRIX_CHILD_REPORTS_DIR"]
if os.environ.get("STRIX_CHILD_DISABLE_STREAMING", "").strip().lower() == "true":
# See the comment above strix_disable_streaming's assignment in bash:
# this routes only the contextual-orchestrator gateway through Strix's
# own non-streaming fallback so stream_options is never sent alongside
# tools, without touching how Strix talks to any other provider.
child_env["LLM_DISABLE_STREAMING"] = "true"
Comment thread
seonghobae marked this conversation as resolved.
Comment thread
seonghobae marked this conversation as resolved.
for key, value in os.environ.items():
if key.startswith("FAKE_STRIX_") and value:
child_env[key] = value
Expand Down
25 changes: 23 additions & 2 deletions scripts/ci/test_strix_quick_gate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,9 @@ assert_strix_workflow_pr_trigger_hardened() {
assert_file_contains "$GATE_SCRIPT" 'child_env["PNPM_CONFIG_IGNORE_SCRIPTS"] = "true"' "strix gate child process disables pnpm lifecycle scripts"
assert_file_contains "$GATE_SCRIPT" 'child_env["YARN_ENABLE_SCRIPTS"] = "false"' "strix gate child process disables yarn lifecycle scripts"
assert_file_contains "$GATE_SCRIPT" 'child_env["PYTHONWARNINGS"] = "ignore:Pydantic serializer warnings:UserWarning:pydantic.main"' "strix gate child env narrowly filters the known third-party Pydantic serializer warning"
assert_file_contains "$GATE_SCRIPT" 'if is_contextual_orchestrator_api_base "$llm_api_base_value"; then' "strix gate scopes the non-streaming opt-in to the contextual-orchestrator loopback gateway"
assert_file_contains "$GATE_SCRIPT" 'STRIX_CHILD_DISABLE_STREAMING="$strix_disable_streaming"' "strix gate threads the streaming opt-in through to the child process environment"
assert_file_contains "$GATE_SCRIPT" 'child_env["LLM_DISABLE_STREAMING"] = "true"' "strix gate disables Strix's own SDK streaming for the contextual-orchestrator gateway, which rejects stream_options.include_usage alongside tools"
assert_file_contains "$GATE_SCRIPT" '[[ "$normalized_changed_file" =~ ^backend/.+\.py$ ]]' "strix gate detects nested backend Python files for PR-scoped import context"
assert_file_contains "$GATE_SCRIPT" '[[ "$normalized_changed_file" == scripts/ci/test_*.sh || "$normalized_changed_file" == scripts/ci/*_test.sh ]]' "strix gate excludes large CI test harness scripts from model scan input"
assert_file_contains "$GATE_SCRIPT" "Materialized PR-head changed-file scope for Strix scan" "strix gate avoids copying the full PR head tree into privileged scan targets by default"
Expand Down Expand Up @@ -3289,7 +3292,7 @@ set -euo pipefail
printf '%s\n' "${STRIX_LLM:-}" >> "${FAKE_STRIX_CALL_LOG:?}"
printf '%s\n' "${LLM_API_BASE:-<unset>}" >> "${FAKE_STRIX_API_BASE_LOG:?}"
if [ -n "${FAKE_STRIX_RUNTIME_ENV_LOG:-}" ]; then
printf 'LLM_TIMEOUT=%s;STRIX_MEMORY_COMPRESSOR_TIMEOUT=%s;STRIX_REASONING_EFFORT=%s;STRIX_LLM_MAX_RETRIES=%s;GEMINI_LOCATION=%s;PYTHONWARNINGS=%s;NPM_CONFIG_IGNORE_SCRIPTS=%s;PNPM_CONFIG_IGNORE_SCRIPTS=%s;YARN_ENABLE_SCRIPTS=%s;UNRELATED_SECRET=%s\n' \
printf 'LLM_TIMEOUT=%s;STRIX_MEMORY_COMPRESSOR_TIMEOUT=%s;STRIX_REASONING_EFFORT=%s;STRIX_LLM_MAX_RETRIES=%s;GEMINI_LOCATION=%s;PYTHONWARNINGS=%s;NPM_CONFIG_IGNORE_SCRIPTS=%s;PNPM_CONFIG_IGNORE_SCRIPTS=%s;YARN_ENABLE_SCRIPTS=%s;UNRELATED_SECRET=%s;LLM_DISABLE_STREAMING=%s\n' \
"${LLM_TIMEOUT:-<unset>}" \
"${STRIX_MEMORY_COMPRESSOR_TIMEOUT:-<unset>}" \
"${STRIX_REASONING_EFFORT:-<unset>}" \
Expand All @@ -3299,7 +3302,8 @@ if [ -n "${FAKE_STRIX_RUNTIME_ENV_LOG:-}" ]; then
"${NPM_CONFIG_IGNORE_SCRIPTS:-<unset>}" \
"${PNPM_CONFIG_IGNORE_SCRIPTS:-<unset>}" \
"${YARN_ENABLE_SCRIPTS:-<unset>}" \
"${UNRELATED_SECRET:-<unset>}" >> "${FAKE_STRIX_RUNTIME_ENV_LOG:?}"
"${UNRELATED_SECRET:-<unset>}" \
"${LLM_DISABLE_STREAMING:-<unset>}" >> "${FAKE_STRIX_RUNTIME_ENV_LOG:?}"
fi

target_path=""
Expand Down Expand Up @@ -5929,13 +5933,30 @@ PY
"$runtime_env_log" \
"LLM_TIMEOUT=90;STRIX_MEMORY_COMPRESSOR_TIMEOUT=10;STRIX_REASONING_EFFORT=minimal;STRIX_LLM_MAX_RETRIES=1;GEMINI_LOCATION=GLOBAL;PYTHONWARNINGS=ignore:Pydantic serializer warnings:UserWarning:pydantic.main;NPM_CONFIG_IGNORE_SCRIPTS=true;PNPM_CONFIG_IGNORE_SCRIPTS=true;YARN_ENABLE_SCRIPTS=false;UNRELATED_SECRET=<unset>" \
"scenario=$scenario runtime env forwarding"
# Non-contextual-orchestrator providers (gemini here) never see the
# stream-disabling opt-in: it is scoped narrowly to the gateway that
# rejects stream_options.include_usage alongside tools.
assert_file_contains \
"$runtime_env_log" \
"LLM_DISABLE_STREAMING=<unset>" \
"scenario=$scenario non-gateway providers keep real streaming"
fi
if [ "$scenario" = "custom-openai-compatible-preserves-effort" ]; then
assert_file_contains \
"$runtime_env_log" \
"STRIX_REASONING_EFFORT=minimal" \
"scenario=$scenario custom compatible endpoint effort"
fi
if [ "$scenario" = "contextual-orchestrator-gateway-model-qualification" ]; then
# contextual-orchestrator rejects stream_options.include_usage=true
# alongside tools; Strix's agent loop always sends both, so the gate
# routes this gateway through Strix's own LLM_DISABLE_STREAMING opt-in
# (single non-streaming get_response per turn) instead of streaming.
assert_file_contains \
"$runtime_env_log" \
"LLM_DISABLE_STREAMING=true" \
"scenario=$scenario contextual-orchestrator gateway disables SDK streaming to avoid the stream_options+tools rejection"
fi

if [ "$scenario" = "report-known-internal-warning-sanitized" ]; then
assert_file_not_contains \
Expand Down
Loading