This repository provides an Issue-led pull-request review workflow and a complete copyable caller.
| File | Role |
|---|---|
.github/workflows/codex-openai-review.yml |
Reusable OpenAI PR reviewer for any repository. |
.github/workflows/openai-pr-review-dispatch.yml |
GizClaw's trusted PR trigger and copyable caller. |
The trigger file is the example. A consuming repository creates one workflow
with the same events, permissions, concurrency, and review job, then changes
only the uses reference from the local path to the protected release:
uses: GizClaw/github-workflows/.github/workflows/codex-openai-review.yml@v1It must pass an OPENAI_API_KEY Actions secret explicitly. Set
review-instructions, issue-review-instructions, and
pr-readiness-instructions in the caller to match the repository's trusted
policy. The shared reviewer always uses gpt-6-sol with low reasoning
effort (the Codex setting corresponding to a light review) and accepts complete
diffs up to 100,000,000 bytes. The legacy model, effort, and max-diff-bytes
inputs remain accepted for pinned callers but are ignored. Existing callers
must update their pinned workflow reference to receive this policy; they can
then remove those three inputs. The caller must grant checks: write so the
shared reviewer can expose its lifecycle on the reviewed PR head, and
pull-requests: write for request reactions on PR comments and native review
publication. It must also grant issues: write for Issue-triggered refreshes
and actions: write so the reviewer can restore the latest per-PR Codex
session artifact and delete superseded snapshots only after a replacement
upload succeeds.
In public caller repositories, complete binary-aware Git patches up to 5,000,000 bytes are reviewed automatically. Binary models, images, and other changed binary payloads count toward this limit even though their contents are not sent to the model. For a larger public-repository diff, an admin of the calling repository must post this line as a PR comment with the current full head commit SHA:
@codex review approve <40-character-head-sha>
The shared reviewer checks the comment author's admin permission in the caller
repository and the live head SHA before model work. A push requires a new
approval. This uses the existing issue_comment trigger and works for public
callers without a GitHub Environment or per-repository approver configuration.
Private caller repositories skip the 5,000,000-byte approval gate and review
automatically. The caller's base repository privacy comes from GitHub's PR API;
unknown privacy is treated as public. Diffs above 100,000,000 bytes remain
rejected in every repository.
- Reviews an open, non-draft PR when it is opened, reopened, edited, marked
ready, or receives a new head through
synchronize, including a PR from an external fork. - Recalculates open PRs that GitHub lists as closing an Issue when that Issue
is edited, reopened, typed, or untyped, using the same caller and reusable PR
reviewer. A PR GitHub has not linked is refreshed by its next event or an
@codex reviewcomment. - A commenter can request a fresh review of an internal or fork PR by putting
@codexor@codex review <focus>on its own line anywhere in a PR comment, so a comment that explains the push and ends with the request is accepted. The whole line must be the request: a mention inside a sentence, an unrecognized word after@codex, or a mention inside a fenced code block, an inline code span (including one that crosses line breaks), an indented code block, or a block quote does not start a review, and neither does a comment authored by an app. Apply repository and API-project usage limits appropriate for a public trigger. - Run workflow accepts a pull-request number as a manual fallback.
- A new request for the same PR cancels the previous one. Request comments use
👀while running,🚀when finished (including a failed attempt), and😕when superseded or cancelled. - Actions workflow reruns are rejected before review work starts because a
rerun reuses an old event while resolving the PR's current head and can lose
the incremental checkpoint chain. Push a new commit, post a new
@codex reviewcomment, or dispatch a new workflow run instead. - Every accepted review creates three fixed Check Runs on the exact PR head:
OpenAI PR Review,OpenAI Issue Review, andOpenAI Code Review. Each reports its own running, successful, failed, or cancelled state, while one nativeOpenAI PR Reviewreport contains the combined conclusion. Its default view keeps the PR-format, Issue-design, and code/plan-conformance verdicts visible alongside the reviewed scope and aggregate usage. OpenAI PR Reviewchecks the title, body, and closing-Issue linkage. The closing Issues are the ones the PR body names with a closing keyword. When a closing Issue has open native sub-issues, every open child must also be in the PR's closing-Issue set. The rule applies recursively because each included child is checked in turn; already-closed children are ignored.OpenAI Issue Reviewchecks every linked Issue independently and aggregates their trusted-base project-policy, repository-fit, and implementation-readiness verdict. It reads the project's root and applicable nestedAGENTS.mdfiles, follows the Issue-review and module documents they require, and applies that repository-owned contract without modifying the Issue or inventing missing decisions.OpenAI Code Reviewchecks only code findings and Issue-plan conformance. Configure all three names as required checks when every stage must block merging.- Code review also reads the recent PR discussion: the last 20 comments, each
clipped to 2,000 characters, with the triggering comment kept to 8,000,
marked, and restored if newer comments crowd it out of that window. It supplies author-stated intent, validation claims, disclosures, and
any focus given in the
@codex reviewcomment. Comments are untrusted data written by any commenter: they never relax the trusted caller review profile, every claim must be checked against the diff, and a claim the diff contradicts is reported. Discussion is deliberately excluded from every content-addressed stage identity, so a comment on an unchanged head still reuses evidence with zero model tokens and its text is not reviewed until a code turn runs for another reason. - An execution failure publishes a titled PR comment with the specific failure reason and a link to the Actions run instead of leaving only a reaction.
- Every published review reports the Codex review time, input, cached-input, cache-write, output, reasoning-output, and total token counts, plus the cache hit ratio. It also reports estimated Codex credits using the current public per-million-token model rate card: uncached input uses the input rate, cached input uses the cached-input rate, and output (including reasoning) uses the output rate. This is a token-derived estimate, not an API billing ledger value. Folded report sections retain the stable PR session key, content-addressed generation key, reviewed commit range, deterministic diff chunk count, and per-stage usage. The stage table identifies full, incremental, reused, and deterministic work, including a separate row for every linked Issue. Reused and deterministic rows consume zero model tokens. Cached-input tokens are part of input tokens, and reasoning-output tokens are part of output tokens; neither is added to the total a second time.
- Model sessions are bound to their trusted base commit. A changed base (or an older artifact without that binding) starts a fresh conversation while keeping the deterministic review ledger. Each model turn receives the current base explicitly, and the runner checks that its Git object is available first.
- Each PR has one logical Codex session. Its 30-day Artifact v2 snapshot stores
the validated Codex rollout plus a generation ledger containing the
last fully reviewed head, any in-progress target, the canonical file listing,
chunk hashes, completed chunk results, stage evidence, and usage. PR metadata,
every linked Issue, and code have independent content-addressed identities.
An unchanged stage reuses validated evidence with zero model tokens; an
edited PR or Issue sends only its field-level snapshot diff plus previous
evidence; a new code head sends only
last_completed_head..current_headwhen ancestry and base still match. Force-pushes, incompatible base updates, missing sessions, corrupt state, and relevant policy changes safely fall back to a complete stage review. - The reviewer fetches PR Git objects without checking out or executing the PR head and computes the complete diff locally, avoiding GitHub's 20,000-line PR-diff API limit. Files use stable byte-order listing. Diffs too large for one model turn are split deterministically at file and hunk boundaries and reviewed sequentially in the same session. The final review is published only after every chunk and aggregation turn completes.
- Every model turn reports an execution status separately from findings and policy blockers. Required input paths are checked for readability before the turn, and the reviewer is instructed to read these explicit inputs even when they live outside its working directory. An incomplete or missing execution status fails the run without caching that turn or publishing a final verdict; a new review request retries the unfinished work. Completed reviews with real blockers remain reusable. Ledger schema v4 invalidates older evidence and chunk checkpoints once, so older execution failures cannot remain cached as completed reviews. The read-only permissions and network restrictions remain.
- Failed chunk reviews checkpoint completed work in the replacement Artifact,
but do not advance
last_completed_head. A retry resumes the first unfinished chunk. Older snapshots are deleted only after the replacement upload succeeds. A missing, expired, corrupt, or incompatible snapshot safely starts a new session. - Fork PRs run through the caller repository's trusted default-branch
pull_request_targetworkflow and use the caller's explicitly forwarded secret. Secrets from the contributor's fork are not imported or used. - Automatic PR events permit an external contributor to consume review requests up to the 5,000,000-byte automatic limit in public callers. Use a dedicated API project with appropriate usage limits and restrict the organization secret to selected repositories.
- Complete diffs larger than 100,000,000 bytes fail before Codex runs. The
chunk-target-bytesinput still controls deterministic chunk sizing; the legacymax-diff-bytesinput no longer changes the total limit. - The reviewer checks out only the trusted base commit, reads the PR diff as untrusted data, never checks out or executes PR-head code, and publishes validated native inline review comments only on added lines.
Use pull_request_target only with this trusted-base, diff-as-data design.
Never check out or execute the pull-request head or merge ref, do not use
secrets: inherit, and restrict the organization secret to the repositories
that should be allowed to review.
The default Issue contract comes from the consuming project's trusted
default-branch AGENTS.md hierarchy and the Issue-review documents it
designates. The workflow itself enforces only cross-project integrity and PR
linkage requirements:
- PR titles use lowercase
prefix: Subjectform. Each slash-separated prefix segment starts with a lowercase letter and may then contain lowercase letters, digits, hyphens, or underscores. - The PR body describes the delivered result and validation.
- The PR body closes at least one same-repository Issue with a closing keyword:
close,closes,closed,fix,fixes,fixed,resolve,resolves, orresolved(any case, optional colon) followed on the same line by#N,owner/repo#N, or an Issue URL, for exampleCloses #123. The body is the only source: GitHub's Development links andclosingIssuesReferencesare not consulted, so linkage does not depend on GitHub having indexed the keyword. References inside fenced, inline, or indented code, block quotes, or HTML comments declare nothing, a plain mention such asRelated to #123does not count, and a reference that is not a readable Issue (a pull request, a missing number, an inaccessible repository) is ignored. - Issue and sub-issue snapshots must be complete.
- When an Issue body declares
- Parent: #N(orowner/repo#Nfor the same repository), GitHub's native parent must be that Issue. This is checked deterministically, never left to the model. - The complete PR result follows the current Issue plan. Material deviations must be reflected in the Issue or disclosed and resolved in the PR.
Review threads are collected across all GraphQL pages before counting unresolved actionable findings. A failed page request or a missing or repeated continuation cursor fails context collection closed; having more than 100 historical threads alone is not a readiness blocker. The publication-time verifier also enumerates every page before comparing the readiness snapshot. It rejects base/head changes between pages and preserves the final snapshot comparison, including unresolved findings on later pages.
The reviewer reads every Issue the body closes, up to 100 distinct references,
in one GraphQL request. It fails closed when the body names more, rather than
silently reviewing a truncated relationship set, and when that request fails
for any reason other than an unreadable reference. Native sub-issue snapshots
use a 100-node fail-closed bound.
Each linked Issue also preserves its native blockedBy and blocking
relationships, including repository, Issue number, and state. Both dependency
directions use the same deterministic normalization and 100-node fail-closed
bound, and their normalized state is part of the Issue and readiness hashes.
Caller policy can add trusted organization-level constraints. Repository-owned
title formats, Issue Types, sections, relationships, ownership rules,
validation commands, platform requirements, and finding severity rules belong
in trusted default-branch AGENTS.md instructions or documents they require,
never in untrusted PR code.
Readiness evidence records the reusable-workflow source for audit and binds the base/head revision, normalized PR metadata, closing-Issue snapshots, trusted policy, model, and effort. Final readiness is always regenerated for the current head. Within that run, only the affected content-addressed PR, Issue, or code stage is invalidated. A reusable-workflow source change alone does not invalidate a compatible session or its stage evidence.
Success from all three OpenAI checks means only that the configured automated blockers were absent. It is not an approval and does not replace human review, hardware or product acceptance, or deployment approval.
The copyable PR caller uses:
on:
pull_request_target:
types: [opened, reopened, synchronize, edited, ready_for_review]
issue_comment:
types: [created]
issues:
types: [edited, reopened, typed, untyped]
workflow_dispatch:The caller passes OPENAI_API_KEY explicitly and uses per-PR concurrency. Do
not use secrets: inherit. Issue events resolve the PRs GitHub lists as closing
the Issue and invoke
the same reusable PR reviewer; there is no separate Issue-review dispatcher or
second workflow.
Use this matrix after the caller is present on the repository's default branch. Every run recreates the three fixed Checks on the exact current PR head; the stage modes below describe model work and evidence reuse inside that run.
| Trigger | PR evidence | Issue evidence | Code evidence | Expected Check publication |
|---|---|---|---|---|
| Open a ready PR | full |
full for every linked Issue |
full complete diff |
All three fixed Checks |
| Edit only the PR body | incremental field diff |
reused |
reused |
All three, with only PR metadata re-reviewed |
| Edit one linked Issue | reused |
incremental for that Issue; others reused |
incremental plan-conformance aggregation with no repeated complete code diff |
All three, with Issue and Code verdicts revalidated |
| Push a descendant commit | reused |
reused |
incremental from the last completed head |
All three on the new head |
| Merge the moved base branch into the PR | reused |
reused |
full from the new merge base; base-branch commits are never reviewed as PR changes |
All three on the merge commit |
| Rerun an unchanged head | deterministic checks plus reused |
reused |
reused |
All three with zero model tokens |
The code diff always starts at the merge base between the live base branch
tip and the PR head, matching the PR's own "Files changed" view.
pull_request.base.sha stays at the base commit recorded when the head was
last pushed, so it is only used to check out trusted reviewer code, never to
decide what counts as a PR change. A base branch that moves without being
merged keeps the merge base and reuses evidence; merging it moves the merge
base and starts a fresh full code review so base-branch commits do not appear
as pull-request changes. A full generation aggregates only its own chunk
reviews; the previous code review is offered for preservation to incremental
generations alone, so findings about an earlier range cannot outlive the diff
that produced them.
Every Issue-stage turn, including an incremental one, also receives the current native Issue Type, state, parent, sub-issues, and dependencies plus the deterministic relationship checks. The reviewer re-validates previous blockers against those current values and drops any they contradict, so a wrong blocker about metadata that never changes cannot outlive its evidence. Changing that input shape invalidates cached Issue evidence once, revalidating it as an incremental turn.
An Issue edit revalidates plan conformance without resending an unchanged complete code diff. A runtime, model, or trusted-policy change intentionally invalidates incompatible session evidence and safely starts the affected review stages again. A workflow-source change remains auditable but preserves compatible cached evidence.
When editing PR metadata, preserve the closing keywords in the body. Removing or changing a closing reference changes the plan-conformance identity and intentionally invalidates the affected Code evidence.
- Copy
openai-pr-review-dispatch.ymlinto the caller repository's default branch. - Replace local reusable-workflow paths with a protected
v1reference or an immutable commit SHA. - Configure trusted repository-specific review instructions.
- Store
OPENAI_API_KEYin an allowlisted organization or repository secret and forward it explicitly. - Open a test PR whose body closes an implementation-ready Issue and confirm all three fixed OpenAI Checks are attached to the exact head.
- Push a new commit and confirm code is reviewed incrementally while unchanged PR and Issue evidence is reused with zero model tokens.
- Test invalid PR metadata, an incomplete Issue, an unexplained plan deviation, and an actionable code finding.
- Edit one linked Issue and confirm only that Issue stage runs incrementally.
- Only after live tests pass, configure all three fixed Check names as required status checks in the caller repository ruleset.