From 23e27d952a7e0884ab01ca4dfaae1590b5e52958 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 30 Jun 2026 18:57:32 +0900 Subject: [PATCH 1/7] Fix Strix dependency lock constraints --- requirements-strix-ci-hashes.txt | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/requirements-strix-ci-hashes.txt b/requirements-strix-ci-hashes.txt index 57e0d52ad..70641b041 100644 --- a/requirements-strix-ci-hashes.txt +++ b/requirements-strix-ci-hashes.txt @@ -772,9 +772,9 @@ google-crc32c==1.8.0 \ # via # google-cloud-storage # google-resumable-media -google-genai==2.10.0 \ - --hash=sha256:77912cd558cd7dfd5b75c25fd1c609e78d7954dde583331104022a46ea90f9ee \ - --hash=sha256:d5350311567ae660c24cbc1752aee4b3d660f89c0106d2dcd2a69978c35afe1e +google-genai==1.75.0 \ + --hash=sha256:56bac3991b311c93f980c0a2abcd287b672146905df1fbd71c92ed633d5a07cf \ + --hash=sha256:8dc4c096e7d6288c3087f6893f582fe52468932464781edb8193bd92b9fefb2c # via google-cloud-aiplatform google-resumable-media==2.10.0 \ --hash=sha256:88152884bee37b2bf36a0ab81ad8c7fd12212c9803dd981d77c1b35b02d34e7c \ @@ -1334,9 +1334,9 @@ openai==2.43.0 \ # via # litellm # openai-agents -openai-agents==0.17.7 \ - --hash=sha256:51b5ae43756eea37032e430f95979ba3999af6b1ade397df6c0ffeaf1939646a \ - --hash=sha256:ca76e7f882c9d8f06e3dfb8064cc33bcb5a5f34a29816cb9af863f395964ff0c +openai-agents==0.14.6 \ + --hash=sha256:e9d16b835f73be4c5e3798694f90d7a62efcade931e59416bc7462c850e15705 \ + --hash=sha256:fdd3fb459892c8af5d0b522908b544e96f6217c7254ba55e966424493b43c1ed # via strix-agent packaging==26.2 \ --hash=sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e \ @@ -1481,15 +1481,17 @@ proto-plus==1.28.0 \ # google-api-core # google-cloud-aiplatform # google-cloud-resource-manager -protobuf==7.35.1 \ - --hash=sha256:11d6b0ec246892d85215b0a13ca6e0233cf5284b68f0ac02646427f4ff88a799 \ - --hash=sha256:230a75ddfc2de4806e56696ce9640c1cdfdb6543b7cfce98d42a4c0a0e7bdb87 \ - --hash=sha256:24f857477359a85c0c235261b8ba905fd51b2562f4a64ca1df5473f29850cbf6 \ - --hash=sha256:353652e4efd0bca5b5fc2656abf8307ef351f0cf938c9eba09f0e09c20a25c30 \ - --hash=sha256:4bc97768d8fe4ad6743c8a19403e314511ed9f6d13205b687e52421c023ac1b9 \ - --hash=sha256:74758715c53d7158fb76caf4f0cfdacc5329a4b1bb994f865d6cf302d413a1c4 \ - --hash=sha256:b73f9489a4b8b1c9cb1f8ed951c736392592edb24b9d6819f36d2e10b171d5b4 \ - --hash=sha256:ce115a26fe0c39a2c29973d914d327e516a6455464489fe3cd1e51a1b354f81a +protobuf==6.33.6 \ + --hash=sha256:0cd27b587afca21b7cfa59a74dcbd48a50f0a6400cfb59391340ad729d91d326 \ + --hash=sha256:77179e006c476e69bf8e8ce866640091ec42e1beb80b213c3900006ecfba6901 \ + --hash=sha256:7d29d9b65f8afef196f8334e80d6bc1d5d4adedb449971fefd3723824e6e77d3 \ + --hash=sha256:9720e6961b251bde64edfdab7d500725a2af5280f3f4c87e57c0208376aa8c3a \ + --hash=sha256:a6768d25248312c297558af96a9f9c929e8c4cee0659cb07e780731095f38135 \ + --hash=sha256:bd56799fb262994b2c2faa1799693c95cc2e22c62f56fb43af311cae45d26f0e \ + --hash=sha256:c96c37eec15086b79762ed265d59ab204dabc53056e3443e702d2681f4b39ce3 \ + --hash=sha256:e2afbae9b8e1825e3529f88d514754e094278bb95eadc0e199751cdd9a2e82a2 \ + --hash=sha256:e9db7e292e0ab79dd108d7f1a94fe31601ce1ee3f7b79e0692043423020b0593 \ + --hash=sha256:f443a394af5ed23672bc6c486be138628fbe5c651ccbc536873d7da23d1868cf # via # google-api-core # google-cloud-aiplatform From a4b52c45725b146197b98453aa928f0a5bf6cc62 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 30 Jun 2026 19:07:10 +0900 Subject: [PATCH 2/7] Allow Strix manual status fallback --- .github/workflows/strix.yml | 61 ++++++++++++++++++++++++++----------- 1 file changed, 43 insertions(+), 18 deletions(-) diff --git a/.github/workflows/strix.yml b/.github/workflows/strix.yml index 7356312d4..edb741a72 100644 --- a/.github/workflows/strix.yml +++ b/.github/workflows/strix.yml @@ -49,6 +49,7 @@ permissions: contents: read id-token: write models: read + statuses: write jobs: strix: @@ -584,7 +585,8 @@ jobs: - name: Publish same-head manual Strix status if: ${{ always() && !cancelled() && github.event_name == 'workflow_dispatch' && github.event.inputs.pr_head_sha != '' }} env: - GH_TOKEN: ${{ steps.target_app_token.outputs.token || secrets.OPENCODE_APPROVE_TOKEN || github.token }} + PRIMARY_STATUS_TOKEN: ${{ steps.target_app_token.outputs.token || secrets.OPENCODE_APPROVE_TOKEN || '' }} + FALLBACK_STATUS_TOKEN: ${{ github.token }} TARGET_REPOSITORY: ${{ github.event.inputs.target_repository || github.repository }} PR_HEAD_SHA: ${{ github.event.inputs.pr_head_sha }} STRIX_RESULT: ${{ job.status }} @@ -610,14 +612,25 @@ jobs: ;; esac - gh api -X POST "repos/${TARGET_REPOSITORY}/statuses/${PR_HEAD_SHA}" \ - -f state="$state" \ - -f context="strix" \ - -f description="$description" \ - -f target_url="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" || { - echo "::warning::Could not publish manual Strix status from scan job; keeping scan evidence result authoritative in the workflow run." - exit 0 - } + post_strix_status() { + token="$1" + if [ -z "$token" ]; then + return 1 + fi + GH_TOKEN="$token" gh api -X POST "repos/${TARGET_REPOSITORY}/statuses/${PR_HEAD_SHA}" \ + -f state="$state" \ + -f context="strix" \ + -f description="$description" \ + -f target_url="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" + } + + if post_strix_status "$PRIMARY_STATUS_TOKEN"; then + exit 0 + fi + if [ "$TARGET_REPOSITORY" = "$GITHUB_REPOSITORY" ] && post_strix_status "$FALLBACK_STATUS_TOKEN"; then + exit 0 + fi + echo "::warning::Could not publish manual Strix status from scan job; keeping scan evidence result authoritative in the workflow run." publish-manual-pr-evidence-status: name: publish-manual-pr-evidence-status @@ -696,7 +709,8 @@ jobs: - name: Publish same-head manual Strix status env: - GH_TOKEN: ${{ steps.target_app_token.outputs.token || secrets.OPENCODE_APPROVE_TOKEN || github.token }} + PRIMARY_STATUS_TOKEN: ${{ steps.target_app_token.outputs.token || secrets.OPENCODE_APPROVE_TOKEN || '' }} + FALLBACK_STATUS_TOKEN: ${{ github.token }} TARGET_REPOSITORY: ${{ github.event.inputs.target_repository || github.repository }} PR_HEAD_SHA: ${{ github.event.inputs.pr_head_sha }} STRIX_RESULT: ${{ needs.strix.result }} @@ -722,11 +736,22 @@ jobs: ;; esac - gh api -X POST "repos/${TARGET_REPOSITORY}/statuses/${PR_HEAD_SHA}" \ - -f state="$state" \ - -f context="strix" \ - -f description="$description" \ - -f target_url="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" || { - echo "::warning::Could not publish manual Strix status from follow-up job; scan job publishes the authoritative status when target credentials are available." - exit 0 - } + post_strix_status() { + token="$1" + if [ -z "$token" ]; then + return 1 + fi + GH_TOKEN="$token" gh api -X POST "repos/${TARGET_REPOSITORY}/statuses/${PR_HEAD_SHA}" \ + -f state="$state" \ + -f context="strix" \ + -f description="$description" \ + -f target_url="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" + } + + if post_strix_status "$PRIMARY_STATUS_TOKEN"; then + exit 0 + fi + if [ "$TARGET_REPOSITORY" = "$GITHUB_REPOSITORY" ] && post_strix_status "$FALLBACK_STATUS_TOKEN"; then + exit 0 + fi + echo "::warning::Could not publish manual Strix status from follow-up job; scan job publishes the authoritative status when target credentials are available." From 7b0e7bf1e599194ea034d7c571fd50e256d75382 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 30 Jun 2026 19:46:41 +0900 Subject: [PATCH 3/7] Recognize manual Strix success runs in OpenCode --- .github/workflows/opencode-review.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.github/workflows/opencode-review.yml b/.github/workflows/opencode-review.yml index 0e68d07e2..a715a0636 100644 --- a/.github/workflows/opencode-review.yml +++ b/.github/workflows/opencode-review.yml @@ -4070,9 +4070,22 @@ jobs: local output_file="$2" local manual_strix_success_target local manual_strix_success_run_id + local manual_strix_run_info + local manual_strix_status + local manual_strix_conclusion + local manual_strix_url local failed_strix_run_id manual_strix_success_target="$(current_head_manual_strix_success_status || true)" + if [ -z "$manual_strix_success_target" ]; then + manual_strix_run_info="$(latest_current_head_manual_strix_run || true)" + IFS=$'\t' read -r manual_strix_status manual_strix_conclusion manual_strix_url <<<"$manual_strix_run_info" || true + if [ "$manual_strix_status" = "completed" ] && + [ "$manual_strix_conclusion" = "success" ] && + [ -n "$manual_strix_url" ]; then + manual_strix_success_target="$manual_strix_url" + fi + fi if [ -n "$manual_strix_success_target" ]; then manual_strix_success_run_id="$(printf '%s' "$manual_strix_success_target" | sed -n 's#.*/actions/runs/\([0-9][0-9]*\).*#\1#p')" while IFS= read -r rollup_line; do From 9f05c6c08d1c50308d88ea15e0fb76f33867dae1 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 30 Jun 2026 20:07:08 +0900 Subject: [PATCH 4/7] Fix OpenCode workflow heredoc parsing --- .github/workflows/opencode-review.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/opencode-review.yml b/.github/workflows/opencode-review.yml index 8377ca77a..9285868bc 100644 --- a/.github/workflows/opencode-review.yml +++ b/.github/workflows/opencode-review.yml @@ -4049,9 +4049,7 @@ jobs: fi manual_run_line="$(latest_current_head_manual_strix_run || true)" - IFS="$(printf '\t')" read -r manual_run_status manual_run_conclusion manual_run_url < Date: Tue, 30 Jun 2026 20:23:15 +0900 Subject: [PATCH 5/7] Trigger central required workflow evaluation From 60c5d2f4e1a4d14d6feb12754ffafd148f4975c6 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 30 Jun 2026 20:42:45 +0900 Subject: [PATCH 6/7] Limit OpenCode Docker evidence to changed Dockerfiles --- .github/workflows/opencode-review.yml | 8 +++++++- scripts/ci/test_strix_quick_gate.sh | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/opencode-review.yml b/.github/workflows/opencode-review.yml index 6ca382809..5910c88d4 100644 --- a/.github/workflows/opencode-review.yml +++ b/.github/workflows/opencode-review.yml @@ -650,6 +650,12 @@ jobs: return fi run_and_capture "Docker runtime version" docker version + changed_dockerfiles="$(mktemp)" + while IFS= read -r dockerfile; do + if [ -f "$dockerfile" ]; then + printf '%s\n' "$dockerfile" + fi + done >"$changed_dockerfiles" < <(changed_files_for_coverage | grep -E '(^|/)Dockerfile(\..*)?$' || true) while IFS= read -r dockerfile; do [ -n "$dockerfile" ] || continue context_dir="$(dirname "$dockerfile")" @@ -657,7 +663,7 @@ jobs: image_tag="opencode-review-${PR_HEAD_SHA:-head}-${tag_suffix}" run_and_capture "Docker build (${dockerfile})" \ docker build --pull=false -f "$dockerfile" -t "$image_tag" "$context_dir" - done < <(git ls-files 'Dockerfile' '*/Dockerfile' 'Dockerfile.*' '*/Dockerfile.*') + done <"$changed_dockerfiles" if has_changed_tracked_files 'docker-compose.yml' 'docker-compose.yaml' 'compose.yml' 'compose.yaml'; then for compose_file in docker-compose.yml docker-compose.yaml compose.yml compose.yaml; do if [ -f "$compose_file" ]; then diff --git a/scripts/ci/test_strix_quick_gate.sh b/scripts/ci/test_strix_quick_gate.sh index 88bb39cad..233f1ab09 100755 --- a/scripts/ci/test_strix_quick_gate.sh +++ b/scripts/ci/test_strix_quick_gate.sh @@ -650,7 +650,7 @@ assert_opencode_review_uses_codegraph_and_gpt5_fallback() { assert_file_contains "$workflow_file" "Repository docstring coverage" "opencode coverage evidence accepts repository-owned docstring coverage scripts" assert_file_contains "$workflow_file" "check:python-docstrings" "opencode coverage evidence can use repository Python docstring gates exposed through package scripts" assert_file_contains "$workflow_file" "Coverage execution evidence" "opencode evidence exposes coverage measurement to the review model" - assert_file_contains "$workflow_file" 'context_dir="$(dirname "$dockerfile")"' "opencode Docker evidence builds each Dockerfile from its containing directory" + assert_file_contains "$workflow_file" 'changed_files_for_coverage | grep -E' "opencode Docker evidence limits Docker builds to changed Dockerfiles" assert_file_contains "$workflow_file" 'docker build --pull=false -f "$dockerfile" -t "$image_tag" "$context_dir"' "opencode Docker evidence keeps Dockerfile paths relative to the source checkout" assert_file_contains "$workflow_file" "has_changed_tracked_files 'docker-compose.yml' 'docker-compose.yaml' 'compose.yml' 'compose.yaml'" "opencode Docker evidence runs compose checks only when compose files changed" assert_file_contains "$workflow_file" "Coverage and Docstring coverage labels must cite Coverage execution evidence showing supported repository test suites passed" "opencode approval requires passing test evidence when coverage is applicable" From 0a2fa62810eeacf9c49df19bda15a87a2266fe50 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 30 Jun 2026 20:49:27 +0900 Subject: [PATCH 7/7] Use advisory coverage reports in OpenCode evidence --- .github/workflows/opencode-review.yml | 21 ++++++++++----------- scripts/ci/test_strix_quick_gate.sh | 2 +- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/.github/workflows/opencode-review.yml b/.github/workflows/opencode-review.yml index 5910c88d4..0e226f738 100644 --- a/.github/workflows/opencode-review.yml +++ b/.github/workflows/opencode-review.yml @@ -349,19 +349,19 @@ jobs: run_and_capture "Python configured CI test suite (${project_dir})" \ bash -c 'cd "$1" && PYTHONPATH=. bash -lc "$2"' bash "$project_dir" "$configured_command" done <<<"$configured_commands" - elif [ -f "${project_dir}/pyproject.toml" ]; then - run_and_capture "Python coverage with missing-line report (${project_dir})" \ - bash -c 'cd "$1" && PYTHONPATH=. uv run --with coverage --with pytest coverage run -m pytest tests && uv run --with coverage coverage report --show-missing --fail-under=100' bash "$project_dir" - else - run_and_capture "Python coverage with missing-line report (${project_dir})" \ - bash -c 'cd "$1" && python3 -m pip install --disable-pip-version-check coverage pytest >/dev/null && PYTHONPATH=. python3 -m coverage run -m pytest tests && python3 -m coverage report --show-missing --fail-under=100' bash "$project_dir" - fi + elif [ -f "${project_dir}/pyproject.toml" ]; then + run_and_capture "Python coverage with missing-line report (${project_dir})" \ + bash -c 'cd "$1" && PYTHONPATH=. uv run --with coverage --with pytest coverage run -m pytest tests && uv run --with coverage coverage report --show-missing' bash "$project_dir" + else + run_and_capture "Python coverage with missing-line report (${project_dir})" \ + bash -c 'cd "$1" && python3 -m pip install --disable-pip-version-check coverage pytest >/dev/null && PYTHONPATH=. python3 -m coverage run -m pytest tests && python3 -m coverage report --show-missing' bash "$project_dir" + fi done < <(tracked_python_projects_with_tests) if [ "$measured_projects" -eq 0 ]; then if has_tracked_files '*.py'; then run_and_capture "Python coverage with missing-line report" \ - bash -c 'python3 -m pip install --disable-pip-version-check coverage pytest >/dev/null && PYTHONPATH=. python3 -m coverage run -m pytest && python3 -m coverage report --show-missing --fail-under=100' + bash -c 'python3 -m pip install --disable-pip-version-check coverage pytest >/dev/null && PYTHONPATH=. python3 -m coverage run -m pytest && python3 -m coverage report --show-missing' elif python3 -c 'import pytest_cov' >/dev/null 2>&1; then run_and_capture "Python pytest-cov coverage" python3 -m pytest --cov=. --cov-report=term-missing else @@ -369,7 +369,7 @@ jobs: append "" append "- Result: FAIL" append "- Reason: Python source exists, but no tests directory or pytest collection contract was found." - append "- Fix: add repository tests discoverable by pytest, then rerun coverage with \`python3 -m coverage run -m pytest && python3 -m coverage report --show-missing --fail-under=100\`." + append "- Fix: add repository tests discoverable by pytest, then rerun coverage with \`python3 -m coverage run -m pytest && python3 -m coverage report --show-missing\`." append "" failures=$((failures + 1)) fi @@ -658,11 +658,10 @@ jobs: done >"$changed_dockerfiles" < <(changed_files_for_coverage | grep -E '(^|/)Dockerfile(\..*)?$' || true) while IFS= read -r dockerfile; do [ -n "$dockerfile" ] || continue - context_dir="$(dirname "$dockerfile")" tag_suffix="$(printf '%s' "$dockerfile" | tr '[:upper:]' '[:lower:]' | tr '/.' '--' | tr -cd '[:alnum:]-' | cut -c1-80)" image_tag="opencode-review-${PR_HEAD_SHA:-head}-${tag_suffix}" run_and_capture "Docker build (${dockerfile})" \ - docker build --pull=false -f "$dockerfile" -t "$image_tag" "$context_dir" + docker build --pull=false -f "$dockerfile" -t "$image_tag" . done <"$changed_dockerfiles" if has_changed_tracked_files 'docker-compose.yml' 'docker-compose.yaml' 'compose.yml' 'compose.yaml'; then for compose_file in docker-compose.yml docker-compose.yaml compose.yml compose.yaml; do diff --git a/scripts/ci/test_strix_quick_gate.sh b/scripts/ci/test_strix_quick_gate.sh index 233f1ab09..a38aab002 100755 --- a/scripts/ci/test_strix_quick_gate.sh +++ b/scripts/ci/test_strix_quick_gate.sh @@ -651,7 +651,7 @@ assert_opencode_review_uses_codegraph_and_gpt5_fallback() { assert_file_contains "$workflow_file" "check:python-docstrings" "opencode coverage evidence can use repository Python docstring gates exposed through package scripts" assert_file_contains "$workflow_file" "Coverage execution evidence" "opencode evidence exposes coverage measurement to the review model" assert_file_contains "$workflow_file" 'changed_files_for_coverage | grep -E' "opencode Docker evidence limits Docker builds to changed Dockerfiles" - assert_file_contains "$workflow_file" 'docker build --pull=false -f "$dockerfile" -t "$image_tag" "$context_dir"' "opencode Docker evidence keeps Dockerfile paths relative to the source checkout" + assert_file_contains "$workflow_file" 'docker build --pull=false -f "$dockerfile" -t "$image_tag" .' "opencode Docker evidence builds changed Dockerfiles from the repository root context" assert_file_contains "$workflow_file" "has_changed_tracked_files 'docker-compose.yml' 'docker-compose.yaml' 'compose.yml' 'compose.yaml'" "opencode Docker evidence runs compose checks only when compose files changed" assert_file_contains "$workflow_file" "Coverage and Docstring coverage labels must cite Coverage execution evidence showing supported repository test suites passed" "opencode approval requires passing test evidence when coverage is applicable" assert_file_contains "$workflow_file" "or explicitly cite Coverage execution evidence as not applicable because no supported source files or package manifests were found" "opencode approval permits only evidence-backed no-source coverage N/A"