From d902ac2e7a03c25d1f3483073fd0b03cf7481ffb Mon Sep 17 00:00:00 2001 From: Elizabeth Maher Date: Thu, 2 Jul 2026 10:19:03 -0700 Subject: [PATCH 1/7] fix(squad): start coding-agent sessions for squad:copilot issues; rename go/no-go workflows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `squad:copilot` label alone never starts a Copilot coding-agent session β€” an issue must be assigned to `copilot-swe-agent[bot]` via the agent-assignment API. That assignment lives in squad-heartbeat.yml (Ralph), but it was gated off: - .squad/team.md had no `πŸ€– Coding Agent` entry and no `` marker, so the step returned early. - The step only assigned issues with zero assignees, but issue-go-yes always assigns the go:yes maintainer, so every routed issue was skipped. Fixes: - team.md: add a Coding Agent section with the auto-assign marker (also makes issue-labels-sync ensure the `squad:copilot` label exists). - squad-heartbeat.yml (active + installed template): assign the bot to any open `squad:copilot` issue that does not already have the agent, as an additional assignee alongside the human owner. Also rename the issue go/no-go decision workflows for discoverability: - issue-nogo.yml -> issue-go-no.yml ("Issue Go: No") - issue-assign.md -> issue-go-yes.md ("Issue Go: Yes") - issue-clarify.md -> issue-go-clarify.md ("Issue Go: Clarify") Display names set via gh-aw frontmatter `name:`; agentic .lock.yml recompiled. NOTE: requires a COPILOT_ASSIGN_TOKEN repo secret (a PAT that can assign the coding agent) for the assignment step to succeed. Refs #194 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- ...ify.lock.yml => issue-go-clarify.lock.yml} | 104 +++++++++--------- .../{issue-clarify.md => issue-go-clarify.md} | 1 + .../{issue-nogo.yml => issue-go-no.yml} | 2 +- ...-assign.lock.yml => issue-go-yes.lock.yml} | 104 +++++++++--------- .../{issue-assign.md => issue-go-yes.md} | 1 + .github/workflows/squad-heartbeat.yml | 17 ++- .squad/team.md | 14 +++ .../templates/workflows/squad-heartbeat.yml | 17 ++- 8 files changed, 145 insertions(+), 115 deletions(-) rename .github/workflows/{issue-clarify.lock.yml => issue-go-clarify.lock.yml} (97%) rename .github/workflows/{issue-clarify.md => issue-go-clarify.md} (99%) rename .github/workflows/{issue-nogo.yml => issue-go-no.yml} (99%) rename .github/workflows/{issue-assign.lock.yml => issue-go-yes.lock.yml} (97%) rename .github/workflows/{issue-assign.md => issue-go-yes.md} (99%) diff --git a/.github/workflows/issue-clarify.lock.yml b/.github/workflows/issue-go-clarify.lock.yml similarity index 97% rename from .github/workflows/issue-clarify.lock.yml rename to .github/workflows/issue-go-clarify.lock.yml index 88b8063c..d980227b 100644 --- a/.github/workflows/issue-clarify.lock.yml +++ b/.github/workflows/issue-go-clarify.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"9d0b2133c80e50579d02c3c6de29c15526822f5bd5eb0894bed614bd2d14700a","body_hash":"e0bda517a121787eedd565136e0527cfdb092404f4a9ad76fbf2c38ef2a5378a","compiler_version":"v0.81.6","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.65"}} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"2d4bfb2a89483076e06f94eb9df8ed8c34e1ff45b3da94c7caeb6440d4ce4bdc","body_hash":"e0bda517a121787eedd565136e0527cfdb092404f4a9ad76fbf2c38ef2a5378a","compiler_version":"v0.81.6","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.65"}} # gh-aw-manifest: {"version":1,"secrets":["GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0","version":"v7.0.0"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/github-script","sha":"ed597411d8f924073f98dfc5c65a23a2325f34cd","version":"v8"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"ba6380cc6e5be5d21677bebe04d52fb48e3abec7","version":"v0.81.6"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.11","digest":"sha256:979723c628182da7729333f2208bb249fd25ddee579645cf9a3892d681a929c7","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.11@sha256:979723c628182da7729333f2208bb249fd25ddee579645cf9a3892d681a929c7"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.11","digest":"sha256:807e4831999b44513b0a66e5859d478dc4da7ae74ab1918cec967d513f95bf9d","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.11@sha256:807e4831999b44513b0a66e5859d478dc4da7ae74ab1918cec967d513f95bf9d"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.11","digest":"sha256:ff27ea0525ad953a6adee28a5fbe9d2e22be47dbec755c15767af4ea3f91df7d","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.11@sha256:ff27ea0525ad953a6adee28a5fbe9d2e22be47dbec755c15767af4ea3f91df7d"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.30","digest":"sha256:35625d1a2269b1238606078c879f59a91cffc4ac33eb54bf39c6418822c1a8be","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.30@sha256:35625d1a2269b1238606078c879f59a91cffc4ac33eb54bf39c6418822c1a8be"},{"image":"ghcr.io/github/gh-aw-node","digest":"sha256:529d02eb970b1161aa25c593a9c3df57fdfad5a8add328cb3b6eccef66f3183b","pinned_image":"ghcr.io/github/gh-aw-node@sha256:529d02eb970b1161aa25c593a9c3df57fdfad5a8add328cb3b6eccef66f3183b"},{"image":"ghcr.io/github/github-mcp-server:v1.4.0","digest":"sha256:2afb26356481d1a350e14544a6e160f7f7ec1561a1ea309b823665abf0309036","pinned_image":"ghcr.io/github/github-mcp-server:v1.4.0@sha256:2afb26356481d1a350e14544a6e160f7f7ec1561a1ea309b823665abf0309036"}]} # This file was automatically generated by gh-aw (v0.81.6). DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md # @@ -50,7 +50,7 @@ # - ghcr.io/github/gh-aw-node@sha256:529d02eb970b1161aa25c593a9c3df57fdfad5a8add328cb3b6eccef66f3183b # - ghcr.io/github/github-mcp-server:v1.4.0@sha256:2afb26356481d1a350e14544a6e160f7f7ec1561a1ea309b823665abf0309036 -name: "Issue Clarification Agent" +name: "Issue Go: Clarify" on: issues: # names: # Label filtering applied via job conditions @@ -66,7 +66,7 @@ permissions: {} concurrency: group: "gh-aw-${{ github.workflow }}-${{ github.event.issue.number || github.run_id }}" -run-name: "Issue Clarification Agent" +run-name: "Issue Go: Clarify" jobs: activation: @@ -108,8 +108,8 @@ jobs: parent-span-id: ${{ needs.pre_activation.outputs.setup-parent-span-id || needs.pre_activation.outputs.setup-span-id }} safe-output-artifact-client: ${{ env.GH_AW_MAX_DAILY_AI_CREDITS != '' }} env: - GH_AW_SETUP_WORKFLOW_NAME: "Issue Clarification Agent" - GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-clarify.lock.yml@${{ github.ref }} + GH_AW_SETUP_WORKFLOW_NAME: "Issue Go: Clarify" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-go-clarify.lock.yml@${{ github.ref }} GH_AW_INFO_VERSION: "1.0.65" GH_AW_INFO_AWF_VERSION: "v0.27.11" GH_AW_INFO_ENGINE_ID: "copilot" @@ -122,7 +122,7 @@ jobs: GH_AW_INFO_VERSION: "1.0.65" GH_AW_INFO_AGENT_VERSION: "1.0.65" GH_AW_INFO_CLI_VERSION: "v0.81.6" - GH_AW_INFO_WORKFLOW_NAME: "Issue Clarification Agent" + GH_AW_INFO_WORKFLOW_NAME: "Issue Go: Clarify" GH_AW_INFO_EXPERIMENTAL: "false" GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true" GH_AW_INFO_STAGED: "false" @@ -145,8 +145,8 @@ jobs: continue-on-error: true uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: - key: agentic-workflow-usage-issueclarify-${{ github.run_id }} - restore-keys: agentic-workflow-usage-issueclarify- + key: agentic-workflow-usage-issuegoclarify-${{ github.run_id }} + restore-keys: agentic-workflow-usage-issuegoclarify- path: /tmp/gh-aw/agentic-workflow-usage-cache.jsonl - name: Restore daily AIC usage cache (artifact fallback) id: restore-daily-aic-cache-fallback @@ -168,8 +168,8 @@ jobs: if: ${{ env.GH_AW_MAX_DAILY_AI_CREDITS != '' }} uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: - GH_AW_WORKFLOW_NAME: "Issue Clarification Agent" - GH_AW_WORKFLOW_ID: "issue-clarify" + GH_AW_WORKFLOW_NAME: "Issue Go: Clarify" + GH_AW_WORKFLOW_ID: "issue-go-clarify" GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} GH_AW_WORKFLOW_DISPATCH_AW_CONTEXT: ${{ github.event.inputs.aw_context || '' }} GH_AW_HAS_SLASH_COMMAND: "false" @@ -209,7 +209,7 @@ jobs: id: check-lock-file uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: - GH_AW_WORKFLOW_FILE: "issue-clarify.lock.yml" + GH_AW_WORKFLOW_FILE: "issue-go-clarify.lock.yml" GH_AW_CONTEXT_WORKFLOW_REF: "${{ github.workflow_ref }}" with: script: | @@ -257,20 +257,20 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_83120a125fdba03a_EOF' + cat << 'GH_AW_PROMPT_01bd8eba433163e9_EOF' - GH_AW_PROMPT_83120a125fdba03a_EOF + GH_AW_PROMPT_01bd8eba433163e9_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_83120a125fdba03a_EOF' + cat << 'GH_AW_PROMPT_01bd8eba433163e9_EOF' Tools: add_comment, missing_tool, missing_data, noop - GH_AW_PROMPT_83120a125fdba03a_EOF + GH_AW_PROMPT_01bd8eba433163e9_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" - cat << 'GH_AW_PROMPT_83120a125fdba03a_EOF' + cat << 'GH_AW_PROMPT_01bd8eba433163e9_EOF' The following GitHub context information is available for this workflow: {{#if github.actor}} @@ -299,12 +299,12 @@ jobs: {{/if}} - GH_AW_PROMPT_83120a125fdba03a_EOF + GH_AW_PROMPT_01bd8eba433163e9_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_83120a125fdba03a_EOF' + cat << 'GH_AW_PROMPT_01bd8eba433163e9_EOF' - {{#runtime-import .github/workflows/issue-clarify.md}} - GH_AW_PROMPT_83120a125fdba03a_EOF + {{#runtime-import .github/workflows/issue-go-clarify.md}} + GH_AW_PROMPT_01bd8eba433163e9_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -398,7 +398,7 @@ jobs: GH_AW_ASSETS_MAX_SIZE_KB: 0 GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }} - GH_AW_WORKFLOW_ID_SANITIZED: issueclarify + GH_AW_WORKFLOW_ID_SANITIZED: issuegoclarify outputs: agentic_engine_timeout: ${{ steps.detect-agent-errors.outputs.agentic_engine_timeout || 'false' }} ai_credits_rate_limit_error: ${{ steps.parse-mcp-gateway.outputs.ai_credits_rate_limit_error || 'false' }} @@ -427,8 +427,8 @@ jobs: trace-id: ${{ needs.activation.outputs.setup-trace-id }} parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }} env: - GH_AW_SETUP_WORKFLOW_NAME: "Issue Clarification Agent" - GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-clarify.lock.yml@${{ github.ref }} + GH_AW_SETUP_WORKFLOW_NAME: "Issue Go: Clarify" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-go-clarify.lock.yml@${{ github.ref }} GH_AW_INFO_VERSION: "1.0.65" GH_AW_INFO_AWF_VERSION: "v0.27.11" GH_AW_INFO_ENGINE_ID: "copilot" @@ -999,7 +999,7 @@ jobs: issues: write pull-requests: write concurrency: - group: "gh-aw-conclusion-issue-clarify" + group: "gh-aw-conclusion-issue-go-clarify" cancel-in-progress: false queue: max env: @@ -1019,8 +1019,8 @@ jobs: trace-id: ${{ needs.activation.outputs.setup-trace-id }} parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }} env: - GH_AW_SETUP_WORKFLOW_NAME: "Issue Clarification Agent" - GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-clarify.lock.yml@${{ github.ref }} + GH_AW_SETUP_WORKFLOW_NAME: "Issue Go: Clarify" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-go-clarify.lock.yml@${{ github.ref }} GH_AW_INFO_VERSION: "1.0.65" GH_AW_INFO_AWF_VERSION: "v0.27.11" GH_AW_INFO_ENGINE_ID: "copilot" @@ -1087,8 +1087,8 @@ jobs: continue-on-error: true uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: - key: agentic-workflow-usage-issueclarify-${{ github.run_id }} - restore-keys: agentic-workflow-usage-issueclarify- + key: agentic-workflow-usage-issuegoclarify-${{ github.run_id }} + restore-keys: agentic-workflow-usage-issuegoclarify- path: /tmp/gh-aw/agentic-workflow-usage-cache.jsonl - name: Write daily AIC usage cache entry id: write-daily-aic-cache @@ -1108,7 +1108,7 @@ jobs: continue-on-error: true uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: - key: agentic-workflow-usage-issueclarify-${{ github.run_id }} + key: agentic-workflow-usage-issuegoclarify-${{ github.run_id }} path: /tmp/gh-aw/agentic-workflow-usage-cache.jsonl - name: Upload daily AIC usage cache artifact id: upload-daily-aic-cache @@ -1126,15 +1126,15 @@ jobs: env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} GH_AW_NOOP_MAX: "1" - GH_AW_WORKFLOW_NAME: "Issue Clarification Agent" - GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-clarify.md" + GH_AW_WORKFLOW_NAME: "Issue Go: Clarify" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-go-clarify.md" GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} GH_AW_NOOP_REPORT_AS_ISSUE: "true" GH_AW_AIC: ${{ needs.agent.outputs.aic }} GH_AW_THREAT_DETECTION_AIC: ${{ needs.detection.outputs.aic }} GH_AW_AMBIENT_CONTEXT: ${{ needs.agent.outputs.ambient_context }} - GH_AW_WORKFLOW_ID: "issue-clarify" + GH_AW_WORKFLOW_ID: "issue-go-clarify" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | @@ -1147,8 +1147,8 @@ jobs: uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "Issue Clarification Agent" - GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-clarify.md" + GH_AW_WORKFLOW_NAME: "Issue Go: Clarify" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-go-clarify.md" GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} GH_AW_DETECTION_CONCLUSION: ${{ needs.detection.outputs.detection_conclusion }} GH_AW_DETECTION_REASON: ${{ needs.detection.outputs.detection_reason }} @@ -1165,8 +1165,8 @@ jobs: env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} GH_AW_MISSING_TOOL_CREATE_ISSUE: "true" - GH_AW_WORKFLOW_NAME: "Issue Clarification Agent" - GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-clarify.md" + GH_AW_WORKFLOW_NAME: "Issue Go: Clarify" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-go-clarify.md" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | @@ -1180,8 +1180,8 @@ jobs: env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} GH_AW_REPORT_INCOMPLETE_CREATE_ISSUE: "true" - GH_AW_WORKFLOW_NAME: "Issue Clarification Agent" - GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-clarify.md" + GH_AW_WORKFLOW_NAME: "Issue Go: Clarify" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-go-clarify.md" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | @@ -1195,11 +1195,11 @@ jobs: uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "Issue Clarification Agent" - GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-clarify.md" + GH_AW_WORKFLOW_NAME: "Issue Go: Clarify" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-go-clarify.md" GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} - GH_AW_WORKFLOW_ID: "issue-clarify" + GH_AW_WORKFLOW_ID: "issue-go-clarify" GH_AW_ACTION_FAILURE_ISSUE_EXPIRES_HOURS: "168" GH_AW_ENGINE_ID: "copilot" GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} @@ -1258,8 +1258,8 @@ jobs: trace-id: ${{ needs.activation.outputs.setup-trace-id }} parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }} env: - GH_AW_SETUP_WORKFLOW_NAME: "Issue Clarification Agent" - GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-clarify.lock.yml@${{ github.ref }} + GH_AW_SETUP_WORKFLOW_NAME: "Issue Go: Clarify" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-go-clarify.lock.yml@${{ github.ref }} GH_AW_INFO_VERSION: "1.0.65" GH_AW_INFO_AWF_VERSION: "v0.27.11" GH_AW_INFO_ENGINE_ID: "copilot" @@ -1331,7 +1331,7 @@ jobs: if: always() && steps.detection_guard.outputs.run_detection == 'true' uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: - WORKFLOW_NAME: "Issue Clarification Agent" + WORKFLOW_NAME: "Issue Go: Clarify" WORKFLOW_DESCRIPTION: "When a maintainer marks an issue go:needs-research, help scope it by asking focused clarifying questions β€” but only if the maintainer has not already asked them. If the maintainer has posted clarifying questions, sharpen or de-ambiguate those instead. Posts at most one comment." HAS_PATCH: ${{ needs.agent.outputs.has_patch }} with: @@ -1499,8 +1499,8 @@ jobs: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} env: - GH_AW_SETUP_WORKFLOW_NAME: "Issue Clarification Agent" - GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-clarify.lock.yml@${{ github.ref }} + GH_AW_SETUP_WORKFLOW_NAME: "Issue Go: Clarify" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-go-clarify.lock.yml@${{ github.ref }} GH_AW_INFO_VERSION: "1.0.65" GH_AW_INFO_AWF_VERSION: "v0.27.11" GH_AW_INFO_ENGINE_ID: "copilot" @@ -1533,7 +1533,7 @@ jobs: GH_AW_AGENT_AIC: ${{ needs.agent.outputs.aic }} GH_AW_AIC: ${{ needs.agent.outputs.aic }} GH_AW_AMBIENT_CONTEXT: ${{ needs.agent.outputs.ambient_context }} - GH_AW_CALLER_WORKFLOW_ID: "${{ github.repository }}/issue-clarify" + GH_AW_CALLER_WORKFLOW_ID: "${{ github.repository }}/issue-go-clarify" GH_AW_DETECTION_CONCLUSION: ${{ needs.detection.outputs.detection_conclusion }} GH_AW_DETECTION_REASON: ${{ needs.detection.outputs.detection_reason }} GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens }} @@ -1542,9 +1542,9 @@ jobs: GH_AW_ENGINE_VERSION: "1.0.65" GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }} GH_AW_THREAT_DETECTION_AIC: ${{ needs.detection.outputs.aic }} - GH_AW_WORKFLOW_ID: "issue-clarify" - GH_AW_WORKFLOW_NAME: "Issue Clarification Agent" - GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-clarify.md" + GH_AW_WORKFLOW_ID: "issue-go-clarify" + GH_AW_WORKFLOW_NAME: "Issue Go: Clarify" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-go-clarify.md" outputs: code_push_failure_count: ${{ steps.process_safe_outputs.outputs.code_push_failure_count }} code_push_failure_errors: ${{ steps.process_safe_outputs.outputs.code_push_failure_errors }} @@ -1564,8 +1564,8 @@ jobs: trace-id: ${{ needs.activation.outputs.setup-trace-id }} parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }} env: - GH_AW_SETUP_WORKFLOW_NAME: "Issue Clarification Agent" - GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-clarify.lock.yml@${{ github.ref }} + GH_AW_SETUP_WORKFLOW_NAME: "Issue Go: Clarify" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-go-clarify.lock.yml@${{ github.ref }} GH_AW_INFO_VERSION: "1.0.65" GH_AW_INFO_AWF_VERSION: "v0.27.11" GH_AW_INFO_ENGINE_ID: "copilot" diff --git a/.github/workflows/issue-clarify.md b/.github/workflows/issue-go-clarify.md similarity index 99% rename from .github/workflows/issue-clarify.md rename to .github/workflows/issue-go-clarify.md index ca1ef4ea..1a3693bf 100644 --- a/.github/workflows/issue-clarify.md +++ b/.github/workflows/issue-go-clarify.md @@ -1,4 +1,5 @@ --- +name: "Issue Go: Clarify" description: > When a maintainer marks an issue go:needs-research, help scope it by asking focused clarifying questions β€” but only if the maintainer has not already asked them. If the diff --git a/.github/workflows/issue-nogo.yml b/.github/workflows/issue-go-no.yml similarity index 99% rename from .github/workflows/issue-nogo.yml rename to .github/workflows/issue-go-no.yml index 724a2213..233c1f13 100644 --- a/.github/workflows/issue-nogo.yml +++ b/.github/workflows/issue-go-no.yml @@ -1,4 +1,4 @@ -name: Issue No-Go +name: "Issue Go: No" # Deterministic Workflow: No-Go decision # Trigger: a maintainer applies the "go:no" label to reject an issue. diff --git a/.github/workflows/issue-assign.lock.yml b/.github/workflows/issue-go-yes.lock.yml similarity index 97% rename from .github/workflows/issue-assign.lock.yml rename to .github/workflows/issue-go-yes.lock.yml index 3cdc5c0c..874a641e 100644 --- a/.github/workflows/issue-assign.lock.yml +++ b/.github/workflows/issue-go-yes.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"60ddfea64f983982e7da70bac227d0bb086de48fd814a6cd6556a22bb6322c84","body_hash":"dab8fe99999fed7d1ef283d6f6a0046aa81ebdda3b72e54fe2b83705f3922bd9","compiler_version":"v0.81.6","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.65"}} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"41f29a749e0bf3667089ac45d06e6adbba2a37f9fff0c8ece29faad09aa22e1d","body_hash":"dab8fe99999fed7d1ef283d6f6a0046aa81ebdda3b72e54fe2b83705f3922bd9","compiler_version":"v0.81.6","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.65"}} # gh-aw-manifest: {"version":1,"secrets":["GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0","version":"v7.0.0"},{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3 (source v6)"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/github-script","sha":"ed597411d8f924073f98dfc5c65a23a2325f34cd","version":"v8"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"ba6380cc6e5be5d21677bebe04d52fb48e3abec7","version":"v0.81.6"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.11","digest":"sha256:979723c628182da7729333f2208bb249fd25ddee579645cf9a3892d681a929c7","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.11@sha256:979723c628182da7729333f2208bb249fd25ddee579645cf9a3892d681a929c7"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.11","digest":"sha256:807e4831999b44513b0a66e5859d478dc4da7ae74ab1918cec967d513f95bf9d","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.11@sha256:807e4831999b44513b0a66e5859d478dc4da7ae74ab1918cec967d513f95bf9d"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.11","digest":"sha256:ff27ea0525ad953a6adee28a5fbe9d2e22be47dbec755c15767af4ea3f91df7d","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.11@sha256:ff27ea0525ad953a6adee28a5fbe9d2e22be47dbec755c15767af4ea3f91df7d"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.30","digest":"sha256:35625d1a2269b1238606078c879f59a91cffc4ac33eb54bf39c6418822c1a8be","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.30@sha256:35625d1a2269b1238606078c879f59a91cffc4ac33eb54bf39c6418822c1a8be"},{"image":"ghcr.io/github/gh-aw-node","digest":"sha256:529d02eb970b1161aa25c593a9c3df57fdfad5a8add328cb3b6eccef66f3183b","pinned_image":"ghcr.io/github/gh-aw-node@sha256:529d02eb970b1161aa25c593a9c3df57fdfad5a8add328cb3b6eccef66f3183b"},{"image":"ghcr.io/github/github-mcp-server:v1.4.0","digest":"sha256:2afb26356481d1a350e14544a6e160f7f7ec1561a1ea309b823665abf0309036","pinned_image":"ghcr.io/github/github-mcp-server:v1.4.0@sha256:2afb26356481d1a350e14544a6e160f7f7ec1561a1ea309b823665abf0309036"}]} # This file was automatically generated by gh-aw (v0.81.6). DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md # @@ -51,7 +51,7 @@ # - ghcr.io/github/gh-aw-node@sha256:529d02eb970b1161aa25c593a9c3df57fdfad5a8add328cb3b6eccef66f3183b # - ghcr.io/github/github-mcp-server:v1.4.0@sha256:2afb26356481d1a350e14544a6e160f7f7ec1561a1ea309b823665abf0309036 -name: "Issue Assignment Agent" +name: "Issue Go: Yes" on: issues: # names: # Label filtering applied via job conditions @@ -67,7 +67,7 @@ permissions: {} concurrency: group: "gh-aw-${{ github.workflow }}-${{ github.event.issue.number || github.run_id }}" -run-name: "Issue Assignment Agent" +run-name: "Issue Go: Yes" jobs: activation: @@ -109,8 +109,8 @@ jobs: parent-span-id: ${{ needs.pre_activation.outputs.setup-parent-span-id || needs.pre_activation.outputs.setup-span-id }} safe-output-artifact-client: ${{ env.GH_AW_MAX_DAILY_AI_CREDITS != '' }} env: - GH_AW_SETUP_WORKFLOW_NAME: "Issue Assignment Agent" - GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-assign.lock.yml@${{ github.ref }} + GH_AW_SETUP_WORKFLOW_NAME: "Issue Go: Yes" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-go-yes.lock.yml@${{ github.ref }} GH_AW_INFO_VERSION: "1.0.65" GH_AW_INFO_AWF_VERSION: "v0.27.11" GH_AW_INFO_ENGINE_ID: "copilot" @@ -123,7 +123,7 @@ jobs: GH_AW_INFO_VERSION: "1.0.65" GH_AW_INFO_AGENT_VERSION: "1.0.65" GH_AW_INFO_CLI_VERSION: "v0.81.6" - GH_AW_INFO_WORKFLOW_NAME: "Issue Assignment Agent" + GH_AW_INFO_WORKFLOW_NAME: "Issue Go: Yes" GH_AW_INFO_EXPERIMENTAL: "false" GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true" GH_AW_INFO_STAGED: "false" @@ -146,8 +146,8 @@ jobs: continue-on-error: true uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: - key: agentic-workflow-usage-issueassign-${{ github.run_id }} - restore-keys: agentic-workflow-usage-issueassign- + key: agentic-workflow-usage-issuegoyes-${{ github.run_id }} + restore-keys: agentic-workflow-usage-issuegoyes- path: /tmp/gh-aw/agentic-workflow-usage-cache.jsonl - name: Restore daily AIC usage cache (artifact fallback) id: restore-daily-aic-cache-fallback @@ -169,8 +169,8 @@ jobs: if: ${{ env.GH_AW_MAX_DAILY_AI_CREDITS != '' }} uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: - GH_AW_WORKFLOW_NAME: "Issue Assignment Agent" - GH_AW_WORKFLOW_ID: "issue-assign" + GH_AW_WORKFLOW_NAME: "Issue Go: Yes" + GH_AW_WORKFLOW_ID: "issue-go-yes" GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} GH_AW_WORKFLOW_DISPATCH_AW_CONTEXT: ${{ github.event.inputs.aw_context || '' }} GH_AW_HAS_SLASH_COMMAND: "false" @@ -210,7 +210,7 @@ jobs: id: check-lock-file uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: - GH_AW_WORKFLOW_FILE: "issue-assign.lock.yml" + GH_AW_WORKFLOW_FILE: "issue-go-yes.lock.yml" GH_AW_CONTEXT_WORKFLOW_REF: "${{ github.workflow_ref }}" with: script: | @@ -258,20 +258,20 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_c55537d93244191d_EOF' + cat << 'GH_AW_PROMPT_793180f3809d79e2_EOF' - GH_AW_PROMPT_c55537d93244191d_EOF + GH_AW_PROMPT_793180f3809d79e2_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_c55537d93244191d_EOF' + cat << 'GH_AW_PROMPT_793180f3809d79e2_EOF' Tools: add_comment, add_labels(max:5), assign_to_user, missing_tool, missing_data, noop - GH_AW_PROMPT_c55537d93244191d_EOF + GH_AW_PROMPT_793180f3809d79e2_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" - cat << 'GH_AW_PROMPT_c55537d93244191d_EOF' + cat << 'GH_AW_PROMPT_793180f3809d79e2_EOF' The following GitHub context information is available for this workflow: {{#if github.actor}} @@ -300,12 +300,12 @@ jobs: {{/if}} - GH_AW_PROMPT_c55537d93244191d_EOF + GH_AW_PROMPT_793180f3809d79e2_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_c55537d93244191d_EOF' + cat << 'GH_AW_PROMPT_793180f3809d79e2_EOF' - {{#runtime-import .github/workflows/issue-assign.md}} - GH_AW_PROMPT_c55537d93244191d_EOF + {{#runtime-import .github/workflows/issue-go-yes.md}} + GH_AW_PROMPT_793180f3809d79e2_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -399,7 +399,7 @@ jobs: GH_AW_ASSETS_MAX_SIZE_KB: 0 GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }} - GH_AW_WORKFLOW_ID_SANITIZED: issueassign + GH_AW_WORKFLOW_ID_SANITIZED: issuegoyes outputs: agentic_engine_timeout: ${{ steps.detect-agent-errors.outputs.agentic_engine_timeout || 'false' }} ai_credits_rate_limit_error: ${{ steps.parse-mcp-gateway.outputs.ai_credits_rate_limit_error || 'false' }} @@ -428,8 +428,8 @@ jobs: trace-id: ${{ needs.activation.outputs.setup-trace-id }} parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }} env: - GH_AW_SETUP_WORKFLOW_NAME: "Issue Assignment Agent" - GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-assign.lock.yml@${{ github.ref }} + GH_AW_SETUP_WORKFLOW_NAME: "Issue Go: Yes" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-go-yes.lock.yml@${{ github.ref }} GH_AW_INFO_VERSION: "1.0.65" GH_AW_INFO_AWF_VERSION: "v0.27.11" GH_AW_INFO_ENGINE_ID: "copilot" @@ -1041,7 +1041,7 @@ jobs: issues: write pull-requests: write concurrency: - group: "gh-aw-conclusion-issue-assign" + group: "gh-aw-conclusion-issue-go-yes" cancel-in-progress: false queue: max env: @@ -1061,8 +1061,8 @@ jobs: trace-id: ${{ needs.activation.outputs.setup-trace-id }} parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }} env: - GH_AW_SETUP_WORKFLOW_NAME: "Issue Assignment Agent" - GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-assign.lock.yml@${{ github.ref }} + GH_AW_SETUP_WORKFLOW_NAME: "Issue Go: Yes" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-go-yes.lock.yml@${{ github.ref }} GH_AW_INFO_VERSION: "1.0.65" GH_AW_INFO_AWF_VERSION: "v0.27.11" GH_AW_INFO_ENGINE_ID: "copilot" @@ -1129,8 +1129,8 @@ jobs: continue-on-error: true uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: - key: agentic-workflow-usage-issueassign-${{ github.run_id }} - restore-keys: agentic-workflow-usage-issueassign- + key: agentic-workflow-usage-issuegoyes-${{ github.run_id }} + restore-keys: agentic-workflow-usage-issuegoyes- path: /tmp/gh-aw/agentic-workflow-usage-cache.jsonl - name: Write daily AIC usage cache entry id: write-daily-aic-cache @@ -1150,7 +1150,7 @@ jobs: continue-on-error: true uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: - key: agentic-workflow-usage-issueassign-${{ github.run_id }} + key: agentic-workflow-usage-issuegoyes-${{ github.run_id }} path: /tmp/gh-aw/agentic-workflow-usage-cache.jsonl - name: Upload daily AIC usage cache artifact id: upload-daily-aic-cache @@ -1168,15 +1168,15 @@ jobs: env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} GH_AW_NOOP_MAX: "1" - GH_AW_WORKFLOW_NAME: "Issue Assignment Agent" - GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-assign.md" + GH_AW_WORKFLOW_NAME: "Issue Go: Yes" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-go-yes.md" GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} GH_AW_NOOP_REPORT_AS_ISSUE: "true" GH_AW_AIC: ${{ needs.agent.outputs.aic }} GH_AW_THREAT_DETECTION_AIC: ${{ needs.detection.outputs.aic }} GH_AW_AMBIENT_CONTEXT: ${{ needs.agent.outputs.ambient_context }} - GH_AW_WORKFLOW_ID: "issue-assign" + GH_AW_WORKFLOW_ID: "issue-go-yes" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | @@ -1189,8 +1189,8 @@ jobs: uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "Issue Assignment Agent" - GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-assign.md" + GH_AW_WORKFLOW_NAME: "Issue Go: Yes" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-go-yes.md" GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} GH_AW_DETECTION_CONCLUSION: ${{ needs.detection.outputs.detection_conclusion }} GH_AW_DETECTION_REASON: ${{ needs.detection.outputs.detection_reason }} @@ -1207,8 +1207,8 @@ jobs: env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} GH_AW_MISSING_TOOL_CREATE_ISSUE: "true" - GH_AW_WORKFLOW_NAME: "Issue Assignment Agent" - GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-assign.md" + GH_AW_WORKFLOW_NAME: "Issue Go: Yes" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-go-yes.md" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | @@ -1222,8 +1222,8 @@ jobs: env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} GH_AW_REPORT_INCOMPLETE_CREATE_ISSUE: "true" - GH_AW_WORKFLOW_NAME: "Issue Assignment Agent" - GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-assign.md" + GH_AW_WORKFLOW_NAME: "Issue Go: Yes" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-go-yes.md" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | @@ -1237,11 +1237,11 @@ jobs: uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "Issue Assignment Agent" - GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-assign.md" + GH_AW_WORKFLOW_NAME: "Issue Go: Yes" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-go-yes.md" GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} - GH_AW_WORKFLOW_ID: "issue-assign" + GH_AW_WORKFLOW_ID: "issue-go-yes" GH_AW_ACTION_FAILURE_ISSUE_EXPIRES_HOURS: "168" GH_AW_ENGINE_ID: "copilot" GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} @@ -1300,8 +1300,8 @@ jobs: trace-id: ${{ needs.activation.outputs.setup-trace-id }} parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }} env: - GH_AW_SETUP_WORKFLOW_NAME: "Issue Assignment Agent" - GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-assign.lock.yml@${{ github.ref }} + GH_AW_SETUP_WORKFLOW_NAME: "Issue Go: Yes" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-go-yes.lock.yml@${{ github.ref }} GH_AW_INFO_VERSION: "1.0.65" GH_AW_INFO_AWF_VERSION: "v0.27.11" GH_AW_INFO_ENGINE_ID: "copilot" @@ -1373,7 +1373,7 @@ jobs: if: always() && steps.detection_guard.outputs.run_detection == 'true' uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: - WORKFLOW_NAME: "Issue Assignment Agent" + WORKFLOW_NAME: "Issue Go: Yes" WORKFLOW_DESCRIPTION: "Assign an approved issue (go:yes) to the maintainer who approved it and route it to squad areas. Reads the prior triage analysis and the squad routing table, applies the squad label plus matched squad:{member} labels (and squad:copilot to hand the issue off to the Copilot coding agent), and posts an assignment rationale comment." HAS_PATCH: ${{ needs.agent.outputs.has_patch }} with: @@ -1617,8 +1617,8 @@ jobs: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} env: - GH_AW_SETUP_WORKFLOW_NAME: "Issue Assignment Agent" - GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-assign.lock.yml@${{ github.ref }} + GH_AW_SETUP_WORKFLOW_NAME: "Issue Go: Yes" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-go-yes.lock.yml@${{ github.ref }} GH_AW_INFO_VERSION: "1.0.65" GH_AW_INFO_AWF_VERSION: "v0.27.11" GH_AW_INFO_ENGINE_ID: "copilot" @@ -1651,7 +1651,7 @@ jobs: GH_AW_AGENT_AIC: ${{ needs.agent.outputs.aic }} GH_AW_AIC: ${{ needs.agent.outputs.aic }} GH_AW_AMBIENT_CONTEXT: ${{ needs.agent.outputs.ambient_context }} - GH_AW_CALLER_WORKFLOW_ID: "${{ github.repository }}/issue-assign" + GH_AW_CALLER_WORKFLOW_ID: "${{ github.repository }}/issue-go-yes" GH_AW_DETECTION_CONCLUSION: ${{ needs.detection.outputs.detection_conclusion }} GH_AW_DETECTION_REASON: ${{ needs.detection.outputs.detection_reason }} GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens }} @@ -1660,9 +1660,9 @@ jobs: GH_AW_ENGINE_VERSION: "1.0.65" GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }} GH_AW_THREAT_DETECTION_AIC: ${{ needs.detection.outputs.aic }} - GH_AW_WORKFLOW_ID: "issue-assign" - GH_AW_WORKFLOW_NAME: "Issue Assignment Agent" - GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-assign.md" + GH_AW_WORKFLOW_ID: "issue-go-yes" + GH_AW_WORKFLOW_NAME: "Issue Go: Yes" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-go-yes.md" outputs: assign_to_user_assigned: ${{ steps.process_safe_outputs.outputs.assigned }} code_push_failure_count: ${{ steps.process_safe_outputs.outputs.code_push_failure_count }} @@ -1683,8 +1683,8 @@ jobs: trace-id: ${{ needs.activation.outputs.setup-trace-id }} parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }} env: - GH_AW_SETUP_WORKFLOW_NAME: "Issue Assignment Agent" - GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-assign.lock.yml@${{ github.ref }} + GH_AW_SETUP_WORKFLOW_NAME: "Issue Go: Yes" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-go-yes.lock.yml@${{ github.ref }} GH_AW_INFO_VERSION: "1.0.65" GH_AW_INFO_AWF_VERSION: "v0.27.11" GH_AW_INFO_ENGINE_ID: "copilot" diff --git a/.github/workflows/issue-assign.md b/.github/workflows/issue-go-yes.md similarity index 99% rename from .github/workflows/issue-assign.md rename to .github/workflows/issue-go-yes.md index 813975cb..dba84b93 100644 --- a/.github/workflows/issue-assign.md +++ b/.github/workflows/issue-go-yes.md @@ -1,4 +1,5 @@ --- +name: "Issue Go: Yes" description: > Assign an approved issue (go:yes) to the maintainer who approved it and route it to squad areas. Reads the prior triage analysis and the squad routing table, applies the diff --git a/.github/workflows/squad-heartbeat.yml b/.github/workflows/squad-heartbeat.yml index 5a70db11..3595845d 100644 --- a/.github/workflows/squad-heartbeat.yml +++ b/.github/workflows/squad-heartbeat.yml @@ -129,12 +129,19 @@ jobs: per_page: 5 }); - const unassigned = copilotIssues.filter(i => - !i.assignees || i.assignees.length === 0 + // Include issues that don't yet have the coding agent assigned. + // issue-go-yes always assigns the go:yes maintainer as owner, so an + // issue almost always has a (human) assignee β€” filtering on "zero + // assignees" would skip every routed issue. Filter on the agent's + // presence instead; the POST below ADDS the bot as an extra assignee + // without removing the human owner. + const COPILOT_LOGINS = ['copilot-swe-agent[bot]', 'copilot-swe-agent', 'Copilot']; + const needsAgent = copilotIssues.filter(i => + !(i.assignees || []).some(a => COPILOT_LOGINS.includes(a.login)) ); - if (unassigned.length === 0) { - core.info('No unassigned squad:copilot issues'); + if (needsAgent.length === 0) { + core.info('No squad:copilot issues awaiting the coding agent'); return; } @@ -144,7 +151,7 @@ jobs: repo: context.repo.repo }); - for (const issue of unassigned) { + for (const issue of needsAgent) { try { await github.request('POST /repos/{owner}/{repo}/issues/{issue_number}/assignees', { owner: context.repo.owner, diff --git a/.squad/team.md b/.squad/team.md index f4088c90..c40ad98e 100644 --- a/.squad/team.md +++ b/.squad/team.md @@ -26,6 +26,20 @@ | SecurityExpert | πŸ”’ Security Expert | [charter](.squad/agents/securityexpert/charter.md) | βœ… Active | | Ralph | πŸ”„ Work Monitor | β€” | βœ… Active | +## Coding Agent + + + +GitHub's Copilot coding agent (`@copilot`) autonomously implements issues labeled +`squad:copilot`. Ralph (`squad-heartbeat.yml`) assigns `copilot-swe-agent[bot]` to +every open `squad:copilot` issue that does not already have the agent assigned β€” +in addition to the human maintainer who owns it β€” which is what actually starts an +agent session (the label alone does not). + +| Name | Role | Auto-assign | Notes | +|------|------|-------------|-------| +| Copilot | πŸ€– Coding Agent | βœ… Enabled | Requires the `COPILOT_ASSIGN_TOKEN` repo secret (a PAT that can assign the coding agent). Without it the assign step is a no-op. | + ## Issue Source - **Repository:** Azure/apiops-cli diff --git a/.squad/templates/workflows/squad-heartbeat.yml b/.squad/templates/workflows/squad-heartbeat.yml index 957915a4..60d6b732 100644 --- a/.squad/templates/workflows/squad-heartbeat.yml +++ b/.squad/templates/workflows/squad-heartbeat.yml @@ -133,12 +133,19 @@ jobs: per_page: 5 }); - const unassigned = copilotIssues.filter(i => - !i.assignees || i.assignees.length === 0 + // Include issues that don't yet have the coding agent assigned. + // issue-go-yes always assigns the go:yes maintainer as owner, so an + // issue almost always has a (human) assignee β€” filtering on "zero + // assignees" would skip every routed issue. Filter on the agent's + // presence instead; the POST below ADDS the bot as an extra assignee + // without removing the human owner. + const COPILOT_LOGINS = ['copilot-swe-agent[bot]', 'copilot-swe-agent', 'Copilot']; + const needsAgent = copilotIssues.filter(i => + !(i.assignees || []).some(a => COPILOT_LOGINS.includes(a.login)) ); - if (unassigned.length === 0) { - core.info('No unassigned squad:copilot issues'); + if (needsAgent.length === 0) { + core.info('No squad:copilot issues awaiting the coding agent'); return; } @@ -148,7 +155,7 @@ jobs: repo: context.repo.repo }); - for (const issue of unassigned) { + for (const issue of needsAgent) { try { await github.request('POST /repos/{owner}/{repo}/issues/{issue_number}/assignees', { owner: context.repo.owner, From 553be0235bbabcac7001766b54dbfc8db83e61c3 Mon Sep 17 00:00:00 2001 From: Elizabeth Maher Date: Thu, 2 Jul 2026 10:41:08 -0700 Subject: [PATCH 2/7] docs(squad): link COPILOT_ASSIGN_TOKEN setup instructions in team.md Add a "Setting up COPILOT_ASSIGN_TOKEN" note to the Coding Agent section with links to fine-grained PAT creation, repository-secret setup, and the GitHub docs describing the exact token/permissions required to assign the Copilot coding agent. Docs-only; no workflow/code changes. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .squad/team.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.squad/team.md b/.squad/team.md index c40ad98e..6911e6a8 100644 --- a/.squad/team.md +++ b/.squad/team.md @@ -40,6 +40,16 @@ agent session (the label alone does not). |------|------|-------------|-------| | Copilot | πŸ€– Coding Agent | βœ… Enabled | Requires the `COPILOT_ASSIGN_TOKEN` repo secret (a PAT that can assign the coding agent). Without it the assign step is a no-op. | +**Setting up `COPILOT_ASSIGN_TOKEN`:** the default `GITHUB_TOKEN` cannot assign the +coding agent, so the assign step needs a user token stored as a repo secret. Create a +[fine-grained personal access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens) +(ideally on a machine/bot account) with **Repository permissions** β€” *Metadata*: read, +and *Actions*, *Contents*, *Issues*, and *Pull requests*: read & write β€” then add it as a +[repository secret](https://docs.github.com/en/actions/how-tos/write-workflows/choose-what-workflows-do/use-secrets#creating-secrets-for-a-repository) +named `COPILOT_ASSIGN_TOKEN`. A classic PAT with the `repo` scope also works. The exact +token requirements are documented under +[Assigning issues to Copilot via the API](https://docs.github.com/en/copilot/how-tos/use-copilot-agents/cloud-agent/use-cloud-agent-via-the-api#using-the-issues-api). + ## Issue Source - **Repository:** Azure/apiops-cli From d0780f88c760196caf981af808be7c48aa96b616 Mon Sep 17 00:00:00 2001 From: Elizabeth Maher Date: Thu, 2 Jul 2026 10:49:23 -0700 Subject: [PATCH 3/7] feat(squad): nudge maintainer to assign Copilot when auto-assign is off Add a deterministic post-check step to the "Issue Go: Yes" workflow that checks whether the approved (go:yes, squad:copilot) issue is actually assigned to the Copilot coding agent. When the COPILOT_ASSIGN_TOKEN secret is not configured (so squad-heartbeat cannot auto-assign), it posts a comment tagging the human assignee(s) explaining they must assign the issue to Copilot to start the work. When the token IS configured, the step is a no-op to avoid noise, since Ralph will auto-assign shortly. Runs in the injection-safe post-check job (not the agentic prompt), so the logic is deterministic. Grants that job issues:write to post the comment. Security note: issue-go-yes.lock.yml now references the COPILOT_ASSIGN_TOKEN secret only inside an expression (secrets.COPILOT_ASSIGN_TOKEN != '') to detect presence; the secret value is never read, logged, or sent anywhere. Refs #194 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .github/workflows/issue-go-yes.lock.yml | 74 +++++++++++++++++++++++-- .github/workflows/issue-go-yes.md | 72 +++++++++++++++++++++++- 2 files changed, 139 insertions(+), 7 deletions(-) diff --git a/.github/workflows/issue-go-yes.lock.yml b/.github/workflows/issue-go-yes.lock.yml index 874a641e..d8769ad0 100644 --- a/.github/workflows/issue-go-yes.lock.yml +++ b/.github/workflows/issue-go-yes.lock.yml @@ -1,5 +1,5 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"41f29a749e0bf3667089ac45d06e6adbba2a37f9fff0c8ece29faad09aa22e1d","body_hash":"dab8fe99999fed7d1ef283d6f6a0046aa81ebdda3b72e54fe2b83705f3922bd9","compiler_version":"v0.81.6","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.65"}} -# gh-aw-manifest: {"version":1,"secrets":["GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0","version":"v7.0.0"},{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3 (source v6)"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/github-script","sha":"ed597411d8f924073f98dfc5c65a23a2325f34cd","version":"v8"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"ba6380cc6e5be5d21677bebe04d52fb48e3abec7","version":"v0.81.6"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.11","digest":"sha256:979723c628182da7729333f2208bb249fd25ddee579645cf9a3892d681a929c7","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.11@sha256:979723c628182da7729333f2208bb249fd25ddee579645cf9a3892d681a929c7"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.11","digest":"sha256:807e4831999b44513b0a66e5859d478dc4da7ae74ab1918cec967d513f95bf9d","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.11@sha256:807e4831999b44513b0a66e5859d478dc4da7ae74ab1918cec967d513f95bf9d"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.11","digest":"sha256:ff27ea0525ad953a6adee28a5fbe9d2e22be47dbec755c15767af4ea3f91df7d","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.11@sha256:ff27ea0525ad953a6adee28a5fbe9d2e22be47dbec755c15767af4ea3f91df7d"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.30","digest":"sha256:35625d1a2269b1238606078c879f59a91cffc4ac33eb54bf39c6418822c1a8be","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.30@sha256:35625d1a2269b1238606078c879f59a91cffc4ac33eb54bf39c6418822c1a8be"},{"image":"ghcr.io/github/gh-aw-node","digest":"sha256:529d02eb970b1161aa25c593a9c3df57fdfad5a8add328cb3b6eccef66f3183b","pinned_image":"ghcr.io/github/gh-aw-node@sha256:529d02eb970b1161aa25c593a9c3df57fdfad5a8add328cb3b6eccef66f3183b"},{"image":"ghcr.io/github/github-mcp-server:v1.4.0","digest":"sha256:2afb26356481d1a350e14544a6e160f7f7ec1561a1ea309b823665abf0309036","pinned_image":"ghcr.io/github/github-mcp-server:v1.4.0@sha256:2afb26356481d1a350e14544a6e160f7f7ec1561a1ea309b823665abf0309036"}]} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"5bda588f8ccf35145433a0a09b0f4a5eb9926a79fb6060fd0d8de01c9b535e18","body_hash":"dab8fe99999fed7d1ef283d6f6a0046aa81ebdda3b72e54fe2b83705f3922bd9","compiler_version":"v0.81.6","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.65"}} +# gh-aw-manifest: {"version":1,"secrets":["COPILOT_ASSIGN_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0","version":"v7.0.0"},{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3 (source v6)"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/github-script","sha":"ed597411d8f924073f98dfc5c65a23a2325f34cd","version":"v8"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"ba6380cc6e5be5d21677bebe04d52fb48e3abec7","version":"v0.81.6"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.11","digest":"sha256:979723c628182da7729333f2208bb249fd25ddee579645cf9a3892d681a929c7","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.11@sha256:979723c628182da7729333f2208bb249fd25ddee579645cf9a3892d681a929c7"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.11","digest":"sha256:807e4831999b44513b0a66e5859d478dc4da7ae74ab1918cec967d513f95bf9d","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.11@sha256:807e4831999b44513b0a66e5859d478dc4da7ae74ab1918cec967d513f95bf9d"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.11","digest":"sha256:ff27ea0525ad953a6adee28a5fbe9d2e22be47dbec755c15767af4ea3f91df7d","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.11@sha256:ff27ea0525ad953a6adee28a5fbe9d2e22be47dbec755c15767af4ea3f91df7d"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.30","digest":"sha256:35625d1a2269b1238606078c879f59a91cffc4ac33eb54bf39c6418822c1a8be","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.30@sha256:35625d1a2269b1238606078c879f59a91cffc4ac33eb54bf39c6418822c1a8be"},{"image":"ghcr.io/github/gh-aw-node","digest":"sha256:529d02eb970b1161aa25c593a9c3df57fdfad5a8add328cb3b6eccef66f3183b","pinned_image":"ghcr.io/github/gh-aw-node@sha256:529d02eb970b1161aa25c593a9c3df57fdfad5a8add328cb3b6eccef66f3183b"},{"image":"ghcr.io/github/github-mcp-server:v1.4.0","digest":"sha256:2afb26356481d1a350e14544a6e160f7f7ec1561a1ea309b823665abf0309036","pinned_image":"ghcr.io/github/github-mcp-server:v1.4.0@sha256:2afb26356481d1a350e14544a6e160f7f7ec1561a1ea309b823665abf0309036"}]} # This file was automatically generated by gh-aw (v0.81.6). DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md # # ___ _ _ @@ -23,9 +23,10 @@ # # For more information: https://github.github.com/gh-aw/introduction/overview/ # -# Assign an approved issue (go:yes) to the maintainer who approved it and route it to squad areas. Reads the prior triage analysis and the squad routing table, applies the squad label plus matched squad:{member} labels (and squad:copilot to hand the issue off to the Copilot coding agent), and posts an assignment rationale comment. +# Assign an approved issue (go:yes) to the maintainer who approved it and route it to squad areas. Reads the prior triage analysis and the squad routing table, applies the squad label plus matched squad:{member} labels (and squad:copilot to hand the issue off to the Copilot coding agent), and posts an assignment rationale comment. A deterministic post-check verifies the assignment and, when auto-assign is not configured (no COPILOT_ASSIGN_TOKEN), comments to nudge the assignee to assign the Copilot coding agent so work can begin. # # Secrets used: +# - COPILOT_ASSIGN_TOKEN # - GH_AW_GITHUB_MCP_SERVER_TOKEN # - GH_AW_GITHUB_TOKEN # - GITHUB_TOKEN @@ -1374,7 +1375,7 @@ jobs: uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: WORKFLOW_NAME: "Issue Go: Yes" - WORKFLOW_DESCRIPTION: "Assign an approved issue (go:yes) to the maintainer who approved it and route it to squad areas. Reads the prior triage analysis and the squad routing table, applies the squad label plus matched squad:{member} labels (and squad:copilot to hand the issue off to the Copilot coding agent), and posts an assignment rationale comment." + WORKFLOW_DESCRIPTION: "Assign an approved issue (go:yes) to the maintainer who approved it and route it to squad areas. Reads the prior triage analysis and the squad routing table, applies the squad label plus matched squad:{member} labels (and squad:copilot to hand the issue off to the Copilot coding agent), and posts an assignment rationale comment. A deterministic post-check verifies the assignment and, when auto-assign is not configured (no COPILOT_ASSIGN_TOKEN), comments to nudge the assignee to assign the Copilot coding agent so work can begin." HAS_PATCH: ${{ needs.agent.outputs.has_patch }} with: script: | @@ -1530,7 +1531,7 @@ jobs: runs-on: ubuntu-latest permissions: contents: read - issues: read + issues: write steps: - name: Configure GH_HOST for enterprise compatibility @@ -1597,6 +1598,69 @@ jobs: } core.info(`βœ… Post-check passed: assignee @${sender}, squad labels [${squadLabels.join(', ')}]`); + - name: Nudge maintainer to assign the Copilot coding agent + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + HAS_ASSIGN_TOKEN: ${{ secrets.COPILOT_ASSIGN_TOKEN != '' }} + ISSUE_NUMBER: ${{ github.event.issue.number }} + with: + script: | + // When COPILOT_ASSIGN_TOKEN is configured, squad-heartbeat auto-assigns + // the coding agent shortly after go:yes, so no manual nudge is needed. + if (process.env.HAS_ASSIGN_TOKEN === 'true') { + core.info('COPILOT_ASSIGN_TOKEN is configured β€” auto-assign will handle it; skipping nudge.'); + return; + } + + const issue_number = Number(process.env.ISSUE_NUMBER); + const { data: issue } = await github.rest.issues.get({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number + }); + + // Only relevant when the issue was handed off to the Copilot coding agent. + const hasCopilotLabel = (issue.labels || []) + .map(l => (typeof l === 'string' ? l : l.name)) + .includes('squad:copilot'); + if (!hasCopilotLabel) { + core.info('No squad:copilot label β€” coding-agent hand-off not requested; skipping nudge.'); + return; + } + + // Logins that count as "assigned to the SWE agent". + const AGENT_LOGINS = new Set(['copilot-swe-agent[bot]', 'copilot-swe-agent', 'copilot']); + const assignees = issue.assignees || []; + const agentAssigned = assignees.some(a => AGENT_LOGINS.has((a.login || '').toLowerCase())); + if (agentAssigned) { + core.info('Copilot coding agent already assigned β€” no nudge needed.'); + return; + } + + // Tag the human assignee(s) so they know to hand off to Copilot. + const humans = assignees + .map(a => a.login) + .filter(l => l && !l.endsWith('[bot]') && !AGENT_LOGINS.has(l.toLowerCase())); + const mention = humans.map(l => `@${l}`).join(' '); + const teamMdUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/blob/HEAD/.squad/team.md`; + + const body = [ + '### πŸ€– Action needed: assign this issue to Copilot', + '', + `${mention ? mention + ' β€” this' : 'This'} issue is approved (\`go:yes\`) and labeled \`squad:copilot\`, but it is **not assigned to the Copilot coding agent**, so no agent session has started yet.`, + '', + 'Automatic hand-off (Ralph / `squad-heartbeat`) is inactive because the `COPILOT_ASSIGN_TOKEN` secret is not configured. To start the work now, **assign this issue to Copilot** from the Assignees menu.', + '', + `To enable automatic hand-off for future issues, see the β€œSetting up \`COPILOT_ASSIGN_TOKEN\`” note in [\`.squad/team.md\`](${teamMdUrl}).`, + ].join('\n'); + + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number, + body + }); + core.info(`Posted Copilot-assignment nudge${mention ? ' tagging ' + mention : ''}.`); pre_activation: if: github.event_name != 'issues' || github.event.action != 'labeled' || github.event.label.name == 'go:yes' diff --git a/.github/workflows/issue-go-yes.md b/.github/workflows/issue-go-yes.md index dba84b93..11026eb4 100644 --- a/.github/workflows/issue-go-yes.md +++ b/.github/workflows/issue-go-yes.md @@ -4,7 +4,10 @@ description: > Assign an approved issue (go:yes) to the maintainer who approved it and route it to squad areas. Reads the prior triage analysis and the squad routing table, applies the squad label plus matched squad:{member} labels (and squad:copilot to hand the issue - off to the Copilot coding agent), and posts an assignment rationale comment. + off to the Copilot coding agent), and posts an assignment rationale comment. A + deterministic post-check verifies the assignment and, when auto-assign is not + configured (no COPILOT_ASSIGN_TOKEN), comments to nudge the assignee to assign the + Copilot coding agent so work can begin. on: issues: @@ -141,7 +144,7 @@ jobs: runs-on: ubuntu-latest permissions: contents: read - issues: read + issues: write # write so the nudge step can comment when auto-assign is off steps: - uses: actions/checkout@v6 - name: Verify assignee and squad labels @@ -196,6 +199,71 @@ jobs: } core.info(`βœ… Post-check passed: assignee @${sender}, squad labels [${squadLabels.join(', ')}]`); + - name: Nudge maintainer to assign the Copilot coding agent + uses: actions/github-script@v8 + env: + ISSUE_NUMBER: ${{ github.event.issue.number }} + # 'true' only when the repo secret is set. Used to skip the nudge when + # Ralph (squad-heartbeat) will auto-assign the coding agent for us. + HAS_ASSIGN_TOKEN: ${{ secrets.COPILOT_ASSIGN_TOKEN != '' }} + with: + script: | + // When COPILOT_ASSIGN_TOKEN is configured, squad-heartbeat auto-assigns + // the coding agent shortly after go:yes, so no manual nudge is needed. + if (process.env.HAS_ASSIGN_TOKEN === 'true') { + core.info('COPILOT_ASSIGN_TOKEN is configured β€” auto-assign will handle it; skipping nudge.'); + return; + } + + const issue_number = Number(process.env.ISSUE_NUMBER); + const { data: issue } = await github.rest.issues.get({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number + }); + + // Only relevant when the issue was handed off to the Copilot coding agent. + const hasCopilotLabel = (issue.labels || []) + .map(l => (typeof l === 'string' ? l : l.name)) + .includes('squad:copilot'); + if (!hasCopilotLabel) { + core.info('No squad:copilot label β€” coding-agent hand-off not requested; skipping nudge.'); + return; + } + + // Logins that count as "assigned to the SWE agent". + const AGENT_LOGINS = new Set(['copilot-swe-agent[bot]', 'copilot-swe-agent', 'copilot']); + const assignees = issue.assignees || []; + const agentAssigned = assignees.some(a => AGENT_LOGINS.has((a.login || '').toLowerCase())); + if (agentAssigned) { + core.info('Copilot coding agent already assigned β€” no nudge needed.'); + return; + } + + // Tag the human assignee(s) so they know to hand off to Copilot. + const humans = assignees + .map(a => a.login) + .filter(l => l && !l.endsWith('[bot]') && !AGENT_LOGINS.has(l.toLowerCase())); + const mention = humans.map(l => `@${l}`).join(' '); + const teamMdUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/blob/HEAD/.squad/team.md`; + + const body = [ + '### πŸ€– Action needed: assign this issue to Copilot', + '', + `${mention ? mention + ' β€” this' : 'This'} issue is approved (\`go:yes\`) and labeled \`squad:copilot\`, but it is **not assigned to the Copilot coding agent**, so no agent session has started yet.`, + '', + 'Automatic hand-off (Ralph / `squad-heartbeat`) is inactive because the `COPILOT_ASSIGN_TOKEN` secret is not configured. To start the work now, **assign this issue to Copilot** from the Assignees menu.', + '', + `To enable automatic hand-off for future issues, see the β€œSetting up \`COPILOT_ASSIGN_TOKEN\`” note in [\`.squad/team.md\`](${teamMdUrl}).`, + ].join('\n'); + + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number, + body + }); + core.info(`Posted Copilot-assignment nudge${mention ? ' tagging ' + mention : ''}.`); --- # Issue Assignment Agent From d45542e0ef56937e36b30871f59050a5d38b1762 Mon Sep 17 00:00:00 2001 From: Elizabeth Maher Date: Thu, 2 Jul 2026 11:01:37 -0700 Subject: [PATCH 4/7] refactor(squad): post Copilot-assignment nudge via agent, not post-check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the "assign this issue to Copilot" nudge out of the deterministic post-check job (which required issues:write) into the agent's single assignment comment, posted through the existing add-comment safe output. The post-check job is back to issues:read. Because the agent cannot read secrets, the gating is computed deterministically in the trusted "Prepare assignment context" shell step: NUDGE_NEEDED is true only when COPILOT_ASSIGN_TOKEN is absent (evaluated as the boolean `secrets.COPILOT_ASSIGN_TOKEN != ''`, never the value) AND the coding agent is not already an assignee. That result is injected into the trusted system-policy.md so the agent includes or omits the "### πŸ€– Action needed" section accordingly. Security note: the raw COPILOT_ASSIGN_TOKEN value is materialized in exactly one place in the compiled lock β€” gh-aw's "Redact secrets in logs" step β€” so its value is scrubbed from agent logs and is never placed in the agent inference step or the prepare step (which only see the boolean). Refs #194 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .github/workflows/issue-go-yes.lock.yml | 77 ++--------------- .github/workflows/issue-go-yes.md | 109 +++++++++--------------- 2 files changed, 47 insertions(+), 139 deletions(-) diff --git a/.github/workflows/issue-go-yes.lock.yml b/.github/workflows/issue-go-yes.lock.yml index d8769ad0..b4953762 100644 --- a/.github/workflows/issue-go-yes.lock.yml +++ b/.github/workflows/issue-go-yes.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"5bda588f8ccf35145433a0a09b0f4a5eb9926a79fb6060fd0d8de01c9b535e18","body_hash":"dab8fe99999fed7d1ef283d6f6a0046aa81ebdda3b72e54fe2b83705f3922bd9","compiler_version":"v0.81.6","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.65"}} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"e2676bb978824e0dd1383e73b616b5979c6e44e4135c387217793ad60449187d","body_hash":"aae9477785b974ef2757510b3c908e4e4e6408bfb9f727b73a8c7266eac17b47","compiler_version":"v0.81.6","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.65"}} # gh-aw-manifest: {"version":1,"secrets":["COPILOT_ASSIGN_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0","version":"v7.0.0"},{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3 (source v6)"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/github-script","sha":"ed597411d8f924073f98dfc5c65a23a2325f34cd","version":"v8"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"ba6380cc6e5be5d21677bebe04d52fb48e3abec7","version":"v0.81.6"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.11","digest":"sha256:979723c628182da7729333f2208bb249fd25ddee579645cf9a3892d681a929c7","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.11@sha256:979723c628182da7729333f2208bb249fd25ddee579645cf9a3892d681a929c7"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.11","digest":"sha256:807e4831999b44513b0a66e5859d478dc4da7ae74ab1918cec967d513f95bf9d","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.11@sha256:807e4831999b44513b0a66e5859d478dc4da7ae74ab1918cec967d513f95bf9d"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.11","digest":"sha256:ff27ea0525ad953a6adee28a5fbe9d2e22be47dbec755c15767af4ea3f91df7d","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.11@sha256:ff27ea0525ad953a6adee28a5fbe9d2e22be47dbec755c15767af4ea3f91df7d"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.30","digest":"sha256:35625d1a2269b1238606078c879f59a91cffc4ac33eb54bf39c6418822c1a8be","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.30@sha256:35625d1a2269b1238606078c879f59a91cffc4ac33eb54bf39c6418822c1a8be"},{"image":"ghcr.io/github/gh-aw-node","digest":"sha256:529d02eb970b1161aa25c593a9c3df57fdfad5a8add328cb3b6eccef66f3183b","pinned_image":"ghcr.io/github/gh-aw-node@sha256:529d02eb970b1161aa25c593a9c3df57fdfad5a8add328cb3b6eccef66f3183b"},{"image":"ghcr.io/github/github-mcp-server:v1.4.0","digest":"sha256:2afb26356481d1a350e14544a6e160f7f7ec1561a1ea309b823665abf0309036","pinned_image":"ghcr.io/github/github-mcp-server:v1.4.0@sha256:2afb26356481d1a350e14544a6e160f7f7ec1561a1ea309b823665abf0309036"}]} # This file was automatically generated by gh-aw (v0.81.6). DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md # @@ -23,7 +23,7 @@ # # For more information: https://github.github.com/gh-aw/introduction/overview/ # -# Assign an approved issue (go:yes) to the maintainer who approved it and route it to squad areas. Reads the prior triage analysis and the squad routing table, applies the squad label plus matched squad:{member} labels (and squad:copilot to hand the issue off to the Copilot coding agent), and posts an assignment rationale comment. A deterministic post-check verifies the assignment and, when auto-assign is not configured (no COPILOT_ASSIGN_TOKEN), comments to nudge the assignee to assign the Copilot coding agent so work can begin. +# Assign an approved issue (go:yes) to the maintainer who approved it and route it to squad areas. Reads the prior triage analysis and the squad routing table, applies the squad label plus matched squad:{member} labels (and squad:copilot to hand the issue off to the Copilot coding agent), and posts an assignment rationale comment that, when auto-assign is not configured (no COPILOT_ASSIGN_TOKEN), also nudges the assignee to assign the Copilot coding agent so work can begin. # # Secrets used: # - COPILOT_ASSIGN_TOKEN @@ -455,13 +455,14 @@ jobs: - env: GH_TOKEN: ${{ github.token }} GO_YES_SENDER: ${{ github.event.sender.login }} + HAS_ASSIGN_TOKEN: ${{ secrets.COPILOT_ASSIGN_TOKEN != '' }} ISSUE_AUTHOR: ${{ github.event.issue.user.login }} ISSUE_BODY: ${{ github.event.issue.body || '' }} ISSUE_NUMBER: ${{ github.event.issue.number }} ISSUE_TITLE: ${{ github.event.issue.title }} id: context name: Prepare assignment context - run: "mkdir -p /tmp/gh-aw/agent\n\n# ---------------------------------------------------------------------\n# USER context (untrusted): the issue itself + the prior triage comment.\n# ---------------------------------------------------------------------\nUSER_FILE=\"/tmp/gh-aw/agent/issue-content.md\"\n{\n printf '%s\\n' '---' 'context-role: user' '---' '# Issue Approved for Work (go:yes)' ''\n printf '**Title:** %s\\n' \"$ISSUE_TITLE\"\n printf '**Number:** #%s\\n' \"$ISSUE_NUMBER\"\n printf '**Author:** @%s\\n' \"$ISSUE_AUTHOR\"\n printf '\\n## Body\\n\\n'\n printf '%s\\n' \"$ISSUE_BODY\"\n printf '\\n## Prior Triage Analysis\\n\\n'\n} > \"$USER_FILE\"\n\n# Append the most recent triage recommendation comment, if one exists.\nTRIAGE=$(gh issue view \"$ISSUE_NUMBER\" --repo \"$GITHUB_REPOSITORY\" --json comments \\\n --jq '[.comments[] | select(.body | test(\"Triage Recommendation|Squad Triage\"))] | last | .body' 2>/dev/null || printf '')\nif [ -n \"$TRIAGE\" ] && [ \"$TRIAGE\" != \"null\" ]; then\n printf '%s\\n' \"$TRIAGE\" >> \"$USER_FILE\"\nelse\n printf '%s\\n' '_No prior triage analysis comment found β€” route from the issue content alone._' >> \"$USER_FILE\"\nfi\n\n# ---------------------------------------------------------------------\n# SYSTEM context (trusted): assignment policy + routing/team tables.\n# Single-quoted printf args keep backticks/`$` literal (no expansion).\n# ---------------------------------------------------------------------\nSYS_FILE=\"/tmp/gh-aw/agent/system-policy.md\"\n{\n printf '%s\\n' '---' 'context-role: system' '---'\n printf '%s\\n\\n' '# Issue Assignment Policy'\n printf '%s\\n\\n' '## Assignment (deterministic β€” do not deviate)'\n printf -- '- The maintainer who applied the `go:yes` label is **@%s**.\\n' \"$GO_YES_SENDER\"\n printf -- '- Assign this issue to **@%s** with the `assign_to_user` tool. Assign no one else.\\n' \"$GO_YES_SENDER\"\n printf '%s\\n' '- Always apply the `squad` label to mark the issue as squad-routed.'\n printf '%s\\n' '- Apply one `squad:{member}` label for every squad area the issue touches, per the routing table below.'\n printf '%s\\n' '- Apply the `squad:copilot` label to hand the issue off to the Copilot coding agent to begin implementation.'\n printf '%s\\n' '- Never apply `go:*`, `priority:*`, `override:*`, or `type:*` labels.'\n printf '\\n'\n} > \"$SYS_FILE\"\n\nappend_md() {\n if [ -f \"$2\" ]; then\n printf '\\n## %s\\n\\n' \"$1\" >> \"$SYS_FILE\"\n cat \"$2\" >> \"$SYS_FILE\"\n printf '\\n' >> \"$SYS_FILE\"\n fi\n}\nappend_json() {\n if [ -f \"$2\" ]; then\n printf '\\n## %s\\n\\n```json\\n' \"$1\" >> \"$SYS_FILE\"\n cat \"$2\" >> \"$SYS_FILE\"\n printf '\\n```\\n' >> \"$SYS_FILE\"\n fi\n}\nappend_md \"Routing Policy (routing.md)\" \".squad/routing.md\"\nappend_md \"Team Roster (team.md)\" \".squad/team.md\"\nappend_json \"Routing Table (routing-table.json)\" \".squad/routing-table.json\"\nappend_json \"Issue Routing (issue-routing.json)\" \".squad/issue-routing.json\"\n\necho \"context_user_file=issue-content.md\" >> \"$GITHUB_OUTPUT\"\necho \"context_system_file=system-policy.md\" >> \"$GITHUB_OUTPUT\"\n" + run: "mkdir -p /tmp/gh-aw/agent\n\n# ---------------------------------------------------------------------\n# USER context (untrusted): the issue itself + the prior triage comment.\n# ---------------------------------------------------------------------\nUSER_FILE=\"/tmp/gh-aw/agent/issue-content.md\"\n{\n printf '%s\\n' '---' 'context-role: user' '---' '# Issue Approved for Work (go:yes)' ''\n printf '**Title:** %s\\n' \"$ISSUE_TITLE\"\n printf '**Number:** #%s\\n' \"$ISSUE_NUMBER\"\n printf '**Author:** @%s\\n' \"$ISSUE_AUTHOR\"\n printf '\\n## Body\\n\\n'\n printf '%s\\n' \"$ISSUE_BODY\"\n printf '\\n## Prior Triage Analysis\\n\\n'\n} > \"$USER_FILE\"\n\n# Append the most recent triage recommendation comment, if one exists.\nTRIAGE=$(gh issue view \"$ISSUE_NUMBER\" --repo \"$GITHUB_REPOSITORY\" --json comments \\\n --jq '[.comments[] | select(.body | test(\"Triage Recommendation|Squad Triage\"))] | last | .body' 2>/dev/null || printf '')\nif [ -n \"$TRIAGE\" ] && [ \"$TRIAGE\" != \"null\" ]; then\n printf '%s\\n' \"$TRIAGE\" >> \"$USER_FILE\"\nelse\n printf '%s\\n' '_No prior triage analysis comment found β€” route from the issue content alone._' >> \"$USER_FILE\"\nfi\n\n# ---------------------------------------------------------------------\n# Copilot coding-agent hand-off status (deterministic, trusted context).\n# NUDGE_NEEDED is true only when auto-assign is unavailable AND the coding\n# agent is not already an assignee β€” so the agent should nudge the human.\n# ---------------------------------------------------------------------\nCURRENT_ASSIGNEES=$(gh issue view \"$ISSUE_NUMBER\" --repo \"$GITHUB_REPOSITORY\" --json assignees \\\n --jq '[.assignees[].login] | join(\",\")' 2>/dev/null | tr 'A-Z' 'a-z' || printf '')\nAGENT_ALREADY_ASSIGNED=false\nif printf ',%s,' \"$CURRENT_ASSIGNEES\" | grep -qE ',(copilot-swe-agent\\[bot\\]|copilot-swe-agent|copilot),'; then\n AGENT_ALREADY_ASSIGNED=true\nfi\nNUDGE_NEEDED=false\nif [ \"${HAS_ASSIGN_TOKEN:-false}\" != \"true\" ] && [ \"$AGENT_ALREADY_ASSIGNED\" != \"true\" ]; then\n NUDGE_NEEDED=true\nfi\n\n# ---------------------------------------------------------------------\n# SYSTEM context (trusted): assignment policy + routing/team tables.\n# Single-quoted printf args keep backticks/`$` literal (no expansion).\n# ---------------------------------------------------------------------\nSYS_FILE=\"/tmp/gh-aw/agent/system-policy.md\"\n{\n printf '%s\\n' '---' 'context-role: system' '---'\n printf '%s\\n\\n' '# Issue Assignment Policy'\n printf '%s\\n\\n' '## Assignment (deterministic β€” do not deviate)'\n printf -- '- The maintainer who applied the `go:yes` label is **@%s**.\\n' \"$GO_YES_SENDER\"\n printf -- '- Assign this issue to **@%s** with the `assign_to_user` tool. Assign no one else.\\n' \"$GO_YES_SENDER\"\n printf '%s\\n' '- Always apply the `squad` label to mark the issue as squad-routed.'\n printf '%s\\n' '- Apply one `squad:{member}` label for every squad area the issue touches, per the routing table below.'\n printf '%s\\n' '- Apply the `squad:copilot` label to hand the issue off to the Copilot coding agent to begin implementation.'\n printf '%s\\n' '- Never apply `go:*`, `priority:*`, `override:*`, or `type:*` labels.'\n if [ \"$NUDGE_NEEDED\" = \"true\" ]; then\n printf -- '- **Copilot hand-off nudge REQUIRED:** automatic coding-agent assignment is not configured and no coding agent is assigned yet. In your single assignment comment, add an `### πŸ€– Action needed` section that @-mentions **@%s** and tells them to assign this issue to Copilot from the Assignees menu so implementation can begin, and reference the \"Setting up `COPILOT_ASSIGN_TOKEN`\" note in `.squad/team.md`.\\n' \"$GO_YES_SENDER\"\n else\n printf '%s\\n' '- **Copilot hand-off nudge:** NOT required β€” do not add any Copilot-assignment nudge to the comment (auto-assign is configured or the coding agent is already assigned).'\n fi\n printf '\\n'\n} > \"$SYS_FILE\"\n\nappend_md() {\n if [ -f \"$2\" ]; then\n printf '\\n## %s\\n\\n' \"$1\" >> \"$SYS_FILE\"\n cat \"$2\" >> \"$SYS_FILE\"\n printf '\\n' >> \"$SYS_FILE\"\n fi\n}\nappend_json() {\n if [ -f \"$2\" ]; then\n printf '\\n## %s\\n\\n```json\\n' \"$1\" >> \"$SYS_FILE\"\n cat \"$2\" >> \"$SYS_FILE\"\n printf '\\n```\\n' >> \"$SYS_FILE\"\n fi\n}\nappend_md \"Routing Policy (routing.md)\" \".squad/routing.md\"\nappend_md \"Team Roster (team.md)\" \".squad/team.md\"\nappend_json \"Routing Table (routing-table.json)\" \".squad/routing-table.json\"\nappend_json \"Issue Routing (issue-routing.json)\" \".squad/issue-routing.json\"\n\necho \"context_user_file=issue-content.md\" >> \"$GITHUB_OUTPUT\"\necho \"context_system_file=system-policy.md\" >> \"$GITHUB_OUTPUT\"\n" - name: Contract test β€” verify context separation run: "USER_FILE=\"/tmp/gh-aw/agent/issue-content.md\"\nSYSTEM_FILE=\"/tmp/gh-aw/agent/system-policy.md\"\n\nif ! head -n 5 \"$USER_FILE\" | grep -qx \"context-role: user\"; then\n echo \"::error::Contract violation: user context file has an unexpected role marker\"\n exit 1\nfi\nif ! head -n 5 \"$SYSTEM_FILE\" | grep -qx \"context-role: system\"; then\n echo \"::error::Contract violation: system context file has an unexpected role marker\"\n exit 1\nfi\n# Untrusted issue markers must NOT bleed into the trusted system context.\nif grep -q \"context-role: user\" \"$SYSTEM_FILE\" || grep -q \"^# Issue Approved for Work\" \"$SYSTEM_FILE\"; then\n echo \"::error::Contract violation: user context leaked into system context\"\n exit 1\nfi\necho \"βœ… Context separation contract verified\"\n" @@ -909,7 +910,8 @@ jobs: const { main } = require('${{ runner.temp }}/gh-aw/actions/redact_secrets.cjs'); await main(); env: - GH_AW_SECRET_NAMES: 'GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN' + GH_AW_SECRET_NAMES: 'COPILOT_ASSIGN_TOKEN,GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN' + SECRET_COPILOT_ASSIGN_TOKEN: ${{ secrets.COPILOT_ASSIGN_TOKEN }} SECRET_GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} SECRET_GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} SECRET_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -1375,7 +1377,7 @@ jobs: uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: WORKFLOW_NAME: "Issue Go: Yes" - WORKFLOW_DESCRIPTION: "Assign an approved issue (go:yes) to the maintainer who approved it and route it to squad areas. Reads the prior triage analysis and the squad routing table, applies the squad label plus matched squad:{member} labels (and squad:copilot to hand the issue off to the Copilot coding agent), and posts an assignment rationale comment. A deterministic post-check verifies the assignment and, when auto-assign is not configured (no COPILOT_ASSIGN_TOKEN), comments to nudge the assignee to assign the Copilot coding agent so work can begin." + WORKFLOW_DESCRIPTION: "Assign an approved issue (go:yes) to the maintainer who approved it and route it to squad areas. Reads the prior triage analysis and the squad routing table, applies the squad label plus matched squad:{member} labels (and squad:copilot to hand the issue off to the Copilot coding agent), and posts an assignment rationale comment that, when auto-assign is not configured (no COPILOT_ASSIGN_TOKEN), also nudges the assignee to assign the Copilot coding agent so work can begin." HAS_PATCH: ${{ needs.agent.outputs.has_patch }} with: script: | @@ -1531,7 +1533,7 @@ jobs: runs-on: ubuntu-latest permissions: contents: read - issues: write + issues: read steps: - name: Configure GH_HOST for enterprise compatibility @@ -1598,69 +1600,6 @@ jobs: } core.info(`βœ… Post-check passed: assignee @${sender}, squad labels [${squadLabels.join(', ')}]`); - - name: Nudge maintainer to assign the Copilot coding agent - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - HAS_ASSIGN_TOKEN: ${{ secrets.COPILOT_ASSIGN_TOKEN != '' }} - ISSUE_NUMBER: ${{ github.event.issue.number }} - with: - script: | - // When COPILOT_ASSIGN_TOKEN is configured, squad-heartbeat auto-assigns - // the coding agent shortly after go:yes, so no manual nudge is needed. - if (process.env.HAS_ASSIGN_TOKEN === 'true') { - core.info('COPILOT_ASSIGN_TOKEN is configured β€” auto-assign will handle it; skipping nudge.'); - return; - } - - const issue_number = Number(process.env.ISSUE_NUMBER); - const { data: issue } = await github.rest.issues.get({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number - }); - - // Only relevant when the issue was handed off to the Copilot coding agent. - const hasCopilotLabel = (issue.labels || []) - .map(l => (typeof l === 'string' ? l : l.name)) - .includes('squad:copilot'); - if (!hasCopilotLabel) { - core.info('No squad:copilot label β€” coding-agent hand-off not requested; skipping nudge.'); - return; - } - - // Logins that count as "assigned to the SWE agent". - const AGENT_LOGINS = new Set(['copilot-swe-agent[bot]', 'copilot-swe-agent', 'copilot']); - const assignees = issue.assignees || []; - const agentAssigned = assignees.some(a => AGENT_LOGINS.has((a.login || '').toLowerCase())); - if (agentAssigned) { - core.info('Copilot coding agent already assigned β€” no nudge needed.'); - return; - } - - // Tag the human assignee(s) so they know to hand off to Copilot. - const humans = assignees - .map(a => a.login) - .filter(l => l && !l.endsWith('[bot]') && !AGENT_LOGINS.has(l.toLowerCase())); - const mention = humans.map(l => `@${l}`).join(' '); - const teamMdUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/blob/HEAD/.squad/team.md`; - - const body = [ - '### πŸ€– Action needed: assign this issue to Copilot', - '', - `${mention ? mention + ' β€” this' : 'This'} issue is approved (\`go:yes\`) and labeled \`squad:copilot\`, but it is **not assigned to the Copilot coding agent**, so no agent session has started yet.`, - '', - 'Automatic hand-off (Ralph / `squad-heartbeat`) is inactive because the `COPILOT_ASSIGN_TOKEN` secret is not configured. To start the work now, **assign this issue to Copilot** from the Assignees menu.', - '', - `To enable automatic hand-off for future issues, see the β€œSetting up \`COPILOT_ASSIGN_TOKEN\`” note in [\`.squad/team.md\`](${teamMdUrl}).`, - ].join('\n'); - - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number, - body - }); - core.info(`Posted Copilot-assignment nudge${mention ? ' tagging ' + mention : ''}.`); pre_activation: if: github.event_name != 'issues' || github.event.action != 'labeled' || github.event.label.name == 'go:yes' diff --git a/.github/workflows/issue-go-yes.md b/.github/workflows/issue-go-yes.md index 11026eb4..a21b4a17 100644 --- a/.github/workflows/issue-go-yes.md +++ b/.github/workflows/issue-go-yes.md @@ -4,10 +4,9 @@ description: > Assign an approved issue (go:yes) to the maintainer who approved it and route it to squad areas. Reads the prior triage analysis and the squad routing table, applies the squad label plus matched squad:{member} labels (and squad:copilot to hand the issue - off to the Copilot coding agent), and posts an assignment rationale comment. A - deterministic post-check verifies the assignment and, when auto-assign is not - configured (no COPILOT_ASSIGN_TOKEN), comments to nudge the assignee to assign the - Copilot coding agent so work can begin. + off to the Copilot coding agent), and posts an assignment rationale comment that, + when auto-assign is not configured (no COPILOT_ASSIGN_TOKEN), also nudges the + assignee to assign the Copilot coding agent so work can begin. on: issues: @@ -48,6 +47,10 @@ steps: ISSUE_TITLE: ${{ github.event.issue.title }} GO_YES_SENDER: ${{ github.event.sender.login }} GH_TOKEN: ${{ github.token }} + # 'true' only when the repo secret is set β€” i.e. squad-heartbeat can + # auto-assign the coding agent. The secret VALUE is never exposed; only + # this boolean is placed in the environment. + HAS_ASSIGN_TOKEN: ${{ secrets.COPILOT_ASSIGN_TOKEN != '' }} run: | mkdir -p /tmp/gh-aw/agent @@ -74,6 +77,22 @@ steps: printf '%s\n' '_No prior triage analysis comment found β€” route from the issue content alone._' >> "$USER_FILE" fi + # --------------------------------------------------------------------- + # Copilot coding-agent hand-off status (deterministic, trusted context). + # NUDGE_NEEDED is true only when auto-assign is unavailable AND the coding + # agent is not already an assignee β€” so the agent should nudge the human. + # --------------------------------------------------------------------- + CURRENT_ASSIGNEES=$(gh issue view "$ISSUE_NUMBER" --repo "$GITHUB_REPOSITORY" --json assignees \ + --jq '[.assignees[].login] | join(",")' 2>/dev/null | tr 'A-Z' 'a-z' || printf '') + AGENT_ALREADY_ASSIGNED=false + if printf ',%s,' "$CURRENT_ASSIGNEES" | grep -qE ',(copilot-swe-agent\[bot\]|copilot-swe-agent|copilot),'; then + AGENT_ALREADY_ASSIGNED=true + fi + NUDGE_NEEDED=false + if [ "${HAS_ASSIGN_TOKEN:-false}" != "true" ] && [ "$AGENT_ALREADY_ASSIGNED" != "true" ]; then + NUDGE_NEEDED=true + fi + # --------------------------------------------------------------------- # SYSTEM context (trusted): assignment policy + routing/team tables. # Single-quoted printf args keep backticks/`$` literal (no expansion). @@ -89,6 +108,11 @@ steps: printf '%s\n' '- Apply one `squad:{member}` label for every squad area the issue touches, per the routing table below.' printf '%s\n' '- Apply the `squad:copilot` label to hand the issue off to the Copilot coding agent to begin implementation.' printf '%s\n' '- Never apply `go:*`, `priority:*`, `override:*`, or `type:*` labels.' + if [ "$NUDGE_NEEDED" = "true" ]; then + printf -- '- **Copilot hand-off nudge REQUIRED:** automatic coding-agent assignment is not configured and no coding agent is assigned yet. In your single assignment comment, add an `### πŸ€– Action needed` section that @-mentions **@%s** and tells them to assign this issue to Copilot from the Assignees menu so implementation can begin, and reference the "Setting up `COPILOT_ASSIGN_TOKEN`" note in `.squad/team.md`.\n' "$GO_YES_SENDER" + else + printf '%s\n' '- **Copilot hand-off nudge:** NOT required β€” do not add any Copilot-assignment nudge to the comment (auto-assign is configured or the coding agent is already assigned).' + fi printf '\n' } > "$SYS_FILE" @@ -144,7 +168,7 @@ jobs: runs-on: ubuntu-latest permissions: contents: read - issues: write # write so the nudge step can comment when auto-assign is off + issues: read steps: - uses: actions/checkout@v6 - name: Verify assignee and squad labels @@ -199,71 +223,6 @@ jobs: } core.info(`βœ… Post-check passed: assignee @${sender}, squad labels [${squadLabels.join(', ')}]`); - - name: Nudge maintainer to assign the Copilot coding agent - uses: actions/github-script@v8 - env: - ISSUE_NUMBER: ${{ github.event.issue.number }} - # 'true' only when the repo secret is set. Used to skip the nudge when - # Ralph (squad-heartbeat) will auto-assign the coding agent for us. - HAS_ASSIGN_TOKEN: ${{ secrets.COPILOT_ASSIGN_TOKEN != '' }} - with: - script: | - // When COPILOT_ASSIGN_TOKEN is configured, squad-heartbeat auto-assigns - // the coding agent shortly after go:yes, so no manual nudge is needed. - if (process.env.HAS_ASSIGN_TOKEN === 'true') { - core.info('COPILOT_ASSIGN_TOKEN is configured β€” auto-assign will handle it; skipping nudge.'); - return; - } - - const issue_number = Number(process.env.ISSUE_NUMBER); - const { data: issue } = await github.rest.issues.get({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number - }); - - // Only relevant when the issue was handed off to the Copilot coding agent. - const hasCopilotLabel = (issue.labels || []) - .map(l => (typeof l === 'string' ? l : l.name)) - .includes('squad:copilot'); - if (!hasCopilotLabel) { - core.info('No squad:copilot label β€” coding-agent hand-off not requested; skipping nudge.'); - return; - } - - // Logins that count as "assigned to the SWE agent". - const AGENT_LOGINS = new Set(['copilot-swe-agent[bot]', 'copilot-swe-agent', 'copilot']); - const assignees = issue.assignees || []; - const agentAssigned = assignees.some(a => AGENT_LOGINS.has((a.login || '').toLowerCase())); - if (agentAssigned) { - core.info('Copilot coding agent already assigned β€” no nudge needed.'); - return; - } - - // Tag the human assignee(s) so they know to hand off to Copilot. - const humans = assignees - .map(a => a.login) - .filter(l => l && !l.endsWith('[bot]') && !AGENT_LOGINS.has(l.toLowerCase())); - const mention = humans.map(l => `@${l}`).join(' '); - const teamMdUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/blob/HEAD/.squad/team.md`; - - const body = [ - '### πŸ€– Action needed: assign this issue to Copilot', - '', - `${mention ? mention + ' β€” this' : 'This'} issue is approved (\`go:yes\`) and labeled \`squad:copilot\`, but it is **not assigned to the Copilot coding agent**, so no agent session has started yet.`, - '', - 'Automatic hand-off (Ralph / `squad-heartbeat`) is inactive because the `COPILOT_ASSIGN_TOKEN` secret is not configured. To start the work now, **assign this issue to Copilot** from the Assignees menu.', - '', - `To enable automatic hand-off for future issues, see the β€œSetting up \`COPILOT_ASSIGN_TOKEN\`” note in [\`.squad/team.md\`](${teamMdUrl}).`, - ].join('\n'); - - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number, - body - }); - core.info(`Posted Copilot-assignment nudge${mention ? ' tagging ' + mention : ''}.`); --- # Issue Assignment Agent @@ -295,6 +254,9 @@ context β€” you do not decide the assignee yourself. `squad` label, `squad:copilot`, and the most relevant matched member labels. 6. **Comment** exactly once with `add_comment`, explaining the assignee, the matched squad areas, and the routing evidence (which routing-table entries matched and why). + If the system policy says a **Copilot hand-off nudge** is REQUIRED, append the + `### πŸ€– Action needed` section (described in that policy) to this same comment. If it + says the nudge is NOT required, omit that section entirely. ## Assignment comment format @@ -310,6 +272,13 @@ context β€” you do not decide the assignee yourself. #### Notes + + +### πŸ€– Action needed +@ β€” this issue is not assigned to the Copilot coding agent yet, so no agent +session has started. Please assign it to Copilot from the Assignees menu to begin work. +To enable automatic hand-off for future issues, see the "Setting up `COPILOT_ASSIGN_TOKEN`" +note in `.squad/team.md`. ``` ## Security Rules From 729da29d91e9763c7df4e89a95ef1f0a358c7f7d Mon Sep 17 00:00:00 2001 From: Elizabeth Maher Date: Thu, 2 Jul 2026 11:02:47 -0700 Subject: [PATCH 5/7] fix(squad): keep COPILOT_ASSIGN_TOKEN out of the posted issue comment The Copilot-assignment nudge must not expose workflow internals in the public issue thread. Remove the ".squad/team.md / COPILOT_ASSIGN_TOKEN setup" reference from the nudge the agent posts, and add explicit guards (system policy + comment-format template) instructing the agent to never mention COPILOT_ASSIGN_TOKEN, repository secrets, or workflow internals in the comment. The nudge now simply asks the assignee to assign the issue to Copilot from the Assignees menu. Refs #194 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .github/workflows/issue-go-yes.lock.yml | 4 ++-- .github/workflows/issue-go-yes.md | 6 ++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/.github/workflows/issue-go-yes.lock.yml b/.github/workflows/issue-go-yes.lock.yml index b4953762..dbf2dc9a 100644 --- a/.github/workflows/issue-go-yes.lock.yml +++ b/.github/workflows/issue-go-yes.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"e2676bb978824e0dd1383e73b616b5979c6e44e4135c387217793ad60449187d","body_hash":"aae9477785b974ef2757510b3c908e4e4e6408bfb9f727b73a8c7266eac17b47","compiler_version":"v0.81.6","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.65"}} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"46dc7cb473f668f59ea39afb12a3f7705d4c316dc2cf17559c4a99b8b05b3c29","body_hash":"5319da7c859b78cf1c300425552ac0636ff93a6cbe82bcfa2e3814c797f18177","compiler_version":"v0.81.6","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.65"}} # gh-aw-manifest: {"version":1,"secrets":["COPILOT_ASSIGN_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0","version":"v7.0.0"},{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3 (source v6)"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/github-script","sha":"ed597411d8f924073f98dfc5c65a23a2325f34cd","version":"v8"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"ba6380cc6e5be5d21677bebe04d52fb48e3abec7","version":"v0.81.6"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.11","digest":"sha256:979723c628182da7729333f2208bb249fd25ddee579645cf9a3892d681a929c7","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.11@sha256:979723c628182da7729333f2208bb249fd25ddee579645cf9a3892d681a929c7"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.11","digest":"sha256:807e4831999b44513b0a66e5859d478dc4da7ae74ab1918cec967d513f95bf9d","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.11@sha256:807e4831999b44513b0a66e5859d478dc4da7ae74ab1918cec967d513f95bf9d"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.11","digest":"sha256:ff27ea0525ad953a6adee28a5fbe9d2e22be47dbec755c15767af4ea3f91df7d","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.11@sha256:ff27ea0525ad953a6adee28a5fbe9d2e22be47dbec755c15767af4ea3f91df7d"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.30","digest":"sha256:35625d1a2269b1238606078c879f59a91cffc4ac33eb54bf39c6418822c1a8be","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.30@sha256:35625d1a2269b1238606078c879f59a91cffc4ac33eb54bf39c6418822c1a8be"},{"image":"ghcr.io/github/gh-aw-node","digest":"sha256:529d02eb970b1161aa25c593a9c3df57fdfad5a8add328cb3b6eccef66f3183b","pinned_image":"ghcr.io/github/gh-aw-node@sha256:529d02eb970b1161aa25c593a9c3df57fdfad5a8add328cb3b6eccef66f3183b"},{"image":"ghcr.io/github/github-mcp-server:v1.4.0","digest":"sha256:2afb26356481d1a350e14544a6e160f7f7ec1561a1ea309b823665abf0309036","pinned_image":"ghcr.io/github/github-mcp-server:v1.4.0@sha256:2afb26356481d1a350e14544a6e160f7f7ec1561a1ea309b823665abf0309036"}]} # This file was automatically generated by gh-aw (v0.81.6). DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md # @@ -462,7 +462,7 @@ jobs: ISSUE_TITLE: ${{ github.event.issue.title }} id: context name: Prepare assignment context - run: "mkdir -p /tmp/gh-aw/agent\n\n# ---------------------------------------------------------------------\n# USER context (untrusted): the issue itself + the prior triage comment.\n# ---------------------------------------------------------------------\nUSER_FILE=\"/tmp/gh-aw/agent/issue-content.md\"\n{\n printf '%s\\n' '---' 'context-role: user' '---' '# Issue Approved for Work (go:yes)' ''\n printf '**Title:** %s\\n' \"$ISSUE_TITLE\"\n printf '**Number:** #%s\\n' \"$ISSUE_NUMBER\"\n printf '**Author:** @%s\\n' \"$ISSUE_AUTHOR\"\n printf '\\n## Body\\n\\n'\n printf '%s\\n' \"$ISSUE_BODY\"\n printf '\\n## Prior Triage Analysis\\n\\n'\n} > \"$USER_FILE\"\n\n# Append the most recent triage recommendation comment, if one exists.\nTRIAGE=$(gh issue view \"$ISSUE_NUMBER\" --repo \"$GITHUB_REPOSITORY\" --json comments \\\n --jq '[.comments[] | select(.body | test(\"Triage Recommendation|Squad Triage\"))] | last | .body' 2>/dev/null || printf '')\nif [ -n \"$TRIAGE\" ] && [ \"$TRIAGE\" != \"null\" ]; then\n printf '%s\\n' \"$TRIAGE\" >> \"$USER_FILE\"\nelse\n printf '%s\\n' '_No prior triage analysis comment found β€” route from the issue content alone._' >> \"$USER_FILE\"\nfi\n\n# ---------------------------------------------------------------------\n# Copilot coding-agent hand-off status (deterministic, trusted context).\n# NUDGE_NEEDED is true only when auto-assign is unavailable AND the coding\n# agent is not already an assignee β€” so the agent should nudge the human.\n# ---------------------------------------------------------------------\nCURRENT_ASSIGNEES=$(gh issue view \"$ISSUE_NUMBER\" --repo \"$GITHUB_REPOSITORY\" --json assignees \\\n --jq '[.assignees[].login] | join(\",\")' 2>/dev/null | tr 'A-Z' 'a-z' || printf '')\nAGENT_ALREADY_ASSIGNED=false\nif printf ',%s,' \"$CURRENT_ASSIGNEES\" | grep -qE ',(copilot-swe-agent\\[bot\\]|copilot-swe-agent|copilot),'; then\n AGENT_ALREADY_ASSIGNED=true\nfi\nNUDGE_NEEDED=false\nif [ \"${HAS_ASSIGN_TOKEN:-false}\" != \"true\" ] && [ \"$AGENT_ALREADY_ASSIGNED\" != \"true\" ]; then\n NUDGE_NEEDED=true\nfi\n\n# ---------------------------------------------------------------------\n# SYSTEM context (trusted): assignment policy + routing/team tables.\n# Single-quoted printf args keep backticks/`$` literal (no expansion).\n# ---------------------------------------------------------------------\nSYS_FILE=\"/tmp/gh-aw/agent/system-policy.md\"\n{\n printf '%s\\n' '---' 'context-role: system' '---'\n printf '%s\\n\\n' '# Issue Assignment Policy'\n printf '%s\\n\\n' '## Assignment (deterministic β€” do not deviate)'\n printf -- '- The maintainer who applied the `go:yes` label is **@%s**.\\n' \"$GO_YES_SENDER\"\n printf -- '- Assign this issue to **@%s** with the `assign_to_user` tool. Assign no one else.\\n' \"$GO_YES_SENDER\"\n printf '%s\\n' '- Always apply the `squad` label to mark the issue as squad-routed.'\n printf '%s\\n' '- Apply one `squad:{member}` label for every squad area the issue touches, per the routing table below.'\n printf '%s\\n' '- Apply the `squad:copilot` label to hand the issue off to the Copilot coding agent to begin implementation.'\n printf '%s\\n' '- Never apply `go:*`, `priority:*`, `override:*`, or `type:*` labels.'\n if [ \"$NUDGE_NEEDED\" = \"true\" ]; then\n printf -- '- **Copilot hand-off nudge REQUIRED:** automatic coding-agent assignment is not configured and no coding agent is assigned yet. In your single assignment comment, add an `### πŸ€– Action needed` section that @-mentions **@%s** and tells them to assign this issue to Copilot from the Assignees menu so implementation can begin, and reference the \"Setting up `COPILOT_ASSIGN_TOKEN`\" note in `.squad/team.md`.\\n' \"$GO_YES_SENDER\"\n else\n printf '%s\\n' '- **Copilot hand-off nudge:** NOT required β€” do not add any Copilot-assignment nudge to the comment (auto-assign is configured or the coding agent is already assigned).'\n fi\n printf '\\n'\n} > \"$SYS_FILE\"\n\nappend_md() {\n if [ -f \"$2\" ]; then\n printf '\\n## %s\\n\\n' \"$1\" >> \"$SYS_FILE\"\n cat \"$2\" >> \"$SYS_FILE\"\n printf '\\n' >> \"$SYS_FILE\"\n fi\n}\nappend_json() {\n if [ -f \"$2\" ]; then\n printf '\\n## %s\\n\\n```json\\n' \"$1\" >> \"$SYS_FILE\"\n cat \"$2\" >> \"$SYS_FILE\"\n printf '\\n```\\n' >> \"$SYS_FILE\"\n fi\n}\nappend_md \"Routing Policy (routing.md)\" \".squad/routing.md\"\nappend_md \"Team Roster (team.md)\" \".squad/team.md\"\nappend_json \"Routing Table (routing-table.json)\" \".squad/routing-table.json\"\nappend_json \"Issue Routing (issue-routing.json)\" \".squad/issue-routing.json\"\n\necho \"context_user_file=issue-content.md\" >> \"$GITHUB_OUTPUT\"\necho \"context_system_file=system-policy.md\" >> \"$GITHUB_OUTPUT\"\n" + run: "mkdir -p /tmp/gh-aw/agent\n\n# ---------------------------------------------------------------------\n# USER context (untrusted): the issue itself + the prior triage comment.\n# ---------------------------------------------------------------------\nUSER_FILE=\"/tmp/gh-aw/agent/issue-content.md\"\n{\n printf '%s\\n' '---' 'context-role: user' '---' '# Issue Approved for Work (go:yes)' ''\n printf '**Title:** %s\\n' \"$ISSUE_TITLE\"\n printf '**Number:** #%s\\n' \"$ISSUE_NUMBER\"\n printf '**Author:** @%s\\n' \"$ISSUE_AUTHOR\"\n printf '\\n## Body\\n\\n'\n printf '%s\\n' \"$ISSUE_BODY\"\n printf '\\n## Prior Triage Analysis\\n\\n'\n} > \"$USER_FILE\"\n\n# Append the most recent triage recommendation comment, if one exists.\nTRIAGE=$(gh issue view \"$ISSUE_NUMBER\" --repo \"$GITHUB_REPOSITORY\" --json comments \\\n --jq '[.comments[] | select(.body | test(\"Triage Recommendation|Squad Triage\"))] | last | .body' 2>/dev/null || printf '')\nif [ -n \"$TRIAGE\" ] && [ \"$TRIAGE\" != \"null\" ]; then\n printf '%s\\n' \"$TRIAGE\" >> \"$USER_FILE\"\nelse\n printf '%s\\n' '_No prior triage analysis comment found β€” route from the issue content alone._' >> \"$USER_FILE\"\nfi\n\n# ---------------------------------------------------------------------\n# Copilot coding-agent hand-off status (deterministic, trusted context).\n# NUDGE_NEEDED is true only when auto-assign is unavailable AND the coding\n# agent is not already an assignee β€” so the agent should nudge the human.\n# ---------------------------------------------------------------------\nCURRENT_ASSIGNEES=$(gh issue view \"$ISSUE_NUMBER\" --repo \"$GITHUB_REPOSITORY\" --json assignees \\\n --jq '[.assignees[].login] | join(\",\")' 2>/dev/null | tr 'A-Z' 'a-z' || printf '')\nAGENT_ALREADY_ASSIGNED=false\nif printf ',%s,' \"$CURRENT_ASSIGNEES\" | grep -qE ',(copilot-swe-agent\\[bot\\]|copilot-swe-agent|copilot),'; then\n AGENT_ALREADY_ASSIGNED=true\nfi\nNUDGE_NEEDED=false\nif [ \"${HAS_ASSIGN_TOKEN:-false}\" != \"true\" ] && [ \"$AGENT_ALREADY_ASSIGNED\" != \"true\" ]; then\n NUDGE_NEEDED=true\nfi\n\n# ---------------------------------------------------------------------\n# SYSTEM context (trusted): assignment policy + routing/team tables.\n# Single-quoted printf args keep backticks/`$` literal (no expansion).\n# ---------------------------------------------------------------------\nSYS_FILE=\"/tmp/gh-aw/agent/system-policy.md\"\n{\n printf '%s\\n' '---' 'context-role: system' '---'\n printf '%s\\n\\n' '# Issue Assignment Policy'\n printf '%s\\n\\n' '## Assignment (deterministic β€” do not deviate)'\n printf -- '- The maintainer who applied the `go:yes` label is **@%s**.\\n' \"$GO_YES_SENDER\"\n printf -- '- Assign this issue to **@%s** with the `assign_to_user` tool. Assign no one else.\\n' \"$GO_YES_SENDER\"\n printf '%s\\n' '- Always apply the `squad` label to mark the issue as squad-routed.'\n printf '%s\\n' '- Apply one `squad:{member}` label for every squad area the issue touches, per the routing table below.'\n printf '%s\\n' '- Apply the `squad:copilot` label to hand the issue off to the Copilot coding agent to begin implementation.'\n printf '%s\\n' '- Never apply `go:*`, `priority:*`, `override:*`, or `type:*` labels.'\n if [ \"$NUDGE_NEEDED\" = \"true\" ]; then\n printf -- '- **Copilot hand-off nudge REQUIRED:** no coding agent is assigned to this issue yet. In your single assignment comment, add an `### πŸ€– Action needed` section that @-mentions **@%s** and tells them to assign this issue to Copilot from the Assignees menu so implementation can begin. Do NOT mention COPILOT_ASSIGN_TOKEN, repository secrets, `.squad/team.md`, or any workflow internals in the comment.\\n' \"$GO_YES_SENDER\"\n else\n printf '%s\\n' '- **Copilot hand-off nudge:** NOT required β€” do not add any Copilot-assignment nudge to the comment (auto-assign is configured or the coding agent is already assigned).'\n fi\n printf '\\n'\n} > \"$SYS_FILE\"\n\nappend_md() {\n if [ -f \"$2\" ]; then\n printf '\\n## %s\\n\\n' \"$1\" >> \"$SYS_FILE\"\n cat \"$2\" >> \"$SYS_FILE\"\n printf '\\n' >> \"$SYS_FILE\"\n fi\n}\nappend_json() {\n if [ -f \"$2\" ]; then\n printf '\\n## %s\\n\\n```json\\n' \"$1\" >> \"$SYS_FILE\"\n cat \"$2\" >> \"$SYS_FILE\"\n printf '\\n```\\n' >> \"$SYS_FILE\"\n fi\n}\nappend_md \"Routing Policy (routing.md)\" \".squad/routing.md\"\nappend_md \"Team Roster (team.md)\" \".squad/team.md\"\nappend_json \"Routing Table (routing-table.json)\" \".squad/routing-table.json\"\nappend_json \"Issue Routing (issue-routing.json)\" \".squad/issue-routing.json\"\n\necho \"context_user_file=issue-content.md\" >> \"$GITHUB_OUTPUT\"\necho \"context_system_file=system-policy.md\" >> \"$GITHUB_OUTPUT\"\n" - name: Contract test β€” verify context separation run: "USER_FILE=\"/tmp/gh-aw/agent/issue-content.md\"\nSYSTEM_FILE=\"/tmp/gh-aw/agent/system-policy.md\"\n\nif ! head -n 5 \"$USER_FILE\" | grep -qx \"context-role: user\"; then\n echo \"::error::Contract violation: user context file has an unexpected role marker\"\n exit 1\nfi\nif ! head -n 5 \"$SYSTEM_FILE\" | grep -qx \"context-role: system\"; then\n echo \"::error::Contract violation: system context file has an unexpected role marker\"\n exit 1\nfi\n# Untrusted issue markers must NOT bleed into the trusted system context.\nif grep -q \"context-role: user\" \"$SYSTEM_FILE\" || grep -q \"^# Issue Approved for Work\" \"$SYSTEM_FILE\"; then\n echo \"::error::Contract violation: user context leaked into system context\"\n exit 1\nfi\necho \"βœ… Context separation contract verified\"\n" diff --git a/.github/workflows/issue-go-yes.md b/.github/workflows/issue-go-yes.md index a21b4a17..0fba62d6 100644 --- a/.github/workflows/issue-go-yes.md +++ b/.github/workflows/issue-go-yes.md @@ -109,7 +109,7 @@ steps: printf '%s\n' '- Apply the `squad:copilot` label to hand the issue off to the Copilot coding agent to begin implementation.' printf '%s\n' '- Never apply `go:*`, `priority:*`, `override:*`, or `type:*` labels.' if [ "$NUDGE_NEEDED" = "true" ]; then - printf -- '- **Copilot hand-off nudge REQUIRED:** automatic coding-agent assignment is not configured and no coding agent is assigned yet. In your single assignment comment, add an `### πŸ€– Action needed` section that @-mentions **@%s** and tells them to assign this issue to Copilot from the Assignees menu so implementation can begin, and reference the "Setting up `COPILOT_ASSIGN_TOKEN`" note in `.squad/team.md`.\n' "$GO_YES_SENDER" + printf -- '- **Copilot hand-off nudge REQUIRED:** no coding agent is assigned to this issue yet. In your single assignment comment, add an `### πŸ€– Action needed` section that @-mentions **@%s** and tells them to assign this issue to Copilot from the Assignees menu so implementation can begin. Do NOT mention COPILOT_ASSIGN_TOKEN, repository secrets, `.squad/team.md`, or any workflow internals in the comment.\n' "$GO_YES_SENDER" else printf '%s\n' '- **Copilot hand-off nudge:** NOT required β€” do not add any Copilot-assignment nudge to the comment (auto-assign is configured or the coding agent is already assigned).' fi @@ -273,12 +273,10 @@ context β€” you do not decide the assignee yourself. #### Notes - + ### πŸ€– Action needed @ β€” this issue is not assigned to the Copilot coding agent yet, so no agent session has started. Please assign it to Copilot from the Assignees menu to begin work. -To enable automatic hand-off for future issues, see the "Setting up `COPILOT_ASSIGN_TOKEN`" -note in `.squad/team.md`. ``` ## Security Rules From 3c1805ace6db80e9d9aeb269fb9fde6e652c2883 Mon Sep 17 00:00:00 2001 From: Elizabeth Maher Date: Thu, 2 Jul 2026 11:10:09 -0700 Subject: [PATCH 6/7] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .squad/templates/workflows/squad-heartbeat.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.squad/templates/workflows/squad-heartbeat.yml b/.squad/templates/workflows/squad-heartbeat.yml index 60d6b732..77d03c23 100644 --- a/.squad/templates/workflows/squad-heartbeat.yml +++ b/.squad/templates/workflows/squad-heartbeat.yml @@ -139,9 +139,9 @@ jobs: // assignees" would skip every routed issue. Filter on the agent's // presence instead; the POST below ADDS the bot as an extra assignee // without removing the human owner. - const COPILOT_LOGINS = ['copilot-swe-agent[bot]', 'copilot-swe-agent', 'Copilot']; + const COPILOT_LOGINS = new Set(['copilot-swe-agent[bot]', 'copilot-swe-agent', 'copilot']); const needsAgent = copilotIssues.filter(i => - !(i.assignees || []).some(a => COPILOT_LOGINS.includes(a.login)) + !(i.assignees || []).some(a => COPILOT_LOGINS.has((a.login || '').toLowerCase())) ); if (needsAgent.length === 0) { From 22ac10d869edcf0f00219fcf9a9d72160af4bc49 Mon Sep 17 00:00:00 2001 From: Elizabeth Maher Date: Thu, 2 Jul 2026 11:10:18 -0700 Subject: [PATCH 7/7] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .github/workflows/squad-heartbeat.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/squad-heartbeat.yml b/.github/workflows/squad-heartbeat.yml index 3595845d..609cb51e 100644 --- a/.github/workflows/squad-heartbeat.yml +++ b/.github/workflows/squad-heartbeat.yml @@ -135,9 +135,9 @@ jobs: // assignees" would skip every routed issue. Filter on the agent's // presence instead; the POST below ADDS the bot as an extra assignee // without removing the human owner. - const COPILOT_LOGINS = ['copilot-swe-agent[bot]', 'copilot-swe-agent', 'Copilot']; + const COPILOT_LOGINS = new Set(['copilot-swe-agent[bot]', 'copilot-swe-agent', 'copilot']); const needsAgent = copilotIssues.filter(i => - !(i.assignees || []).some(a => COPILOT_LOGINS.includes(a.login)) + !(i.assignees || []).some(a => COPILOT_LOGINS.has((a.login || '').toLowerCase())) ); if (needsAgent.length === 0) {