mirror of
https://github.com/Comfy-Org/github-workflows.git
synced 2026-11-05 00:17:37 +00:00
[PR #399] [MERGED] feat(cursor-review): optional direct-Anthropic judge via the pinned Claude Code CLI #400
Labels
No labels
cursor-review-catalog-drift
groom
groom
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Comfy-Org/github-workflows#400
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/Comfy-Org/github-workflows/pull/399
Author: @mattmillerai
Created: 10/9/2026
Status: ✅ Merged
Merged: 10/9/2026
Merged by: @mattmillerai
Base:
main← Head:matt/be-19914-direct-judge📝 Commits (2)
998545dfeat(cursor-review): optional direct-Anthropic judge via the pinned Claude Code CLI (BE-19914)3880687fix(cursor-review): run the direct judge in its own job so ANTHROPIC_API_KEY never reaches consolidate📊 Changes
10 files changed (+1001 additions, -30 deletions)
View changed files
📝
.github/cursor-review/README.md(+3 -1)📝
.github/cursor-review/catalog-drift.py(+1 -1)📝
.github/cursor-review/package.json(+1 -1)📝
.github/cursor-review/tests/test_workflow_job_isolation.py(+8 -6)➕
.github/cursor-review/tests/test_workflow_judge_direct.py(+414 -0)📝
.github/cursor-review/tests/test_workflow_panel_integrity.py(+5 -2)📝
.github/cursor-review/tests/test_workflow_ref_guard_parity.py(+1 -1)📝
.github/workflow-pins/tests/test_check_workflow_pins.py(+6 -2)📝
.github/workflows/cursor-review.yml(+559 -15)📝
docs/callers/cursor-review.md(+3 -1)📄 Description
Summary
This adds an opt-in direct-Anthropic judge to
cursor-review.yml. It is the judge's counterpart to the direct-Anthropic review cells (#396) and reuses their pinned Claude Code CLI, their install and verify steps, and theANTHROPIC_API_KEYsecret.judge_direct_model(default'') andjudge_direct_effort(defaultxhigh). Preflight emitsjudge_direct=trueonly when the id is plain ([A-Za-z0-9._-]{1,100}, no whitespace) and the gate'santhropic_key_presentis true. In any other case it warns and the Cursor judge runs. An unknown effort warns and falls back toxhigh.judge-directjob (GitHub-hostedubuntu-latest,contents: read, no Cursor CLI and no shell agent). It runs only whenconsolidatewould andjudge_direct == 'true':It rebuilds the judge input with steps byte-identical to
consolidate's: checkout, assets, the reviewed diff, the ledger, the panel findings,Aggregate panel findingsandBuild judge prompt. A test checks that they stay identical.Install Claude Code CLIandVerify Claude Code CLI versionare the cells' steps, reading the pin from.github/cursor-review/package.json. They are absorbed and time-boxed (5m and 2m).The new
Run judge (direct)step does the following inside the PR checkout:find . -type l -deleteand removes.claude/,.mcp.jsonandCLAUDE.local.md;claude -pon the same/tmp/judge-prompt.txt;review-output-mcp.py --mode judgeserver, writing to/tmp/judge-findings.json;timeout-minutesandcontinue-on-error.ANTHROPIC_API_KEYis set in this step's env only, together withCLAUDE_CONFIG_DIR=$(mktemp -d -p "$RUNNER_TEMP")andCLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1. Every stdin Python in this job runs aspython3 -I.Exfil guard:
Refuse a judge review carrying the API keyruns withalways(). If the review contains the key (LC_ALL=C grep -qF), it replaces the file with the--initerror seed. It then logs onlystatus=<ok|error|?>, N finding(s)and never the review text or the raw result.Upload direct judge reviewuploads/tmp/judge-findings.jsonascursor-review-judge-direct. It is not absorbed.consolidatejob: it never referencesANTHROPIC_API_KEY, and itsruns-onis unchanged frommain.Install Cursor agent CLIandRun judge(Cursor) are skipped.Download direct judge review/Adopt direct judge reviewcopy the artifact over the seed, but only whenjudge-directsucceeded and the file is a JSON object. Otherwise the seed stays andBuild consolidated findings filetakes the existing degraded panel-union path. A panel cell that uploads under that name first makes the real upload 409, which fails the job, so nothing forged is adopted.<model> (direct)..github/cursor-review/README.mdanddocs/callers/cursor-review.md, with the same zero-data-retention noteanthropic_direct_modelhas. Updated theANTHROPIC_API_KEYrow to match.Judgment calls and deviations from the spec
No
--bare. The spec's flag list includes--bare. While #396 was being merged, testing showed that on the pinned CLI (2.1.286)--baresilently drops Grep and Glob from--tools "Read,Grep,Glob", which leaves only Read. So this step mirrors the merged cells instead:--bare;--setting-sources ""plus a freshCLAUDE_CONFIG_DIRcover what--barewould have skipped;--disallowedTools "Read(//proc/**),Read(//sys/**)"is a second layer under--restricted, because the key sits in/proc/self/environ;A test pins that
--barestays out.The judge runs in its own job, not inside
consolidate. The spec puts the direct judge inconsolidate. But Actions sends a job every secret its steps reference, including skipped steps. Inconsolidate, the key would therefore sit beside the Cursor judge (an unsandboxed shell agent over PR text) for any caller who passes it, including callers who pass it only for the direct cells. A first version movedconsolidatetoubuntu-latestwhenever the key was passed. That fixed the pool exposure but not the shell agent, and it changedconsolidate's runner for those callers, so review led to the separatejudge-directjob instead. The cost is a few duplicated steps (pinned byte-identical by a test) plus one artifact hand-off.gateresolvesanthropic_key_presentonly when either direct input is set, and acceptance criterion 1 now holds as written:consolidatefollowsruns_onexactly as onmain.Install and verify are absorbed (
continue-on-error) and time-boxed (5m and 2m) here, unlike in the cells. A judge whose CLI fails to install or verify, or hangs doing it, is skipped. The seed is then posted through the degraded panel-union path, the same outcome as a failed Cursor judge, instead of failing the review and posting nothing.Mutually exclusive judges. The spec says to run
claude -pinstead ofcursor-agent. With the judge direct,consolidateskips the Cursor judge and its CLI install and adopts thejudge-directreview instead. Otherwisejudge-directdoes not run. A test checks that exactly one judge runs.catalog-drift.py'sLAST_CHECKED_WINDOWgoes from 40 to 50. The two new preflight env lines pushed thelast checkedaudit comment past the window, and the real-workflow test caught it.Tests
test_workflow_judge_direct.py:Define panel modelsscript for the set, unset, missing-key (falseand''), non-plain-id (space,/, more than 100 characters, newline,$(id)) and bad-effort cases. It also checks that the panel list does not depend on the judge input.consolidatenever mentionsANTHROPIC_API_KEYand followsruns_on;judge-directis hosted and read-only, hasconsolidate's cap,needs(minus itself) andif:(plusjudge_direct), and contains no Cursor agent and no barepython3 -;consolidate's;judge-directto have succeeded;find -type l -deletebeforeclaude -p;Configure structured final review,Adopt direct judge reviewandBuild consolidated findings file:degraded=trueand posts the panel union;degraded=false;statusvalue is never echoed.test_workflow_job_isolation.py:judge-direct(hosted) joins the gate and the direct cells as the onlyANTHROPIC_API_KEYholders. Theruns_onrouting test is unchanged frommain.test_workflow_ref_guard_parity.pyandtest_check_workflow_pins.py: the guard count rises by one forjudge-direct's own byte-identical copy of theworkflows_refguard.judge_direct=true, the Cursor step'sif:and the symlink delete) cover code that the restructure did not change.Residual
claude -pas the judge, with a realANTHROPIC_API_KEYon a real PR, was made from here, because this host has no key and no caller. The confinement flags are the ones #396 verified on the pinned 2.1.286 binary, but this specific command line (judge MCP toolcursor_review_submit_final, cwd at the root of the merge-ref checkout) has only been checked structurally and by executing the surrounding steps. The first opted-in caller run should confirm that a direct judge submits (Direct judge: status=ok) and that a review posts un-degraded.<model> (direct)is recorded injudge-findings.json'smodelfield, which travels in thecursor-review-consolidatedpayload artifact, and not in the rendered review text. If the review body itself should show the judge, that needs apost-review.pychange.Verification
python3 -m unittest discover -s .github/cursor-review/tests -p 'test_*.py': OKpython3 -m unittest discover -s .github/workflow-pins/tests -p 'test_*.py': OKcheck_workflow_pins.py: OKcheck_agents_md.py --root .: passed, with 2 pre-existing warningscheck-org-repo-literals.sh: OKactionlint: only thejob.workflow_shaexpression findings, whichmainhas too, plus shellcheck info-level notesProvenance
judge-directisolation and parity tests.check_workflow_pins.pyare green.main.--bare;--setting-sources ""and deny rules are used instead.judge-directjob instead of insideconsolidate.🤖 Generated with Claude Code
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.