diff --git a/.github/workflows/claude-review.yml b/.github/workflows/claude-review.yml index ce6f4a7..8284a35 100644 --- a/.github/workflows/claude-review.yml +++ b/.github/workflows/claude-review.yml @@ -24,7 +24,7 @@ concurrency: jobs: review: - uses: HarperFast/ai-review-prompts/.github/workflows/_claude-review.yml@128656e40c87c0e1293c542a5500df4f68dbff85 # main 2026-05-12 (post #25 — symmetric pin with gemini-review.yml; picks up shared-script refactor and authorize-ai-workflow.sh rename) + uses: HarperFast/ai-review-prompts/.github/workflows/_claude-review.yml@045c81bf2c2b5b5b4a520fa6b2de137f86fcbc2a # main 2026-05-14 (post #30..#36 — symmetric pin with gemini-review.yml; Claude has no functional change from any of these; pin just stays in lockstep) with: # Same SHA as the `uses:` ref above. The reusable uses this to # check out HarperFast/ai-review-prompts (layer files + bash @@ -35,7 +35,7 @@ jobs: # introspect their own ref (`github.workflow_ref` resolves to the # CALLER's ref in `workflow_call` context), and `uses: …@` # is parsed literally so we can't interpolate a variable. - ai-review-prompts-ref: 128656e40c87c0e1293c542a5500df4f68dbff85 + ai-review-prompts-ref: 045c81bf2c2b5b5b4a520fa6b2de137f86fcbc2a review-layers: | universal harper/common diff --git a/.github/workflows/gemini-review-debug.yml b/.github/workflows/gemini-review-debug.yml new file mode 100644 index 0000000..59c4eec --- /dev/null +++ b/.github/workflows/gemini-review-debug.yml @@ -0,0 +1,182 @@ +name: Gemini PR Review (debug) + +# Pragmatic shell-based Gemini reviewer. After 3 debug iterations +# proving MCP tool propagation is unreliable (v1.0.x server bug, +# umbrella-tool-shape mismatch with model's training, INVALID_STREAM +# on /pr-code-review, hallucinated review on /pr-review), pivoting +# to what the model wants to do anyway: use the `gh` CLI. +# +# Goal: produce A working Gemini review on PR #83 to compare against +# Claude. Architectural elegance is a non-goal for this iteration. +# +# Architecture: +# - No MCP. No upstream `code-review` extension. No custom slash +# command file. Just an inline prompt. +# - tools.core allows `gh`, `git`, `cat`, `echo`, `grep`, `head`, +# `tail`. The agent uses these natively. +# - Agent reads the diff via `gh pr diff`, generates a review, +# posts it via `gh pr review --comment --body`. +# - Body-anchored findings (no per-line inline comments — would +# require MCP, which we just spent 3 iterations failing to wire). +# Findings reference file:line as `**File:** path:N` plain text. + +on: + pull_request: + types: [opened, synchronize, reopened] + +concurrency: + group: gemini-review-debug-${{ github.event.pull_request.number }} + cancel-in-progress: true + +jobs: + review: + runs-on: ubuntu-latest + timeout-minutes: 10 + permissions: + contents: read + id-token: write + pull-requests: write + steps: + - name: Checkout + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.2 + with: + persist-credentials: 'false' + + - name: Run Gemini pull request review + id: gemini-review + uses: google-github-actions/run-gemini-cli@f77273f4c914e4bf38440cf36a0369cb64a37489 # v0.1.22 + env: + GEMINI_CLI_TRUST_WORKSPACE: 'true' + GITHUB_TOKEN: ${{ github.token }} + GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }} + GH_TOKEN: ${{ github.token }} + PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} + REPOSITORY: ${{ github.repository }} + with: + gemini_api_key: ${{ secrets.GEMINI_API_KEY }} + gemini_model: 'gemini-3-flash-preview' + gemini_cli_version: 'latest' + gemini_debug: 'true' + upload_artifacts: 'true' + settings: |- + { + "model": { + "maxSessionTurns": 15 + }, + "telemetry": { + "enabled": true, + "target": "local", + "outfile": ".gemini/telemetry.log" + }, + "tools": { + "core": [ + "run_shell_command(gh)", + "run_shell_command(git)", + "run_shell_command(cat)", + "run_shell_command(echo)", + "run_shell_command(grep)", + "run_shell_command(head)", + "run_shell_command(tail)" + ] + } + } + prompt: | + You are a senior software engineer reviewing pull request + #${{ github.event.pull_request.number }} on + ${{ github.repository }}. + + Step 1 — Read the diff. Run: + + gh pr diff ${{ github.event.pull_request.number }} \ + --repo ${{ github.repository }} + + Step 2 — Decide if the diff is trivial. Trivial means + dependency version bumps, CI workflow pin updates, + lockfile-only churn, prose-only doc edits, version-string + changes. If trivial, skip to Step 4 with the no-blockers + template. + + Step 3 — For substantive diffs, review for BLOCKERS only. + A blocker is a 🔴 Critical (security vulnerability, + data-loss bug, broken public API contract) or 🟠 High + (clear correctness/security issue likely to bite in + production) finding. Do NOT post 🟡 Medium or 🟢 Low + findings. Cap at 10 findings. Reference each finding's + file:line as plain-text `**File:** path:LINE`. + + Step 4 — Post the review via: + + gh pr review ${{ github.event.pull_request.number }} \ + --repo ${{ github.repository }} \ + --comment \ + --body "$REVIEW_BODY" + + Where REVIEW_BODY is your review markdown formatted as: + + + + ## 📋 Review Summary + + + + ## 🔍 Findings + + ### 1. 🔴 + + **File:** `path/to/file.ext:LINE` + + **What:** <one or two sentences> + + **Why it matters:** <impact> + + **Suggested fix:** <concrete change or fenced code block> + + ### 2. ... + + Omit the `## 🔍 Findings` section entirely if you have + zero blockers. + + The `<!-- gemini-review:v1 -->` marker on the first line + is REQUIRED — it's how the team's tooling threads runs + together across pushes. + + After posting, your job is done. Do not post a duplicate. + Do not edit the review. + + - name: Upload gemini-artifacts (failure path) + if: failure() + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: gemini-debug-output-failure + path: gemini-artifacts/ + if-no-files-found: warn + retention-days: 14 + + - name: Append gemini logs tail to job summary + if: failure() + shell: bash + run: | + set -eu + if [ ! -d gemini-artifacts ]; then + { + echo "## ⚠️ Gemini debug run failed (no gemini-artifacts/ directory)" + } >> "$GITHUB_STEP_SUMMARY" + exit 0 + fi + { + echo "## ⚠️ Gemini debug run failed — log tails" + echo + echo "Full logs uploaded as the \`gemini-debug-output-failure\` artifact." + echo + for f in stdout.log stderr.log telemetry.log; do + if [ -f "gemini-artifacts/$f" ] && [ -s "gemini-artifacts/$f" ]; then + echo "### \`gemini-artifacts/$f\` (last 200 lines)" + echo + echo '```' + (tail -n 200 "gemini-artifacts/$f" | head -c 50000) || true + echo + echo '```' + echo + fi + done + } >> "$GITHUB_STEP_SUMMARY" diff --git a/.github/workflows/gemini-review.yml b/.github/workflows/gemini-review.yml index 936a315..53c7c1a 100644 --- a/.github/workflows/gemini-review.yml +++ b/.github/workflows/gemini-review.yml @@ -34,13 +34,13 @@ concurrency: jobs: review: - uses: HarperFast/ai-review-prompts/.github/workflows/_gemini-review.yml@128656e40c87c0e1293c542a5500df4f68dbff85 # main 2026-05-12 (post #25 — workflow posts Gemini response, output-name fix, default model gemini-3-flash-preview) + uses: HarperFast/ai-review-prompts/.github/workflows/_gemini-review.yml@045c81bf2c2b5b5b4a520fa6b2de137f86fcbc2a # main 2026-05-14 (post #30..#36 — visibility fix: caller-side if-failure upload of gemini-artifacts (works around upstream's missing if:always() on its own upload step) + job-summary tail; this run-attempt's purpose is to capture the full post-#35 agent trace) with: # Same SHA as the `uses:` ref above. See claude-review.yml # in this repo for why the duplication is unavoidable # (reusable workflows can't introspect their own ref in # workflow_call context). - ai-review-prompts-ref: 128656e40c87c0e1293c542a5500df4f68dbff85 + ai-review-prompts-ref: 045c81bf2c2b5b5b4a520fa6b2de137f86fcbc2a review-layers: | universal harper/common