From 20a69fd7ca9af3efb43f4bf878f4064ae508faa5 Mon Sep 17 00:00:00 2001 From: Sasa Junuzovic Date: Tue, 17 Mar 2026 21:28:46 -0700 Subject: [PATCH 1/9] fix: restore responder to working version (f2a4b14) minus resolve Exact match to the version that successfully addressed review threads (run 23117978475, 2026-03-15), with only two changes: 1. Added if: label gate for aw PRs 2. Removed resolve-pull-request-review-thread safe-output and step 6e (orchestrator handles resolution) No other changes. This commit should not be modified. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/review-responder.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/review-responder.md b/.github/workflows/review-responder.md index 9fa69209..ed88a0b8 100644 --- a/.github/workflows/review-responder.md +++ b/.github/workflows/review-responder.md @@ -58,13 +58,11 @@ This workflow runs when a review is submitted on a pull request. 6. For each unresolved review comment thread (up to 10): a. Read the comment and understand what change is being requested b. Read the relevant file and surrounding code context - c. Make the requested fix in the code (edit the file locally — do NOT push yet) + c. Make the requested fix in the code d. Reply to the comment thread explaining what you changed 7. After addressing all comments, run the CI checks locally to make sure your fixes don't break anything: `uv sync && uv run ruff check --fix . && uv run ruff format . && uv run pyright && uv run pytest --cov --cov-fail-under=80 -v` -8. Push all changes in a single commit with message "fix: address review comments". Reply to all threads BEFORE pushing — replies after a push will appear on outdated code. +8. Push all changes in a single commit with message "fix: address review comments". If a review comment requests a change that would be architecturally significant or you're unsure about, reply to the thread explaining your concern rather than making the change blindly. - -NOTE: Thread resolution is handled separately by the pipeline orchestrator after this workflow completes. Your job is to fix the code and reply to threads — do NOT attempt to resolve threads. From 38394561f4f181a0f20d8080c72a0c1ff30cb0f8 Mon Sep 17 00:00:00 2001 From: Sasa Junuzovic Date: Tue, 17 Mar 2026 21:51:58 -0700 Subject: [PATCH 2/9] feat: switch responder to workflow_dispatch trigger MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace pull_request_review trigger with workflow_dispatch + pr_number input. No more loops from stray review events. Orchestrator or manual dispatch controls when responder runs. Removed aw label check and triggering review check — no longer applicable with workflow_dispatch. Renumbered steps. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/review-responder.lock.yml | 44 ++++++--------------- .github/workflows/review-responder.md | 31 +++++++-------- 2 files changed, 26 insertions(+), 49 deletions(-) diff --git a/.github/workflows/review-responder.lock.yml b/.github/workflows/review-responder.lock.yml index 26e31f2d..422356a6 100644 --- a/.github/workflows/review-responder.lock.yml +++ b/.github/workflows/review-responder.lock.yml @@ -22,40 +22,34 @@ # For more information: https://github.github.com/gh-aw/introduction/overview/ # # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"1f273805d83429b3a54dcfbae6be92e73d936e61f45a40685d07d6aea98ec2ad","compiler_version":"v0.60.0","strict":true} +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"18ea3aea8412a09391cfc10b7bb4fdb762ed47ac575855ee07f24644e6fb3cc7","compiler_version":"v0.60.0","strict":true} name: "Review Responder" "on": - # bots: # Bots processed as bot check in pre-activation job - # - Copilot # Bots processed as bot check in pre-activation job - # - copilot-pull-request-reviewer # Bots processed as bot check in pre-activation job - pull_request_review: - types: - - submitted - # roles: all # Roles processed as role check in pre-activation job + workflow_dispatch: + inputs: + pr_number: + description: PR number to address review comments on + required: true + type: string permissions: {} concurrency: - group: "gh-aw-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref || github.run_id }}" - cancel-in-progress: true + group: "gh-aw-${{ github.workflow }}" run-name: "Review Responder" jobs: activation: - if: contains(github.event.pull_request.labels.*.name, 'aw') runs-on: ubuntu-slim permissions: contents: read outputs: - body: ${{ steps.sanitized.outputs.body }} comment_id: "" comment_repo: "" model: ${{ steps.generate_aw_info.outputs.model }} secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} - text: ${{ steps.sanitized.outputs.text }} - title: ${{ steps.sanitized.outputs.title }} steps: - name: Setup Scripts uses: github/gh-aw-actions/setup@v0.60.0 @@ -109,17 +103,6 @@ jobs: setupGlobals(core, github, context, exec, io); const { main } = require('/opt/gh-aw/actions/check_workflow_timestamp_api.cjs'); await main(); - - name: Compute current body text - id: sanitized - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_ALLOWED_BOTS: Copilot,copilot-pull-request-reviewer - with: - script: | - const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io); - const { main } = require('/opt/gh-aw/actions/compute_text.cjs'); - await main(); - name: Create prompt with built-in context env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt @@ -132,7 +115,7 @@ jobs: GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} - GH_AW_IS_PR_COMMENT: ${{ github.event.issue.pull_request && 'true' || '' }} + GH_AW_INPUTS_PR_NUMBER: ${{ inputs.pr_number }} run: | bash /opt/gh-aw/actions/create_prompt_first.sh { @@ -180,9 +163,6 @@ jobs: GH_AW_PROMPT_EOF cat "/opt/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - if [ "$GITHUB_EVENT_NAME" = "issue_comment" ] && [ -n "$GH_AW_IS_PR_COMMENT" ] || [ "$GITHUB_EVENT_NAME" = "pull_request_review_comment" ] || [ "$GITHUB_EVENT_NAME" = "pull_request_review" ]; then - cat "/opt/gh-aw/prompts/pr_context_prompt.md" - fi cat << 'GH_AW_PROMPT_EOF' GH_AW_PROMPT_EOF @@ -194,7 +174,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} + GH_AW_INPUTS_PR_NUMBER: ${{ inputs.pr_number }} with: script: | const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); @@ -213,7 +193,7 @@ jobs: GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} - GH_AW_IS_PR_COMMENT: ${{ github.event.issue.pull_request && 'true' || '' }} + GH_AW_INPUTS_PR_NUMBER: ${{ inputs.pr_number }} with: script: | const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); @@ -233,7 +213,7 @@ jobs: GH_AW_GITHUB_REPOSITORY: process.env.GH_AW_GITHUB_REPOSITORY, GH_AW_GITHUB_RUN_ID: process.env.GH_AW_GITHUB_RUN_ID, GH_AW_GITHUB_WORKSPACE: process.env.GH_AW_GITHUB_WORKSPACE, - GH_AW_IS_PR_COMMENT: process.env.GH_AW_IS_PR_COMMENT + GH_AW_INPUTS_PR_NUMBER: process.env.GH_AW_INPUTS_PR_NUMBER } }); - name: Validate prompt placeholders diff --git a/.github/workflows/review-responder.md b/.github/workflows/review-responder.md index ed88a0b8..5ab78bf5 100644 --- a/.github/workflows/review-responder.md +++ b/.github/workflows/review-responder.md @@ -1,10 +1,11 @@ --- -if: "contains(github.event.pull_request.labels.*.name, 'aw')" on: - pull_request_review: - types: [submitted] - roles: all - bots: [Copilot, copilot-pull-request-reviewer] + workflow_dispatch: + inputs: + pr_number: + description: "PR number to address review comments on" + required: true + type: string permissions: contents: read @@ -39,30 +40,26 @@ safe-outputs: # Review Responder -Address review comments on pull request #${{ github.event.pull_request.number }}. +Address review comments on pull request #${{ inputs.pr_number }}. ## Instructions -This workflow runs when a review is submitted on a pull request. +This workflow addresses unresolved review comments on a pull request. -1. First, check if the PR has the `aw` label. If it does NOT have the `aw` label, stop immediately — this workflow only handles agent-created PRs. +1. Check if the PR already has the label `review-response-attempted`. If it does, add a comment to the PR saying "Review response already attempted — stopping to prevent loops. Manual intervention needed." and stop. -2. Check the review that triggered this workflow. If the review has no comments (e.g., a plain approval with no inline comments), stop — there is nothing to address. +2. Add the label `review-response-attempted` to the PR. -3. Check if the PR already has the label `review-response-attempted`. If it does, add a comment to the PR saying "Review response already attempted — stopping to prevent loops. Manual intervention needed." and stop. +3. Read the unresolved review comment threads on the PR (not just the latest review — get all unresolved threads). If there are more than 10 unresolved threads, address the first 10 and leave a summary comment on the PR noting how many remain for manual follow-up. -4. Add the label `review-response-attempted` to the PR. - -5. Read the unresolved review comment threads on the PR (not just the latest review — get all unresolved threads). If there are more than 10 unresolved threads, address the first 10 and leave a summary comment on the PR noting how many remain for manual follow-up. - -6. For each unresolved review comment thread (up to 10): +4. For each unresolved review comment thread (up to 10): a. Read the comment and understand what change is being requested b. Read the relevant file and surrounding code context c. Make the requested fix in the code d. Reply to the comment thread explaining what you changed -7. After addressing all comments, run the CI checks locally to make sure your fixes don't break anything: `uv sync && uv run ruff check --fix . && uv run ruff format . && uv run pyright && uv run pytest --cov --cov-fail-under=80 -v` +5. After addressing all comments, run the CI checks locally to make sure your fixes don't break anything: `uv sync && uv run ruff check --fix . && uv run ruff format . && uv run pyright && uv run pytest --cov --cov-fail-under=80 -v` -8. Push all changes in a single commit with message "fix: address review comments". +6. Push all changes in a single commit with message "fix: address review comments". If a review comment requests a change that would be architecturally significant or you're unsure about, reply to the thread explaining your concern rather than making the change blindly. From af4ee63cbe100c3f6217c83791f080b013ef63fb Mon Sep 17 00:00:00 2001 From: Sasa Junuzovic Date: Tue, 17 Mar 2026 21:52:14 -0700 Subject: [PATCH 3/9] feat: responder fixes CI failures before pushing If CI checks fail after addressing review comments, fix the issues and re-run until they pass. Do not push broken code. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/review-responder.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/review-responder.md b/.github/workflows/review-responder.md index 5ab78bf5..3ca813cf 100644 --- a/.github/workflows/review-responder.md +++ b/.github/workflows/review-responder.md @@ -60,6 +60,8 @@ This workflow addresses unresolved review comments on a pull request. 5. After addressing all comments, run the CI checks locally to make sure your fixes don't break anything: `uv sync && uv run ruff check --fix . && uv run ruff format . && uv run pyright && uv run pytest --cov --cov-fail-under=80 -v` -6. Push all changes in a single commit with message "fix: address review comments". +6. If CI checks fail, fix the issues and re-run until they pass. Do not push broken code. + +7. Push all changes in a single commit with message "fix: address review comments". If a review comment requests a change that would be architecturally significant or you're unsure about, reply to the thread explaining your concern rather than making the change blindly. From 69cf6915e288497e314e86d35347b85a2815d27c Mon Sep 17 00:00:00 2001 From: Sasa Junuzovic Date: Tue, 17 Mar 2026 22:55:47 -0700 Subject: [PATCH 4/9] feat: set target '*' on safe outputs for workflow_dispatch support The reply-to-pull-request-review-comment and push-to-pull-request-branch safe output handlers default to target 'triggering' which requires a pull_request event context. Setting target to '*' lets the agent specify the PR number in each message, enabling workflow_dispatch. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/review-responder.lock.yml | 16 +++++++++++++--- .github/workflows/review-responder.md | 7 +++++++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/.github/workflows/review-responder.lock.yml b/.github/workflows/review-responder.lock.yml index 422356a6..4e7b8824 100644 --- a/.github/workflows/review-responder.lock.yml +++ b/.github/workflows/review-responder.lock.yml @@ -22,7 +22,7 @@ # For more information: https://github.github.com/gh-aw/introduction/overview/ # # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"18ea3aea8412a09391cfc10b7bb4fdb762ed47ac575855ee07f24644e6fb3cc7","compiler_version":"v0.60.0","strict":true} +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"e9dedf9ee2f5a6beffd74f5c1ac40c9263eda4f41e3db146c13a4d8576fd3970","compiler_version":"v0.60.0","strict":true} name: "Review Responder" "on": @@ -159,6 +159,9 @@ jobs: {{#if __GH_AW_GITHUB_RUN_ID__ }} - **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__ {{/if}} + - **checkouts**: The following repositories have been checked out and are available in the workspace: + - `$GITHUB_WORKSPACE` → `__GH_AW_GITHUB_REPOSITORY__` (cwd) [full history, all branches available as remote-tracking refs] [additional refs fetched: *] + - **Note**: If a branch you need is not in the list above and is not listed as an additional fetched ref, it has NOT been checked out. For private repositories you cannot fetch it without proper authentication. If the branch is required and not available, exit with an error and ask the user to add it to the `fetch:` option of the `checkout:` configuration (e.g., `fetch: ["refs/pulls/open/*"]` for all open PR refs, or `fetch: ["main", "feature/my-branch"]` for specific branches). GH_AW_PROMPT_EOF @@ -269,6 +272,13 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false + fetch-depth: 0 + - name: Fetch additional refs + env: + GH_AW_FETCH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + run: | + header=$(printf "x-access-token:%s" "${GH_AW_FETCH_TOKEN}" | base64 -w 0) + git -c "http.extraheader=Authorization: Basic ${header}" fetch origin '+refs/heads/*:refs/remotes/origin/*' - name: Create gh-aw temp directory run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh - name: Configure Git credentials @@ -321,7 +331,7 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > /opt/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF' - {"add_labels":{"max":3},"missing_data":{},"missing_tool":{},"noop":{"max":1},"push_to_pull_request_branch":{"max":1},"reply_to_pull_request_review_comment":{"max":10}} + {"add_labels":{"max":3},"missing_data":{},"missing_tool":{},"noop":{"max":1},"push_to_pull_request_branch":{"max":1,"target":"*"},"reply_to_pull_request_review_comment":{"max":10,"target":"*"}} GH_AW_SAFE_OUTPUTS_CONFIG_EOF - name: Write Safe Outputs Tools run: | @@ -1050,7 +1060,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "*.pythonhosted.org,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,conda.anaconda.org,conda.binstar.org,crates.io,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,files.pythonhosted.org,github.com,host.docker.internal,index.crates.io,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,pip.pypa.io,ppa.launchpad.net,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.npmjs.org,repo.anaconda.com,repo.continuum.io,s.symcb.com,s.symcd.com,security.ubuntu.com,static.crates.io,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_labels\":{\"github-token\":\"${{ secrets.GH_AW_WRITE_TOKEN }}\"},\"missing_data\":{},\"missing_tool\":{},\"push_to_pull_request_branch\":{\"github-token\":\"${{ secrets.GH_AW_WRITE_TOKEN }}\",\"if_no_changes\":\"warn\",\"max_patch_size\":1024,\"protected_files\":[\"package.json\",\"bun.lockb\",\"bunfig.toml\",\"deno.json\",\"deno.jsonc\",\"deno.lock\",\"global.json\",\"NuGet.Config\",\"Directory.Packages.props\",\"mix.exs\",\"mix.lock\",\"go.mod\",\"go.sum\",\"stack.yaml\",\"stack.yaml.lock\",\"pom.xml\",\"build.gradle\",\"build.gradle.kts\",\"settings.gradle\",\"settings.gradle.kts\",\"gradle.properties\",\"package-lock.json\",\"yarn.lock\",\"pnpm-lock.yaml\",\"npm-shrinkwrap.json\",\"requirements.txt\",\"Pipfile\",\"Pipfile.lock\",\"pyproject.toml\",\"setup.py\",\"setup.cfg\",\"Gemfile\",\"Gemfile.lock\",\"uv.lock\",\"AGENTS.md\"],\"protected_path_prefixes\":[\".github/\",\".agents/\"]},\"reply_to_pull_request_review_comment\":{\"github-token\":\"${{ secrets.GH_AW_WRITE_TOKEN }}\",\"max\":10}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_labels\":{\"github-token\":\"${{ secrets.GH_AW_WRITE_TOKEN }}\"},\"missing_data\":{},\"missing_tool\":{},\"push_to_pull_request_branch\":{\"github-token\":\"${{ secrets.GH_AW_WRITE_TOKEN }}\",\"if_no_changes\":\"warn\",\"labels\":[\"aw\"],\"max_patch_size\":1024,\"protected_files\":[\"package.json\",\"bun.lockb\",\"bunfig.toml\",\"deno.json\",\"deno.jsonc\",\"deno.lock\",\"global.json\",\"NuGet.Config\",\"Directory.Packages.props\",\"mix.exs\",\"mix.lock\",\"go.mod\",\"go.sum\",\"stack.yaml\",\"stack.yaml.lock\",\"pom.xml\",\"build.gradle\",\"build.gradle.kts\",\"settings.gradle\",\"settings.gradle.kts\",\"gradle.properties\",\"package-lock.json\",\"yarn.lock\",\"pnpm-lock.yaml\",\"npm-shrinkwrap.json\",\"requirements.txt\",\"Pipfile\",\"Pipfile.lock\",\"pyproject.toml\",\"setup.py\",\"setup.cfg\",\"Gemfile\",\"Gemfile.lock\",\"uv.lock\",\"AGENTS.md\"],\"protected_path_prefixes\":[\".github/\",\".agents/\"],\"target\":\"*\"},\"reply_to_pull_request_review_comment\":{\"github-token\":\"${{ secrets.GH_AW_WRITE_TOKEN }}\",\"max\":10,\"target\":\"*\"}}" GH_AW_CI_TRIGGER_TOKEN: ${{ secrets.GH_AW_CI_TRIGGER_TOKEN }} GITHUB_TOKEN: ${{ secrets.GH_AW_WRITE_TOKEN }} with: diff --git a/.github/workflows/review-responder.md b/.github/workflows/review-responder.md index 3ca813cf..c0d1a44e 100644 --- a/.github/workflows/review-responder.md +++ b/.github/workflows/review-responder.md @@ -12,6 +12,10 @@ permissions: issues: read pull-requests: read +checkout: + fetch: ["*"] + fetch-depth: 0 + engine: id: copilot model: claude-opus-4.6 @@ -29,8 +33,11 @@ safe-outputs: noop: report-as-issue: false push-to-pull-request-branch: + target: "*" + labels: [aw] github-token: ${{ secrets.GH_AW_WRITE_TOKEN }} reply-to-pull-request-review-comment: + target: "*" max: 10 github-token: ${{ secrets.GH_AW_WRITE_TOKEN }} add-labels: From ca1945c6142f349ab275d84f6f1528c95106d53c Mon Sep 17 00:00:00 2001 From: Sasa Junuzovic Date: Wed, 18 Mar 2026 23:12:10 -0700 Subject: [PATCH 5/9] feat: ci-fixer target '*' + checkout fetch for workflow_dispatch support Same fix as the responder: set target '*' on push-to-pull-request-branch so the agent specifies the PR number in its message (no event context needed). Added labels: [aw] to restrict pushes. Added checkout fetch config so all remote branches are available. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/ci-fixer.lock.yml | 16 +++++++++++++--- .github/workflows/ci-fixer.md | 6 ++++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci-fixer.lock.yml b/.github/workflows/ci-fixer.lock.yml index 00122283..38f8ec8a 100644 --- a/.github/workflows/ci-fixer.lock.yml +++ b/.github/workflows/ci-fixer.lock.yml @@ -22,7 +22,7 @@ # For more information: https://github.github.com/gh-aw/introduction/overview/ # # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"c98baaa4a5441be843d9eeff48e720eb24e733bef35184d2c5d5317d3b4f36c7","compiler_version":"v0.60.0","strict":true} +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"758fa9374f179a42496f526b463402eb4a8da6d9989669b7afa121352e870f66","compiler_version":"v0.60.0","strict":true} name: "CI Fixer" "on": @@ -159,6 +159,9 @@ jobs: {{#if __GH_AW_GITHUB_RUN_ID__ }} - **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__ {{/if}} + - **checkouts**: The following repositories have been checked out and are available in the workspace: + - `$GITHUB_WORKSPACE` → `__GH_AW_GITHUB_REPOSITORY__` (cwd) [full history, all branches available as remote-tracking refs] [additional refs fetched: *] + - **Note**: If a branch you need is not in the list above and is not listed as an additional fetched ref, it has NOT been checked out. For private repositories you cannot fetch it without proper authentication. If the branch is required and not available, exit with an error and ask the user to add it to the `fetch:` option of the `checkout:` configuration (e.g., `fetch: ["refs/pulls/open/*"]` for all open PR refs, or `fetch: ["main", "feature/my-branch"]` for specific branches). GH_AW_PROMPT_EOF @@ -270,6 +273,13 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false + fetch-depth: 0 + - name: Fetch additional refs + env: + GH_AW_FETCH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + run: | + header=$(printf "x-access-token:%s" "${GH_AW_FETCH_TOKEN}" | base64 -w 0) + git -c "http.extraheader=Authorization: Basic ${header}" fetch origin '+refs/heads/*:refs/remotes/origin/*' - name: Create gh-aw temp directory run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh - name: Configure Git credentials @@ -322,7 +332,7 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > /opt/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF' - {"add_comment":{"max":1},"add_labels":{"max":3},"missing_data":{},"missing_tool":{},"noop":{"max":1},"push_to_pull_request_branch":{"max":1}} + {"add_comment":{"max":1},"add_labels":{"max":3},"missing_data":{},"missing_tool":{},"noop":{"max":1},"push_to_pull_request_branch":{"max":1,"target":"*"}} GH_AW_SAFE_OUTPUTS_CONFIG_EOF - name: Write Safe Outputs Tools run: | @@ -1051,7 +1061,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "*.pythonhosted.org,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,conda.anaconda.org,conda.binstar.org,crates.io,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,files.pythonhosted.org,github.com,host.docker.internal,index.crates.io,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,pip.pypa.io,ppa.launchpad.net,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.npmjs.org,repo.anaconda.com,repo.continuum.io,s.symcb.com,s.symcd.com,security.ubuntu.com,static.crates.io,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"github-token\":\"${{ secrets.GH_AW_WRITE_TOKEN }}\",\"max\":1},\"add_labels\":{\"github-token\":\"${{ secrets.GH_AW_WRITE_TOKEN }}\"},\"missing_data\":{},\"missing_tool\":{},\"push_to_pull_request_branch\":{\"github-token\":\"${{ secrets.GH_AW_WRITE_TOKEN }}\",\"if_no_changes\":\"warn\",\"max_patch_size\":1024,\"protected_files\":[\"package.json\",\"bun.lockb\",\"bunfig.toml\",\"deno.json\",\"deno.jsonc\",\"deno.lock\",\"global.json\",\"NuGet.Config\",\"Directory.Packages.props\",\"mix.exs\",\"mix.lock\",\"go.mod\",\"go.sum\",\"stack.yaml\",\"stack.yaml.lock\",\"pom.xml\",\"build.gradle\",\"build.gradle.kts\",\"settings.gradle\",\"settings.gradle.kts\",\"gradle.properties\",\"package-lock.json\",\"yarn.lock\",\"pnpm-lock.yaml\",\"npm-shrinkwrap.json\",\"requirements.txt\",\"Pipfile\",\"Pipfile.lock\",\"pyproject.toml\",\"setup.py\",\"setup.cfg\",\"Gemfile\",\"Gemfile.lock\",\"uv.lock\",\"AGENTS.md\"],\"protected_path_prefixes\":[\".github/\",\".agents/\"]}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"github-token\":\"${{ secrets.GH_AW_WRITE_TOKEN }}\",\"max\":1},\"add_labels\":{\"github-token\":\"${{ secrets.GH_AW_WRITE_TOKEN }}\"},\"missing_data\":{},\"missing_tool\":{},\"push_to_pull_request_branch\":{\"github-token\":\"${{ secrets.GH_AW_WRITE_TOKEN }}\",\"if_no_changes\":\"warn\",\"labels\":[\"aw\"],\"max_patch_size\":1024,\"protected_files\":[\"package.json\",\"bun.lockb\",\"bunfig.toml\",\"deno.json\",\"deno.jsonc\",\"deno.lock\",\"global.json\",\"NuGet.Config\",\"Directory.Packages.props\",\"mix.exs\",\"mix.lock\",\"go.mod\",\"go.sum\",\"stack.yaml\",\"stack.yaml.lock\",\"pom.xml\",\"build.gradle\",\"build.gradle.kts\",\"settings.gradle\",\"settings.gradle.kts\",\"gradle.properties\",\"package-lock.json\",\"yarn.lock\",\"pnpm-lock.yaml\",\"npm-shrinkwrap.json\",\"requirements.txt\",\"Pipfile\",\"Pipfile.lock\",\"pyproject.toml\",\"setup.py\",\"setup.cfg\",\"Gemfile\",\"Gemfile.lock\",\"uv.lock\",\"AGENTS.md\"],\"protected_path_prefixes\":[\".github/\",\".agents/\"],\"target\":\"*\"}}" GH_AW_CI_TRIGGER_TOKEN: ${{ secrets.GH_AW_CI_TRIGGER_TOKEN }} GITHUB_TOKEN: ${{ secrets.GH_AW_WRITE_TOKEN }} with: diff --git a/.github/workflows/ci-fixer.md b/.github/workflows/ci-fixer.md index 84854e03..35a66bfb 100644 --- a/.github/workflows/ci-fixer.md +++ b/.github/workflows/ci-fixer.md @@ -13,6 +13,10 @@ permissions: pull-requests: read actions: read +checkout: + fetch: ["*"] + fetch-depth: 0 + engine: id: copilot model: claude-opus-4.6 @@ -30,6 +34,8 @@ safe-outputs: noop: report-as-issue: false push-to-pull-request-branch: + target: "*" + labels: [aw] github-token: ${{ secrets.GH_AW_WRITE_TOKEN }} add-labels: github-token: ${{ secrets.GH_AW_WRITE_TOKEN }} From 73ad68f5318b01551084ad5d7baa6f854e99e921 Mon Sep 17 00:00:00 2001 From: Sasa Junuzovic Date: Thu, 19 Mar 2026 00:01:47 -0700 Subject: [PATCH 6/9] feat: instruct responder to use REST API for reading review threads MCP tools intermittently return empty results for review data. The agent sometimes falls back to REST API on its own (PR #152) but not always (PR #158). Explicitly instruct it to use the REST API endpoints for comments and reviews. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/review-responder.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/review-responder.md b/.github/workflows/review-responder.md index c0d1a44e..f3dbc97c 100644 --- a/.github/workflows/review-responder.md +++ b/.github/workflows/review-responder.md @@ -57,7 +57,7 @@ This workflow addresses unresolved review comments on a pull request. 2. Add the label `review-response-attempted` to the PR. -3. Read the unresolved review comment threads on the PR (not just the latest review — get all unresolved threads). If there are more than 10 unresolved threads, address the first 10 and leave a summary comment on the PR noting how many remain for manual follow-up. +3. Read the unresolved review comment threads on the PR using the GitHub REST API: fetch `https://api.github.com/repos/$OWNER/$REPO/pulls/$PR_NUMBER/comments` and `https://api.github.com/repos/$OWNER/$REPO/pulls/$PR_NUMBER/reviews`. If there are more than 10 unresolved threads, address the first 10 and leave a summary comment on the PR noting how many remain for manual follow-up. 4. For each unresolved review comment thread (up to 10): a. Read the comment and understand what change is being requested From b291a66aa0b9cbd7d540a6732d09cadae1bcd249 Mon Sep 17 00:00:00 2001 From: Sasa Junuzovic Date: Tue, 17 Mar 2026 20:54:53 -0700 Subject: [PATCH 7/9] test: add responder sandbox file for testing review response Intentionally imperfect code for testing the review-responder agent. DO NOT MERGE this branch to main. --- tests/test_responder_sandbox.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 tests/test_responder_sandbox.py diff --git a/tests/test_responder_sandbox.py b/tests/test_responder_sandbox.py new file mode 100644 index 00000000..2098409b --- /dev/null +++ b/tests/test_responder_sandbox.py @@ -0,0 +1,16 @@ +# Responder Sandbox — intentionally imperfect code for testing + + +def calculate_total(lst: list[int]) -> int: + x = 0 + for i in lst: + x = x + i + return x + + +def format_output(data: list[str], verbose: bool) -> str: + result = "" + for item in data: + suffix = "\n" if verbose else ", " + result = result + str(item) + suffix + return result From 8f0d9f9288226ef93a92d279918f07fb7eafef1f Mon Sep 17 00:00:00 2001 From: Sasa Junuzovic Date: Wed, 18 Mar 2026 23:13:15 -0700 Subject: [PATCH 8/9] test: add broken function for ci-fixer testing --- tests/test_responder_sandbox.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/test_responder_sandbox.py b/tests/test_responder_sandbox.py index 2098409b..71b9f42d 100644 --- a/tests/test_responder_sandbox.py +++ b/tests/test_responder_sandbox.py @@ -2,10 +2,10 @@ def calculate_total(lst: list[int]) -> int: - x = 0 + total = 0 for i in lst: - x = x + i - return x + total = total + i + return total def format_output(data: list[str], verbose: bool) -> str: @@ -14,3 +14,7 @@ def format_output(data: list[str], verbose: bool) -> str: suffix = "\n" if verbose else ", " result = result + str(item) + suffix return result + + +def broken_function(value: int) -> str: + return value + 1 # type error: returns int, not str From 80d5003f048616cccfd5e308526078327ab42980 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 19 Mar 2026 07:13:54 +0000 Subject: [PATCH 9/9] fix: resolve CI failure (pyright reportReturnType error) Fix broken_function return type mismatch: wrap int result with str() to match declared return type. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- tests/test_responder_sandbox.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_responder_sandbox.py b/tests/test_responder_sandbox.py index 71b9f42d..30f57db0 100644 --- a/tests/test_responder_sandbox.py +++ b/tests/test_responder_sandbox.py @@ -17,4 +17,4 @@ def format_output(data: list[str], verbose: bool) -> str: def broken_function(value: int) -> str: - return value + 1 # type error: returns int, not str + return str(value + 1)