diff --git a/AGENTS.md b/AGENTS.md index cf8df236be..bc560d9aaa 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -9,6 +9,11 @@ commit and exposed without running build hooks; a lone `--require-hashes` directive is not trust evidence. See [`docs/doctoring/opencode-exact-vcs-dependency-evidence.md`](docs/doctoring/opencode-exact-vcs-dependency-evidence.md). Conflict-scope roots fail closed when the immediate parent directory is a symbolic link. +OriginWeave hourly NVIDIA NIM repair is a thin caller at minute 10. See [`docs/doctoring/originweave-hourly-review-caller.md`](docs/doctoring/originweave-hourly-review-caller.md). +nonnest2 hourly NVIDIA NIM repair is a thin caller at minute 16. See [`docs/doctoring/nonnest2-hourly-review-caller.md`](docs/doctoring/nonnest2-hourly-review-caller.md). + +Strix `ModelBehaviorError: Tool … not found in agent strix` is retryable infrastructure, not a vulnerability finding. See [`docs/doctoring/strix-tool-protocol-fallback.md`](docs/doctoring/strix-tool-protocol-fallback.md). + All 18 product hourly review-repair callers (OriginWeave at minute 10, nonnest2 at minute 16, and 16 others) are one file, [`.github/workflows/hourly-review-repair.yml`](.github/workflows/hourly-review-repair.yml), a `github.event.schedule` lookup table rather than 18 near-copy-pasted files. See [`docs/doctoring/hourly-review-repair-single-file-consolidation.md`](docs/doctoring/hourly-review-repair-single-file-consolidation.md); the per-repository doctoring records (e.g. [`docs/doctoring/originweave-hourly-review-caller.md`](docs/doctoring/originweave-hourly-review-caller.md), [`docs/doctoring/nonnest2-hourly-review-caller.md`](docs/doctoring/nonnest2-hourly-review-caller.md)) remain as historical background per repository. Organization edge runtimes use Cloudflare Pingora. Do not add or preserve active Nginx containers, packages, commands, service/config files, or Kubernetes Nginx ingress annotations/classes. Read [`docs/policies/PINGORA_EDGE_POLICY.md`](docs/policies/PINGORA_EDGE_POLICY.md) and ADR-0019 before changing HTTP edge, static-serving, ingress, TLS, or proxy deployment behavior. diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index e12f33542d..da80d58013 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -64,6 +64,14 @@ flowchart TD Labels --> Verify ``` +## Strix tool-protocol fallback + +When a provider emits `agents.exceptions.ModelBehaviorError: Tool +not found in agent strix`, the quick gate treats that line as retryable +infrastructure and continues to a distinct configured model. It is not +scan evidence from the target repository. + +## Hourly NVIDIA NIM repair gate The metadata reconciler is convergent and mode-aware. Already-correct descriptions/topics and legacy default-branch `/docs` Pages sites receive no write; absent or drifted legacy Pages state is created/updated, and disabled @@ -262,6 +270,8 @@ resolver conflict. — import-only exact source dependencies for networkless coverage. - [`docs/doctoring/fast-mlsirm-hourly-review-caller.md`](docs/doctoring/fast-mlsirm-hourly-review-caller.md) — product-specific psychometric repair heartbeat and scientific gates. + + - [`docs/doctoring/exact-artifact-sbom-attestation.md`](docs/doctoring/exact-artifact-sbom-attestation.md) — current increment's attestation decision and APA 7th citations. - [`docs/doctoring/sandboxed-web-readiness-loopback-boundary.md`](docs/doctoring/sandboxed-web-readiness-loopback-boundary.md) diff --git a/CHANGELOG.md b/CHANGELOG.md index 30eafe8250..395b1be813 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1265,6 +1265,7 @@ Semantic Versioning where the repository publishes a release. - Download the pinned `uv` 0.12.1 exporter from the official GitHub Releases URL instead of `releases.astral.sh`, which now returns HTTP 403 and blocks org-wide OpenCode `coverage-evidence`. The SHA-256 pin is unchanged. The opener may follow one hop onto `release-assets.githubusercontent.com` or `objects.githubusercontent.com` and still rejects every other host, userinfo, non-HTTPS scheme, and nondefault port (ContextualWisdomLab/.github#1109). - Compared the trusted `uv` executable's post-install `--version` output against the real GitHub Releases build's full string, `uv 0.12.1 (x86_64-unknown-linux-gnu)`, instead of the bare `uv 0.12.1` the prior check required; the genuine release binary always prints the target triple, so every installation was failing the pin check immediately after the archive download itself was fixed (ContextualWisdomLab/.github#1109). - Excluded relative `-r` and `--requirement` referrers from generated flat base-lock publication while retaining bounded include syntax diagnostics and discovering independently complete direct `.txt` children of `requirements` directories. +- Treat Strix `ModelBehaviorError: Tool … not found in agent strix` as retryable infrastructure so a configured fallback model can finish the required security scan instead of failing the repository as insecure. - Bound the central Semgrep job to one `SEMGREP_IMAGE` digest for log evidence, manifest inspection, and `docker run`, so a buyer reconstructing the scan can prove the logged scanner is the scanner that ran. - Published substantive OpenCode LLM probes when they already carried an independent proof and exact source-line digest but omitted a duplicated `path:line` citation, so NVIDIA NIM / OpenCode review evidence is no longer discarded as `NO_CONCLUSION`. - Refused a conflict-scope repository root whose immediate parent is a symbolic link, so a swapped parent cannot redirect the canonical worktree after the last-component check (CWE-367). diff --git a/CLAUDE.md b/CLAUDE.md index 216561be83..3a7a5c8c96 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -132,6 +132,8 @@ repeatable compile command. - **Product hourly callers** stay thin. Do not hard-code OriginWeave, aFIPC, naruon, or Keyverse into `pr-review-fix-scheduler.yml`. The model credential remains `NVIDIA_NIM_API_KEY` on the worker, never `COPILOT_GITHUB_TOKEN`. +- **Strix tool-protocol errors** (`ModelBehaviorError: Tool … not found in agent strix`) are + retryable infrastructure. They must not be published as repository vulnerabilities. - **Central review routes through the vendored contextual-orchestrator gateway.** `pr-review-autofix.yml` provisions `scripts/ci/contextual_orchestrator_review_sidecar.sh` (the five provider secrets flow into its KV; the writer runs diff --git a/docs/doctoring/strix-tool-protocol-fallback.md b/docs/doctoring/strix-tool-protocol-fallback.md new file mode 100644 index 0000000000..594be186ac --- /dev/null +++ b/docs/doctoring/strix-tool-protocol-fallback.md @@ -0,0 +1,27 @@ +# Strix tool-protocol fallback + +## Incident and buyer impact + +Strix can exit before producing security evidence when the selected model +emits a tool call the `strix` agent does not expose: + +`agents.exceptions.ModelBehaviorError: Tool execute not found in agent strix` + +The required check then failed as if the target repository were insecure, +and configured fallback models never ran. + +## Decision + +Classify only that exact exception class, missing-tool phrase, and agent +name `strix` as retryable infrastructure. Fallback to a distinct configured +model. Vulnerability artifacts and fallback exhaustion remain fail-closed. +Generic application errors are not matched. + +## References + +National Institute of Standards and Technology. (2020). *Security and +privacy controls for information systems and organizations* (NIST Special +Publication 800-53 Rev. 5). https://doi.org/10.6028/NIST.SP.800-53r5 + +OpenAI. (2025). *OpenAI Agents SDK*. +https://openai.github.io/openai-agents-python/ diff --git a/scripts/ci/strix_quick_gate.sh b/scripts/ci/strix_quick_gate.sh index 3a563d7020..b33b9a96f4 100755 --- a/scripts/ci/strix_quick_gate.sh +++ b/scripts/ci/strix_quick_gate.sh @@ -3357,6 +3357,15 @@ is_llm_token_limit_error() { return 1 } +# Strix's agent SDK can reject a provider response before it produces scan +# evidence when the model emits a tool call that the selected agent does not +# expose. Treat this exact SDK/provider failure as retryable so a configured +# fallback model can complete the security scan; it is not evidence from the +# target repository and must never be treated as a vulnerability. +is_model_tool_protocol_error() { + grep -Eiq 'agents\.exceptions\.ModelBehaviorError:[[:space:]]*Tool [[:alnum:]_]+ not found in agent strix' "$STRIX_LOG" +} + # Detect whether the strix log contains evidence of infrastructure-level # errors (timeout, rate-limit, transport failures) that indicate the scan # was interrupted or incomplete. Used as a guard to prevent the @@ -3378,6 +3387,10 @@ has_detected_infrastructure_error() { return 0 fi + if is_model_tool_protocol_error; then + return 0 + fi + if is_midstream_fallback_error; then return 0 fi @@ -4268,6 +4281,12 @@ is_model_retryable_error() { return 0 fi + if is_model_tool_protocol_error; then + # A provider/model tool-contract failure is recoverable with a distinct + # configured model, but it is not a clean scan result. + return 0 + fi + if is_timeout_error; then # Process and provider timeouts are not clean evidence, but they are # recoverable across distinct fallback models. Strict provider-signal diff --git a/scripts/ci/test_strix_quick_gate.sh b/scripts/ci/test_strix_quick_gate.sh index dba374617c..e334013141 100755 --- a/scripts/ci/test_strix_quick_gate.sh +++ b/scripts/ci/test_strix_quick_gate.sh @@ -775,6 +775,8 @@ assert_opencode_review_uses_codegraph_and_contextual_orchestrator() { assert_file_contains "$REPO_ROOT/scripts/ci/run_opencode_review_model_pool.sh" "skipping remaining attempts for this model" "opencode review skips same-model retries after context-window overflow" assert_file_contains "$REPO_ROOT/.github/workflows/strix.yml" "exceeded your current quota" "strix wrapper neutralizes quota-only provider failures without vulnerability reports" assert_file_contains "$REPO_ROOT/scripts/ci/strix_quick_gate.sh" "billing details" "strix quick gate classifies provider quota starvation as infrastructure" + assert_file_contains "$REPO_ROOT/scripts/ci/strix_quick_gate.sh" "is_model_tool_protocol_error" "strix quick gate retries agent tool-protocol provider failures" + assert_file_contains "$REPO_ROOT/scripts/ci/strix_quick_gate.sh" "ModelBehaviorError:[[:space:]]*Tool [[:alnum:]_]+ not found in agent strix" "strix quick gate identifies unsupported agent tool responses" assert_file_not_contains "$workflow_file" 'timeout-minutes: 325' "opencode review target must not cap inference" assert_file_contains "$workflow_file" 'timeout-minutes: 12' "opencode evidence preparation fails closed before it ties up the review queue" assert_file_not_contains "$workflow_file" 'timeout-minutes: 205' "opencode model pool step must not cap inference" @@ -3677,6 +3679,23 @@ REPORT ;; esac ;; + tool-protocol-fallback-success) + case "${STRIX_LLM:-}" in + vertex_ai/tool-protocol-primary) + echo "agents.exceptions.ModelBehaviorError: Tool execute not found in agent strix" + echo "agents.exceptions.ModelBehaviorError: Tool agent_finish not found in agent strix" + exit 1 + ;; + vertex_ai/fallback-one) + echo "scan ok after tool-protocol fallback" + exit 0 + ;; + *) + echo "Error: tool-protocol fallback path unexpected (${STRIX_LLM:-})" >&2 + exit 26 + ;; + esac + ;; openai-primary-quota-fallback-success) case "${STRIX_LLM:-}" in openai/quota-primary) @@ -6277,6 +6296,16 @@ run_filtered_gate_case_if_requested() { input-file-root-override-precedence) run_input_file_root_override_takes_precedence_over_runner_temp_case ;; + tool-protocol-fallback-success) + run_gate_case "tool-protocol-fallback-success" \ + "vertex_ai/tool-protocol-primary" \ + "vertex_ai/fallback-one" \ + "0" \ + "REGEX:Strix quick scan succeeded with fallback model 'vertex_ai/fallback-one' in [0-9]+s\\." \ + "2" \ + "vertex_ai/tool-protocol-primary|vertex_ai/fallback-one" \ + "|" + ;; vertex-without-llm-api-key) run_vertex_without_llm_api_key_case ;; @@ -10147,6 +10176,15 @@ run_gate_case_allow_provider_signal "vertex-primary-midstream-fallback-success" "vertex_ai/midstream-primary|vertex_ai/fallback-one" \ "|" +run_gate_case "tool-protocol-fallback-success" \ + "vertex_ai/tool-protocol-primary" \ + "vertex_ai/fallback-one" \ + "0" \ + "REGEX:Strix quick scan succeeded with fallback model 'vertex_ai/fallback-one' in [0-9]+s\\." \ + "2" \ + "vertex_ai/tool-protocol-primary|vertex_ai/fallback-one" \ + "|" + run_gate_case_allow_provider_signal "vertex-primary-midstream-retry-same-model-success" \ "vertex_ai/retry-midstream-primary" \ "vertex_ai/fallback-one vertex_ai/fallback-two" \