From fa481e119a505ae416fd11a61eac5dae5fc707ae Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 21 Jun 2026 18:15:22 +0900 Subject: [PATCH 1/3] Require OpenCode inline suggested diffs --- .github/workflows/opencode-review.yml | 115 +++++++++++++++++++++++--- 1 file changed, 102 insertions(+), 13 deletions(-) diff --git a/.github/workflows/opencode-review.yml b/.github/workflows/opencode-review.yml index ca29f11e..e99d8f49 100644 --- a/.github/workflows/opencode-review.yml +++ b/.github/workflows/opencode-review.yml @@ -1283,6 +1283,24 @@ jobs: "- Workflow attempt: ${RUN_ATTEMPT}" >"$body_file" } + create_pull_review_with_payload() { + local event="$1" body="$2" review_payload_file="$3" fallback_body_file="$4" + local gh_error_file + gh_error_file="$(mktemp)" + if ! gh api -X POST "repos/${GH_REPOSITORY}/pulls/${PR_NUMBER}/reviews" --input "$review_payload_file" >/dev/null 2>"$gh_error_file"; then + warn_gh_publication_failure "pull review inline comments" "$gh_error_file" + rm -f "$gh_error_file" + if [ -s "$fallback_body_file" ]; then + create_pull_review "$event" "$(cat "$fallback_body_file")" + else + update_review_overview "$event" "$body" + fi + return 0 + fi + rm -f "$gh_error_file" + update_review_overview "$event" "$body" + } + request_changes_for_gate_failure() { local reason="$1" local body @@ -1338,7 +1356,7 @@ jobs: + "- Root cause: " + (.value.root_cause // "") + "\n" + "- Fix: " + (.value.fix_direction // "") + "\n" + "- Regression test: " + (.value.regression_test_direction // "") + "\n" - + "- Suggested diff:\n```diff\n" + (.value.suggested_diff // "") + "\n```" + + "- Suggested diff: posted in this finding'\''s inline review thread." ) | join("\n\n") ' "$control_json" @@ -1364,6 +1382,65 @@ jobs: } >"$body_file" } + build_request_changes_review_payload() { + local control_json="$1" + local body_file="$2" + local payload_file="$3" + + # shellcheck disable=SC2016 + jq -n --rawfile body "$body_file" --slurpfile control "$control_json" --arg commit_id "$HEAD_SHA" ' + def text($value): ($value // "" | tostring); + { + event: "REQUEST_CHANGES", + body: $body, + commit_id: $commit_id, + comments: [ + (($control[0].findings // [])[] | { + path: text(.path), + line: (.line | tonumber), + side: "RIGHT", + body: ( + "### " + (text(.severity) | ascii_upcase) + " " + text(.title) + "\n\n" + + "- Location: `" + text(.path) + ":" + ((.line // 0) | tostring) + "`\n" + + "- Problem: " + text(.problem) + "\n" + + "- Root cause: " + text(.root_cause) + "\n" + + "- Fix: " + text(.fix_direction) + "\n" + + "- Regression test: " + text(.regression_test_direction) + "\n\n" + + "#### Suggested diff\n```diff\n" + text(.suggested_diff) + "\n```" + ) + }) + ] + } + ' >"$payload_file" + } + + build_inline_comment_failure_body() { + local body_file="$1" + local output_file="$2" + + { + cat "$body_file" + printf '\n## Inline comment publishing failed\n\n' + printf 'GitHub did not accept the inline review comments for the cited finding lines, so OpenCode did not copy suggested diffs into this PR-level body. Re-run the review after the findings are anchored to changed diff lines, or inspect the workflow log/control JSON and apply the changes manually.\n' + } >"$output_file" + } + + publish_request_changes_from_control() { + local control_json="$1" + local body_file + local payload_file + local fallback_body_file + + body_file="$(mktemp)" + payload_file="$(mktemp)" + fallback_body_file="$(mktemp)" + format_request_changes_body "$control_json" "$body_file" + build_request_changes_review_payload "$control_json" "$body_file" "$payload_file" + build_inline_comment_failure_body "$body_file" "$fallback_body_file" + create_pull_review_with_payload "REQUEST_CHANGES" "$(cat "$body_file")" "$payload_file" "$fallback_body_file" + rm -f "$body_file" "$payload_file" "$fallback_body_file" + } + emit_line_specific_fallback_findings() { local evidence_file="$1" local finding_index=0 @@ -1647,6 +1724,8 @@ jobs: local failed_checks_file="$1" local evidence_file="$2" local body_file="$3" + local review_payload_file="${4:-}" + local fallback_body_file="${5:-}" local prompt_file local opencode_json_file local opencode_export_file @@ -1719,6 +1798,12 @@ jobs: return 1 fi format_request_changes_body "$control_json" "$body_file" + if [ -n "$review_payload_file" ]; then + build_request_changes_review_payload "$control_json" "$body_file" "$review_payload_file" + fi + if [ -n "$fallback_body_file" ]; then + build_inline_comment_failure_body "$body_file" "$fallback_body_file" + fi } collect_current_head_strix_workflow_runs() { @@ -2101,7 +2186,7 @@ jobs: pending_checks_file="" # shellcheck disable=SC2329 cleanup_failed_outcome_files() { - rm -f "$failed_checks_file" "$failed_check_evidence_file" "$failed_check_review_body_file" "$pending_checks_file" + rm -f "$failed_checks_file" "$failed_check_evidence_file" "$failed_check_review_body_file" "$failed_check_review_payload_file" "$failed_check_inline_failure_body_file" "$pending_checks_file" } trap cleanup_failed_outcome_files EXIT if collect_github_checks_with_retry collect_failed_github_checks "$failed_checks_file"; then @@ -2112,8 +2197,8 @@ jobs: if stop_for_external_failed_check_if_needed "$failed_checks_file" "$failed_check_evidence_file" "$failed_check_review_body_file"; then : fi - if run_failed_check_diagnosis "$failed_checks_file" "$failed_check_evidence_file" "$failed_check_review_body_file"; then - create_pull_review "REQUEST_CHANGES" "$(cat "$failed_check_review_body_file")" + if run_failed_check_diagnosis "$failed_checks_file" "$failed_check_evidence_file" "$failed_check_review_body_file" "$failed_check_review_payload_file" "$failed_check_inline_failure_body_file"; then + create_pull_review_with_payload "REQUEST_CHANGES" "$(cat "$failed_check_review_body_file")" "$failed_check_review_payload_file" "$failed_check_inline_failure_body_file" else build_failed_check_fallback_body "$failed_checks_file" "$failed_check_evidence_file" "$failed_check_review_body_file" create_pull_review "REQUEST_CHANGES" "$(cat "$failed_check_review_body_file")" @@ -2190,10 +2275,12 @@ jobs: failed_checks_file="" failed_check_evidence_file="" failed_check_review_body_file="" + failed_check_review_payload_file="" + failed_check_inline_failure_body_file="" pending_checks_file="" # shellcheck disable=SC2329 cleanup_approval_files() { - rm -f "$tmp_body" "$control_json" "$failed_checks_file" "$failed_check_evidence_file" "$failed_check_review_body_file" "$pending_checks_file" + rm -f "$tmp_body" "$control_json" "$failed_checks_file" "$failed_check_evidence_file" "$failed_check_review_body_file" "$failed_check_review_payload_file" "$failed_check_inline_failure_body_file" "$failed_check_review_payload_file" "$failed_check_inline_failure_body_file" "$pending_checks_file" } trap cleanup_approval_files EXIT printf '%s\n' "$comment_body" >"$tmp_body" @@ -2239,14 +2326,16 @@ jobs: if [ -s "$failed_checks_file" ]; then failed_check_evidence_file="$(mktemp)" failed_check_review_body_file="$(mktemp)" + failed_check_review_payload_file="$(mktemp)" + failed_check_inline_failure_body_file="$(mktemp)" if ! scripts/ci/collect_failed_check_evidence.sh "$failed_check_evidence_file"; then printf "Failed GitHub Check evidence could not be collected for current head \`%s\`.\n" "$HEAD_SHA" >"$failed_check_evidence_file" fi if stop_for_external_failed_check_if_needed "$failed_checks_file" "$failed_check_evidence_file" "$failed_check_review_body_file"; then : fi - if run_failed_check_diagnosis "$failed_checks_file" "$failed_check_evidence_file" "$failed_check_review_body_file"; then - create_pull_review "REQUEST_CHANGES" "$(cat "$failed_check_review_body_file")" + if run_failed_check_diagnosis "$failed_checks_file" "$failed_check_evidence_file" "$failed_check_review_body_file" "$failed_check_review_payload_file" "$failed_check_inline_failure_body_file"; then + create_pull_review_with_payload "REQUEST_CHANGES" "$(cat "$failed_check_review_body_file")" "$failed_check_review_payload_file" "$failed_check_inline_failure_body_file" else build_failed_check_fallback_body "$failed_checks_file" "$failed_check_evidence_file" "$failed_check_review_body_file" create_pull_review "REQUEST_CHANGES" "$(cat "$failed_check_review_body_file")" @@ -2296,6 +2385,8 @@ jobs: ;; REQUEST_CHANGES) failed_check_review_body_file="$(mktemp)" + failed_check_review_payload_file="$(mktemp)" + failed_check_inline_failure_body_file="$(mktemp)" failed_checks_file="$(mktemp)" if ! collect_github_checks_with_retry collect_failed_github_checks "$failed_checks_file"; then body="$(printf '%s\n' \ @@ -2315,19 +2406,17 @@ jobs: printf "Failed GitHub Check evidence could not be collected for current head \`%s\`.\n" "$HEAD_SHA" >"$failed_check_evidence_file" fi if scripts/ci/validate_opencode_failed_check_review.sh "$control_json" "$failed_checks_file" "$failed_check_evidence_file"; then - format_request_changes_body "$control_json" "$failed_check_review_body_file" - create_pull_review "REQUEST_CHANGES" "$(cat "$failed_check_review_body_file")" + publish_request_changes_from_control "$control_json" elif stop_for_external_failed_check_if_needed "$failed_checks_file" "$failed_check_evidence_file" "$failed_check_review_body_file"; then : - elif run_failed_check_diagnosis "$failed_checks_file" "$failed_check_evidence_file" "$failed_check_review_body_file"; then - create_pull_review "REQUEST_CHANGES" "$(cat "$failed_check_review_body_file")" + elif run_failed_check_diagnosis "$failed_checks_file" "$failed_check_evidence_file" "$failed_check_review_body_file" "$failed_check_review_payload_file" "$failed_check_inline_failure_body_file"; then + create_pull_review_with_payload "REQUEST_CHANGES" "$(cat "$failed_check_review_body_file")" "$failed_check_review_payload_file" "$failed_check_inline_failure_body_file" else build_failed_check_fallback_body "$failed_checks_file" "$failed_check_evidence_file" "$failed_check_review_body_file" create_pull_review "REQUEST_CHANGES" "$(cat "$failed_check_review_body_file")" fi else - format_request_changes_body "$control_json" "$failed_check_review_body_file" - create_pull_review "REQUEST_CHANGES" "$(cat "$failed_check_review_body_file")" + publish_request_changes_from_control "$control_json" fi ;; *) From a9c404981b34ae9fc84cc7370e1eb13079b65d4b Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 21 Jun 2026 18:27:32 +0900 Subject: [PATCH 2/3] Fix inline review fallback warning --- .github/workflows/opencode-review.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/opencode-review.yml b/.github/workflows/opencode-review.yml index e99d8f49..7b0d45cf 100644 --- a/.github/workflows/opencode-review.yml +++ b/.github/workflows/opencode-review.yml @@ -1288,7 +1288,10 @@ jobs: local gh_error_file gh_error_file="$(mktemp)" if ! gh api -X POST "repos/${GH_REPOSITORY}/pulls/${PR_NUMBER}/reviews" --input "$review_payload_file" >/dev/null 2>"$gh_error_file"; then - warn_gh_publication_failure "pull review inline comments" "$gh_error_file" + echo "::warning::OpenCode could not submit pull review inline comments; falling back to body-only ${event} review." + if [ -s "$gh_error_file" ]; then + sed -E 's/[[:space:]]+/ /g; s/^/::warning::GitHub API: /' "$gh_error_file" || true + fi rm -f "$gh_error_file" if [ -s "$fallback_body_file" ]; then create_pull_review "$event" "$(cat "$fallback_body_file")" From 82284ee9e38f1a0cb84c70926f6f5c916ce58933 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 21 Jun 2026 18:43:02 +0900 Subject: [PATCH 3/3] Harden OpenCode runtime-failure cleanup --- .github/workflows/opencode-review.yml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/opencode-review.yml b/.github/workflows/opencode-review.yml index 7b0d45cf..875fc403 100644 --- a/.github/workflows/opencode-review.yml +++ b/.github/workflows/opencode-review.yml @@ -544,7 +544,7 @@ jobs: OPENCODE_EVIDENCE_FILE: ${{ runner.temp }}/opencode-review-evidence.md OPENCODE_OUTPUT_FILE: ${{ runner.temp }}/opencode-review-primary.md OPENCODE_REVIEW_WORKDIR: ${{ runner.temp }}/opencode-review-project - OPENCODE_PROMPT_EVIDENCE_BYTES: "3200" + OPENCODE_PROMPT_EVIDENCE_BYTES: "1800" OPENCODE_PRIMARY_TIMEOUT_SECONDS: "600" PR_NUMBER: ${{ github.event.pull_request.number || github.event.inputs.pr_number }} HEAD_SHA: ${{ github.event.pull_request.head.sha || github.event.inputs.pr_head_sha }} @@ -651,7 +651,7 @@ jobs: OPENCODE_EVIDENCE_FILE: ${{ runner.temp }}/opencode-review-evidence.md OPENCODE_OUTPUT_FILE: ${{ runner.temp }}/opencode-review-fallback.md OPENCODE_REVIEW_WORKDIR: ${{ runner.temp }}/opencode-review-project - OPENCODE_PROMPT_EVIDENCE_BYTES: "3200" + OPENCODE_PROMPT_EVIDENCE_BYTES: "1800" PR_NUMBER: ${{ github.event.pull_request.number || github.event.inputs.pr_number }} HEAD_SHA: ${{ github.event.pull_request.head.sha || github.event.inputs.pr_head_sha }} RUN_ID: ${{ github.run_id }} @@ -756,7 +756,7 @@ jobs: OPENCODE_EVIDENCE_FILE: ${{ runner.temp }}/opencode-review-evidence.md OPENCODE_OUTPUT_FILE: ${{ runner.temp }}/opencode-review-second-fallback.md OPENCODE_REVIEW_WORKDIR: ${{ runner.temp }}/opencode-review-project - OPENCODE_PROMPT_EVIDENCE_BYTES: "3200" + OPENCODE_PROMPT_EVIDENCE_BYTES: "1800" PR_NUMBER: ${{ github.event.pull_request.number || github.event.inputs.pr_number }} HEAD_SHA: ${{ github.event.pull_request.head.sha || github.event.inputs.pr_head_sha }} RUN_ID: ${{ github.run_id }} @@ -2186,6 +2186,8 @@ jobs: failed_checks_file="$(mktemp)" failed_check_evidence_file="$(mktemp)" failed_check_review_body_file="$(mktemp)" + failed_check_review_payload_file="" + failed_check_inline_failure_body_file="" pending_checks_file="" # shellcheck disable=SC2329 cleanup_failed_outcome_files() { @@ -2197,6 +2199,8 @@ jobs: if ! scripts/ci/collect_failed_check_evidence.sh "$failed_check_evidence_file"; then printf "Failed GitHub Check evidence could not be collected for current head \`%s\`.\n" "$HEAD_SHA" >"$failed_check_evidence_file" fi + failed_check_review_payload_file="$(mktemp)" + failed_check_inline_failure_body_file="$(mktemp)" if stop_for_external_failed_check_if_needed "$failed_checks_file" "$failed_check_evidence_file" "$failed_check_review_body_file"; then : fi