Skip to content
49 changes: 49 additions & 0 deletions .github/actions/pr-review/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,17 @@ runs:
# Bind a fresh provisional comment before the model runs. Completed
# reports remain separate, CI-owned publication output.
run: python3 ${{ github.action_path }}/scripts/prepare-review-summary.py
- name: Freeze prior blocking reviews for optional self-dismissal
id: reset-prepare
continue-on-error: true
shell: bash
env:
GH_TOKEN: ${{ inputs.github_token }}
PR_NUMBER: ${{ inputs.pr_number }}
SUMMARY_MARKER: ${{ steps.review-config.outputs.summary_heading }}
REVIEW_RUN_STARTED_AT: ${{ steps.review-config.outputs.review_run_started_at }}
REVIEW_RESET_SNAPSHOT: ${{ runner.temp }}/pr-review-reset-${{ steps.summary-transport.outputs.comment_id }}-snapshot.json
run: python3 ${{ github.action_path }}/scripts/review-reset.py prepare
- name: Run Claude PR Review
id: claude_review
uses: anthropics/claude-code-action@9171db3e57d6a3140a37ddc2ba92788584e0ead6 # v1.0.234: Claude Code 2.1.282
Expand Down Expand Up @@ -185,6 +196,29 @@ runs:
# shell path) to create or edit comments.
claude_args: --model claude-opus-5-5 --max-turns 100 --setting-sources user --strict-mcp-config --disallowedTools "Skill,ScheduleWakeup,CronCreate,CronDelete,CronList" --allowedTools "Read,Glob,Grep,Task,mcp__github_inline_comment__create_inline_comment,mcp__github_comment__update_claude_comment,Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh api:*)"
prompt: ${{ env.REVIEW_PROMPT }}
- name: Capture optional terminal reset proof
id: reset-proof
if: steps.claude_review.outcome == 'success' && steps.reset-prepare.outcome == 'success' && steps.reset-prepare.outputs.has_targets == 'true'
continue-on-error: true
shell: bash
env:
SUMMARY_MARKER: ${{ steps.review-config.outputs.summary_heading }}
REVIEW_RESET_SNAPSHOT: ${{ runner.temp }}/pr-review-reset-${{ steps.summary-transport.outputs.comment_id }}-snapshot.json
REVIEW_EXECUTION_FILE: ${{ steps.claude_review.outputs.execution_file }}
REVIEW_SESSION_ID: ${{ steps.claude_review.outputs.session_id }}
REVIEW_RESET_FILE: ${{ runner.temp }}/pr-review-reset-${{ steps.summary-transport.outputs.comment_id }}.json
run: python3 ${{ github.action_path }}/scripts/review-reset.py capture
- name: Persist accepted reset evidence
id: reset-upload
if: steps.reset-proof.outcome == 'success'
continue-on-error: true
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
with:
name: ${{ steps.reset-prepare.outputs.artifact_name }}
path: ${{ runner.temp }}/pr-review-reset-${{ steps.summary-transport.outputs.comment_id }}.json
if-no-files-found: error
# Repository retention defaults apply. Failure retains blocks but does not
# suppress the ordinary publisher; outcome below is NOT masked conclusion.
- name: Publish review report and verdict
id: publish
# CI finalizes the run deterministically rather than relying on the agent
Expand Down Expand Up @@ -235,3 +269,18 @@ runs:
.github/review-criteria.md
.github/review-criteria.json
retention-days: 7
- name: Dismiss exactly audited prior blocking reviews
if: steps.publish.outcome == 'success' && steps.reset-proof.outcome == 'success' && steps.reset-upload.outcome == 'success'
continue-on-error: true
shell: bash
env:
GH_TOKEN: ${{ inputs.github_token }}
PR_NUMBER: ${{ inputs.pr_number }}
SUMMARY_MARKER: ${{ steps.review-config.outputs.summary_heading }}
REVIEW_RUN_STARTED_AT: ${{ steps.review-config.outputs.review_run_started_at }}
REVIEW_RESET_FILE: ${{ runner.temp }}/pr-review-reset-${{ steps.summary-transport.outputs.comment_id }}.json
REVIEW_RESET_SHA256: ${{ steps.reset-proof.outputs.sha256 }}
REVIEW_RESET_UPLOAD_OUTCOME: ${{ steps.reset-upload.outcome }}
REVIEW_RESET_ARTIFACT_ID: ${{ steps.reset-upload.outputs.artifact-id }}
REVIEW_RESET_ARTIFACT_DIGEST: ${{ steps.reset-upload.outputs.artifact-digest }}
run: python3 ${{ github.action_path }}/scripts/review-reset.py dismiss
32 changes: 32 additions & 0 deletions .github/actions/pr-review/prompts/base-pr-review.md
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,38 @@ Your only obligation is an accurate count and a complete summary; a missing or
malformed count turns the whole run red, so always post the summary in the exact
template above.

### Optional terminal proof for clearing this reviewer's prior blocks

If `.github/review-reset.json` is available and its `targets` list is nonempty,
read its frozen `audit` entries in addition to Step 3. Recheck EACH entry against
current code, including all original blocking report findings; duplicated entries
still need their own audit IDs. Missing/deleted/edited original evidence is not
proof of a fix.
Do not rely on resolved threads or earlier runs' “fixed” assertions.
If there are no eligible targets, skip this optional proof and publish normally.

Post the usual final Markdown summary through the native comment tool first.
Then end your terminal response with one `review-reset-proof` fenced JSON block
(not a comment, file, tool call, or a second copy of the Markdown):

```review-reset-proof
{"review_complete":true,"coverage_gaps":[],"blocking_issues":0,
"audit":[{"id":"<each frozen audit ID>","disposition":"fixed",
"evidence":[{"path":"path/to/file","location":"line range or symbol",
"explanation":"Current code evidence resolving this exact finding"}]}]}
```

CI supplies run/attempt, head/base, and session provenance from its frozen
snapshot and runner metadata; do not add provenance fields to this proof.

Use `fixed`, `obsolete` (identify replacement code), `incorrect` (explain why the
original finding was wrong), `still_present`, or `unverified` honestly for every
entry. Set completeness, coverage gaps, and blocking count to the actual review
outcome, never to obtain dismissal. Material gaps keep the normal summary
provisional as already required. Finish all foreground audit agents before the
terminal response. If the reset snapshot/proof is unavailable, publish normally;
CI simply retains prior blocks. This proof never authorizes APPROVE.

## Review Criteria

Use these base criteria for every repository. Built-in mixins and trusted repo-local
Expand Down
Loading
Loading