diff --git a/.github/workflows/gitnexus-review-agent.yml b/.github/workflows/gitnexus-review-agent.yml index 7102e7e5e5..b2a5c3d0f9 100644 --- a/.github/workflows/gitnexus-review-agent.yml +++ b/.github/workflows/gitnexus-review-agent.yml @@ -232,7 +232,6 @@ jobs: uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: '22.16.0' - cache: false - name: Install and preflight Claude subprocess isolation id: isolation @@ -1878,8 +1877,8 @@ jobs: timeout-minutes: 10 permissions: actions: read # Download the immutable review artifact from the analyze job. - pull-requests: read # Reject publication when the PR tuple moved. - issues: write # Upsert the bounded bot review comment. + pull-requests: write # Reject publication when the PR tuple moved; upsert the bounded bot review comment on the PR. + issues: write # Issue-comment scope for non-PR fallbacks. steps: - name: Download review artifact id: download diff --git a/gitnexus/test/unit/review-agent-workflow.test.ts b/gitnexus/test/unit/review-agent-workflow.test.ts index 46f1232795..03ee5bb61b 100644 --- a/gitnexus/test/unit/review-agent-workflow.test.ts +++ b/gitnexus/test/unit/review-agent-workflow.test.ts @@ -1045,7 +1045,8 @@ describe('gitnexus review-agent workflow security contract', () => { expect(analyze).toContain('pull-requests: read'); expect(analyze).not.toContain('issues: write'); expect(publish).toContain('issues: write'); - expect(publish).toContain('pull-requests: read'); + expect(publish).toContain('pull-requests: write'); + expect(publish).not.toContain('contents: write'); expect(publish).not.toContain('actions/checkout@'); expect(publish).not.toContain('ANTHROPIC_API_KEY'); expect(publish).not.toContain('CLAUDE_CODE_OAUTH_TOKEN');