From 81720a923dc1f280dcadf85f41fe8d63d5f76e18 Mon Sep 17 00:00:00 2001 From: Patrick Lacey Date: Fri, 3 Jul 2026 03:17:44 -0400 Subject: [PATCH 1/3] fix(ci): report agent workflow handoff failures --- .github/codex/prompts/issue-implement.md | 9 +++ .github/workflows/issue-implement.yml | 84 ++++++++++++++++++++++++ .github/workflows/pr-review.yml | 42 ++++++++++++ 3 files changed, 135 insertions(+) diff --git a/.github/codex/prompts/issue-implement.md b/.github/codex/prompts/issue-implement.md index 36e989d..a3f1df4 100644 --- a/.github/codex/prompts/issue-implement.md +++ b/.github/codex/prompts/issue-implement.md @@ -28,6 +28,15 @@ Before editing, determine: - What behavior needs to change - What tests or checks should validate the fix +Runtime and validation guidance: + +- You are running on an Ubuntu GitHub Actions runner in a temporary worktree. +- Use non-interactive, Linux-compatible commands. Do not start servers, watchers, or tools that wait for user input. +- The workflow will run the repository's authoritative validation after you finish. For this repository, that is `ruff format --check .`, `ruff check .`, and `pytest`. +- During your session, prefer focused tests that cover the files or behavior you changed, plus quick lint or format checks when practical. +- If a broad validation command appears to hang or stays silent for a reasonable period, interrupt it once, record the command as inconclusive, and finish the handoff so the workflow validation step can run. +- For broad pytest runs, prefer `pytest` over `pytest -q` so progress is visible in the Actions log. + After editing, return a markdown summary with: ## Summary diff --git a/.github/workflows/issue-implement.yml b/.github/workflows/issue-implement.yml index a6cb854..2fa84ae 100644 --- a/.github/workflows/issue-implement.yml +++ b/.github/workflows/issue-implement.yml @@ -17,6 +17,9 @@ permissions: issues: write pull-requests: write +# Draft PR creation also requires the repository Actions setting +# "Allow GitHub Actions to create and approve pull requests". +# The permissions block above cannot enable that setting by itself. concurrency: group: agent-issue-${{ github.event.issue.number || inputs.issue_number }} cancel-in-progress: false @@ -365,6 +368,7 @@ jobs: run: exit 1 - name: Push branch + id: push if: steps.validate.outcome == 'success' && steps.commit.outcome == 'success' && steps.commit.outputs.has_changes == 'true' working-directory: ../agent-worktree env: @@ -419,6 +423,7 @@ jobs: )" - name: Update issue agent labels + id: update_labels if: steps.create_pr.outcome == 'success' env: GH_TOKEN: ${{ github.token }} @@ -466,3 +471,82 @@ jobs: issue_number: issueNumber, labels: ["agent-blocked"] }); + + - name: Comment when issue workflow failed + if: > + ${{ + always() && + failure() && + steps.issue.outputs.number != '' && + steps.validate.outcome != 'failure' && + ( + steps.commit.outcome != 'failure' || + steps.commit.outputs.block_reason != 'forbidden_artifacts' + ) + }} + uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7 + env: + ISSUE_NUMBER: ${{ steps.issue.outputs.number }} + RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + BRANCH_NAME: ${{ steps.branch.outputs.name }} + AGENT_SUMMARY: ${{ steps.run_codex.outputs.final-message }} + CODEX_OUTCOME: ${{ steps.run_codex.outcome }} + VALIDATION_OUTCOME: ${{ steps.validate.outcome }} + COMMIT_OUTCOME: ${{ steps.commit.outcome }} + PUSH_OUTCOME: ${{ steps.push.outcome }} + CREATE_PR_OUTCOME: ${{ steps.create_pr.outcome }} + LABEL_UPDATE_OUTCOME: ${{ steps.update_labels.outcome }} + with: + script: | + const issueNumber = Number(process.env.ISSUE_NUMBER); + + const outcomes = [ + ["Codex implementation", process.env.CODEX_OUTCOME], + ["workflow validation", process.env.VALIDATION_OUTCOME], + ["commit", process.env.COMMIT_OUTCOME], + ["push", process.env.PUSH_OUTCOME], + ["draft PR creation", process.env.CREATE_PR_OUTCOME], + ["issue label update", process.env.LABEL_UPDATE_OUTCOME], + ].filter(([, outcome]) => outcome && outcome !== ""); + + const body = [ + "## Agent workflow failed", + "", + "The agent workflow failed after issue validation, so the normal handoff did not complete.", + "", + process.env.BRANCH_NAME + ? `Working branch: \`${process.env.BRANCH_NAME}\`` + : "Working branch: unavailable", + `Run: ${process.env.RUN_URL}`, + "", + "### Step outcomes", + "", + ...outcomes.map(([name, outcome]) => `- ${name}: ${outcome}`), + "", + "## Agent notes", + "", + process.env.AGENT_SUMMARY || "_No additional summary was returned._", + ].join("\n"); + + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, + body, + }); + + try { + await github.rest.issues.removeLabel({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, + name: "agent-ready" + }); + } catch (e) { /* label may already be absent */ } + + await github.rest.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, + labels: ["agent-blocked"] + }); diff --git a/.github/workflows/pr-review.yml b/.github/workflows/pr-review.yml index 30aeee1..c6d0c7c 100644 --- a/.github/workflows/pr-review.yml +++ b/.github/workflows/pr-review.yml @@ -187,6 +187,7 @@ jobs: output-file: codex-pr-review.md - name: Post review notes as PR comment + id: post_review_comment uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7 env: PR_NUMBER: ${{ steps.pr.outputs.number }} @@ -213,3 +214,44 @@ jobs: issue_number: Number(process.env.PR_NUMBER), body }); + + - name: Comment when PR review workflow failed + if: ${{ always() && failure() && steps.pr.outputs.number != '' }} + uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7 + env: + PR_NUMBER: ${{ steps.pr.outputs.number }} + RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + VALIDATION_OUTCOME: ${{ steps.validate.outcome }} + CODEX_OUTCOME: ${{ steps.run_codex.outcome }} + REVIEW_COMMENT_OUTCOME: ${{ steps.post_review_comment.outcome }} + VALIDATION_SUMMARY: ${{ steps.validation_summary.outputs.summary }} + with: + script: | + const outcomes = [ + ["validation", process.env.VALIDATION_OUTCOME], + ["Codex review", process.env.CODEX_OUTCOME], + ["review comment", process.env.REVIEW_COMMENT_OUTCOME], + ].filter(([, outcome]) => outcome && outcome !== ""); + + const body = [ + "## Agent PR review failed", + "", + "The automated review workflow failed before it could complete the normal review comment.", + "", + `Run: ${process.env.RUN_URL}`, + "", + "### Step outcomes", + "", + ...outcomes.map(([name, outcome]) => `- ${name}: ${outcome}`), + "", + "## Validation", + "", + process.env.VALIDATION_SUMMARY || "_Validation result was unavailable._", + ].join("\n"); + + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: Number(process.env.PR_NUMBER), + body, + }); From 16bb5452bd124657af96743aff0b812651246a81 Mon Sep 17 00:00:00 2001 From: Patrick Lacey Date: Fri, 3 Jul 2026 15:36:36 -0400 Subject: [PATCH 2/3] fix(ci): harden agent workflow handoffs --- .github/workflows/issue-implement.yml | 31 ++++++++++++++++----------- .github/workflows/pr-review.yml | 7 +++--- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/.github/workflows/issue-implement.yml b/.github/workflows/issue-implement.yml index 2fa84ae..4b21947 100644 --- a/.github/workflows/issue-implement.yml +++ b/.github/workflows/issue-implement.yml @@ -109,6 +109,14 @@ jobs: with: fetch-depth: 0 + - name: Checkout trusted Codex assets from default branch + uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5 + with: + ref: ${{ github.event.repository.default_branch || 'main' }} + path: trusted-base + persist-credentials: false + sparse-checkout: .github/codex + - name: Configure git identity run: | git config user.name "agent-bot" @@ -156,9 +164,9 @@ jobs: model: ${{ vars.CODEX_MODEL || 'gpt-5.5' }} effort: ${{ vars.CODEX_EFFORT || 'medium' }} working-directory: ../agent-worktree - prompt-file: .github/codex/prompts/issue-implement.md + prompt-file: trusted-base/.github/codex/prompts/issue-implement.md sandbox: workspace-write - codex-home: .github/codex/home + codex-home: trusted-base/.github/codex/home output-file: codex-issue-implementation.md - name: Run project checks if available @@ -474,16 +482,15 @@ jobs: - name: Comment when issue workflow failed if: > - ${{ - always() && - failure() && - steps.issue.outputs.number != '' && - steps.validate.outcome != 'failure' && - ( - steps.commit.outcome != 'failure' || - steps.commit.outputs.block_reason != 'forbidden_artifacts' - ) - }} + always() && + failure() && + steps.issue.outputs.number != '' && + steps.validate.outcome != 'failure' && + ( + steps.commit.outcome != 'failure' || + steps.commit.outputs.block_reason != 'forbidden_artifacts' + ) + continue-on-error: true uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7 env: ISSUE_NUMBER: ${{ steps.issue.outputs.number }} diff --git a/.github/workflows/pr-review.yml b/.github/workflows/pr-review.yml index c6d0c7c..c594fd1 100644 --- a/.github/workflows/pr-review.yml +++ b/.github/workflows/pr-review.yml @@ -15,7 +15,7 @@ on: permissions: contents: read - pull-requests: read + pull-requests: write issues: write concurrency: @@ -65,7 +65,7 @@ jobs: # any edits to the review prompt itself. Check out the prompts from the # default branch separately so a PR cannot rewrite its own reviewer # instructions (prompt injection). - - name: Checkout trusted prompts from default branch + - name: Checkout trusted Codex assets from default branch uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5 with: ref: ${{ github.event.repository.default_branch || 'main' }} @@ -183,7 +183,7 @@ jobs: effort: ${{ vars.CODEX_EFFORT || 'medium' }} prompt-file: trusted-base/.github/codex/prompts/pr-review.md sandbox: read-only - codex-home: .github/codex/home + codex-home: trusted-base/.github/codex/home output-file: codex-pr-review.md - name: Post review notes as PR comment @@ -217,6 +217,7 @@ jobs: - name: Comment when PR review workflow failed if: ${{ always() && failure() && steps.pr.outputs.number != '' }} + continue-on-error: true uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7 env: PR_NUMBER: ${{ steps.pr.outputs.number }} From 4f5c459e8ddd1cb55fa4930f16fb4e8837856a60 Mon Sep 17 00:00:00 2001 From: Patrick Lacey Date: Sat, 4 Jul 2026 01:36:09 -0400 Subject: [PATCH 3/3] fix: restrict PR reveiw workflow permissions --- .github/workflows/pr-review.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr-review.yml b/.github/workflows/pr-review.yml index c594fd1..7c72c8a 100644 --- a/.github/workflows/pr-review.yml +++ b/.github/workflows/pr-review.yml @@ -15,7 +15,7 @@ on: permissions: contents: read - pull-requests: write + pull-requests: read issues: write concurrency: