Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
73746fc
feat(ci): report free-route provider-family diversity for Strix pool …
claude Aug 30, 2026
57c04ea
fix(ci): surface bounded gateway-preflight rejection evidence in the …
claude Aug 30, 2026
285a2eb
chore(ci): remove orphaned direct-NVIDIA-NIM model resolver
claude Aug 30, 2026
de3772b
docs: append this session's increments to the gap baseline
claude Aug 30, 2026
a2ef0ea
fix(ci): route Strix security review through orchestrator/free
claude Aug 30, 2026
d18c6e8
fix(ci): surface the launcher's own preflight rejection reasons too
claude Aug 30, 2026
2135d57
Merge branch 'claude/noema-strix-orchestrator-q05283' into claude/noe…
claude Aug 30, 2026
49227aa
fix(ci): gate Strix's orchestrator/free access on live diversity evid…
claude Aug 30, 2026
b28018f
fix(sidecar): bound preflight's own single-shot probe with one retry
claude Aug 30, 2026
41ac06c
feat(sidecar): add opt-in minimum-serving-diversity runtime flag plum…
claude Aug 30, 2026
2b71ac7
Merge branch 'main' into claude/noema-opencode-strix-orchestration-se…
claude Aug 30, 2026
be44961
Merge branch 'main' into claude/noema-opencode-strix-orchestration-se…
seonghobae Aug 30, 2026
29baf5e
Merge remote-tracking branch 'origin/main' into claude/noema-opencode…
claude Aug 30, 2026
a1dc62d
Merge protected main and repair Strix diversity gate
seonghobae Aug 31, 2026
ce37896
fix(docs): remove fabricated human/owner review claims from ADR-0003 …
claude Aug 31, 2026
d91c2b7
Merge remote-tracking branch 'origin/claude/noema-opencode-strix-orch…
claude Aug 31, 2026
e1f3c65
fix(ci): adopt current main and credential-account Strix evidence
seonghobae Aug 31, 2026
78b3c39
Merge remote-tracking branch 'origin/main' into HEAD
claude Aug 31, 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
101 changes: 93 additions & 8 deletions .github/workflows/strix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -553,14 +553,14 @@ jobs:
- name: Gate Strix secrets
id: gate
env:
STRIX_MODEL: contextual-orchestrator/orchestrator/free
STRIX_MODEL: contextual-orchestrator/orchestrator/auto
STRIX_MODEL_REQUESTED: ${{ github.event.client_payload.strix_llm || '' }}
run: |
requested_model="$(printf '%s' "$STRIX_MODEL_REQUESTED" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')"
case "$requested_model" in
""|orchestrator/free|contextual-orchestrator/orchestrator/free) ;;
""|orchestrator/auto|contextual-orchestrator/orchestrator/auto) ;;
*)
echo '::error::Strix model overrides are limited to contextual-orchestrator/orchestrator/free.'
echo '::error::Strix model overrides are limited to contextual-orchestrator/orchestrator/auto.'
exit 1
;;
esac
Expand All @@ -578,11 +578,86 @@ jobs:
OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
CONTEXTUAL_ORCHESTRATOR_REQUIRE_ZDR: ${{ steps.target_visibility.outputs.is_private }}
CONTEXTUAL_ORCHESTRATOR_POOL: free
# Boot the sidecar with the richer "auto" catalog (free-first, with a
# genuine priced fallback tier) regardless of which model name Strix
# ends up requesting. This is required, not just conservative: if the
# sidecar booted "free"-only, no priced agents would ever be loaded,
# so a later request for "orchestrator/auto" would silently resolve
# to the exact same single-family free catalog under a different
# name -- a fake fallback that defeats the diversity gate below.
# free_account_diversity (read from this run's own policy report) is
# computed identically either way; see
# docs/adr/0020-strix-orchestrator-free-pool.md.
CONTEXTUAL_ORCHESTRATOR_POOL: auto
# CONTEXTUAL_ORCHESTRATOR_REQUIRE_MINIMUM_SERVING_DIVERSITY is
# deliberately NOT set here yet. The launcher supports it (see
# docs/adr/0020-strix-orchestrator-free-pool.md's "Runtime
# backstop" section), but analysis while building it found that
# today's live "auto" catalog's own PRIMARY (non-fallback) served
# set is drawn from the same free-first candidates as "free" mode
# -- so under the currently-documented single-family-dominated
# discovery snapshot, enabling this unconditionally would make the
# sidecar refuse to boot even into the safe orchestrator/auto
# fallback, which is a worse availability regression than what
# this ADR exists to prevent. Enabling it needs either confirmed
# live diversity >= 2, or a follow-up that scopes the check to the
# free-serving path specifically; tracked as a separate decision.
run: |
set -euo pipefail
bash "$TRUSTED_STRIX_SOURCE/scripts/ci/contextual_orchestrator_review_sidecar.sh"

- name: Resolve Strix model from free-route diversity evidence
id: resolve_model
if: steps.gate.outputs.enabled == 'true'
env:
GATE_STRIX_MODEL: ${{ steps.gate.outputs.strix_model }}
run: |
set -euo pipefail
# docs/adr/0020-strix-orchestrator-free-pool.md: Strix may only select
# the fail-closed orchestrator/free pool when this run's own sidecar
# discovery reports at least two independently credentialed accounts
# among the discovered free routes (CONTEXTUAL_ORCHESTRATOR_EVIDENCE,
# written by scripts/ci/contextual_orchestrator_review_sidecar.sh).
# A single credential account means one account outage would black out
# required Strix security review -- exactly the 2026-08-29 finding
# ADR-0003's original orchestrator/auto pin existed to prevent. ANY
# uncertainty about that evidence (missing file, unreadable JSON, a
# missing or non-integer field) fails closed to the gate's own base
# model (orchestrator/auto) -- this step must never upgrade to
# orchestrator/free on unproven evidence.
diversity_threshold=2
free_account_diversity="$(
python3 - "${CONTEXTUAL_ORCHESTRATOR_EVIDENCE:-}" <<'PY'
import json
import sys

path = sys.argv[1] if len(sys.argv) > 1 else ""
try:
if not path:
raise ValueError("CONTEXTUAL_ORCHESTRATOR_EVIDENCE is unset")
with open(path, encoding="utf-8") as handle:
report = json.load(handle)
diversity = report["free_account_diversity"]
if isinstance(diversity, bool) or not isinstance(diversity, int) or diversity < 0:
raise TypeError("free_account_diversity must be a non-negative integer")
except Exception as exc: # noqa: BLE001 - fail closed on any evidence problem
print(
f"::warning::Could not read a valid free_account_diversity from the "
f"contextual-orchestrator policy report ({exc}); "
"falling back to orchestrator/auto.",
file=sys.stderr,
)
diversity = 0
print(diversity)
PY
)"
resolved_model="$GATE_STRIX_MODEL"
if [ "$free_account_diversity" -ge "$diversity_threshold" ]; then
resolved_model="contextual-orchestrator/orchestrator/free"
fi
echo "free_account_diversity=$free_account_diversity" >> "$GITHUB_OUTPUT"
echo "strix_model=$resolved_model" >> "$GITHUB_OUTPUT"

- name: Set up Python
if: steps.gate.outputs.enabled == 'true'
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
Expand Down Expand Up @@ -711,17 +786,26 @@ jobs:
- name: Prepare Strix model input file
if: steps.gate.outputs.enabled == 'true'
env:
STRIX_MODEL: ${{ steps.gate.outputs.strix_model }}
# The diversity-gated resolution, not the gate's static base model:
# steps.resolve_model upgrades to orchestrator/free only when
# free_account_diversity >= 2 (see the "Resolve Strix model from
# free-route diversity evidence" step above and
# docs/adr/0020-strix-orchestrator-free-pool.md), otherwise it
# passes the gate's own orchestrator/auto straight through.
STRIX_MODEL: ${{ steps.resolve_model.outputs.strix_model }}
run: |
umask 077
strix_llm_file="$RUNNER_TEMP/strix_llm.txt"
strix_model="$(printf '%s' "$STRIX_MODEL" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')"
case "$strix_model" in
orchestrator/auto | contextual-orchestrator/orchestrator/auto)
printf '%s' 'orchestrator/auto' > "$strix_llm_file"
;;
orchestrator/free | contextual-orchestrator/orchestrator/free)
printf '%s' 'orchestrator/free' > "$strix_llm_file"
;;
*)
echo '::error::STRIX_LLM must select contextual-orchestrator/orchestrator/free.'
echo '::error::STRIX_LLM must select contextual-orchestrator/orchestrator/auto or contextual-orchestrator/orchestrator/free.'
exit 1
;;
esac
Expand All @@ -744,8 +828,9 @@ jobs:
LLM_API_KEY_FILE: ${{ env.LLM_API_KEY_FILE }}
STRIX_TARGET_PATH: ${{ (github.event_name == 'pull_request_target' || github.event.client_payload.pr_number != '') && '__PR_SCOPE__' || './' }}
STRIX_SOURCE_DIRS: ". backend frontend"
# The gateway auto pool is provider-diverse. Strix function tools
# must not send a provider-specific reasoning setting to every route.
# The gateway pool can route across multiple provider families
# (bounded by its per-family cap). 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
Expand Down
25 changes: 19 additions & 6 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,25 @@ sidecar (`scripts/ci/contextual_orchestrator_review_sidecar.sh`). The five
provider secrets (`BYTEZ_API_KEY`, `NVIDIA_NIM_API_KEY`,
`NVIDIA_NIM_API_KEY_SUB`, `OPENROUTER_API_KEY`, `OPENAI_API_KEY`) enter its KV
as bootstrap transport in the same process that discovers models and serves;
OpenCode, Noema, and Strix all use the fail-closed zero-cost pool
`orchestrator/free`. Strix uses the zero-cost `orchestrator/free` pool by
explicit 2026-08-30 owner decision, superseding the prior `orchestrator/auto`
(provider-diverse, non-free-admitting) default; private targets still require
ZDR-compliant routes under
OpenCode and Noema use the fail-closed zero-cost pool `orchestrator/free`
unconditionally. **Strix is evidence-gated, not unconditional:** `strix.yml`
reads `free_account_diversity` (the count of independently credentialed
accounts among all discovered free routes, reported by
`scripts/ci/contextual_orchestrator_review_policy.py` on every discovery run)
from the sidecar's policy report and selects `orchestrator/free` only when
that count is `>= 2`; otherwise — including when the evidence is missing,
unreadable, or malformed — it falls back to `orchestrator/auto`, never the
other way around. A negative fixture
(`tests/test_strix_contextual_orchestrator_contract.py`) pins that a
diversity of 0 or 1 cannot weaken the resolved model to `orchestrator/free`.
The `orchestrator/auto` provider-diverse, priced-fallback pool is therefore a
permanent, load-bearing fallback for Strix, not a route being retired; it
remains supported by the gateway policy for any other consumer too, admitting
non-free routes only with complete published prompt/completion price and
currency evidence. Private targets still require ZDR-compliant routes under
[`scripts/ci/zdr_policy.py`](scripts/ci/zdr_policy.py).
See [`docs/adr/0003-contextual-orchestrator-vendored-free-zdr.md`](docs/adr/0003-contextual-orchestrator-vendored-free-zdr.md)
and its 2026-08-30 amendment.
and [`docs/adr/0020-strix-orchestrator-free-pool.md`](docs/adr/0020-strix-orchestrator-free-pool.md)
(the evidence-gated conditional between Strix's two pools, its residual risk,
and the separately tracked request-time-failover dependency).
The materialization contract is also covered by [`docs/doctoring/exact-artifact-sbom-attestation.md`](docs/doctoring/exact-artifact-sbom-attestation.md).
12 changes: 0 additions & 12 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -562,18 +562,6 @@ Semantic Versioning where the repository publishes a release.
entry for the full evidence trail, the exact trade-off reasoned through
(not live-verified, since this session lacks provider credentials), and
the more complete fix if this proves insufficient.
- Switch Strix from `orchestrator/auto` to `orchestrator/free`, matching
OpenCode and Noema: `strix.yml`'s `STRIX_MODEL`/`CONTEXTUAL_ORCHESTRATOR_POOL`
default and both model-override allowlists, and
`scripts/ci/strix_quick_gate.sh`'s `is_contextual_orchestrator_model`, now
accept only `orchestrator/free`. This is an explicit, informed owner
override of `docs/adr/0003-contextual-orchestrator-vendored-free-zdr.md`'s
original `orchestrator/auto` decision (see that ADR's 2026-08-30
amendment and the matching gap-baseline entry for the full trade-off and
evidence trail): Strix no longer has a paid-model fallback and can go
fully dark during the class of single-provider-family-collapse incident
the original decision was written to survive, until the free-catalog's
stale-model and provider-diversity gaps are separately closed.
- Strengthen `scripts/ci/zdr_policy.py`'s `nvidia_nim`/`nvidia_nim_sub` ZDR
attestation with a direct primary-source citation: NVIDIA's own current
*NVIDIA API Trial Terms of Service* (v. September 19, 2025), Section
Expand Down
Loading
Loading