diff --git a/.github/workflows/opencode-review-dispatch.yml b/.github/workflows/opencode-review-dispatch.yml index d86497b3f4..bbbdf45c5f 100644 --- a/.github/workflows/opencode-review-dispatch.yml +++ b/.github/workflows/opencode-review-dispatch.yml @@ -1916,8 +1916,16 @@ jobs: # coverage command still runs and reports any uncovered GPU lines # exactly as before, so Rust repositories without GPU code are # unaffected and no gate is weakened. - if ls /usr/share/vulkan/icd.d/lvp_icd*.json >/dev/null 2>&1; then - lvp_icd="$(ls /usr/share/vulkan/icd.d/lvp_icd*.json | head -n1)" + local lvp_icd="" + local candidate + local LC_ALL=C + for candidate in /usr/share/vulkan/icd.d/lvp_icd*.json; do + if [ -f "$candidate" ]; then + lvp_icd="$candidate" + break + fi + done + if [ -n "$lvp_icd" ]; then export VK_ICD_FILENAMES="$lvp_icd" export VK_DRIVER_FILES="$lvp_icd" export WGPU_BACKEND=vulkan diff --git a/CHANGELOG.md b/CHANGELOG.md index bf192f6a9e..37a88e543b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +### Deterministic Rust GPGPU software-adapter discovery + +- Exact-head Runtime Quality correction: use the test module's canonical dispatch path constant and advance the independent trusted-workflow blob pin after the workflow change; production behavior is unchanged. + +- The OpenCode Rust coverage worker now selects the first regular Mesa lavapipe ICD through Bash pathname expansion under `LC_ALL=C`. It removes the `ls | head` command-substitution pipeline from the write-capable workflow, so GitHub Actions' Bash `pipefail` behavior cannot turn adapter discovery into pipeline authority and filenames are evaluated as pathname values rather than parsed command output. The GPU-less-runner fallback and fail-closed coverage boundary are unchanged. + ### Failed-check finding names the Strix sandbox instead of the gateway - `opencode-review-dispatch.yml`'s `emit_strix_provider_failure_finding` rendered one fixed finding for every `STRIX_PROVIDER_UNAVAILABLE` line, whose Root cause read "The contextual-orchestrator gateway or its discovered provider pool was unavailable for this run". `#1953` had just given the Strix sandbox bootstrap failure its own second verdict token (`STRIX_SANDBOX_UNAVAILABLE`) precisely because that attribution is wrong for it -- the sandbox container never reaches its Caido proxy, so the run dies before the gateway serves anything -- and this consumer re-applied the wrong attribution one step downstream, into the review findings and the failure census. The emitter now branches on the second token: a sandbox verdict gets a finding that names Strix's sandbox, says the verdict does not name the gateway, and tells the reader not to change gateway or provider configuration on its strength. A `STRIX_PROVIDER_UNAVAILABLE` line without the token keeps its existing text verbatim, so the gateway class has no regression surface. No test covered this finding text at all before (`gateway or its discovered provider pool` matched nothing under `tests/`); `tests/test_opencode_dispatch_strix_sandbox_finding.py` now runs the production emitter from the published run block and pins both directions plus the no-signal case. Refs #1953, #1935. diff --git a/docs/doctoring/opencode-rust-gpu-adapter-discovery.md b/docs/doctoring/opencode-rust-gpu-adapter-discovery.md new file mode 100644 index 0000000000..98ac17ebe5 --- /dev/null +++ b/docs/doctoring/opencode-rust-gpu-adapter-discovery.md @@ -0,0 +1,48 @@ +# Deterministic Rust GPGPU software-adapter discovery + +Decision date: **2026-09-08** + +## Problem + +The OpenCode Rust coverage worker enables Mesa lavapipe on GPU-less hosted +runners. Its adapter selection previously parsed `ls` output through +`head -n1`. GitHub documents that its Bash runner enables `pipefail`, so a +selection pipeline contributes its own process and exit-status behavior to a +coverage prerequisite. Parsing command output is also unnecessary because the +candidate namespace is a trusted local directory and Bash already exposes +matching pathnames as separate values. + +## Decision + +Inside `ensure_rust_gpu_adapter`, set the function-local collation locale to +`C`, iterate `/usr/share/vulkan/icd.d/lvp_icd*.json`, and select the first +regular file. If the pattern has no regular-file match, preserve the current +no-adapter path. Do not change Rust ownership, wgpu coverage expectations, the +software-rendering environment, or the fail-closed coverage result. + +## Verification and failure scenes + +The permanent contract rejects the old `ls | head` pipeline and requires the +locale pin, pathname loop, regular-file check, and first-match assignment. +A runner with one or more lavapipe manifests selects one deterministic regular +file. A runner without a matching regular file reports the existing fallback +receipt and continues to expose uncovered GPU code through the ordinary Rust +coverage gate. + +## Exact-head validation correction + +Runtime Quality run `34180697875`, job `101919047830`, exposed two +test-contract defects on exact head `fd2a497f3484cdd1938fd07beffaa6a7cf40a09a`: +the new regression referenced an undefined `OPENCODE_DISPATCH` name instead of +the file's canonical `_DISPATCH_WORKFLOW_PATH`, and the independent trusted +workflow blob pin still named the predecessor file. The repair uses the existing +path constant and advances the pin to the unchanged production blob +`bbbdf45c5fbb312ead7c99023a86d78a287d10dd`. No workflow behavior changed. + +## References + +Free Software Foundation. (2025). *Bash reference manual: Filename expansion*. +https://www.gnu.org/software/bash/manual/html_node/Filename-Expansion.html + +GitHub. (2026). *Workflow syntax for GitHub Actions*. Retrieved September 8, +2026, from https://docs.github.com/actions/using-workflows/workflow-syntax-for-github-actions diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index 1cc9e20313..a0fcc1d44b 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -3353,3 +3353,11 @@ queries the check-runs API at its own time, order-independently. The implementin their change was safe because they had scoped it narrowly, not because they had checked for the name collision — which is the more useful lesson: **a job name is unique only within one workflow file, and the same name in another file can carry the opposite safety property.** + +### Deterministic Rust GPGPU software-adapter discovery + +- **Status:** Proposed — current-head hosted verification required. +- **Canonical owner:** ContextualWisdomLab/.github OpenCode Rust coverage dispatch. +- **Gap:** Software Vulkan adapter selection used `ls /usr/share/vulkan/icd.d/lvp_icd*.json | head -n1` inside a Bash `pipefail` workflow, coupling adapter discovery to subprocess/output parsing rather than the shell's pathname values. +- **Action:** Iterate the trusted lavapipe glob in `LC_ALL=C`, select the first regular file, and preserve the existing no-adapter fallback. +- **Evidence:** RED `4d976e8899e755f4e9c2caca804278ae304b3611`; permanent workflow contract in `tests/test_opencode_rust_coverage_toolchain_contract.py`. Exact-head Runtime Quality run `34180697875` then exposed an undefined test path name and stale workflow blob pin; both are repaired without changing production behavior. diff --git a/tests/test_opencode_rust_coverage_toolchain_contract.py b/tests/test_opencode_rust_coverage_toolchain_contract.py index cc0c49af6f..114bd06f66 100644 --- a/tests/test_opencode_rust_coverage_toolchain_contract.py +++ b/tests/test_opencode_rust_coverage_toolchain_contract.py @@ -214,3 +214,17 @@ def test_helper_admits_the_reviewed_llvm_19_tools_when_present() -> None: assert result.returncode == 0 assert result.stderr == "" + +def test_software_vulkan_adapter_uses_stable_glob_order() -> None: + """Select the first matching lavapipe adapter without an ls/head pipeline.""" + + dispatch = _DISPATCH_WORKFLOW_PATH.read_text(encoding="utf-8") + adapter = dispatch.split("ensure_rust_gpu_adapter() {", 1)[1].split( + "\n }", 1 + )[0] + + assert "for candidate in /usr/share/vulkan/icd.d/lvp_icd*.json; do" in adapter + assert "local LC_ALL=C" in adapter + assert 'if [ -f "$candidate" ]; then' in adapter + assert 'lvp_icd="$candidate"' in adapter + assert "ls /usr/share/vulkan/icd.d/lvp_icd*.json | head -n1" not in adapter diff --git a/tests/test_pr_review_autofix_nvidia_nim_contract.py b/tests/test_pr_review_autofix_nvidia_nim_contract.py index 2e733ac9e9..4cfbcc4be0 100644 --- a/tests/test_pr_review_autofix_nvidia_nim_contract.py +++ b/tests/test_pr_review_autofix_nvidia_nim_contract.py @@ -17,7 +17,7 @@ DOCTORING_RECORD = Path("docs/doctoring/hourly-nvidia-nim-autofix.md") CHANGELOG = Path("CHANGELOG.md") REVIEW_DISPATCH_WORKFLOW = Path(".github/workflows/opencode-review-dispatch.yml") -REVIEW_DISPATCH_BLOB_SHA = "d86497b3f43bebbabbb4f504eb5132cdf3b7b293" +REVIEW_DISPATCH_BLOB_SHA = "bbbdf45c5fbb312ead7c99023a86d78a287d10dd" def _workflow_text(path: Path) -> str: