From e5e181a3490d0b823c5689a8225a628962de0dca Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 31 Aug 2026 07:25:58 +0000 Subject: [PATCH 1/2] fix(ci): correct strix quick-gate opencode fuzz support-file case pattern copy_required_scope_support_files() matched the dead fuzz/fuzz_opencode_normalize_output.py duplicate (calls a nonexistent extract_json_object) instead of the real, live fuzz target fuzz/fuzz_opencode_review_normalize_output.py, which imports scripts/ci/opencode_review_normalize_output.py. A PR touching only the real fuzz target never got the normalizer module copied into the Strix scan scope. Add regression coverage for this case arm. --- scripts/ci/strix_quick_gate.sh | 2 +- scripts/ci/test_strix_quick_gate.sh | 38 +++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/scripts/ci/strix_quick_gate.sh b/scripts/ci/strix_quick_gate.sh index 4f0d7b1ca..4af1e5150 100755 --- a/scripts/ci/strix_quick_gate.sh +++ b/scripts/ci/strix_quick_gate.sh @@ -1676,7 +1676,7 @@ PY scripts/ci/strix_quick_gate.sh | scripts/ci/test_strix_quick_gate.sh) include_strix_model_utils=1 ;; - fuzz/fuzz_opencode_normalize_output.py | scripts/ci/opencode_review_normalize_output.py | tests/test_opencode_review_normalize_output.py) + fuzz/fuzz_opencode_review_normalize_output.py | scripts/ci/opencode_review_normalize_output.py | tests/test_opencode_review_normalize_output.py) include_opencode_normalizer=1 ;; esac diff --git a/scripts/ci/test_strix_quick_gate.sh b/scripts/ci/test_strix_quick_gate.sh index 4053f4fd5..37594ccb2 100644 --- a/scripts/ci/test_strix_quick_gate.sh +++ b/scripts/ci/test_strix_quick_gate.sh @@ -5347,6 +5347,14 @@ EOS echo "Error: PR changed-file scope missing CI support dependency ($target_path)" >&2 exit 55 ;; + pr-changed-scope-includes-opencode-normalizer) + if [ -f "$target_path/fuzz/fuzz_opencode_review_normalize_output.py" ] && [ -f "$target_path/scripts/ci/opencode_review_normalize_output.py" ]; then + echo "scan ok with opencode normalizer support dependency" + exit 0 + fi + echo "Error: PR changed-file scope missing opencode normalizer support dependency ($target_path)" >&2 + exit 64 + ;; pr-deployment-scope-entrypoint-context) if [ ! -f "$target_path/Dockerfile" ]; then echo "Error: deployment scope missing Dockerfile ($target_path)" >&2 @@ -5544,6 +5552,10 @@ EOS echo 'def real_changed_endpoint(): pass' >"$repo_root_dir/backend/api/emails.py" elif [ "$scenario" = "pr-changed-scope-bounded" ]; then echo 'class Unrelated {}' >"$repo_root_dir/sync-module-system/smart-crawling-common/src/main/java/org/empasy/sync/common/system/util/JwtUtil.java" + elif [ "$scenario" = "pr-changed-scope-includes-opencode-normalizer" ]; then + mkdir -p "$repo_root_dir/fuzz" + echo 'from scripts.ci import opencode_review_normalize_output as normalizer' >"$repo_root_dir/fuzz/fuzz_opencode_review_normalize_output.py" + echo 'def iter_json_objects(text): return []' >"$repo_root_dir/scripts/ci/opencode_review_normalize_output.py" elif [ "$scenario" = "pr-python-scope-context" ]; then mkdir -p "$repo_root_dir/backend/api" "$repo_root_dir/backend/core" "$repo_root_dir/backend/db" "$repo_root_dir/backend/services" touch "$repo_root_dir/backend/api/__init__.py" @@ -11807,6 +11819,32 @@ run_gate_case "pr-changed-scope-includes-ci-dependency" \ "pull_request" \ "scripts/ci/strix_quick_gate.sh" +# The real, live Atheris fuzz target that imports +# scripts/ci/opencode_review_normalize_output.py is +# fuzz/fuzz_opencode_review_normalize_output.py (not the deleted +# fuzz/fuzz_opencode_normalize_output.py duplicate). A PR that changes only +# that fuzz target must still pull the normalizer module into scan scope. +run_gate_case "pr-changed-scope-includes-opencode-normalizer" \ + "openai/gpt-4o-mini" \ + "" \ + "0" \ + "scan ok with opencode normalizer support dependency" \ + "1" \ + "openai/gpt-4o-mini" \ + "https://example.invalid" \ + "vertex_ai" \ + "__DEFAULT__" \ + "" \ + "0" \ + "CRITICAL" \ + "0" \ + "" \ + "" \ + "1200" \ + "0" \ + "pull_request" \ + "fuzz/fuzz_opencode_review_normalize_output.py" + run_gate_case "pr-ci-test-harness-only-skip" \ "openai/gpt-4o-mini" \ "" \ From 0974a0451f4e9cf8985acc705b7e3caaed7179f9 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 31 Aug 2026 22:32:07 +0000 Subject: [PATCH 2/2] fix(ci): bound required-workflow-bootstrap awk extraction to its own job exact-head-path-policy fails on this PR's own head not because of this PR's diff, but because of a pre-existing bug on main in test_strix_quick_gate.sh: the awk range /^ required-workflow-bootstrap:$/,/^[^ ]/ never finds its end pattern (every job key is indented 2 spaces, never column 0), so it captures the rest of the jobs section instead of just that job. A legitimate, unrelated if: added elsewhere in opencode-review.yml by PR #1497 gets swept into the captured block and trips the "must not depend on required-workflow event payload fields" assertion. This check runs on plain pull_request (not pull_request_target) against each PR's own head, so the base-branch fix in #1506 doesn't propagate here automatically; porting the same fix directly is what makes this PR's own check pass. Ports the exact fix from ContextualWisdomLab/.github#1506. --- scripts/ci/test_strix_quick_gate.sh | 31 ++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/scripts/ci/test_strix_quick_gate.sh b/scripts/ci/test_strix_quick_gate.sh index 37594ccb2..3bd9f5377 100644 --- a/scripts/ci/test_strix_quick_gate.sh +++ b/scripts/ci/test_strix_quick_gate.sh @@ -96,6 +96,13 @@ assert_file_not_contains() { fi } +required_workflow_bootstrap_has_if() { + local bootstrap_file="$1" + + awk '/^ required-workflow-bootstrap:$/{p=1; print; next} p && /^ [A-Za-z0-9_-]+:/{exit} p' "$bootstrap_file" | + grep '^[[:space:]]*if:' >/dev/null +} + seal_opencode_test_artifacts() { local runner_temp="$1" local head_sha="$2" @@ -522,9 +529,31 @@ assert_opencode_review_uses_codegraph_and_contextual_orchestrator() { assert_file_not_contains "$workflow_file" "Wait for trusted OpenCode approval review" "opencode pull_request bridge was removed to avoid duplicate required-check resource use" assert_file_not_contains "$workflow_file" "Trusted OpenCode requested changes for head" "opencode pull_request bridge no longer reconsumes stale trusted review state" assert_file_not_contains "$workflow_file" "github.event.pull_request.number == 240" "opencode review workflow must not hard-code repository-specific PR bypasses" - if awk '/^ required-workflow-bootstrap:$/,/^[^ ]/' "$bootstrap_file" | grep -q '^[[:space:]]*if:'; then + # Match against the full awk output rather than letting `grep -q` close its + # end of the pipe on the first match: a large bootstrap job's piped output + # can exceed the OS pipe buffer, and `grep -q`'s early exit can SIGPIPE the + # still-writing awk producer. Under `set -o pipefail` (top of this file) + # that SIGPIPE (128+13=141) outranks grep's own 0 exit, so the `if` + # incorrectly takes the "no match" branch even though the forbidden `if:` + # key was found. Dropping `-q` makes grep read to completion, so it never + # closes the pipe early and the real exit status is preserved. + if required_workflow_bootstrap_has_if "$bootstrap_file"; then record_failure "opencode required workflow bootstrap must not depend on required-workflow event payload fields" fi + local large_bootstrap_fixture + local fixture_line + large_bootstrap_fixture="$(mktemp)" + { + printf '%s\n' 'jobs:' ' required-workflow-bootstrap:' ' if: forbidden' + for ((fixture_line = 0; fixture_line < 20000; fixture_line++)); do + printf '%s\n' ' # padding forces the producer past the pipe buffer' + done + printf '%s\n' ' next-job:' ' runs-on: ubuntu-latest' + } >"$large_bootstrap_fixture" + if ! required_workflow_bootstrap_has_if "$large_bootstrap_fixture"; then + record_failure "opencode required workflow bootstrap condition detection must survive a job block larger than the pipe buffer" + fi + rm -f "$large_bootstrap_fixture" assert_file_contains "$workflow_file" 'github.event.client_payload.target_repository || github.repository' "opencode review scopes concurrency by target repository" assert_file_contains "$workflow_file" "format('pr-{0}', github.event.client_payload.pr_number)" "opencode review scopes repository_dispatch concurrency by current PR" assert_file_not_contains "$workflow_file" "format('pr-{0}-{1}'" "opencode review does not keep stale head-specific concurrency groups"