diff --git a/.github/aw/actions-lock.json b/.github/aw/actions-lock.json index f9e0ec5..4c3f26d 100644 --- a/.github/aw/actions-lock.json +++ b/.github/aw/actions-lock.json @@ -10,10 +10,10 @@ "version": "v9.0.0", "sha": "3a2844b7e9c422d3c10d287c895573f7108da1b3" }, - "github/gh-aw-actions/setup@v0.86.2": { + "github/gh-aw-actions/setup@v0.88.7": { "repo": "github/gh-aw-actions/setup", - "version": "v0.86.2", - "sha": "6aab9e5b5c91c615506061f09bedd81a23babe3c" + "version": "v0.88.7", + "sha": "5e508589e03a7757a7e05b26e834292f5445bfb6" } }, "containers": { diff --git a/.github/workflows/repo-assist.lock.yml b/.github/workflows/repo-assist.lock.yml index edaa076..2ddf8c7 100644 --- a/.github/workflows/repo-assist.lock.yml +++ b/.github/workflows/repo-assist.lock.yml @@ -1,6 +1,6 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"5d1dff6563da3a0a9bfd1d0edaf9c651687f338f4dd5ce7a3bb3f921f5b46720","body_hash":"422779c1cf00c63c80de694bfd2f865689ebccc15752ec4eb9bbd8a64df5318c","compiler_version":"v0.86.2","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.79"}} -# gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"55cc8345863c7cc4c66a329aec7e433d2d1c52a9","version":"v6.1.0"},{"repo":"actions/cache/save","sha":"55cc8345863c7cc4c66a329aec7e433d2d1c52a9","version":"v6.1.0"},{"repo":"actions/checkout","sha":"3d3c42e5aac5ba805825da76410c181273ba90b1","version":"v7.0.1"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"820762786026740c76f36085b0efc47a31fe5020","version":"v7.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"6aab9e5b5c91c615506061f09bedd81a23babe3c","version":"v0.86.2"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.44","digest":"sha256:0d727725c737b58c7bdf51f640cffb928385ec46517e0917c7f1a02f1bada8b4","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.44@sha256:0d727725c737b58c7bdf51f640cffb928385ec46517e0917c7f1a02f1bada8b4"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.44","digest":"sha256:b50fbadba138f6e9aba94aca09711335c489bb3b15861220cb66f6092e042dc7","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.44@sha256:b50fbadba138f6e9aba94aca09711335c489bb3b15861220cb66f6092e042dc7"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.44","digest":"sha256:83e48bbe12c634be8c228a576832fe45f66c529ac3659db92bddbcf2eeb6d627","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.44@sha256:83e48bbe12c634be8c228a576832fe45f66c529ac3659db92bddbcf2eeb6d627"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.4.9","digest":"sha256:e5a1569aeaf41820fa7bdee3e94468cae448133cdbf00119ad24f5b74db1ab9f","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.4.9@sha256:e5a1569aeaf41820fa7bdee3e94468cae448133cdbf00119ad24f5b74db1ab9f"},{"image":"ghcr.io/github/gh-aw-node","digest":"sha256:a8082161d7dceda14b68f32eb39d0eaa96b825d07f5895b096afab9d9e0c7748","pinned_image":"ghcr.io/github/gh-aw-node@sha256:a8082161d7dceda14b68f32eb39d0eaa96b825d07f5895b096afab9d9e0c7748"},{"image":"ghcr.io/github/github-mcp-server:v1.9.0","digest":"sha256:881b53d6f75f69bdbc1b5b10fc2f1361717c19054143b3a8529fb5c32061a50e","pinned_image":"ghcr.io/github/github-mcp-server:v1.9.0@sha256:881b53d6f75f69bdbc1b5b10fc2f1361717c19054143b3a8529fb5c32061a50e"}]} -# This file was automatically generated by gh-aw (v0.86.2). DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"25a01e6c81bd7c17374ae6055896c4c943c905e986edbe4f87572795f4434d55","body_hash":"56ef1236adc7c34fa215b511776bcf585e1944b6636f664338a47cee833c16bc","compiler_version":"v0.88.7","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.80"}} +# gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_CI_TRIGGER_TOKEN","GH_AW_DEFAULT_OTLP_HEADERS","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"55cc8345863c7cc4c66a329aec7e433d2d1c52a9","version":"v6.1.0"},{"repo":"actions/cache/save","sha":"55cc8345863c7cc4c66a329aec7e433d2d1c52a9","version":"v6.1.0"},{"repo":"actions/checkout","sha":"3d3c42e5aac5ba805825da76410c181273ba90b1","version":"v7.0.1"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"820762786026740c76f36085b0efc47a31fe5020","version":"v7.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"5e508589e03a7757a7e05b26e834292f5445bfb6","version":"v0.88.7"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.28.14","digest":"sha256:f7df036c86575527b61f3f7df91c4412349a12b2a74988d929eafa2999230c98","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.28.14@sha256:f7df036c86575527b61f3f7df91c4412349a12b2a74988d929eafa2999230c98"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.28.14","digest":"sha256:6f95e2234dd9bd6333a8ff28ccea7ecf0204acd4a09108723844dbd2bf6268c5","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.28.14@sha256:6f95e2234dd9bd6333a8ff28ccea7ecf0204acd4a09108723844dbd2bf6268c5"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.28.14","digest":"sha256:2ce8df3abf3e9b76e9c0cf5863da41f1ab3f89b20ad14b988806ab89e7bf2cd5","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.28.14@sha256:2ce8df3abf3e9b76e9c0cf5863da41f1ab3f89b20ad14b988806ab89e7bf2cd5"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.4.18","digest":"sha256:85b940556a8faa4e1fdbef124bfd75f2c4ebd855a10b88a1c3b6f3e97f6f1a53","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.4.18@sha256:85b940556a8faa4e1fdbef124bfd75f2c4ebd855a10b88a1c3b6f3e97f6f1a53"},{"image":"ghcr.io/github/gh-aw-node","digest":"sha256:a8082161d7dceda14b68f32eb39d0eaa96b825d07f5895b096afab9d9e0c7748","pinned_image":"ghcr.io/github/gh-aw-node@sha256:a8082161d7dceda14b68f32eb39d0eaa96b825d07f5895b096afab9d9e0c7748"},{"image":"ghcr.io/github/github-mcp-server:v1.11.0","digest":"sha256:fbec75de11c255213fa08d80fb166abe73d851fff631c51c0079872967720699","pinned_image":"ghcr.io/github/github-mcp-server:v1.11.0@sha256:fbec75de11c255213fa08d80fb166abe73d851fff631c51c0079872967720699"}],"memory_validation_scripts":[{"memory":"repo-memory:default","sha256":"ee19c879719ce3afb59ca3f2caa37b8ba715dd95b1b10f04f5e7bcbfb9bb5330"}],"mcp_servers":[{"name":"github","tools":["actions_get","actions_list","get_code_scanning_alert","get_commit","get_discussion","get_discussion_comments","get_file_contents","get_job_logs","get_label","get_latest_release","get_me","get_notification_details","get_pull_request","get_pull_request_comments","get_pull_request_diff","get_pull_request_files","get_pull_request_review_comments","get_pull_request_reviews","get_pull_request_status","get_release_by_tag","get_secret_scanning_alert","get_tag","issue_read","list_branches","list_code_scanning_alerts","list_commits","list_discussion_categories","list_discussions","list_issue_types","list_issues","list_label","list_notifications","list_pull_requests","list_releases","list_secret_scanning_alerts","list_starred_repositories","list_tags","pull_request_read","search_code","search_issues","search_orgs","search_pull_requests","search_repositories","search_users"]},{"name":"safeoutputs","tools":["add_comment","add_labels","create_issue","create_pull_request","missing_data","missing_tool","noop","push_to_pull_request_branch","remove_labels","update_issue"]}]} +# This file was automatically generated by gh-aw (v0.88.7). DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md # # ___ _ _ # / _ \ | | (_) @@ -17,7 +17,7 @@ # \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/ # # -# To update this file, edit githubnext/agentics/workflows/repo-assist.md@ae8d551f07c7ed7619f8c58c7bb4c3ac89395d38 and run: +# To update this file, edit githubnext/agentics/workflows/repo-assist.md@4bc8419fad05e6b032741cbfd189986700bcf71c and run: # gh aw compile # Not all edits will cause changes to this file. # @@ -26,21 +26,22 @@ # A friendly repository assistant that runs regularly (twice a day by default) to assist maintainers. # Can also be triggered on-demand via '/repo-assist ' to perform specific tasks. # - Labels and triages open issues -# - Comments helpfully on open issues to unblock contributors and onboard newcomers +# - Investigates open issues and resolves, fixes, clarifies, or comments on them # - Identifies issues that can be fixed and creates draft pull requests with fixes # - Improves performance, testing, and code quality via PRs # - Makes engineering investments: dependency updates, CI improvements, tooling # - Updates its own PRs when CI fails or merge conflicts arise -# - Nudges stale PRs waiting for author response +# - Improves documentation, performs ad hoc QA, and maintains project basics # - Takes the repository forward with proactive improvements # - Maintains a persistent memory of work done and what remains # Always polite, constructive, and mindful of the project's goals. # -# Source: githubnext/agentics/workflows/repo-assist.md@ae8d551f07c7ed7619f8c58c7bb4c3ac89395d38 +# Source: githubnext/agentics/workflows/repo-assist.md@4bc8419fad05e6b032741cbfd189986700bcf71c # # Secrets used: # - COPILOT_GITHUB_TOKEN # - GH_AW_CI_TRIGGER_TOKEN +# - GH_AW_DEFAULT_OTLP_HEADERS # - GH_AW_GITHUB_MCP_SERVER_TOKEN # - GH_AW_GITHUB_TOKEN # - GITHUB_TOKEN @@ -54,15 +55,15 @@ # - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 (source v9) # - actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 # - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 -# - github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2 +# - github/gh-aw-actions/setup@5e508589e03a7757a7e05b26e834292f5445bfb6 # v0.88.7 # # Container images used: -# - ghcr.io/github/gh-aw-firewall/agent:0.27.44@sha256:0d727725c737b58c7bdf51f640cffb928385ec46517e0917c7f1a02f1bada8b4 -# - ghcr.io/github/gh-aw-firewall/api-proxy:0.27.44@sha256:b50fbadba138f6e9aba94aca09711335c489bb3b15861220cb66f6092e042dc7 -# - ghcr.io/github/gh-aw-firewall/squid:0.27.44@sha256:83e48bbe12c634be8c228a576832fe45f66c529ac3659db92bddbcf2eeb6d627 -# - ghcr.io/github/gh-aw-mcpg:v0.4.9@sha256:e5a1569aeaf41820fa7bdee3e94468cae448133cdbf00119ad24f5b74db1ab9f +# - ghcr.io/github/gh-aw-firewall/agent:0.28.14@sha256:f7df036c86575527b61f3f7df91c4412349a12b2a74988d929eafa2999230c98 +# - ghcr.io/github/gh-aw-firewall/api-proxy:0.28.14@sha256:6f95e2234dd9bd6333a8ff28ccea7ecf0204acd4a09108723844dbd2bf6268c5 +# - ghcr.io/github/gh-aw-firewall/squid:0.28.14@sha256:2ce8df3abf3e9b76e9c0cf5863da41f1ab3f89b20ad14b988806ab89e7bf2cd5 +# - ghcr.io/github/gh-aw-mcpg:v0.4.18@sha256:85b940556a8faa4e1fdbef124bfd75f2c4ebd855a10b88a1c3b6f3e97f6f1a53 # - ghcr.io/github/gh-aw-node@sha256:a8082161d7dceda14b68f32eb39d0eaa96b825d07f5895b096afab9d9e0c7748 -# - ghcr.io/github/github-mcp-server:v1.9.0@sha256:881b53d6f75f69bdbc1b5b10fc2f1361717c19054143b3a8529fb5c32061a50e +# - ghcr.io/github/github-mcp-server:v1.11.0@sha256:fbec75de11c255213fa08d80fb166abe73d851fff631c51c0079872967720699 name: "Repo Assist" on: @@ -122,9 +123,18 @@ permissions: {} concurrency: group: "gh-aw-${{ github.workflow }}-${{ github.event.issue.number || github.event.pull_request.number || github.run_id }}" + queue: max run-name: "Repo Assist" +env: + OTEL_EXPORTER_OTLP_ENDPOINT: ${{ vars.GH_AW_DEFAULT_OTLP_ENDPOINT }} + OTEL_SERVICE_NAME: gh-aw.repo-assist + OTEL_RESOURCE_ATTRIBUTES: 'gh-aw.workflow.name=Repo%20Assist,gh-aw.repository=${{ github.repository }},gh-aw.run.id=${{ github.run_id }},github.run_id=${{ github.run_id }},gh-aw.engine.id=copilot' + OTEL_EXPORTER_OTLP_HEADERS: ${{ secrets.GH_AW_DEFAULT_OTLP_HEADERS }} + GH_AW_OTLP_ENDPOINTS: '[{"url":"${{ vars.GH_AW_DEFAULT_OTLP_ENDPOINT }}","headers":"${{ secrets.GH_AW_DEFAULT_OTLP_HEADERS }}"}]' + GH_AW_OTLP_IF_MISSING: ignore + jobs: activation: needs: pre_activation @@ -163,7 +173,7 @@ jobs: steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2 + uses: github/gh-aw-actions/setup@5e508589e03a7757a7e05b26e834292f5445bfb6 # v0.88.7 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} @@ -173,38 +183,42 @@ jobs: env: GH_AW_SETUP_WORKFLOW_NAME: "Repo Assist" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/repo-assist.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "1.0.79" - GH_AW_INFO_AWF_VERSION: "v0.27.44" + GH_AW_INFO_VERSION: "1.0.80" + GH_AW_INFO_AWF_VERSION: "v0.28.14" GH_AW_INFO_BODY_MODIFIED: "false" GH_AW_INFO_ENGINE_ID: "copilot" + - name: Mask OTLP telemetry headers + run: bash "${RUNNER_TEMP}/gh-aw/actions/mask_otlp_headers.sh" - name: Generate agentic run info id: generate_aw_info env: GH_AW_INFO_ENGINE_ID: "copilot" GH_AW_INFO_ENGINE_NAME: "GitHub Copilot CLI" GH_AW_INFO_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || vars.GH_AW_DEFAULT_MODEL_COPILOT || 'auto' }} - GH_AW_INFO_VERSION: "1.0.79" - GH_AW_INFO_AGENT_VERSION: "1.0.79" - GH_AW_INFO_CLI_VERSION: "v0.86.2" + GH_AW_INFO_VERSION: "1.0.80" + GH_AW_INFO_AGENT_VERSION: "1.0.80" + GH_AW_INFO_CLI_VERSION: "v0.88.7" GH_AW_INFO_WORKFLOW_NAME: "Repo Assist" GH_AW_INFO_EXPERIMENTAL: "false" GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true" GH_AW_INFO_STAGED: "false" - GH_AW_INFO_ALLOWED_DOMAINS: '["defaults","dotnet","node","python","rust","java"]' + GH_AW_INFO_ALLOWED_DOMAINS: '["defaults","dotnet","node","python","rust","java","github"]' GH_AW_INFO_FIREWALL_ENABLED: "true" - GH_AW_INFO_AWF_VERSION: "v0.27.44" + GH_AW_INFO_AWF_VERSION: "v0.28.14" GH_AW_INFO_AWMG_VERSION: "" GH_AW_INFO_FIREWALL_TYPE: "squid" GH_AW_INFO_AGENT_RUNTIME: "" - GH_AW_INFO_FRONTMATTER_SOURCE: "githubnext/agentics/workflows/repo-assist.md@ae8d551f07c7ed7619f8c58c7bb4c3ac89395d38" + GH_AW_INFO_FRONTMATTER_SOURCE: "githubnext/agentics/workflows/repo-assist.md@4bc8419fad05e6b032741cbfd189986700bcf71c" GH_AW_INFO_BODY_MODIFIED: "false" GH_AW_COMPILED_STRICT: "true" uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/generate_aw_info.cjs'); + const { main } = require(path.join(actionsDir, 'generate_aw_info.cjs')); await main(core, context); - name: Restore daily AIC usage cache id: restore-daily-aic-cache @@ -226,9 +240,11 @@ jobs: with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/restore_aic_usage_cache_fallback.cjs'); + const { main } = require(path.join(actionsDir, 'restore_aic_usage_cache_fallback.cjs')); await main(); - name: Check daily workflow token guardrail id: daily-effective-workflow-guardrail @@ -246,9 +262,11 @@ jobs: with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/check_daily_aic_workflow_guardrail.cjs'); + const { main } = require(path.join(actionsDir, 'check_daily_aic_workflow_guardrail.cjs')); await main(); - name: Add eyes reaction for immediate feedback id: react @@ -259,9 +277,11 @@ jobs: with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/add_reaction.cjs'); + const { main } = require(path.join(actionsDir, 'add_reaction.cjs')); await main(); - name: Validate COPILOT_GITHUB_TOKEN secret id: validate-secret @@ -302,30 +322,36 @@ jobs: GH_AW_CONTEXT_WORKFLOW_REF: "${{ github.workflow_ref }}" with: script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/check_workflow_timestamp_api.cjs'); + const { main } = require(path.join(actionsDir, 'check_workflow_timestamp_api.cjs')); await main(); - name: Check compile-agentic version uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: - GH_AW_COMPILED_VERSION: "v0.86.2" + GH_AW_COMPILED_VERSION: "v0.88.7" with: script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/check_version_updates.cjs'); + const { main } = require(path.join(actionsDir, 'check_version_updates.cjs')); await main(); - name: Compute current body text id: sanitized uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: - GH_AW_ALLOWED_DOMAINS: "*.gradle-enterprise.cloud,*.pythonhosted.org,*.vsblob.vsassets.io,adoptium.net,anaconda.org,api.adoptium.net,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.foojay.io,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.nuget.org,api.snapcraft.io,archive.apache.org,archive.ubuntu.com,azure.archive.ubuntu.com,azuresearch-usnc.nuget.org,azuresearch-ussc.nuget.org,binstar.org,bootstrap.pypa.io,builds.dotnet.microsoft.com,bun.sh,cdn.azul.com,cdn.jsdelivr.net,central.sonatype.com,ci.dot.net,conda.anaconda.org,conda.binstar.org,crates.io,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,dc.services.visualstudio.com,deb.nodesource.com,deno.land,develocity.apache.org,dist.nuget.org,dl.google.com,dlcdn.apache.org,dot.net,dotnet.microsoft.com,dotnetcli.blob.core.windows.net,download.eclipse.org,download.java.net,download.oracle.com,downloads.gradle-dn.com,esm.sh,files.pythonhosted.org,ge.spockframework.org,get.pnpm.io,github.com,googleapis.deno.dev,googlechromelabs.github.io,gradle.org,host.docker.internal,index.crates.io,jcenter.bintray.com,jdk.java.net,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,maven-central.storage-download.googleapis.com,maven.apache.org,maven.google.com,maven.oracle.com,maven.pkg.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,nuget.org,nuget.pkg.github.com,nugetregistryv2prod.blob.core.windows.net,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,oneocsp.microsoft.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,pip.pypa.io,pkgs.dev.azure.com,plugins-artifacts.gradle.org,plugins.gradle.org,ppa.launchpad.net,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.gradle.org,repo.grails.org,repo.maven.apache.org,repo.spring.io,repo.yarnpkg.com,repo1.maven.org,repository.apache.org,s.symcb.com,s.symcd.com,scans-in.gradle.com,security.ubuntu.com,services.gradle.org,sh.rustup.rs,skimdb.npmjs.com,static.crates.io,static.rust-lang.org,storage.googleapis.com,telemetry.enterprise.githubcopilot.com,telemetry.vercel.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com,www.java.com,www.microsoft.com,www.npmjs.com,www.npmjs.org,yarnpkg.com" + GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,*.gradle-enterprise.cloud,*.pythonhosted.org,*.vsblob.vsassets.io,adoptium.net,anaconda.org,api.adoptium.net,api.foojay.io,api.npms.io,api.nuget.org,api.snapcraft.io,archive.apache.org,archive.ubuntu.com,azure.archive.ubuntu.com,azuresearch-usnc.nuget.org,azuresearch-ussc.nuget.org,binstar.org,bootstrap.pypa.io,builds.dotnet.microsoft.com,bun.sh,cdn.azul.com,cdn.jsdelivr.net,central.sonatype.com,ci.dot.net,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,dc.services.visualstudio.com,deb.nodesource.com,deno.land,develocity.apache.org,dist.nuget.org,dl.google.com,dlcdn.apache.org,docs.github.com,dot.net,dotnet.microsoft.com,dotnetcli.blob.core.windows.net,download.eclipse.org,download.java.net,download.oracle.com,downloads.gradle-dn.com,esm.sh,files.pythonhosted.org,ge.spockframework.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.blog,github.com,github.githubassets.com,googleapis.deno.dev,googlechromelabs.github.io,gradle.org,index.crates.io,jcenter.bintray.com,jdk.java.net,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,maven-central.storage-download.googleapis.com,maven.apache.org,maven.google.com,maven.oracle.com,maven.pkg.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,nuget.org,nuget.pkg.github.com,nugetregistryv2prod.blob.core.windows.net,objects.githubusercontent.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,oneocsp.microsoft.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,patch-diff.githubusercontent.com,patchdiff.githubusercontent.com,pip.pypa.io,pkgs.dev.azure.com,plugins-artifacts.gradle.org,plugins.gradle.org,ppa.launchpad.net,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.gradle.org,repo.grails.org,repo.maven.apache.org,repo.spring.io,repo.yarnpkg.com,repo1.maven.org,repository.apache.org,s.symcb.com,s.symcd.com,scans-in.gradle.com,security.ubuntu.com,services.gradle.org,sh.rustup.rs,skimdb.npmjs.com,static.crates.io,static.rust-lang.org,storage.googleapis.com,telemetry.vercel.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com,www.java.com,www.microsoft.com,www.npmjs.com,www.npmjs.org,yarnpkg.com" with: script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/compute_text.cjs'); + const { main } = require(path.join(actionsDir, 'compute_text.cjs')); await main(); - name: Add comment with workflow run link id: add-comment @@ -336,9 +362,11 @@ jobs: GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"\\u003e Generated by 🌈 {workflow_name}, see [workflow run]({run_url}). [Learn more](https://github.com/githubnext/agentics/blob/main/docs/repo-assist.md).\",\"runStarted\":\"{workflow_name} is processing {event_type}, see [workflow run]({run_url})...\",\"runSuccess\":\"βœ“ {workflow_name} completed successfully, see [workflow run]({run_url}).\",\"runFailure\":\"βœ— {workflow_name} encountered {status}, see [workflow run]({run_url}).\"}" with: script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/add_workflow_run_comment.cjs'); + const { main } = require(path.join(actionsDir, 'add_workflow_run_comment.cjs')); await main(); - name: Log runtime features if: ${{ contains(toJSON(vars), '"GH_AW_RUNTIME_FEATURES":') }} @@ -349,7 +377,7 @@ jobs: GH_AW_ACTIONS_DIR: ${{ runner.temp }}/gh-aw/actions GH_AW_PROMPT: ${{ runner.temp }}/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ runner.temp }}/gh-aw/safeoutputs/outputs.jsonl - GH_AW_PROMPT_CONFIG: "{\"items\":[{\"content_env\":\"GH_AW_PROMPT_CONTENT_0000\"},{\"file\":\"xpia.md\"},{\"file\":\"temp_folder_prompt.md\"},{\"file\":\"markdown.md\"},{\"file\":\"repo_memory_prompt.md\"},{\"file\":\"safe_outputs_prompt.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0001\"},{\"file\":\"safe_outputs_create_pull_request.md\"},{\"file\":\"safe_outputs_push_to_pr_branch.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0002\"},{\"file\":\"mcp_cli_tools_prompt.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0003\"},{\"file\":\"github_mcp_tools_with_safeoutputs_prompt.md\"},{\"file\":\"pr_context_prompt.md\",\"condition_env\":\"GH_AW_INCLUDE_PR_CONTEXT\"},{\"file\":\"pr_context_push_to_pr_branch_guidance.md\",\"condition_env\":\"GH_AW_INCLUDE_PR_CONTEXT\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0004\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0005\"}]}" + GH_AW_PROMPT_CONFIG: "{\"items\":[{\"content_env\":\"GH_AW_PROMPT_CONTENT_0000\"},{\"file\":\"xpia.md\"},{\"file\":\"temp_folder_prompt.md\"},{\"file\":\"markdown.md\"},{\"file\":\"repo_memory_prompt.md\"},{\"file\":\"safe_outputs_prompt.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0001\"},{\"file\":\"safe_outputs_create_pull_request.md\"},{\"file\":\"safe_outputs_push_to_pr_branch.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0002\"},{\"file\":\"mcp_cli_tools_with_safeoutputs_prompt.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0003\"},{\"file\":\"github_mcp_tools_with_safeoutputs_prompt.md\"},{\"file\":\"pr_context_prompt.md\",\"condition_env\":\"GH_AW_INCLUDE_PR_CONTEXT\"},{\"file\":\"pr_context_push_to_pr_branch_guidance.md\",\"condition_env\":\"GH_AW_INCLUDE_PR_CONTEXT\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0004\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0005\"}]}" GH_AW_EXPR_1A3A194A: ${{ github.event.discussion.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'discussion' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} GH_AW_EXPR_1DD9F1B7: ${{ steps.sanitized.outputs.text || inputs.command }} GH_AW_EXPR_463A214A: ${{ github.event.pull_request.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'pull_request' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} @@ -389,9 +417,11 @@ jobs: GH_AW_STEPS_SANITIZED_OUTPUTS_TEXT: ${{ steps.sanitized.outputs.text }} with: script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/interpolate_prompt.cjs'); + const { main } = require(path.join(actionsDir, 'interpolate_prompt.cjs')); await main(); - name: Substitute placeholders uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -411,7 +441,7 @@ jobs: GH_AW_INPUTS_COMMAND: ${{ inputs.command }} GH_AW_MCP_CLI_SERVERS_LIST: "- `github` β€” run `github --help` to see available tools\n- `safeoutputs` β€” run `safeoutputs --help` to see available tools" GH_AW_MEMORY_BRANCH_NAME: 'memory/repo-assist' - GH_AW_MEMORY_CONSTRAINTS: "\n\n**Constraints:**\n- **Max File Size**: 102400 bytes (0.10 MB) per file\n- **Max File Count**: 100 files per commit\n- **Max Patch Size**: 10240 bytes (10 KB) total per push (max: 1024 KB)\n" + GH_AW_MEMORY_CONSTRAINTS: "\n\n**Constraints:**\n- **Max File Size**: 65536 bytes (0.06 MB) per file\n- **Max File Count**: 1 files per commit\n- **Max Patch Size**: 65536 bytes (64 KB) total per push (max: 1024 KB)\n" GH_AW_MEMORY_DESCRIPTION: '' GH_AW_MEMORY_DIR: '/tmp/gh-aw/repo-memory/default/' GH_AW_MEMORY_TARGET_REPO: ' of the current repository' @@ -421,10 +451,12 @@ jobs: GH_AW_WIKI_NOTE: '' with: script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); setupGlobals(core, github, context, exec, io, getOctokit); - const substitutePlaceholders = require('${{ runner.temp }}/gh-aw/actions/substitute_placeholders.cjs'); + const substitutePlaceholders = require(path.join(actionsDir, 'substitute_placeholders.cjs')); // Call the substitution function return await substitutePlaceholders({ @@ -469,7 +501,7 @@ jobs: mkdir -p /tmp/gh-aw/aw-prompts cp -a "${RUNNER_TEMP}/gh-aw/aw-prompts/." /tmp/gh-aw/aw-prompts/ - name: Upload activation artifact - if: success() + if: success() || failure() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: activation @@ -492,12 +524,19 @@ jobs: if: needs.activation.outputs.daily_ai_credits_exceeded != 'true' runs-on: ubuntu-latest permissions: read-all + timeout-minutes: 60 env: DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} GH_AW_ASSETS_ALLOWED_EXTS: "" GH_AW_ASSETS_BRANCH: "" GH_AW_ASSETS_MAX_SIZE_KB: 0 GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs + GH_AW_PR_HEAD_BASE_BRANCH: "" + GH_AW_PR_HEAD_BASE_PR_NUMBER: "" + GH_AW_PR_HEAD_BASE_REF: "" + GH_AW_PR_HEAD_BASE_REPO: "" + GH_AW_PR_HEAD_BASE_SHA: "" + GH_AW_PR_HEAD_REPO: "" GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }} GH_AW_WORKFLOW_ID_SANITIZED: repoassist outputs: @@ -522,11 +561,12 @@ jobs: setup-parent-span-id: ${{ steps.setup.outputs.parent-span-id || steps.setup.outputs.span-id }} setup-span-id: ${{ steps.setup.outputs.span-id }} setup-trace-id: ${{ steps.setup.outputs.trace-id }} + shell_expansion_guard_rejected: ${{ steps.detect-agent-errors.outputs.shell_expansion_guard_rejected || 'false' }} unknown_model_ai_credits: ${{ steps.parse-mcp-gateway.outputs.unknown_model_ai_credits || 'false' }} steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2 + uses: github/gh-aw-actions/setup@5e508589e03a7757a7e05b26e834292f5445bfb6 # v0.88.7 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} @@ -535,18 +575,27 @@ jobs: env: GH_AW_SETUP_WORKFLOW_NAME: "Repo Assist" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/repo-assist.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "1.0.79" - GH_AW_INFO_AWF_VERSION: "v0.27.44" + GH_AW_INFO_VERSION: "1.0.80" + GH_AW_INFO_AWF_VERSION: "v0.28.14" GH_AW_INFO_BODY_MODIFIED: "false" GH_AW_INFO_ENGINE_ID: "copilot" - name: Set runtime paths id: set-runtime-paths + env: + GH_AW_RUNNER_TOOL_CACHE: ${{ runner.tool_cache }} run: | + if [ -z "${RUNNER_TOOL_CACHE:-}" ]; then + echo "RUNNER_TOOL_CACHE=${GH_AW_RUNNER_TOOL_CACHE}" >> "$GITHUB_ENV" + fi { echo "GH_AW_SAFE_OUTPUTS=${RUNNER_TEMP}/gh-aw/safeoutputs/outputs.jsonl" echo "GH_AW_SAFE_OUTPUTS_CONFIG_PATH=${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" echo "GH_AW_SAFE_OUTPUTS_TOOLS_PATH=${RUNNER_TEMP}/gh-aw/safeoutputs/tools.json" } >> "$GITHUB_OUTPUT" + - name: Mask OTLP telemetry headers + run: bash "${RUNNER_TEMP}/gh-aw/actions/mask_otlp_headers.sh" + - name: Check OTLP telemetry configuration + run: bash "${RUNNER_TEMP}/gh-aw/actions/check_otlp_default_credentials.sh" - name: Checkout repository uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: @@ -576,7 +625,7 @@ jobs: GITHUB_COPILOT_BASE_URL: ${{ env.GITHUB_COPILOT_BASE_URL }} GH_AW_NETWORK_ISOLATION: 'true' DIFC_PROXY_POLICY: '{"allow-only":{"min-integrity":"none","repos":"all"}}' - DIFC_PROXY_IMAGE: 'ghcr.io/github/gh-aw-mcpg:v0.4.9' + DIFC_PROXY_IMAGE: 'ghcr.io/github/gh-aw-mcpg:v0.4.18' run: | bash "${RUNNER_TEMP}/gh-aw/actions/start_difc_proxy.sh" - name: Download activation artifact @@ -616,16 +665,15 @@ jobs: open_issues = len(issues) unlabelled = sum(1 for i in issues if not i.get('labels')) repo_assist_prs = sum(1 for p in prs if p['title'].startswith('[repo-assist]')) - other_prs = sum(1 for p in prs if not p['title'].startswith('[repo-assist]')) task_names = { 1: 'Issue Labelling', - 2: 'Issue Investigation and Comment', + 2: 'Issue Investigation then Resolve, Fix, Seek Clarification or Comment', 3: 'Issue Investigation and Fix', 4: 'Engineering Investments', 5: 'Coding Improvements', 6: 'Maintain Repo Assist PRs', - 7: 'Stale PR Nudges', + 7: 'Documentation Improvements, Ad Hoc QA, and Project Basics', 8: 'Performance Improvements', 9: 'Testing Improvements', 10: 'Take the Repository Forward', @@ -638,7 +686,7 @@ jobs: 4: 5 + 0.2 * open_issues, 5: 5 + 0.1 * open_issues, 6: float(repo_assist_prs), - 7: 0.1 * other_prs, + 7: 3 + 0.05 * open_issues, 8: 3 + 0.05 * open_issues, 9: 3 + 0.05 * open_issues, 10: 3 + 0.05 * open_issues, @@ -665,7 +713,6 @@ jobs: print(f'Open issues : {open_issues}') print(f'Unlabelled issues : {unlabelled}') print(f'Repo Assist PRs : {repo_assist_prs}') - print(f'Other open PRs : {other_prs}') print() print('Task weights:') for t, w in weights.items(): @@ -676,7 +723,7 @@ jobs: result = { 'open_issues': open_issues, 'unlabelled_issues': unlabelled, - 'repo_assist_prs': repo_assist_prs, 'other_prs': other_prs, + 'repo_assist_prs': repo_assist_prs, 'task_names': task_names, 'weights': {str(k): round(v, 2) for k, v in weights.items()}, 'selected_tasks': chosen, @@ -707,19 +754,19 @@ jobs: with: github-token: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/checkout_pr_branch.cjs'); + const { main } = require(path.join(actionsDir, 'checkout_pr_branch.cjs')); await main(); - - name: Install ripgrep - run: bash "${RUNNER_TEMP}/gh-aw/actions/install_ripgrep.sh" - name: Install GitHub Copilot CLI run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" env: GH_HOST: github.com - GH_AW_COMPILED_VERSION: v0.86.2 + GH_AW_COMPILED_VERSION: v0.88.7 - name: Install AWF binary - run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.27.44 --rootless + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.28.14 --rootless - name: Determine automatic lockdown mode for GitHub MCP Server id: determine-automatic-lockdown uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 (source v9) @@ -729,7 +776,9 @@ jobs: GH_AW_GITHUB_MIN_INTEGRITY: 'none' with: script: | - const determineAutomaticLockdown = require('${{ runner.temp }}/gh-aw/actions/determine_automatic_lockdown.cjs'); + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const determineAutomaticLockdown = require(path.join(actionsDir, 'determine_automatic_lockdown.cjs')); await determineAutomaticLockdown(github, context, core); - name: Parse integrity filter lists id: parse-guard-vars @@ -758,15 +807,26 @@ jobs: GH_AW_SKILL_DIR: ".github/skills" run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_inline_skills.sh" - name: Download container images - run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.27.44@sha256:0d727725c737b58c7bdf51f640cffb928385ec46517e0917c7f1a02f1bada8b4 ghcr.io/github/gh-aw-firewall/api-proxy:0.27.44@sha256:b50fbadba138f6e9aba94aca09711335c489bb3b15861220cb66f6092e042dc7 ghcr.io/github/gh-aw-firewall/squid:0.27.44@sha256:83e48bbe12c634be8c228a576832fe45f66c529ac3659db92bddbcf2eeb6d627 ghcr.io/github/gh-aw-mcpg:v0.4.9@sha256:e5a1569aeaf41820fa7bdee3e94468cae448133cdbf00119ad24f5b74db1ab9f ghcr.io/github/gh-aw-node@sha256:a8082161d7dceda14b68f32eb39d0eaa96b825d07f5895b096afab9d9e0c7748 ghcr.io/github/github-mcp-server:v1.9.0@sha256:881b53d6f75f69bdbc1b5b10fc2f1361717c19054143b3a8529fb5c32061a50e - - name: Generate Safe Outputs Config + run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.28.14@sha256:f7df036c86575527b61f3f7df91c4412349a12b2a74988d929eafa2999230c98 ghcr.io/github/gh-aw-firewall/api-proxy:0.28.14@sha256:6f95e2234dd9bd6333a8ff28ccea7ecf0204acd4a09108723844dbd2bf6268c5 ghcr.io/github/gh-aw-firewall/squid:0.28.14@sha256:2ce8df3abf3e9b76e9c0cf5863da41f1ab3f89b20ad14b988806ab89e7bf2cd5 ghcr.io/github/gh-aw-mcpg:v0.4.18@sha256:85b940556a8faa4e1fdbef124bfd75f2c4ebd855a10b88a1c3b6f3e97f6f1a53 ghcr.io/github/gh-aw-node@sha256:a8082161d7dceda14b68f32eb39d0eaa96b825d07f5895b096afab9d9e0c7748 ghcr.io/github/github-mcp-server:v1.11.0@sha256:fbec75de11c255213fa08d80fb166abe73d851fff631c51c0079872967720699 + - name: Prepare Safe Outputs Directories run: | mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs - cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_923f890bec99273a_EOF' - {"add_comment":{"hide_older_comments":true,"max":10,"target":"*"},"add_labels":{"allowed":["bug","enhancement","help wanted","good first issue","spam","off topic","documentation","question","duplicate","wontfix","needs triage","needs investigation","breaking change","performance","security","refactor"],"max":30,"target":"*"},"create_issue":{"labels":["automation","repo-assist"],"max":4,"title_prefix":"[repo-assist] "},"create_pull_request":{"draft":true,"labels":["automation","repo-assist"],"max":4,"max_patch_files":100,"max_patch_size":4096,"protect_top_level_dot_folders":true,"protected_files":["package.json","bun.lockb","bunfig.toml","deno.json","deno.jsonc","deno.lock","global.json","NuGet.Config","Directory.Packages.props","mix.exs","mix.lock","go.mod","go.sum","stack.yaml","stack.yaml.lock","pom.xml","build.gradle","build.gradle.kts","settings.gradle","settings.gradle.kts","gradle.properties","package-lock.json","yarn.lock","pnpm-lock.yaml","npm-shrinkwrap.json","requirements.txt","Pipfile","Pipfile.lock","pyproject.toml","setup.py","setup.cfg","Gemfile","Gemfile.lock","uv.lock","CODEOWNERS","DESIGN.md","README.md","CONTRIBUTING.md","CHANGELOG.md","SECURITY.md","CODE_OF_CONDUCT.md","AGENTS.md"],"protected_files_policy":"fallback-to-issue","title_prefix":"[repo-assist] "},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"false"},"push_repo_memory":{"memories":[{"dir":"/tmp/gh-aw/repo-memory/default","id":"default","max_file_count":100,"max_file_size":102400,"max_patch_size":10240}]},"push_to_pull_request_branch":{"if_no_changes":"warn","max":4,"max_patch_size":4096,"protect_top_level_dot_folders":true,"protected_files":["package.json","bun.lockb","bunfig.toml","deno.json","deno.jsonc","deno.lock","global.json","NuGet.Config","Directory.Packages.props","mix.exs","mix.lock","go.mod","go.sum","stack.yaml","stack.yaml.lock","pom.xml","build.gradle","build.gradle.kts","settings.gradle","settings.gradle.kts","gradle.properties","package-lock.json","yarn.lock","pnpm-lock.yaml","npm-shrinkwrap.json","requirements.txt","Pipfile","Pipfile.lock","pyproject.toml","setup.py","setup.cfg","Gemfile","Gemfile.lock","uv.lock","CODEOWNERS","DESIGN.md","README.md","CONTRIBUTING.md","CHANGELOG.md","SECURITY.md","CODE_OF_CONDUCT.md","AGENTS.md"],"protected_files_policy":"fallback-to-issue","target":"*","title_prefix":"[repo-assist] "},"remove_labels":{"allowed":["bug","enhancement","help wanted","good first issue","spam","off topic","documentation","question","duplicate","wontfix","needs triage","needs investigation","breaking change","performance","security","refactor"],"max":5,"target":"*"},"report_incomplete":{},"update_issue":{"allow_body":true,"max":1,"required_title_prefix":"[repo-assist] ","target":"*"}} - GH_AW_SAFE_OUTPUTS_CONFIG_923f890bec99273a_EOF + - name: Generate Safe Outputs Config + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_FILE_ROOT: "${{ runner.temp }}/gh-aw" + GH_AW_FILE_CONFIG: "{\"files\":[{\"path\":\"safeoutputs/config.json\",\"content_env\":\"GH_AW_SAFE_OUTPUTS_CONFIG\"}]}" + GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_comment\":{\"hide_older_comments\":true,\"max\":10,\"target\":\"*\"},\"add_labels\":{\"allowed\":[\"bug\",\"enhancement\",\"help wanted\",\"good first issue\",\"spam\",\"off topic\",\"documentation\",\"question\",\"duplicate\",\"wontfix\",\"needs triage\",\"needs investigation\",\"breaking change\",\"performance\",\"security\",\"refactor\"],\"max\":30,\"target\":\"*\"},\"create_issue\":{\"labels\":[\"automation\",\"repo-assist\"],\"max\":4,\"title_prefix\":\"[repo-assist] \"},\"create_pull_request\":{\"draft\":true,\"labels\":[\"automation\",\"repo-assist\"],\"max\":4,\"max_patch_files\":100,\"max_patch_size\":4096,\"protect_top_level_dot_folders\":true,\"protected_files\":[\"package.json\",\"bun.lockb\",\"bunfig.toml\",\"deno.json\",\"deno.jsonc\",\"deno.lock\",\"global.json\",\"NuGet.Config\",\"Directory.Packages.props\",\"mix.exs\",\"mix.lock\",\"go.mod\",\"go.sum\",\"stack.yaml\",\"stack.yaml.lock\",\"pom.xml\",\"build.gradle\",\"build.gradle.kts\",\"settings.gradle\",\"settings.gradle.kts\",\"gradle.properties\",\"package-lock.json\",\"yarn.lock\",\"pnpm-lock.yaml\",\"npm-shrinkwrap.json\",\"requirements.txt\",\"Pipfile\",\"Pipfile.lock\",\"pyproject.toml\",\"setup.py\",\"setup.cfg\",\"Gemfile\",\"Gemfile.lock\",\"uv.lock\",\"CODEOWNERS\",\"DESIGN.md\",\"CONTRIBUTING.md\",\"SECURITY.md\",\"CODE_OF_CONDUCT.md\",\"AGENTS.md\"],\"protected_files_policy\":\"request_review\",\"title_prefix\":\"[repo-assist] \"},\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"false\"},\"push_repo_memory\":{\"memories\":[{\"allowed_extensions\":[\".json\"],\"dir\":\"/tmp/gh-aw/repo-memory/default\",\"format_json\":true,\"id\":\"default\",\"max_file_count\":1,\"max_file_size\":65536,\"max_patch_size\":65536,\"validation\":{\"script\":\"const fs = require(\\\"node:fs\\\");\\nconst path = require(\\\"node:path\\\");\\nconst fail = message => { throw new Error(`notes.json: ${message}`); };\\nconst notesPath = path.join(memoryRoot, \\\"notes.json\\\");\\nif (!fs.existsSync(notesPath)) fail(\\\"missing (create an initial notes.json that matches schema version 1)\\\");\\nconst data = JSON.parse(fs.readFileSync(notesPath, \\\"utf8\\\"));\\nconst isObject = value => value !== null && typeof value === \\\"object\\\" && !Array.isArray(value);\\nconst exactKeys = (value, keys) => isObject(value) && Object.keys(value).sort().join(\\\",\\\") === [...keys].sort().join(\\\",\\\");\\nconst validDate = value => typeof value === \\\"string\\\" && /^[0-9]{4}-[0-9]{2}-[0-9]{2}$/.test(value);\\nconst validText = (value, maximum) => typeof value === \\\"string\\\" && value.length > 0 && value.length <= maximum;\\nconst unique = (entries, key, label) => {\\n const values = entries.map(key);\\n if (new Set(values).size !== values.length) fail(`${label} must be unique`);\\n};\\n\\nif (!exactKeys(data, [\\\"version\\\", \\\"cursors\\\", \\\"issues\\\", \\\"fixes\\\", \\\"checks\\\", \\\"completed_actions\\\", \\\"priorities\\\"])) fail(\\\"must contain exactly version, cursors, issues, fixes, checks, completed_actions, and priorities\\\");\\nif (data.version !== 1) fail(\\\"version must be 1\\\");\\nif (!exactKeys(data.cursors, [\\\"labelling_after\\\", \\\"investigation_after\\\"])) fail(\\\"cursors must contain exactly labelling_after and investigation_after\\\");\\nfor (const [name, value] of Object.entries(data.cursors)) {\\n if (value !== null && (!Number.isInteger(value) || value < 1)) fail(`${name} must be null or a positive issue number`);\\n}\\n\\nconst issueStates = new Set([\\\"commented\\\", \\\"awaiting_clarification\\\", \\\"resolution_recommended\\\", \\\"deferred\\\", \\\"awaiting_approval\\\"]);\\nif (!Array.isArray(data.issues) || data.issues.length > 100) fail(\\\"issues must be an array of at most 100 entries\\\");\\nfor (const [index, entry] of data.issues.entries()) {\\n if (!exactKeys(entry, [\\\"number\\\", \\\"state\\\", \\\"updated_at\\\", \\\"note\\\"])) fail(`invalid issues entry at index ${index}`);\\n if (!Number.isInteger(entry.number) || entry.number < 1) fail(`invalid issue number at index ${index}`);\\n if (!issueStates.has(entry.state)) fail(`invalid issue state at index ${index}`);\\n if (!validDate(entry.updated_at)) fail(`invalid issue date at index ${index}`);\\n if (!validText(entry.note, 300)) fail(`invalid issue note at index ${index}`);\\n}\\nunique(data.issues, entry => entry.number, \\\"issue numbers\\\");\\n\\nconst fixStates = new Set([\\\"open\\\", \\\"merged\\\", \\\"closed\\\", \\\"blocked\\\"]);\\nif (!Array.isArray(data.fixes) || data.fixes.length > 50) fail(\\\"fixes must be an array of at most 50 entries\\\");\\nfor (const [index, entry] of data.fixes.entries()) {\\n if (!exactKeys(entry, [\\\"issue\\\", \\\"pr\\\", \\\"branch\\\", \\\"status\\\", \\\"updated_at\\\", \\\"note\\\"])) fail(`invalid fixes entry at index ${index}`);\\n if (!Number.isInteger(entry.issue) || entry.issue < 1) fail(`invalid fix issue at index ${index}`);\\n if (entry.pr !== null && (!Number.isInteger(entry.pr) || entry.pr < 1)) fail(`invalid fix PR at index ${index}`);\\n if (entry.branch !== null && !validText(entry.branch, 120)) fail(`invalid fix branch at index ${index}`);\\n if (!fixStates.has(entry.status)) fail(`invalid fix status at index ${index}`);\\n if (!validDate(entry.updated_at)) fail(`invalid fix date at index ${index}`);\\n if (!validText(entry.note, 300)) fail(`invalid fix note at index ${index}`);\\n}\\nunique(data.fixes, entry => entry.issue, \\\"fix issue numbers\\\");\\nunique(data.fixes.filter(entry => entry.pr !== null), entry => entry.pr, \\\"fix PR numbers\\\");\\n\\nconst checkAreas = new Set([\\\"dependencies\\\", \\\"ci\\\", \\\"tooling\\\", \\\"build\\\", \\\"code\\\", \\\"docs\\\", \\\"qa\\\", \\\"hygiene\\\", \\\"performance\\\", \\\"tests\\\", \\\"release\\\", \\\"repo_assist_prs\\\"]);\\nif (!Array.isArray(data.checks) || data.checks.length > checkAreas.size) fail(\\\"checks must contain at most one entry per area\\\");\\nfor (const [index, entry] of data.checks.entries()) {\\n if (!exactKeys(entry, [\\\"area\\\", \\\"checked_at\\\", \\\"result\\\", \\\"follow_up\\\"])) fail(`invalid checks entry at index ${index}`);\\n if (!checkAreas.has(entry.area)) fail(`invalid check area at index ${index}`);\\n if (!validDate(entry.checked_at)) fail(`invalid check date at index ${index}`);\\n if (!validText(entry.result, 300)) fail(`invalid check result at index ${index}`);\\n if (entry.follow_up !== null && !validText(entry.follow_up, 300)) fail(`invalid check follow_up at index ${index}`);\\n}\\nunique(data.checks, entry => entry.area, \\\"check areas\\\");\\n\\nif (!Array.isArray(data.completed_actions) || data.completed_actions.length > 100) fail(\\\"completed_actions must be an array of at most 100 entries\\\");\\nfor (const [index, entry] of data.completed_actions.entries()) {\\n if (!exactKeys(entry, [\\\"key\\\", \\\"completed_at\\\"])) fail(`invalid completed_actions entry at index ${index}`);\\n if (!validText(entry.key, 100)) fail(`invalid completed action key at index ${index}`);\\n if (!validDate(entry.completed_at)) fail(`invalid completed action date at index ${index}`);\\n}\\nunique(data.completed_actions, entry => entry.key, \\\"completed action keys\\\");\\n\\nif (!Array.isArray(data.priorities) || data.priorities.length > 20) fail(\\\"priorities must be an array of at most 20 entries\\\");\\nfor (const [index, entry] of data.priorities.entries()) {\\n if (!exactKeys(entry, [\\\"task\\\", \\\"item\\\", \\\"note\\\"])) fail(`invalid priorities entry at index ${index}`);\\n if (!Number.isInteger(entry.task) || entry.task < 1 || entry.task > 10) fail(`invalid priority task at index ${index}`);\\n if (!validText(entry.item, 100)) fail(`invalid priority item at index ${index}`);\\n if (!validText(entry.note, 300)) fail(`invalid priority note at index ${index}`);\\n}\\nunique(data.priorities, entry => `${entry.task}:${entry.item}`, \\\"priority task/item pairs\\\");\\nconsole.log(\\\"repo-assist notes.json conforms to schema\\\");\\n\",\"timeout\":60}}]},\"push_to_pull_request_branch\":{\"if_no_changes\":\"warn\",\"max\":4,\"max_patch_size\":4096,\"protect_top_level_dot_folders\":true,\"protected_files\":[\"package.json\",\"bun.lockb\",\"bunfig.toml\",\"deno.json\",\"deno.jsonc\",\"deno.lock\",\"global.json\",\"NuGet.Config\",\"Directory.Packages.props\",\"mix.exs\",\"mix.lock\",\"go.mod\",\"go.sum\",\"stack.yaml\",\"stack.yaml.lock\",\"pom.xml\",\"build.gradle\",\"build.gradle.kts\",\"settings.gradle\",\"settings.gradle.kts\",\"gradle.properties\",\"package-lock.json\",\"yarn.lock\",\"pnpm-lock.yaml\",\"npm-shrinkwrap.json\",\"requirements.txt\",\"Pipfile\",\"Pipfile.lock\",\"pyproject.toml\",\"setup.py\",\"setup.cfg\",\"Gemfile\",\"Gemfile.lock\",\"uv.lock\",\"CODEOWNERS\",\"DESIGN.md\",\"CONTRIBUTING.md\",\"SECURITY.md\",\"CODE_OF_CONDUCT.md\",\"AGENTS.md\"],\"protected_files_policy\":\"allowed\",\"target\":\"*\",\"title_prefix\":\"[repo-assist] \"},\"remove_labels\":{\"allowed\":[\"bug\",\"enhancement\",\"help wanted\",\"good first issue\",\"spam\",\"off topic\",\"documentation\",\"question\",\"duplicate\",\"wontfix\",\"needs triage\",\"needs investigation\",\"breaking change\",\"performance\",\"security\",\"refactor\"],\"max\":5,\"target\":\"*\"},\"report_incomplete\":{},\"update_issue\":{\"allow_body\":true,\"max\":1,\"required_title_prefix\":\"[repo-assist] \",\"target\":\"*\"}}" + with: + script: | + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require(path.join(actionsDir, 'create_files.cjs')); + await main(); - name: Generate Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -845,6 +905,7 @@ jobs: "create_issue": { "defaultMax": 1, "fields": { + "blocked_by": {}, "body": { "required": true, "type": "string", @@ -899,6 +960,12 @@ jobs: "sanitize": true, "maxLength": 256 }, + "dependencies": { + "type": "array", + "itemType": "string", + "itemSanitize": true, + "itemMaxLength": 256 + }, "draft": { "type": "boolean" }, @@ -912,6 +979,14 @@ jobs: "type": "string", "maxLength": 256 }, + "stack_position": { + "optionalPositiveInteger": true + }, + "stack_root": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, "temporary_id": { "type": "string", "pattern": "^#?aw_[A-Za-z0-9_]{3,12}$" @@ -1101,9 +1176,11 @@ jobs: uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/generate_safe_outputs_tools.cjs'); + const { main } = require(path.join(actionsDir, 'generate_safe_outputs_tools.cjs')); await main(); - name: Start MCP Gateway id: start-mcp-gateway @@ -1118,34 +1195,45 @@ jobs: run: | set -eo pipefail mkdir -p "${RUNNER_TEMP}/gh-aw/mcp-config" + if [ -n "${GITHUB_EVENT_PATH:-}" ] && [ -r "${GITHUB_EVENT_PATH}" ]; then + GH_AW_SAFEOUTPUTS_EVENT_PATH="${RUNNER_TEMP}/gh-aw/safeoutputs/github_event.json" + cp "${GITHUB_EVENT_PATH}" "${GH_AW_SAFEOUTPUTS_EVENT_PATH}" + export GITHUB_EVENT_PATH="${GH_AW_SAFEOUTPUTS_EVENT_PATH}" + fi # Export gateway environment variables for MCP config and gateway script export MCP_GATEWAY_PORT="8080" export MCP_GATEWAY_DOMAIN="awmg-mcpg" export MCP_GATEWAY_HOST_DOMAIN="localhost" - MCP_GATEWAY_API_KEY=$(openssl rand -base64 45 | tr -d '/+=') - echo "::add-mask::${MCP_GATEWAY_API_KEY}" - export MCP_GATEWAY_API_KEY + MCP_GATEWAY_AGENT_ID=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${MCP_GATEWAY_AGENT_ID}" + export MCP_GATEWAY_AGENT_ID export MCP_GATEWAY_PAYLOAD_DIR="/tmp/gh-aw/mcp-payloads" mkdir -p "${MCP_GATEWAY_PAYLOAD_DIR}" export MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD="524288" export MCP_GATEWAY_ALLOWED_MOUNT_ROOTS="${GITHUB_WORKSPACE}:rw,${RUNNER_TEMP}/gh-aw:ro,${RUNNER_TEMP}/gh-aw/safeoutputs:rw,/opt:ro,/tmp:rw,/usr/bin/gh:ro" + export GH_AW_PR_HEAD_BASE_BRANCH="${GH_AW_PR_HEAD_BASE_BRANCH:-}" + export GH_AW_PR_HEAD_BASE_SHA="${GH_AW_PR_HEAD_BASE_SHA:-}" + export GH_AW_PR_HEAD_BASE_REPO="${GH_AW_PR_HEAD_BASE_REPO:-}" + export GH_AW_PR_HEAD_BASE_PR_NUMBER="${GH_AW_PR_HEAD_BASE_PR_NUMBER:-}" + export GH_AW_PR_HEAD_BASE_REF="${GH_AW_PR_HEAD_BASE_REF:-}" + export GH_AW_PR_HEAD_REPO="${GH_AW_PR_HEAD_REPO:-}" export DEBUG="*" export GH_AW_ENGINE="copilot" MCP_GATEWAY_UID=$(id -u 2>/dev/null || echo '0') MCP_GATEWAY_GID=$(id -g 2>/dev/null || echo '0') source "${RUNNER_TEMP}/gh-aw/actions/resolve_docker_socket_gid.sh" - export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network bridge -p 127.0.0.1:'"${MCP_GATEWAY_PORT}"':'"${MCP_GATEWAY_PORT}"' --name awmg-mcpg --add-host host.docker.internal:host-gateway --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v '"${DOCKER_SOCK_PATH}"':/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DOCKER_HOST=unix:///var/run/docker.sock -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_POLICY_ALLOW_CREATE_PULL_REQUEST -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GH_AW_SINK_VISIBILITY -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e RUNNER_TEMP -e MCP_GATEWAY_ALLOWED_MOUNT_ROOTS -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw -v '"${RUNNER_TEMP}"'/gh-aw/safeoutputs:'"${RUNNER_TEMP}"'/gh-aw/safeoutputs:rw ghcr.io/github/gh-aw-mcpg:v0.4.9' + export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network bridge -p 127.0.0.1:'"${MCP_GATEWAY_PORT}"':'"${MCP_GATEWAY_PORT}"' --name awmg-mcpg --add-host host.docker.internal:host-gateway --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v '"${DOCKER_SOCK_PATH}"':/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_AGENT_ID -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DOCKER_HOST=unix:///var/run/docker.sock -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_PR_HEAD_BASE_BRANCH -e GH_AW_PR_HEAD_BASE_SHA -e GH_AW_PR_HEAD_BASE_REPO -e GH_AW_PR_HEAD_BASE_PR_NUMBER -e GH_AW_PR_HEAD_BASE_REF -e GH_AW_PR_HEAD_REPO -e GH_AW_POLICY_ALLOW_CREATE_PULL_REQUEST -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GH_AW_SINK_VISIBILITY -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e RUNNER_TEMP -e RUNNER_TOOL_CACHE -e MCP_GATEWAY_ALLOWED_MOUNT_ROOTS -e GITHUB_AW_OTEL_TRACE_ID -e GITHUB_AW_OTEL_PARENT_SPAN_ID -e OTEL_EXPORTER_OTLP_HEADERS -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw -v '"${RUNNER_TEMP}"'/gh-aw/safeoutputs:'"${RUNNER_TEMP}"'/gh-aw/safeoutputs:rw ghcr.io/github/gh-aw-mcpg:v0.4.18' mkdir -p "$HOME/.copilot" GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) - cat << GH_AW_MCP_CONFIG_6bd3d8c1c13e81be_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_c4bcf965024be97a_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "github": { "type": "stdio", - "container": "ghcr.io/github/github-mcp-server:v1.9.0", + "container": "ghcr.io/github/github-mcp-server:v1.11.0", "env": { "GITHUB_FEATURES": "fields_param", "GITHUB_HOST": "${GITHUB_SERVER_URL}", @@ -1181,6 +1269,14 @@ jobs: "GH_AW_SAFE_OUTPUTS_CONFIG_PATH": "\${GH_AW_SAFE_OUTPUTS_CONFIG_PATH}", "GH_AW_SAFE_OUTPUTS_TOOLS_PATH": "\${GH_AW_SAFE_OUTPUTS_TOOLS_PATH}", "GH_AW_POLICY_ALLOW_CREATE_PULL_REQUEST": "\${GH_AW_POLICY_ALLOW_CREATE_PULL_REQUEST}", + "GH_AW_PR_HEAD_BASE_BRANCH": "\${GH_AW_PR_HEAD_BASE_BRANCH}", + "GH_AW_PR_HEAD_BASE_SHA": "\${GH_AW_PR_HEAD_BASE_SHA}", + "GH_AW_PR_HEAD_BASE_REPO": "\${GH_AW_PR_HEAD_BASE_REPO}", + "GH_AW_PR_HEAD_BASE_PR_NUMBER": "\${GH_AW_PR_HEAD_BASE_PR_NUMBER}", + "GH_AW_PR_HEAD_BASE_REF": "\${GH_AW_PR_HEAD_BASE_REF}", + "GH_AW_PR_HEAD_REPO": "\${GH_AW_PR_HEAD_REPO}", + "GITHUB_EVENT_NAME": "\${GITHUB_EVENT_NAME}", + "GITHUB_EVENT_PATH": "\${GITHUB_EVENT_PATH}", "GITHUB_REPOSITORY": "\${GITHUB_REPOSITORY}", "GITHUB_SHA": "\${GITHUB_SHA}", "GITHUB_TOKEN": "\${GITHUB_TOKEN}", @@ -1200,25 +1296,32 @@ jobs: "gateway": { "port": $MCP_GATEWAY_PORT, "domain": "${MCP_GATEWAY_DOMAIN}", - "apiKey": "${MCP_GATEWAY_API_KEY}", + "agentId": "${MCP_GATEWAY_AGENT_ID}", "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}", - "startupTimeout": 120 + "startupTimeout": 120, + "opentelemetry": { + "endpoint": "${OTEL_EXPORTER_OTLP_ENDPOINT}", + "traceId": "${GITHUB_AW_OTEL_TRACE_ID}", + "spanId": "${GITHUB_AW_OTEL_PARENT_SPAN_ID}" + } } } - GH_AW_MCP_CONFIG_6bd3d8c1c13e81be_EOF + GH_AW_MCP_CONFIG_c4bcf965024be97a_EOF - name: Mount MCP servers as CLIs id: mount-mcp-clis continue-on-error: true env: - MCP_GATEWAY_API_KEY: ${{ steps.start-mcp-gateway.outputs.gateway-api-key }} + MCP_GATEWAY_AGENT_ID: ${{ steps.start-mcp-gateway.outputs.gateway-agent-id }} MCP_GATEWAY_DOMAIN: ${{ steps.start-mcp-gateway.outputs.gateway-domain }} MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }} uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); setupGlobals(core, github, context, exec, io); - const { main } = require('${{ runner.temp }}/gh-aw/actions/mount_mcp_as_cli.cjs'); + const { main } = require(path.join(actionsDir, 'mount_mcp_as_cli.cjs')); await main(); - name: Clean credentials continue-on-error: true @@ -1230,11 +1333,16 @@ jobs: - name: Execute GitHub Copilot CLI id: agentic_execution # Copilot CLI tool arguments (sorted): + # --allow-tool github + # --allow-tool safeoutputs + # --allow-tool shell + # --allow-tool web_fetch + # --allow-tool write timeout-minutes: 60 run: | set -o pipefail printf '%s' "$(date +%s%3N)" > /tmp/gh-aw/agent_cli_start_ms.txt - trap 'gh_aw_exit_code=$?; mkdir -p /tmp/gh-aw >/dev/null 2>&1 || true; printf "%s" "$gh_aw_exit_code" > /tmp/gh-aw/agent_execution_exit_code.txt || true; rm -f "$HOME/.copilot/settings.json"' EXIT + trap 'gh_aw_exit_code=$?; mkdir -p /tmp/gh-aw >/dev/null 2>&1 || true; printf "%s" "$gh_aw_exit_code" > /tmp/gh-aw/agent_execution_exit_code.txt || true; rm -f "$HOME/.copilot/settings.json"; if [ "$gh_aw_exit_code" -ne 0 ]; then echo "::error::Agent execution exited with code $gh_aw_exit_code"; fi' EXIT mkdir -p "$HOME/.copilot" printf '%s' '{"builtInAgents":{"rubberDuck":false}}' > "$HOME/.copilot/settings.json" export XDG_CONFIG_HOME="$HOME" @@ -1257,7 +1365,10 @@ jobs: export COPILOT_API_KEY="$COPILOT_DUMMY_BYOK" (umask 177 && touch /tmp/gh-aw/agent-stdio.log) GH_AW_MAX_AI_CREDITS="${GH_AW_MAX_AI_CREDITS:-1000}" - printf '%s\n' "{\"\$schema\":\"https://github.com/github/gh-aw-firewall/releases/download/v0.27.44/awf-config.schema.json\",\"network\":{\"allowDomains\":[\"*.gradle-enterprise.cloud\",\"*.pythonhosted.org\",\"*.vsblob.vsassets.io\",\"adoptium.net\",\"anaconda.org\",\"api.adoptium.net\",\"api.business.githubcopilot.com\",\"api.enterprise.githubcopilot.com\",\"api.foojay.io\",\"api.github.com\",\"api.githubcopilot.com\",\"api.individual.githubcopilot.com\",\"api.npms.io\",\"api.nuget.org\",\"api.snapcraft.io\",\"archive.apache.org\",\"archive.ubuntu.com\",\"azure.archive.ubuntu.com\",\"azuresearch-usnc.nuget.org\",\"azuresearch-ussc.nuget.org\",\"binstar.org\",\"bootstrap.pypa.io\",\"builds.dotnet.microsoft.com\",\"bun.sh\",\"cdn.azul.com\",\"cdn.jsdelivr.net\",\"central.sonatype.com\",\"ci.dot.net\",\"conda.anaconda.org\",\"conda.binstar.org\",\"crates.io\",\"crl.geotrust.com\",\"crl.globalsign.com\",\"crl.identrust.com\",\"crl.sectigo.com\",\"crl.thawte.com\",\"crl.usertrust.com\",\"crl.verisign.com\",\"crl3.digicert.com\",\"crl4.digicert.com\",\"crls.ssl.com\",\"dc.services.visualstudio.com\",\"deb.nodesource.com\",\"deno.land\",\"develocity.apache.org\",\"dist.nuget.org\",\"dl.google.com\",\"dlcdn.apache.org\",\"dot.net\",\"dotnet.microsoft.com\",\"dotnetcli.blob.core.windows.net\",\"download.eclipse.org\",\"download.java.net\",\"download.oracle.com\",\"downloads.gradle-dn.com\",\"esm.sh\",\"files.pythonhosted.org\",\"ge.spockframework.org\",\"get.pnpm.io\",\"github.com\",\"googleapis.deno.dev\",\"googlechromelabs.github.io\",\"gradle.org\",\"host.docker.internal\",\"index.crates.io\",\"jcenter.bintray.com\",\"jdk.java.net\",\"json-schema.org\",\"json.schemastore.org\",\"jsr.io\",\"keyserver.ubuntu.com\",\"maven-central.storage-download.googleapis.com\",\"maven.apache.org\",\"maven.google.com\",\"maven.oracle.com\",\"maven.pkg.github.com\",\"nodejs.org\",\"npm.pkg.github.com\",\"npmjs.com\",\"npmjs.org\",\"nuget.org\",\"nuget.pkg.github.com\",\"nugetregistryv2prod.blob.core.windows.net\",\"ocsp.digicert.com\",\"ocsp.geotrust.com\",\"ocsp.globalsign.com\",\"ocsp.identrust.com\",\"ocsp.sectigo.com\",\"ocsp.ssl.com\",\"ocsp.thawte.com\",\"ocsp.usertrust.com\",\"ocsp.verisign.com\",\"oneocsp.microsoft.com\",\"packagecloud.io\",\"packages.cloud.google.com\",\"packages.microsoft.com\",\"pip.pypa.io\",\"pkgs.dev.azure.com\",\"plugins-artifacts.gradle.org\",\"plugins.gradle.org\",\"ppa.launchpad.net\",\"pypi.org\",\"pypi.python.org\",\"raw.githubusercontent.com\",\"registry.bower.io\",\"registry.npmjs.com\",\"registry.npmjs.org\",\"registry.yarnpkg.com\",\"repo.anaconda.com\",\"repo.continuum.io\",\"repo.gradle.org\",\"repo.grails.org\",\"repo.maven.apache.org\",\"repo.spring.io\",\"repo.yarnpkg.com\",\"repo1.maven.org\",\"repository.apache.org\",\"s.symcb.com\",\"s.symcd.com\",\"scans-in.gradle.com\",\"security.ubuntu.com\",\"services.gradle.org\",\"sh.rustup.rs\",\"skimdb.npmjs.com\",\"static.crates.io\",\"static.rust-lang.org\",\"storage.googleapis.com\",\"telemetry.enterprise.githubcopilot.com\",\"telemetry.vercel.com\",\"ts-crl.ws.symantec.com\",\"ts-ocsp.ws.symantec.com\",\"www.googleapis.com\",\"www.java.com\",\"www.microsoft.com\",\"www.npmjs.com\",\"www.npmjs.org\",\"yarnpkg.com\"],\"isolation\":true,\"topologyAttach\":[\"awmg-mcpg\"]},\"apiProxy\":{\"enabled\":true,\"enableTokenSteering\":true,\"maxRuns\":500,\"maxAiCredits\":${GH_AW_MAX_AI_CREDITS},\"maxCacheMisses\":5,\"models\":{\"agent\":[\"sonnet-6x\",\"gpt-5.4\",\"gpt-5.5\",\"gpt-5.6\",\"gpt-5.3\",\"gemini-pro\",\"any\"],\"antigravity\":[\"copilot/antigravity*\",\"google/antigravity*\",\"gemini/antigravity*\"],\"any\":[\"copilot/*\",\"anthropic/*\",\"openai/*\",\"google/*\",\"gemini/*\"],\"auto\":[\"copilot/auto\",\"large\"],\"claude\":[\"agent\"],\"codex\":[\"agent\"],\"coding\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\",\"gpt-5-codex\",\"kimi\"],\"computer-use\":[\"copilot/*computer-use*\",\"google/*computer-use*\",\"gemini/*computer-use*\",\"openai/*computer-use*\"],\"copilot\":[\"agent\"],\"deep-research\":[\"copilot/deep-research*\",\"copilot/o3-deep-research*\",\"copilot/o4-mini-deep-research*\",\"google/deep-research*\",\"gemini/deep-research*\",\"openai/o3-deep-research*\",\"openai/o4-mini-deep-research*\"],\"detection\":[\"small\"],\"evals\":[\"small\"],\"fable\":[\"copilot/*fable*\",\"anthropic/*fable*\"],\"gemini\":[\"agent\"],\"gemini-3-flash\":[\"copilot/gemini-3*flash*\",\"google/gemini-3*flash*\",\"gemini/gemini-3*flash*\"],\"gemini-3-pro\":[\"copilot/gemini-3*pro*\",\"google/gemini-3*pro*\",\"google/nano-banana*\",\"gemini/gemini-3*pro*\"],\"gemini-3.1-flash\":[\"copilot/gemini-3.1*flash*\",\"google/gemini-3.1*flash*\",\"gemini/gemini-3.1*flash*\"],\"gemini-3.1-pro\":[\"copilot/gemini-3.1*pro*\",\"google/gemini-3.1*pro*\",\"gemini/gemini-3.1*pro*\"],\"gemini-3.5-flash\":[\"copilot/gemini-3.5*flash*\",\"google/gemini-3.5*flash*\",\"gemini/gemini-3.5*flash*\"],\"gemini-3.6-flash\":[\"copilot/gemini-3.6*flash*\",\"google/gemini-3.6*flash*\",\"gemini/gemini-3.6*flash*\"],\"gemini-flash\":[\"copilot/gemini-*flash*\",\"google/gemini-*flash*\",\"gemini/gemini-*flash*\"],\"gemini-flash-lite\":[\"copilot/gemini-*flash*lite*\",\"google/gemini-*flash*lite*\",\"gemini/gemini-*flash*lite*\"],\"gemini-omni\":[\"copilot/gemini-omni*\",\"google/gemini-omni*\",\"gemini/gemini-omni*\"],\"gemini-pro\":[\"copilot/gemini-*pro*\",\"google/gemini-*pro*\",\"gemini/gemini-*pro*\"],\"gemma\":[\"copilot/gemma*\",\"google/gemma*\",\"gemini/gemma*\"],\"gpt-5\":[\"copilot/gpt-5*\",\"openai/gpt-5*\"],\"gpt-5-codex\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\"],\"gpt-5-mini\":[\"copilot/gpt-5*mini*\",\"openai/gpt-5*mini*\"],\"gpt-5-nano\":[\"copilot/gpt-5*nano*\",\"openai/gpt-5*nano*\"],\"gpt-5-pro\":[\"copilot/gpt-5*pro*\",\"openai/gpt-5*pro*\"],\"gpt-5.1\":[\"copilot/gpt-5.1*\",\"openai/gpt-5.1*\"],\"gpt-5.2\":[\"copilot/gpt-5.2*\",\"openai/gpt-5.2*\"],\"gpt-5.3\":[\"copilot/gpt-5.3*\",\"openai/gpt-5.3*\"],\"gpt-5.4\":[\"copilot/gpt-5.4*\",\"openai/gpt-5.4*\"],\"gpt-5.5\":[\"copilot/gpt-5.5*\",\"openai/gpt-5.5*\"],\"gpt-5.6\":[\"copilot/gpt-5.6*\",\"openai/gpt-5.6*\"],\"grok\":[\"copilot/*grok*\",\"openai/*grok*\"],\"haiku\":[\"copilot/*haiku*\",\"anthropic/*haiku*\"],\"image-generation\":[\"copilot/gpt-image*\",\"openai/gpt-image*\",\"openai/chatgpt-image*\",\"copilot/gemini-*image*\",\"google/gemini-*image*\",\"gemini/gemini-*image*\",\"google/imagen*\"],\"kimi\":[\"copilot/kimi*\",\"openai/kimi*\"],\"kiwi\":[\"copilot/kiwi*\",\"openai/kiwi*\"],\"large\":[\"sonnet\",\"gpt-5-pro\",\"gpt-5\",\"gemini-pro\"],\"lyria\":[\"google/lyria*\",\"gemini/lyria*\",\"copilot/lyria*\"],\"mai-code\":[\"copilot/MAI-Code*\",\"copilot/mai-code*\",\"openai/MAI-Code*\"],\"mai-code-1-flash-picker\":[\"copilot/MAI-Code-1-Flash-picker*\",\"copilot/mai-code-1-flash-picker*\",\"openai/MAI-Code-1-Flash-picker*\"],\"mini\":[\"haiku\",\"gpt-5-mini\",\"gpt-5-nano\",\"gemini-flash-lite\"],\"nano-banana\":[\"copilot/nano-banana*\",\"google/nano-banana*\",\"gemini/nano-banana*\"],\"opus\":[\"copilot/*opus*\",\"anthropic/*opus*\"],\"opusplan\":[\"opus?effort=high\"],\"raptor-mini\":[\"copilot/raptor*\",\"openai/raptor*\"],\"reasoning\":[\"copilot/o1*\",\"copilot/o3*\",\"copilot/o4*\",\"openai/o1*\",\"openai/o3*\",\"openai/o4*\"],\"robotics\":[\"copilot/*robotics*\",\"google/*robotics*\",\"gemini/*robotics*\"],\"small\":[\"mini\"],\"small-agent\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash\"],\"sonnet\":[\"copilot/*sonnet*\",\"anthropic/*sonnet*\"],\"sonnet-6x\":[\"copilot/*sonnet-4.5*\",\"copilot/*sonnet-4.6*\",\"copilot/*sonnet-5*\",\"copilot/*sonnet-4-5-*\",\"anthropic/*sonnet-4-5-*\",\"copilot/*sonnet-4-6*\",\"anthropic/*sonnet-4-6*\",\"anthropic/*sonnet-5*\"],\"summarization\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash-lite\",\"mini\"],\"veo\":[\"google/veo*\",\"gemini/veo*\"],\"vision\":[\"copilot/gemini-*image*\",\"google/gemini-*image*\",\"gemini/gemini-*image*\",\"copilot/gemini-*flash*\",\"google/gemini-*flash*\",\"gemini/gemini-*flash*\"]}},\"container\":{\"imageTag\":\"0.27.44,squid=sha256:83e48bbe12c634be8c228a576832fe45f66c529ac3659db92bddbcf2eeb6d627,agent=sha256:0d727725c737b58c7bdf51f640cffb928385ec46517e0917c7f1a02f1bada8b4,api-proxy=sha256:b50fbadba138f6e9aba94aca09711335c489bb3b15861220cb66f6092e042dc7,cli-proxy=sha256:c064d15974f7c933ec7d3f7b4038f4fd203547b3154bdc821afd379144887eff\"},\"logging\":{\"proxyLogsDir\":\"/tmp/gh-aw/sandbox/firewall/logs\",\"auditDir\":\"/tmp/gh-aw/sandbox/firewall/audit\"}}" > "${RUNNER_TEMP}/gh-aw/awf-config.json" + if [[ ! "$GH_AW_MAX_AI_CREDITS" =~ ^[0-9]+$ ]]; then + GH_AW_MAX_AI_CREDITS="1000" + fi + printf '%s\n' "{\"\$schema\":\"https://github.com/github/gh-aw-firewall/releases/download/v0.28.14/awf-config.schema.json\",\"network\":{\"allowDomains\":[\"*.githubusercontent.com\",\"*.gradle-enterprise.cloud\",\"*.pythonhosted.org\",\"*.vsblob.vsassets.io\",\"adoptium.net\",\"anaconda.org\",\"api.adoptium.net\",\"api.foojay.io\",\"api.npms.io\",\"api.nuget.org\",\"api.snapcraft.io\",\"archive.apache.org\",\"archive.ubuntu.com\",\"azure.archive.ubuntu.com\",\"azuresearch-usnc.nuget.org\",\"azuresearch-ussc.nuget.org\",\"binstar.org\",\"bootstrap.pypa.io\",\"builds.dotnet.microsoft.com\",\"bun.sh\",\"cdn.azul.com\",\"cdn.jsdelivr.net\",\"central.sonatype.com\",\"ci.dot.net\",\"codeload.github.com\",\"conda.anaconda.org\",\"conda.binstar.org\",\"crates.io\",\"crl.geotrust.com\",\"crl.globalsign.com\",\"crl.identrust.com\",\"crl.sectigo.com\",\"crl.thawte.com\",\"crl.usertrust.com\",\"crl.verisign.com\",\"crl3.digicert.com\",\"crl4.digicert.com\",\"crls.ssl.com\",\"dc.services.visualstudio.com\",\"deb.nodesource.com\",\"deno.land\",\"develocity.apache.org\",\"dist.nuget.org\",\"dl.google.com\",\"dlcdn.apache.org\",\"docs.github.com\",\"dot.net\",\"dotnet.microsoft.com\",\"dotnetcli.blob.core.windows.net\",\"download.eclipse.org\",\"download.java.net\",\"download.oracle.com\",\"downloads.gradle-dn.com\",\"esm.sh\",\"files.pythonhosted.org\",\"ge.spockframework.org\",\"get.pnpm.io\",\"github-cloud.githubusercontent.com\",\"github-cloud.s3.amazonaws.com\",\"github.blog\",\"github.com\",\"github.githubassets.com\",\"googleapis.deno.dev\",\"googlechromelabs.github.io\",\"gradle.org\",\"index.crates.io\",\"jcenter.bintray.com\",\"jdk.java.net\",\"json-schema.org\",\"json.schemastore.org\",\"jsr.io\",\"keyserver.ubuntu.com\",\"lfs.github.com\",\"maven-central.storage-download.googleapis.com\",\"maven.apache.org\",\"maven.google.com\",\"maven.oracle.com\",\"maven.pkg.github.com\",\"nodejs.org\",\"npm.pkg.github.com\",\"npmjs.com\",\"npmjs.org\",\"nuget.org\",\"nuget.pkg.github.com\",\"nugetregistryv2prod.blob.core.windows.net\",\"objects.githubusercontent.com\",\"ocsp.digicert.com\",\"ocsp.geotrust.com\",\"ocsp.globalsign.com\",\"ocsp.identrust.com\",\"ocsp.sectigo.com\",\"ocsp.ssl.com\",\"ocsp.thawte.com\",\"ocsp.usertrust.com\",\"ocsp.verisign.com\",\"oneocsp.microsoft.com\",\"packagecloud.io\",\"packages.cloud.google.com\",\"packages.microsoft.com\",\"patch-diff.githubusercontent.com\",\"patchdiff.githubusercontent.com\",\"pip.pypa.io\",\"pkgs.dev.azure.com\",\"plugins-artifacts.gradle.org\",\"plugins.gradle.org\",\"ppa.launchpad.net\",\"pypi.org\",\"pypi.python.org\",\"raw.githubusercontent.com\",\"registry.bower.io\",\"registry.npmjs.com\",\"registry.npmjs.org\",\"registry.yarnpkg.com\",\"repo.anaconda.com\",\"repo.continuum.io\",\"repo.gradle.org\",\"repo.grails.org\",\"repo.maven.apache.org\",\"repo.spring.io\",\"repo.yarnpkg.com\",\"repo1.maven.org\",\"repository.apache.org\",\"s.symcb.com\",\"s.symcd.com\",\"scans-in.gradle.com\",\"security.ubuntu.com\",\"services.gradle.org\",\"sh.rustup.rs\",\"skimdb.npmjs.com\",\"static.crates.io\",\"static.rust-lang.org\",\"storage.googleapis.com\",\"telemetry.vercel.com\",\"ts-crl.ws.symantec.com\",\"ts-ocsp.ws.symantec.com\",\"www.googleapis.com\",\"www.java.com\",\"www.microsoft.com\",\"www.npmjs.com\",\"www.npmjs.org\",\"yarnpkg.com\"],\"isolation\":true,\"topologyAttach\":[\"awmg-mcpg\"]},\"apiProxy\":{\"enabled\":true,\"enableTokenSteering\":true,\"maxRuns\":500,\"maxAiCredits\":${GH_AW_MAX_AI_CREDITS},\"maxCacheMisses\":5,\"models\":{\"agent\":[\"sonnet-6x\",\"gpt-5.4\",\"gpt-5.5\",\"gpt-5.6\",\"gpt-5.3\",\"gemini-pro\",\"any\"],\"antigravity\":[\"copilot/antigravity*\",\"google/antigravity*\",\"gemini/antigravity*\"],\"any\":[\"copilot/*\",\"anthropic/*\",\"openai/*\",\"google/*\",\"gemini/*\"],\"auto\":[\"copilot/auto\",\"large\"],\"claude\":[\"agent\"],\"codex\":[\"agent\"],\"coding\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\",\"gpt-5-codex\",\"kimi\"],\"computer-use\":[\"copilot/*computer-use*\",\"google/*computer-use*\",\"gemini/*computer-use*\",\"openai/*computer-use*\"],\"copilot\":[\"agent\"],\"deep-research\":[\"copilot/deep-research*\",\"copilot/o3-deep-research*\",\"copilot/o4-mini-deep-research*\",\"google/deep-research*\",\"gemini/deep-research*\",\"openai/o3-deep-research*\",\"openai/o4-mini-deep-research*\"],\"detection\":[\"small\"],\"evals\":[\"small\"],\"fable\":[\"copilot/*fable*\",\"anthropic/*fable*\"],\"gemini\":[\"agent\"],\"gemini-3-flash\":[\"copilot/gemini-3*flash*\",\"google/gemini-3*flash*\",\"gemini/gemini-3*flash*\"],\"gemini-3-pro\":[\"copilot/gemini-3*pro*\",\"google/gemini-3*pro*\",\"google/nano-banana*\",\"gemini/gemini-3*pro*\"],\"gemini-3.1-flash\":[\"copilot/gemini-3.1*flash*\",\"google/gemini-3.1*flash*\",\"gemini/gemini-3.1*flash*\"],\"gemini-3.1-pro\":[\"copilot/gemini-3.1*pro*\",\"google/gemini-3.1*pro*\",\"gemini/gemini-3.1*pro*\"],\"gemini-3.5-flash\":[\"copilot/gemini-3.5*flash*\",\"google/gemini-3.5*flash*\",\"gemini/gemini-3.5*flash*\"],\"gemini-3.6-flash\":[\"copilot/gemini-3.6*flash*\",\"google/gemini-3.6*flash*\",\"gemini/gemini-3.6*flash*\"],\"gemini-3.7-flash\":[\"copilot/gemini-3.7*flash*\",\"google/gemini-3.7*flash*\",\"gemini/gemini-3.7*flash*\"],\"gemini-flash\":[\"copilot/gemini-*flash*\",\"google/gemini-*flash*\",\"gemini/gemini-*flash*\"],\"gemini-flash-lite\":[\"copilot/gemini-*flash*lite*\",\"google/gemini-*flash*lite*\",\"gemini/gemini-*flash*lite*\"],\"gemini-omni\":[\"copilot/gemini-omni*\",\"google/gemini-omni*\",\"gemini/gemini-omni*\"],\"gemini-pro\":[\"copilot/gemini-*pro*\",\"google/gemini-*pro*\",\"gemini/gemini-*pro*\"],\"gemma\":[\"copilot/gemma*\",\"google/gemma*\",\"gemini/gemma*\"],\"gpt-5\":[\"copilot/gpt-5*\",\"openai/gpt-5*\"],\"gpt-5-codex\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\"],\"gpt-5-mini\":[\"copilot/gpt-5*mini*\",\"openai/gpt-5*mini*\"],\"gpt-5-nano\":[\"copilot/gpt-5*nano*\",\"openai/gpt-5*nano*\"],\"gpt-5-pro\":[\"copilot/gpt-5*pro*\",\"openai/gpt-5*pro*\"],\"gpt-5.1\":[\"copilot/gpt-5.1*\",\"openai/gpt-5.1*\"],\"gpt-5.2\":[\"copilot/gpt-5.2*\",\"openai/gpt-5.2*\"],\"gpt-5.3\":[\"copilot/gpt-5.3*\",\"openai/gpt-5.3*\"],\"gpt-5.4\":[\"copilot/gpt-5.4*\",\"openai/gpt-5.4*\"],\"gpt-5.5\":[\"copilot/gpt-5.5*\",\"openai/gpt-5.5*\"],\"gpt-5.6\":[\"copilot/gpt-5.6*\",\"openai/gpt-5.6*\"],\"grok\":[\"copilot/*grok*\",\"openai/*grok*\"],\"haiku\":[\"copilot/*haiku*\",\"anthropic/*haiku*\"],\"image-generation\":[\"copilot/gpt-image*\",\"openai/gpt-image*\",\"openai/chatgpt-image*\",\"copilot/gemini-*image*\",\"google/gemini-*image*\",\"gemini/gemini-*image*\",\"google/imagen*\"],\"kimi\":[\"copilot/kimi*\",\"openai/kimi*\"],\"kiwi\":[\"copilot/kiwi*\",\"openai/kiwi*\"],\"large\":[\"sonnet\",\"gpt-5-pro\",\"gpt-5\",\"gemini-pro\"],\"lyria\":[\"google/lyria*\",\"gemini/lyria*\",\"copilot/lyria*\"],\"mai-code\":[\"copilot/MAI-Code*\",\"copilot/mai-code*\",\"openai/MAI-Code*\"],\"mai-code-1-flash-picker\":[\"copilot/MAI-Code-1-Flash-picker*\",\"copilot/mai-code-1-flash-picker*\",\"openai/MAI-Code-1-Flash-picker*\"],\"mini\":[\"haiku\",\"gpt-5-mini\",\"gpt-5-nano\",\"gemini-flash-lite\"],\"nano-banana\":[\"copilot/nano-banana*\",\"google/nano-banana*\",\"gemini/nano-banana*\"],\"opus\":[\"copilot/*opus*\",\"anthropic/*opus*\"],\"opusplan\":[\"opus?effort=high\"],\"raptor-mini\":[\"copilot/raptor*\",\"openai/raptor*\"],\"reasoning\":[\"copilot/o1*\",\"copilot/o3*\",\"copilot/o4*\",\"openai/o1*\",\"openai/o3*\",\"openai/o4*\"],\"robotics\":[\"copilot/*robotics*\",\"google/*robotics*\",\"gemini/*robotics*\"],\"small\":[\"mini\"],\"small-agent\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash\"],\"sonnet\":[\"copilot/*sonnet*\",\"anthropic/*sonnet*\"],\"sonnet-6x\":[\"copilot/*sonnet-4.5*\",\"copilot/*sonnet-4.6*\",\"copilot/*sonnet-5*\",\"copilot/*sonnet-4-5-*\",\"anthropic/*sonnet-4-5-*\",\"copilot/*sonnet-4-6*\",\"anthropic/*sonnet-4-6*\",\"anthropic/*sonnet-5*\"],\"summarization\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash-lite\",\"mini\"],\"veo\":[\"google/veo*\",\"gemini/veo*\"],\"vision\":[\"copilot/gemini-*image*\",\"google/gemini-*image*\",\"gemini/gemini-*image*\",\"copilot/gemini-*flash*\",\"google/gemini-*flash*\",\"gemini/gemini-*flash*\"]}},\"container\":{\"imageTag\":\"0.28.14,squid=sha256:2ce8df3abf3e9b76e9c0cf5863da41f1ab3f89b20ad14b988806ab89e7bf2cd5,agent=sha256:f7df036c86575527b61f3f7df91c4412349a12b2a74988d929eafa2999230c98,api-proxy=sha256:6f95e2234dd9bd6333a8ff28ccea7ecf0204acd4a09108723844dbd2bf6268c5,cli-proxy=sha256:3a379c5e96e29499c815e9dd2a71334d01c326a9b73991c76544fda9cae35c34\"},\"logging\":{\"proxyLogsDir\":\"/tmp/gh-aw/sandbox/firewall/logs\",\"auditDir\":\"/tmp/gh-aw/sandbox/firewall/audit\"}}" > "${RUNNER_TEMP}/gh-aw/awf-config.json" cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json export GH_AW_MODELS_JSON_PATH="/tmp/gh-aw/models.json" GH_AW_DOCKER_HOST="" @@ -1275,8 +1386,13 @@ jobs: fi fi # shellcheck disable=SC1003,SC2016,SC2086 - awf --config "${RUNNER_TEMP}/gh-aw/awf-config.json" --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" ${GH_AW_TOOL_CACHE_MOUNT:+--mount "$GH_AW_TOOL_CACHE_MOUNT"} ${GH_AW_DOCKER_HOST:+--docker-host "$GH_AW_DOCKER_HOST"} --env-all --exclude-env ACTIONS_ID_TOKEN_REQUEST_TOKEN --exclude-env ACTIONS_ID_TOKEN_REQUEST_URL --exclude-env COPILOT_GITHUB_TOKEN --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --mount /tmp/gh-aw:/tmp/gh-aw:rw --log-level info --skip-pull \ - -- /bin/bash -c 'set +o histexpand; export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && : "${RUNNER_TOOL_CACHE:?RUNNER_TOOL_CACHE must be set}"; GH_AW_TOOL_CACHE="$RUNNER_TOOL_CACHE"; export PATH="$(find "$GH_AW_TOOL_CACHE" -maxdepth 5 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true; [ -n "$ERLANG_HOME" ] && export PATH="$ERLANG_HOME/bin:$PATH" || true && GH_AW_NODE_EXEC="${GH_AW_NODE_BIN:-}"; if [ -z "$GH_AW_NODE_EXEC" ] || [ ! -x "$GH_AW_NODE_EXEC" ]; then GH_AW_NODE_EXEC="$(command -v node 2>/dev/null || true)"; fi; if [ -z "$GH_AW_NODE_EXEC" ]; then echo "node runtime missing on this runner β€” check runtimes.node in workflow YAML" >&2; exit 127; fi; GH_AW_NPM_GLOBAL_ROOT="$(npm root -g 2>/dev/null || true)"; if [ -n "$GH_AW_NPM_GLOBAL_ROOT" ]; then export NODE_PATH="${GH_AW_NPM_GLOBAL_ROOT}${NODE_PATH:+:${NODE_PATH}}"; fi; "$GH_AW_NODE_EXEC" "${RUNNER_TEMP}/gh-aw/actions/copilot_harness.cjs" "${RUNNER_TEMP}/gh-aw/bin/copilot" --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --allow-all-tools --allow-all-paths --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + GH_AW_AWF_ENGINE_NAME=copilot \ + GH_AW_AWF_HARNESS_MARKER='[copilot-harness]' \ + GH_AW_AWF_LOG_FILE=/tmp/gh-aw/agent-stdio.log \ + GH_AW_AWF_ATTEMPT_LOG_NAME=copilot \ + bash "${RUNNER_TEMP}/gh-aw/actions/run_awf_with_startup_retries.sh" -- \ + awf --config "${RUNNER_TEMP}/gh-aw/awf-config.json" --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" ${GH_AW_TOOL_CACHE_MOUNT:+--mount "$GH_AW_TOOL_CACHE_MOUNT"} ${GH_AW_DOCKER_HOST:+--docker-host "$GH_AW_DOCKER_HOST"} --env-all --exclude-env ACTIONS_ID_TOKEN_REQUEST_TOKEN --exclude-env ACTIONS_ID_TOKEN_REQUEST_URL --exclude-env COPILOT_GITHUB_TOKEN --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_AGENT_ID --mount /tmp/gh-aw:/tmp/gh-aw:rw --log-level info --skip-pull \ + -- /bin/bash -c 'set +o histexpand; export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && : "${RUNNER_TOOL_CACHE:?RUNNER_TOOL_CACHE must be set}"; GH_AW_TOOL_CACHE="$RUNNER_TOOL_CACHE"; GH_AW_TOOL_BINS="$(find "$GH_AW_TOOL_CACHE" -maxdepth 5 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')"; GH_AW_TOOL_BINS="${GH_AW_TOOL_BINS%:}"; export PATH="$PATH${GH_AW_TOOL_BINS:+:}$GH_AW_TOOL_BINS"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true; [ -n "$ERLANG_HOME" ] && export PATH="$ERLANG_HOME/bin:$PATH" || true && GH_AW_NODE_EXEC="${GH_AW_NODE_BIN:-}"; if [ -z "$GH_AW_NODE_EXEC" ] || [ ! -x "$GH_AW_NODE_EXEC" ]; then GH_AW_NODE_EXEC="$(command -v node 2>/dev/null || true)"; fi; if [ -z "$GH_AW_NODE_EXEC" ]; then echo "node runtime missing on this runner β€” check runtimes.node in workflow YAML" >&2; exit 127; fi; GH_AW_NPM_GLOBAL_ROOT="$(npm root -g 2>/dev/null || true)"; if [ -n "$GH_AW_NPM_GLOBAL_ROOT" ]; then export NODE_PATH="${GH_AW_NPM_GLOBAL_ROOT}${NODE_PATH:+:${NODE_PATH}}"; fi; "$GH_AW_NODE_EXEC" "${RUNNER_TEMP}/gh-aw/actions/copilot_harness.cjs" "${RUNNER_TEMP}/gh-aw/bin/copilot" --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --no-ask-user --allow-tool github --allow-tool safeoutputs --allow-tool shell --allow-tool web_fetch --allow-tool write --allow-all-paths --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' env: AWF_REFLECT_ENABLED: 1 COPILOT_AGENT_RUNNER_TYPE: STANDALONE @@ -1290,7 +1406,7 @@ jobs: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} GH_AW_TIMEOUT_MINUTES: 60 - GH_AW_VERSION: v0.86.2 + GH_AW_VERSION: v0.88.7 GITHUB_API_URL: ${{ github.api_url }} GITHUB_AW: true GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows @@ -1310,7 +1426,18 @@ jobs: if: always() id: detect-agent-errors continue-on-error: true - run: node "${RUNNER_TEMP}/gh-aw/actions/detect_agent_errors.cjs" + env: + GH_AW_AGENTIC_EXECUTION_OUTCOME: ${{ steps.agentic_execution.outcome }} + GH_AW_ENGINE_STEP_TIMEOUT_MINUTES: 60 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require(path.join(actionsDir, 'detect_agent_errors.cjs')); + await main(); - name: Configure Git credentials env: GITHUB_REPOSITORY: ${{ github.repository }} @@ -1326,7 +1453,7 @@ jobs: continue-on-error: true env: MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }} - MCP_GATEWAY_API_KEY: ${{ steps.start-mcp-gateway.outputs.gateway-api-key }} + MCP_GATEWAY_AGENT_ID: ${{ steps.start-mcp-gateway.outputs.gateway-agent-id }} GATEWAY_PID: ${{ steps.start-mcp-gateway.outputs.gateway-pid }} run: | bash "${RUNNER_TEMP}/gh-aw/actions/stop_mcp_gateway.sh" "$GATEWAY_PID" @@ -1335,9 +1462,11 @@ jobs: uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/redact_secrets.cjs'); + const { main } = require(path.join(actionsDir, 'redact_secrets.cjs')); await main(); env: GH_AW_SECRET_NAMES: 'COPILOT_GITHUB_TOKEN,GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN' @@ -1361,15 +1490,17 @@ jobs: uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} - GH_AW_ALLOWED_DOMAINS: "*.gradle-enterprise.cloud,*.pythonhosted.org,*.vsblob.vsassets.io,adoptium.net,anaconda.org,api.adoptium.net,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.foojay.io,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.nuget.org,api.snapcraft.io,archive.apache.org,archive.ubuntu.com,azure.archive.ubuntu.com,azuresearch-usnc.nuget.org,azuresearch-ussc.nuget.org,binstar.org,bootstrap.pypa.io,builds.dotnet.microsoft.com,bun.sh,cdn.azul.com,cdn.jsdelivr.net,central.sonatype.com,ci.dot.net,conda.anaconda.org,conda.binstar.org,crates.io,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,dc.services.visualstudio.com,deb.nodesource.com,deno.land,develocity.apache.org,dist.nuget.org,dl.google.com,dlcdn.apache.org,dot.net,dotnet.microsoft.com,dotnetcli.blob.core.windows.net,download.eclipse.org,download.java.net,download.oracle.com,downloads.gradle-dn.com,esm.sh,files.pythonhosted.org,ge.spockframework.org,get.pnpm.io,github.com,googleapis.deno.dev,googlechromelabs.github.io,gradle.org,host.docker.internal,index.crates.io,jcenter.bintray.com,jdk.java.net,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,maven-central.storage-download.googleapis.com,maven.apache.org,maven.google.com,maven.oracle.com,maven.pkg.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,nuget.org,nuget.pkg.github.com,nugetregistryv2prod.blob.core.windows.net,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,oneocsp.microsoft.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,pip.pypa.io,pkgs.dev.azure.com,plugins-artifacts.gradle.org,plugins.gradle.org,ppa.launchpad.net,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.gradle.org,repo.grails.org,repo.maven.apache.org,repo.spring.io,repo.yarnpkg.com,repo1.maven.org,repository.apache.org,s.symcb.com,s.symcd.com,scans-in.gradle.com,security.ubuntu.com,services.gradle.org,sh.rustup.rs,skimdb.npmjs.com,static.crates.io,static.rust-lang.org,storage.googleapis.com,telemetry.enterprise.githubcopilot.com,telemetry.vercel.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com,www.java.com,www.microsoft.com,www.npmjs.com,www.npmjs.org,yarnpkg.com" + GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,*.gradle-enterprise.cloud,*.pythonhosted.org,*.vsblob.vsassets.io,adoptium.net,anaconda.org,api.adoptium.net,api.foojay.io,api.npms.io,api.nuget.org,api.snapcraft.io,archive.apache.org,archive.ubuntu.com,azure.archive.ubuntu.com,azuresearch-usnc.nuget.org,azuresearch-ussc.nuget.org,binstar.org,bootstrap.pypa.io,builds.dotnet.microsoft.com,bun.sh,cdn.azul.com,cdn.jsdelivr.net,central.sonatype.com,ci.dot.net,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,dc.services.visualstudio.com,deb.nodesource.com,deno.land,develocity.apache.org,dist.nuget.org,dl.google.com,dlcdn.apache.org,docs.github.com,dot.net,dotnet.microsoft.com,dotnetcli.blob.core.windows.net,download.eclipse.org,download.java.net,download.oracle.com,downloads.gradle-dn.com,esm.sh,files.pythonhosted.org,ge.spockframework.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.blog,github.com,github.githubassets.com,googleapis.deno.dev,googlechromelabs.github.io,gradle.org,index.crates.io,jcenter.bintray.com,jdk.java.net,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,maven-central.storage-download.googleapis.com,maven.apache.org,maven.google.com,maven.oracle.com,maven.pkg.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,nuget.org,nuget.pkg.github.com,nugetregistryv2prod.blob.core.windows.net,objects.githubusercontent.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,oneocsp.microsoft.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,patch-diff.githubusercontent.com,patchdiff.githubusercontent.com,pip.pypa.io,pkgs.dev.azure.com,plugins-artifacts.gradle.org,plugins.gradle.org,ppa.launchpad.net,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.gradle.org,repo.grails.org,repo.maven.apache.org,repo.spring.io,repo.yarnpkg.com,repo1.maven.org,repository.apache.org,s.symcb.com,s.symcd.com,scans-in.gradle.com,security.ubuntu.com,services.gradle.org,sh.rustup.rs,skimdb.npmjs.com,static.crates.io,static.rust-lang.org,storage.googleapis.com,telemetry.vercel.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com,www.java.com,www.microsoft.com,www.npmjs.com,www.npmjs.org,yarnpkg.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} GH_AW_COMMANDS: "[\"repo-assist\"]" with: script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/collect_ndjson_output.cjs'); + const { main } = require(path.join(actionsDir, 'collect_ndjson_output.cjs')); await main(); - name: Parse agent logs for step summary if: always() @@ -1379,9 +1510,11 @@ jobs: GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} with: script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_copilot_log.cjs'); + const { main } = require(path.join(actionsDir, 'parse_copilot_log.cjs')); await main(); - name: Parse MCP Gateway logs for step summary if: always() @@ -1389,9 +1522,11 @@ jobs: uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_mcp_gateway_log.cjs'); + const { main } = require(path.join(actionsDir, 'parse_mcp_gateway_log.cjs')); await main(); - name: Print firewall logs if: always() @@ -1405,9 +1540,11 @@ jobs: uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_token_usage.cjs'); + const { main } = require(path.join(actionsDir, 'parse_token_usage.cjs')); await main(); - name: Print AWF reflect summary if: always() @@ -1415,10 +1552,23 @@ jobs: uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/awf_reflect_summary.cjs'); + const { main } = require(path.join(actionsDir, 'awf_reflect_summary.cjs')); await main(); + - name: Generate observability summary + if: always() + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require(path.join(actionsDir, 'generate_observability_summary.cjs')); + await main(core); - name: Write agent output placeholder if missing if: always() run: | @@ -1432,14 +1582,59 @@ jobs: env: MEMORY_DIR: /tmp/gh-aw/repo-memory/default run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" - - name: Upload repo-memory artifact (default) + - name: Filter repo-memory files (default) + id: filter_repo_memory_64656661756c74 if: always() + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + MEMORY_DIR: /tmp/gh-aw/repo-memory/default + ALLOWED_EXTENSIONS: '[".json"]' + with: + script: | + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require(path.join(actionsDir, 'memory_file_eligibility.cjs')); + await main(); + - name: Validate repo-memory domain content (default) + id: validate_repo_memory_64656661756c74 + if: always() && steps.filter_repo_memory_64656661756c74.outcome == 'success' + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + MEMORY_DIR: /tmp/gh-aw/repo-memory/default + MEMORY_ID: default + VALIDATION_SCRIPT_B64: Y29uc3QgZnMgPSByZXF1aXJlKCJub2RlOmZzIik7CmNvbnN0IHBhdGggPSByZXF1aXJlKCJub2RlOnBhdGgiKTsKY29uc3QgZmFpbCA9IG1lc3NhZ2UgPT4geyB0aHJvdyBuZXcgRXJyb3IoYG5vdGVzLmpzb246ICR7bWVzc2FnZX1gKTsgfTsKY29uc3Qgbm90ZXNQYXRoID0gcGF0aC5qb2luKG1lbW9yeVJvb3QsICJub3Rlcy5qc29uIik7CmlmICghZnMuZXhpc3RzU3luYyhub3Rlc1BhdGgpKSBmYWlsKCJtaXNzaW5nIChjcmVhdGUgYW4gaW5pdGlhbCBub3Rlcy5qc29uIHRoYXQgbWF0Y2hlcyBzY2hlbWEgdmVyc2lvbiAxKSIpOwpjb25zdCBkYXRhID0gSlNPTi5wYXJzZShmcy5yZWFkRmlsZVN5bmMobm90ZXNQYXRoLCAidXRmOCIpKTsKY29uc3QgaXNPYmplY3QgPSB2YWx1ZSA9PiB2YWx1ZSAhPT0gbnVsbCAmJiB0eXBlb2YgdmFsdWUgPT09ICJvYmplY3QiICYmICFBcnJheS5pc0FycmF5KHZhbHVlKTsKY29uc3QgZXhhY3RLZXlzID0gKHZhbHVlLCBrZXlzKSA9PiBpc09iamVjdCh2YWx1ZSkgJiYgT2JqZWN0LmtleXModmFsdWUpLnNvcnQoKS5qb2luKCIsIikgPT09IFsuLi5rZXlzXS5zb3J0KCkuam9pbigiLCIpOwpjb25zdCB2YWxpZERhdGUgPSB2YWx1ZSA9PiB0eXBlb2YgdmFsdWUgPT09ICJzdHJpbmciICYmIC9eWzAtOV17NH0tWzAtOV17Mn0tWzAtOV17Mn0kLy50ZXN0KHZhbHVlKTsKY29uc3QgdmFsaWRUZXh0ID0gKHZhbHVlLCBtYXhpbXVtKSA9PiB0eXBlb2YgdmFsdWUgPT09ICJzdHJpbmciICYmIHZhbHVlLmxlbmd0aCA+IDAgJiYgdmFsdWUubGVuZ3RoIDw9IG1heGltdW07CmNvbnN0IHVuaXF1ZSA9IChlbnRyaWVzLCBrZXksIGxhYmVsKSA9PiB7CiAgY29uc3QgdmFsdWVzID0gZW50cmllcy5tYXAoa2V5KTsKICBpZiAobmV3IFNldCh2YWx1ZXMpLnNpemUgIT09IHZhbHVlcy5sZW5ndGgpIGZhaWwoYCR7bGFiZWx9IG11c3QgYmUgdW5pcXVlYCk7Cn07CgppZiAoIWV4YWN0S2V5cyhkYXRhLCBbInZlcnNpb24iLCAiY3Vyc29ycyIsICJpc3N1ZXMiLCAiZml4ZXMiLCAiY2hlY2tzIiwgImNvbXBsZXRlZF9hY3Rpb25zIiwgInByaW9yaXRpZXMiXSkpIGZhaWwoIm11c3QgY29udGFpbiBleGFjdGx5IHZlcnNpb24sIGN1cnNvcnMsIGlzc3VlcywgZml4ZXMsIGNoZWNrcywgY29tcGxldGVkX2FjdGlvbnMsIGFuZCBwcmlvcml0aWVzIik7CmlmIChkYXRhLnZlcnNpb24gIT09IDEpIGZhaWwoInZlcnNpb24gbXVzdCBiZSAxIik7CmlmICghZXhhY3RLZXlzKGRhdGEuY3Vyc29ycywgWyJsYWJlbGxpbmdfYWZ0ZXIiLCAiaW52ZXN0aWdhdGlvbl9hZnRlciJdKSkgZmFpbCgiY3Vyc29ycyBtdXN0IGNvbnRhaW4gZXhhY3RseSBsYWJlbGxpbmdfYWZ0ZXIgYW5kIGludmVzdGlnYXRpb25fYWZ0ZXIiKTsKZm9yIChjb25zdCBbbmFtZSwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKGRhdGEuY3Vyc29ycykpIHsKICBpZiAodmFsdWUgIT09IG51bGwgJiYgKCFOdW1iZXIuaXNJbnRlZ2VyKHZhbHVlKSB8fCB2YWx1ZSA8IDEpKSBmYWlsKGAke25hbWV9IG11c3QgYmUgbnVsbCBvciBhIHBvc2l0aXZlIGlzc3VlIG51bWJlcmApOwp9Cgpjb25zdCBpc3N1ZVN0YXRlcyA9IG5ldyBTZXQoWyJjb21tZW50ZWQiLCAiYXdhaXRpbmdfY2xhcmlmaWNhdGlvbiIsICJyZXNvbHV0aW9uX3JlY29tbWVuZGVkIiwgImRlZmVycmVkIiwgImF3YWl0aW5nX2FwcHJvdmFsIl0pOwppZiAoIUFycmF5LmlzQXJyYXkoZGF0YS5pc3N1ZXMpIHx8IGRhdGEuaXNzdWVzLmxlbmd0aCA+IDEwMCkgZmFpbCgiaXNzdWVzIG11c3QgYmUgYW4gYXJyYXkgb2YgYXQgbW9zdCAxMDAgZW50cmllcyIpOwpmb3IgKGNvbnN0IFtpbmRleCwgZW50cnldIG9mIGRhdGEuaXNzdWVzLmVudHJpZXMoKSkgewogIGlmICghZXhhY3RLZXlzKGVudHJ5LCBbIm51bWJlciIsICJzdGF0ZSIsICJ1cGRhdGVkX2F0IiwgIm5vdGUiXSkpIGZhaWwoYGludmFsaWQgaXNzdWVzIGVudHJ5IGF0IGluZGV4ICR7aW5kZXh9YCk7CiAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKGVudHJ5Lm51bWJlcikgfHwgZW50cnkubnVtYmVyIDwgMSkgZmFpbChgaW52YWxpZCBpc3N1ZSBudW1iZXIgYXQgaW5kZXggJHtpbmRleH1gKTsKICBpZiAoIWlzc3VlU3RhdGVzLmhhcyhlbnRyeS5zdGF0ZSkpIGZhaWwoYGludmFsaWQgaXNzdWUgc3RhdGUgYXQgaW5kZXggJHtpbmRleH1gKTsKICBpZiAoIXZhbGlkRGF0ZShlbnRyeS51cGRhdGVkX2F0KSkgZmFpbChgaW52YWxpZCBpc3N1ZSBkYXRlIGF0IGluZGV4ICR7aW5kZXh9YCk7CiAgaWYgKCF2YWxpZFRleHQoZW50cnkubm90ZSwgMzAwKSkgZmFpbChgaW52YWxpZCBpc3N1ZSBub3RlIGF0IGluZGV4ICR7aW5kZXh9YCk7Cn0KdW5pcXVlKGRhdGEuaXNzdWVzLCBlbnRyeSA9PiBlbnRyeS5udW1iZXIsICJpc3N1ZSBudW1iZXJzIik7Cgpjb25zdCBmaXhTdGF0ZXMgPSBuZXcgU2V0KFsib3BlbiIsICJtZXJnZWQiLCAiY2xvc2VkIiwgImJsb2NrZWQiXSk7CmlmICghQXJyYXkuaXNBcnJheShkYXRhLmZpeGVzKSB8fCBkYXRhLmZpeGVzLmxlbmd0aCA+IDUwKSBmYWlsKCJmaXhlcyBtdXN0IGJlIGFuIGFycmF5IG9mIGF0IG1vc3QgNTAgZW50cmllcyIpOwpmb3IgKGNvbnN0IFtpbmRleCwgZW50cnldIG9mIGRhdGEuZml4ZXMuZW50cmllcygpKSB7CiAgaWYgKCFleGFjdEtleXMoZW50cnksIFsiaXNzdWUiLCAicHIiLCAiYnJhbmNoIiwgInN0YXR1cyIsICJ1cGRhdGVkX2F0IiwgIm5vdGUiXSkpIGZhaWwoYGludmFsaWQgZml4ZXMgZW50cnkgYXQgaW5kZXggJHtpbmRleH1gKTsKICBpZiAoIU51bWJlci5pc0ludGVnZXIoZW50cnkuaXNzdWUpIHx8IGVudHJ5Lmlzc3VlIDwgMSkgZmFpbChgaW52YWxpZCBmaXggaXNzdWUgYXQgaW5kZXggJHtpbmRleH1gKTsKICBpZiAoZW50cnkucHIgIT09IG51bGwgJiYgKCFOdW1iZXIuaXNJbnRlZ2VyKGVudHJ5LnByKSB8fCBlbnRyeS5wciA8IDEpKSBmYWlsKGBpbnZhbGlkIGZpeCBQUiBhdCBpbmRleCAke2luZGV4fWApOwogIGlmIChlbnRyeS5icmFuY2ggIT09IG51bGwgJiYgIXZhbGlkVGV4dChlbnRyeS5icmFuY2gsIDEyMCkpIGZhaWwoYGludmFsaWQgZml4IGJyYW5jaCBhdCBpbmRleCAke2luZGV4fWApOwogIGlmICghZml4U3RhdGVzLmhhcyhlbnRyeS5zdGF0dXMpKSBmYWlsKGBpbnZhbGlkIGZpeCBzdGF0dXMgYXQgaW5kZXggJHtpbmRleH1gKTsKICBpZiAoIXZhbGlkRGF0ZShlbnRyeS51cGRhdGVkX2F0KSkgZmFpbChgaW52YWxpZCBmaXggZGF0ZSBhdCBpbmRleCAke2luZGV4fWApOwogIGlmICghdmFsaWRUZXh0KGVudHJ5Lm5vdGUsIDMwMCkpIGZhaWwoYGludmFsaWQgZml4IG5vdGUgYXQgaW5kZXggJHtpbmRleH1gKTsKfQp1bmlxdWUoZGF0YS5maXhlcywgZW50cnkgPT4gZW50cnkuaXNzdWUsICJmaXggaXNzdWUgbnVtYmVycyIpOwp1bmlxdWUoZGF0YS5maXhlcy5maWx0ZXIoZW50cnkgPT4gZW50cnkucHIgIT09IG51bGwpLCBlbnRyeSA9PiBlbnRyeS5wciwgImZpeCBQUiBudW1iZXJzIik7Cgpjb25zdCBjaGVja0FyZWFzID0gbmV3IFNldChbImRlcGVuZGVuY2llcyIsICJjaSIsICJ0b29saW5nIiwgImJ1aWxkIiwgImNvZGUiLCAiZG9jcyIsICJxYSIsICJoeWdpZW5lIiwgInBlcmZvcm1hbmNlIiwgInRlc3RzIiwgInJlbGVhc2UiLCAicmVwb19hc3Npc3RfcHJzIl0pOwppZiAoIUFycmF5LmlzQXJyYXkoZGF0YS5jaGVja3MpIHx8IGRhdGEuY2hlY2tzLmxlbmd0aCA+IGNoZWNrQXJlYXMuc2l6ZSkgZmFpbCgiY2hlY2tzIG11c3QgY29udGFpbiBhdCBtb3N0IG9uZSBlbnRyeSBwZXIgYXJlYSIpOwpmb3IgKGNvbnN0IFtpbmRleCwgZW50cnldIG9mIGRhdGEuY2hlY2tzLmVudHJpZXMoKSkgewogIGlmICghZXhhY3RLZXlzKGVudHJ5LCBbImFyZWEiLCAiY2hlY2tlZF9hdCIsICJyZXN1bHQiLCAiZm9sbG93X3VwIl0pKSBmYWlsKGBpbnZhbGlkIGNoZWNrcyBlbnRyeSBhdCBpbmRleCAke2luZGV4fWApOwogIGlmICghY2hlY2tBcmVhcy5oYXMoZW50cnkuYXJlYSkpIGZhaWwoYGludmFsaWQgY2hlY2sgYXJlYSBhdCBpbmRleCAke2luZGV4fWApOwogIGlmICghdmFsaWREYXRlKGVudHJ5LmNoZWNrZWRfYXQpKSBmYWlsKGBpbnZhbGlkIGNoZWNrIGRhdGUgYXQgaW5kZXggJHtpbmRleH1gKTsKICBpZiAoIXZhbGlkVGV4dChlbnRyeS5yZXN1bHQsIDMwMCkpIGZhaWwoYGludmFsaWQgY2hlY2sgcmVzdWx0IGF0IGluZGV4ICR7aW5kZXh9YCk7CiAgaWYgKGVudHJ5LmZvbGxvd191cCAhPT0gbnVsbCAmJiAhdmFsaWRUZXh0KGVudHJ5LmZvbGxvd191cCwgMzAwKSkgZmFpbChgaW52YWxpZCBjaGVjayBmb2xsb3dfdXAgYXQgaW5kZXggJHtpbmRleH1gKTsKfQp1bmlxdWUoZGF0YS5jaGVja3MsIGVudHJ5ID0+IGVudHJ5LmFyZWEsICJjaGVjayBhcmVhcyIpOwoKaWYgKCFBcnJheS5pc0FycmF5KGRhdGEuY29tcGxldGVkX2FjdGlvbnMpIHx8IGRhdGEuY29tcGxldGVkX2FjdGlvbnMubGVuZ3RoID4gMTAwKSBmYWlsKCJjb21wbGV0ZWRfYWN0aW9ucyBtdXN0IGJlIGFuIGFycmF5IG9mIGF0IG1vc3QgMTAwIGVudHJpZXMiKTsKZm9yIChjb25zdCBbaW5kZXgsIGVudHJ5XSBvZiBkYXRhLmNvbXBsZXRlZF9hY3Rpb25zLmVudHJpZXMoKSkgewogIGlmICghZXhhY3RLZXlzKGVudHJ5LCBbImtleSIsICJjb21wbGV0ZWRfYXQiXSkpIGZhaWwoYGludmFsaWQgY29tcGxldGVkX2FjdGlvbnMgZW50cnkgYXQgaW5kZXggJHtpbmRleH1gKTsKICBpZiAoIXZhbGlkVGV4dChlbnRyeS5rZXksIDEwMCkpIGZhaWwoYGludmFsaWQgY29tcGxldGVkIGFjdGlvbiBrZXkgYXQgaW5kZXggJHtpbmRleH1gKTsKICBpZiAoIXZhbGlkRGF0ZShlbnRyeS5jb21wbGV0ZWRfYXQpKSBmYWlsKGBpbnZhbGlkIGNvbXBsZXRlZCBhY3Rpb24gZGF0ZSBhdCBpbmRleCAke2luZGV4fWApOwp9CnVuaXF1ZShkYXRhLmNvbXBsZXRlZF9hY3Rpb25zLCBlbnRyeSA9PiBlbnRyeS5rZXksICJjb21wbGV0ZWQgYWN0aW9uIGtleXMiKTsKCmlmICghQXJyYXkuaXNBcnJheShkYXRhLnByaW9yaXRpZXMpIHx8IGRhdGEucHJpb3JpdGllcy5sZW5ndGggPiAyMCkgZmFpbCgicHJpb3JpdGllcyBtdXN0IGJlIGFuIGFycmF5IG9mIGF0IG1vc3QgMjAgZW50cmllcyIpOwpmb3IgKGNvbnN0IFtpbmRleCwgZW50cnldIG9mIGRhdGEucHJpb3JpdGllcy5lbnRyaWVzKCkpIHsKICBpZiAoIWV4YWN0S2V5cyhlbnRyeSwgWyJ0YXNrIiwgIml0ZW0iLCAibm90ZSJdKSkgZmFpbChgaW52YWxpZCBwcmlvcml0aWVzIGVudHJ5IGF0IGluZGV4ICR7aW5kZXh9YCk7CiAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKGVudHJ5LnRhc2spIHx8IGVudHJ5LnRhc2sgPCAxIHx8IGVudHJ5LnRhc2sgPiAxMCkgZmFpbChgaW52YWxpZCBwcmlvcml0eSB0YXNrIGF0IGluZGV4ICR7aW5kZXh9YCk7CiAgaWYgKCF2YWxpZFRleHQoZW50cnkuaXRlbSwgMTAwKSkgZmFpbChgaW52YWxpZCBwcmlvcml0eSBpdGVtIGF0IGluZGV4ICR7aW5kZXh9YCk7CiAgaWYgKCF2YWxpZFRleHQoZW50cnkubm90ZSwgMzAwKSkgZmFpbChgaW52YWxpZCBwcmlvcml0eSBub3RlIGF0IGluZGV4ICR7aW5kZXh9YCk7Cn0KdW5pcXVlKGRhdGEucHJpb3JpdGllcywgZW50cnkgPT4gYCR7ZW50cnkudGFza306JHtlbnRyeS5pdGVtfWAsICJwcmlvcml0eSB0YXNrL2l0ZW0gcGFpcnMiKTsKY29uc29sZS5sb2coInJlcG8tYXNzaXN0IG5vdGVzLmpzb24gY29uZm9ybXMgdG8gc2NoZW1hIik7Cg== + VALIDATION_TIMEOUT_SECONDS: 60 + FORMAT_JSON: 'true' + with: + script: | + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); + setupGlobals(core, github, context, exec, io, getOctokit); + const { validateMemoryStep } = require(path.join(actionsDir, 'validate_memory_step.cjs')); + validateMemoryStep(core, { kind: 'repo', formatJSON: process.env.FORMAT_JSON === 'true', requireValidationScript: true }); + - name: Upload repo-memory artifact (default) + if: always() && steps.filter_repo_memory_64656661756c74.outcome == 'success' && steps.validate_repo_memory_64656661756c74.outcome == 'success' uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: repo-memory-default path: /tmp/gh-aw/repo-memory/default retention-days: 1 if-no-files-found: ignore + # Small dedicated copy of the agent output so safe-output processing + # survives a failed or timed-out upload of the larger agent artifact + - name: Upload agent output fallback artifact + if: always() + continue-on-error: true + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: agent-output-fallback + path: | + /tmp/gh-aw/agent_output.json + /tmp/gh-aw/safeoutputs.jsonl + if-no-files-found: ignore - name: Upload agent artifacts if: always() continue-on-error: true @@ -1456,8 +1651,9 @@ jobs: /tmp/gh-aw/agent_usage.json /tmp/gh-aw/agent-stdio.log /tmp/gh-aw/pre-agent-audit.txt - /tmp/gh-aw/agent/ /tmp/gh-aw/github_rate_limits.jsonl + /tmp/gh-aw/otel.jsonl + /tmp/gh-aw/otlp-export-errors.jsonl /tmp/gh-aw/safeoutputs.jsonl /tmp/gh-aw/agent_output.json /tmp/gh-aw/aw-*.patch @@ -1486,7 +1682,7 @@ jobs: issues: write pull-requests: write concurrency: - group: "gh-aw-conclusion-repo-assist" + group: "gh-aw-conclusion-repo-assist-${{ github.event_name == 'schedule' && 'scheduled' || github.run_id }}" cancel-in-progress: false queue: max env: @@ -1499,7 +1695,7 @@ jobs: steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2 + uses: github/gh-aw-actions/setup@5e508589e03a7757a7e05b26e834292f5445bfb6 # v0.88.7 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} @@ -1508,8 +1704,8 @@ jobs: env: GH_AW_SETUP_WORKFLOW_NAME: "Repo Assist" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/repo-assist.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "1.0.79" - GH_AW_INFO_AWF_VERSION: "v0.27.44" + GH_AW_INFO_VERSION: "1.0.80" + GH_AW_INFO_AWF_VERSION: "v0.28.14" GH_AW_INFO_BODY_MODIFIED: "false" GH_AW_INFO_ENGINE_ID: "copilot" - name: Download agent output artifact @@ -1517,7 +1713,8 @@ jobs: continue-on-error: true uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: - name: agent + pattern: "{agent,agent-output-fallback}" + merge-multiple: true path: /tmp/gh-aw/ - name: Setup agent output environment variable id: setup-agent-output-env @@ -1525,14 +1722,24 @@ jobs: run: | mkdir -p /tmp/gh-aw/ find "/tmp/gh-aw/" -type f -print - echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT" + if [ -f "/tmp/gh-aw/agent_output.json" ]; then + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT" + fi + - name: Download detection artifact + id: download-detection-artifact + continue-on-error: true + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: detection + path: /tmp/gh-aw/threat-detection/ - name: Download Safe Outputs Items Manifest id: download-safe-outputs-manifest if: always() continue-on-error: true uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: - name: safe-outputs-items + pattern: safe-outputs-items + merge-multiple: true path: /tmp/gh-aw/ - name: Collect usage artifact files if: always() @@ -1551,6 +1758,8 @@ jobs: /tmp/gh-aw/usage/agent_usage.jsonl /tmp/gh-aw/usage/detection_usage.jsonl /tmp/gh-aw/usage/evals.jsonl + /tmp/gh-aw/usage/graders/grader_manifest.json + /tmp/gh-aw/usage/graders/grader_results.json /tmp/gh-aw/usage/github_rate_limits.jsonl /tmp/gh-aw/usage/agent/token_usage.jsonl /tmp/gh-aw/usage/detection/token_usage.jsonl @@ -1573,9 +1782,11 @@ jobs: with: github-token: ${{ github.token }} script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); setupGlobals(core, github, context); - const { main } = require('${{ runner.temp }}/gh-aw/actions/write_daily_aic_usage_cache.cjs'); + const { main } = require(path.join(actionsDir, 'write_daily_aic_usage_cache.cjs')); await main(); - name: Save daily AIC usage cache id: save-daily-aic-cache @@ -1602,8 +1813,8 @@ jobs: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} GH_AW_NOOP_MAX: "1" GH_AW_WORKFLOW_NAME: "Repo Assist" - GH_AW_WORKFLOW_SOURCE: "githubnext/agentics/workflows/repo-assist.md@ae8d551f07c7ed7619f8c58c7bb4c3ac89395d38" - GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/githubnext/agentics/blob/ae8d551f07c7ed7619f8c58c7bb4c3ac89395d38/workflows/repo-assist.md" + GH_AW_WORKFLOW_SOURCE: "githubnext/agentics/workflows/repo-assist.md@4bc8419fad05e6b032741cbfd189986700bcf71c" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/githubnext/agentics/blob/4bc8419fad05e6b032741cbfd189986700bcf71c/workflows/repo-assist.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: "false" @@ -1614,9 +1825,11 @@ jobs: with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/handle_noop_message.cjs'); + const { main } = require(path.join(actionsDir, 'handle_noop_message.cjs')); await main(); - name: Log detection run id: detection_runs @@ -1624,17 +1837,19 @@ jobs: env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} GH_AW_WORKFLOW_NAME: "Repo Assist" - GH_AW_WORKFLOW_SOURCE: "githubnext/agentics/workflows/repo-assist.md@ae8d551f07c7ed7619f8c58c7bb4c3ac89395d38" - GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/githubnext/agentics/blob/ae8d551f07c7ed7619f8c58c7bb4c3ac89395d38/workflows/repo-assist.md" + GH_AW_WORKFLOW_SOURCE: "githubnext/agentics/workflows/repo-assist.md@4bc8419fad05e6b032741cbfd189986700bcf71c" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/githubnext/agentics/blob/4bc8419fad05e6b032741cbfd189986700bcf71c/workflows/repo-assist.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 }} with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/handle_detection_runs.cjs'); + const { main } = require(path.join(actionsDir, 'handle_detection_runs.cjs')); await main(); - name: Record missing tool id: missing_tool @@ -1643,14 +1858,16 @@ jobs: 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: "Repo Assist" - GH_AW_WORKFLOW_SOURCE: "githubnext/agentics/workflows/repo-assist.md@ae8d551f07c7ed7619f8c58c7bb4c3ac89395d38" - GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/githubnext/agentics/blob/ae8d551f07c7ed7619f8c58c7bb4c3ac89395d38/workflows/repo-assist.md" + GH_AW_WORKFLOW_SOURCE: "githubnext/agentics/workflows/repo-assist.md@4bc8419fad05e6b032741cbfd189986700bcf71c" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/githubnext/agentics/blob/4bc8419fad05e6b032741cbfd189986700bcf71c/workflows/repo-assist.md" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/missing_tool.cjs'); + const { main } = require(path.join(actionsDir, 'missing_tool.cjs')); await main(); - name: Record incomplete id: report_incomplete @@ -1659,14 +1876,16 @@ jobs: 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: "Repo Assist" - GH_AW_WORKFLOW_SOURCE: "githubnext/agentics/workflows/repo-assist.md@ae8d551f07c7ed7619f8c58c7bb4c3ac89395d38" - GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/githubnext/agentics/blob/ae8d551f07c7ed7619f8c58c7bb4c3ac89395d38/workflows/repo-assist.md" + GH_AW_WORKFLOW_SOURCE: "githubnext/agentics/workflows/repo-assist.md@4bc8419fad05e6b032741cbfd189986700bcf71c" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/githubnext/agentics/blob/4bc8419fad05e6b032741cbfd189986700bcf71c/workflows/repo-assist.md" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/report_incomplete_handler.cjs'); + const { main } = require(path.join(actionsDir, 'report_incomplete_handler.cjs')); await main(); - name: Handle agent failure id: handle_agent_failure @@ -1675,8 +1894,8 @@ jobs: env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} GH_AW_WORKFLOW_NAME: "Repo Assist" - GH_AW_WORKFLOW_SOURCE: "githubnext/agentics/workflows/repo-assist.md@ae8d551f07c7ed7619f8c58c7bb4c3ac89395d38" - GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/githubnext/agentics/blob/ae8d551f07c7ed7619f8c58c7bb4c3ac89395d38/workflows/repo-assist.md" + GH_AW_WORKFLOW_SOURCE: "githubnext/agentics/workflows/repo-assist.md@4bc8419fad05e6b032741cbfd189986700bcf71c" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/githubnext/agentics/blob/4bc8419fad05e6b032741cbfd189986700bcf71c/workflows/repo-assist.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: "repo-assist" @@ -1699,6 +1918,7 @@ jobs: GH_AW_MAX_CACHE_MISSES_EXCEEDED: ${{ needs.agent.outputs.max_cache_misses_exceeded }} GH_AW_MISSING_MODEL_PRICING_ERROR: ${{ needs.agent.outputs.missing_model_pricing_error }} GH_AW_MISSING_MODEL_PRICING_MODEL_NAME: ${{ needs.agent.outputs.missing_model_pricing_model_name }} + GH_AW_SHELL_EXPANSION_GUARD_REJECTED: ${{ needs.agent.outputs.shell_expansion_guard_rejected }} GH_AW_ENGINE_API_HOSTS: "api.enterprise.githubcopilot.com,api.githubcopilot.com,api.business.githubcopilot.com,api.individual.githubcopilot.com" GH_AW_CODE_PUSH_FAILURE_ERRORS: ${{ needs.safe_outputs.outputs.code_push_failure_errors }} GH_AW_CODE_PUSH_FAILURE_COUNT: ${{ needs.safe_outputs.outputs.code_push_failure_count }} @@ -1721,9 +1941,11 @@ jobs: with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/handle_agent_failure.cjs'); + const { main } = require(path.join(actionsDir, 'handle_agent_failure.cjs')); await main(); - name: Report failed jobs id: report_failed_jobs @@ -1732,16 +1954,18 @@ jobs: env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} GH_AW_WORKFLOW_NAME: "Repo Assist" - GH_AW_WORKFLOW_SOURCE: "githubnext/agentics/workflows/repo-assist.md@ae8d551f07c7ed7619f8c58c7bb4c3ac89395d38" - GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/githubnext/agentics/blob/ae8d551f07c7ed7619f8c58c7bb4c3ac89395d38/workflows/repo-assist.md" + GH_AW_WORKFLOW_SOURCE: "githubnext/agentics/workflows/repo-assist.md@4bc8419fad05e6b032741cbfd189986700bcf71c" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/githubnext/agentics/blob/4bc8419fad05e6b032741cbfd189986700bcf71c/workflows/repo-assist.md" GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} GH_AW_REPORT_FAILED_JOBS: "true" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/report_failed_jobs.cjs'); + const { main } = require(path.join(actionsDir, 'report_failed_jobs.cjs')); await main(); - name: Update reaction comment with completion status id: conclusion @@ -1760,9 +1984,11 @@ jobs: with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/notify_comment_error.cjs'); + const { main } = require(path.join(actionsDir, 'notify_comment_error.cjs')); await main(); detection: @@ -1773,6 +1999,7 @@ jobs: runs-on: ubuntu-latest permissions: contents: read + timeout-minutes: 10 env: GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }} outputs: @@ -1783,7 +2010,7 @@ jobs: steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2 + uses: github/gh-aw-actions/setup@5e508589e03a7757a7e05b26e834292f5445bfb6 # v0.88.7 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} @@ -1792,16 +2019,23 @@ jobs: env: GH_AW_SETUP_WORKFLOW_NAME: "Repo Assist" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/repo-assist.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "1.0.79" - GH_AW_INFO_AWF_VERSION: "v0.27.44" + GH_AW_INFO_VERSION: "1.0.80" + GH_AW_INFO_AWF_VERSION: "v0.28.14" GH_AW_INFO_BODY_MODIFIED: "false" GH_AW_INFO_ENGINE_ID: "copilot" + - name: Download activation artifact + continue-on-error: true + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: activation + path: /tmp/gh-aw - name: Download agent output artifact id: download-agent-output continue-on-error: true uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: - name: agent + pattern: "{agent,agent-output-fallback}" + merge-multiple: true path: /tmp/gh-aw/ - name: Setup agent output environment variable id: setup-agent-output-env @@ -1809,7 +2043,9 @@ jobs: run: | mkdir -p /tmp/gh-aw/ find "/tmp/gh-aw/" -type f -print - echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT" + if [ -f "/tmp/gh-aw/agent_output.json" ]; then + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT" + fi - name: Checkout repository for patch context if: needs.agent.outputs.has_patch == 'true' uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 @@ -1821,7 +2057,7 @@ jobs: rm -rf /tmp/gh-aw/sandbox/firewall/logs rm -rf /tmp/gh-aw/sandbox/firewall/audit - name: Download container images - run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.27.44@sha256:0d727725c737b58c7bdf51f640cffb928385ec46517e0917c7f1a02f1bada8b4 ghcr.io/github/gh-aw-firewall/api-proxy:0.27.44@sha256:b50fbadba138f6e9aba94aca09711335c489bb3b15861220cb66f6092e042dc7 ghcr.io/github/gh-aw-firewall/squid:0.27.44@sha256:83e48bbe12c634be8c228a576832fe45f66c529ac3659db92bddbcf2eeb6d627 + run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.28.14@sha256:f7df036c86575527b61f3f7df91c4412349a12b2a74988d929eafa2999230c98 ghcr.io/github/gh-aw-firewall/api-proxy:0.28.14@sha256:6f95e2234dd9bd6333a8ff28ccea7ecf0204acd4a09108723844dbd2bf6268c5 ghcr.io/github/gh-aw-firewall/squid:0.28.14@sha256:2ce8df3abf3e9b76e9c0cf5863da41f1ab3f89b20ad14b988806ab89e7bf2cd5 - name: Check if detection needed id: detection_guard if: always() @@ -1851,49 +2087,80 @@ jobs: uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: WORKFLOW_NAME: "Repo Assist" - WORKFLOW_DESCRIPTION: "A friendly repository assistant that runs regularly (twice a day by default) to assist maintainers.\nCan also be triggered on-demand via '/repo-assist ' to perform specific tasks.\n- Labels and triages open issues\n- Comments helpfully on open issues to unblock contributors and onboard newcomers\n- Identifies issues that can be fixed and creates draft pull requests with fixes\n- Improves performance, testing, and code quality via PRs\n- Makes engineering investments: dependency updates, CI improvements, tooling\n- Updates its own PRs when CI fails or merge conflicts arise\n- Nudges stale PRs waiting for author response\n- Takes the repository forward with proactive improvements\n- Maintains a persistent memory of work done and what remains\nAlways polite, constructive, and mindful of the project's goals." + WORKFLOW_DESCRIPTION: "A friendly repository assistant that runs regularly (twice a day by default) to assist maintainers.\nCan also be triggered on-demand via '/repo-assist ' to perform specific tasks.\n- Labels and triages open issues\n- Investigates open issues and resolves, fixes, clarifies, or comments on them\n- Identifies issues that can be fixed and creates draft pull requests with fixes\n- Improves performance, testing, and code quality via PRs\n- Makes engineering investments: dependency updates, CI improvements, tooling\n- Updates its own PRs when CI fails or merge conflicts arise\n- Improves documentation, performs ad hoc QA, and maintains project basics\n- Takes the repository forward with proactive improvements\n- Maintains a persistent memory of work done and what remains\nAlways polite, constructive, and mindful of the project's goals." HAS_PATCH: ${{ needs.agent.outputs.has_patch }} GH_AW_DETECTION_CONTINUE_ON_ERROR: "true" + GH_AW_DETECTION_SKIP_PROMPT_SUMMARY: "true" with: script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/setup_threat_detection.cjs'); + const { main } = require(path.join(actionsDir, 'setup_threat_detection.cjs')); await main(); - name: Ensure threat-detection directory and log if: always() && steps.detection_guard.outputs.run_detection == 'true' run: | mkdir -p /tmp/gh-aw/threat-detection touch /tmp/gh-aw/threat-detection/detection.log - rm -f /tmp/gh-aw/step-summary.md - touch /tmp/gh-aw/step-summary.md + - name: Install AWF binary + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.28.14 --rootless - name: Setup Node.js uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version: '24' package-manager-cache: false - - name: Install ripgrep - run: bash "${RUNNER_TEMP}/gh-aw/actions/install_ripgrep.sh" - name: Install GitHub Copilot CLI run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" env: GH_HOST: github.com - GH_AW_COMPILED_VERSION: v0.86.2 - - name: Install AWF binary - run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.27.44 - - name: Execute GitHub Copilot CLI + GH_AW_COMPILED_VERSION: v0.88.7 + - name: Install threat-detect binary if: always() && steps.detection_guard.outputs.run_detection == 'true' continue-on-error: true + run: | + bash "${RUNNER_TEMP}/gh-aw/actions/install_threat_detect_binary.sh" v0.5.1 + - name: Execute threat detection with AWF id: detection_agentic_execution - # Copilot CLI tool arguments (sorted): - timeout-minutes: 20 + if: always() && steps.detection_guard.outputs.run_detection == 'true' + continue-on-error: true + timeout-minutes: 10 + env: + AWF_REFLECT_ENABLED: 1 + COPILOT_AGENT_RUNNER_TYPE: STANDALONE + COPILOT_DUMMY_BYOK: dummy-byok-key-for-offline-mode + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: detection + GH_AW_HARNESS_MAX_RETRIES: 0 + GH_AW_LLM_PROVIDER: github + GH_AW_MAX_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_DETECTION_MAX_AI_CREDITS || '400' }} + GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }} + GH_AW_PHASE: detection + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_TIMEOUT_MINUTES: 10 + GH_AW_VERSION: v0.88.7 + GITHUB_API_URL: ${{ github.api_url }} + GITHUB_AW: true + GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows + GITHUB_HEAD_REF: ${{ github.head_ref }} + GITHUB_REF_NAME: ${{ github.ref_name }} + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_STEP_SUMMARY: /tmp/gh-aw/agent-step-summary.md + GITHUB_WORKSPACE: ${{ github.workspace }} + GIT_AUTHOR_EMAIL: github-actions[bot]@users.noreply.github.com + GIT_AUTHOR_NAME: github-actions[bot] + GIT_COMMITTER_EMAIL: github-actions[bot]@users.noreply.github.com + GIT_COMMITTER_NAME: github-actions[bot] + RUNNER_TEMP: ${{ runner.temp }} + TRACEPARENT: ${{ env.GITHUB_AW_OTEL_TRACE_ID != '' && env.GITHUB_AW_OTEL_PARENT_SPAN_ID != '' && format('00-{0}-{1}-01', env.GITHUB_AW_OTEL_TRACE_ID, env.GITHUB_AW_OTEL_PARENT_SPAN_ID) || '' }} + WORKFLOW_NAME: "Repo Assist" + WORKFLOW_DESCRIPTION: "A friendly repository assistant that runs regularly (twice a day by default) to assist maintainers.\nCan also be triggered on-demand via '/repo-assist ' to perform specific tasks.\n- Labels and triages open issues\n- Investigates open issues and resolves, fixes, clarifies, or comments on them\n- Identifies issues that can be fixed and creates draft pull requests with fixes\n- Improves performance, testing, and code quality via PRs\n- Makes engineering investments: dependency updates, CI improvements, tooling\n- Updates its own PRs when CI fails or merge conflicts arise\n- Improves documentation, performs ad hoc QA, and maintains project basics\n- Takes the repository forward with proactive improvements\n- Maintains a persistent memory of work done and what remains\nAlways polite, constructive, and mindful of the project's goals." + HAS_PATCH: ${{ needs.agent.outputs.has_patch }} + GH_AW_DETECTION_CONTINUE_ON_ERROR: "true" run: | set -o pipefail printf '%s' "$(date +%s%3N)" > /tmp/gh-aw/agent_cli_start_ms.txt - trap 'gh_aw_exit_code=$?; mkdir -p /tmp/gh-aw >/dev/null 2>&1 || true; printf "%s" "$gh_aw_exit_code" > /tmp/gh-aw/agent_execution_exit_code.txt || true; rm -f "$HOME/.copilot/settings.json"' EXIT - mkdir -p "$HOME/.copilot" - printf '%s' '{"builtInAgents":{"rubberDuck":false}}' > "$HOME/.copilot/settings.json" - export XDG_CONFIG_HOME="$HOME" GH_AW_COPILOT_SRC="$(command -v copilot 2>/dev/null || true)" if [ -z "$GH_AW_COPILOT_SRC" ] || [ ! -x "$GH_AW_COPILOT_SRC" ]; then echo "GitHub Copilot CLI executable not found on PATH after installation" >&2 @@ -1906,13 +2173,12 @@ jobs: fi chmod 755 "$GH_AW_COPILOT_BIN" - touch /tmp/gh-aw/agent-step-summary.md - GH_AW_NODE_BIN=$(command -v node 2>/dev/null || true) - export GH_AW_NODE_BIN - export COPILOT_API_KEY="$COPILOT_DUMMY_BYOK" (umask 177 && touch /tmp/gh-aw/threat-detection/detection.log) GH_AW_MAX_AI_CREDITS="${GH_AW_MAX_AI_CREDITS:-400}" - printf '%s\n' "{\"\$schema\":\"https://github.com/github/gh-aw-firewall/releases/download/v0.27.44/awf-config.schema.json\",\"network\":{\"allowDomains\":[\"api.business.githubcopilot.com\",\"api.enterprise.githubcopilot.com\",\"api.github.com\",\"api.githubcopilot.com\",\"api.individual.githubcopilot.com\",\"github.com\",\"host.docker.internal\",\"registry.npmjs.org\",\"telemetry.enterprise.githubcopilot.com\"]},\"apiProxy\":{\"enabled\":true,\"enableTokenSteering\":true,\"maxRuns\":500,\"maxAiCredits\":${GH_AW_MAX_AI_CREDITS},\"maxCacheMisses\":5,\"models\":{\"agent\":[\"sonnet-6x\",\"gpt-5.4\",\"gpt-5.5\",\"gpt-5.6\",\"gpt-5.3\",\"gemini-pro\",\"any\"],\"antigravity\":[\"copilot/antigravity*\",\"google/antigravity*\",\"gemini/antigravity*\"],\"any\":[\"copilot/*\",\"anthropic/*\",\"openai/*\",\"google/*\",\"gemini/*\"],\"auto\":[\"copilot/auto\",\"large\"],\"claude\":[\"agent\"],\"codex\":[\"agent\"],\"coding\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\",\"gpt-5-codex\",\"kimi\"],\"computer-use\":[\"copilot/*computer-use*\",\"google/*computer-use*\",\"gemini/*computer-use*\",\"openai/*computer-use*\"],\"copilot\":[\"agent\"],\"deep-research\":[\"copilot/deep-research*\",\"copilot/o3-deep-research*\",\"copilot/o4-mini-deep-research*\",\"google/deep-research*\",\"gemini/deep-research*\",\"openai/o3-deep-research*\",\"openai/o4-mini-deep-research*\"],\"detection\":[\"small\"],\"evals\":[\"small\"],\"fable\":[\"copilot/*fable*\",\"anthropic/*fable*\"],\"gemini\":[\"agent\"],\"gemini-3-flash\":[\"copilot/gemini-3*flash*\",\"google/gemini-3*flash*\",\"gemini/gemini-3*flash*\"],\"gemini-3-pro\":[\"copilot/gemini-3*pro*\",\"google/gemini-3*pro*\",\"google/nano-banana*\",\"gemini/gemini-3*pro*\"],\"gemini-3.1-flash\":[\"copilot/gemini-3.1*flash*\",\"google/gemini-3.1*flash*\",\"gemini/gemini-3.1*flash*\"],\"gemini-3.1-pro\":[\"copilot/gemini-3.1*pro*\",\"google/gemini-3.1*pro*\",\"gemini/gemini-3.1*pro*\"],\"gemini-3.5-flash\":[\"copilot/gemini-3.5*flash*\",\"google/gemini-3.5*flash*\",\"gemini/gemini-3.5*flash*\"],\"gemini-3.6-flash\":[\"copilot/gemini-3.6*flash*\",\"google/gemini-3.6*flash*\",\"gemini/gemini-3.6*flash*\"],\"gemini-flash\":[\"copilot/gemini-*flash*\",\"google/gemini-*flash*\",\"gemini/gemini-*flash*\"],\"gemini-flash-lite\":[\"copilot/gemini-*flash*lite*\",\"google/gemini-*flash*lite*\",\"gemini/gemini-*flash*lite*\"],\"gemini-omni\":[\"copilot/gemini-omni*\",\"google/gemini-omni*\",\"gemini/gemini-omni*\"],\"gemini-pro\":[\"copilot/gemini-*pro*\",\"google/gemini-*pro*\",\"gemini/gemini-*pro*\"],\"gemma\":[\"copilot/gemma*\",\"google/gemma*\",\"gemini/gemma*\"],\"gpt-5\":[\"copilot/gpt-5*\",\"openai/gpt-5*\"],\"gpt-5-codex\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\"],\"gpt-5-mini\":[\"copilot/gpt-5*mini*\",\"openai/gpt-5*mini*\"],\"gpt-5-nano\":[\"copilot/gpt-5*nano*\",\"openai/gpt-5*nano*\"],\"gpt-5-pro\":[\"copilot/gpt-5*pro*\",\"openai/gpt-5*pro*\"],\"gpt-5.1\":[\"copilot/gpt-5.1*\",\"openai/gpt-5.1*\"],\"gpt-5.2\":[\"copilot/gpt-5.2*\",\"openai/gpt-5.2*\"],\"gpt-5.3\":[\"copilot/gpt-5.3*\",\"openai/gpt-5.3*\"],\"gpt-5.4\":[\"copilot/gpt-5.4*\",\"openai/gpt-5.4*\"],\"gpt-5.5\":[\"copilot/gpt-5.5*\",\"openai/gpt-5.5*\"],\"gpt-5.6\":[\"copilot/gpt-5.6*\",\"openai/gpt-5.6*\"],\"grok\":[\"copilot/*grok*\",\"openai/*grok*\"],\"haiku\":[\"copilot/*haiku*\",\"anthropic/*haiku*\"],\"image-generation\":[\"copilot/gpt-image*\",\"openai/gpt-image*\",\"openai/chatgpt-image*\",\"copilot/gemini-*image*\",\"google/gemini-*image*\",\"gemini/gemini-*image*\",\"google/imagen*\"],\"kimi\":[\"copilot/kimi*\",\"openai/kimi*\"],\"kiwi\":[\"copilot/kiwi*\",\"openai/kiwi*\"],\"large\":[\"sonnet\",\"gpt-5-pro\",\"gpt-5\",\"gemini-pro\"],\"lyria\":[\"google/lyria*\",\"gemini/lyria*\",\"copilot/lyria*\"],\"mai-code\":[\"copilot/MAI-Code*\",\"copilot/mai-code*\",\"openai/MAI-Code*\"],\"mai-code-1-flash-picker\":[\"copilot/MAI-Code-1-Flash-picker*\",\"copilot/mai-code-1-flash-picker*\",\"openai/MAI-Code-1-Flash-picker*\"],\"mini\":[\"haiku\",\"gpt-5-mini\",\"gpt-5-nano\",\"gemini-flash-lite\"],\"nano-banana\":[\"copilot/nano-banana*\",\"google/nano-banana*\",\"gemini/nano-banana*\"],\"opus\":[\"copilot/*opus*\",\"anthropic/*opus*\"],\"opusplan\":[\"opus?effort=high\"],\"raptor-mini\":[\"copilot/raptor*\",\"openai/raptor*\"],\"reasoning\":[\"copilot/o1*\",\"copilot/o3*\",\"copilot/o4*\",\"openai/o1*\",\"openai/o3*\",\"openai/o4*\"],\"robotics\":[\"copilot/*robotics*\",\"google/*robotics*\",\"gemini/*robotics*\"],\"small\":[\"mini\"],\"small-agent\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash\"],\"sonnet\":[\"copilot/*sonnet*\",\"anthropic/*sonnet*\"],\"sonnet-6x\":[\"copilot/*sonnet-4.5*\",\"copilot/*sonnet-4.6*\",\"copilot/*sonnet-5*\",\"copilot/*sonnet-4-5-*\",\"anthropic/*sonnet-4-5-*\",\"copilot/*sonnet-4-6*\",\"anthropic/*sonnet-4-6*\",\"anthropic/*sonnet-5*\"],\"summarization\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash-lite\",\"mini\"],\"veo\":[\"google/veo*\",\"gemini/veo*\"],\"vision\":[\"copilot/gemini-*image*\",\"google/gemini-*image*\",\"gemini/gemini-*image*\",\"copilot/gemini-*flash*\",\"google/gemini-*flash*\",\"gemini/gemini-*flash*\"]}},\"container\":{\"imageTag\":\"0.27.44,squid=sha256:83e48bbe12c634be8c228a576832fe45f66c529ac3659db92bddbcf2eeb6d627,agent=sha256:0d727725c737b58c7bdf51f640cffb928385ec46517e0917c7f1a02f1bada8b4,api-proxy=sha256:b50fbadba138f6e9aba94aca09711335c489bb3b15861220cb66f6092e042dc7,cli-proxy=sha256:c064d15974f7c933ec7d3f7b4038f4fd203547b3154bdc821afd379144887eff\"},\"logging\":{\"proxyLogsDir\":\"/tmp/gh-aw/sandbox/firewall/logs\",\"auditDir\":\"/tmp/gh-aw/sandbox/firewall/audit\"}}" > "${RUNNER_TEMP}/gh-aw/awf-config.json" + if [[ ! "$GH_AW_MAX_AI_CREDITS" =~ ^[0-9]+$ ]]; then + GH_AW_MAX_AI_CREDITS="400" + fi + printf '%s\n' "{\"\$schema\":\"https://github.com/github/gh-aw-firewall/releases/download/v0.28.14/awf-config.schema.json\",\"apiProxy\":{\"enabled\":true,\"enableTokenSteering\":true,\"maxRuns\":500,\"maxAiCredits\":${GH_AW_MAX_AI_CREDITS},\"maxCacheMisses\":5,\"models\":{\"agent\":[\"sonnet-6x\",\"gpt-5.4\",\"gpt-5.5\",\"gpt-5.6\",\"gpt-5.3\",\"gemini-pro\",\"any\"],\"antigravity\":[\"copilot/antigravity*\",\"google/antigravity*\",\"gemini/antigravity*\"],\"any\":[\"copilot/*\",\"anthropic/*\",\"openai/*\",\"google/*\",\"gemini/*\"],\"auto\":[\"copilot/auto\",\"large\"],\"claude\":[\"agent\"],\"codex\":[\"agent\"],\"coding\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\",\"gpt-5-codex\",\"kimi\"],\"computer-use\":[\"copilot/*computer-use*\",\"google/*computer-use*\",\"gemini/*computer-use*\",\"openai/*computer-use*\"],\"copilot\":[\"agent\"],\"deep-research\":[\"copilot/deep-research*\",\"copilot/o3-deep-research*\",\"copilot/o4-mini-deep-research*\",\"google/deep-research*\",\"gemini/deep-research*\",\"openai/o3-deep-research*\",\"openai/o4-mini-deep-research*\"],\"detection\":[\"small\"],\"evals\":[\"small\"],\"fable\":[\"copilot/*fable*\",\"anthropic/*fable*\"],\"gemini\":[\"agent\"],\"gemini-3-flash\":[\"copilot/gemini-3*flash*\",\"google/gemini-3*flash*\",\"gemini/gemini-3*flash*\"],\"gemini-3-pro\":[\"copilot/gemini-3*pro*\",\"google/gemini-3*pro*\",\"google/nano-banana*\",\"gemini/gemini-3*pro*\"],\"gemini-3.1-flash\":[\"copilot/gemini-3.1*flash*\",\"google/gemini-3.1*flash*\",\"gemini/gemini-3.1*flash*\"],\"gemini-3.1-pro\":[\"copilot/gemini-3.1*pro*\",\"google/gemini-3.1*pro*\",\"gemini/gemini-3.1*pro*\"],\"gemini-3.5-flash\":[\"copilot/gemini-3.5*flash*\",\"google/gemini-3.5*flash*\",\"gemini/gemini-3.5*flash*\"],\"gemini-3.6-flash\":[\"copilot/gemini-3.6*flash*\",\"google/gemini-3.6*flash*\",\"gemini/gemini-3.6*flash*\"],\"gemini-3.7-flash\":[\"copilot/gemini-3.7*flash*\",\"google/gemini-3.7*flash*\",\"gemini/gemini-3.7*flash*\"],\"gemini-flash\":[\"copilot/gemini-*flash*\",\"google/gemini-*flash*\",\"gemini/gemini-*flash*\"],\"gemini-flash-lite\":[\"copilot/gemini-*flash*lite*\",\"google/gemini-*flash*lite*\",\"gemini/gemini-*flash*lite*\"],\"gemini-omni\":[\"copilot/gemini-omni*\",\"google/gemini-omni*\",\"gemini/gemini-omni*\"],\"gemini-pro\":[\"copilot/gemini-*pro*\",\"google/gemini-*pro*\",\"gemini/gemini-*pro*\"],\"gemma\":[\"copilot/gemma*\",\"google/gemma*\",\"gemini/gemma*\"],\"gpt-5\":[\"copilot/gpt-5*\",\"openai/gpt-5*\"],\"gpt-5-codex\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\"],\"gpt-5-mini\":[\"copilot/gpt-5*mini*\",\"openai/gpt-5*mini*\"],\"gpt-5-nano\":[\"copilot/gpt-5*nano*\",\"openai/gpt-5*nano*\"],\"gpt-5-pro\":[\"copilot/gpt-5*pro*\",\"openai/gpt-5*pro*\"],\"gpt-5.1\":[\"copilot/gpt-5.1*\",\"openai/gpt-5.1*\"],\"gpt-5.2\":[\"copilot/gpt-5.2*\",\"openai/gpt-5.2*\"],\"gpt-5.3\":[\"copilot/gpt-5.3*\",\"openai/gpt-5.3*\"],\"gpt-5.4\":[\"copilot/gpt-5.4*\",\"openai/gpt-5.4*\"],\"gpt-5.5\":[\"copilot/gpt-5.5*\",\"openai/gpt-5.5*\"],\"gpt-5.6\":[\"copilot/gpt-5.6*\",\"openai/gpt-5.6*\"],\"grok\":[\"copilot/*grok*\",\"openai/*grok*\"],\"haiku\":[\"copilot/*haiku*\",\"anthropic/*haiku*\"],\"image-generation\":[\"copilot/gpt-image*\",\"openai/gpt-image*\",\"openai/chatgpt-image*\",\"copilot/gemini-*image*\",\"google/gemini-*image*\",\"gemini/gemini-*image*\",\"google/imagen*\"],\"kimi\":[\"copilot/kimi*\",\"openai/kimi*\"],\"kiwi\":[\"copilot/kiwi*\",\"openai/kiwi*\"],\"large\":[\"sonnet\",\"gpt-5-pro\",\"gpt-5\",\"gemini-pro\"],\"lyria\":[\"google/lyria*\",\"gemini/lyria*\",\"copilot/lyria*\"],\"mai-code\":[\"copilot/MAI-Code*\",\"copilot/mai-code*\",\"openai/MAI-Code*\"],\"mai-code-1-flash-picker\":[\"copilot/MAI-Code-1-Flash-picker*\",\"copilot/mai-code-1-flash-picker*\",\"openai/MAI-Code-1-Flash-picker*\"],\"mini\":[\"haiku\",\"gpt-5-mini\",\"gpt-5-nano\",\"gemini-flash-lite\"],\"nano-banana\":[\"copilot/nano-banana*\",\"google/nano-banana*\",\"gemini/nano-banana*\"],\"opus\":[\"copilot/*opus*\",\"anthropic/*opus*\"],\"opusplan\":[\"opus?effort=high\"],\"raptor-mini\":[\"copilot/raptor*\",\"openai/raptor*\"],\"reasoning\":[\"copilot/o1*\",\"copilot/o3*\",\"copilot/o4*\",\"openai/o1*\",\"openai/o3*\",\"openai/o4*\"],\"robotics\":[\"copilot/*robotics*\",\"google/*robotics*\",\"gemini/*robotics*\"],\"small\":[\"mini\"],\"small-agent\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash\"],\"sonnet\":[\"copilot/*sonnet*\",\"anthropic/*sonnet*\"],\"sonnet-6x\":[\"copilot/*sonnet-4.5*\",\"copilot/*sonnet-4.6*\",\"copilot/*sonnet-5*\",\"copilot/*sonnet-4-5-*\",\"anthropic/*sonnet-4-5-*\",\"copilot/*sonnet-4-6*\",\"anthropic/*sonnet-4-6*\",\"anthropic/*sonnet-5*\"],\"summarization\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash-lite\",\"mini\"],\"veo\":[\"google/veo*\",\"gemini/veo*\"],\"vision\":[\"copilot/gemini-*image*\",\"google/gemini-*image*\",\"gemini/gemini-*image*\",\"copilot/gemini-*flash*\",\"google/gemini-*flash*\",\"gemini/gemini-*flash*\"]}},\"container\":{\"imageTag\":\"0.28.14,squid=sha256:2ce8df3abf3e9b76e9c0cf5863da41f1ab3f89b20ad14b988806ab89e7bf2cd5,agent=sha256:f7df036c86575527b61f3f7df91c4412349a12b2a74988d929eafa2999230c98,api-proxy=sha256:6f95e2234dd9bd6333a8ff28ccea7ecf0204acd4a09108723844dbd2bf6268c5,cli-proxy=sha256:3a379c5e96e29499c815e9dd2a71334d01c326a9b73991c76544fda9cae35c34\"},\"logging\":{\"proxyLogsDir\":\"/tmp/gh-aw/sandbox/firewall/logs\",\"auditDir\":\"/tmp/gh-aw/sandbox/firewall/audit\"}}" > "${RUNNER_TEMP}/gh-aw/awf-config.json" cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json export GH_AW_MODELS_JSON_PATH="/tmp/gh-aw/models.json" GH_AW_DOCKER_HOST="" @@ -1922,7 +2188,6 @@ jobs: if [[ "${DOCKER_HOST:-}" =~ ^tcp:// ]]; then _GH_AW_CHROOT_JSON=$(jq -c --arg src "${RUNNER_TEMP}/gh-aw" --arg user "$(id -un)" --argjson uid "$(id -u)" --argjson gid "$(id -g)" --arg home "${RUNNER_TEMP}/gh-aw/home" '.chroot={"binariesSourcePath":$src,"identity":{"user":$user,"uid":$uid,"gid":$gid,"home":$home}}' "${RUNNER_TEMP}/gh-aw/awf-config.json") || { echo "chroot config patch failed" >&2; exit 1; } printf '%s\n' "$_GH_AW_CHROOT_JSON" > "${RUNNER_TEMP}/gh-aw/awf-config.json" - printf '%s\n' "$_GH_AW_CHROOT_JSON" > "${RUNNER_TEMP}/gh-aw/awf-config.json" fi GH_AW_TOOL_CACHE_MOUNT="" GH_AW_TOOL_CACHE="${RUNNER_TOOL_CACHE:?RUNNER_TOOL_CACHE must be set}" @@ -1932,52 +2197,37 @@ jobs: fi fi # shellcheck disable=SC1003,SC2016,SC2086 - awf --config "${RUNNER_TEMP}/gh-aw/awf-config.json" --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" ${GH_AW_TOOL_CACHE_MOUNT:+--mount "$GH_AW_TOOL_CACHE_MOUNT"} ${GH_AW_DOCKER_HOST:+--docker-host "$GH_AW_DOCKER_HOST"} --env-all --exclude-env ACTIONS_ID_TOKEN_REQUEST_TOKEN --exclude-env ACTIONS_ID_TOKEN_REQUEST_URL --exclude-env COPILOT_GITHUB_TOKEN --mount /tmp/gh-aw:/tmp/gh-aw:rw --log-level info --skip-pull \ - -- /bin/bash -c 'set +o histexpand; : "${RUNNER_TOOL_CACHE:?RUNNER_TOOL_CACHE must be set}"; GH_AW_TOOL_CACHE="$RUNNER_TOOL_CACHE"; export PATH="$(find "$GH_AW_TOOL_CACHE" -maxdepth 5 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true; [ -n "$ERLANG_HOME" ] && export PATH="$ERLANG_HOME/bin:$PATH" || true && GH_AW_NODE_EXEC="${GH_AW_NODE_BIN:-}"; if [ -z "$GH_AW_NODE_EXEC" ] || [ ! -x "$GH_AW_NODE_EXEC" ]; then GH_AW_NODE_EXEC="$(command -v node 2>/dev/null || true)"; fi; if [ -z "$GH_AW_NODE_EXEC" ]; then echo "node runtime missing on this runner β€” check runtimes.node in workflow YAML" >&2; exit 127; fi; GH_AW_NPM_GLOBAL_ROOT="$(npm root -g 2>/dev/null || true)"; if [ -n "$GH_AW_NPM_GLOBAL_ROOT" ]; then export NODE_PATH="${GH_AW_NPM_GLOBAL_ROOT}${NODE_PATH:+:${NODE_PATH}}"; fi; "$GH_AW_NODE_EXEC" "${RUNNER_TEMP}/gh-aw/actions/copilot_harness.cjs" "${RUNNER_TEMP}/gh-aw/bin/copilot" --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --allow-all-tools --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/threat-detection/detection.log - env: - GITHUB_STEP_SUMMARY: /tmp/gh-aw/step-summary.md - AWF_REFLECT_ENABLED: 1 - COPILOT_AGENT_RUNNER_TYPE: STANDALONE - COPILOT_DUMMY_BYOK: dummy-byok-key-for-offline-mode - COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} - COPILOT_MODEL: detection - GH_AW_LLM_PROVIDER: github - GH_AW_MAX_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_DETECTION_MAX_AI_CREDITS || '400' }} - GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }} - GH_AW_PHASE: detection - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - GH_AW_TIMEOUT_MINUTES: 20 - GH_AW_VERSION: v0.86.2 - GITHUB_API_URL: ${{ github.api_url }} - GITHUB_AW: true - GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows - GITHUB_HEAD_REF: ${{ github.head_ref }} - GITHUB_REF_NAME: ${{ github.ref_name }} - GITHUB_SERVER_URL: ${{ github.server_url }} - GITHUB_WORKSPACE: ${{ github.workspace }} - GIT_AUTHOR_EMAIL: github-actions[bot]@users.noreply.github.com - GIT_AUTHOR_NAME: github-actions[bot] - GIT_COMMITTER_EMAIL: github-actions[bot]@users.noreply.github.com - GIT_COMMITTER_NAME: github-actions[bot] - RUNNER_TEMP: ${{ runner.temp }} - TRACEPARENT: ${{ env.GITHUB_AW_OTEL_TRACE_ID != '' && env.GITHUB_AW_OTEL_PARENT_SPAN_ID != '' && format('00-{0}-{1}-01', env.GITHUB_AW_OTEL_TRACE_ID, env.GITHUB_AW_OTEL_PARENT_SPAN_ID) || '' }} - - name: Echo detection step summary - if: always() && steps.detection_guard.outputs.run_detection == 'true' - continue-on-error: true - run: | - if [ -s /tmp/gh-aw/step-summary.md ]; then - cat /tmp/gh-aw/step-summary.md - fi + awf --config "${RUNNER_TEMP}/gh-aw/awf-config.json" --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" ${GH_AW_TOOL_CACHE_MOUNT:+--mount "$GH_AW_TOOL_CACHE_MOUNT"} ${GH_AW_DOCKER_HOST:+--docker-host "$GH_AW_DOCKER_HOST"} --env-all --exclude-env ACTIONS_ID_TOKEN_REQUEST_TOKEN --exclude-env ACTIONS_ID_TOKEN_REQUEST_URL --exclude-env COPILOT_GITHUB_TOKEN --mount /tmp/gh-aw:/tmp/gh-aw:rw --mount /tmp/gh-aw/threat-detection:/tmp/gh-aw/threat-detection:rw --log-level info --skip-pull \ + -- /bin/bash -c 'set +o histexpand; export PATH="${RUNNER_TEMP}/gh-aw/bin:$PATH" && : "${RUNNER_TOOL_CACHE:?RUNNER_TOOL_CACHE must be set}"; GH_AW_TOOL_CACHE="$RUNNER_TOOL_CACHE"; GH_AW_TOOL_BINS="$(find "$GH_AW_TOOL_CACHE" -maxdepth 5 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')"; GH_AW_TOOL_BINS="${GH_AW_TOOL_BINS%:}"; export PATH="$PATH${GH_AW_TOOL_BINS:+:}$GH_AW_TOOL_BINS"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true; [ -n "$ERLANG_HOME" ] && export PATH="$ERLANG_HOME/bin:$PATH" || true && threat-detect --engine copilot --output /tmp/gh-aw/threat-detection/detection_result.json /tmp/gh-aw/threat-detection' 2>&1 | tee -a /tmp/gh-aw/threat-detection/detection.log - name: Render detection log if: always() && steps.detection_guard.outputs.run_detection == 'true' continue-on-error: true uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/render_detection_log.cjs'); + const { main } = require(path.join(actionsDir, 'render_detection_log.cjs')); await main(); + - name: Copy detection firewall logs + if: always() && steps.detection_guard.outputs.run_detection == 'true' + continue-on-error: true + run: | + mkdir -p /tmp/gh-aw/threat-detection/sandbox/firewall + if [ -d /tmp/gh-aw/sandbox/firewall/logs ]; then mkdir -p /tmp/gh-aw/threat-detection/sandbox/firewall/logs && cp -r /tmp/gh-aw/sandbox/firewall/logs/. /tmp/gh-aw/threat-detection/sandbox/firewall/logs/; fi + if [ -d /tmp/gh-aw/sandbox/firewall/audit ]; then mkdir -p /tmp/gh-aw/threat-detection/sandbox/firewall/audit && cp -r /tmp/gh-aw/sandbox/firewall/audit/. /tmp/gh-aw/threat-detection/sandbox/firewall/audit/; fi + - name: Upload threat detection artifact + if: always() && steps.detection_guard.outputs.run_detection == 'true' + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: detection + path: | + /tmp/gh-aw/threat-detection/detection_result.json + /tmp/gh-aw/threat-detection/sandbox/firewall/logs/ + /tmp/gh-aw/threat-detection/sandbox/firewall/audit/ + if-no-files-found: ignore - name: Parse threat detection token usage for step summary id: parse_detection_token_usage if: always() @@ -1987,49 +2237,22 @@ jobs: GH_AW_TOKEN_USAGE_SUMMARY_TITLE: Threat Detection Token Usage with: script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_token_usage.cjs'); + const { main } = require(path.join(actionsDir, 'parse_token_usage.cjs')); await main(); - - name: Upload threat detection log - if: always() && steps.detection_guard.outputs.run_detection == 'true' - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - with: - name: detection - path: /tmp/gh-aw/threat-detection/detection.log - if-no-files-found: ignore - - name: Parse and conclude threat detection + - name: Conclude threat detection id: detection_conclusion if: always() continue-on-error: true - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: RUN_DETECTION: ${{ steps.detection_guard.outputs.run_detection }} DETECTION_AGENTIC_EXECUTION_OUTCOME: ${{ steps.detection_agentic_execution.outcome }} GH_AW_DETECTION_CONTINUE_ON_ERROR: "true" - with: - script: | - try { - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_threat_detection_results.cjs'); - await main(); - } catch (loadErr) { - const continueOnError = process.env.GH_AW_DETECTION_CONTINUE_ON_ERROR !== 'false'; - const detectionExecutionFailed = process.env.DETECTION_AGENTIC_EXECUTION_OUTCOME === 'failure'; - const msg = 'ERR_SYSTEM: \u274C Unexpected error loading threat detection module: ' + (loadErr && loadErr.message ? loadErr.message : String(loadErr)); - core.error(msg); - core.setOutput('reason', 'parse_error'); - if (continueOnError && !detectionExecutionFailed) { - core.warning('\u26A0\uFE0F ' + msg); - core.setOutput('conclusion', 'warning'); - core.setOutput('success', 'false'); - } else { - core.setOutput('conclusion', 'failure'); - core.setOutput('success', 'false'); - core.setFailed(msg); - } - } + run: | + bash "${RUNNER_TEMP}/gh-aw/actions/conclude_threat_detection.sh" /tmp/gh-aw/threat-detection/detection_result.json pre_activation: runs-on: ubuntu-slim @@ -2047,15 +2270,15 @@ jobs: steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2 + uses: github/gh-aw-actions/setup@5e508589e03a7757a7e05b26e834292f5445bfb6 # v0.88.7 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} env: GH_AW_SETUP_WORKFLOW_NAME: "Repo Assist" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/repo-assist.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "1.0.79" - GH_AW_INFO_AWF_VERSION: "v0.27.44" + GH_AW_INFO_VERSION: "1.0.80" + GH_AW_INFO_AWF_VERSION: "v0.28.14" GH_AW_INFO_BODY_MODIFIED: "false" GH_AW_INFO_ENGINE_ID: "copilot" - name: Check command position @@ -2065,9 +2288,11 @@ jobs: GH_AW_COMMANDS: "[\"repo-assist\"]" with: script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/check_command_position.cjs'); + const { main } = require(path.join(actionsDir, 'check_command_position.cjs')); await main(); - name: Check team membership for command workflow id: check_membership @@ -2078,9 +2303,11 @@ jobs: with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/check_membership.cjs'); + const { main } = require(path.join(actionsDir, 'check_membership.cjs')); await main(); - id: check run: | @@ -2114,7 +2341,7 @@ jobs: steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2 + uses: github/gh-aw-actions/setup@5e508589e03a7757a7e05b26e834292f5445bfb6 # v0.88.7 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} @@ -2123,8 +2350,8 @@ jobs: env: GH_AW_SETUP_WORKFLOW_NAME: "Repo Assist" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/repo-assist.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "1.0.79" - GH_AW_INFO_AWF_VERSION: "v0.27.44" + GH_AW_INFO_VERSION: "1.0.80" + GH_AW_INFO_AWF_VERSION: "v0.28.14" GH_AW_INFO_BODY_MODIFIED: "false" GH_AW_INFO_ENGINE_ID: "copilot" - name: Checkout repository @@ -2156,15 +2383,20 @@ jobs: MEMORY_ID: default TARGET_REPO: ${{ github.repository }} BRANCH_NAME: memory/repo-assist - MAX_FILE_SIZE: 102400 - MAX_FILE_COUNT: 100 - MAX_PATCH_SIZE: 10240 - ALLOWED_EXTENSIONS: '[]' + MAX_FILE_SIZE: 65536 + MAX_FILE_COUNT: 1 + MAX_PATCH_SIZE: 65536 + ALLOWED_EXTENSIONS: '[".json"]' + FORMAT_JSON: 'true' + VALIDATION_SCRIPT_B64: Y29uc3QgZnMgPSByZXF1aXJlKCJub2RlOmZzIik7CmNvbnN0IHBhdGggPSByZXF1aXJlKCJub2RlOnBhdGgiKTsKY29uc3QgZmFpbCA9IG1lc3NhZ2UgPT4geyB0aHJvdyBuZXcgRXJyb3IoYG5vdGVzLmpzb246ICR7bWVzc2FnZX1gKTsgfTsKY29uc3Qgbm90ZXNQYXRoID0gcGF0aC5qb2luKG1lbW9yeVJvb3QsICJub3Rlcy5qc29uIik7CmlmICghZnMuZXhpc3RzU3luYyhub3Rlc1BhdGgpKSBmYWlsKCJtaXNzaW5nIChjcmVhdGUgYW4gaW5pdGlhbCBub3Rlcy5qc29uIHRoYXQgbWF0Y2hlcyBzY2hlbWEgdmVyc2lvbiAxKSIpOwpjb25zdCBkYXRhID0gSlNPTi5wYXJzZShmcy5yZWFkRmlsZVN5bmMobm90ZXNQYXRoLCAidXRmOCIpKTsKY29uc3QgaXNPYmplY3QgPSB2YWx1ZSA9PiB2YWx1ZSAhPT0gbnVsbCAmJiB0eXBlb2YgdmFsdWUgPT09ICJvYmplY3QiICYmICFBcnJheS5pc0FycmF5KHZhbHVlKTsKY29uc3QgZXhhY3RLZXlzID0gKHZhbHVlLCBrZXlzKSA9PiBpc09iamVjdCh2YWx1ZSkgJiYgT2JqZWN0LmtleXModmFsdWUpLnNvcnQoKS5qb2luKCIsIikgPT09IFsuLi5rZXlzXS5zb3J0KCkuam9pbigiLCIpOwpjb25zdCB2YWxpZERhdGUgPSB2YWx1ZSA9PiB0eXBlb2YgdmFsdWUgPT09ICJzdHJpbmciICYmIC9eWzAtOV17NH0tWzAtOV17Mn0tWzAtOV17Mn0kLy50ZXN0KHZhbHVlKTsKY29uc3QgdmFsaWRUZXh0ID0gKHZhbHVlLCBtYXhpbXVtKSA9PiB0eXBlb2YgdmFsdWUgPT09ICJzdHJpbmciICYmIHZhbHVlLmxlbmd0aCA+IDAgJiYgdmFsdWUubGVuZ3RoIDw9IG1heGltdW07CmNvbnN0IHVuaXF1ZSA9IChlbnRyaWVzLCBrZXksIGxhYmVsKSA9PiB7CiAgY29uc3QgdmFsdWVzID0gZW50cmllcy5tYXAoa2V5KTsKICBpZiAobmV3IFNldCh2YWx1ZXMpLnNpemUgIT09IHZhbHVlcy5sZW5ndGgpIGZhaWwoYCR7bGFiZWx9IG11c3QgYmUgdW5pcXVlYCk7Cn07CgppZiAoIWV4YWN0S2V5cyhkYXRhLCBbInZlcnNpb24iLCAiY3Vyc29ycyIsICJpc3N1ZXMiLCAiZml4ZXMiLCAiY2hlY2tzIiwgImNvbXBsZXRlZF9hY3Rpb25zIiwgInByaW9yaXRpZXMiXSkpIGZhaWwoIm11c3QgY29udGFpbiBleGFjdGx5IHZlcnNpb24sIGN1cnNvcnMsIGlzc3VlcywgZml4ZXMsIGNoZWNrcywgY29tcGxldGVkX2FjdGlvbnMsIGFuZCBwcmlvcml0aWVzIik7CmlmIChkYXRhLnZlcnNpb24gIT09IDEpIGZhaWwoInZlcnNpb24gbXVzdCBiZSAxIik7CmlmICghZXhhY3RLZXlzKGRhdGEuY3Vyc29ycywgWyJsYWJlbGxpbmdfYWZ0ZXIiLCAiaW52ZXN0aWdhdGlvbl9hZnRlciJdKSkgZmFpbCgiY3Vyc29ycyBtdXN0IGNvbnRhaW4gZXhhY3RseSBsYWJlbGxpbmdfYWZ0ZXIgYW5kIGludmVzdGlnYXRpb25fYWZ0ZXIiKTsKZm9yIChjb25zdCBbbmFtZSwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKGRhdGEuY3Vyc29ycykpIHsKICBpZiAodmFsdWUgIT09IG51bGwgJiYgKCFOdW1iZXIuaXNJbnRlZ2VyKHZhbHVlKSB8fCB2YWx1ZSA8IDEpKSBmYWlsKGAke25hbWV9IG11c3QgYmUgbnVsbCBvciBhIHBvc2l0aXZlIGlzc3VlIG51bWJlcmApOwp9Cgpjb25zdCBpc3N1ZVN0YXRlcyA9IG5ldyBTZXQoWyJjb21tZW50ZWQiLCAiYXdhaXRpbmdfY2xhcmlmaWNhdGlvbiIsICJyZXNvbHV0aW9uX3JlY29tbWVuZGVkIiwgImRlZmVycmVkIiwgImF3YWl0aW5nX2FwcHJvdmFsIl0pOwppZiAoIUFycmF5LmlzQXJyYXkoZGF0YS5pc3N1ZXMpIHx8IGRhdGEuaXNzdWVzLmxlbmd0aCA+IDEwMCkgZmFpbCgiaXNzdWVzIG11c3QgYmUgYW4gYXJyYXkgb2YgYXQgbW9zdCAxMDAgZW50cmllcyIpOwpmb3IgKGNvbnN0IFtpbmRleCwgZW50cnldIG9mIGRhdGEuaXNzdWVzLmVudHJpZXMoKSkgewogIGlmICghZXhhY3RLZXlzKGVudHJ5LCBbIm51bWJlciIsICJzdGF0ZSIsICJ1cGRhdGVkX2F0IiwgIm5vdGUiXSkpIGZhaWwoYGludmFsaWQgaXNzdWVzIGVudHJ5IGF0IGluZGV4ICR7aW5kZXh9YCk7CiAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKGVudHJ5Lm51bWJlcikgfHwgZW50cnkubnVtYmVyIDwgMSkgZmFpbChgaW52YWxpZCBpc3N1ZSBudW1iZXIgYXQgaW5kZXggJHtpbmRleH1gKTsKICBpZiAoIWlzc3VlU3RhdGVzLmhhcyhlbnRyeS5zdGF0ZSkpIGZhaWwoYGludmFsaWQgaXNzdWUgc3RhdGUgYXQgaW5kZXggJHtpbmRleH1gKTsKICBpZiAoIXZhbGlkRGF0ZShlbnRyeS51cGRhdGVkX2F0KSkgZmFpbChgaW52YWxpZCBpc3N1ZSBkYXRlIGF0IGluZGV4ICR7aW5kZXh9YCk7CiAgaWYgKCF2YWxpZFRleHQoZW50cnkubm90ZSwgMzAwKSkgZmFpbChgaW52YWxpZCBpc3N1ZSBub3RlIGF0IGluZGV4ICR7aW5kZXh9YCk7Cn0KdW5pcXVlKGRhdGEuaXNzdWVzLCBlbnRyeSA9PiBlbnRyeS5udW1iZXIsICJpc3N1ZSBudW1iZXJzIik7Cgpjb25zdCBmaXhTdGF0ZXMgPSBuZXcgU2V0KFsib3BlbiIsICJtZXJnZWQiLCAiY2xvc2VkIiwgImJsb2NrZWQiXSk7CmlmICghQXJyYXkuaXNBcnJheShkYXRhLmZpeGVzKSB8fCBkYXRhLmZpeGVzLmxlbmd0aCA+IDUwKSBmYWlsKCJmaXhlcyBtdXN0IGJlIGFuIGFycmF5IG9mIGF0IG1vc3QgNTAgZW50cmllcyIpOwpmb3IgKGNvbnN0IFtpbmRleCwgZW50cnldIG9mIGRhdGEuZml4ZXMuZW50cmllcygpKSB7CiAgaWYgKCFleGFjdEtleXMoZW50cnksIFsiaXNzdWUiLCAicHIiLCAiYnJhbmNoIiwgInN0YXR1cyIsICJ1cGRhdGVkX2F0IiwgIm5vdGUiXSkpIGZhaWwoYGludmFsaWQgZml4ZXMgZW50cnkgYXQgaW5kZXggJHtpbmRleH1gKTsKICBpZiAoIU51bWJlci5pc0ludGVnZXIoZW50cnkuaXNzdWUpIHx8IGVudHJ5Lmlzc3VlIDwgMSkgZmFpbChgaW52YWxpZCBmaXggaXNzdWUgYXQgaW5kZXggJHtpbmRleH1gKTsKICBpZiAoZW50cnkucHIgIT09IG51bGwgJiYgKCFOdW1iZXIuaXNJbnRlZ2VyKGVudHJ5LnByKSB8fCBlbnRyeS5wciA8IDEpKSBmYWlsKGBpbnZhbGlkIGZpeCBQUiBhdCBpbmRleCAke2luZGV4fWApOwogIGlmIChlbnRyeS5icmFuY2ggIT09IG51bGwgJiYgIXZhbGlkVGV4dChlbnRyeS5icmFuY2gsIDEyMCkpIGZhaWwoYGludmFsaWQgZml4IGJyYW5jaCBhdCBpbmRleCAke2luZGV4fWApOwogIGlmICghZml4U3RhdGVzLmhhcyhlbnRyeS5zdGF0dXMpKSBmYWlsKGBpbnZhbGlkIGZpeCBzdGF0dXMgYXQgaW5kZXggJHtpbmRleH1gKTsKICBpZiAoIXZhbGlkRGF0ZShlbnRyeS51cGRhdGVkX2F0KSkgZmFpbChgaW52YWxpZCBmaXggZGF0ZSBhdCBpbmRleCAke2luZGV4fWApOwogIGlmICghdmFsaWRUZXh0KGVudHJ5Lm5vdGUsIDMwMCkpIGZhaWwoYGludmFsaWQgZml4IG5vdGUgYXQgaW5kZXggJHtpbmRleH1gKTsKfQp1bmlxdWUoZGF0YS5maXhlcywgZW50cnkgPT4gZW50cnkuaXNzdWUsICJmaXggaXNzdWUgbnVtYmVycyIpOwp1bmlxdWUoZGF0YS5maXhlcy5maWx0ZXIoZW50cnkgPT4gZW50cnkucHIgIT09IG51bGwpLCBlbnRyeSA9PiBlbnRyeS5wciwgImZpeCBQUiBudW1iZXJzIik7Cgpjb25zdCBjaGVja0FyZWFzID0gbmV3IFNldChbImRlcGVuZGVuY2llcyIsICJjaSIsICJ0b29saW5nIiwgImJ1aWxkIiwgImNvZGUiLCAiZG9jcyIsICJxYSIsICJoeWdpZW5lIiwgInBlcmZvcm1hbmNlIiwgInRlc3RzIiwgInJlbGVhc2UiLCAicmVwb19hc3Npc3RfcHJzIl0pOwppZiAoIUFycmF5LmlzQXJyYXkoZGF0YS5jaGVja3MpIHx8IGRhdGEuY2hlY2tzLmxlbmd0aCA+IGNoZWNrQXJlYXMuc2l6ZSkgZmFpbCgiY2hlY2tzIG11c3QgY29udGFpbiBhdCBtb3N0IG9uZSBlbnRyeSBwZXIgYXJlYSIpOwpmb3IgKGNvbnN0IFtpbmRleCwgZW50cnldIG9mIGRhdGEuY2hlY2tzLmVudHJpZXMoKSkgewogIGlmICghZXhhY3RLZXlzKGVudHJ5LCBbImFyZWEiLCAiY2hlY2tlZF9hdCIsICJyZXN1bHQiLCAiZm9sbG93X3VwIl0pKSBmYWlsKGBpbnZhbGlkIGNoZWNrcyBlbnRyeSBhdCBpbmRleCAke2luZGV4fWApOwogIGlmICghY2hlY2tBcmVhcy5oYXMoZW50cnkuYXJlYSkpIGZhaWwoYGludmFsaWQgY2hlY2sgYXJlYSBhdCBpbmRleCAke2luZGV4fWApOwogIGlmICghdmFsaWREYXRlKGVudHJ5LmNoZWNrZWRfYXQpKSBmYWlsKGBpbnZhbGlkIGNoZWNrIGRhdGUgYXQgaW5kZXggJHtpbmRleH1gKTsKICBpZiAoIXZhbGlkVGV4dChlbnRyeS5yZXN1bHQsIDMwMCkpIGZhaWwoYGludmFsaWQgY2hlY2sgcmVzdWx0IGF0IGluZGV4ICR7aW5kZXh9YCk7CiAgaWYgKGVudHJ5LmZvbGxvd191cCAhPT0gbnVsbCAmJiAhdmFsaWRUZXh0KGVudHJ5LmZvbGxvd191cCwgMzAwKSkgZmFpbChgaW52YWxpZCBjaGVjayBmb2xsb3dfdXAgYXQgaW5kZXggJHtpbmRleH1gKTsKfQp1bmlxdWUoZGF0YS5jaGVja3MsIGVudHJ5ID0+IGVudHJ5LmFyZWEsICJjaGVjayBhcmVhcyIpOwoKaWYgKCFBcnJheS5pc0FycmF5KGRhdGEuY29tcGxldGVkX2FjdGlvbnMpIHx8IGRhdGEuY29tcGxldGVkX2FjdGlvbnMubGVuZ3RoID4gMTAwKSBmYWlsKCJjb21wbGV0ZWRfYWN0aW9ucyBtdXN0IGJlIGFuIGFycmF5IG9mIGF0IG1vc3QgMTAwIGVudHJpZXMiKTsKZm9yIChjb25zdCBbaW5kZXgsIGVudHJ5XSBvZiBkYXRhLmNvbXBsZXRlZF9hY3Rpb25zLmVudHJpZXMoKSkgewogIGlmICghZXhhY3RLZXlzKGVudHJ5LCBbImtleSIsICJjb21wbGV0ZWRfYXQiXSkpIGZhaWwoYGludmFsaWQgY29tcGxldGVkX2FjdGlvbnMgZW50cnkgYXQgaW5kZXggJHtpbmRleH1gKTsKICBpZiAoIXZhbGlkVGV4dChlbnRyeS5rZXksIDEwMCkpIGZhaWwoYGludmFsaWQgY29tcGxldGVkIGFjdGlvbiBrZXkgYXQgaW5kZXggJHtpbmRleH1gKTsKICBpZiAoIXZhbGlkRGF0ZShlbnRyeS5jb21wbGV0ZWRfYXQpKSBmYWlsKGBpbnZhbGlkIGNvbXBsZXRlZCBhY3Rpb24gZGF0ZSBhdCBpbmRleCAke2luZGV4fWApOwp9CnVuaXF1ZShkYXRhLmNvbXBsZXRlZF9hY3Rpb25zLCBlbnRyeSA9PiBlbnRyeS5rZXksICJjb21wbGV0ZWQgYWN0aW9uIGtleXMiKTsKCmlmICghQXJyYXkuaXNBcnJheShkYXRhLnByaW9yaXRpZXMpIHx8IGRhdGEucHJpb3JpdGllcy5sZW5ndGggPiAyMCkgZmFpbCgicHJpb3JpdGllcyBtdXN0IGJlIGFuIGFycmF5IG9mIGF0IG1vc3QgMjAgZW50cmllcyIpOwpmb3IgKGNvbnN0IFtpbmRleCwgZW50cnldIG9mIGRhdGEucHJpb3JpdGllcy5lbnRyaWVzKCkpIHsKICBpZiAoIWV4YWN0S2V5cyhlbnRyeSwgWyJ0YXNrIiwgIml0ZW0iLCAibm90ZSJdKSkgZmFpbChgaW52YWxpZCBwcmlvcml0aWVzIGVudHJ5IGF0IGluZGV4ICR7aW5kZXh9YCk7CiAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKGVudHJ5LnRhc2spIHx8IGVudHJ5LnRhc2sgPCAxIHx8IGVudHJ5LnRhc2sgPiAxMCkgZmFpbChgaW52YWxpZCBwcmlvcml0eSB0YXNrIGF0IGluZGV4ICR7aW5kZXh9YCk7CiAgaWYgKCF2YWxpZFRleHQoZW50cnkuaXRlbSwgMTAwKSkgZmFpbChgaW52YWxpZCBwcmlvcml0eSBpdGVtIGF0IGluZGV4ICR7aW5kZXh9YCk7CiAgaWYgKCF2YWxpZFRleHQoZW50cnkubm90ZSwgMzAwKSkgZmFpbChgaW52YWxpZCBwcmlvcml0eSBub3RlIGF0IGluZGV4ICR7aW5kZXh9YCk7Cn0KdW5pcXVlKGRhdGEucHJpb3JpdGllcywgZW50cnkgPT4gYCR7ZW50cnkudGFza306JHtlbnRyeS5pdGVtfWAsICJwcmlvcml0eSB0YXNrL2l0ZW0gcGFpcnMiKTsKY29uc29sZS5sb2coInJlcG8tYXNzaXN0IG5vdGVzLmpzb24gY29uZm9ybXMgdG8gc2NoZW1hIik7Cg== + VALIDATION_TIMEOUT_SECONDS: 60 with: script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/push_repo_memory.cjs'); + const { main } = require(path.join(actionsDir, 'push_repo_memory.cjs')); await main(); safe_outputs: @@ -2195,8 +2427,8 @@ jobs: GH_AW_THREAT_DETECTION_AIC: ${{ needs.detection.outputs.aic }} GH_AW_WORKFLOW_ID: "repo-assist" GH_AW_WORKFLOW_NAME: "Repo Assist" - GH_AW_WORKFLOW_SOURCE: "githubnext/agentics/workflows/repo-assist.md@ae8d551f07c7ed7619f8c58c7bb4c3ac89395d38" - GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/githubnext/agentics/blob/ae8d551f07c7ed7619f8c58c7bb4c3ac89395d38/workflows/repo-assist.md" + GH_AW_WORKFLOW_SOURCE: "githubnext/agentics/workflows/repo-assist.md@4bc8419fad05e6b032741cbfd189986700bcf71c" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/githubnext/agentics/blob/4bc8419fad05e6b032741cbfd189986700bcf71c/workflows/repo-assist.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 }} @@ -2223,7 +2455,7 @@ jobs: steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2 + uses: github/gh-aw-actions/setup@5e508589e03a7757a7e05b26e834292f5445bfb6 # v0.88.7 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} @@ -2232,16 +2464,19 @@ jobs: env: GH_AW_SETUP_WORKFLOW_NAME: "Repo Assist" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/repo-assist.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "1.0.79" - GH_AW_INFO_AWF_VERSION: "v0.27.44" + GH_AW_INFO_VERSION: "1.0.80" + GH_AW_INFO_AWF_VERSION: "v0.28.14" GH_AW_INFO_BODY_MODIFIED: "false" GH_AW_INFO_ENGINE_ID: "copilot" + - name: Mask OTLP telemetry headers + run: bash "${RUNNER_TEMP}/gh-aw/actions/mask_otlp_headers.sh" - name: Download agent output artifact id: download-agent-output continue-on-error: true uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: - name: agent + pattern: "{agent,agent-output-fallback}" + merge-multiple: true path: /tmp/gh-aw/ - name: Setup agent output environment variable id: setup-agent-output-env @@ -2249,7 +2484,9 @@ jobs: run: | mkdir -p /tmp/gh-aw/ find "/tmp/gh-aw/" -type f -print - echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT" + if [ -f "/tmp/gh-aw/agent_output.json" ]; then + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT" + fi - name: Download patch artifact continue-on-error: true uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 @@ -2292,17 +2529,19 @@ jobs: env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} GH_AW_COMMENT_ID: ${{ needs.activation.outputs.comment_id }} - GH_AW_ALLOWED_DOMAINS: "*.gradle-enterprise.cloud,*.pythonhosted.org,*.vsblob.vsassets.io,adoptium.net,anaconda.org,api.adoptium.net,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.foojay.io,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.nuget.org,api.snapcraft.io,archive.apache.org,archive.ubuntu.com,azure.archive.ubuntu.com,azuresearch-usnc.nuget.org,azuresearch-ussc.nuget.org,binstar.org,bootstrap.pypa.io,builds.dotnet.microsoft.com,bun.sh,cdn.azul.com,cdn.jsdelivr.net,central.sonatype.com,ci.dot.net,conda.anaconda.org,conda.binstar.org,crates.io,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,dc.services.visualstudio.com,deb.nodesource.com,deno.land,develocity.apache.org,dist.nuget.org,dl.google.com,dlcdn.apache.org,dot.net,dotnet.microsoft.com,dotnetcli.blob.core.windows.net,download.eclipse.org,download.java.net,download.oracle.com,downloads.gradle-dn.com,esm.sh,files.pythonhosted.org,ge.spockframework.org,get.pnpm.io,github.com,googleapis.deno.dev,googlechromelabs.github.io,gradle.org,host.docker.internal,index.crates.io,jcenter.bintray.com,jdk.java.net,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,maven-central.storage-download.googleapis.com,maven.apache.org,maven.google.com,maven.oracle.com,maven.pkg.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,nuget.org,nuget.pkg.github.com,nugetregistryv2prod.blob.core.windows.net,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,oneocsp.microsoft.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,pip.pypa.io,pkgs.dev.azure.com,plugins-artifacts.gradle.org,plugins.gradle.org,ppa.launchpad.net,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.gradle.org,repo.grails.org,repo.maven.apache.org,repo.spring.io,repo.yarnpkg.com,repo1.maven.org,repository.apache.org,s.symcb.com,s.symcd.com,scans-in.gradle.com,security.ubuntu.com,services.gradle.org,sh.rustup.rs,skimdb.npmjs.com,static.crates.io,static.rust-lang.org,storage.googleapis.com,telemetry.enterprise.githubcopilot.com,telemetry.vercel.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com,www.java.com,www.microsoft.com,www.npmjs.com,www.npmjs.org,yarnpkg.com" + GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,*.gradle-enterprise.cloud,*.pythonhosted.org,*.vsblob.vsassets.io,adoptium.net,anaconda.org,api.adoptium.net,api.foojay.io,api.npms.io,api.nuget.org,api.snapcraft.io,archive.apache.org,archive.ubuntu.com,azure.archive.ubuntu.com,azuresearch-usnc.nuget.org,azuresearch-ussc.nuget.org,binstar.org,bootstrap.pypa.io,builds.dotnet.microsoft.com,bun.sh,cdn.azul.com,cdn.jsdelivr.net,central.sonatype.com,ci.dot.net,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,dc.services.visualstudio.com,deb.nodesource.com,deno.land,develocity.apache.org,dist.nuget.org,dl.google.com,dlcdn.apache.org,docs.github.com,dot.net,dotnet.microsoft.com,dotnetcli.blob.core.windows.net,download.eclipse.org,download.java.net,download.oracle.com,downloads.gradle-dn.com,esm.sh,files.pythonhosted.org,ge.spockframework.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.blog,github.com,github.githubassets.com,googleapis.deno.dev,googlechromelabs.github.io,gradle.org,index.crates.io,jcenter.bintray.com,jdk.java.net,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,maven-central.storage-download.googleapis.com,maven.apache.org,maven.google.com,maven.oracle.com,maven.pkg.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,nuget.org,nuget.pkg.github.com,nugetregistryv2prod.blob.core.windows.net,objects.githubusercontent.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,oneocsp.microsoft.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,patch-diff.githubusercontent.com,patchdiff.githubusercontent.com,pip.pypa.io,pkgs.dev.azure.com,plugins-artifacts.gradle.org,plugins.gradle.org,ppa.launchpad.net,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.gradle.org,repo.grails.org,repo.maven.apache.org,repo.spring.io,repo.yarnpkg.com,repo1.maven.org,repository.apache.org,s.symcb.com,s.symcd.com,scans-in.gradle.com,security.ubuntu.com,services.gradle.org,sh.rustup.rs,skimdb.npmjs.com,static.crates.io,static.rust-lang.org,storage.googleapis.com,telemetry.vercel.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com,www.java.com,www.microsoft.com,www.npmjs.com,www.npmjs.org,yarnpkg.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"hide_older_comments\":true,\"max\":10,\"target\":\"*\"},\"add_labels\":{\"allowed\":[\"bug\",\"enhancement\",\"help wanted\",\"good first issue\",\"spam\",\"off topic\",\"documentation\",\"question\",\"duplicate\",\"wontfix\",\"needs triage\",\"needs investigation\",\"breaking change\",\"performance\",\"security\",\"refactor\"],\"max\":30,\"target\":\"*\"},\"create_issue\":{\"labels\":[\"automation\",\"repo-assist\"],\"max\":4,\"title_prefix\":\"[repo-assist] \"},\"create_pull_request\":{\"draft\":true,\"labels\":[\"automation\",\"repo-assist\"],\"max\":4,\"max_patch_files\":100,\"max_patch_size\":4096,\"protect_top_level_dot_folders\":true,\"protected_files\":[\"package.json\",\"bun.lockb\",\"bunfig.toml\",\"deno.json\",\"deno.jsonc\",\"deno.lock\",\"global.json\",\"NuGet.Config\",\"Directory.Packages.props\",\"mix.exs\",\"mix.lock\",\"go.mod\",\"go.sum\",\"stack.yaml\",\"stack.yaml.lock\",\"pom.xml\",\"build.gradle\",\"build.gradle.kts\",\"settings.gradle\",\"settings.gradle.kts\",\"gradle.properties\",\"package-lock.json\",\"yarn.lock\",\"pnpm-lock.yaml\",\"npm-shrinkwrap.json\",\"requirements.txt\",\"Pipfile\",\"Pipfile.lock\",\"pyproject.toml\",\"setup.py\",\"setup.cfg\",\"Gemfile\",\"Gemfile.lock\",\"uv.lock\",\"CODEOWNERS\",\"DESIGN.md\",\"README.md\",\"CONTRIBUTING.md\",\"CHANGELOG.md\",\"SECURITY.md\",\"CODE_OF_CONDUCT.md\",\"AGENTS.md\"],\"protected_files_policy\":\"fallback-to-issue\",\"title_prefix\":\"[repo-assist] \"},\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"false\"},\"push_to_pull_request_branch\":{\"if_no_changes\":\"warn\",\"max\":4,\"max_patch_size\":4096,\"protect_top_level_dot_folders\":true,\"protected_files\":[\"package.json\",\"bun.lockb\",\"bunfig.toml\",\"deno.json\",\"deno.jsonc\",\"deno.lock\",\"global.json\",\"NuGet.Config\",\"Directory.Packages.props\",\"mix.exs\",\"mix.lock\",\"go.mod\",\"go.sum\",\"stack.yaml\",\"stack.yaml.lock\",\"pom.xml\",\"build.gradle\",\"build.gradle.kts\",\"settings.gradle\",\"settings.gradle.kts\",\"gradle.properties\",\"package-lock.json\",\"yarn.lock\",\"pnpm-lock.yaml\",\"npm-shrinkwrap.json\",\"requirements.txt\",\"Pipfile\",\"Pipfile.lock\",\"pyproject.toml\",\"setup.py\",\"setup.cfg\",\"Gemfile\",\"Gemfile.lock\",\"uv.lock\",\"CODEOWNERS\",\"DESIGN.md\",\"README.md\",\"CONTRIBUTING.md\",\"CHANGELOG.md\",\"SECURITY.md\",\"CODE_OF_CONDUCT.md\",\"AGENTS.md\"],\"protected_files_policy\":\"fallback-to-issue\",\"target\":\"*\",\"title_prefix\":\"[repo-assist] \"},\"remove_labels\":{\"allowed\":[\"bug\",\"enhancement\",\"help wanted\",\"good first issue\",\"spam\",\"off topic\",\"documentation\",\"question\",\"duplicate\",\"wontfix\",\"needs triage\",\"needs investigation\",\"breaking change\",\"performance\",\"security\",\"refactor\"],\"max\":5,\"target\":\"*\"},\"report_incomplete\":{},\"update_issue\":{\"allow_body\":true,\"max\":1,\"required_title_prefix\":\"[repo-assist] \",\"target\":\"*\"}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"hide_older_comments\":true,\"max\":10,\"target\":\"*\"},\"add_labels\":{\"allowed\":[\"bug\",\"enhancement\",\"help wanted\",\"good first issue\",\"spam\",\"off topic\",\"documentation\",\"question\",\"duplicate\",\"wontfix\",\"needs triage\",\"needs investigation\",\"breaking change\",\"performance\",\"security\",\"refactor\"],\"max\":30,\"target\":\"*\"},\"create_issue\":{\"labels\":[\"automation\",\"repo-assist\"],\"max\":4,\"title_prefix\":\"[repo-assist] \"},\"create_pull_request\":{\"draft\":true,\"labels\":[\"automation\",\"repo-assist\"],\"max\":4,\"max_patch_files\":100,\"max_patch_size\":4096,\"protect_top_level_dot_folders\":true,\"protected_files\":[\"package.json\",\"bun.lockb\",\"bunfig.toml\",\"deno.json\",\"deno.jsonc\",\"deno.lock\",\"global.json\",\"NuGet.Config\",\"Directory.Packages.props\",\"mix.exs\",\"mix.lock\",\"go.mod\",\"go.sum\",\"stack.yaml\",\"stack.yaml.lock\",\"pom.xml\",\"build.gradle\",\"build.gradle.kts\",\"settings.gradle\",\"settings.gradle.kts\",\"gradle.properties\",\"package-lock.json\",\"yarn.lock\",\"pnpm-lock.yaml\",\"npm-shrinkwrap.json\",\"requirements.txt\",\"Pipfile\",\"Pipfile.lock\",\"pyproject.toml\",\"setup.py\",\"setup.cfg\",\"Gemfile\",\"Gemfile.lock\",\"uv.lock\",\"CODEOWNERS\",\"DESIGN.md\",\"CONTRIBUTING.md\",\"SECURITY.md\",\"CODE_OF_CONDUCT.md\",\"AGENTS.md\"],\"protected_files_policy\":\"request_review\",\"title_prefix\":\"[repo-assist] \"},\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"false\"},\"push_to_pull_request_branch\":{\"if_no_changes\":\"warn\",\"max\":4,\"max_patch_size\":4096,\"protect_top_level_dot_folders\":true,\"protected_files\":[\"package.json\",\"bun.lockb\",\"bunfig.toml\",\"deno.json\",\"deno.jsonc\",\"deno.lock\",\"global.json\",\"NuGet.Config\",\"Directory.Packages.props\",\"mix.exs\",\"mix.lock\",\"go.mod\",\"go.sum\",\"stack.yaml\",\"stack.yaml.lock\",\"pom.xml\",\"build.gradle\",\"build.gradle.kts\",\"settings.gradle\",\"settings.gradle.kts\",\"gradle.properties\",\"package-lock.json\",\"yarn.lock\",\"pnpm-lock.yaml\",\"npm-shrinkwrap.json\",\"requirements.txt\",\"Pipfile\",\"Pipfile.lock\",\"pyproject.toml\",\"setup.py\",\"setup.cfg\",\"Gemfile\",\"Gemfile.lock\",\"uv.lock\",\"CODEOWNERS\",\"DESIGN.md\",\"CONTRIBUTING.md\",\"SECURITY.md\",\"CODE_OF_CONDUCT.md\",\"AGENTS.md\"],\"protected_files_policy\":\"allowed\",\"target\":\"*\",\"title_prefix\":\"[repo-assist] \"},\"remove_labels\":{\"allowed\":[\"bug\",\"enhancement\",\"help wanted\",\"good first issue\",\"spam\",\"off topic\",\"documentation\",\"question\",\"duplicate\",\"wontfix\",\"needs triage\",\"needs investigation\",\"breaking change\",\"performance\",\"security\",\"refactor\"],\"max\":5,\"target\":\"*\"},\"report_incomplete\":{},\"update_issue\":{\"allow_body\":true,\"max\":1,\"required_title_prefix\":\"[repo-assist] \",\"target\":\"*\"}}" GH_AW_CI_TRIGGER_TOKEN: ${{ secrets.GH_AW_CI_TRIGGER_TOKEN }} with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/process_safe_outputs.cjs'); + const { main } = require(path.join(actionsDir, 'process_safe_outputs.cjs')); await main(); - name: Upload Safe Outputs Items if: always() @@ -2312,4 +2551,5 @@ jobs: path: | /tmp/gh-aw/safe-output-items.jsonl /tmp/gh-aw/temporary-id-map.json + /tmp/gh-aw/safe-output-errors.json if-no-files-found: ignore diff --git a/.github/workflows/repo-assist.md b/.github/workflows/repo-assist.md index 445565b..b91f222 100644 --- a/.github/workflows/repo-assist.md +++ b/.github/workflows/repo-assist.md @@ -3,12 +3,12 @@ description: | A friendly repository assistant that runs regularly (twice a day by default) to assist maintainers. Can also be triggered on-demand via '/repo-assist ' to perform specific tasks. - Labels and triages open issues - - Comments helpfully on open issues to unblock contributors and onboard newcomers + - Investigates open issues and resolves, fixes, clarifies, or comments on them - Identifies issues that can be fixed and creates draft pull requests with fixes - Improves performance, testing, and code quality via PRs - Makes engineering investments: dependency updates, CI improvements, tooling - Updates its own PRs when CI fails or merge conflicts arise - - Nudges stale PRs waiting for author response + - Improves documentation, performs ad hoc QA, and maintains project basics - Takes the repository forward with proactive improvements - Maintains a persistent memory of work done and what remains Always polite, constructive, and mindful of the project's goals. @@ -38,6 +38,9 @@ on: [[ "$COUNT" -lt "$MAX_OPEN_PRS" ]] # exits 0 if not scheduled or { throw new Error(`notes.json: ${message}`); }; + const notesPath = path.join(memoryRoot, "notes.json"); + if (!fs.existsSync(notesPath)) fail("missing (create an initial notes.json that matches schema version 1)"); + const data = JSON.parse(fs.readFileSync(notesPath, "utf8")); + const isObject = value => value !== null && typeof value === "object" && !Array.isArray(value); + const exactKeys = (value, keys) => isObject(value) && Object.keys(value).sort().join(",") === [...keys].sort().join(","); + const validDate = value => typeof value === "string" && /^[0-9]{4}-[0-9]{2}-[0-9]{2}$/.test(value); + const validText = (value, maximum) => typeof value === "string" && value.length > 0 && value.length <= maximum; + const unique = (entries, key, label) => { + const values = entries.map(key); + if (new Set(values).size !== values.length) fail(`${label} must be unique`); + }; + + if (!exactKeys(data, ["version", "cursors", "issues", "fixes", "checks", "completed_actions", "priorities"])) fail("must contain exactly version, cursors, issues, fixes, checks, completed_actions, and priorities"); + if (data.version !== 1) fail("version must be 1"); + if (!exactKeys(data.cursors, ["labelling_after", "investigation_after"])) fail("cursors must contain exactly labelling_after and investigation_after"); + for (const [name, value] of Object.entries(data.cursors)) { + if (value !== null && (!Number.isInteger(value) || value < 1)) fail(`${name} must be null or a positive issue number`); + } + + const issueStates = new Set(["commented", "awaiting_clarification", "resolution_recommended", "deferred", "awaiting_approval"]); + if (!Array.isArray(data.issues) || data.issues.length > 100) fail("issues must be an array of at most 100 entries"); + for (const [index, entry] of data.issues.entries()) { + if (!exactKeys(entry, ["number", "state", "updated_at", "note"])) fail(`invalid issues entry at index ${index}`); + if (!Number.isInteger(entry.number) || entry.number < 1) fail(`invalid issue number at index ${index}`); + if (!issueStates.has(entry.state)) fail(`invalid issue state at index ${index}`); + if (!validDate(entry.updated_at)) fail(`invalid issue date at index ${index}`); + if (!validText(entry.note, 300)) fail(`invalid issue note at index ${index}`); + } + unique(data.issues, entry => entry.number, "issue numbers"); + + const fixStates = new Set(["open", "merged", "closed", "blocked"]); + if (!Array.isArray(data.fixes) || data.fixes.length > 50) fail("fixes must be an array of at most 50 entries"); + for (const [index, entry] of data.fixes.entries()) { + if (!exactKeys(entry, ["issue", "pr", "branch", "status", "updated_at", "note"])) fail(`invalid fixes entry at index ${index}`); + if (!Number.isInteger(entry.issue) || entry.issue < 1) fail(`invalid fix issue at index ${index}`); + if (entry.pr !== null && (!Number.isInteger(entry.pr) || entry.pr < 1)) fail(`invalid fix PR at index ${index}`); + if (entry.branch !== null && !validText(entry.branch, 120)) fail(`invalid fix branch at index ${index}`); + if (!fixStates.has(entry.status)) fail(`invalid fix status at index ${index}`); + if (!validDate(entry.updated_at)) fail(`invalid fix date at index ${index}`); + if (!validText(entry.note, 300)) fail(`invalid fix note at index ${index}`); + } + unique(data.fixes, entry => entry.issue, "fix issue numbers"); + unique(data.fixes.filter(entry => entry.pr !== null), entry => entry.pr, "fix PR numbers"); + + const checkAreas = new Set(["dependencies", "ci", "tooling", "build", "code", "docs", "qa", "hygiene", "performance", "tests", "release", "repo_assist_prs"]); + if (!Array.isArray(data.checks) || data.checks.length > checkAreas.size) fail("checks must contain at most one entry per area"); + for (const [index, entry] of data.checks.entries()) { + if (!exactKeys(entry, ["area", "checked_at", "result", "follow_up"])) fail(`invalid checks entry at index ${index}`); + if (!checkAreas.has(entry.area)) fail(`invalid check area at index ${index}`); + if (!validDate(entry.checked_at)) fail(`invalid check date at index ${index}`); + if (!validText(entry.result, 300)) fail(`invalid check result at index ${index}`); + if (entry.follow_up !== null && !validText(entry.follow_up, 300)) fail(`invalid check follow_up at index ${index}`); + } + unique(data.checks, entry => entry.area, "check areas"); + + if (!Array.isArray(data.completed_actions) || data.completed_actions.length > 100) fail("completed_actions must be an array of at most 100 entries"); + for (const [index, entry] of data.completed_actions.entries()) { + if (!exactKeys(entry, ["key", "completed_at"])) fail(`invalid completed_actions entry at index ${index}`); + if (!validText(entry.key, 100)) fail(`invalid completed action key at index ${index}`); + if (!validDate(entry.completed_at)) fail(`invalid completed action date at index ${index}`); + } + unique(data.completed_actions, entry => entry.key, "completed action keys"); + + if (!Array.isArray(data.priorities) || data.priorities.length > 20) fail("priorities must be an array of at most 20 entries"); + for (const [index, entry] of data.priorities.entries()) { + if (!exactKeys(entry, ["task", "item", "note"])) fail(`invalid priorities entry at index ${index}`); + if (!Number.isInteger(entry.task) || entry.task < 1 || entry.task > 10) fail(`invalid priority task at index ${index}`); + if (!validText(entry.item, 100)) fail(`invalid priority item at index ${index}`); + if (!validText(entry.note, 300)) fail(`invalid priority note at index ${index}`); + } + unique(data.priorities, entry => `${entry.task}:${entry.item}`, "priority task/item pairs"); + console.log("repo-assist notes.json conforms to schema"); safe-outputs: messages: @@ -79,13 +166,21 @@ safe-outputs: draft: true title-prefix: "[repo-assist] " labels: [automation, repo-assist] - protected-files: fallback-to-issue + protected-files: + policy: request_review + exclude: + - CHANGELOG.md + - README.md max: 4 push-to-pull-request-branch: target: "*" required-title-prefix: "[repo-assist] " max: 4 - protected-files: fallback-to-issue + protected-files: + policy: allowed + exclude: + - CHANGELOG.md + - README.md create-issue: title-prefix: "[repo-assist] " labels: [automation, repo-assist] @@ -128,16 +223,15 @@ steps: open_issues = len(issues) unlabelled = sum(1 for i in issues if not i.get('labels')) repo_assist_prs = sum(1 for p in prs if p['title'].startswith('[repo-assist]')) - other_prs = sum(1 for p in prs if not p['title'].startswith('[repo-assist]')) task_names = { 1: 'Issue Labelling', - 2: 'Issue Investigation and Comment', + 2: 'Issue Investigation then Resolve, Fix, Seek Clarification or Comment', 3: 'Issue Investigation and Fix', 4: 'Engineering Investments', 5: 'Coding Improvements', 6: 'Maintain Repo Assist PRs', - 7: 'Stale PR Nudges', + 7: 'Documentation Improvements, Ad Hoc QA, and Project Basics', 8: 'Performance Improvements', 9: 'Testing Improvements', 10: 'Take the Repository Forward', @@ -150,7 +244,7 @@ steps: 4: 5 + 0.2 * open_issues, 5: 5 + 0.1 * open_issues, 6: float(repo_assist_prs), - 7: 0.1 * other_prs, + 7: 3 + 0.05 * open_issues, 8: 3 + 0.05 * open_issues, 9: 3 + 0.05 * open_issues, 10: 3 + 0.05 * open_issues, @@ -177,7 +271,6 @@ steps: print(f'Open issues : {open_issues}') print(f'Unlabelled issues : {unlabelled}') print(f'Repo Assist PRs : {repo_assist_prs}') - print(f'Other open PRs : {other_prs}') print() print('Task weights:') for t, w in weights.items(): @@ -188,7 +281,7 @@ steps: result = { 'open_issues': open_issues, 'unlabelled_issues': unlabelled, - 'repo_assist_prs': repo_assist_prs, 'other_prs': other_prs, + 'repo_assist_prs': repo_assist_prs, 'task_names': task_names, 'weights': {str(k): round(v, 2) for k, v in weights.items()}, 'selected_tasks': chosen, @@ -197,7 +290,7 @@ steps: json.dump(result, f, indent=2) EOF -source: githubnext/agentics/workflows/repo-assist.md@ae8d551f07c7ed7619f8c58c7bb4c3ac89395d38 +source: githubnext/agentics/workflows/repo-assist.md@4bc8419fad05e6b032741cbfd189986700bcf71c --- # Repo Assist @@ -212,7 +305,7 @@ Then exit - do not run the normal workflow after completing the instructions. ## Non-Command Mode -You are Repo Assist for `${{ github.repository }}`. Your job is to support human contributors, help onboard newcomers, identify improvements, and fix bugs by creating pull requests. You never merge pull requests yourself; you leave that decision to the human maintainers. +You are Repo Assist for `${{ github.repository }}`. Your job is to make forward progress by investigating and clarifying issues, resolving issues where possible, identifying improvements, and fixing bugs and feature requests by creating pull requests. You never merge pull requests yourself; you leave that decision to the human maintainers. Always be: @@ -224,34 +317,38 @@ Always be: ## Memory -Use persistent repo memory to track: +Repo memory contains exactly one schema-validated file, `notes.json`. Read it at the **start** of every run, using `jq` to select only the fields needed for the selected tasks. Update it at the **end** whenever state changed. + +The schema stores only: -- issues already commented on (with timestamps to detect new human activity) -- fix attempts and outcomes, improvement ideas already submitted, a short to-do list -- a **backlog cursor** so each run continues where the previous one left off -- previously checked off items (checked off by maintainer) in the Monthly Activity Summary to maintain an accurate pending actions list for maintainers +- `cursors`: the last issue reached by Tasks 1 and 2, or `null` when a fresh search is required +- `issues`: the latest still-actionable Repo Assist interaction or investigation state for an issue +- `fixes`: one record per attempted issue fix, including its PR or branch when known +- `checks`: only the latest result for each engineering, documentation, QA, testing, release, or maintenance area +- `completed_actions`: Monthly Activity actions checked off by a maintainer, so they are not proposed again +- `priorities`: a short queue of concrete follow-up work -Read memory at the **start** of every run; update it at the **end**. +Keep notes terse and current. Replace superseded entries, remove resolved issue records and closed fix records once they are no longer needed for duplicate prevention, and never store run-by-run narration, exhaustive label histories, stale PR inventories, copied GitHub content, or facts that can be cheaply queried again. Stay within the schema's array and text limits; do not create another memory file. **Important**: Memory may not be 100% accurate. Issues may have been created, closed, or commented on; PRs may have been created, merged, commented on, or closed since the last run. Always verify memory against current repository state β€” reviewing recent activity since your last run is wise before acting on stale assumptions. -**Memory backlog tracking**: Your memory may contain notes about issues or PRs that still need attention (e.g., "issues #384, #336 have labels but no comments"). These are **action items for you**, not just informational notes. Each run, check your memory's `notes` field and other tracking fields for any explicitly flagged backlog work, and prioritise acting on it. +**Memory backlog tracking**: Records in `issues`, `fixes`, and `priorities` are **action items for you**, not just informational notes. Each run, prioritise applicable work from those fields and remove or replace entries as their state changes. ## Workflow -Each run, the deterministic pre-step collects live repo data (open issue count, unlabelled issue count, open Repo Assist PRs, other open PRs), computes a **weighted probability** for each task, and selects **three tasks** for this run using a seeded random draw. The weights and selected tasks are printed in the workflow logs. You will find the selection in `/tmp/gh-aw/task_selection.json`. +Each run, the deterministic pre-step collects live repo data (open issue count, unlabelled issue count, and open Repo Assist PRs), computes a **weighted probability** for each task, and selects **three tasks** for this run using a seeded random draw. The weights and selected tasks are printed in the workflow logs. You will find the selection in `/tmp/gh-aw/task_selection.json`. **Read the task selection**: at the start of your run, read `/tmp/gh-aw/task_selection.json` and confirm the three selected tasks in your opening reasoning. Execute **those three tasks** (plus the mandatory Task 11). If a selected task is not applicable to the current repo state, substitute its fallback task rather than doing nothing. Record the substitution in the Task 11 run history entry. | Selected task | Not applicable when… | Fallback | |---|---|---| | Task 1 (Issue Labelling) | All open issues already labelled | Task 2 | -| Task 2 (Issue Comment) | All open issues already have a recent Repo Assist comment and no new human activity | Task 1 | +| Task 2 (Issue Investigation then Resolve, Fix, Seek Clarification or Comment) | All open issues are resolved, have an active fix, or have a recent Repo Assist response with no new human activity | Task 1 | | Task 3 (Issue Fix) | No issues labelled `bug`, `help wanted`, or `good first issue` that are fixable | Task 2 | | Task 4 (Engineering Investments) | No actionable dependency updates, CI gaps, or build improvements identifiable | Task 5 | | Task 5 (Coding Improvements) | No clearly beneficial, low-risk improvements identifiable after reviewing the codebase | Task 9 | | Task 6 (Maintain Repo Assist PRs) | No open Repo Assist PRs exist | Task 2 | -| Task 7 (Stale PR Nudges) | No non-Repo-Assist PRs stale 14+ days, or all already nudged | Task 2 | +| Task 7 (Documentation Improvements, Ad Hoc QA, and Project Basics) | No useful documentation, QA, or basic maintenance improvement is identifiable | Task 5 | | Task 8 (Performance Improvements) | No measurable performance opportunities identifiable | Task 9 | | Task 9 (Testing Improvements) | Test coverage is already comprehensive and no gaps identified | Task 5 | | Task 10 (Take Repo Forward) | In-progress work from memory is blocked or complete; no valuable next step | Task 2 | @@ -259,14 +356,14 @@ Each run, the deterministic pre-step collects live repo data (open issue count, The weighting scheme naturally adapts to repo state: - When unlabelled issues pile up, Task 1 (labelling) dominates. -- When there are many open issues, Tasks 2 and 3 (commenting and fixing) get more weight. -- As the backlog clears, Tasks 4–10 (engineering, improvements, nudges, forward progress) draw more evenly. +- When there are many open issues, Tasks 2 and 3 (investigating, resolving, and fixing) get more weight. +- As the backlog clears, Tasks 4–10 (engineering, documentation, QA, improvements, and forward progress) draw more evenly. **Repeat-run mode**: When invoked via `gh aw run repo-assist --repeat`, runs occur every 5–10 minutes. Each run is independent β€” do not skip a run. Always check memory to avoid duplicate work across runs. **Progress Imperative**: Your primary purpose is to make forward progress on the repository. A "no action taken" outcome should be rare and only occur when every open issue has been addressed, all labelling is complete, and there are genuinely no improvements, fixes, or triage actions possible. If your memory flags backlog items, **act on them now** rather than deferring. -Always do Task 11 (Update Monthly Activity Summary Issue) every run. In all comments and PR descriptions, identify yourself as "Repo Assist". When engaging with first-time contributors, welcome them warmly and point them to README and CONTRIBUTING β€” this is good default behaviour regardless of which tasks are selected. +Always do Task 11 (Update Monthly Activity Summary Issue) after performing work in non-command mode, including when manually dispatched without a command. Command-mode and no-op runs do not update the issue. In all comments and PR descriptions, identify yourself as "Repo Assist". ### Task 1: Issue Labelling @@ -276,13 +373,18 @@ For each item, apply the best-fitting labels from: `bug`, `enhancement`, `help w Update memory with labels applied and cursor position. -### Task 2: Issue Investigation and Comment +### Task 2: Issue Investigation then Resolve, Fix, Seek Clarification or Comment 1. List open issues sorted by creation date ascending (oldest first). Resume from your memory's backlog cursor; reset when you reach the end. -2. **Prioritise issues that have never received a Repo Assist comment.** Read the issue comments and check memory's `comments_made` field. Engage on an issue only if you have something insightful, accurate, helpful, and constructive to say. Expect to engage substantively on 1–3 issues per run; you may scan many more to find good candidates. Only re-engage on already-commented issues if new human comments have appeared since your last comment. -3. Respond based on type: bugs β†’ investigate the code and suggest a root cause or workaround; feature requests β†’ discuss feasibility and implementation approach; questions β†’ answer concisely with references to relevant code; onboarding β†’ point to README/CONTRIBUTING. Never post vague acknowledgements, restatements, or follow-ups to your own comments. +2. **Prioritise issues that have never received substantive Repo Assist action.** Read the issue and its comments, inspect the relevant code and tests, and check memory's `issues` and `fixes` records. Expect to act substantively on 1–3 issues per run; you may scan many more to find good candidates. Only re-engage on an already-addressed issue if new human comments or repository changes warrant further action. +3. After investigation, choose the outcome that makes the most forward progress: + a. **Resolve**: if the issue is already fixed, answered, a duplicate, unsupported, or no longer applicable, provide the evidence and recommend or apply the appropriate resolution and labels. + b. **Fix**: for a fixable bug or feature request, implement it and create a tested draft PR. Follow Task 3's requirements for duplicate checks, branching, focused changes, tests, AI disclosure, issue linking, and memory updates. + c. **Seek clarification**: when essential reproduction details, expected behaviour, scope, or design decisions are missing, ask only the specific questions needed to unblock investigation or implementation. + d. **Comment**: otherwise, provide a concrete root-cause analysis, verified workaround, feasibility assessment, implementation approach, or concise answer with references to relevant code. + Bugs should be investigated in code, but do not stop at suggesting a root cause or workaround when a confident fix is feasible. Treat implementable feature requests the same way. Never post vague acknowledgements, restatements, generic contributor guidance, or follow-ups to your own comments. 4. Begin every comment with: `πŸ€– *This is an automated response from Repo Assist.*` -5. Update memory with comments made and the new cursor position. +5. Update memory with resolutions, clarification requests, comments, fix attempts, and the new cursor position. ### Task 3: Issue Investigation and Fix @@ -325,11 +427,13 @@ Check memory for already-submitted ideas; do not re-propose them. Create a fresh 3. Do not push updates for infrastructure-only failures β€” comment instead. 4. Update memory. -### Task 7: Stale PR Nudges +### Task 7: Documentation Improvements, Ad Hoc QA, and Project Basics + +Improve the repository's documentation, manually exercise important workflows, and address small project-maintenance gaps. Prioritise work that prevents user confusion or catches real regressions. + +Good candidates: stale or inaccurate documentation, broken links and examples, mismatches between CLI behaviour and docs, missing guidance for common workflows, focused ad hoc QA of commands or release artifacts, and basic repository hygiene. Verify claims against the current code and observed behaviour; do not make speculative documentation changes or duplicate Task 9's automated test-coverage work. -1. List open non-Repo-Assist PRs not updated in 14+ days. -2. For each (check memory β€” skip if already nudged): if the PR is waiting on the author, post a single polite comment asking if they need help or want to hand off. Do not comment if the PR is waiting on a maintainer. -3. **Maximum 3 nudges per run.** Update memory. +Check memory for work already attempted. For a worthwhile change, create a fresh branch `repo-assist/basics-` off the default branch, make a small focused improvement, run the relevant documentation checks, builds, commands, or tests, and create a draft PR with AI disclosure, rationale, and a Test Status section. Record checks, findings, changes, and follow-up work in memory. ### Task 8: Performance Improvements diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 65c1d5e..57f2944 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -2,6 +2,8 @@ * Test coverage: Added tests for previously-untested public API functions `AsyncSeq.tryFirst`, `AsyncSeq.firstOrDefault`, `AsyncSeq.zipWithParallel`, `AsyncSeq.combineLatestWithAsync`, and `AsyncSeq.toObservable`. No functional changes. * Fixed Fable CI build: `Microsoft.Bcl.AsyncInterfaces` was pinned to a specific version (`10.0.7`) that was older than the version resolved transitively via `System.Threading.Channels`, causing a `NU1605` package downgrade error that made Fable's project cracker fail during `dotnet fable`. The reference now uses `Version="*"` (matching `System.Threading.Channels`) so both resolve consistently. (#334) +* Tests: Added comprehensive tests for `AsyncSeq.zapp`, `AsyncSeq.zappAsync`, and `AsyncSeq.compareWithAsync`, which previously had no dedicated test coverage. +* Performance: Optimised `AsyncSeq.distinctUntilChangedWithAsync` (and thus `distinctUntilChangedWith` / `distinctUntilChanged`) to track the previous element with a `hasPrev` flag and a direct `mutable` field instead of wrapping it in a `'T option`. Previously each iteration heap-allocated a new `Some` box; the new implementation eliminates that allocation, matching the pattern already used by `pairwise`. ### 4.17.0 diff --git a/src/FSharp.Control.AsyncSeq/AsyncSeq.fs b/src/FSharp.Control.AsyncSeq/AsyncSeq.fs index a6bb766..d50650d 100644 --- a/src/FSharp.Control.AsyncSeq/AsyncSeq.fs +++ b/src/FSharp.Control.AsyncSeq/AsyncSeq.fs @@ -2740,16 +2740,18 @@ module AsyncSeq = use ie = source.GetEnumerator() let! move = ie.MoveNext() let mutable b = move - let mutable prev = None + // Use a flag + mutable field instead of Option to avoid per-element heap allocation + let mutable hasPrev = false + let mutable prev = Unchecked.defaultof<'T> while b.IsSome do let v = b.Value - match prev with - | None -> + if not hasPrev then yield v - | Some p -> - let! changed = f p v + else + let! changed = f prev v if not changed then yield v - prev <- Some v + hasPrev <- true + prev <- v let! moven = ie.MoveNext() b <- moven } diff --git a/tests/FSharp.Control.AsyncSeq.Tests/AsyncSeqTests.fs b/tests/FSharp.Control.AsyncSeq.Tests/AsyncSeqTests.fs index c3738f3..03f8dc0 100644 --- a/tests/FSharp.Control.AsyncSeq.Tests/AsyncSeqTests.fs +++ b/tests/FSharp.Control.AsyncSeq.Tests/AsyncSeqTests.fs @@ -5178,3 +5178,102 @@ let ``AsyncSeq.toObservable on empty sequence emits nothing`` () = use _sub = (AsyncSeq.toObservable (AsyncSeq.empty)).Subscribe(observer) Assert.IsTrue(completedEvent.Wait(2000)) Assert.AreEqual([||], received.ToArray()) + +// ===== zapp / zappAsync ===== + +[] +let ``AsyncSeq.zapp applies functions to corresponding elements`` () = + let fs = asyncSeq { yield (fun x -> x + 10); yield (fun x -> x * 2); yield (fun x -> x - 1) } + let vs = asyncSeq { yield 1; yield 2; yield 3 } + let result = AsyncSeq.zapp fs vs |> AsyncSeq.toArrayAsync |> Async.RunSynchronously + Assert.AreEqual([| 11; 4; 2 |], result) + +[] +let ``AsyncSeq.zapp stops when functions run out`` () = + let fs = asyncSeq { yield (fun x -> x + 1); yield (fun x -> x + 2) } + let vs = asyncSeq { yield 10; yield 20; yield 30 } + let result = AsyncSeq.zapp fs vs |> AsyncSeq.toArrayAsync |> Async.RunSynchronously + Assert.AreEqual([| 11; 22 |], result) + +[] +let ``AsyncSeq.zapp stops when values run out`` () = + let fs = asyncSeq { yield (fun x -> x + 1); yield (fun x -> x + 2); yield (fun x -> x + 3) } + let vs = asyncSeq { yield 5 } + let result = AsyncSeq.zapp fs vs |> AsyncSeq.toArrayAsync |> Async.RunSynchronously + Assert.AreEqual([| 6 |], result) + +[] +let ``AsyncSeq.zapp on empty functions returns empty`` () = + let fs = AsyncSeq.empty int> + let vs = asyncSeq { yield 1; yield 2; yield 3 } + let result = AsyncSeq.zapp fs vs |> AsyncSeq.toArrayAsync |> Async.RunSynchronously + Assert.AreEqual([||], result) + +[] +let ``AsyncSeq.zappAsync applies async functions to corresponding elements`` () = + let fs = asyncSeq { + yield (fun x -> async { return x + 10 }) + yield (fun x -> async { return x * 3 }) + } + let vs = asyncSeq { yield 5; yield 4 } + let result = AsyncSeq.zappAsync fs vs |> AsyncSeq.toArrayAsync |> Async.RunSynchronously + Assert.AreEqual([| 15; 12 |], result) + +[] +let ``AsyncSeq.zappAsync on empty source returns empty`` () = + let fs = asyncSeq { yield (fun x -> async { return x + 1 }) } + let vs = AsyncSeq.empty + let result = AsyncSeq.zappAsync fs vs |> AsyncSeq.toArrayAsync |> Async.RunSynchronously + Assert.AreEqual([||], result) + +// ===== compareWithAsync ===== + +[] +let ``AsyncSeq.compareWithAsync equal sequences returns 0`` () = + let result = + AsyncSeq.compareWithAsync + (fun a b -> async { return compare a b }) + (AsyncSeq.ofSeq [1;2;3]) + (AsyncSeq.ofSeq [1;2;3]) + |> Async.RunSynchronously + Assert.AreEqual(0, result) + +[] +let ``AsyncSeq.compareWithAsync shorter is less than longer`` () = + let result = + AsyncSeq.compareWithAsync + (fun a b -> async { return compare a b }) + (AsyncSeq.ofSeq [1;2]) + (AsyncSeq.ofSeq [1;2;3]) + |> Async.RunSynchronously + Assert.IsTrue(result < 0) + +[] +let ``AsyncSeq.compareWithAsync longer is greater than shorter`` () = + let result = + AsyncSeq.compareWithAsync + (fun a b -> async { return compare a b }) + (AsyncSeq.ofSeq [1;2;3]) + (AsyncSeq.ofSeq [1;2]) + |> Async.RunSynchronously + Assert.IsTrue(result > 0) + +[] +let ``AsyncSeq.compareWithAsync lexicographic difference`` () = + let result = + AsyncSeq.compareWithAsync + (fun a b -> async { return compare a b }) + (AsyncSeq.ofSeq [1;3]) + (AsyncSeq.ofSeq [1;2]) + |> Async.RunSynchronously + Assert.IsTrue(result > 0) + +[] +let ``AsyncSeq.compareWithAsync empty sequences returns 0`` () = + let result = + AsyncSeq.compareWithAsync + (fun a b -> async { return compare a b }) + AsyncSeq.empty + AsyncSeq.empty + |> Async.RunSynchronously + Assert.AreEqual(0, result)