From 5ca7325702500925f50063ee07cccfaed51c2e79 Mon Sep 17 00:00:00 2001 From: idy Date: Sat, 26 Sep 2026 03:10:09 +0800 Subject: [PATCH 1/2] fix: centralize Codex review model and diff limit --- .github/scripts/pr-review/test.mjs | 16 ++++++++ .github/workflows/codex-openai-review.yml | 40 +++++++++++-------- .../workflows/openai-pr-review-dispatch.yml | 4 -- README.md | 18 +++++---- 4 files changed, 50 insertions(+), 28 deletions(-) diff --git a/.github/scripts/pr-review/test.mjs b/.github/scripts/pr-review/test.mjs index aff4336..e4d888d 100644 --- a/.github/scripts/pr-review/test.mjs +++ b/.github/scripts/pr-review/test.mjs @@ -144,6 +144,22 @@ const workflowSource = fs.readFileSync( ), "utf8", ); +// Deprecated caller inputs must not override the policy that is used for +// execution, session restore, readiness evidence, or review publication. +assert.doesNotMatch(workflowSource, /\$\{\{ inputs\.(?:model|effort|max-diff-bytes) \}\}/); +assert.match(workflowSource, /^ review:\n(?:(?!^ \S)[\s\S])*?^ REVIEW_MODEL: gpt-6-sol$/m); +assert.match(workflowSource, /^ review:\n(?:(?!^ \S)[\s\S])*?^ REVIEW_EFFORT: low$/m); +assert.match(workflowSource, /^ review:\n(?:(?!^ \S)[\s\S])*?^ REVIEW_MAX_DIFF_BYTES: '5000000'$/m); +assert.match(workflowSource, /^ publish:\n(?:(?!^ \S)[\s\S])*?^ REVIEW_MODEL: gpt-6-sol$/m); +assert.match(workflowSource, /^ publish:\n(?:(?!^ \S)[\s\S])*?^ REVIEW_EFFORT: low$/m); +assert.match(workflowSource, /MAX_DIFF_BYTES: \$\{\{ env\.REVIEW_MAX_DIFF_BYTES \}\}/); +assert.equal((workflowSource.match(/MODEL: \$\{\{ env\.REVIEW_MODEL \}\}/g) ?? []).length, 5); +assert.equal((workflowSource.match(/EFFORT: \$\{\{ env\.REVIEW_EFFORT \}\}/g) ?? []).length, 5); +const dispatchSource = fs.readFileSync( + path.join(path.dirname(new URL(import.meta.url).pathname), "..", "..", "workflows", "openai-pr-review-dispatch.yml"), + "utf8", +); +assert.doesNotMatch(dispatchSource, /^ (?:model|effort|max-diff-bytes):/m); assert.match( workflowSource, /^ rerun-guard:\n(?:(?!^ \S)[\s\S])*?RUN_ATTEMPT: \$\{\{ github\.run_attempt \}\}(?:(?!^ \S)[\s\S])*?if \[ "\$RUN_ATTEMPT" -ne 1 \]; then(?:(?!^ \S)[\s\S])*?exit 1$/m, diff --git a/.github/workflows/codex-openai-review.yml b/.github/workflows/codex-openai-review.yml index 0f96449..fa7d70a 100644 --- a/.github/workflows/codex-openai-review.yml +++ b/.github/workflows/codex-openai-review.yml @@ -4,14 +4,14 @@ on: workflow_call: inputs: model: - description: OpenAI model used by Codex for this review. + description: Deprecated compatibility input; the shared reviewer always uses gpt-6-sol. required: false - default: gpt-5.6-terra + default: gpt-6-sol type: string effort: - description: Reasoning effort supplied to Codex for this review. + description: Deprecated compatibility input; the shared reviewer always uses low reasoning effort. required: false - default: medium + default: low type: string codex-version: description: Exact Codex CLI version used so persisted sessions remain compatible. @@ -19,9 +19,9 @@ on: default: 0.145.0 type: string max-diff-bytes: - description: Maximum complete base-to-head diff size accepted for one PR. + description: Deprecated compatibility input; the shared reviewer always accepts up to 5000000 diff bytes. required: false - default: 1000000 + default: 5000000 type: number chunk-target-bytes: description: Deterministic target size for each first-review or incremental diff chunk. @@ -317,6 +317,9 @@ jobs: || (steps.evaluate_readiness.outcome == 'failure' && 'Could not produce structured PR readiness evidence.') || '' }} env: + REVIEW_MODEL: gpt-6-sol + REVIEW_EFFORT: low + REVIEW_MAX_DIFF_BYTES: '5000000' PULL_REQUEST_NUMBER: ${{ needs.resolve.outputs.number }} PR_BASE_SHA: ${{ needs.resolve.outputs.base_sha }} PR_BASE_REF: ${{ needs.resolve.outputs.base_ref }} @@ -691,8 +694,8 @@ jobs: env: EXPECTED_ARTIFACT_ID: ${{ steps.find_session.outputs.artifact_id }} EXPECTED_CODEX_VERSION: ${{ inputs.codex-version }} - EXPECTED_MODEL: ${{ inputs.model }} - EXPECTED_EFFORT: ${{ inputs.effort }} + EXPECTED_MODEL: ${{ env.REVIEW_MODEL }} + EXPECTED_EFFORT: ${{ env.REVIEW_EFFORT }} REPOSITORY_ID: ${{ github.repository_id }} REVIEW_INSTRUCTIONS: >- ${{ inputs.review-instructions }} @@ -840,7 +843,7 @@ jobs: id: prepare_diff env: REPOSITORY_DIR: ${{ env.PR_DIFF_REPOSITORY }} - MAX_DIFF_BYTES: ${{ inputs.max-diff-bytes }} + MAX_DIFF_BYTES: ${{ env.REVIEW_MAX_DIFF_BYTES }} CHUNK_TARGET_BYTES: ${{ inputs.chunk-target-bytes }} READINESS_CONTEXT_SHA256: ${{ steps.prepare_readiness.outputs.context_sha256 }} run: node "$REVIEWER_SOURCE_DIR/.github/scripts/pr-review/prepare.mjs" @@ -879,8 +882,8 @@ jobs: GENERATION_KEY: ${{ steps.prepare_diff.outputs.generation_key }} GENERATION_REUSED: ${{ steps.prepare_diff.outputs.reused }} RESUMED_SESSION_ID: ${{ steps.restore_session.outputs.session_id }} - MODEL: ${{ inputs.model }} - EFFORT: ${{ inputs.effort }} + MODEL: ${{ env.REVIEW_MODEL }} + EFFORT: ${{ env.REVIEW_EFFORT }} REVIEW_INSTRUCTIONS: ${{ inputs.review-instructions }} ISSUE_REVIEW_INSTRUCTIONS: ${{ inputs.issue-review-instructions }} PR_REVIEW_INSTRUCTIONS: ${{ inputs.pr-readiness-instructions }} @@ -893,8 +896,8 @@ jobs: env: REVIEW: ${{ steps.run_review.outputs.review }} WORKFLOW_SOURCE_SHA: ${{ job.workflow_sha }} - MODEL: ${{ inputs.model }} - EFFORT: ${{ inputs.effort }} + MODEL: ${{ env.REVIEW_MODEL }} + EFFORT: ${{ env.REVIEW_EFFORT }} run: >- node "$REVIEWER_SOURCE_DIR/.github/scripts/pr-readiness/evaluate.mjs" @@ -921,8 +924,8 @@ jobs: continue-on-error: true env: CODEX_VERSION: ${{ inputs.codex-version }} - MODEL: ${{ inputs.model }} - EFFORT: ${{ inputs.effort }} + MODEL: ${{ env.REVIEW_MODEL }} + EFFORT: ${{ env.REVIEW_EFFORT }} REPOSITORY_ID: ${{ github.repository_id }} WORKFLOW_SOURCE_SHA: ${{ job.workflow_sha }} REVIEW_INSTRUCTIONS: >- @@ -1179,6 +1182,9 @@ jobs: contents: read issues: read pull-requests: write + env: + REVIEW_MODEL: gpt-6-sol + REVIEW_EFFORT: low outputs: failure_reason: >- ${{ (steps.verify_identity.outcome == 'failure' @@ -1216,8 +1222,8 @@ jobs: env: REVIEW: ${{ needs.review.outputs.review }} READINESS_EVIDENCE: ${{ needs.review.outputs.readiness_evidence }} - MODEL: ${{ inputs.model }} - EFFORT: ${{ inputs.effort }} + MODEL: ${{ env.REVIEW_MODEL }} + EFFORT: ${{ env.REVIEW_EFFORT }} DURATION_SECONDS: ${{ needs.review.outputs.duration_seconds }} USAGE_AVAILABLE: ${{ needs.review.outputs.usage_available }} INPUT_TOKENS: ${{ needs.review.outputs.input_tokens }} diff --git a/.github/workflows/openai-pr-review-dispatch.yml b/.github/workflows/openai-pr-review-dispatch.yml index 158aa92..8a3062e 100644 --- a/.github/workflows/openai-pr-review-dispatch.yml +++ b/.github/workflows/openai-pr-review-dispatch.yml @@ -30,8 +30,6 @@ jobs: if: github.event_name != 'issues' uses: ./.github/workflows/codex-openai-review.yml with: - model: gpt-5.6-terra - effort: medium review-instructions: >- Review the pull-request diff and report actionable findings. issue-review-instructions: >- @@ -101,8 +99,6 @@ jobs: pull_request_number: ${{ fromJSON(needs.resolve_linked_prs.outputs.pull_requests) }} uses: ./.github/workflows/codex-openai-review.yml with: - model: gpt-5.6-terra - effort: medium review-instructions: >- Review the pull-request diff and report actionable findings. issue-review-instructions: >- diff --git a/README.md b/README.md index e30cb8d..2a2f662 100644 --- a/README.md +++ b/README.md @@ -16,10 +16,15 @@ only the `uses` reference from the local path to the protected release: uses: GizClaw/github-workflows/.github/workflows/codex-openai-review.yml@v1 ``` -It must pass an `OPENAI_API_KEY` Actions secret explicitly. Set `model`, -`effort`, `review-instructions`, `issue-review-instructions`, and +It 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 caller must grant `checks: write` so the +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 5,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 @@ -137,10 +142,9 @@ upload succeeds. review requests when opening, editing, or pushing to an eligible PR. Use a dedicated API project with appropriate usage limits and restrict the organization secret to selected repositories. -- Complete diffs larger than 1 MB fail before Codex runs by default, limiting - untrusted input and avoiding unbounded model usage. Callers can explicitly - set `max-diff-bytes` and `chunk-target-bytes` when their cost policy permits - larger reviews. +- Complete diffs larger than 5,000,000 bytes fail before Codex runs. The + `chunk-target-bytes` input still controls deterministic chunk sizing; the + legacy `max-diff-bytes` input 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. From dcf9195d34eff8cef68b813468adfbc5b163d89d Mon Sep 17 00:00:00 2001 From: idy Date: Sat, 26 Sep 2026 03:25:42 +0800 Subject: [PATCH 2/2] fix: raise enforced review diff limit to 100 MB --- .github/scripts/pr-review/test.mjs | 2 +- .github/workflows/codex-openai-review.yml | 6 +++--- README.md | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/scripts/pr-review/test.mjs b/.github/scripts/pr-review/test.mjs index e4d888d..5f5847e 100644 --- a/.github/scripts/pr-review/test.mjs +++ b/.github/scripts/pr-review/test.mjs @@ -149,7 +149,7 @@ const workflowSource = fs.readFileSync( assert.doesNotMatch(workflowSource, /\$\{\{ inputs\.(?:model|effort|max-diff-bytes) \}\}/); assert.match(workflowSource, /^ review:\n(?:(?!^ \S)[\s\S])*?^ REVIEW_MODEL: gpt-6-sol$/m); assert.match(workflowSource, /^ review:\n(?:(?!^ \S)[\s\S])*?^ REVIEW_EFFORT: low$/m); -assert.match(workflowSource, /^ review:\n(?:(?!^ \S)[\s\S])*?^ REVIEW_MAX_DIFF_BYTES: '5000000'$/m); +assert.match(workflowSource, /^ review:\n(?:(?!^ \S)[\s\S])*?^ REVIEW_MAX_DIFF_BYTES: '100000000'$/m); assert.match(workflowSource, /^ publish:\n(?:(?!^ \S)[\s\S])*?^ REVIEW_MODEL: gpt-6-sol$/m); assert.match(workflowSource, /^ publish:\n(?:(?!^ \S)[\s\S])*?^ REVIEW_EFFORT: low$/m); assert.match(workflowSource, /MAX_DIFF_BYTES: \$\{\{ env\.REVIEW_MAX_DIFF_BYTES \}\}/); diff --git a/.github/workflows/codex-openai-review.yml b/.github/workflows/codex-openai-review.yml index fa7d70a..d8130ca 100644 --- a/.github/workflows/codex-openai-review.yml +++ b/.github/workflows/codex-openai-review.yml @@ -19,9 +19,9 @@ on: default: 0.145.0 type: string max-diff-bytes: - description: Deprecated compatibility input; the shared reviewer always accepts up to 5000000 diff bytes. + description: Deprecated compatibility input; the shared reviewer always accepts up to 100000000 diff bytes. required: false - default: 5000000 + default: 100000000 type: number chunk-target-bytes: description: Deterministic target size for each first-review or incremental diff chunk. @@ -319,7 +319,7 @@ jobs: env: REVIEW_MODEL: gpt-6-sol REVIEW_EFFORT: low - REVIEW_MAX_DIFF_BYTES: '5000000' + REVIEW_MAX_DIFF_BYTES: '100000000' PULL_REQUEST_NUMBER: ${{ needs.resolve.outputs.number }} PR_BASE_SHA: ${{ needs.resolve.outputs.base_sha }} PR_BASE_REF: ${{ needs.resolve.outputs.base_ref }} diff --git a/README.md b/README.md index 2a2f662..f778cd7 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ It must pass an `OPENAI_API_KEY` Actions secret explicitly. Set `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 5,000,000 bytes. The legacy `model`, `effort`, and `max-diff-bytes` +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 @@ -142,7 +142,7 @@ upload succeeds. review requests when opening, editing, or pushing to an eligible PR. Use a dedicated API project with appropriate usage limits and restrict the organization secret to selected repositories. -- Complete diffs larger than 5,000,000 bytes fail before Codex runs. The +- Complete diffs larger than 100,000,000 bytes fail before Codex runs. The `chunk-target-bytes` input still controls deterministic chunk sizing; the legacy `max-diff-bytes` input no longer changes the total limit. - The reviewer checks out only the trusted base commit, reads the PR diff as