From 0eac4d3726697bf54e93494457f53d149f6b68d9 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Fri, 8 May 2026 12:12:21 -0700 Subject: [PATCH 1/8] feat: convert jqschema into a skill (#31069) * chore: plan jqschema conversion to skill Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> * feat: convert jqschema.sh into a skill and remove shared agentic workflow - Create .github/skills/jqschema/SKILL.md with tools, steps, and full documentation - Delete .github/workflows/shared/jqschema.md - Update all .github/workflows/*.md files to import ../skills/jqschema/SKILL.md - Update all .github/workflows/shared/*.md files to import ../skills/jqschema/SKILL.md - Update documentation references in shared workflows - Update pkg/cli/workflows/shared/jqschema.md with actual skill content - Recompile all lock files Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> * feat: store jqschema.sh as a file in the skill folder Instead of generating jqschema.sh inline via a heredoc, the skill now stores jqschema.sh as a real file at .github/skills/jqschema/jqschema.sh and the setup step copies it to /tmp/gh-aw/jqschema.sh at runtime. Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> * chore: recompile all lock files after jqschema skill conversion Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> * chore: merge main and recompile all lock files Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .../jqschema.md => skills/jqschema/SKILL.md} | 19 +----- .github/skills/jqschema/jqschema.sh | 14 ++++ .../workflows/api-consumption-report.lock.yml | 35 +++++----- .github/workflows/api-consumption-report.md | 2 +- .github/workflows/audit-workflows.lock.yml | 35 +++++----- .github/workflows/audit-workflows.md | 2 +- .github/workflows/changeset.lock.yml | 47 +++++++------ .github/workflows/changeset.md | 2 +- .github/workflows/ci-coach.lock.yml | 41 ++++++------ .../workflows/cli-version-checker.lock.yml | 35 +++++----- .github/workflows/cli-version-checker.md | 2 +- .github/workflows/cloclo.lock.yml | 39 ++++++----- .github/workflows/cloclo.md | 2 +- .../workflows/copilot-agent-analysis.lock.yml | 35 +++++----- .github/workflows/copilot-opt.lock.yml | 35 +++++----- .github/workflows/copilot-opt.md | 2 +- .../copilot-pr-merged-report.lock.yml | 43 ++++++------ .../copilot-pr-nlp-analysis.lock.yml | 35 +++++----- .../copilot-pr-prompt-analysis.lock.yml | 35 +++++----- .../copilot-session-insights.lock.yml | 37 +++++----- .github/workflows/copilot-session-insights.md | 2 +- .../workflows/daily-issues-report.lock.yml | 47 +++++-------- .github/workflows/daily-issues-report.md | 2 +- .github/workflows/daily-news.lock.yml | 35 +++++----- .github/workflows/daily-news.md | 2 +- .../daily-safe-output-optimizer.lock.yml | 35 +++++----- .../workflows/daily-safe-output-optimizer.md | 2 +- .github/workflows/deep-report.lock.yml | 35 +++++----- .github/workflows/deep-report.md | 2 +- .../workflows/discussion-task-miner.lock.yml | 35 +++++----- .github/workflows/discussion-task-miner.md | 2 +- .github/workflows/issue-arborist.lock.yml | 67 +++++++------------ .github/workflows/issue-arborist.md | 2 +- .github/workflows/org-health-report.lock.yml | 35 +++++----- .github/workflows/org-health-report.md | 2 +- .../prompt-clustering-analysis.lock.yml | 35 +++++----- .../workflows/prompt-clustering-analysis.md | 2 +- .github/workflows/safe-output-health.lock.yml | 35 +++++----- .github/workflows/safe-output-health.md | 2 +- .github/workflows/scout.lock.yml | 35 +++++----- .github/workflows/scout.md | 2 +- .github/workflows/shared/ci-data-analysis.md | 2 +- .../shared/copilot-pr-analysis-base.md | 2 +- .../workflows/shared/copilot-pr-data-fetch.md | 4 +- .../shared/copilot-session-data-fetch.md | 12 ++-- .../shared/discussions-data-fetch.md | 2 +- .github/workflows/shared/issues-data-fetch.md | 2 +- .../shared/weekly-issues-data-fetch.md | 2 +- .../workflows/stale-repo-identifier.lock.yml | 47 +++++-------- .github/workflows/stale-repo-identifier.md | 2 +- pkg/actionpins/spec_test.go | 1 - pkg/cli/workflows/shared/jqschema.md | 26 ++++++- 52 files changed, 525 insertions(+), 490 deletions(-) rename .github/{workflows/shared/jqschema.md => skills/jqschema/SKILL.md} (87%) create mode 100644 .github/skills/jqschema/jqschema.sh diff --git a/.github/workflows/shared/jqschema.md b/.github/skills/jqschema/SKILL.md similarity index 87% rename from .github/workflows/shared/jqschema.md rename to .github/skills/jqschema/SKILL.md index 5e21b9a1361..ebd822aa2e1 100644 --- a/.github/workflows/shared/jqschema.md +++ b/.github/skills/jqschema/SKILL.md @@ -1,4 +1,6 @@ --- +name: jqschema +description: JSON schema discovery utility that extracts structure and type information from JSON data tools: bash: - "jq *" @@ -8,22 +10,7 @@ steps: - name: Setup jq utilities directory run: | mkdir -p /tmp/gh-aw - cat > /tmp/gh-aw/jqschema.sh << 'EOF' - #!/usr/bin/env bash - # jqschema.sh - jq -c ' - def walk(f): - . as $in | - if type == "object" then - reduce keys[] as $k ({}; . + {($k): ($in[$k] | walk(f))}) - elif type == "array" then - if length == 0 then [] else [.[0] | walk(f)] end - else - type - end; - walk(.) - ' - EOF + cp "$GITHUB_WORKSPACE/.github/skills/jqschema/jqschema.sh" /tmp/gh-aw/jqschema.sh chmod +x /tmp/gh-aw/jqschema.sh --- diff --git a/.github/skills/jqschema/jqschema.sh b/.github/skills/jqschema/jqschema.sh new file mode 100644 index 00000000000..daf0457d9a0 --- /dev/null +++ b/.github/skills/jqschema/jqschema.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash +# jqschema.sh +jq -c ' +def walk(f): + . as $in | + if type == "object" then + reduce keys[] as $k ({}; . + {($k): ($in[$k] | walk(f))}) + elif type == "array" then + if length == 0 then [] else [.[0] | walk(f)] end + else + type + end; +walk(.) +' diff --git a/.github/workflows/api-consumption-report.lock.yml b/.github/workflows/api-consumption-report.lock.yml index 0a4b1e2604b..934c10a95b5 100644 --- a/.github/workflows/api-consumption-report.lock.yml +++ b/.github/workflows/api-consumption-report.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"d5e4c223b74f48b6393e7e180fbc9fd8bff65ffebae0390bb4c8e592c3939cb7","strict":true,"agent_id":"claude"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"68f5e3e65ff0777e8634d414b1f69c1e033d5391c26f8d5cb436cacadcf5f36f","strict":true,"agent_id":"claude"} # gh-aw-manifest: {"version":1,"secrets":["ANTHROPIC_API_KEY","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_ENDPOINT","GH_AW_OTEL_HEADERS","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-go","sha":"4a3601121dd01d1626a1e23e37211e3254c1c06c","version":"v6.4.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/setup-python","sha":"a309ff8b426b58ec0e2a45f0f869d46889d02405","version":"v6.2.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"docker/build-push-action","sha":"bcafcacb16a39f128d818304e6c9c0c18556b85f","version":"v7.1.0"},{"repo":"docker/setup-buildx-action","sha":"4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd","version":"v4.0.0"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41","digest":"sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41@sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41","digest":"sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41@sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41","digest":"sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41@sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.6","digest":"sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c"},{"image":"ghcr.io/github/github-mcp-server:v1.0.3","digest":"sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} # ___ _ _ # / _ \ | | (_) @@ -26,8 +26,8 @@ # # Resolved workflow manifest: # Imports: +# - ../skills/jqschema/SKILL.md # - shared/daily-audit-discussion.md -# - shared/jqschema.md # - shared/observability-otlp.md # - shared/reporting.md # - shared/daily-audit-base.md @@ -207,24 +207,24 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_2ed8e2a89c4f122b_EOF' + cat << 'GH_AW_PROMPT_afe290ebea046dda_EOF' - GH_AW_PROMPT_2ed8e2a89c4f122b_EOF + GH_AW_PROMPT_afe290ebea046dda_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/agentic_workflows_guide.md" cat "${RUNNER_TEMP}/gh-aw/prompts/cache_memory_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_2ed8e2a89c4f122b_EOF' + cat << 'GH_AW_PROMPT_afe290ebea046dda_EOF' Tools: create_discussion, upload_asset(max:5), missing_tool, missing_data, noop upload_asset: provide a file path; returns a URL; assets are published after the workflow completes (safeoutputs). - GH_AW_PROMPT_2ed8e2a89c4f122b_EOF + GH_AW_PROMPT_afe290ebea046dda_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" - cat << 'GH_AW_PROMPT_2ed8e2a89c4f122b_EOF' + cat << 'GH_AW_PROMPT_afe290ebea046dda_EOF' The following GitHub context information is available for this workflow: {{#if __GH_AW_GITHUB_ACTOR__ }} @@ -253,16 +253,16 @@ jobs: {{/if}} - GH_AW_PROMPT_2ed8e2a89c4f122b_EOF + GH_AW_PROMPT_afe290ebea046dda_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_2ed8e2a89c4f122b_EOF' + cat << 'GH_AW_PROMPT_afe290ebea046dda_EOF' - {{#runtime-import .github/workflows/shared/jqschema.md}} + {{#runtime-import .github/skills/jqschema/SKILL.md}} {{#runtime-import .github/workflows/shared/observability-otlp.md}} {{#runtime-import .github/workflows/shared/trending-charts-simple.md}} {{#runtime-import .github/workflows/shared/reporting.md}} {{#runtime-import .github/workflows/api-consumption-report.md}} - GH_AW_PROMPT_2ed8e2a89c4f122b_EOF + GH_AW_PROMPT_afe290ebea046dda_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -448,7 +448,10 @@ jobs: env: GH_TOKEN: ${{ github.token }} - name: Setup jq utilities directory - run: "mkdir -p /tmp/gh-aw\ncat > /tmp/gh-aw/jqschema.sh << 'EOF'\n#!/usr/bin/env bash\n# jqschema.sh\njq -c '\ndef walk(f):\n . as $in |\n if type == \"object\" then\n reduce keys[] as $k ({}; . + {($k): ($in[$k] | walk(f))})\n elif type == \"array\" then\n if length == 0 then [] else [.[0] | walk(f)] end\n else\n type\n end;\nwalk(.)\n'\nEOF\nchmod +x /tmp/gh-aw/jqschema.sh\n" + run: | + mkdir -p /tmp/gh-aw + cp "$GITHUB_WORKSPACE/.github/skills/jqschema/jqschema.sh" /tmp/gh-aw/jqschema.sh + chmod +x /tmp/gh-aw/jqschema.sh - name: Setup Python environment run: "mkdir -p /tmp/gh-aw/python/{data,charts,artifacts}\n# Create a virtual environment for proper package isolation (avoids --break-system-packages)\nif [ ! -d /tmp/gh-aw/venv ]; then\n python3 -m venv /tmp/gh-aw/venv\nfi\necho \"/tmp/gh-aw/venv/bin\" >> \"$GITHUB_PATH\"\n/tmp/gh-aw/venv/bin/pip install --quiet numpy pandas matplotlib seaborn scipy\n" - if: always() @@ -576,9 +579,9 @@ jobs: 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_cb4758322070deae_EOF + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << GH_AW_SAFE_OUTPUTS_CONFIG_e2ebce053bafc806_EOF {"create_discussion":{"category":"audits","close_older_discussions":true,"expires":72,"fallback_to_issue":true,"max":1,"title_prefix":"[api-consumption] "},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{},"upload_asset":{"allowed-exts":[".png",".jpg",".jpeg",".svg"],"branch":"assets/${GITHUB_WORKFLOW}","max":5,"max-size":10240}} - GH_AW_SAFE_OUTPUTS_CONFIG_cb4758322070deae_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_e2ebce053bafc806_EOF - name: Generate Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -786,7 +789,7 @@ jobs: export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v /var/run/docker.sock:/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 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_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 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 GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -e GITHUB_AW_OTEL_TRACE_ID -e GITHUB_AW_OTEL_PARENT_SPAN_ID -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 ghcr.io/github/gh-aw-mcpg:v0.3.6' GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) - cat << GH_AW_MCP_CONFIG_e8c66d5ec234696f_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_72e149820af8a903_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "agenticworkflows": { @@ -850,7 +853,7 @@ jobs: } } } - GH_AW_MCP_CONFIG_e8c66d5ec234696f_EOF + GH_AW_MCP_CONFIG_72e149820af8a903_EOF - name: Mount MCP servers as CLIs id: mount-mcp-clis continue-on-error: true diff --git a/.github/workflows/api-consumption-report.md b/.github/workflows/api-consumption-report.md index f8bbc41660f..c00ea264c38 100644 --- a/.github/workflows/api-consumption-report.md +++ b/.github/workflows/api-consumption-report.md @@ -26,7 +26,7 @@ imports: with: title-prefix: "[api-consumption] " expires: 3d - - shared/jqschema.md + - ../skills/jqschema/SKILL.md - shared/observability-otlp.md diff --git a/.github/workflows/audit-workflows.lock.yml b/.github/workflows/audit-workflows.lock.yml index 97f41779813..840ce69bd6f 100644 --- a/.github/workflows/audit-workflows.lock.yml +++ b/.github/workflows/audit-workflows.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"43620e61da74dea1d1d5d7d111055882c9b96a703a37977301204eff39ed959b","strict":true,"agent_id":"claude"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"4689ad71c303882b4714a0e98230c8f6b93c66ecb352cd5940fdf7d17c6419f5","strict":true,"agent_id":"claude"} # gh-aw-manifest: {"version":1,"secrets":["ANTHROPIC_API_KEY","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_ENDPOINT","GH_AW_OTEL_HEADERS","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-go","sha":"4a3601121dd01d1626a1e23e37211e3254c1c06c","version":"v6.4.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/setup-python","sha":"a309ff8b426b58ec0e2a45f0f869d46889d02405","version":"v6.2.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"docker/build-push-action","sha":"bcafcacb16a39f128d818304e6c9c0c18556b85f","version":"v7.1.0"},{"repo":"docker/setup-buildx-action","sha":"4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd","version":"v4.0.0"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41","digest":"sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41@sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41","digest":"sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41@sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41","digest":"sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41@sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.6","digest":"sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c"},{"image":"ghcr.io/github/github-mcp-server:v1.0.3","digest":"sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} # ___ _ _ # / _ \ | | (_) @@ -26,8 +26,8 @@ # # Resolved workflow manifest: # Imports: +# - ../skills/jqschema/SKILL.md # - shared/daily-audit-discussion.md -# - shared/jqschema.md # - shared/observability-otlp.md # - shared/repo-memory-standard.md # - shared/reporting.md @@ -208,9 +208,9 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_7e337aa8d9cdd6ba_EOF' + cat << 'GH_AW_PROMPT_91ee9d396891ebfd_EOF' - GH_AW_PROMPT_7e337aa8d9cdd6ba_EOF + GH_AW_PROMPT_91ee9d396891ebfd_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" @@ -218,15 +218,15 @@ jobs: cat "${RUNNER_TEMP}/gh-aw/prompts/cache_memory_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/repo_memory_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_7e337aa8d9cdd6ba_EOF' + cat << 'GH_AW_PROMPT_91ee9d396891ebfd_EOF' Tools: create_discussion, upload_asset(max:3), missing_tool, missing_data, noop upload_asset: provide a file path; returns a URL; assets are published after the workflow completes (safeoutputs). - GH_AW_PROMPT_7e337aa8d9cdd6ba_EOF + GH_AW_PROMPT_91ee9d396891ebfd_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" - cat << 'GH_AW_PROMPT_7e337aa8d9cdd6ba_EOF' + cat << 'GH_AW_PROMPT_91ee9d396891ebfd_EOF' The following GitHub context information is available for this workflow: {{#if __GH_AW_GITHUB_ACTOR__ }} @@ -255,17 +255,17 @@ jobs: {{/if}} - GH_AW_PROMPT_7e337aa8d9cdd6ba_EOF + GH_AW_PROMPT_91ee9d396891ebfd_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_7e337aa8d9cdd6ba_EOF' + cat << 'GH_AW_PROMPT_91ee9d396891ebfd_EOF' - {{#runtime-import .github/workflows/shared/jqschema.md}} + {{#runtime-import .github/skills/jqschema/SKILL.md}} {{#runtime-import .github/workflows/shared/observability-otlp.md}} {{#runtime-import .github/workflows/shared/trending-charts-simple.md}} {{#runtime-import .github/workflows/shared/reporting.md}} {{#runtime-import .github/workflows/shared/noop-reminder.md}} {{#runtime-import .github/workflows/audit-workflows.md}} - GH_AW_PROMPT_7e337aa8d9cdd6ba_EOF + GH_AW_PROMPT_91ee9d396891ebfd_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -458,7 +458,10 @@ jobs: env: GH_TOKEN: ${{ github.token }} - name: Setup jq utilities directory - run: "mkdir -p /tmp/gh-aw\ncat > /tmp/gh-aw/jqschema.sh << 'EOF'\n#!/usr/bin/env bash\n# jqschema.sh\njq -c '\ndef walk(f):\n . as $in |\n if type == \"object\" then\n reduce keys[] as $k ({}; . + {($k): ($in[$k] | walk(f))})\n elif type == \"array\" then\n if length == 0 then [] else [.[0] | walk(f)] end\n else\n type\n end;\nwalk(.)\n'\nEOF\nchmod +x /tmp/gh-aw/jqschema.sh\n" + run: | + mkdir -p /tmp/gh-aw + cp "$GITHUB_WORKSPACE/.github/skills/jqschema/jqschema.sh" /tmp/gh-aw/jqschema.sh + chmod +x /tmp/gh-aw/jqschema.sh - name: Setup Python environment run: "mkdir -p /tmp/gh-aw/python/{data,charts,artifacts}\n# Create a virtual environment for proper package isolation (avoids --break-system-packages)\nif [ ! -d /tmp/gh-aw/venv ]; then\n python3 -m venv /tmp/gh-aw/venv\nfi\necho \"/tmp/gh-aw/venv/bin\" >> \"$GITHUB_PATH\"\n/tmp/gh-aw/venv/bin/pip install --quiet numpy pandas matplotlib seaborn scipy\n" - if: always() @@ -596,9 +599,9 @@ jobs: 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_93bd7435df2943e9_EOF + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << GH_AW_SAFE_OUTPUTS_CONFIG_ed56a2e430b056b4_EOF {"create_discussion":{"category":"audits","close_older_discussions":true,"expires":24,"fallback_to_issue":true,"max":1,"title_prefix":"[audit-workflows] "},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"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}]},"report_incomplete":{},"upload_asset":{"allowed-exts":[".png",".jpg",".jpeg",".svg"],"branch":"assets/${GITHUB_WORKFLOW}","max":3,"max-size":10240}} - GH_AW_SAFE_OUTPUTS_CONFIG_93bd7435df2943e9_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_ed56a2e430b056b4_EOF - name: Generate Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -806,7 +809,7 @@ jobs: export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v /var/run/docker.sock:/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 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_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 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 GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -e GITHUB_AW_OTEL_TRACE_ID -e GITHUB_AW_OTEL_PARENT_SPAN_ID -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 ghcr.io/github/gh-aw-mcpg:v0.3.6' GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) - cat << GH_AW_MCP_CONFIG_667c4fb6cb922aa6_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_537c45ae9a7d7f33_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "agenticworkflows": { @@ -870,7 +873,7 @@ jobs: } } } - GH_AW_MCP_CONFIG_667c4fb6cb922aa6_EOF + GH_AW_MCP_CONFIG_537c45ae9a7d7f33_EOF - name: Mount MCP servers as CLIs id: mount-mcp-clis continue-on-error: true diff --git a/.github/workflows/audit-workflows.md b/.github/workflows/audit-workflows.md index 91d1ae9244a..85a0ef6ac93 100644 --- a/.github/workflows/audit-workflows.md +++ b/.github/workflows/audit-workflows.md @@ -28,7 +28,7 @@ imports: with: branch-name: "memory/audit-workflows" description: "Historical audit data and patterns" - - shared/jqschema.md + - ../skills/jqschema/SKILL.md - shared/observability-otlp.md diff --git a/.github/workflows/changeset.lock.yml b/.github/workflows/changeset.lock.yml index 9036b8a1513..84c4a095590 100644 --- a/.github/workflows/changeset.lock.yml +++ b/.github/workflows/changeset.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"689e8aa2805c2b22c91fa4fbe85cb1714e61721aeabde97aebd5254b25249284","strict":true,"agent_id":"codex","agent_model":"gpt-5.4-mini"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"12ca4252297b19573625318ab734570ad227161d2bc0f626f03535dcd5099b0d","strict":true,"agent_id":"codex","agent_model":"gpt-5.4-mini"} # gh-aw-manifest: {"version":1,"secrets":["CODEX_API_KEY","GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_ENDPOINT","GH_AW_OTEL_HEADERS","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"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":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41","digest":"sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41@sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41","digest":"sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41@sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41","digest":"sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41@sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.6","digest":"sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c"},{"image":"ghcr.io/github/github-mcp-server:v1.0.3","digest":"sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} # ___ _ _ # / _ \ | | (_) @@ -26,8 +26,8 @@ # # Resolved workflow manifest: # Imports: +# - ../skills/jqschema/SKILL.md # - shared/changeset-format.md -# - shared/jqschema.md # - shared/observability-otlp.md # # Secrets used: @@ -241,23 +241,23 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_802a243cd285ffa0_EOF' + cat << 'GH_AW_PROMPT_916b2bc58f40c391_EOF' - GH_AW_PROMPT_802a243cd285ffa0_EOF + GH_AW_PROMPT_916b2bc58f40c391_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_802a243cd285ffa0_EOF' + cat << 'GH_AW_PROMPT_916b2bc58f40c391_EOF' Tools: update_pull_request, push_to_pull_request_branch, missing_tool, missing_data, noop - GH_AW_PROMPT_802a243cd285ffa0_EOF + GH_AW_PROMPT_916b2bc58f40c391_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_push_to_pr_branch.md" - cat << 'GH_AW_PROMPT_802a243cd285ffa0_EOF' + cat << 'GH_AW_PROMPT_916b2bc58f40c391_EOF' - GH_AW_PROMPT_802a243cd285ffa0_EOF + GH_AW_PROMPT_916b2bc58f40c391_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" - cat << 'GH_AW_PROMPT_802a243cd285ffa0_EOF' + cat << 'GH_AW_PROMPT_916b2bc58f40c391_EOF' The following GitHub context information is available for this workflow: {{#if __GH_AW_GITHUB_ACTOR__ }} @@ -286,15 +286,15 @@ jobs: {{/if}} - GH_AW_PROMPT_802a243cd285ffa0_EOF + GH_AW_PROMPT_916b2bc58f40c391_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_802a243cd285ffa0_EOF' + cat << 'GH_AW_PROMPT_916b2bc58f40c391_EOF' {{#runtime-import .github/workflows/shared/changeset-format.md}} - {{#runtime-import .github/workflows/shared/jqschema.md}} + {{#runtime-import .github/skills/jqschema/SKILL.md}} {{#runtime-import .github/workflows/shared/observability-otlp.md}} {{#runtime-import .github/workflows/changeset.md}} - GH_AW_PROMPT_802a243cd285ffa0_EOF + GH_AW_PROMPT_916b2bc58f40c391_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -441,7 +441,10 @@ jobs: env: GH_TOKEN: ${{ github.token }} - name: Setup jq utilities directory - run: "mkdir -p /tmp/gh-aw\ncat > /tmp/gh-aw/jqschema.sh << 'EOF'\n#!/usr/bin/env bash\n# jqschema.sh\njq -c '\ndef walk(f):\n . as $in |\n if type == \"object\" then\n reduce keys[] as $k ({}; . + {($k): ($in[$k] | walk(f))})\n elif type == \"array\" then\n if length == 0 then [] else [.[0] | walk(f)] end\n else\n type\n end;\nwalk(.)\n'\nEOF\nchmod +x /tmp/gh-aw/jqschema.sh\n" + run: | + mkdir -p /tmp/gh-aw + cp "$GITHUB_WORKSPACE/.github/skills/jqschema/jqschema.sh" /tmp/gh-aw/jqschema.sh + chmod +x /tmp/gh-aw/jqschema.sh - name: Configure Git credentials env: @@ -512,9 +515,9 @@ jobs: 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_0d57de660a26d1e9_EOF' + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_d210d8d1fe91287b_EOF' {"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"push_to_pull_request_branch":{"allowed_files":[".changeset/**"],"commit_title_suffix":" [skip-ci]","if_no_changes":"warn","max_patch_size":1024,"patch_format":"bundle","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","CLAUDE.md","GEMINI.md"]},"report_incomplete":{},"update_pull_request":{"allow_body":true,"allow_title":false,"default_operation":"append","max":1,"update_branch":false}} - GH_AW_SAFE_OUTPUTS_CONFIG_0d57de660a26d1e9_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_d210d8d1fe91287b_EOF - name: Generate Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -739,7 +742,7 @@ jobs: DOCKER_SOCK_GID=$(stat -c '%g' /var/run/docker.sock 2>/dev/null || echo '0') export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v /var/run/docker.sock:/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 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_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 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 GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -e GITHUB_AW_OTEL_TRACE_ID -e GITHUB_AW_OTEL_PARENT_SPAN_ID -e CODEX_HOME -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 ghcr.io/github/gh-aw-mcpg:v0.3.6' - cat > "${RUNNER_TEMP}/gh-aw/mcp-config/config.toml" << GH_AW_MCP_CONFIG_8cd17614441f5d2a_EOF + cat > "${RUNNER_TEMP}/gh-aw/mcp-config/config.toml" << GH_AW_MCP_CONFIG_a82b6803edffb2e8_EOF [history] persistence = "none" @@ -766,11 +769,11 @@ jobs: [mcp_servers.safeoutputs."guard-policies".write-sink] accept = ["*"] - GH_AW_MCP_CONFIG_8cd17614441f5d2a_EOF + GH_AW_MCP_CONFIG_a82b6803edffb2e8_EOF # Generate JSON config for MCP gateway GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) - cat << GH_AW_MCP_CONFIG_8cd17614441f5d2a_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_a82b6803edffb2e8_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "github": { @@ -816,11 +819,11 @@ jobs: } } } - GH_AW_MCP_CONFIG_8cd17614441f5d2a_EOF + GH_AW_MCP_CONFIG_a82b6803edffb2e8_EOF # Sync converter output to writable CODEX_HOME for Codex mkdir -p /tmp/gh-aw/mcp-config - cat > "/tmp/gh-aw/mcp-config/config.toml" << GH_AW_CODEX_SHELL_POLICY_deab52a582969330_EOF + cat > "/tmp/gh-aw/mcp-config/config.toml" << GH_AW_CODEX_SHELL_POLICY_11d5fb7bbaaa9abd_EOF model_provider = "openai-proxy" @@ -832,7 +835,7 @@ jobs: [shell_environment_policy] inherit = "core" include_only = ["CODEX_API_KEY", "GH_AW_ASSETS_ALLOWED_EXTS", "GH_AW_ASSETS_BRANCH", "GH_AW_ASSETS_MAX_SIZE_KB", "GH_AW_SAFE_OUTPUTS", "GITHUB_PERSONAL_ACCESS_TOKEN", "GITHUB_REPOSITORY", "GITHUB_SERVER_URL", "HOME", "OPENAI_API_KEY", "PATH"] - GH_AW_CODEX_SHELL_POLICY_deab52a582969330_EOF + GH_AW_CODEX_SHELL_POLICY_11d5fb7bbaaa9abd_EOF awk ' BEGIN { skip_openai_proxy = 0 } /^[[:space:]]*model_provider[[:space:]]*=/ { next } diff --git a/.github/workflows/changeset.md b/.github/workflows/changeset.md index 089dd146ea4..2523a118b82 100644 --- a/.github/workflows/changeset.md +++ b/.github/workflows/changeset.md @@ -41,7 +41,7 @@ tools: edit: imports: - shared/changeset-format.md - - shared/jqschema.md + - ../skills/jqschema/SKILL.md - shared/observability-otlp.md diff --git a/.github/workflows/ci-coach.lock.yml b/.github/workflows/ci-coach.lock.yml index 790a02eb548..523d237fcb1 100644 --- a/.github/workflows/ci-coach.lock.yml +++ b/.github/workflows/ci-coach.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"e46e44cf30811727563fa1bd976472feae720b8adb9d77ced32c1c5641aceb63","strict":true,"agent_id":"copilot"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"5866dd65facf7832d15e53f37cff1ef247ca95c232129ff92058d095aed8f96b","strict":true,"agent_id":"copilot"} # gh-aw-manifest: {"version":1,"secrets":["GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_ENDPOINT","GH_AW_OTEL_HEADERS","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-go","sha":"4a3601121dd01d1626a1e23e37211e3254c1c06c","version":"v6.4.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41","digest":"sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41@sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41","digest":"sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41@sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0"},{"image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.41","digest":"sha256:62171f2fa508667b8b0a9e096f826983f312e3da0ce894f80c0f83a875af60fe","pinned_image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.41@sha256:62171f2fa508667b8b0a9e096f826983f312e3da0ce894f80c0f83a875af60fe"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41","digest":"sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41@sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.6","digest":"sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c"},{"image":"ghcr.io/github/github-mcp-server:v1.0.3","digest":"sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} # ___ _ _ # / _ \ | | (_) @@ -26,9 +26,9 @@ # # Resolved workflow manifest: # Imports: -# - shared/ci-optimization-strategies.md -# - shared/jqschema.md +# - ../skills/jqschema/SKILL.md # - shared/ci-data-analysis.md +# - shared/ci-optimization-strategies.md # - shared/observability-otlp.md # - shared/reporting.md # @@ -197,24 +197,24 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_abcb9fcb3b31b0ab_EOF' + cat << 'GH_AW_PROMPT_f208f17f3e415246_EOF' - GH_AW_PROMPT_abcb9fcb3b31b0ab_EOF + GH_AW_PROMPT_f208f17f3e415246_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/cache_memory_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_abcb9fcb3b31b0ab_EOF' + cat << 'GH_AW_PROMPT_f208f17f3e415246_EOF' Tools: create_pull_request, missing_tool, missing_data, noop - GH_AW_PROMPT_abcb9fcb3b31b0ab_EOF + GH_AW_PROMPT_f208f17f3e415246_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_create_pull_request.md" - cat << 'GH_AW_PROMPT_abcb9fcb3b31b0ab_EOF' + cat << 'GH_AW_PROMPT_f208f17f3e415246_EOF' - GH_AW_PROMPT_abcb9fcb3b31b0ab_EOF + GH_AW_PROMPT_f208f17f3e415246_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" - cat << 'GH_AW_PROMPT_abcb9fcb3b31b0ab_EOF' + cat << 'GH_AW_PROMPT_f208f17f3e415246_EOF' The following GitHub context information is available for this workflow: {{#if __GH_AW_GITHUB_ACTOR__ }} @@ -243,18 +243,18 @@ jobs: {{/if}} - GH_AW_PROMPT_abcb9fcb3b31b0ab_EOF + GH_AW_PROMPT_f208f17f3e415246_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/cli_proxy_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_abcb9fcb3b31b0ab_EOF' + cat << 'GH_AW_PROMPT_f208f17f3e415246_EOF' {{#runtime-import .github/workflows/shared/ci-data-analysis.md}} {{#runtime-import .github/workflows/shared/ci-optimization-strategies.md}} {{#runtime-import .github/workflows/shared/reporting.md}} {{#runtime-import .github/workflows/shared/observability-otlp.md}} - {{#runtime-import .github/workflows/shared/jqschema.md}} + {{#runtime-import .github/skills/jqschema/SKILL.md}} {{#runtime-import .github/workflows/shared/noop-reminder.md}} {{#runtime-import .github/workflows/ci-coach.md}} - GH_AW_PROMPT_abcb9fcb3b31b0ab_EOF + GH_AW_PROMPT_f208f17f3e415246_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -447,7 +447,10 @@ jobs: mkdir -p /tmp/gh-aw go test -v -json -count=1 -timeout=3m -tags '!integration' -run='^Test' ./... | tee /tmp/gh-aw/test-results.json - name: Setup jq utilities directory - run: "mkdir -p /tmp/gh-aw\ncat > /tmp/gh-aw/jqschema.sh << 'EOF'\n#!/usr/bin/env bash\n# jqschema.sh\njq -c '\ndef walk(f):\n . as $in |\n if type == \"object\" then\n reduce keys[] as $k ({}; . + {($k): ($in[$k] | walk(f))})\n elif type == \"array\" then\n if length == 0 then [] else [.[0] | walk(f)] end\n else\n type\n end;\nwalk(.)\n'\nEOF\nchmod +x /tmp/gh-aw/jqschema.sh\n" + run: | + mkdir -p /tmp/gh-aw + cp "$GITHUB_WORKSPACE/.github/skills/jqschema/jqschema.sh" /tmp/gh-aw/jqschema.sh + chmod +x /tmp/gh-aw/jqschema.sh # Cache memory file share configuration from frontmatter processed below - name: Create cache-memory directory @@ -530,9 +533,9 @@ jobs: 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_3787085c13dce67f_EOF' + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_2964393b5a55119e_EOF' {"create_pull_request":{"expires":48,"max":1,"max_patch_files":100,"max_patch_size":1024,"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","CLAUDE.md","GEMINI.md"],"protected_files_policy":"fallback-to-issue","title_prefix":"[ci-coach] "},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} - GH_AW_SAFE_OUTPUTS_CONFIG_3787085c13dce67f_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_2964393b5a55119e_EOF - name: Generate Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -739,7 +742,7 @@ jobs: mkdir -p /home/runner/.copilot GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) - cat << GH_AW_MCP_CONFIG_4ac2c66f16a8db5a_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_6333d3a1b66df60c_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "safeoutputs": { @@ -770,7 +773,7 @@ jobs: } } } - GH_AW_MCP_CONFIG_4ac2c66f16a8db5a_EOF + GH_AW_MCP_CONFIG_6333d3a1b66df60c_EOF - name: Mount MCP servers as CLIs id: mount-mcp-clis continue-on-error: true diff --git a/.github/workflows/cli-version-checker.lock.yml b/.github/workflows/cli-version-checker.lock.yml index 0b01674d30c..3598f19e0ee 100644 --- a/.github/workflows/cli-version-checker.lock.yml +++ b/.github/workflows/cli-version-checker.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"a29bde63ed47ee4d7f1b709c471f6260be5a83080a235290d91810d7ca04020e","agent_id":"claude"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"3b614d9634b708d7c5fcf25600a4223112bb19bff5651c2e7fdb34ccca89e4e9","agent_id":"claude"} # gh-aw-manifest: {"version":1,"secrets":["ANTHROPIC_API_KEY","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_ENDPOINT","GH_AW_OTEL_HEADERS","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"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":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41","digest":"sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41@sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41","digest":"sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41@sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41","digest":"sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41@sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.6","digest":"sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c"},{"image":"ghcr.io/github/github-mcp-server:v1.0.3","digest":"sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} # ___ _ _ # / _ \ | | (_) @@ -26,7 +26,7 @@ # # Resolved workflow manifest: # Imports: -# - shared/jqschema.md +# - ../skills/jqschema/SKILL.md # - shared/observability-otlp.md # - shared/reporting.md # @@ -198,21 +198,21 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_29e579ace2c240a9_EOF' + cat << 'GH_AW_PROMPT_8e8b5d02e440018f_EOF' - GH_AW_PROMPT_29e579ace2c240a9_EOF + GH_AW_PROMPT_8e8b5d02e440018f_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/cache_memory_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_29e579ace2c240a9_EOF' + cat << 'GH_AW_PROMPT_8e8b5d02e440018f_EOF' Tools: create_issue, missing_tool, missing_data, noop - GH_AW_PROMPT_29e579ace2c240a9_EOF + GH_AW_PROMPT_8e8b5d02e440018f_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" - cat << 'GH_AW_PROMPT_29e579ace2c240a9_EOF' + cat << 'GH_AW_PROMPT_8e8b5d02e440018f_EOF' The following GitHub context information is available for this workflow: {{#if __GH_AW_GITHUB_ACTOR__ }} @@ -241,16 +241,16 @@ jobs: {{/if}} - GH_AW_PROMPT_29e579ace2c240a9_EOF + GH_AW_PROMPT_8e8b5d02e440018f_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_29e579ace2c240a9_EOF' + cat << 'GH_AW_PROMPT_8e8b5d02e440018f_EOF' - {{#runtime-import .github/workflows/shared/jqschema.md}} + {{#runtime-import .github/skills/jqschema/SKILL.md}} {{#runtime-import .github/workflows/shared/reporting.md}} {{#runtime-import .github/workflows/shared/observability-otlp.md}} {{#runtime-import .github/workflows/shared/noop-reminder.md}} {{#runtime-import .github/workflows/cli-version-checker.md}} - GH_AW_PROMPT_29e579ace2c240a9_EOF + GH_AW_PROMPT_8e8b5d02e440018f_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -397,7 +397,10 @@ jobs: env: GH_TOKEN: ${{ github.token }} - name: Setup jq utilities directory - run: "mkdir -p /tmp/gh-aw\ncat > /tmp/gh-aw/jqschema.sh << 'EOF'\n#!/usr/bin/env bash\n# jqschema.sh\njq -c '\ndef walk(f):\n . as $in |\n if type == \"object\" then\n reduce keys[] as $k ({}; . + {($k): ($in[$k] | walk(f))})\n elif type == \"array\" then\n if length == 0 then [] else [.[0] | walk(f)] end\n else\n type\n end;\nwalk(.)\n'\nEOF\nchmod +x /tmp/gh-aw/jqschema.sh\n" + run: | + mkdir -p /tmp/gh-aw + cp "$GITHUB_WORKSPACE/.github/skills/jqschema/jqschema.sh" /tmp/gh-aw/jqschema.sh + chmod +x /tmp/gh-aw/jqschema.sh # Cache memory file share configuration from frontmatter processed below - name: Create cache-memory directory @@ -483,9 +486,9 @@ jobs: 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_c9d9704321dce32b_EOF' + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_b71ea9e6d0996de0_EOF' {"create_issue":{"close_older_issues":true,"expires":48,"labels":["automation","dependencies","cookie"],"max":1,"title_prefix":"[ca] "},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} - GH_AW_SAFE_OUTPUTS_CONFIG_c9d9704321dce32b_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_b71ea9e6d0996de0_EOF - name: Generate Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -689,7 +692,7 @@ jobs: export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v /var/run/docker.sock:/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 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_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 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 GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -e GITHUB_AW_OTEL_TRACE_ID -e GITHUB_AW_OTEL_PARENT_SPAN_ID -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 ghcr.io/github/gh-aw-mcpg:v0.3.6' GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) - cat << GH_AW_MCP_CONFIG_dd4e0349632dfab4_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_7f204516c4000e28_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "github": { @@ -735,7 +738,7 @@ jobs: } } } - GH_AW_MCP_CONFIG_dd4e0349632dfab4_EOF + GH_AW_MCP_CONFIG_7f204516c4000e28_EOF - name: Mount MCP servers as CLIs id: mount-mcp-clis continue-on-error: true diff --git a/.github/workflows/cli-version-checker.md b/.github/workflows/cli-version-checker.md index 045356f08c2..030a8886b05 100644 --- a/.github/workflows/cli-version-checker.md +++ b/.github/workflows/cli-version-checker.md @@ -12,7 +12,7 @@ engine: claude network: allowed: [defaults, node, go, "api.github.com", "ghcr.io"] imports: - - shared/jqschema.md + - ../skills/jqschema/SKILL.md - shared/reporting.md - shared/observability-otlp.md tools: diff --git a/.github/workflows/cloclo.lock.yml b/.github/workflows/cloclo.lock.yml index 209efd84985..b85bb4481bb 100644 --- a/.github/workflows/cloclo.lock.yml +++ b/.github/workflows/cloclo.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"ac1f73602782b781282d3405f9d72acad8c6fb619fa896d2a1d77d9bb0b0ee7c","strict":true,"agent_id":"claude"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"7580a647bab899ad36421143e1965286e78b15bbb5431b173f3c6afa33b428c2","strict":true,"agent_id":"claude"} # gh-aw-manifest: {"version":1,"secrets":["ANTHROPIC_API_KEY","GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_ENDPOINT","GH_AW_OTEL_HEADERS","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-go","sha":"4a3601121dd01d1626a1e23e37211e3254c1c06c","version":"v6.4.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"docker/build-push-action","sha":"bcafcacb16a39f128d818304e6c9c0c18556b85f","version":"v7.1.0"},{"repo":"docker/setup-buildx-action","sha":"4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd","version":"v4.0.0"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41","digest":"sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41@sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41","digest":"sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41@sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41","digest":"sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41@sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.6","digest":"sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c"},{"image":"ghcr.io/github/github-mcp-server:v1.0.3","digest":"sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959"},{"image":"ghcr.io/github/serena-mcp-server:latest","digest":"sha256:bf343399e3725c45528f531a230f3a04521d4cdef29f9a5af6282ff0d3c393c5","pinned_image":"ghcr.io/github/serena-mcp-server:latest@sha256:bf343399e3725c45528f531a230f3a04521d4cdef29f9a5af6282ff0d3c393c5"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} # ___ _ _ # / _ \ | | (_) @@ -25,7 +25,7 @@ # # Resolved workflow manifest: # Imports: -# - shared/jqschema.md +# - ../skills/jqschema/SKILL.md # - shared/mcp/serena-go.md # - shared/mcp/serena.md # - shared/observability-otlp.md @@ -290,9 +290,9 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_3bb69d774fbb01e5_EOF' + cat << 'GH_AW_PROMPT_ecf4dc9a517c46f0_EOF' - GH_AW_PROMPT_3bb69d774fbb01e5_EOF + GH_AW_PROMPT_ecf4dc9a517c46f0_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" @@ -300,16 +300,16 @@ jobs: cat "${RUNNER_TEMP}/gh-aw/prompts/agentic_workflows_guide.md" cat "${RUNNER_TEMP}/gh-aw/prompts/cache_memory_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_3bb69d774fbb01e5_EOF' + cat << 'GH_AW_PROMPT_ecf4dc9a517c46f0_EOF' Tools: add_comment, create_pull_request, missing_tool, missing_data, noop - GH_AW_PROMPT_3bb69d774fbb01e5_EOF + GH_AW_PROMPT_ecf4dc9a517c46f0_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_create_pull_request.md" - cat << 'GH_AW_PROMPT_3bb69d774fbb01e5_EOF' + cat << 'GH_AW_PROMPT_ecf4dc9a517c46f0_EOF' - GH_AW_PROMPT_3bb69d774fbb01e5_EOF + GH_AW_PROMPT_ecf4dc9a517c46f0_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" - cat << 'GH_AW_PROMPT_3bb69d774fbb01e5_EOF' + cat << 'GH_AW_PROMPT_ecf4dc9a517c46f0_EOF' The following GitHub context information is available for this workflow: {{#if __GH_AW_GITHUB_ACTOR__ }} @@ -338,12 +338,12 @@ jobs: {{/if}} - GH_AW_PROMPT_3bb69d774fbb01e5_EOF + GH_AW_PROMPT_ecf4dc9a517c46f0_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" if [ "$GITHUB_EVENT_NAME" = "issue_comment" ] && [ -n "$GH_AW_IS_PR_COMMENT" ] || [ "$GITHUB_EVENT_NAME" = "pull_request_review_comment" ] || [ "$GITHUB_EVENT_NAME" = "pull_request_review" ]; then cat "${RUNNER_TEMP}/gh-aw/prompts/pr_context_prompt.md" fi - cat << 'GH_AW_PROMPT_3bb69d774fbb01e5_EOF' + cat << 'GH_AW_PROMPT_ecf4dc9a517c46f0_EOF' ## Serena Code Analysis @@ -376,13 +376,13 @@ jobs: 4. **Focus on the relevant language files** — ignore unrelated file types - {{#runtime-import .github/workflows/shared/jqschema.md}} + {{#runtime-import .github/skills/jqschema/SKILL.md}} {{#runtime-import .github/workflows/shared/mcp/serena-go.md}} {{#runtime-import .github/workflows/shared/reporting.md}} {{#runtime-import .github/workflows/shared/observability-otlp.md}} {{#runtime-import .github/workflows/shared/noop-reminder.md}} {{#runtime-import .github/workflows/cloclo.md}} - GH_AW_PROMPT_3bb69d774fbb01e5_EOF + GH_AW_PROMPT_ecf4dc9a517c46f0_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -584,7 +584,10 @@ jobs: env: GH_TOKEN: ${{ github.token }} - name: Setup jq utilities directory - run: "mkdir -p /tmp/gh-aw\ncat > /tmp/gh-aw/jqschema.sh << 'EOF'\n#!/usr/bin/env bash\n# jqschema.sh\njq -c '\ndef walk(f):\n . as $in |\n if type == \"object\" then\n reduce keys[] as $k ({}; . + {($k): ($in[$k] | walk(f))})\n elif type == \"array\" then\n if length == 0 then [] else [.[0] | walk(f)] end\n else\n type\n end;\nwalk(.)\n'\nEOF\nchmod +x /tmp/gh-aw/jqschema.sh\n" + run: | + mkdir -p /tmp/gh-aw + cp "$GITHUB_WORKSPACE/.github/skills/jqschema/jqschema.sh" /tmp/gh-aw/jqschema.sh + chmod +x /tmp/gh-aw/jqschema.sh # Cache memory file share configuration from frontmatter processed below - name: Create cache-memory directory @@ -702,9 +705,9 @@ jobs: 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_d9888d9d2884516e_EOF' + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_576530abb8320c80_EOF' {"add_comment":{"max":1},"create_pull_request":{"excluded_files":[".github/workflows/*.lock.yml"],"expires":48,"labels":["automation","cloclo"],"max":1,"max_patch_files":100,"max_patch_size":1024,"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","CLAUDE.md","AGENTS.md"],"protected_files_policy":"fallback-to-issue","title_prefix":"[cloclo] "},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} - GH_AW_SAFE_OUTPUTS_CONFIG_d9888d9d2884516e_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_576530abb8320c80_EOF - name: Generate Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -937,7 +940,7 @@ jobs: export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v /var/run/docker.sock:/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 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_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 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 GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -e GITHUB_AW_OTEL_TRACE_ID -e GITHUB_AW_OTEL_PARENT_SPAN_ID -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 ghcr.io/github/gh-aw-mcpg:v0.3.6' GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) - cat << GH_AW_MCP_CONFIG_320dfdaa683356e2_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_6cb18be545797135_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "agenticworkflows": { @@ -1027,7 +1030,7 @@ jobs: } } } - GH_AW_MCP_CONFIG_320dfdaa683356e2_EOF + GH_AW_MCP_CONFIG_6cb18be545797135_EOF - name: Mount MCP servers as CLIs id: mount-mcp-clis continue-on-error: true diff --git a/.github/workflows/cloclo.md b/.github/workflows/cloclo.md index 92dff5f5558..75fe83b78bd 100644 --- a/.github/workflows/cloclo.md +++ b/.github/workflows/cloclo.md @@ -17,7 +17,7 @@ engine: id: claude max-turns: 100 imports: - - shared/jqschema.md + - ../skills/jqschema/SKILL.md - shared/mcp/serena-go.md - shared/reporting.md - shared/observability-otlp.md diff --git a/.github/workflows/copilot-agent-analysis.lock.yml b/.github/workflows/copilot-agent-analysis.lock.yml index ba11518d2ce..c7781418b86 100644 --- a/.github/workflows/copilot-agent-analysis.lock.yml +++ b/.github/workflows/copilot-agent-analysis.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"3a7c34dc63959b3ad4da2b45014d0df5e4d7b55e4a1b354723c381a4da60c6dc","strict":true,"agent_id":"claude"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"995086cb29cb968ce3990239cfac468a7bb7a3371ff66c9d615f132c0c8485ac","strict":true,"agent_id":"claude"} # gh-aw-manifest: {"version":1,"secrets":["ANTHROPIC_API_KEY","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_ENDPOINT","GH_AW_OTEL_HEADERS","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"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":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41","digest":"sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41@sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41","digest":"sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41@sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41","digest":"sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41@sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.6","digest":"sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c"},{"image":"ghcr.io/github/github-mcp-server:v1.0.3","digest":"sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} # ___ _ _ # / _ \ | | (_) @@ -26,9 +26,9 @@ # # Resolved workflow manifest: # Imports: +# - ../skills/jqschema/SKILL.md # - shared/copilot-pr-data-fetch.md # - shared/daily-audit-discussion.md -# - shared/jqschema.md # - shared/observability-otlp.md # - shared/repo-memory-standard.md # - shared/reporting.md @@ -204,22 +204,22 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_c1a849f5dd4bea78_EOF' + cat << 'GH_AW_PROMPT_730eddda7ac122f3_EOF' - GH_AW_PROMPT_c1a849f5dd4bea78_EOF + GH_AW_PROMPT_730eddda7ac122f3_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/cache_memory_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/repo_memory_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_c1a849f5dd4bea78_EOF' + cat << 'GH_AW_PROMPT_730eddda7ac122f3_EOF' Tools: create_discussion, missing_tool, missing_data, noop - GH_AW_PROMPT_c1a849f5dd4bea78_EOF + GH_AW_PROMPT_730eddda7ac122f3_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" - cat << 'GH_AW_PROMPT_c1a849f5dd4bea78_EOF' + cat << 'GH_AW_PROMPT_730eddda7ac122f3_EOF' The following GitHub context information is available for this workflow: {{#if __GH_AW_GITHUB_ACTOR__ }} @@ -248,18 +248,18 @@ jobs: {{/if}} - GH_AW_PROMPT_c1a849f5dd4bea78_EOF + GH_AW_PROMPT_730eddda7ac122f3_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_c1a849f5dd4bea78_EOF' + cat << 'GH_AW_PROMPT_730eddda7ac122f3_EOF' {{#runtime-import .github/workflows/shared/copilot-pr-analysis-base.md}} {{#runtime-import .github/workflows/shared/observability-otlp.md}} {{#runtime-import .github/workflows/shared/reporting.md}} - {{#runtime-import .github/workflows/shared/jqschema.md}} + {{#runtime-import .github/skills/jqschema/SKILL.md}} {{#runtime-import .github/workflows/shared/copilot-pr-data-fetch.md}} {{#runtime-import .github/workflows/shared/noop-reminder.md}} {{#runtime-import .github/workflows/copilot-agent-analysis.md}} - GH_AW_PROMPT_c1a849f5dd4bea78_EOF + GH_AW_PROMPT_730eddda7ac122f3_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -418,7 +418,10 @@ jobs: env: GH_TOKEN: ${{ github.token }} - name: Setup jq utilities directory - run: "mkdir -p /tmp/gh-aw\ncat > /tmp/gh-aw/jqschema.sh << 'EOF'\n#!/usr/bin/env bash\n# jqschema.sh\njq -c '\ndef walk(f):\n . as $in |\n if type == \"object\" then\n reduce keys[] as $k ({}; . + {($k): ($in[$k] | walk(f))})\n elif type == \"array\" then\n if length == 0 then [] else [.[0] | walk(f)] end\n else\n type\n end;\nwalk(.)\n'\nEOF\nchmod +x /tmp/gh-aw/jqschema.sh\n" + run: | + mkdir -p /tmp/gh-aw + cp "$GITHUB_WORKSPACE/.github/skills/jqschema/jqschema.sh" /tmp/gh-aw/jqschema.sh + chmod +x /tmp/gh-aw/jqschema.sh - name: Install gh CLI run: | bash "${RUNNER_TEMP}/gh-aw/actions/install_gh_cli.sh" @@ -522,9 +525,9 @@ jobs: 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_f9bb70021cec309c_EOF' + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_91a9a42d6b609ad5_EOF' {"create_discussion":{"category":"audits","close_older_discussions":true,"expires":24,"fallback_to_issue":true,"max":1,"title_prefix":"[copilot-agent-analysis] "},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"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}]},"report_incomplete":{}} - GH_AW_SAFE_OUTPUTS_CONFIG_f9bb70021cec309c_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_91a9a42d6b609ad5_EOF - name: Generate Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -718,7 +721,7 @@ jobs: export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v /var/run/docker.sock:/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 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_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 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 GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -e GITHUB_AW_OTEL_TRACE_ID -e GITHUB_AW_OTEL_PARENT_SPAN_ID -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 ghcr.io/github/gh-aw-mcpg:v0.3.6' GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) - cat << GH_AW_MCP_CONFIG_9ddf7081554e6901_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_bc1ccfde6242b748_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "github": { @@ -764,7 +767,7 @@ jobs: } } } - GH_AW_MCP_CONFIG_9ddf7081554e6901_EOF + GH_AW_MCP_CONFIG_bc1ccfde6242b748_EOF - name: Mount MCP servers as CLIs id: mount-mcp-clis continue-on-error: true diff --git a/.github/workflows/copilot-opt.lock.yml b/.github/workflows/copilot-opt.lock.yml index 8cdba534138..59dbd611953 100644 --- a/.github/workflows/copilot-opt.lock.yml +++ b/.github/workflows/copilot-opt.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"c7c2d6ae6c748beed0cdcf646e5bc5b24eff94789ad12bd8a32bcfc4a2fd1e41","strict":true,"agent_id":"copilot"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"956c6e68343956112b1f1986a252aab2a8197f20b93cb1e1c853f0317605de09","strict":true,"agent_id":"copilot"} # gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_ENDPOINT","GH_AW_OTEL_HEADERS","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"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":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41","digest":"sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41@sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41","digest":"sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41@sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0"},{"image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.41","digest":"sha256:62171f2fa508667b8b0a9e096f826983f312e3da0ce894f80c0f83a875af60fe","pinned_image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.41@sha256:62171f2fa508667b8b0a9e096f826983f312e3da0ce894f80c0f83a875af60fe"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41","digest":"sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41@sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.6","digest":"sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c"},{"image":"ghcr.io/github/github-mcp-server:v1.0.3","digest":"sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} # ___ _ _ # / _ \ | | (_) @@ -26,8 +26,8 @@ # # Resolved workflow manifest: # Imports: +# - ../skills/jqschema/SKILL.md # - shared/copilot-pr-data-fetch.md -# - shared/jqschema.md # - shared/copilot-session-data-fetch.md # - shared/observability-otlp.md # - shared/reporting.md @@ -201,21 +201,21 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_6c65c9a985cebc9b_EOF' + cat << 'GH_AW_PROMPT_c2f435548a37f9c7_EOF' - GH_AW_PROMPT_6c65c9a985cebc9b_EOF + GH_AW_PROMPT_c2f435548a37f9c7_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/cache_memory_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_6c65c9a985cebc9b_EOF' + cat << 'GH_AW_PROMPT_c2f435548a37f9c7_EOF' Tools: create_issue(max:3), missing_tool, missing_data, noop - GH_AW_PROMPT_6c65c9a985cebc9b_EOF + GH_AW_PROMPT_c2f435548a37f9c7_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" - cat << 'GH_AW_PROMPT_6c65c9a985cebc9b_EOF' + cat << 'GH_AW_PROMPT_c2f435548a37f9c7_EOF' The following GitHub context information is available for this workflow: {{#if __GH_AW_GITHUB_ACTOR__ }} @@ -244,18 +244,18 @@ jobs: {{/if}} - GH_AW_PROMPT_6c65c9a985cebc9b_EOF + GH_AW_PROMPT_c2f435548a37f9c7_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/cli_proxy_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_6c65c9a985cebc9b_EOF' + cat << 'GH_AW_PROMPT_c2f435548a37f9c7_EOF' - {{#runtime-import .github/workflows/shared/jqschema.md}} + {{#runtime-import .github/skills/jqschema/SKILL.md}} {{#runtime-import .github/workflows/shared/copilot-session-data-fetch.md}} {{#runtime-import .github/workflows/shared/copilot-pr-data-fetch.md}} {{#runtime-import .github/workflows/shared/reporting.md}} {{#runtime-import .github/workflows/shared/observability-otlp.md}} {{#runtime-import .github/workflows/shared/noop-reminder.md}} {{#runtime-import .github/workflows/copilot-opt.md}} - GH_AW_PROMPT_6c65c9a985cebc9b_EOF + GH_AW_PROMPT_c2f435548a37f9c7_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -405,7 +405,10 @@ jobs: env: GH_TOKEN: ${{ github.token }} - name: Setup jq utilities directory - run: "mkdir -p /tmp/gh-aw\ncat > /tmp/gh-aw/jqschema.sh << 'EOF'\n#!/usr/bin/env bash\n# jqschema.sh\njq -c '\ndef walk(f):\n . as $in |\n if type == \"object\" then\n reduce keys[] as $k ({}; . + {($k): ($in[$k] | walk(f))})\n elif type == \"array\" then\n if length == 0 then [] else [.[0] | walk(f)] end\n else\n type\n end;\nwalk(.)\n'\nEOF\nchmod +x /tmp/gh-aw/jqschema.sh\n" + run: | + mkdir -p /tmp/gh-aw + cp "$GITHUB_WORKSPACE/.github/skills/jqschema/jqschema.sh" /tmp/gh-aw/jqschema.sh + chmod +x /tmp/gh-aw/jqschema.sh - name: Install gh CLI run: | bash "${RUNNER_TEMP}/gh-aw/actions/install_gh_cli.sh" @@ -504,9 +507,9 @@ jobs: 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_a79a2db96d293a5f_EOF' + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_ecb3e3bac9d64337_EOF' {"create_issue":{"close_older_issues":true,"labels":["copilot-opt","optimization","cookie"],"max":3,"title_prefix":"[copilot-opt] "},"create_report_incomplete_issue":{},"mentions":{"enabled":false},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} - GH_AW_SAFE_OUTPUTS_CONFIG_a79a2db96d293a5f_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_ecb3e3bac9d64337_EOF - name: Generate Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -708,7 +711,7 @@ jobs: mkdir -p /home/runner/.copilot GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) - cat << GH_AW_MCP_CONFIG_834c4dbef94aac46_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_3526674f05acf7c6_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "safeoutputs": { @@ -739,7 +742,7 @@ jobs: } } } - GH_AW_MCP_CONFIG_834c4dbef94aac46_EOF + GH_AW_MCP_CONFIG_3526674f05acf7c6_EOF - name: Mount MCP servers as CLIs id: mount-mcp-clis continue-on-error: true diff --git a/.github/workflows/copilot-opt.md b/.github/workflows/copilot-opt.md index d2be7817e76..5d29a62786d 100644 --- a/.github/workflows/copilot-opt.md +++ b/.github/workflows/copilot-opt.md @@ -38,7 +38,7 @@ safe-outputs: title-prefix: "[copilot-opt] " close-older-issues: true imports: - - shared/jqschema.md + - ../skills/jqschema/SKILL.md - shared/copilot-session-data-fetch.md - shared/copilot-pr-data-fetch.md - shared/reporting.md diff --git a/.github/workflows/copilot-pr-merged-report.lock.yml b/.github/workflows/copilot-pr-merged-report.lock.yml index d3a4f2f7f58..8e3a6a5ea9e 100644 --- a/.github/workflows/copilot-pr-merged-report.lock.yml +++ b/.github/workflows/copilot-pr-merged-report.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"ae704c71cc3592379e0f93e6216a80e8e924f4af7526b2ece5945eefff1dbf96","agent_id":"copilot"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"5bc8ad9b2e91af98cd91f438f95a294cfe104ae17145185ed2e47b7b48d48e9f","agent_id":"copilot"} # gh-aw-manifest: {"version":1,"secrets":["GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_ENDPOINT","GH_AW_OTEL_HEADERS","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"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":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41","digest":"sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41@sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41","digest":"sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41@sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41","digest":"sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41@sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.6","digest":"sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} # ___ _ _ # / _ \ | | (_) @@ -26,10 +26,10 @@ # # Resolved workflow manifest: # Imports: +# - ../skills/jqschema/SKILL.md # - shared/copilot-pr-data-fetch.md # - shared/daily-audit-discussion.md # - shared/gh.md -# - shared/jqschema.md # - shared/observability-otlp.md # - shared/reporting.md # - shared/copilot-pr-analysis-base.md @@ -188,31 +188,31 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_d1825dd664ed2b4b_EOF' + cat << 'GH_AW_PROMPT_1c54514a2e632903_EOF' - GH_AW_PROMPT_d1825dd664ed2b4b_EOF + GH_AW_PROMPT_1c54514a2e632903_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/cache_memory_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_d1825dd664ed2b4b_EOF' + cat << 'GH_AW_PROMPT_1c54514a2e632903_EOF' Tools: create_discussion, missing_tool, missing_data, noop - GH_AW_PROMPT_d1825dd664ed2b4b_EOF + GH_AW_PROMPT_1c54514a2e632903_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" - cat << 'GH_AW_PROMPT_d1825dd664ed2b4b_EOF' + cat << 'GH_AW_PROMPT_1c54514a2e632903_EOF' {{#runtime-import .github/workflows/shared/gh.md}} {{#runtime-import .github/workflows/shared/copilot-pr-analysis-base.md}} {{#runtime-import .github/workflows/shared/observability-otlp.md}} {{#runtime-import .github/workflows/shared/reporting.md}} - {{#runtime-import .github/workflows/shared/jqschema.md}} + {{#runtime-import .github/skills/jqschema/SKILL.md}} {{#runtime-import .github/workflows/shared/copilot-pr-data-fetch.md}} {{#runtime-import .github/workflows/shared/noop-reminder.md}} {{#runtime-import .github/workflows/copilot-pr-merged-report.md}} - GH_AW_PROMPT_d1825dd664ed2b4b_EOF + GH_AW_PROMPT_1c54514a2e632903_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -353,7 +353,10 @@ jobs: env: GH_TOKEN: ${{ github.token }} - name: Setup jq utilities directory - run: "mkdir -p /tmp/gh-aw\ncat > /tmp/gh-aw/jqschema.sh << 'EOF'\n#!/usr/bin/env bash\n# jqschema.sh\njq -c '\ndef walk(f):\n . as $in |\n if type == \"object\" then\n reduce keys[] as $k ({}; . + {($k): ($in[$k] | walk(f))})\n elif type == \"array\" then\n if length == 0 then [] else [.[0] | walk(f)] end\n else\n type\n end;\nwalk(.)\n'\nEOF\nchmod +x /tmp/gh-aw/jqschema.sh\n" + run: | + mkdir -p /tmp/gh-aw + cp "$GITHUB_WORKSPACE/.github/skills/jqschema/jqschema.sh" /tmp/gh-aw/jqschema.sh + chmod +x /tmp/gh-aw/jqschema.sh - name: Install gh CLI run: | bash "${RUNNER_TEMP}/gh-aw/actions/install_gh_cli.sh" @@ -434,9 +437,9 @@ jobs: 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_8e41c6cf3e63f0ad_EOF' + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_ae70993d164056cb_EOF' {"create_discussion":{"category":"audits","close_older_discussions":true,"expires":24,"fallback_to_issue":true,"max":1,"title_prefix":"[copilot-pr-merged-report] "},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} - GH_AW_SAFE_OUTPUTS_CONFIG_8e41c6cf3e63f0ad_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_ae70993d164056cb_EOF - name: Generate Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -599,7 +602,7 @@ jobs: - name: Write MCP Scripts Config run: | mkdir -p "${RUNNER_TEMP}/gh-aw/mcp-scripts/logs" - cat > "${RUNNER_TEMP}/gh-aw/mcp-scripts/tools.json" << 'GH_AW_MCP_SCRIPTS_TOOLS_95292c23eb5d8318_EOF' + cat > "${RUNNER_TEMP}/gh-aw/mcp-scripts/tools.json" << 'GH_AW_MCP_SCRIPTS_TOOLS_93b2f7aca95b9b23_EOF' { "serverName": "mcpscripts", "version": "1.0.0", @@ -629,8 +632,8 @@ jobs: } ] } - GH_AW_MCP_SCRIPTS_TOOLS_95292c23eb5d8318_EOF - cat > "${RUNNER_TEMP}/gh-aw/mcp-scripts/mcp-server.cjs" << 'GH_AW_MCP_SCRIPTS_SERVER_48987cc3d52ac9ac_EOF' + GH_AW_MCP_SCRIPTS_TOOLS_93b2f7aca95b9b23_EOF + cat > "${RUNNER_TEMP}/gh-aw/mcp-scripts/mcp-server.cjs" << 'GH_AW_MCP_SCRIPTS_SERVER_64b8c1338d01e062_EOF' const path = require("path"); const { startHttpServer } = require("./mcp_scripts_mcp_server_http.cjs"); const configPath = path.join(__dirname, "tools.json"); @@ -644,12 +647,12 @@ jobs: console.error("Failed to start mcp-scripts HTTP server:", error); process.exit(1); }); - GH_AW_MCP_SCRIPTS_SERVER_48987cc3d52ac9ac_EOF + GH_AW_MCP_SCRIPTS_SERVER_64b8c1338d01e062_EOF chmod +x "${RUNNER_TEMP}/gh-aw/mcp-scripts/mcp-server.cjs" - name: Write MCP Scripts Tool Files run: | - cat > "${RUNNER_TEMP}/gh-aw/mcp-scripts/gh.sh" << 'GH_AW_MCP_SCRIPTS_SH_GH_ea20a3f8f0367490_EOF' + cat > "${RUNNER_TEMP}/gh-aw/mcp-scripts/gh.sh" << 'GH_AW_MCP_SCRIPTS_SH_GH_879cb8072f8dd6ad_EOF' #!/bin/bash # Auto-generated mcp-script tool: gh # Execute any gh CLI command. This tool is accessible as 'mcpscripts-gh'. Provide the full command after 'gh' (e.g., args: 'pr list --limit 5'). The tool will run: gh . Use single quotes ' for complex args to avoid shell interpretation issues. @@ -661,7 +664,7 @@ jobs: GH_TOKEN="$GH_AW_GH_TOKEN" gh $INPUT_ARGS - GH_AW_MCP_SCRIPTS_SH_GH_ea20a3f8f0367490_EOF + GH_AW_MCP_SCRIPTS_SH_GH_879cb8072f8dd6ad_EOF chmod +x "${RUNNER_TEMP}/gh-aw/mcp-scripts/gh.sh" - name: Generate MCP Scripts Server Config @@ -734,7 +737,7 @@ jobs: mkdir -p /home/runner/.copilot GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) - cat << GH_AW_MCP_CONFIG_ec9bf980c78f2602_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_5864554b0c515fcc_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "mcpscripts": { @@ -765,7 +768,7 @@ jobs: } } } - GH_AW_MCP_CONFIG_ec9bf980c78f2602_EOF + GH_AW_MCP_CONFIG_5864554b0c515fcc_EOF - name: Mount MCP servers as CLIs id: mount-mcp-clis continue-on-error: true diff --git a/.github/workflows/copilot-pr-nlp-analysis.lock.yml b/.github/workflows/copilot-pr-nlp-analysis.lock.yml index fa221a5c2b4..7088f337d57 100644 --- a/.github/workflows/copilot-pr-nlp-analysis.lock.yml +++ b/.github/workflows/copilot-pr-nlp-analysis.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"e680d07d85ca99dc6dc3ee4be59cdb3c9d1c49e7bf28efa85f1641c408445d8c","strict":true,"agent_id":"copilot"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"b903d2f1ca087d19dcf72e650d21fc3202c06244f547fd4e4e6dac9bc00b7c53","strict":true,"agent_id":"copilot"} # gh-aw-manifest: {"version":1,"secrets":["GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_ENDPOINT","GH_AW_OTEL_HEADERS","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"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":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/setup-python","sha":"a309ff8b426b58ec0e2a45f0f869d46889d02405","version":"v6.2.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41","digest":"sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41@sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41","digest":"sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41@sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41","digest":"sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41@sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.6","digest":"sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c"},{"image":"ghcr.io/github/github-mcp-server:v1.0.3","digest":"sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} # ___ _ _ # / _ \ | | (_) @@ -26,9 +26,9 @@ # # Resolved workflow manifest: # Imports: +# - ../skills/jqschema/SKILL.md # - shared/copilot-pr-data-fetch.md # - shared/daily-audit-discussion.md -# - shared/jqschema.md # - shared/observability-otlp.md # - shared/python-dataviz.md # - shared/python-nlp.md @@ -200,24 +200,24 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_8606fe4617a8c3f3_EOF' + cat << 'GH_AW_PROMPT_d884817c907b64ae_EOF' - GH_AW_PROMPT_8606fe4617a8c3f3_EOF + GH_AW_PROMPT_d884817c907b64ae_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/cache_memory_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/repo_memory_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_8606fe4617a8c3f3_EOF' + cat << 'GH_AW_PROMPT_d884817c907b64ae_EOF' Tools: create_discussion, upload_asset(max:5), missing_tool, missing_data, noop upload_asset: provide a file path; returns a URL; assets are published after the workflow completes (safeoutputs). - GH_AW_PROMPT_8606fe4617a8c3f3_EOF + GH_AW_PROMPT_d884817c907b64ae_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" - cat << 'GH_AW_PROMPT_8606fe4617a8c3f3_EOF' + cat << 'GH_AW_PROMPT_d884817c907b64ae_EOF' The following GitHub context information is available for this workflow: {{#if __GH_AW_GITHUB_ACTOR__ }} @@ -246,20 +246,20 @@ jobs: {{/if}} - GH_AW_PROMPT_8606fe4617a8c3f3_EOF + GH_AW_PROMPT_d884817c907b64ae_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_8606fe4617a8c3f3_EOF' + cat << 'GH_AW_PROMPT_d884817c907b64ae_EOF' {{#runtime-import .github/workflows/shared/copilot-pr-analysis-base.md}} {{#runtime-import .github/workflows/shared/python-dataviz.md}} {{#runtime-import .github/workflows/shared/python-nlp.md}} {{#runtime-import .github/workflows/shared/reporting.md}} {{#runtime-import .github/workflows/shared/observability-otlp.md}} - {{#runtime-import .github/workflows/shared/jqschema.md}} + {{#runtime-import .github/skills/jqschema/SKILL.md}} {{#runtime-import .github/workflows/shared/copilot-pr-data-fetch.md}} {{#runtime-import .github/workflows/shared/noop-reminder.md}} {{#runtime-import .github/workflows/copilot-pr-nlp-analysis.md}} - GH_AW_PROMPT_8606fe4617a8c3f3_EOF + GH_AW_PROMPT_d884817c907b64ae_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -444,7 +444,10 @@ jobs: - name: Setup Python NLP environment run: "mkdir -p /tmp/gh-aw/python/{data,charts,artifacts}\n# Create a virtual environment for proper package isolation (avoids --break-system-packages)\nif [ ! -d /tmp/gh-aw/venv ]; then\n python3 -m venv /tmp/gh-aw/venv\nfi\necho \"/tmp/gh-aw/venv/bin\" >> \"$GITHUB_PATH\"\n/tmp/gh-aw/venv/bin/pip install --quiet nltk scikit-learn textblob wordcloud\n\n# Download required NLTK corpora\n/tmp/gh-aw/venv/bin/python3 -c \"\nimport nltk\nfor corpus in ['punkt_tab', 'stopwords', 'vader_lexicon', 'averaged_perceptron_tagger_eng']:\n nltk.download(corpus, quiet=True)\nprint('NLTK corpora ready')\n\"\n\n/tmp/gh-aw/venv/bin/python3 -c \"import sklearn; print(f'scikit-learn {sklearn.__version__}')\"\n" - name: Setup jq utilities directory - run: "mkdir -p /tmp/gh-aw\ncat > /tmp/gh-aw/jqschema.sh << 'EOF'\n#!/usr/bin/env bash\n# jqschema.sh\njq -c '\ndef walk(f):\n . as $in |\n if type == \"object\" then\n reduce keys[] as $k ({}; . + {($k): ($in[$k] | walk(f))})\n elif type == \"array\" then\n if length == 0 then [] else [.[0] | walk(f)] end\n else\n type\n end;\nwalk(.)\n'\nEOF\nchmod +x /tmp/gh-aw/jqschema.sh\n" + run: | + mkdir -p /tmp/gh-aw + cp "$GITHUB_WORKSPACE/.github/skills/jqschema/jqschema.sh" /tmp/gh-aw/jqschema.sh + chmod +x /tmp/gh-aw/jqschema.sh - name: Install gh CLI run: | bash "${RUNNER_TEMP}/gh-aw/actions/install_gh_cli.sh" @@ -552,9 +555,9 @@ jobs: 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_07cb27f9768f0b1e_EOF + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << GH_AW_SAFE_OUTPUTS_CONFIG_e04404dfdee09ceb_EOF {"create_discussion":{"category":"audits","close_older_discussions":true,"expires":24,"fallback_to_issue":true,"max":1,"title_prefix":"[nlp-analysis] "},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"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}]},"report_incomplete":{},"upload_asset":{"allowed-exts":[".png",".jpg",".jpeg",".svg"],"branch":"assets/${GITHUB_WORKFLOW}","max":5,"max-size":10240}} - GH_AW_SAFE_OUTPUTS_CONFIG_07cb27f9768f0b1e_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_e04404dfdee09ceb_EOF - name: Generate Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -762,7 +765,7 @@ jobs: mkdir -p /home/runner/.copilot GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) - cat << GH_AW_MCP_CONFIG_c5ecfc3538b5d2e9_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_bb2086e4e1cf8527_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "github": { @@ -809,7 +812,7 @@ jobs: } } } - GH_AW_MCP_CONFIG_c5ecfc3538b5d2e9_EOF + GH_AW_MCP_CONFIG_bb2086e4e1cf8527_EOF - name: Mount MCP servers as CLIs id: mount-mcp-clis continue-on-error: true diff --git a/.github/workflows/copilot-pr-prompt-analysis.lock.yml b/.github/workflows/copilot-pr-prompt-analysis.lock.yml index 2246195dc59..1bb8a61c0fd 100644 --- a/.github/workflows/copilot-pr-prompt-analysis.lock.yml +++ b/.github/workflows/copilot-pr-prompt-analysis.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"de8678d78d372fc79f77f85aa0136ad2b76a6b7f04a8773a248f28960a2a52d6","strict":true,"agent_id":"copilot"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"4e27933d10af6b3636135a7a3ac7c4672e57414826323ca9c4948c37283d517d","strict":true,"agent_id":"copilot"} # gh-aw-manifest: {"version":1,"secrets":["GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_ENDPOINT","GH_AW_OTEL_HEADERS","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"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":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41","digest":"sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41@sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41","digest":"sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41@sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41","digest":"sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41@sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.6","digest":"sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c"},{"image":"ghcr.io/github/github-mcp-server:v1.0.3","digest":"sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} # ___ _ _ # / _ \ | | (_) @@ -26,9 +26,9 @@ # # Resolved workflow manifest: # Imports: +# - ../skills/jqschema/SKILL.md # - shared/copilot-pr-data-fetch.md # - shared/daily-audit-discussion.md -# - shared/jqschema.md # - shared/observability-otlp.md # - shared/repo-memory-standard.md # - shared/reporting.md @@ -197,22 +197,22 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_ffa4c570c65d54ac_EOF' + cat << 'GH_AW_PROMPT_e328b60a4eb8058f_EOF' - GH_AW_PROMPT_ffa4c570c65d54ac_EOF + GH_AW_PROMPT_e328b60a4eb8058f_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/cache_memory_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/repo_memory_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_ffa4c570c65d54ac_EOF' + cat << 'GH_AW_PROMPT_e328b60a4eb8058f_EOF' Tools: create_discussion, missing_tool, missing_data, noop - GH_AW_PROMPT_ffa4c570c65d54ac_EOF + GH_AW_PROMPT_e328b60a4eb8058f_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" - cat << 'GH_AW_PROMPT_ffa4c570c65d54ac_EOF' + cat << 'GH_AW_PROMPT_e328b60a4eb8058f_EOF' The following GitHub context information is available for this workflow: {{#if __GH_AW_GITHUB_ACTOR__ }} @@ -241,18 +241,18 @@ jobs: {{/if}} - GH_AW_PROMPT_ffa4c570c65d54ac_EOF + GH_AW_PROMPT_e328b60a4eb8058f_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_ffa4c570c65d54ac_EOF' + cat << 'GH_AW_PROMPT_e328b60a4eb8058f_EOF' {{#runtime-import .github/workflows/shared/copilot-pr-analysis-base.md}} {{#runtime-import .github/workflows/shared/observability-otlp.md}} {{#runtime-import .github/workflows/shared/reporting.md}} - {{#runtime-import .github/workflows/shared/jqschema.md}} + {{#runtime-import .github/skills/jqschema/SKILL.md}} {{#runtime-import .github/workflows/shared/copilot-pr-data-fetch.md}} {{#runtime-import .github/workflows/shared/noop-reminder.md}} {{#runtime-import .github/workflows/copilot-pr-prompt-analysis.md}} - GH_AW_PROMPT_ffa4c570c65d54ac_EOF + GH_AW_PROMPT_e328b60a4eb8058f_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -417,7 +417,10 @@ jobs: env: GH_TOKEN: ${{ github.token }} - name: Setup jq utilities directory - run: "mkdir -p /tmp/gh-aw\ncat > /tmp/gh-aw/jqschema.sh << 'EOF'\n#!/usr/bin/env bash\n# jqschema.sh\njq -c '\ndef walk(f):\n . as $in |\n if type == \"object\" then\n reduce keys[] as $k ({}; . + {($k): ($in[$k] | walk(f))})\n elif type == \"array\" then\n if length == 0 then [] else [.[0] | walk(f)] end\n else\n type\n end;\nwalk(.)\n'\nEOF\nchmod +x /tmp/gh-aw/jqschema.sh\n" + run: | + mkdir -p /tmp/gh-aw + cp "$GITHUB_WORKSPACE/.github/skills/jqschema/jqschema.sh" /tmp/gh-aw/jqschema.sh + chmod +x /tmp/gh-aw/jqschema.sh - name: Install gh CLI run: | bash "${RUNNER_TEMP}/gh-aw/actions/install_gh_cli.sh" @@ -518,9 +521,9 @@ jobs: 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_6ad5288ac8493a62_EOF' + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_9fcbecb87eb57b01_EOF' {"create_discussion":{"category":"audits","close_older_discussions":true,"expires":24,"fallback_to_issue":true,"max":1,"title_prefix":"[prompt-analysis] "},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"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}]},"report_incomplete":{}} - GH_AW_SAFE_OUTPUTS_CONFIG_6ad5288ac8493a62_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_9fcbecb87eb57b01_EOF - name: Generate Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -715,7 +718,7 @@ jobs: mkdir -p /home/runner/.copilot GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) - cat << GH_AW_MCP_CONFIG_ef669893c51243d9_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_11ca3361b29bf4c1_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "github": { @@ -762,7 +765,7 @@ jobs: } } } - GH_AW_MCP_CONFIG_ef669893c51243d9_EOF + GH_AW_MCP_CONFIG_11ca3361b29bf4c1_EOF - name: Mount MCP servers as CLIs id: mount-mcp-clis continue-on-error: true diff --git a/.github/workflows/copilot-session-insights.lock.yml b/.github/workflows/copilot-session-insights.lock.yml index eb600da5d51..d63678a7c95 100644 --- a/.github/workflows/copilot-session-insights.lock.yml +++ b/.github/workflows/copilot-session-insights.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"e3ddf222aa674527da3e52613dfbfe29d6093b8a998ccc787e77b9ba0daac6b5","strict":true,"agent_id":"claude"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"e001379556a9418376151a5d6511719c04ce12a61c5f0b2a50d84d2769b81ce2","strict":true,"agent_id":"claude"} # gh-aw-manifest: {"version":1,"secrets":["ANTHROPIC_API_KEY","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_ENDPOINT","GH_AW_OTEL_HEADERS","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"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":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/setup-python","sha":"a309ff8b426b58ec0e2a45f0f869d46889d02405","version":"v6.2.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41","digest":"sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41@sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41","digest":"sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41@sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0"},{"image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.41","digest":"sha256:62171f2fa508667b8b0a9e096f826983f312e3da0ce894f80c0f83a875af60fe","pinned_image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.41@sha256:62171f2fa508667b8b0a9e096f826983f312e3da0ce894f80c0f83a875af60fe"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41","digest":"sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41@sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.6","digest":"sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c"},{"image":"ghcr.io/github/github-mcp-server:v1.0.3","digest":"sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} # ___ _ _ # / _ \ | | (_) @@ -26,9 +26,9 @@ # # Resolved workflow manifest: # Imports: -# - shared/daily-audit-discussion.md -# - shared/jqschema.md +# - ../skills/jqschema/SKILL.md # - shared/copilot-session-data-fetch.md +# - shared/daily-audit-discussion.md # - shared/observability-otlp.md # - shared/python-dataviz.md # - shared/repo-memory-standard.md @@ -209,24 +209,24 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_26e83b4824f840f8_EOF' + cat << 'GH_AW_PROMPT_c58b23f31246885a_EOF' - GH_AW_PROMPT_26e83b4824f840f8_EOF + GH_AW_PROMPT_c58b23f31246885a_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/cache_memory_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/repo_memory_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_26e83b4824f840f8_EOF' + cat << 'GH_AW_PROMPT_c58b23f31246885a_EOF' Tools: create_discussion, upload_asset(max:5), missing_tool, missing_data, noop upload_asset: provide a file path; returns a URL; assets are published after the workflow completes (safeoutputs). - GH_AW_PROMPT_26e83b4824f840f8_EOF + GH_AW_PROMPT_c58b23f31246885a_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" - cat << 'GH_AW_PROMPT_26e83b4824f840f8_EOF' + cat << 'GH_AW_PROMPT_c58b23f31246885a_EOF' The following GitHub context information is available for this workflow: {{#if __GH_AW_GITHUB_ACTOR__ }} @@ -255,11 +255,11 @@ jobs: {{/if}} - GH_AW_PROMPT_26e83b4824f840f8_EOF + GH_AW_PROMPT_c58b23f31246885a_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/cli_proxy_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_26e83b4824f840f8_EOF' + cat << 'GH_AW_PROMPT_c58b23f31246885a_EOF' - {{#runtime-import .github/workflows/shared/jqschema.md}} + {{#runtime-import .github/skills/jqschema/SKILL.md}} {{#runtime-import .github/workflows/shared/copilot-session-data-fetch.md}} {{#runtime-import .github/workflows/shared/session-analysis-charts.md}} {{#runtime-import .github/workflows/shared/session-analysis-strategies.md}} @@ -268,7 +268,7 @@ jobs: {{#runtime-import .github/workflows/shared/python-dataviz.md}} {{#runtime-import .github/workflows/shared/noop-reminder.md}} {{#runtime-import .github/workflows/copilot-session-insights.md}} - GH_AW_PROMPT_26e83b4824f840f8_EOF + GH_AW_PROMPT_c58b23f31246885a_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -435,7 +435,10 @@ jobs: env: GH_TOKEN: ${{ github.token }} - name: Setup jq utilities directory - run: "mkdir -p /tmp/gh-aw\ncat > /tmp/gh-aw/jqschema.sh << 'EOF'\n#!/usr/bin/env bash\n# jqschema.sh\njq -c '\ndef walk(f):\n . as $in |\n if type == \"object\" then\n reduce keys[] as $k ({}; . + {($k): ($in[$k] | walk(f))})\n elif type == \"array\" then\n if length == 0 then [] else [.[0] | walk(f)] end\n else\n type\n end;\nwalk(.)\n'\nEOF\nchmod +x /tmp/gh-aw/jqschema.sh\n" + run: | + mkdir -p /tmp/gh-aw + cp "$GITHUB_WORKSPACE/.github/skills/jqschema/jqschema.sh" /tmp/gh-aw/jqschema.sh + chmod +x /tmp/gh-aw/jqschema.sh - name: Install gh CLI run: | bash "${RUNNER_TEMP}/gh-aw/actions/install_gh_cli.sh" @@ -555,9 +558,9 @@ jobs: 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_06486e815d77e58e_EOF + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << GH_AW_SAFE_OUTPUTS_CONFIG_e7a235924990539f_EOF {"create_discussion":{"category":"audits","close_older_discussions":true,"expires":24,"fallback_to_issue":true,"max":1,"title_prefix":"[copilot-session-insights] "},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"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}]},"report_incomplete":{},"upload_asset":{"allowed-exts":[".png",".jpg",".jpeg",".svg"],"branch":"assets/${GITHUB_WORKFLOW}","max":5,"max-size":10240}} - GH_AW_SAFE_OUTPUTS_CONFIG_06486e815d77e58e_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_e7a235924990539f_EOF - name: Generate Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -761,7 +764,7 @@ jobs: export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v /var/run/docker.sock:/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 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_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 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 GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -e GITHUB_AW_OTEL_TRACE_ID -e GITHUB_AW_OTEL_PARENT_SPAN_ID -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 ghcr.io/github/gh-aw-mcpg:v0.3.6' GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) - cat << GH_AW_MCP_CONFIG_b3a495f2b455d7a8_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_7254448b52fe8ab9_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "safeoutputs": { @@ -792,7 +795,7 @@ jobs: } } } - GH_AW_MCP_CONFIG_b3a495f2b455d7a8_EOF + GH_AW_MCP_CONFIG_7254448b52fe8ab9_EOF - name: Mount MCP servers as CLIs id: mount-mcp-clis continue-on-error: true diff --git a/.github/workflows/copilot-session-insights.md b/.github/workflows/copilot-session-insights.md index 069d5381e17..5481fcd481d 100644 --- a/.github/workflows/copilot-session-insights.md +++ b/.github/workflows/copilot-session-insights.md @@ -45,7 +45,7 @@ imports: with: branch-name: "memory/session-insights" description: "Historical session analysis data" - - shared/jqschema.md # Must come before copilot-session-data-fetch.md (dependency) + - ../skills/jqschema/SKILL.md # Must come before copilot-session-data-fetch.md (dependency) - shared/copilot-session-data-fetch.md - shared/session-analysis-charts.md - shared/session-analysis-strategies.md diff --git a/.github/workflows/daily-issues-report.lock.yml b/.github/workflows/daily-issues-report.lock.yml index 1e24a3c58fe..d05919242cc 100644 --- a/.github/workflows/daily-issues-report.lock.yml +++ b/.github/workflows/daily-issues-report.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"1fa97df3113da2734ca63206eddcd53d89509104d4f538ea37a6a75d6dff43a8","strict":true,"agent_id":"copilot"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"7d9053b732081f0394acdfc484dd973fbf01edb4ceed65b5b352eea4112863c2","strict":true,"agent_id":"copilot"} # gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_ENDPOINT","GH_AW_OTEL_HEADERS","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"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":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/setup-python","sha":"a309ff8b426b58ec0e2a45f0f869d46889d02405","version":"v6.2.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41","digest":"sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41@sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41","digest":"sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41@sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0"},{"image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.41","digest":"sha256:62171f2fa508667b8b0a9e096f826983f312e3da0ce894f80c0f83a875af60fe","pinned_image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.41@sha256:62171f2fa508667b8b0a9e096f826983f312e3da0ce894f80c0f83a875af60fe"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41","digest":"sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41@sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.6","digest":"sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c"},{"image":"ghcr.io/github/github-mcp-server:v1.0.3","digest":"sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} # ___ _ _ # / _ \ | | (_) @@ -26,10 +26,10 @@ # # Resolved workflow manifest: # Imports: +# - ../skills/jqschema/SKILL.md # - shared/daily-audit-discussion.md # - shared/github-guard-policy.md # - shared/issues-data-fetch.md -# - shared/jqschema.md # - shared/observability-otlp.md # - shared/python-dataviz.md # - shared/python-nlp.md @@ -242,23 +242,23 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_6e7b51b8c77d15b1_EOF' + cat << 'GH_AW_PROMPT_728af52b5157ef07_EOF' - GH_AW_PROMPT_6e7b51b8c77d15b1_EOF + GH_AW_PROMPT_728af52b5157ef07_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/cache_memory_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_6e7b51b8c77d15b1_EOF' + cat << 'GH_AW_PROMPT_728af52b5157ef07_EOF' Tools: create_discussion, upload_asset(max:5), missing_tool, missing_data, noop upload_asset: provide a file path; returns a URL; assets are published after the workflow completes (safeoutputs). - GH_AW_PROMPT_6e7b51b8c77d15b1_EOF + GH_AW_PROMPT_728af52b5157ef07_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" - cat << 'GH_AW_PROMPT_6e7b51b8c77d15b1_EOF' + cat << 'GH_AW_PROMPT_728af52b5157ef07_EOF' The following GitHub context information is available for this workflow: {{#if __GH_AW_GITHUB_ACTOR__ }} @@ -287,12 +287,12 @@ jobs: {{/if}} - GH_AW_PROMPT_6e7b51b8c77d15b1_EOF + GH_AW_PROMPT_728af52b5157ef07_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/cli_proxy_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_6e7b51b8c77d15b1_EOF' + cat << 'GH_AW_PROMPT_728af52b5157ef07_EOF' {{#runtime-import .github/workflows/shared/github-guard-policy.md}} - {{#runtime-import .github/workflows/shared/jqschema.md}} + {{#runtime-import .github/skills/jqschema/SKILL.md}} {{#runtime-import .github/workflows/shared/issues-data-fetch.md}} {{#runtime-import .github/workflows/shared/python-dataviz.md}} {{#runtime-import .github/workflows/shared/python-nlp.md}} @@ -302,7 +302,7 @@ jobs: {{#runtime-import .github/shared/editorial.md}} {{#runtime-import .github/workflows/shared/noop-reminder.md}} {{#runtime-import .github/workflows/daily-issues-report.md}} - GH_AW_PROMPT_6e7b51b8c77d15b1_EOF + GH_AW_PROMPT_728af52b5157ef07_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -477,22 +477,7 @@ jobs: - name: Setup jq utilities directory run: | mkdir -p /tmp/gh-aw - cat > /tmp/gh-aw/jqschema.sh << 'EOF' - #!/usr/bin/env bash - # jqschema.sh - jq -c ' - def walk(f): - . as $in | - if type == "object" then - reduce keys[] as $k ({}; . + {($k): ($in[$k] | walk(f))}) - elif type == "array" then - if length == 0 then [] else [.[0] | walk(f)] end - else - type - end; - walk(.) - ' - EOF + cp "$GITHUB_WORKSPACE/.github/skills/jqschema/jqschema.sh" /tmp/gh-aw/jqschema.sh chmod +x /tmp/gh-aw/jqschema.sh env: GH_HOST: localhost:18443 @@ -737,9 +722,9 @@ jobs: 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_0ece45d3e20b9fb7_EOF + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << GH_AW_SAFE_OUTPUTS_CONFIG_b630b608321b2441_EOF {"create_discussion":{"category":"audits","close_older_discussions":true,"expires":72,"fallback_to_issue":true,"max":1,"title_prefix":"[daily issues] "},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{},"upload_asset":{"allowed-exts":[".png",".jpg",".jpeg",".svg"],"branch":"assets/${GITHUB_WORKFLOW}","max":5,"max-size":10240}} - GH_AW_SAFE_OUTPUTS_CONFIG_0ece45d3e20b9fb7_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_b630b608321b2441_EOF - name: Generate Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -944,7 +929,7 @@ jobs: mkdir -p /home/runner/.copilot GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) - cat << GH_AW_MCP_CONFIG_5583c72007dd5696_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_23940c1664db79ab_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "safeoutputs": { @@ -975,7 +960,7 @@ jobs: } } } - GH_AW_MCP_CONFIG_5583c72007dd5696_EOF + GH_AW_MCP_CONFIG_23940c1664db79ab_EOF - name: Mount MCP servers as CLIs id: mount-mcp-clis continue-on-error: true diff --git a/.github/workflows/daily-issues-report.md b/.github/workflows/daily-issues-report.md index ef1a243b4d6..fcb2127a333 100644 --- a/.github/workflows/daily-issues-report.md +++ b/.github/workflows/daily-issues-report.md @@ -42,7 +42,7 @@ imports: - uses: shared/daily-audit-base.md with: title-prefix: "[daily issues] " - - shared/jqschema.md + - ../skills/jqschema/SKILL.md - shared/issues-data-fetch.md - shared/python-dataviz.md - shared/python-nlp.md diff --git a/.github/workflows/daily-news.lock.yml b/.github/workflows/daily-news.lock.yml index db82f948ad4..9336a6934be 100644 --- a/.github/workflows/daily-news.lock.yml +++ b/.github/workflows/daily-news.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"e4d131d5456a6d0f6ffa5f2a45ba07888731d53ee28522688c43ef8b8e6c77f3","strict":true,"agent_id":"copilot"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"168baf184c312b3cd4a889f4d1d8a8dfab5b8b41e9c30357ac88b719557b51a6","strict":true,"agent_id":"copilot"} # gh-aw-manifest: {"version":1,"secrets":["GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_ENDPOINT","GH_AW_OTEL_HEADERS","GITHUB_TOKEN","TAVILY_API_KEY"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"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":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/setup-python","sha":"a309ff8b426b58ec0e2a45f0f869d46889d02405","version":"v6.2.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41","digest":"sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41@sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41","digest":"sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41@sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41","digest":"sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41@sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.6","digest":"sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c"},{"image":"ghcr.io/github/github-mcp-server:v1.0.3","digest":"sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} # ___ _ _ # / _ \ | | (_) @@ -26,8 +26,8 @@ # # Resolved workflow manifest: # Imports: +# - ../skills/jqschema/SKILL.md # - shared/daily-audit-discussion.md -# - shared/jqschema.md # - shared/mcp/tavily.md # - shared/observability-otlp.md # - shared/python-dataviz.md @@ -200,24 +200,24 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_e9babfc76ee66412_EOF' + cat << 'GH_AW_PROMPT_217ef54f5fd2d557_EOF' - GH_AW_PROMPT_e9babfc76ee66412_EOF + GH_AW_PROMPT_217ef54f5fd2d557_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/cache_memory_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/repo_memory_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_e9babfc76ee66412_EOF' + cat << 'GH_AW_PROMPT_217ef54f5fd2d557_EOF' Tools: create_discussion, upload_asset(max:5), missing_tool, missing_data, noop upload_asset: provide a file path; returns a URL; assets are published after the workflow completes (safeoutputs). - GH_AW_PROMPT_e9babfc76ee66412_EOF + GH_AW_PROMPT_217ef54f5fd2d557_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" - cat << 'GH_AW_PROMPT_e9babfc76ee66412_EOF' + cat << 'GH_AW_PROMPT_217ef54f5fd2d557_EOF' The following GitHub context information is available for this workflow: {{#if __GH_AW_GITHUB_ACTOR__ }} @@ -246,12 +246,12 @@ jobs: {{/if}} - GH_AW_PROMPT_e9babfc76ee66412_EOF + GH_AW_PROMPT_217ef54f5fd2d557_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_e9babfc76ee66412_EOF' + cat << 'GH_AW_PROMPT_217ef54f5fd2d557_EOF' {{#runtime-import .github/workflows/shared/mcp/tavily.md}} - {{#runtime-import .github/workflows/shared/jqschema.md}} + {{#runtime-import .github/skills/jqschema/SKILL.md}} {{#runtime-import .github/workflows/shared/trends.md}} {{#runtime-import .github/workflows/shared/observability-otlp.md}} {{#runtime-import .github/workflows/shared/reporting.md}} @@ -259,7 +259,7 @@ jobs: {{#runtime-import .github/shared/editorial.md}} {{#runtime-import .github/workflows/shared/noop-reminder.md}} {{#runtime-import .github/workflows/daily-news.md}} - GH_AW_PROMPT_e9babfc76ee66412_EOF + GH_AW_PROMPT_217ef54f5fd2d557_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -432,7 +432,10 @@ jobs: env: GH_TOKEN: ${{ github.token }} - name: Setup jq utilities directory - run: "mkdir -p /tmp/gh-aw\ncat > /tmp/gh-aw/jqschema.sh << 'EOF'\n#!/usr/bin/env bash\n# jqschema.sh\njq -c '\ndef walk(f):\n . as $in |\n if type == \"object\" then\n reduce keys[] as $k ({}; . + {($k): ($in[$k] | walk(f))})\n elif type == \"array\" then\n if length == 0 then [] else [.[0] | walk(f)] end\n else\n type\n end;\nwalk(.)\n'\nEOF\nchmod +x /tmp/gh-aw/jqschema.sh\n" + run: | + mkdir -p /tmp/gh-aw + cp "$GITHUB_WORKSPACE/.github/skills/jqschema/jqschema.sh" /tmp/gh-aw/jqschema.sh + chmod +x /tmp/gh-aw/jqschema.sh - name: Setup Python environment run: "# Create working directory for Python scripts\nmkdir -p /tmp/gh-aw/python\nmkdir -p /tmp/gh-aw/python/data\nmkdir -p /tmp/gh-aw/python/charts\nmkdir -p /tmp/gh-aw/python/artifacts\n\necho \"Python environment setup complete\"\necho \"Working directory: /tmp/gh-aw/python\"\necho \"Data directory: /tmp/gh-aw/python/data\"\necho \"Charts directory: /tmp/gh-aw/python/charts\"\necho \"Artifacts directory: /tmp/gh-aw/python/artifacts\"\n" - name: Install Python scientific libraries @@ -611,9 +614,9 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs/upload-artifacts" - cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << GH_AW_SAFE_OUTPUTS_CONFIG_1798f1d95ccaa31e_EOF + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << GH_AW_SAFE_OUTPUTS_CONFIG_d34bb642d32bb13c_EOF {"create_discussion":{"category":"daily-news","close_older_discussions":true,"expires":72,"fallback_to_issue":true,"max":1},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"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}]},"report_incomplete":{},"upload_artifact":{"max-size-bytes":104857600,"max-uploads":3,"retention-days":30,"skip-archive":true},"upload_asset":{"allowed-exts":[".png",".jpg",".jpeg",".svg"],"branch":"assets/${GITHUB_WORKFLOW}","max":5,"max-size":10240}} - GH_AW_SAFE_OUTPUTS_CONFIG_1798f1d95ccaa31e_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_d34bb642d32bb13c_EOF - name: Generate Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -822,7 +825,7 @@ jobs: mkdir -p /home/runner/.copilot GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) - cat << GH_AW_MCP_CONFIG_fbab7644d7765543_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_2faccd8f1b90d093_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "github": { @@ -889,7 +892,7 @@ jobs: } } } - GH_AW_MCP_CONFIG_fbab7644d7765543_EOF + GH_AW_MCP_CONFIG_2faccd8f1b90d093_EOF - name: Mount MCP servers as CLIs id: mount-mcp-clis continue-on-error: true diff --git a/.github/workflows/daily-news.md b/.github/workflows/daily-news.md index f4afae2548b..205359cd925 100644 --- a/.github/workflows/daily-news.md +++ b/.github/workflows/daily-news.md @@ -291,7 +291,7 @@ imports: branch-name: "memory/daily-news" description: "Historical news digest data" - shared/mcp/tavily.md - - shared/jqschema.md + - ../skills/jqschema/SKILL.md - uses: shared/daily-audit-base.md with: title-prefix: "[daily-news] " diff --git a/.github/workflows/daily-safe-output-optimizer.lock.yml b/.github/workflows/daily-safe-output-optimizer.lock.yml index 37fef5b8255..a1d69e4d4d4 100644 --- a/.github/workflows/daily-safe-output-optimizer.lock.yml +++ b/.github/workflows/daily-safe-output-optimizer.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"2b0a7d1ec1c92152619a413d17a02e3b71be0f7f3916f7202e92ce2cf2945207","strict":true,"agent_id":"claude"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"96a6b65da0962328605f75e5121dba54a03d9ad93ad6890b31170a5200a1ecf4","strict":true,"agent_id":"claude"} # gh-aw-manifest: {"version":1,"secrets":["ANTHROPIC_API_KEY","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_ENDPOINT","GH_AW_OTEL_HEADERS","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-go","sha":"4a3601121dd01d1626a1e23e37211e3254c1c06c","version":"v6.4.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"docker/build-push-action","sha":"bcafcacb16a39f128d818304e6c9c0c18556b85f","version":"v7.1.0"},{"repo":"docker/setup-buildx-action","sha":"4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd","version":"v4.0.0"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41","digest":"sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41@sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41","digest":"sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41@sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41","digest":"sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41@sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.6","digest":"sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c"},{"image":"ghcr.io/github/github-mcp-server:v1.0.3","digest":"sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} # ___ _ _ # / _ \ | | (_) @@ -26,10 +26,10 @@ # # Resolved workflow manifest: # Imports: +# - ../skills/jqschema/SKILL.md # - shared/activation-app.md # - shared/aw-logs-24h-fetch.md # - shared/daily-audit-discussion.md -# - shared/jqschema.md # - shared/observability-otlp.md # - shared/reporting.md # - shared/daily-audit-base.md @@ -209,22 +209,22 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_1017c2bcf2421942_EOF' + cat << 'GH_AW_PROMPT_77291a4f902a62a4_EOF' - GH_AW_PROMPT_1017c2bcf2421942_EOF + GH_AW_PROMPT_77291a4f902a62a4_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/agentic_workflows_guide.md" cat "${RUNNER_TEMP}/gh-aw/prompts/cache_memory_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_1017c2bcf2421942_EOF' + cat << 'GH_AW_PROMPT_77291a4f902a62a4_EOF' Tools: create_issue, create_discussion, missing_tool, missing_data, noop - GH_AW_PROMPT_1017c2bcf2421942_EOF + GH_AW_PROMPT_77291a4f902a62a4_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" - cat << 'GH_AW_PROMPT_1017c2bcf2421942_EOF' + cat << 'GH_AW_PROMPT_77291a4f902a62a4_EOF' The following GitHub context information is available for this workflow: {{#if __GH_AW_GITHUB_ACTOR__ }} @@ -253,18 +253,18 @@ jobs: {{/if}} - GH_AW_PROMPT_1017c2bcf2421942_EOF + GH_AW_PROMPT_77291a4f902a62a4_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_1017c2bcf2421942_EOF' + cat << 'GH_AW_PROMPT_77291a4f902a62a4_EOF' {{#runtime-import .github/workflows/shared/aw-logs-24h-fetch.md}} {{#runtime-import .github/workflows/shared/activation-app.md}} - {{#runtime-import .github/workflows/shared/jqschema.md}} + {{#runtime-import .github/skills/jqschema/SKILL.md}} {{#runtime-import .github/workflows/shared/observability-otlp.md}} {{#runtime-import .github/workflows/shared/reporting.md}} {{#runtime-import .github/workflows/shared/noop-reminder.md}} {{#runtime-import .github/workflows/daily-safe-output-optimizer.md}} - GH_AW_PROMPT_1017c2bcf2421942_EOF + GH_AW_PROMPT_77291a4f902a62a4_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -447,7 +447,10 @@ jobs: name: Download logs from last 24 hours run: ./gh-aw logs --start-date -1d -o /tmp/gh-aw/aw-mcp/logs - name: Setup jq utilities directory - run: "mkdir -p /tmp/gh-aw\ncat > /tmp/gh-aw/jqschema.sh << 'EOF'\n#!/usr/bin/env bash\n# jqschema.sh\njq -c '\ndef walk(f):\n . as $in |\n if type == \"object\" then\n reduce keys[] as $k ({}; . + {($k): ($in[$k] | walk(f))})\n elif type == \"array\" then\n if length == 0 then [] else [.[0] | walk(f)] end\n else\n type\n end;\nwalk(.)\n'\nEOF\nchmod +x /tmp/gh-aw/jqschema.sh\n" + run: | + mkdir -p /tmp/gh-aw + cp "$GITHUB_WORKSPACE/.github/skills/jqschema/jqschema.sh" /tmp/gh-aw/jqschema.sh + chmod +x /tmp/gh-aw/jqschema.sh # Cache memory file share configuration from frontmatter processed below - name: Create cache-memory directory @@ -561,9 +564,9 @@ jobs: 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_6681d7e2a037ebd9_EOF' + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_245c6f94c4efa11e_EOF' {"create_discussion":{"category":"audits","close_older_discussions":true,"expires":72,"fallback_to_issue":true,"max":1,"title_prefix":"[safe-output-optimizer] "},"create_issue":{"expires":48,"labels":["bug","safe-outputs","tool-improvement","automated-analysis","cookie"],"max":1,"title_prefix":"[safeoutputs] "},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} - GH_AW_SAFE_OUTPUTS_CONFIG_6681d7e2a037ebd9_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_245c6f94c4efa11e_EOF - name: Generate Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -795,7 +798,7 @@ jobs: export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v /var/run/docker.sock:/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 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_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 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 GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -e GITHUB_AW_OTEL_TRACE_ID -e GITHUB_AW_OTEL_PARENT_SPAN_ID -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 ghcr.io/github/gh-aw-mcpg:v0.3.6' GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) - cat << GH_AW_MCP_CONFIG_efd754a98bf60c1b_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_3486f2f350bbc93d_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "agenticworkflows": { @@ -859,7 +862,7 @@ jobs: } } } - GH_AW_MCP_CONFIG_efd754a98bf60c1b_EOF + GH_AW_MCP_CONFIG_3486f2f350bbc93d_EOF - name: Mount MCP servers as CLIs id: mount-mcp-clis continue-on-error: true diff --git a/.github/workflows/daily-safe-output-optimizer.md b/.github/workflows/daily-safe-output-optimizer.md index 272045e58c6..ce7458f29b8 100644 --- a/.github/workflows/daily-safe-output-optimizer.md +++ b/.github/workflows/daily-safe-output-optimizer.md @@ -28,7 +28,7 @@ imports: title-prefix: "[safeoutputs]" - shared/aw-logs-24h-fetch.md - shared/activation-app.md - - shared/jqschema.md + - ../skills/jqschema/SKILL.md - uses: shared/daily-audit-base.md with: title-prefix: "[safe-output-optimizer] " diff --git a/.github/workflows/deep-report.lock.yml b/.github/workflows/deep-report.lock.yml index d44b5d47d48..17ed22bc599 100644 --- a/.github/workflows/deep-report.lock.yml +++ b/.github/workflows/deep-report.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"fb9d1be57bf8cd5c787f27964c08a3d3a510c8a74b67642fe48cf1129a1e4c7a","strict":true,"agent_id":"claude"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"437ba76d48c88b2bad1349fdbeae244a80234fabd2e7bd3faa40ea2b03ec67ad","strict":true,"agent_id":"claude"} # gh-aw-manifest: {"version":1,"secrets":["ANTHROPIC_API_KEY","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_ENDPOINT","GH_AW_OTEL_HEADERS","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-go","sha":"4a3601121dd01d1626a1e23e37211e3254c1c06c","version":"v6.4.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"docker/build-push-action","sha":"bcafcacb16a39f128d818304e6c9c0c18556b85f","version":"v7.1.0"},{"repo":"docker/setup-buildx-action","sha":"4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd","version":"v4.0.0"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41","digest":"sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41@sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41","digest":"sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41@sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0"},{"image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.41","digest":"sha256:62171f2fa508667b8b0a9e096f826983f312e3da0ce894f80c0f83a875af60fe","pinned_image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.41@sha256:62171f2fa508667b8b0a9e096f826983f312e3da0ce894f80c0f83a875af60fe"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41","digest":"sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41@sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.6","digest":"sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c"},{"image":"ghcr.io/github/github-mcp-server:v1.0.3","digest":"sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} # ___ _ _ # / _ \ | | (_) @@ -26,8 +26,8 @@ # # Resolved workflow manifest: # Imports: +# - ../skills/jqschema/SKILL.md # - shared/discussions-data-fetch.md -# - shared/jqschema.md # - shared/meta-analysis-base.md # - shared/observability-otlp.md # - shared/reporting.md @@ -242,9 +242,9 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_5ac9c18a60775687_EOF' + cat << 'GH_AW_PROMPT_7c3396ec41543904_EOF' - GH_AW_PROMPT_5ac9c18a60775687_EOF + GH_AW_PROMPT_7c3396ec41543904_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" @@ -252,13 +252,13 @@ jobs: cat "${RUNNER_TEMP}/gh-aw/prompts/cache_memory_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/repo_memory_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_5ac9c18a60775687_EOF' + cat << 'GH_AW_PROMPT_7c3396ec41543904_EOF' Tools: create_issue(max:7), create_discussion, missing_tool, missing_data, noop - GH_AW_PROMPT_5ac9c18a60775687_EOF + GH_AW_PROMPT_7c3396ec41543904_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" - cat << 'GH_AW_PROMPT_5ac9c18a60775687_EOF' + cat << 'GH_AW_PROMPT_7c3396ec41543904_EOF' The following GitHub context information is available for this workflow: {{#if __GH_AW_GITHUB_ACTOR__ }} @@ -287,21 +287,21 @@ jobs: {{/if}} - GH_AW_PROMPT_5ac9c18a60775687_EOF + GH_AW_PROMPT_7c3396ec41543904_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/cli_proxy_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_5ac9c18a60775687_EOF' + cat << 'GH_AW_PROMPT_7c3396ec41543904_EOF' **IMPORTANT**: When analyzing agentic workflows, use the `agentic-workflows` tool to read workflow files. - {{#runtime-import .github/workflows/shared/jqschema.md}} + {{#runtime-import .github/skills/jqschema/SKILL.md}} {{#runtime-import .github/workflows/shared/discussions-data-fetch.md}} {{#runtime-import .github/workflows/shared/weekly-issues-data-fetch.md}} {{#runtime-import .github/workflows/shared/reporting.md}} {{#runtime-import .github/workflows/shared/observability-otlp.md}} {{#runtime-import .github/workflows/shared/noop-reminder.md}} {{#runtime-import .github/workflows/deep-report.md}} - GH_AW_PROMPT_5ac9c18a60775687_EOF + GH_AW_PROMPT_7c3396ec41543904_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -494,7 +494,10 @@ jobs: env: GH_TOKEN: ${{ github.token }} - name: Setup jq utilities directory - run: "mkdir -p /tmp/gh-aw\ncat > /tmp/gh-aw/jqschema.sh << 'EOF'\n#!/usr/bin/env bash\n# jqschema.sh\njq -c '\ndef walk(f):\n . as $in |\n if type == \"object\" then\n reduce keys[] as $k ({}; . + {($k): ($in[$k] | walk(f))})\n elif type == \"array\" then\n if length == 0 then [] else [.[0] | walk(f)] end\n else\n type\n end;\nwalk(.)\n'\nEOF\nchmod +x /tmp/gh-aw/jqschema.sh\n" + run: | + mkdir -p /tmp/gh-aw + cp "$GITHUB_WORKSPACE/.github/skills/jqschema/jqschema.sh" /tmp/gh-aw/jqschema.sh + chmod +x /tmp/gh-aw/jqschema.sh - name: Install gh CLI run: | bash "${RUNNER_TEMP}/gh-aw/actions/install_gh_cli.sh" @@ -637,9 +640,9 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs/upload-artifacts" - cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_ee5a05a505aa1011_EOF' + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_6a2a6a90202a4e2c_EOF' {"create_discussion":{"category":"reports","close_older_discussions":true,"expires":168,"fallback_to_issue":true,"max":1},"create_issue":{"expires":48,"group":true,"labels":["automation","improvement","quick-win","cookie"],"max":7,"title_prefix":"[deep-report] "},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"push_repo_memory":{"memories":[{"dir":"/tmp/gh-aw/repo-memory/default","id":"default","max_file_count":100,"max_file_size":1048576,"max_patch_size":10240}]},"report_incomplete":{},"upload_artifact":{"max-size-bytes":104857600,"max-uploads":1,"retention-days":30}} - GH_AW_SAFE_OUTPUTS_CONFIG_ee5a05a505aa1011_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_6a2a6a90202a4e2c_EOF - name: Generate Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -868,7 +871,7 @@ jobs: export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v /var/run/docker.sock:/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 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_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 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 GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -e GITHUB_AW_OTEL_TRACE_ID -e GITHUB_AW_OTEL_PARENT_SPAN_ID -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 ghcr.io/github/gh-aw-mcpg:v0.3.6' GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) - cat << GH_AW_MCP_CONFIG_5657b326b0fda232_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_1019fca97965a7ab_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "agenticworkflows": { @@ -917,7 +920,7 @@ jobs: } } } - GH_AW_MCP_CONFIG_5657b326b0fda232_EOF + GH_AW_MCP_CONFIG_1019fca97965a7ab_EOF - name: Mount MCP servers as CLIs id: mount-mcp-clis continue-on-error: true diff --git a/.github/workflows/deep-report.md b/.github/workflows/deep-report.md index 95430fedddd..e08687f965c 100644 --- a/.github/workflows/deep-report.md +++ b/.github/workflows/deep-report.md @@ -71,7 +71,7 @@ imports: - uses: shared/meta-analysis-base.md with: toolsets: [all] - - shared/jqschema.md + - ../skills/jqschema/SKILL.md - shared/discussions-data-fetch.md - shared/weekly-issues-data-fetch.md - shared/reporting.md diff --git a/.github/workflows/discussion-task-miner.lock.yml b/.github/workflows/discussion-task-miner.lock.yml index 46e2405b81f..af90fb76499 100644 --- a/.github/workflows/discussion-task-miner.lock.yml +++ b/.github/workflows/discussion-task-miner.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"1ddea104b81c1092ed234e78a0cae8a2fdfa819fcb4692474ce4c67ff5c18043","strict":true,"agent_id":"copilot"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"cd83e1e823cae1d4a0e2d170933d97025997d6cd00d290c7d54a157eecfe7ef1","strict":true,"agent_id":"copilot"} # gh-aw-manifest: {"version":1,"secrets":["GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_ENDPOINT","GH_AW_OTEL_HEADERS","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"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":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41","digest":"sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41@sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41","digest":"sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41@sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0"},{"image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.41","digest":"sha256:62171f2fa508667b8b0a9e096f826983f312e3da0ce894f80c0f83a875af60fe","pinned_image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.41@sha256:62171f2fa508667b8b0a9e096f826983f312e3da0ce894f80c0f83a875af60fe"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41","digest":"sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41@sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.6","digest":"sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c"},{"image":"ghcr.io/github/github-mcp-server:v1.0.3","digest":"sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} # ___ _ _ # / _ \ | | (_) @@ -26,8 +26,8 @@ # # Resolved workflow manifest: # Imports: +# - ../skills/jqschema/SKILL.md # - shared/github-guard-policy.md -# - shared/jqschema.md # - shared/observability-otlp.md # - shared/repo-memory-standard.md # - shared/reporting.md @@ -192,21 +192,21 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_ac933141e2e1c235_EOF' + cat << 'GH_AW_PROMPT_422a5e186f654fe6_EOF' - GH_AW_PROMPT_ac933141e2e1c235_EOF + GH_AW_PROMPT_422a5e186f654fe6_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/repo_memory_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_ac933141e2e1c235_EOF' + cat << 'GH_AW_PROMPT_422a5e186f654fe6_EOF' Tools: add_comment(max:3), create_issue(max:5), missing_tool, missing_data, noop - GH_AW_PROMPT_ac933141e2e1c235_EOF + GH_AW_PROMPT_422a5e186f654fe6_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" - cat << 'GH_AW_PROMPT_ac933141e2e1c235_EOF' + cat << 'GH_AW_PROMPT_422a5e186f654fe6_EOF' The following GitHub context information is available for this workflow: {{#if __GH_AW_GITHUB_ACTOR__ }} @@ -235,17 +235,17 @@ jobs: {{/if}} - GH_AW_PROMPT_ac933141e2e1c235_EOF + GH_AW_PROMPT_422a5e186f654fe6_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/cli_proxy_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_ac933141e2e1c235_EOF' + cat << 'GH_AW_PROMPT_422a5e186f654fe6_EOF' {{#runtime-import .github/workflows/shared/github-guard-policy.md}} - {{#runtime-import .github/workflows/shared/jqschema.md}} + {{#runtime-import .github/skills/jqschema/SKILL.md}} {{#runtime-import .github/workflows/shared/reporting.md}} {{#runtime-import .github/workflows/shared/observability-otlp.md}} {{#runtime-import .github/workflows/shared/noop-reminder.md}} {{#runtime-import .github/workflows/discussion-task-miner.md}} - GH_AW_PROMPT_ac933141e2e1c235_EOF + GH_AW_PROMPT_422a5e186f654fe6_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -402,7 +402,10 @@ jobs: env: GH_TOKEN: ${{ github.token }} - name: Setup jq utilities directory - run: "mkdir -p /tmp/gh-aw\ncat > /tmp/gh-aw/jqschema.sh << 'EOF'\n#!/usr/bin/env bash\n# jqschema.sh\njq -c '\ndef walk(f):\n . as $in |\n if type == \"object\" then\n reduce keys[] as $k ({}; . + {($k): ($in[$k] | walk(f))})\n elif type == \"array\" then\n if length == 0 then [] else [.[0] | walk(f)] end\n else\n type\n end;\nwalk(.)\n'\nEOF\nchmod +x /tmp/gh-aw/jqschema.sh\n" + run: | + mkdir -p /tmp/gh-aw + cp "$GITHUB_WORKSPACE/.github/skills/jqschema/jqschema.sh" /tmp/gh-aw/jqschema.sh + chmod +x /tmp/gh-aw/jqschema.sh # Repo memory git-based storage configuration from frontmatter processed below - name: Clone repo-memory branch (default) @@ -478,9 +481,9 @@ jobs: 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_7e3782728a8b2149_EOF' + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_3c036ca0a255d1e5_EOF' {"add_comment":{"max":3},"create_issue":{"expires":24,"group":true,"labels":["code-quality","automation","task-mining"],"max":5,"title_prefix":"[Code Quality] "},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"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}]},"report_incomplete":{}} - GH_AW_SAFE_OUTPUTS_CONFIG_7e3782728a8b2149_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_3c036ca0a255d1e5_EOF - name: Generate Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -705,7 +708,7 @@ jobs: mkdir -p /home/runner/.copilot GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) - cat << GH_AW_MCP_CONFIG_17b9a8d4ab7922a7_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_6abd5bd8db6639f0_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "safeoutputs": { @@ -736,7 +739,7 @@ jobs: } } } - GH_AW_MCP_CONFIG_17b9a8d4ab7922a7_EOF + GH_AW_MCP_CONFIG_6abd5bd8db6639f0_EOF - name: Mount MCP servers as CLIs id: mount-mcp-clis continue-on-error: true diff --git a/.github/workflows/discussion-task-miner.md b/.github/workflows/discussion-task-miner.md index 709edfddebf..e59b0eac2b5 100644 --- a/.github/workflows/discussion-task-miner.md +++ b/.github/workflows/discussion-task-miner.md @@ -54,7 +54,7 @@ imports: with: branch-name: "memory/discussion-task-miner" description: "Track processed discussions and extracted tasks" - - shared/jqschema.md + - ../skills/jqschema/SKILL.md - shared/reporting.md - shared/observability-otlp.md diff --git a/.github/workflows/issue-arborist.lock.yml b/.github/workflows/issue-arborist.lock.yml index 4f7ff23222d..21119ca3ba3 100644 --- a/.github/workflows/issue-arborist.lock.yml +++ b/.github/workflows/issue-arborist.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"a92c7ef940b04e5c3ac55a459701c9e1e7b4d71a6ca81a7e66e564049bf80f42","strict":true,"agent_id":"codex"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"8bc500431295c30f00d9a0549c3cc4d74adff9c2e29e5864df365117eea35f25","strict":true,"agent_id":"codex"} # gh-aw-manifest: {"version":1,"secrets":["CODEX_API_KEY","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_ENDPOINT","GH_AW_OTEL_HEADERS","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"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":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41","digest":"sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41@sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41","digest":"sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41@sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0"},{"image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.41","digest":"sha256:62171f2fa508667b8b0a9e096f826983f312e3da0ce894f80c0f83a875af60fe","pinned_image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.41@sha256:62171f2fa508667b8b0a9e096f826983f312e3da0ce894f80c0f83a875af60fe"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41","digest":"sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41@sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.6","digest":"sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c"},{"image":"ghcr.io/github/github-mcp-server:v1.0.3","digest":"sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} # ___ _ _ # / _ \ | | (_) @@ -26,8 +26,8 @@ # # Resolved workflow manifest: # Imports: +# - ../skills/jqschema/SKILL.md # - shared/github-guard-policy.md -# - shared/jqschema.md # - shared/observability-otlp.md # - shared/reporting.md # @@ -235,20 +235,20 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_b7afd8fba6d8272d_EOF' + cat << 'GH_AW_PROMPT_4b9f69203671c22f_EOF' - GH_AW_PROMPT_b7afd8fba6d8272d_EOF + GH_AW_PROMPT_4b9f69203671c22f_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_b7afd8fba6d8272d_EOF' + cat << 'GH_AW_PROMPT_4b9f69203671c22f_EOF' Tools: create_issue(max:5), create_discussion, link_sub_issue(max:50), missing_tool, missing_data, noop - GH_AW_PROMPT_b7afd8fba6d8272d_EOF + GH_AW_PROMPT_4b9f69203671c22f_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" - cat << 'GH_AW_PROMPT_b7afd8fba6d8272d_EOF' + cat << 'GH_AW_PROMPT_4b9f69203671c22f_EOF' The following GitHub context information is available for this workflow: {{#if __GH_AW_GITHUB_ACTOR__ }} @@ -277,17 +277,17 @@ jobs: {{/if}} - GH_AW_PROMPT_b7afd8fba6d8272d_EOF + GH_AW_PROMPT_4b9f69203671c22f_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/cli_proxy_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_b7afd8fba6d8272d_EOF' + cat << 'GH_AW_PROMPT_4b9f69203671c22f_EOF' {{#runtime-import .github/workflows/shared/github-guard-policy.md}} - {{#runtime-import .github/workflows/shared/jqschema.md}} + {{#runtime-import .github/skills/jqschema/SKILL.md}} {{#runtime-import .github/workflows/shared/reporting.md}} {{#runtime-import .github/workflows/shared/observability-otlp.md}} {{#runtime-import .github/workflows/shared/noop-reminder.md}} {{#runtime-import .github/workflows/issue-arborist.md}} - GH_AW_PROMPT_b7afd8fba6d8272d_EOF + GH_AW_PROMPT_4b9f69203671c22f_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -438,22 +438,7 @@ jobs: - name: Setup jq utilities directory run: | mkdir -p /tmp/gh-aw - cat > /tmp/gh-aw/jqschema.sh << 'EOF' - #!/usr/bin/env bash - # jqschema.sh - jq -c ' - def walk(f): - . as $in | - if type == "object" then - reduce keys[] as $k ({}; . + {($k): ($in[$k] | walk(f))}) - elif type == "array" then - if length == 0 then [] else [.[0] | walk(f)] end - else - type - end; - walk(.) - ' - EOF + cp "$GITHUB_WORKSPACE/.github/skills/jqschema/jqschema.sh" /tmp/gh-aw/jqschema.sh chmod +x /tmp/gh-aw/jqschema.sh env: GH_HOST: localhost:18443 @@ -565,9 +550,9 @@ jobs: 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_dff7e564b2382fcd_EOF' + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_b079854b0c907535_EOF' {"create_discussion":{"category":"audits","close_older_discussions":true,"expires":24,"fallback_to_issue":true,"max":1,"title_prefix":"[Issue Arborist] "},"create_issue":{"expires":48,"group":true,"max":5,"title_prefix":"[Parent] "},"create_report_incomplete_issue":{},"link_sub_issue":{"max":50},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} - GH_AW_SAFE_OUTPUTS_CONFIG_dff7e564b2382fcd_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_b079854b0c907535_EOF - name: Generate Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -814,7 +799,7 @@ jobs: DOCKER_SOCK_GID=$(stat -c '%g' /var/run/docker.sock 2>/dev/null || echo '0') export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v /var/run/docker.sock:/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 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_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 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 GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -e GITHUB_AW_OTEL_TRACE_ID -e GITHUB_AW_OTEL_PARENT_SPAN_ID -e CODEX_HOME -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 ghcr.io/github/gh-aw-mcpg:v0.3.6' - cat > "${RUNNER_TEMP}/gh-aw/mcp-config/config.toml" << GH_AW_MCP_CONFIG_d38cfdd69f3d4f9f_EOF + cat > "${RUNNER_TEMP}/gh-aw/mcp-config/config.toml" << GH_AW_MCP_CONFIG_2194ad019b3f775c_EOF [history] persistence = "none" @@ -833,11 +818,11 @@ jobs: [mcp_servers.safeoutputs."guard-policies".write-sink] accept = ["*"] - GH_AW_MCP_CONFIG_d38cfdd69f3d4f9f_EOF + GH_AW_MCP_CONFIG_2194ad019b3f775c_EOF # Generate JSON config for MCP gateway GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) - cat << GH_AW_MCP_CONFIG_d38cfdd69f3d4f9f_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_2194ad019b3f775c_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "safeoutputs": { @@ -868,11 +853,11 @@ jobs: } } } - GH_AW_MCP_CONFIG_d38cfdd69f3d4f9f_EOF + GH_AW_MCP_CONFIG_2194ad019b3f775c_EOF # Sync converter output to writable CODEX_HOME for Codex mkdir -p /tmp/gh-aw/mcp-config - cat > "/tmp/gh-aw/mcp-config/config.toml" << GH_AW_CODEX_SHELL_POLICY_b80f5d67a293b1e6_EOF + cat > "/tmp/gh-aw/mcp-config/config.toml" << GH_AW_CODEX_SHELL_POLICY_8b937b6bb6a0d0bd_EOF model_provider = "openai-proxy" @@ -884,7 +869,7 @@ jobs: [shell_environment_policy] inherit = "core" include_only = ["CODEX_API_KEY", "GH_AW_ASSETS_ALLOWED_EXTS", "GH_AW_ASSETS_BRANCH", "GH_AW_ASSETS_MAX_SIZE_KB", "GH_AW_SAFE_OUTPUTS", "GITHUB_REPOSITORY", "GITHUB_SERVER_URL", "HOME", "OPENAI_API_KEY", "PATH"] - GH_AW_CODEX_SHELL_POLICY_b80f5d67a293b1e6_EOF + GH_AW_CODEX_SHELL_POLICY_8b937b6bb6a0d0bd_EOF awk ' BEGIN { skip_openai_proxy = 0 } /^[[:space:]]*model_provider[[:space:]]*=/ { next } @@ -1421,18 +1406,18 @@ jobs: DOCKER_SOCK_GID=$(stat -c '%g' /var/run/docker.sock 2>/dev/null || echo '0') export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v /var/run/docker.sock:/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 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_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 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 CODEX_HOME -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 ghcr.io/github/gh-aw-mcpg:v0.3.6' - cat > "${RUNNER_TEMP}/gh-aw/mcp-config/config.toml" << GH_AW_MCP_CONFIG_e247c0c84678d8ae_EOF + cat > "${RUNNER_TEMP}/gh-aw/mcp-config/config.toml" << GH_AW_MCP_CONFIG_bcf31f878ff6c40c_EOF [history] persistence = "none" [shell_environment_policy] inherit = "core" include_only = ["CODEX_API_KEY", "HOME", "OPENAI_API_KEY", "PATH"] - GH_AW_MCP_CONFIG_e247c0c84678d8ae_EOF + GH_AW_MCP_CONFIG_bcf31f878ff6c40c_EOF # Generate JSON config for MCP gateway GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) - cat << GH_AW_MCP_CONFIG_b94066b6d62be69f_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_3bbd22c4a041fde6_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { }, @@ -1443,11 +1428,11 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_b94066b6d62be69f_EOF + GH_AW_MCP_CONFIG_3bbd22c4a041fde6_EOF # Sync converter output to writable CODEX_HOME for Codex mkdir -p /tmp/gh-aw/mcp-config - cat > "/tmp/gh-aw/mcp-config/config.toml" << GH_AW_CODEX_SHELL_POLICY_ab2dc34dd1197dc6_EOF + cat > "/tmp/gh-aw/mcp-config/config.toml" << GH_AW_CODEX_SHELL_POLICY_0446dcc9cb1f9d23_EOF model_provider = "openai-proxy" [model_providers.openai-proxy] name = "OpenAI AWF proxy" @@ -1457,7 +1442,7 @@ jobs: [shell_environment_policy] inherit = "core" include_only = ["CODEX_API_KEY", "HOME", "OPENAI_API_KEY", "PATH"] - GH_AW_CODEX_SHELL_POLICY_ab2dc34dd1197dc6_EOF + GH_AW_CODEX_SHELL_POLICY_0446dcc9cb1f9d23_EOF awk ' BEGIN { skip_openai_proxy = 0 } /^[[:space:]]*model_provider[[:space:]]*=/ { next } diff --git a/.github/workflows/issue-arborist.md b/.github/workflows/issue-arborist.md index 755acbacd95..3a69ed31509 100644 --- a/.github/workflows/issue-arborist.md +++ b/.github/workflows/issue-arborist.md @@ -15,7 +15,7 @@ network: - github imports: - shared/github-guard-policy.md - - shared/jqschema.md + - ../skills/jqschema/SKILL.md - shared/reporting.md - shared/observability-otlp.md tools: diff --git a/.github/workflows/org-health-report.lock.yml b/.github/workflows/org-health-report.lock.yml index 16cd997fd09..acb896fccb8 100644 --- a/.github/workflows/org-health-report.lock.yml +++ b/.github/workflows/org-health-report.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"c742a8622994169ede9ad92b7cbc8a147fdbccd8baff4039c3c1f04989f5713a","strict":true,"agent_id":"copilot"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"f0859b204f80db2c1287e5a42fa87f366d8dbfc788ade5b5d05ffcb5055c07ef","strict":true,"agent_id":"copilot"} # gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_ENDPOINT","GH_AW_OTEL_HEADERS","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"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":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/setup-python","sha":"a309ff8b426b58ec0e2a45f0f869d46889d02405","version":"v6.2.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41","digest":"sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41@sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41","digest":"sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41@sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0"},{"image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.41","digest":"sha256:62171f2fa508667b8b0a9e096f826983f312e3da0ce894f80c0f83a875af60fe","pinned_image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.41@sha256:62171f2fa508667b8b0a9e096f826983f312e3da0ce894f80c0f83a875af60fe"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41","digest":"sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41@sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.6","digest":"sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c"},{"image":"ghcr.io/github/github-mcp-server:v1.0.3","digest":"sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} # ___ _ _ # / _ \ | | (_) @@ -26,8 +26,8 @@ # # Resolved workflow manifest: # Imports: +# - ../skills/jqschema/SKILL.md # - shared/github-guard-policy.md -# - shared/jqschema.md # - shared/observability-otlp.md # - shared/python-dataviz.md # - shared/reporting.md @@ -201,23 +201,23 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_adfbb6460e448d64_EOF' + cat << 'GH_AW_PROMPT_566864e6f0e4981d_EOF' - GH_AW_PROMPT_adfbb6460e448d64_EOF + GH_AW_PROMPT_566864e6f0e4981d_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/cache_memory_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_adfbb6460e448d64_EOF' + cat << 'GH_AW_PROMPT_566864e6f0e4981d_EOF' Tools: create_discussion, upload_asset(max:5), missing_tool, missing_data, noop upload_asset: provide a file path; returns a URL; assets are published after the workflow completes (safeoutputs). - GH_AW_PROMPT_adfbb6460e448d64_EOF + GH_AW_PROMPT_566864e6f0e4981d_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" - cat << 'GH_AW_PROMPT_adfbb6460e448d64_EOF' + cat << 'GH_AW_PROMPT_566864e6f0e4981d_EOF' The following GitHub context information is available for this workflow: {{#if __GH_AW_GITHUB_ACTOR__ }} @@ -246,18 +246,18 @@ jobs: {{/if}} - GH_AW_PROMPT_adfbb6460e448d64_EOF + GH_AW_PROMPT_566864e6f0e4981d_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/cli_proxy_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_adfbb6460e448d64_EOF' + cat << 'GH_AW_PROMPT_566864e6f0e4981d_EOF' {{#runtime-import .github/workflows/shared/github-guard-policy.md}} {{#runtime-import .github/workflows/shared/python-dataviz.md}} - {{#runtime-import .github/workflows/shared/jqschema.md}} + {{#runtime-import .github/skills/jqschema/SKILL.md}} {{#runtime-import .github/workflows/shared/reporting.md}} {{#runtime-import .github/workflows/shared/observability-otlp.md}} {{#runtime-import .github/workflows/shared/noop-reminder.md}} {{#runtime-import .github/workflows/org-health-report.md}} - GH_AW_PROMPT_adfbb6460e448d64_EOF + GH_AW_PROMPT_566864e6f0e4981d_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -426,7 +426,10 @@ jobs: /tmp/gh-aw/python/data/* retention-days: 30 - name: Setup jq utilities directory - run: "mkdir -p /tmp/gh-aw\ncat > /tmp/gh-aw/jqschema.sh << 'EOF'\n#!/usr/bin/env bash\n# jqschema.sh\njq -c '\ndef walk(f):\n . as $in |\n if type == \"object\" then\n reduce keys[] as $k ({}; . + {($k): ($in[$k] | walk(f))})\n elif type == \"array\" then\n if length == 0 then [] else [.[0] | walk(f)] end\n else\n type\n end;\nwalk(.)\n'\nEOF\nchmod +x /tmp/gh-aw/jqschema.sh\n" + run: | + mkdir -p /tmp/gh-aw + cp "$GITHUB_WORKSPACE/.github/skills/jqschema/jqschema.sh" /tmp/gh-aw/jqschema.sh + chmod +x /tmp/gh-aw/jqschema.sh # Cache memory file share configuration from frontmatter processed below - name: Create cache-memory directory @@ -510,9 +513,9 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs/upload-artifacts" - cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << GH_AW_SAFE_OUTPUTS_CONFIG_ea5951ee31b18024_EOF + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << GH_AW_SAFE_OUTPUTS_CONFIG_f47c3160618031ae_EOF {"create_discussion":{"category":"reports","close_older_discussions":true,"expires":24,"fallback_to_issue":true,"max":1},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{},"upload_artifact":{"max-size-bytes":104857600,"max-uploads":3,"retention-days":30,"skip-archive":true},"upload_asset":{"allowed-exts":[".png",".jpg",".jpeg",".svg"],"branch":"assets/${GITHUB_WORKFLOW}","max":5,"max-size":10240}} - GH_AW_SAFE_OUTPUTS_CONFIG_ea5951ee31b18024_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_f47c3160618031ae_EOF - name: Generate Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -717,7 +720,7 @@ jobs: mkdir -p /home/runner/.copilot GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) - cat << GH_AW_MCP_CONFIG_24e35888cf329040_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_126eeb8130624ed1_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "safeoutputs": { @@ -748,7 +751,7 @@ jobs: } } } - GH_AW_MCP_CONFIG_24e35888cf329040_EOF + GH_AW_MCP_CONFIG_126eeb8130624ed1_EOF - name: Mount MCP servers as CLIs id: mount-mcp-clis continue-on-error: true diff --git a/.github/workflows/org-health-report.md b/.github/workflows/org-health-report.md index 6efb44b318f..012e9ab7b33 100644 --- a/.github/workflows/org-health-report.md +++ b/.github/workflows/org-health-report.md @@ -42,7 +42,7 @@ network: imports: - shared/github-guard-policy.md - shared/python-dataviz.md - - shared/jqschema.md + - ../skills/jqschema/SKILL.md - shared/reporting.md diff --git a/.github/workflows/prompt-clustering-analysis.lock.yml b/.github/workflows/prompt-clustering-analysis.lock.yml index 171b2e522cf..d02d4d42b71 100644 --- a/.github/workflows/prompt-clustering-analysis.lock.yml +++ b/.github/workflows/prompt-clustering-analysis.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"c672aaffac712c83e31d3240f869cc7f22070415379a20eae8342c2a87df41b5","strict":true,"agent_id":"claude"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"37cfc83fa864728e0a7eb276ff1e37a714aebabe1bfb3029dab0fdc9115f6e5f","strict":true,"agent_id":"claude"} # gh-aw-manifest: {"version":1,"secrets":["ANTHROPIC_API_KEY","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_ENDPOINT","GH_AW_OTEL_HEADERS","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-go","sha":"4a3601121dd01d1626a1e23e37211e3254c1c06c","version":"v6.4.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/setup-python","sha":"a309ff8b426b58ec0e2a45f0f869d46889d02405","version":"v6.2.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"docker/build-push-action","sha":"bcafcacb16a39f128d818304e6c9c0c18556b85f","version":"v7.1.0"},{"repo":"docker/setup-buildx-action","sha":"4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd","version":"v4.0.0"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41","digest":"sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41@sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41","digest":"sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41@sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0"},{"image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.41","digest":"sha256:62171f2fa508667b8b0a9e096f826983f312e3da0ce894f80c0f83a875af60fe","pinned_image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.41@sha256:62171f2fa508667b8b0a9e096f826983f312e3da0ce894f80c0f83a875af60fe"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41","digest":"sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41@sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.6","digest":"sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c"},{"image":"ghcr.io/github/github-mcp-server:v1.0.3","digest":"sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} # ___ _ _ # / _ \ | | (_) @@ -26,9 +26,9 @@ # # Resolved workflow manifest: # Imports: +# - ../skills/jqschema/SKILL.md # - shared/copilot-pr-data-fetch.md # - shared/daily-audit-discussion.md -# - shared/jqschema.md # - shared/meta-analysis-base.md # - shared/observability-otlp.md # - shared/python-nlp.md @@ -213,24 +213,24 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_055e071b56ad42d2_EOF' + cat << 'GH_AW_PROMPT_45d1580a9b58d30a_EOF' - GH_AW_PROMPT_055e071b56ad42d2_EOF + GH_AW_PROMPT_45d1580a9b58d30a_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/agentic_workflows_guide.md" cat "${RUNNER_TEMP}/gh-aw/prompts/cache_memory_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_055e071b56ad42d2_EOF' + cat << 'GH_AW_PROMPT_45d1580a9b58d30a_EOF' Tools: create_discussion, upload_asset(max:5), missing_tool, missing_data, noop upload_asset: provide a file path; returns a URL; assets are published after the workflow completes (safeoutputs). - GH_AW_PROMPT_055e071b56ad42d2_EOF + GH_AW_PROMPT_45d1580a9b58d30a_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" - cat << 'GH_AW_PROMPT_055e071b56ad42d2_EOF' + cat << 'GH_AW_PROMPT_45d1580a9b58d30a_EOF' The following GitHub context information is available for this workflow: {{#if __GH_AW_GITHUB_ACTOR__ }} @@ -259,14 +259,14 @@ jobs: {{/if}} - GH_AW_PROMPT_055e071b56ad42d2_EOF + GH_AW_PROMPT_45d1580a9b58d30a_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/cli_proxy_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_055e071b56ad42d2_EOF' + cat << 'GH_AW_PROMPT_45d1580a9b58d30a_EOF' **IMPORTANT**: When analyzing agentic workflows, use the `agentic-workflows` tool to read workflow files. - {{#runtime-import .github/workflows/shared/jqschema.md}} + {{#runtime-import .github/skills/jqschema/SKILL.md}} {{#runtime-import .github/workflows/shared/copilot-pr-data-fetch.md}} {{#runtime-import .github/workflows/shared/python-nlp.md}} {{#runtime-import .github/workflows/shared/observability-otlp.md}} @@ -274,7 +274,7 @@ jobs: {{#runtime-import .github/workflows/shared/reporting.md}} {{#runtime-import .github/workflows/shared/noop-reminder.md}} {{#runtime-import .github/workflows/prompt-clustering-analysis.md}} - GH_AW_PROMPT_055e071b56ad42d2_EOF + GH_AW_PROMPT_45d1580a9b58d30a_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -454,7 +454,10 @@ jobs: env: GH_TOKEN: ${{ github.token }} - name: Setup jq utilities directory - run: "mkdir -p /tmp/gh-aw\ncat > /tmp/gh-aw/jqschema.sh << 'EOF'\n#!/usr/bin/env bash\n# jqschema.sh\njq -c '\ndef walk(f):\n . as $in |\n if type == \"object\" then\n reduce keys[] as $k ({}; . + {($k): ($in[$k] | walk(f))})\n elif type == \"array\" then\n if length == 0 then [] else [.[0] | walk(f)] end\n else\n type\n end;\nwalk(.)\n'\nEOF\nchmod +x /tmp/gh-aw/jqschema.sh\n" + run: | + mkdir -p /tmp/gh-aw + cp "$GITHUB_WORKSPACE/.github/skills/jqschema/jqschema.sh" /tmp/gh-aw/jqschema.sh + chmod +x /tmp/gh-aw/jqschema.sh - name: Install gh CLI run: | bash "${RUNNER_TEMP}/gh-aw/actions/install_gh_cli.sh" @@ -609,9 +612,9 @@ jobs: 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_fa0bfc9d52426266_EOF + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << GH_AW_SAFE_OUTPUTS_CONFIG_9b0b41cec98e145e_EOF {"create_discussion":{"category":"audits","close_older_discussions":true,"expires":24,"fallback_to_issue":true,"max":1,"title_prefix":"[prompt-clustering] "},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{},"upload_asset":{"allowed-exts":[".png",".jpg",".jpeg",".svg"],"branch":"assets/${GITHUB_WORKFLOW}","max":5,"max-size":10240}} - GH_AW_SAFE_OUTPUTS_CONFIG_fa0bfc9d52426266_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_9b0b41cec98e145e_EOF - name: Generate Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -816,7 +819,7 @@ jobs: export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v /var/run/docker.sock:/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 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_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 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 GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -e GITHUB_AW_OTEL_TRACE_ID -e GITHUB_AW_OTEL_PARENT_SPAN_ID -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 ghcr.io/github/gh-aw-mcpg:v0.3.6' GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) - cat << GH_AW_MCP_CONFIG_a3de6fa5178b53a8_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_778846b008ffb21d_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "agenticworkflows": { @@ -865,7 +868,7 @@ jobs: } } } - GH_AW_MCP_CONFIG_a3de6fa5178b53a8_EOF + GH_AW_MCP_CONFIG_778846b008ffb21d_EOF - name: Mount MCP servers as CLIs id: mount-mcp-clis continue-on-error: true diff --git a/.github/workflows/prompt-clustering-analysis.md b/.github/workflows/prompt-clustering-analysis.md index 885f9fcc672..ecbeab1087c 100644 --- a/.github/workflows/prompt-clustering-analysis.md +++ b/.github/workflows/prompt-clustering-analysis.md @@ -27,7 +27,7 @@ imports: with: title-prefix: "[prompt-clustering] " expires: 1d - - shared/jqschema.md + - ../skills/jqschema/SKILL.md - shared/copilot-pr-data-fetch.md - shared/python-nlp.md diff --git a/.github/workflows/safe-output-health.lock.yml b/.github/workflows/safe-output-health.lock.yml index 8cfb66b8d20..536ef211a11 100644 --- a/.github/workflows/safe-output-health.lock.yml +++ b/.github/workflows/safe-output-health.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"f0025140e25161df7104dbca996567b1aafc45ec5946f6e2b6e1c17a0556e66c","strict":true,"agent_id":"claude"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"d4b315759297a783907787822b46f6e6654dd820ee177b5dceeaddc1879bef32","strict":true,"agent_id":"claude"} # gh-aw-manifest: {"version":1,"secrets":["ANTHROPIC_API_KEY","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_ENDPOINT","GH_AW_OTEL_HEADERS","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-go","sha":"4a3601121dd01d1626a1e23e37211e3254c1c06c","version":"v6.4.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"docker/build-push-action","sha":"bcafcacb16a39f128d818304e6c9c0c18556b85f","version":"v7.1.0"},{"repo":"docker/setup-buildx-action","sha":"4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd","version":"v4.0.0"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41","digest":"sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41@sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41","digest":"sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41@sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41","digest":"sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41@sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.6","digest":"sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c"},{"image":"ghcr.io/github/github-mcp-server:v1.0.3","digest":"sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} # ___ _ _ # / _ \ | | (_) @@ -26,9 +26,9 @@ # # Resolved workflow manifest: # Imports: +# - ../skills/jqschema/SKILL.md # - shared/aw-logs-24h-fetch.md # - shared/daily-audit-discussion.md -# - shared/jqschema.md # - shared/observability-otlp.md # - shared/reporting.md # - shared/daily-audit-base.md @@ -204,22 +204,22 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_6807e14c6cd05a07_EOF' + cat << 'GH_AW_PROMPT_ed406c1dd295ad84_EOF' - GH_AW_PROMPT_6807e14c6cd05a07_EOF + GH_AW_PROMPT_ed406c1dd295ad84_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/agentic_workflows_guide.md" cat "${RUNNER_TEMP}/gh-aw/prompts/cache_memory_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_6807e14c6cd05a07_EOF' + cat << 'GH_AW_PROMPT_ed406c1dd295ad84_EOF' Tools: create_discussion, missing_tool, missing_data, noop - GH_AW_PROMPT_6807e14c6cd05a07_EOF + GH_AW_PROMPT_ed406c1dd295ad84_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" - cat << 'GH_AW_PROMPT_6807e14c6cd05a07_EOF' + cat << 'GH_AW_PROMPT_ed406c1dd295ad84_EOF' The following GitHub context information is available for this workflow: {{#if __GH_AW_GITHUB_ACTOR__ }} @@ -248,17 +248,17 @@ jobs: {{/if}} - GH_AW_PROMPT_6807e14c6cd05a07_EOF + GH_AW_PROMPT_ed406c1dd295ad84_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_6807e14c6cd05a07_EOF' + cat << 'GH_AW_PROMPT_ed406c1dd295ad84_EOF' {{#runtime-import .github/workflows/shared/aw-logs-24h-fetch.md}} - {{#runtime-import .github/workflows/shared/jqschema.md}} + {{#runtime-import .github/skills/jqschema/SKILL.md}} {{#runtime-import .github/workflows/shared/observability-otlp.md}} {{#runtime-import .github/workflows/shared/reporting.md}} {{#runtime-import .github/workflows/shared/noop-reminder.md}} {{#runtime-import .github/workflows/safe-output-health.md}} - GH_AW_PROMPT_6807e14c6cd05a07_EOF + GH_AW_PROMPT_ed406c1dd295ad84_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -439,7 +439,10 @@ jobs: name: Download logs from last 24 hours run: ./gh-aw logs --start-date -1d -o /tmp/gh-aw/aw-mcp/logs - name: Setup jq utilities directory - run: "mkdir -p /tmp/gh-aw\ncat > /tmp/gh-aw/jqschema.sh << 'EOF'\n#!/usr/bin/env bash\n# jqschema.sh\njq -c '\ndef walk(f):\n . as $in |\n if type == \"object\" then\n reduce keys[] as $k ({}; . + {($k): ($in[$k] | walk(f))})\n elif type == \"array\" then\n if length == 0 then [] else [.[0] | walk(f)] end\n else\n type\n end;\nwalk(.)\n'\nEOF\nchmod +x /tmp/gh-aw/jqschema.sh\n" + run: | + mkdir -p /tmp/gh-aw + cp "$GITHUB_WORKSPACE/.github/skills/jqschema/jqschema.sh" /tmp/gh-aw/jqschema.sh + chmod +x /tmp/gh-aw/jqschema.sh # Cache memory file share configuration from frontmatter processed below - name: Create cache-memory directory @@ -553,9 +556,9 @@ jobs: 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_ee519ca6f12989f0_EOF' + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_1e6fd9157660f7c7_EOF' {"create_discussion":{"category":"audits","close_older_discussions":true,"expires":24,"fallback_to_issue":true,"max":1,"title_prefix":"[safe-output-health] "},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} - GH_AW_SAFE_OUTPUTS_CONFIG_ee519ca6f12989f0_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_1e6fd9157660f7c7_EOF - name: Generate Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -750,7 +753,7 @@ jobs: export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v /var/run/docker.sock:/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 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_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 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 GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -e GITHUB_AW_OTEL_TRACE_ID -e GITHUB_AW_OTEL_PARENT_SPAN_ID -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 ghcr.io/github/gh-aw-mcpg:v0.3.6' GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) - cat << GH_AW_MCP_CONFIG_dc8f0be72de9cc99_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_827076f14e61baf2_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "agenticworkflows": { @@ -814,7 +817,7 @@ jobs: } } } - GH_AW_MCP_CONFIG_dc8f0be72de9cc99_EOF + GH_AW_MCP_CONFIG_827076f14e61baf2_EOF - name: Mount MCP servers as CLIs id: mount-mcp-clis continue-on-error: true diff --git a/.github/workflows/safe-output-health.md b/.github/workflows/safe-output-health.md index f16584049f9..1e02b4cf50c 100644 --- a/.github/workflows/safe-output-health.md +++ b/.github/workflows/safe-output-health.md @@ -19,7 +19,7 @@ imports: title-prefix: "[safe-output-health] " expires: 1d - shared/aw-logs-24h-fetch.md - - shared/jqschema.md + - ../skills/jqschema/SKILL.md - shared/observability-otlp.md --- diff --git a/.github/workflows/scout.lock.yml b/.github/workflows/scout.lock.yml index 8f6d54de9ad..1123b296286 100644 --- a/.github/workflows/scout.lock.yml +++ b/.github/workflows/scout.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"5bd3efe25115439d15a37baea9ec087fb2ebb313146340230603a82466de75a7","strict":true,"agent_id":"claude"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"f0e66eadbf3c1e78ed235f7fcf27c880104c3922b4106161dbe49a17f21124d3","strict":true,"agent_id":"claude"} # gh-aw-manifest: {"version":1,"secrets":["ANTHROPIC_API_KEY","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_ENDPOINT","GH_AW_OTEL_HEADERS","GITHUB_TOKEN","TAVILY_API_KEY"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"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":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41","digest":"sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41@sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41","digest":"sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41@sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0"},{"image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.41","digest":"sha256:62171f2fa508667b8b0a9e096f826983f312e3da0ce894f80c0f83a875af60fe","pinned_image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.41@sha256:62171f2fa508667b8b0a9e096f826983f312e3da0ce894f80c0f83a875af60fe"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41","digest":"sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41@sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.6","digest":"sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c"},{"image":"ghcr.io/github/github-mcp-server:v1.0.3","digest":"sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959"},{"image":"mcp/arxiv-mcp-server","digest":"sha256:6dc6bba6dfed97f4ad6eb8d23a5c98ef5b7fa6184937d54b2d675801cd9dd29e","pinned_image":"mcp/arxiv-mcp-server@sha256:6dc6bba6dfed97f4ad6eb8d23a5c98ef5b7fa6184937d54b2d675801cd9dd29e"},{"image":"mcp/markitdown","digest":"sha256:1cef3bf502503310ed0884441874ccf6cdaac20136dc1179797fa048269dc4cb","pinned_image":"mcp/markitdown@sha256:1cef3bf502503310ed0884441874ccf6cdaac20136dc1179797fa048269dc4cb"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} # ___ _ _ # / _ \ | | (_) @@ -26,7 +26,7 @@ # # Resolved workflow manifest: # Imports: -# - shared/jqschema.md +# - ../skills/jqschema/SKILL.md # - shared/mcp/arxiv.md # - shared/mcp/deepwiki.md # - shared/mcp/markitdown.md @@ -297,21 +297,21 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_2e364aae077e08ca_EOF' + cat << 'GH_AW_PROMPT_53916e0a4be8b22d_EOF' - GH_AW_PROMPT_2e364aae077e08ca_EOF + GH_AW_PROMPT_53916e0a4be8b22d_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/cache_memory_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_2e364aae077e08ca_EOF' + cat << 'GH_AW_PROMPT_53916e0a4be8b22d_EOF' Tools: add_comment, add_labels, missing_tool, missing_data, noop - GH_AW_PROMPT_2e364aae077e08ca_EOF + GH_AW_PROMPT_53916e0a4be8b22d_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" - cat << 'GH_AW_PROMPT_2e364aae077e08ca_EOF' + cat << 'GH_AW_PROMPT_53916e0a4be8b22d_EOF' The following GitHub context information is available for this workflow: {{#if __GH_AW_GITHUB_ACTOR__ }} @@ -340,12 +340,12 @@ jobs: {{/if}} - GH_AW_PROMPT_2e364aae077e08ca_EOF + GH_AW_PROMPT_53916e0a4be8b22d_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/cli_proxy_with_safeoutputs_prompt.md" if [ "$GITHUB_EVENT_NAME" = "issue_comment" ] && [ -n "$GH_AW_IS_PR_COMMENT" ] || [ "$GITHUB_EVENT_NAME" = "pull_request_review_comment" ] || [ "$GITHUB_EVENT_NAME" = "pull_request_review" ]; then cat "${RUNNER_TEMP}/gh-aw/prompts/pr_context_prompt.md" fi - cat << 'GH_AW_PROMPT_2e364aae077e08ca_EOF' + cat << 'GH_AW_PROMPT_53916e0a4be8b22d_EOF' {{#runtime-import .github/workflows/shared/reporting.md}} {{#runtime-import .github/workflows/shared/mcp/arxiv.md}} @@ -353,11 +353,11 @@ jobs: {{#runtime-import .github/workflows/shared/mcp/microsoft-docs.md}} {{#runtime-import .github/workflows/shared/mcp/deepwiki.md}} {{#runtime-import .github/workflows/shared/mcp/markitdown.md}} - {{#runtime-import .github/workflows/shared/jqschema.md}} + {{#runtime-import .github/skills/jqschema/SKILL.md}} {{#runtime-import .github/workflows/shared/observability-otlp.md}} {{#runtime-import .github/workflows/shared/noop-reminder.md}} {{#runtime-import .github/workflows/scout.md}} - GH_AW_PROMPT_2e364aae077e08ca_EOF + GH_AW_PROMPT_53916e0a4be8b22d_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -520,7 +520,10 @@ jobs: env: GH_TOKEN: ${{ github.token }} - name: Setup jq utilities directory - run: "mkdir -p /tmp/gh-aw\ncat > /tmp/gh-aw/jqschema.sh << 'EOF'\n#!/usr/bin/env bash\n# jqschema.sh\njq -c '\ndef walk(f):\n . as $in |\n if type == \"object\" then\n reduce keys[] as $k ({}; . + {($k): ($in[$k] | walk(f))})\n elif type == \"array\" then\n if length == 0 then [] else [.[0] | walk(f)] end\n else\n type\n end;\nwalk(.)\n'\nEOF\nchmod +x /tmp/gh-aw/jqschema.sh\n" + run: | + mkdir -p /tmp/gh-aw + cp "$GITHUB_WORKSPACE/.github/skills/jqschema/jqschema.sh" /tmp/gh-aw/jqschema.sh + chmod +x /tmp/gh-aw/jqschema.sh # Cache memory file share configuration from frontmatter processed below - name: Create cache-memory directory @@ -603,9 +606,9 @@ jobs: 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_27cd2e632bf0c881_EOF' + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_f985bd20b76e5f75_EOF' {"add_comment":{"max":1},"add_labels":{"max":1},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} - GH_AW_SAFE_OUTPUTS_CONFIG_27cd2e632bf0c881_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_f985bd20b76e5f75_EOF - name: Generate Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -813,7 +816,7 @@ jobs: export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v /var/run/docker.sock:/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 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_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 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 GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -e GITHUB_AW_OTEL_TRACE_ID -e GITHUB_AW_OTEL_PARENT_SPAN_ID -e TAVILY_API_KEY -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 ghcr.io/github/gh-aw-mcpg:v0.3.6' GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) - cat << GH_AW_MCP_CONFIG_c532768f8d223a1f_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_4fc128b59de2a442_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "arxiv": { @@ -924,7 +927,7 @@ jobs: } } } - GH_AW_MCP_CONFIG_c532768f8d223a1f_EOF + GH_AW_MCP_CONFIG_4fc128b59de2a442_EOF - name: Mount MCP servers as CLIs id: mount-mcp-clis continue-on-error: true diff --git a/.github/workflows/scout.md b/.github/workflows/scout.md index 3c68cb74e2e..35b7878dc10 100644 --- a/.github/workflows/scout.md +++ b/.github/workflows/scout.md @@ -30,7 +30,7 @@ imports: - shared/mcp/microsoft-docs.md - shared/mcp/deepwiki.md - shared/mcp/markitdown.md - - shared/jqschema.md + - ../skills/jqschema/SKILL.md - shared/observability-otlp.md tools: cli-proxy: true diff --git a/.github/workflows/shared/ci-data-analysis.md b/.github/workflows/shared/ci-data-analysis.md index 082c7af162b..4f71453bfc4 100644 --- a/.github/workflows/shared/ci-data-analysis.md +++ b/.github/workflows/shared/ci-data-analysis.md @@ -12,7 +12,7 @@ # - Collect performance metrics imports: - - shared/jqschema.md + - ../skills/jqschema/SKILL.md tools: cache-memory: true diff --git a/.github/workflows/shared/copilot-pr-analysis-base.md b/.github/workflows/shared/copilot-pr-analysis-base.md index dc51cf1e6b6..cb36ea7fac2 100644 --- a/.github/workflows/shared/copilot-pr-analysis-base.md +++ b/.github/workflows/shared/copilot-pr-analysis-base.md @@ -6,7 +6,7 @@ tools: bash: ["*"] imports: - - shared/jqschema.md + - ../skills/jqschema/SKILL.md - shared/reporting.md - shared/copilot-pr-data-fetch.md --- diff --git a/.github/workflows/shared/copilot-pr-data-fetch.md b/.github/workflows/shared/copilot-pr-data-fetch.md index 59766d5f9f3..8a03298292d 100644 --- a/.github/workflows/shared/copilot-pr-data-fetch.md +++ b/.github/workflows/shared/copilot-pr-data-fetch.md @@ -116,7 +116,7 @@ Import this component in your workflow: ```yaml imports: - shared/copilot-pr-data-fetch.md - - shared/jqschema.md # Required for schema generation + - ../skills/jqschema/SKILL.md # Required for schema generation ``` Then access the pre-fetched data in your workflow prompt: @@ -135,7 +135,7 @@ jq '[.[].number]' /tmp/gh-aw/pr-data/copilot-prs.json ### Requirements -- Requires `jqschema.md` to be imported for schema generation +- Requires the `jqschema` skill to be imported for schema generation - Uses `gh pr list` with the `--search "head:copilot/"` pattern for reliable Copilot PR detection - Cross-platform date calculation (works on both GNU and BSD date commands) - Cache-memory tool is automatically configured for data persistence diff --git a/.github/workflows/shared/copilot-session-data-fetch.md b/.github/workflows/shared/copilot-session-data-fetch.md index dfe804c7591..95231d882d7 100644 --- a/.github/workflows/shared/copilot-session-data-fetch.md +++ b/.github/workflows/shared/copilot-session-data-fetch.md @@ -1,16 +1,16 @@ --- -# This shared component depends on jqschema.md being imported first. +# This shared component depends on the jqschema skill being imported first. # # NOTE: Due to BFS import ordering, transitive imports are not guaranteed to have their # steps executed before the parent import's steps. To ensure correct execution order, -# import jqschema.md directly in your workflow BEFORE importing this file: +# import the jqschema skill directly in your workflow BEFORE importing this file: # # imports: -# - shared/jqschema.md # Must come first +# - ../skills/jqschema/SKILL.md # Must come first # - shared/copilot-session-data-fetch.md # imports: - - shared/jqschema.md + - ../skills/jqschema/SKILL.md tools: cache-memory: @@ -214,7 +214,7 @@ imports: - shared/copilot-session-data-fetch.md ``` -**Note**: This component automatically imports `jqschema.md` as a dependency. The compiler handles the transitive closure of imports, ensuring all required utilities are set up in the correct order. +**Note**: This component automatically imports the `jqschema` skill as a dependency. The compiler handles the transitive closure of imports, ensuring all required utilities are set up in the correct order. Then access the pre-fetched data in your workflow prompt: @@ -238,7 +238,7 @@ cat /tmp/gh-aw/session-data/logs/123-conversation.txt ### Requirements -- Automatically imports `jqschema.md` for schema generation (via transitive import closure) +- Automatically imports the `jqschema` skill for schema generation (via transitive import closure) - Uses GitHub Actions API to fetch workflow runs from `copilot/*` branches - **Uses `gh agent-task view --log` to fetch conversation transcripts** (requires gh CLI v2.80.0+) - Cross-platform date calculation (works on both GNU and BSD date commands) diff --git a/.github/workflows/shared/discussions-data-fetch.md b/.github/workflows/shared/discussions-data-fetch.md index fc6a5a6a54f..ba3388e21ac 100644 --- a/.github/workflows/shared/discussions-data-fetch.md +++ b/.github/workflows/shared/discussions-data-fetch.md @@ -192,7 +192,7 @@ This shared component fetches open discussions from the repository, with intelli ### Requirements -- Requires `jqschema.md` to be imported for schema generation +- Requires the `jqschema` skill to be imported for schema generation - Uses GitHub GraphQL API to fetch open discussions - Cache-memory tool is automatically configured for data persistence --> diff --git a/.github/workflows/shared/issues-data-fetch.md b/.github/workflows/shared/issues-data-fetch.md index 20ecea21ce6..b644ac875dd 100644 --- a/.github/workflows/shared/issues-data-fetch.md +++ b/.github/workflows/shared/issues-data-fetch.md @@ -109,7 +109,7 @@ This shared component fetches up to 1000 issues from the repository, with intell ### Requirements -- Requires `jqschema.md` to be imported for schema generation +- Requires the `jqschema` skill to be imported for schema generation - Uses `gh issue list` with `--state all` to get both open and closed issues - Cache-memory tool is automatically configured for data persistence --> diff --git a/.github/workflows/shared/weekly-issues-data-fetch.md b/.github/workflows/shared/weekly-issues-data-fetch.md index 891c2565a08..39b4123b416 100644 --- a/.github/workflows/shared/weekly-issues-data-fetch.md +++ b/.github/workflows/shared/weekly-issues-data-fetch.md @@ -112,7 +112,7 @@ This shared component fetches issues from the last 7 days, with intelligent cach ### Requirements -- Requires `jqschema.md` to be imported for schema generation +- Requires the `jqschema` skill to be imported for schema generation - Uses `gh issue list` with `--search "updated:>=[DATE]"` to get recent activity - Cross-platform date calculation (works on both GNU and BSD date commands) - Cache-memory tool is automatically configured for data persistence diff --git a/.github/workflows/stale-repo-identifier.lock.yml b/.github/workflows/stale-repo-identifier.lock.yml index eee87a46e07..91aa399ce75 100644 --- a/.github/workflows/stale-repo-identifier.lock.yml +++ b/.github/workflows/stale-repo-identifier.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"5c2a504240dd4074c4366f5cec594b2b6bea3e8ef7eda05f7dce105e19b98aa2","strict":true,"agent_id":"copilot"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"58380325c1aec7a875c6da16d2946dbbfb20c5bf9be319c2ae322d4d789ab873","strict":true,"agent_id":"copilot"} # gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_ENDPOINT","GH_AW_OTEL_HEADERS","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"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":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/setup-python","sha":"a309ff8b426b58ec0e2a45f0f869d46889d02405","version":"v6.2.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/stale-repos","sha":"5f2e18fc5432823f96c1feb69327f665c2acab59","version":"v9.0.8"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41","digest":"sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41@sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41","digest":"sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41@sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0"},{"image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.41","digest":"sha256:62171f2fa508667b8b0a9e096f826983f312e3da0ce894f80c0f83a875af60fe","pinned_image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.41@sha256:62171f2fa508667b8b0a9e096f826983f312e3da0ce894f80c0f83a875af60fe"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41","digest":"sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41@sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.6","digest":"sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c"},{"image":"ghcr.io/github/github-mcp-server:v1.0.3","digest":"sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} # ___ _ _ # / _ \ | | (_) @@ -26,9 +26,9 @@ # # Resolved workflow manifest: # Imports: +# - ../skills/jqschema/SKILL.md # - shared/daily-audit-discussion.md # - shared/github-guard-policy.md -# - shared/jqschema.md # - shared/observability-otlp.md # - shared/reporting.md # - shared/daily-audit-base.md @@ -214,23 +214,23 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_f132e7ae654dc146_EOF' + cat << 'GH_AW_PROMPT_64a23ad700a6f7ab_EOF' - GH_AW_PROMPT_f132e7ae654dc146_EOF + GH_AW_PROMPT_64a23ad700a6f7ab_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/cache_memory_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_f132e7ae654dc146_EOF' + cat << 'GH_AW_PROMPT_64a23ad700a6f7ab_EOF' Tools: add_comment(max:5), create_issue(max:10), create_discussion, upload_asset(max:5), missing_tool, missing_data, noop upload_asset: provide a file path; returns a URL; assets are published after the workflow completes (safeoutputs). - GH_AW_PROMPT_f132e7ae654dc146_EOF + GH_AW_PROMPT_64a23ad700a6f7ab_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" - cat << 'GH_AW_PROMPT_f132e7ae654dc146_EOF' + cat << 'GH_AW_PROMPT_64a23ad700a6f7ab_EOF' The following GitHub context information is available for this workflow: {{#if __GH_AW_GITHUB_ACTOR__ }} @@ -259,18 +259,18 @@ jobs: {{/if}} - GH_AW_PROMPT_f132e7ae654dc146_EOF + GH_AW_PROMPT_64a23ad700a6f7ab_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/cli_proxy_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_f132e7ae654dc146_EOF' + cat << 'GH_AW_PROMPT_64a23ad700a6f7ab_EOF' {{#runtime-import .github/workflows/shared/github-guard-policy.md}} - {{#runtime-import .github/workflows/shared/jqschema.md}} + {{#runtime-import .github/skills/jqschema/SKILL.md}} {{#runtime-import .github/workflows/shared/observability-otlp.md}} {{#runtime-import .github/workflows/shared/trending-charts-simple.md}} {{#runtime-import .github/workflows/shared/reporting.md}} {{#runtime-import .github/workflows/shared/noop-reminder.md}} {{#runtime-import .github/workflows/stale-repo-identifier.md}} - GH_AW_PROMPT_f132e7ae654dc146_EOF + GH_AW_PROMPT_64a23ad700a6f7ab_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -439,22 +439,7 @@ jobs: - name: Setup jq utilities directory run: | mkdir -p /tmp/gh-aw - cat > /tmp/gh-aw/jqschema.sh << 'EOF' - #!/usr/bin/env bash - # jqschema.sh - jq -c ' - def walk(f): - . as $in | - if type == "object" then - reduce keys[] as $k ({}; . + {($k): ($in[$k] | walk(f))}) - elif type == "array" then - if length == 0 then [] else [.[0] | walk(f)] end - else - type - end; - walk(.) - ' - EOF + cp "$GITHUB_WORKSPACE/.github/skills/jqschema/jqschema.sh" /tmp/gh-aw/jqschema.sh chmod +x /tmp/gh-aw/jqschema.sh env: GH_HOST: localhost:18443 @@ -606,9 +591,9 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs/upload-artifacts" - cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << GH_AW_SAFE_OUTPUTS_CONFIG_48fb85f9df1170b4_EOF + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << GH_AW_SAFE_OUTPUTS_CONFIG_111efb238b522317_EOF {"add_comment":{"max":5},"create_discussion":{"category":"audits","close_older_discussions":true,"expires":72,"fallback_to_issue":true,"max":1,"title_prefix":"[stale-repo-identifier] "},"create_issue":{"expires":48,"group":true,"labels":["stale-repository","automated-analysis","cookie"],"max":10,"title_prefix":"[Stale Repository] "},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{},"upload_artifact":{"allowed-paths":["**/*.png","**/*.jpg","**/*.svg"],"max-size-bytes":104857600,"max-uploads":5,"retention-days":30,"skip-archive":true},"upload_asset":{"allowed-exts":[".png",".jpg",".jpeg",".svg"],"branch":"assets/${GITHUB_WORKFLOW}","max":5,"max-size":10240}} - GH_AW_SAFE_OUTPUTS_CONFIG_48fb85f9df1170b4_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_111efb238b522317_EOF - name: Generate Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -873,7 +858,7 @@ jobs: mkdir -p /home/runner/.copilot GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) - cat << GH_AW_MCP_CONFIG_48bc4930497c79f5_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_27e0452e1344069e_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "safeoutputs": { @@ -904,7 +889,7 @@ jobs: } } } - GH_AW_MCP_CONFIG_48bc4930497c79f5_EOF + GH_AW_MCP_CONFIG_27e0452e1344069e_EOF - name: Mount MCP servers as CLIs id: mount-mcp-clis continue-on-error: true diff --git a/.github/workflows/stale-repo-identifier.md b/.github/workflows/stale-repo-identifier.md index 3620c059b8e..7c3c3c53363 100644 --- a/.github/workflows/stale-repo-identifier.md +++ b/.github/workflows/stale-repo-identifier.md @@ -29,7 +29,7 @@ imports: - uses: shared/daily-audit-charts.md with: title-prefix: "[stale-repo-identifier] " - - shared/jqschema.md + - ../skills/jqschema/SKILL.md - shared/observability-otlp.md network: diff --git a/pkg/actionpins/spec_test.go b/pkg/actionpins/spec_test.go index 957ffeb00a8..5c3988e35a3 100644 --- a/pkg/actionpins/spec_test.go +++ b/pkg/actionpins/spec_test.go @@ -326,7 +326,6 @@ func TestSpec_DynamicResolution_VersionCommentConsistency(t *testing.T) { }) } - // TestSpec_PublicAPI_GetActionPins_SPEC_MISMATCH documents a spec-implementation gap. // SPEC_MISMATCH: The README specifies GetActionPins() []ActionPin ("Returns all loaded pins") // but this function is not implemented. Only GetActionPinsByRepo(repo string) is available. diff --git a/pkg/cli/workflows/shared/jqschema.md b/pkg/cli/workflows/shared/jqschema.md index d74169ca348..3ce6dbba27e 100644 --- a/pkg/cli/workflows/shared/jqschema.md +++ b/pkg/cli/workflows/shared/jqschema.md @@ -1,5 +1,25 @@ -# jqschema utility +--- +name: jqschema +description: JSON schema discovery utility that extracts structure and type information from JSON data +tools: + bash: + - "jq *" + - "/tmp/gh-aw/jqschema.sh" + - "git" +steps: + - name: Setup jq utilities directory + run: | + mkdir -p /tmp/gh-aw + cp "$GITHUB_WORKSPACE/.github/skills/jqschema/jqschema.sh" /tmp/gh-aw/jqschema.sh + chmod +x /tmp/gh-aw/jqschema.sh +--- -This is a placeholder for the jqschema utility import. +## jqschema - JSON Schema Discovery -The jqschema.sh script should be used to extract JSON structure and type information. +A utility script is available at `/tmp/gh-aw/jqschema.sh` to help you discover the structure of complex JSON responses. + +### Usage + +```bash +cat data.json | /tmp/gh-aw/jqschema.sh +``` From c5538f41e410cbee1b8053d9a983fb3b53d5b46e Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Fri, 8 May 2026 12:30:47 -0700 Subject: [PATCH 2/8] Apply console.Format helpers to high-traffic CLI stderr output paths (#31068) * Initial plan * chore: outline console formatting fix plan Agent-Logs-Url: https://github.com/github/gh-aw/sessions/15373968-96a0-4486-9c15-f2f8fed316f9 Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com> * fix: format high-traffic cli stderr messages Agent-Logs-Url: https://github.com/github/gh-aw/sessions/15373968-96a0-4486-9c15-f2f8fed316f9 Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com> * test: harden cli stderr formatting coverage Agent-Logs-Url: https://github.com/github/gh-aw/sessions/15373968-96a0-4486-9c15-f2f8fed316f9 Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com> * style: refine cli stderr formatting assertions Agent-Logs-Url: https://github.com/github/gh-aw/sessions/15373968-96a0-4486-9c15-f2f8fed316f9 Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com> Co-authored-by: Peli de Halleux --- pkg/cli/add_interactive_engine.go | 2 +- pkg/cli/add_interactive_secrets_test.go | 35 ++++++++++++ pkg/cli/commands_file_watching_test.go | 72 +++++++++++++++++++++++++ pkg/cli/compile_file_operations.go | 7 ++- 4 files changed, 111 insertions(+), 5 deletions(-) diff --git a/pkg/cli/add_interactive_engine.go b/pkg/cli/add_interactive_engine.go index 5d7c17bc351..67acb435465 100644 --- a/pkg/cli/add_interactive_engine.go +++ b/pkg/cli/add_interactive_engine.go @@ -74,7 +74,7 @@ func (c *AddInteractiveConfig) selectAIEngineAndKey() error { // If engine is already overridden, skip selection if c.EngineOverride != "" { - fmt.Fprintf(os.Stderr, "Using coding agent: %s\n", c.EngineOverride) + fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf("Using coding agent: %s", c.EngineOverride))) return c.configureEngineAPISecret(c.EngineOverride) } diff --git a/pkg/cli/add_interactive_secrets_test.go b/pkg/cli/add_interactive_secrets_test.go index f68a9bfec67..58095427501 100644 --- a/pkg/cli/add_interactive_secrets_test.go +++ b/pkg/cli/add_interactive_secrets_test.go @@ -3,9 +3,13 @@ package cli import ( + "bytes" + "context" + "io" "os" "testing" + "github.com/github/gh-aw/pkg/console" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -169,6 +173,37 @@ func TestAddInteractiveConfig_configureEngineAPISecret_skipSecret(t *testing.T) } } +func TestAddInteractiveConfig_selectAIEngineAndKey_engineOverrideFormatsInfoMessage(t *testing.T) { + config := &AddInteractiveConfig{ + Ctx: context.Background(), + EngineOverride: "copilot", + SkipSecret: true, + RepoOverride: "owner/repo", + } + + oldStderr := os.Stderr + r, w, err := os.Pipe() + require.NoError(t, err, "Failed to create stderr pipe") + os.Stderr = w + t.Cleanup(func() { os.Stderr = oldStderr }) + + err = config.selectAIEngineAndKey() + + w.Close() + + var buf bytes.Buffer + _, copyErr := io.Copy(&buf, r) + require.NoError(t, copyErr, "Failed to read stderr output") + require.NoError(t, err, "selectAIEngineAndKey should succeed with an explicit engine override") + + assert.Contains( + t, + buf.String(), + console.FormatInfoMessage("Using coding agent: copilot"), + "Expected engine override path to use formatted info output", + ) +} + func TestParseSecretNames(t *testing.T) { tests := []struct { name string diff --git a/pkg/cli/commands_file_watching_test.go b/pkg/cli/commands_file_watching_test.go index bac66f6883e..a765005bd5a 100644 --- a/pkg/cli/commands_file_watching_test.go +++ b/pkg/cli/commands_file_watching_test.go @@ -3,14 +3,17 @@ package cli import ( + "bytes" "context" "fmt" + "io" "os" "path/filepath" "strings" "testing" "time" + "github.com/github/gh-aw/pkg/console" "github.com/github/gh-aw/pkg/stringutil" "github.com/github/gh-aw/pkg/testutil" @@ -439,6 +442,40 @@ func TestCompileSingleFile(t *testing.T) { } }) + t.Run("compile single file formats errors for stderr", func(t *testing.T) { + tempDir := testutil.TempDir(t, "test-*") + workflowsDir := filepath.Join(tempDir, ".github/workflows") + os.MkdirAll(workflowsDir, 0755) + + filePath := filepath.Join(workflowsDir, "invalid.md") + content := "---\nmalformed: yaml: content:\n - missing\n proper: structure\n---\n# Invalid\n" + os.WriteFile(filePath, []byte(content), 0644) + + compiler := workflow.NewCompiler() + stats := &CompilationStats{} + + oldStderr := os.Stderr + r, w, err := os.Pipe() + require.NoError(t, err, "Failed to create stderr pipe") + os.Stderr = w + t.Cleanup(func() { os.Stderr = oldStderr }) + + result := compileSingleFile(compiler, filePath, stats, false, false) + + w.Close() + + var buf bytes.Buffer + _, err = io.Copy(&buf, r) + require.NoError(t, err, "Failed to read stderr output") + + strippedOutput := stringutil.StripANSI(buf.String()) + + assert.True(t, result, "Expected compilation to be attempted") + assert.Contains(t, strippedOutput, "✗", "Expected compile errors to include the formatted error marker") + assert.Contains(t, strippedOutput, "invalid.md", "Expected stderr output to identify the failing workflow") + assert.Contains(t, strippedOutput, "unexpected ':'", "Expected stderr output to include the compiler error details") + }) + t.Run("compile single file with checkExists true and file exists", func(t *testing.T) { tempDir := testutil.TempDir(t, "test-*") workflowsDir := filepath.Join(tempDir, ".github/workflows") @@ -516,3 +553,38 @@ func TestCompileSingleFile(t *testing.T) { } }) } + +func TestCompileModifiedFilesWithDependencies_FormatsWatchMessage(t *testing.T) { + tempDir := testutil.TempDir(t, "test-*") + workflowsDir := filepath.Join(tempDir, ".github/workflows") + require.NoError(t, os.MkdirAll(workflowsDir, 0755), "Failed to create workflows directory") + + filePath := filepath.Join(workflowsDir, "test.md") + content := "---\non: push\nengine: claude\n---\n# Test\n\nTest workflow content" + require.NoError(t, os.WriteFile(filePath, []byte(content), 0644), "Failed to write workflow file") + + compiler := workflow.NewCompiler() + depGraph := NewDependencyGraph(workflowsDir) + require.NoError(t, depGraph.BuildGraph(compiler), "Failed to build dependency graph") + + oldStderr := os.Stderr + r, w, err := os.Pipe() + require.NoError(t, err, "Failed to create stderr pipe") + os.Stderr = w + t.Cleanup(func() { os.Stderr = oldStderr }) + + compileModifiedFilesWithDependencies(compiler, depGraph, []string{filePath}, false) + + w.Close() + + var buf bytes.Buffer + _, err = io.Copy(&buf, r) + require.NoError(t, err, "Failed to read stderr output") + + assert.Contains( + t, + buf.String(), + console.FormatProgressMessage("Watching for file changes"), + "Expected watch mode to use formatted progress output", + ) +} diff --git a/pkg/cli/compile_file_operations.go b/pkg/cli/compile_file_operations.go index d8eec5f0101..b29817f6341 100644 --- a/pkg/cli/compile_file_operations.go +++ b/pkg/cli/compile_file_operations.go @@ -69,9 +69,8 @@ func compileSingleFile(compiler *workflow.Compiler, file string, stats *Compilat } if err := CompileWorkflowWithValidation(compiler, file, verbose, false, false, false, false, false); err != nil { - // Always show compilation errors on new line - // Note: Don't wrap in FormatErrorMessage as the error is already formatted by console.FormatError - fmt.Fprintln(os.Stderr, err.Error()) + // Always show compilation errors on a new line using standard CLI error styling. + fmt.Fprintln(os.Stderr, console.FormatErrorMessage(err.Error())) stats.Errors++ stats.FailedWorkflows = append(stats.FailedWorkflows, filepath.Base(file)) } else { @@ -171,7 +170,7 @@ func compileModifiedFilesWithDependencies(compiler *workflow.Compiler, depGraph } } - fmt.Fprintln(os.Stderr, "Watching for file changes") + fmt.Fprintln(os.Stderr, console.FormatProgressMessage("Watching for file changes")) if verbose { fmt.Fprintln(os.Stderr, console.FormatProgressMessage(fmt.Sprintf("Recompiling %d workflow(s) affected by %d change(s)...", len(workflowsToCompile), len(files)))) } From b77112c665d86015d5d430ea60b73911be7973c4 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Fri, 8 May 2026 12:40:49 -0700 Subject: [PATCH 3/8] fix: use pure Go filesystem traversal for git repo detection (fixes macOS ARM64 / Rosetta 2 failure) (#31050) * Initial plan * chore: planning git detection fix for macOS ARM64 Agent-Logs-Url: https://github.com/github/gh-aw/sessions/82628923-30ee-4061-af73-61b141aba2e4 Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com> * fix: replace exec.Command git detection with pure Go filesystem traversal Fixes `gh aw init` failing with "not in a git repository" on macOS ARM64 (Apple Silicon) when the x86_64 binary runs under Rosetta 2. Previously, `isGitRepo()` and `FindGitRoot()` used `exec.Command("git", ...)` to detect git repositories. Under Rosetta 2 (x86_64 emulation on ARM64), this subprocess call can silently fail due to PATH differences or OS-level subprocess restrictions. Replace with pure Go filesystem traversal: walk up from the current directory (or a given starting directory) looking for a `.git` entry (directory or file, handling both normal repos and worktrees). This eliminates the dependency on the `git` executable for repository detection, making it work regardless of architecture, Rosetta translation, or git installation state. Changes: - `pkg/gitutil/gitutil.go`: `FindGitRoot()` now uses `os.Stat`/`filepath.Dir` traversal; new exported `FindGitRootFrom(startDir)` helper for callers that start from a specific directory - `pkg/cli/git.go`: `isGitRepo()` delegates to `gitutil.FindGitRoot()`; `findGitRootForPath()` uses `gitutil.FindGitRootFrom(dir)` instead of exec - `pkg/gitutil/gitutil_test.go`: add `TestFindGitRootFrom` tests - `pkg/gitutil/spec_test.go`: update doc comment to reflect new implementation Agent-Logs-Url: https://github.com/github/gh-aw/sessions/82628923-30ee-4061-af73-61b141aba2e4 Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com> * fix: address code review feedback - fix error message and improve test robustness Agent-Logs-Url: https://github.com/github/gh-aw/sessions/82628923-30ee-4061-af73-61b141aba2e4 Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com> * chore: merge main and recompile workflow lock files Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> * fix: improve FindGitRootFrom robustness and add worktree/edge-case tests Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com> Co-authored-by: Peli de Halleux Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- pkg/cli/git.go | 10 ++--- pkg/gitutil/gitutil.go | 66 +++++++++++++++++++++++++--- pkg/gitutil/gitutil_test.go | 85 +++++++++++++++++++++++++++++++++++++ pkg/gitutil/spec_test.go | 5 ++- 4 files changed, 151 insertions(+), 15 deletions(-) diff --git a/pkg/cli/git.go b/pkg/cli/git.go index 527b2105e97..953405525b7 100644 --- a/pkg/cli/git.go +++ b/pkg/cli/git.go @@ -18,8 +18,8 @@ import ( var gitLog = logger.New("cli:git") func isGitRepo() bool { - cmd := exec.Command("git", "rev-parse", "--git-dir") - return cmd.Run() == nil + _, err := gitutil.FindGitRoot() + return err == nil } // findGitRootForPath finds the root directory of the git repository containing the specified path @@ -41,13 +41,11 @@ func findGitRootForPath(path string) (string, error) { // Use the directory containing the file dir := filepath.Dir(absPath) - // Run git command in the file's directory - cmd := exec.Command("git", "-C", dir, "rev-parse", "--show-toplevel") - output, err := cmd.Output() + // Find git root using filesystem traversal from the file's directory + gitRoot, err := gitutil.FindGitRootFrom(dir) if err != nil { return "", fmt.Errorf("failed to get repository root for path %s: %w", path, err) } - gitRoot := strings.TrimSpace(string(output)) gitLog.Printf("Found git root for path: %s", gitRoot) return gitRoot, nil } diff --git a/pkg/gitutil/gitutil.go b/pkg/gitutil/gitutil.go index 5ffb76626ea..497d9c92b17 100644 --- a/pkg/gitutil/gitutil.go +++ b/pkg/gitutil/gitutil.go @@ -1,7 +1,9 @@ package gitutil import ( + "errors" "fmt" + "os" "os/exec" "path/filepath" "regexp" @@ -75,18 +77,68 @@ func ExtractBaseRepo(repoPath string) string { } // FindGitRoot finds the root directory of the git repository. -// Returns an error if not in a git repository or if the git command fails. +// Uses pure Go filesystem traversal to avoid requiring the git executable, +// which can fail when the binary runs under Rosetta 2 on macOS ARM64 or in +// environments where git is not on PATH. +// Returns an error if not in a git repository. func FindGitRoot() (string, error) { log.Print("Finding git root directory") - cmd := exec.Command("git", "rev-parse", "--show-toplevel") - output, err := cmd.Output() + + dir, err := os.Getwd() + if err != nil { + log.Printf("Failed to get current directory: %v", err) + return "", fmt.Errorf("failed to get current directory: %w", err) + } + + root, err := FindGitRootFrom(dir) if err != nil { log.Printf("Failed to find git root: %v", err) - return "", fmt.Errorf("not in a git repository or git command failed: %w", err) + return "", err + } + + log.Printf("Found git root: %s", root) + return root, nil +} + +// FindGitRootFrom finds the root directory of the git repository starting from +// the given directory. It traverses upward until it finds a .git entry (file or +// directory) or reaches the filesystem root. +// Returns an error if not in a git repository. +func FindGitRootFrom(startDir string) (string, error) { + dir, err := filepath.Abs(startDir) + if err != nil { + return "", fmt.Errorf("failed to resolve absolute path for %q: %w", startDir, err) + } + dir = filepath.Clean(dir) + for { + gitPath := filepath.Join(dir, ".git") + info, err := os.Stat(gitPath) + if err == nil { + // .git exists — accept if it's a directory (normal repo) or a + // regular file (worktree / git-submodule pointer). + if info.IsDir() { + return dir, nil + } + // Worktree marker: must be a regular file beginning with "gitdir:" + if info.Mode().IsRegular() { + data, readErr := os.ReadFile(gitPath) + if readErr != nil { + return "", fmt.Errorf("failed to read .git file at %q: %w", gitPath, readErr) + } + if strings.HasPrefix(strings.TrimSpace(string(data)), "gitdir:") { + return dir, nil + } + } + } else if !errors.Is(err, os.ErrNotExist) { + // Unexpected error (e.g. permission denied) — surface it. + return "", fmt.Errorf("failed to stat %q: %w", gitPath, err) + } + parent := filepath.Dir(dir) + if parent == dir { + return "", errors.New("not in a git repository") + } + dir = parent } - gitRoot := strings.TrimSpace(string(output)) - log.Printf("Found git root: %s", gitRoot) - return gitRoot, nil } // ReadFileFromHEADWithRoot is like ReadFileFromHEAD but accepts a pre-computed git diff --git a/pkg/gitutil/gitutil_test.go b/pkg/gitutil/gitutil_test.go index bfb87542295..ec542ac4e57 100644 --- a/pkg/gitutil/gitutil_test.go +++ b/pkg/gitutil/gitutil_test.go @@ -3,6 +3,7 @@ package gitutil import ( + "os" "path/filepath" "testing" @@ -293,6 +294,90 @@ func TestFindGitRoot(t *testing.T) { }) } +func TestFindGitRootFrom(t *testing.T) { + t.Run("returns git root from the repository root itself", func(t *testing.T) { + gitRoot, err := FindGitRoot() + require.NoError(t, err, "must be inside a git repository") + + root, err := FindGitRootFrom(gitRoot) + require.NoError(t, err, "FindGitRootFrom should succeed when starting from the git root") + assert.Equal(t, gitRoot, root, "FindGitRootFrom from git root should return git root") + }) + + t.Run("returns git root from a subdirectory", func(t *testing.T) { + gitRoot, err := FindGitRoot() + require.NoError(t, err, "must be inside a git repository") + + // Create a temporary subdirectory inside the repo to avoid depending on + // specific repo layout (e.g. pkg/ may not exist in all test environments). + subDir, mkdirErr := os.MkdirTemp(gitRoot, "test-subdir-*") + require.NoError(t, mkdirErr, "should create temp subdir inside git repo") + defer os.RemoveAll(subDir) + + root, err := FindGitRootFrom(subDir) + require.NoError(t, err, "FindGitRootFrom should succeed from a subdirectory") + assert.Equal(t, gitRoot, root, "FindGitRootFrom from subdirectory should return the git root") + }) + + t.Run("returns error when starting outside any git repository", func(t *testing.T) { + tmpDir := t.TempDir() + // Create a nested directory that is definitely not a git repo + nonRepoDir := filepath.Join(tmpDir, "not-a-git-repo", "subdir") + require.NoError(t, os.MkdirAll(nonRepoDir, 0755), "should create nested temp dir") + + _, err := FindGitRootFrom(nonRepoDir) + require.Error(t, err, "FindGitRootFrom should return error outside a git repository") + assert.Contains(t, err.Error(), "not in a git repository", "error should mention not in git repository") + }) + + t.Run("returns git root when .git is a worktree marker file", func(t *testing.T) { + // Simulate a git worktree: the repo root has a .git *file* (not dir) + // whose content begins with "gitdir: /some/path" + tmpDir := t.TempDir() + repoRoot := filepath.Join(tmpDir, "worktree-repo") + require.NoError(t, os.MkdirAll(repoRoot, 0755)) + + // Write a valid worktree .git file + gitFile := filepath.Join(repoRoot, ".git") + require.NoError(t, os.WriteFile(gitFile, []byte("gitdir: /tmp/real-repo/.git/worktrees/myworktree\n"), 0644)) + + // Start from the root itself + root, err := FindGitRootFrom(repoRoot) + require.NoError(t, err, "FindGitRootFrom should detect a worktree .git file") + assert.Equal(t, repoRoot, root) + + // Start from a subdirectory inside the worktree + subDir := filepath.Join(repoRoot, "pkg", "sub") + require.NoError(t, os.MkdirAll(subDir, 0755)) + root, err = FindGitRootFrom(subDir) + require.NoError(t, err, "FindGitRootFrom should detect worktree root from a subdirectory") + assert.Equal(t, repoRoot, root) + }) + + t.Run("ignores non-worktree .git files without gitdir prefix", func(t *testing.T) { + // A plain file named .git that does NOT start with "gitdir:" should not + // be treated as a valid repo root. + tmpDir := t.TempDir() + repoRoot := filepath.Join(tmpDir, "fake-git-file") + require.NoError(t, os.MkdirAll(repoRoot, 0755)) + require.NoError(t, os.WriteFile(filepath.Join(repoRoot, ".git"), []byte("not a valid git file\n"), 0644)) + + _, err := FindGitRootFrom(repoRoot) + require.Error(t, err, "FindGitRootFrom should not accept a .git file without gitdir: prefix") + assert.Contains(t, err.Error(), "not in a git repository") + }) + + t.Run("handles relative path input", func(t *testing.T) { + // "." should resolve to os.Getwd(). Skip gracefully if the working + // directory is not inside a git repository (e.g. some CI containers). + root, err := FindGitRootFrom(".") + if err != nil { + t.Skipf("skipping: working directory is not inside a git repository (%v)", err) + } + assert.NotEmpty(t, root) + }) +} + func TestReadFileFromHEADWithRoot(t *testing.T) { t.Run("reads a committed file with pre-computed root", func(t *testing.T) { gitRoot, err := FindGitRoot() diff --git a/pkg/gitutil/spec_test.go b/pkg/gitutil/spec_test.go index a397821337f..170ef35c161 100644 --- a/pkg/gitutil/spec_test.go +++ b/pkg/gitutil/spec_test.go @@ -270,8 +270,9 @@ func TestSpec_PublicAPI_IsValidFullSHA(t *testing.T) { // FindGitRoot as described in the package README.md. // // Specification: Returns the absolute path of the root directory of the current -// Git repository by running `git rev-parse --show-toplevel`. Returns an error -// if the working directory is not inside a Git repository. +// Git repository using pure Go filesystem traversal (looks for .git in the +// current directory and its parents). Returns an error if the working directory +// is not inside a Git repository. func TestSpec_PublicAPI_FindGitRoot(t *testing.T) { t.Run("returns non-empty absolute path when in git repository", func(t *testing.T) { root, err := FindGitRoot() From a54a6e71075ed0b02016f3df7db28871ad718b97 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Fri, 8 May 2026 13:58:05 -0700 Subject: [PATCH 4/8] Block silent detection pass and classify Claude embedded 429 rate limits (#31081) --- actions/setup/js/claude_harness.cjs | 7 ++++++- actions/setup/js/claude_harness.test.cjs | 16 +++++++++++++++- .../setup/js/parse_threat_detection_results.cjs | 6 +++++- .../js/parse_threat_detection_results.test.cjs | 13 +++++++++++++ pkg/workflow/detection_success_test.go | 3 +++ pkg/workflow/threat_detection.go | 4 +++- 6 files changed, 45 insertions(+), 4 deletions(-) diff --git a/actions/setup/js/claude_harness.cjs b/actions/setup/js/claude_harness.cjs index c838800d8bf..0e594935744 100644 --- a/actions/setup/js/claude_harness.cjs +++ b/actions/setup/js/claude_harness.cjs @@ -61,7 +61,11 @@ const MAX_DELAY_MS = 60000; const OVERLOADED_ERROR_PATTERN = /overloaded_error|"overloaded"/i; // Pattern to detect Anthropic rate-limit errors (HTTP 429). -const RATE_LIMIT_ERROR_PATTERN = /rate_limit_error|429 Too Many Requests/i; +// Claude CLI may surface this as: +// - transport-style text (e.g. "429 Too Many Requests") +// - embedded stream-json result fields (e.g. "api_error_status":429) +// - human-readable message text ("rate limit") +const RATE_LIMIT_ERROR_PATTERN = /rate_limit_error|429 Too Many Requests|"api_error_status"\s*:\s*429|request rejected \(429\)|rate limit/i; // Pattern to detect a clean max-turns exit from Claude Code. // Claude Code emits a JSON result object with "subtype":"error_max_turns" when the @@ -341,6 +345,7 @@ if (typeof module !== "undefined" && module.exports) { module.exports = { resolveClaudePromptFileArgs, stripPromptFileArgs, + isRateLimitError, isMaxTurnsExit, isNoDeferredMarkerError, }; diff --git a/actions/setup/js/claude_harness.test.cjs b/actions/setup/js/claude_harness.test.cjs index 9830c2ee686..e73049e9b3f 100644 --- a/actions/setup/js/claude_harness.test.cjs +++ b/actions/setup/js/claude_harness.test.cjs @@ -5,7 +5,7 @@ import os from "os"; import path from "path"; const require = createRequire(import.meta.url); -const { resolveClaudePromptFileArgs, stripPromptFileArgs, isMaxTurnsExit, isNoDeferredMarkerError } = require("./claude_harness.cjs"); +const { resolveClaudePromptFileArgs, stripPromptFileArgs, isRateLimitError, isMaxTurnsExit, isNoDeferredMarkerError } = require("./claude_harness.cjs"); describe("claude_harness.cjs", () => { describe("resolveClaudePromptFileArgs", () => { @@ -108,6 +108,20 @@ describe("claude_harness.cjs", () => { }); }); + describe("isRateLimitError", () => { + it("returns true for stream-json api_error_status 429", () => { + expect(isRateLimitError('{"type":"result","subtype":"success","is_error":true,"api_error_status":429}')).toBe(true); + }); + + it("returns true for stream-json request rejected 429 message", () => { + expect(isRateLimitError("API Error: Request rejected (429) · This request would exceed your account's rate limit.")).toBe(true); + }); + + it("returns false for non-rate-limit output", () => { + expect(isRateLimitError('{"type":"result","subtype":"success","is_error":false}')).toBe(false); + }); + }); + describe("isNoDeferredMarkerError", () => { it("returns true for the canonical no-deferred-marker error message", () => { const output = diff --git a/actions/setup/js/parse_threat_detection_results.cjs b/actions/setup/js/parse_threat_detection_results.cjs index 0e87683583e..924170825cf 100644 --- a/actions/setup/js/parse_threat_detection_results.cjs +++ b/actions/setup/js/parse_threat_detection_results.cjs @@ -263,6 +263,8 @@ async function main() { const logPath = path.join(threatDetectionDir, DETECTION_LOG_FILENAME); const runDetection = process.env.RUN_DETECTION; const continueOnError = process.env.GH_AW_DETECTION_CONTINUE_ON_ERROR !== "false"; + const detectionExecutionOutcome = process.env.DETECTION_AGENTIC_EXECUTION_OUTCOME || ""; + const detectionExecutionFailed = detectionExecutionOutcome === "failure"; const isWarnMode = continueOnError; /** @@ -273,8 +275,9 @@ async function main() { * @param {string} message - Human-readable error message */ function setDetectionFailure(reason, message) { + const mustFail = detectionExecutionFailed && (reason === "agent_failure" || reason === "parse_error"); core.setOutput("reason", reason); - if (isWarnMode) { + if (isWarnMode && !mustFail) { core.warning(`⚠️ ${message}`); core.setOutput("conclusion", "warning"); core.setOutput("success", "false"); @@ -309,6 +312,7 @@ async function main() { core.info("════════════════════════════════════════════════════════"); core.info(`📋 RUN_DETECTION env: ${JSON.stringify(runDetection)}`); core.info(`📋 continue-on-error: ${continueOnError}`); + core.info(`📋 detection execution outcome: ${JSON.stringify(detectionExecutionOutcome)}`); core.info(`📁 Threat detection directory: ${threatDetectionDir}`); core.info(`📄 Detection log path: ${logPath}`); diff --git a/actions/setup/js/parse_threat_detection_results.test.cjs b/actions/setup/js/parse_threat_detection_results.test.cjs index a0dd5cca623..471457866ff 100644 --- a/actions/setup/js/parse_threat_detection_results.test.cjs +++ b/actions/setup/js/parse_threat_detection_results.test.cjs @@ -444,6 +444,7 @@ describe("main", () => { // Reset environment variables delete process.env.RUN_DETECTION; delete process.env.GH_AW_DETECTION_CONTINUE_ON_ERROR; + delete process.env.DETECTION_AGENTIC_EXECUTION_OUTCOME; // Re-import to get fresh module with mocks mod = await import("./parse_threat_detection_results.cjs"); }); @@ -508,6 +509,18 @@ describe("main", () => { expect(mockCore.setFailed).toHaveBeenCalledWith(expect.stringContaining("Detection log file not found")); }); + it("should fail when detection execution failed even in warn mode", async () => { + process.env.DETECTION_AGENTIC_EXECUTION_OUTCOME = "failure"; + mockExistsSync.mockReturnValue(false); + + await mod.main(); + + expect(mockCore.setOutput).toHaveBeenCalledWith("conclusion", "failure"); + expect(mockCore.setOutput).toHaveBeenCalledWith("success", "false"); + expect(mockCore.setOutput).toHaveBeenCalledWith("reason", "agent_failure"); + expect(mockCore.setFailed).toHaveBeenCalledWith(expect.stringContaining("Detection log file not found")); + }); + // Note: The following tests are skipped because mocking fs for CJS modules // is difficult in vitest (same issue as safe_output_validator.test.cjs). // The core parsing logic is thoroughly tested via parseDetectionLog above. diff --git a/pkg/workflow/detection_success_test.go b/pkg/workflow/detection_success_test.go index 4b80d824f3c..fc60df3a8c3 100644 --- a/pkg/workflow/detection_success_test.go +++ b/pkg/workflow/detection_success_test.go @@ -70,6 +70,9 @@ Create an issue. if !strings.Contains(detectionSection, "GH_AW_DETECTION_CONTINUE_ON_ERROR:") { t.Error("Detection conclusion step missing GH_AW_DETECTION_CONTINUE_ON_ERROR env var") } + if !strings.Contains(detectionSection, "DETECTION_AGENTIC_EXECUTION_OUTCOME: ${{ steps.detection_agentic_execution.outcome }}") { + t.Error("Detection conclusion step missing DETECTION_AGENTIC_EXECUTION_OUTCOME env var") + } // Check that the combined parse-and-conclude step has ID detection_conclusion if !strings.Contains(detectionSection, "id: detection_conclusion") { diff --git a/pkg/workflow/threat_detection.go b/pkg/workflow/threat_detection.go index 75c72899696..8ed7c3db183 100644 --- a/pkg/workflow/threat_detection.go +++ b/pkg/workflow/threat_detection.go @@ -488,6 +488,7 @@ func (c *Compiler) buildDetectionConclusionStep(data *WorkflowData) []string { fmt.Sprintf(" uses: %s\n", getCachedActionPin("actions/github-script", data)), " env:\n", " RUN_DETECTION: ${{ steps.detection_guard.outputs.run_detection }}\n", + " DETECTION_AGENTIC_EXECUTION_OUTCOME: ${{ steps.detection_agentic_execution.outcome }}\n", coeEnvLine, " with:\n", " script: |\n", @@ -774,10 +775,11 @@ func (c *Compiler) buildResultsParsingScriptRequire() string { 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) { + if (continueOnError && !detectionExecutionFailed) { core.warning('\u26A0\uFE0F ' + msg); core.setOutput('conclusion', 'warning'); core.setOutput('success', 'false'); From eb490bcb0f9a32216ef66be5442a3a63b8aaf698 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 8 May 2026 14:41:32 -0700 Subject: [PATCH 5/8] [caveman] Optimize instruction verbosity in adr-writer and developer.instructions (#31092) --- .github/agents/adr-writer.agent.md | 147 +++++++++++------------ .github/agents/developer.instructions.md | 142 +++++++++------------- 2 files changed, 124 insertions(+), 165 deletions(-) diff --git a/.github/agents/adr-writer.agent.md b/.github/agents/adr-writer.agent.md index 90f9f07ba63..7e5045b347b 100644 --- a/.github/agents/adr-writer.agent.md +++ b/.github/agents/adr-writer.agent.md @@ -5,21 +5,21 @@ description: Best-practice Architecture Decision Record (ADR) writer following t # ADR Writer Agent -You are an expert Architecture Decision Record (ADR) writer. Your role is to produce high-quality, clear, and actionable ADRs that help teams understand *why* the codebase looks the way it does. You follow the **Michael Nygard ADR template** and store all records in `docs/adr/`. +Expert Architecture Decision Record (ADR) writer. Follow the **Michael Nygard ADR template**. Store all records in `docs/adr/`. ## ADR Philosophy -ADRs are permanent records of significant technical decisions. They answer the question: *"Why does the codebase look the way it does?"* +ADRs are permanent records of significant technical decisions: *"Why does the codebase look the way it does?"* Key principles: - **Immutable once accepted** — approved ADRs are never deleted; superseded ones are marked "Superseded by ADR-XXXX" - **Decision-focused** — capture the *why*, not just the *what* - **Honest about trade-offs** — include real negatives and costs, not just positives -- **Written for future readers** — someone unfamiliar with the context should be able to understand the decision 12 months later +- **Written for future readers** — someone unfamiliar with the context should understand the decision 12 months later ## Storage Convention -All ADRs are stored in `docs/adr/` as sequentially numbered Markdown files: +ADRs live in `docs/adr/` as sequentially numbered Markdown files: ``` docs/adr/ @@ -29,13 +29,13 @@ docs/adr/ ``` **Filename format**: `NNNN-kebab-case-title.md` -- `NNNN` is zero-padded to 4 digits (e.g., `0001`, `0042`, `0100`) -- The title uses lowercase kebab-case, derived from the ADR title +- `NNNN` zero-padded to 4 digits (e.g., `0001`, `0042`, `0100`) +- Title in lowercase kebab-case, derived from the ADR title - No special characters other than hyphens ## ADR Template -Every ADR you write must follow this two-part structure. The first part is a **human-friendly narrative** for developers and stakeholders who need to understand the decision quickly. The second part is a **normative specification** written in RFC 2119 language for precise, machine-checkable conformance requirements. +Two-part structure: a **human-friendly narrative** for developers/stakeholders, then a **normative specification** in RFC 2119 language for machine-checkable conformance. ```markdown # ADR-{NNNN}: {Concise Decision Title} @@ -125,33 +125,33 @@ An implementation is considered conformant with this ADR if it satisfies all **M #### Context Section - Answer: *What problem were we solving? What constraints existed?* -- Include relevant technical, organizational, or timeline constraints -- Mention the state of the codebase or system at the time of the decision +- Include technical, organizational, or timeline constraints +- Mention the state of the codebase at the time of the decision - Avoid implementation details — focus on the *problem space* - **Length**: 3–5 sentences #### Decision Section -- Start with an active voice statement: "We will use X because Y" -- State the primary driver of the decision (performance, simplicity, team familiarity, cost, etc.) -- If the decision involves a pattern or principle, name it explicitly +- Start with active voice: "We will use X because Y" +- State the primary driver (performance, simplicity, familiarity, cost, etc.) +- Name the pattern or principle explicitly if applicable - **Length**: 2–4 sentences #### Alternatives Considered - Include **at least 2 genuine alternatives** (not strawmen) -- For each alternative, explain: what it is, why it was considered, and why it was rejected +- For each: what it is, why considered, why rejected - If an alternative was close to being chosen, say so -- Do not include options that were never seriously considered +- Do not include options never seriously considered - **Each alternative**: 2–4 sentences #### Consequences Section -- **Positive**: Real, specific benefits — not marketing language -- **Negative**: Real costs, trade-offs, and technical debt — be honest -- **Neutral**: Side effects worth noting (e.g., "This requires updating the deployment pipeline") -- Aim for at least 2 items in each category for non-trivial decisions +- **Positive**: real, specific benefits — not marketing language +- **Negative**: real costs, trade-offs, technical debt — be honest +- **Neutral**: side effects worth noting (e.g., "requires updating the deployment pipeline") +- Aim for ≥2 items per category for non-trivial decisions ### Part 2 — Normative Specification -The normative section translates the narrative decision into precise, testable requirements using [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) keywords. +Translates the narrative decision into precise, testable requirements using [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) keywords. #### RFC 2119 Keyword Usage @@ -166,21 +166,18 @@ The normative section translates the narrative decision into precise, testable r #### Writing Normative Requirements - Each requirement **MUST** be a complete sentence ending with a period -- Keywords (**MUST**, **SHOULD**, **MAY**, etc.) **MUST** be written in **bold** +- Keywords (**MUST**, **SHOULD**, **MAY**, etc.) **MUST** be in **bold** - Requirements **MUST** be atomic — one constraint per numbered item -- Group requirements into named subsections by concern area (e.g., "Storage", "API", "Authentication") -- Every normative section **MUST** end with a **Conformance** paragraph explaining what constitutes conformance -- Derive normative statements directly from the narrative Decision section — the two parts must be consistent -- If the narrative says "We will always use X", the normative form is "Implementations **MUST** use X" -- If the narrative says "We prefer Y", the normative form is "Implementations **SHOULD** use Y" +- Group into named subsections by concern (e.g., "Storage", "API", "Authentication") +- Every normative section **MUST** end with a **Conformance** paragraph +- Derive normative statements directly from the narrative Decision — the two parts must be consistent +- "We will always use X" → "Implementations **MUST** use X" +- "We prefer Y" → "Implementations **SHOULD** use Y" ## Procedure: Writing a New ADR -When asked to write an ADR, follow these steps: - ### Step 1: Determine the Next Sequence Number -Check the existing ADRs: ```bash ls docs/adr/*.md 2>/dev/null | grep -oP '\d{4}' | sort -n | tail -1 ``` @@ -189,11 +186,11 @@ If no ADRs exist, start at `0001`. Otherwise, increment the highest number by 1. ### Step 2: Derive the Filename -Convert the decision title to kebab-case for the filename: +Convert the decision title to kebab-case: - Lowercase all characters - Replace spaces and special characters with hyphens -- Remove articles (a, an, the) at the start if they add no meaning -- Keep it concise (3–6 words ideal) +- Remove leading articles (a, an, the) if meaningless +- Keep concise (3–6 words ideal) Example: "Use PostgreSQL for Primary Storage" → `0001-use-postgresql-for-primary-storage.md` @@ -205,14 +202,13 @@ mkdir -p docs/adr ### Step 4: Analyze the Context -Before writing, gather all available context: -- If writing from a PR diff: read the diff carefully and identify what decisions the code is making implicitly -- If writing from a description: clarify the decision and its rationale -- If updating an existing ADR: read the current version first +- From a PR diff: read the diff and identify what decisions the code is making implicitly +- From a description: clarify the decision and its rationale +- Updating an existing ADR: read the current version first ### Step 5: Write the ADR -Apply the template strictly. Fill in every section. Do not leave placeholder text in the output — if you cannot determine something from context, write what you *can* infer and mark it with `[TODO: verify]`. +Apply the template strictly. Fill in every section. No placeholder text in the output — if you can't determine something, write what you *can* infer and mark it `[TODO: verify]`. ### Step 6: Save the File @@ -220,72 +216,65 @@ Write the ADR to `docs/adr/{NNNN}-{title}.md`. ### Step 7: Validate the ADR -Before finishing, check: - **Part 1 — Narrative:** -- [ ] Context, Decision, Alternatives Considered, and Consequences sections are all present -- [ ] Status is set to `Draft` for new ADRs -- [ ] Date is set to today (YYYY-MM-DD format) -- [ ] At least 2 genuine alternatives are listed -- [ ] Both positive and negative consequences are listed -- [ ] The filename follows the NNNN-kebab-case-title.md convention -- [ ] The ADR number in the title matches the filename number +- [ ] Context, Decision, Alternatives, Consequences sections all present +- [ ] Status is `Draft` for new ADRs +- [ ] Date is today (YYYY-MM-DD format) +- [ ] ≥2 genuine alternatives listed +- [ ] Both positive and negative consequences listed +- [ ] Filename follows NNNN-kebab-case-title.md convention +- [ ] ADR number in title matches filename number **Part 2 — Normative Specification:** -- [ ] RFC 2119 boilerplate paragraph is present -- [ ] All normative keywords are in **bold** -- [ ] Each requirement is atomic (one constraint per item) -- [ ] Requirements are grouped into named subsections -- [ ] A Conformance paragraph is present +- [ ] RFC 2119 boilerplate paragraph present +- [ ] All normative keywords in **bold** +- [ ] Each requirement atomic (one constraint per item) +- [ ] Requirements grouped into named subsections +- [ ] Conformance paragraph present - [ ] Normative requirements are consistent with the narrative Decision section ## Procedure: Analyzing a PR Diff for ADR Content -When given a PR diff to analyze, identify design decisions by looking for: +Identify design decisions by looking for: -1. **New abstractions** — new interfaces, base classes, or protocols introduced -2. **Technology choices** — new libraries, frameworks, databases, or services added +1. **New abstractions** — interfaces, base classes, or protocols introduced +2. **Technology choices** — libraries, frameworks, databases, or services added 3. **Structural changes** — reorganization of packages, modules, or directory structure -4. **Pattern adoption** — new design patterns, conventions, or coding standards -5. **Integration points** — new external service integrations or API contracts -6. **Data model changes** — new schemas, types, or data representations +4. **Pattern adoption** — design patterns, conventions, or coding standards +5. **Integration points** — external service integrations or API contracts +6. **Data model changes** — schemas, types, or data representations 7. **Performance trade-offs** — algorithms or caching strategies chosen -For each decision identified, ask: -- What problem does this solve? -- What alternatives could have been used? -- What are the consequences of this choice? +For each decision: what problem does this solve? what alternatives could have been used? what are the consequences? ## Procedure: Verifying an Existing ADR Against Code -When asked to verify whether code matches an ADR: - -1. Read the ADR's **Decision** section carefully — extract the key commitments -2. Read the code changes — look for conformance or deviation -3. Check for each commitment in the Decision section: does the code implement it? -4. Note any **divergences**: places where the code contradicts or ignores the stated decision -5. Note any **scope creep**: significant decisions in the code that the ADR doesn't cover +1. Read the ADR's **Decision** section — extract key commitments +2. Read the code changes — check conformance or deviation +3. For each commitment: does the code implement it? +4. Note **divergences**: places where the code contradicts the decision +5. Note **scope creep**: significant decisions in code the ADR doesn't cover -Return a structured assessment: +Return: - **Aligned**: code faithfully implements the ADR -- **Partially aligned**: most decisions are implemented, minor divergences exist +- **Partially aligned**: most decisions implemented, minor divergences - **Divergent**: significant contradictions between ADR and code ## Examples of ADR-Worthy Decisions -These types of changes warrant an ADR: +Warrant an ADR: - Choosing a database, message queue, cache, or storage system - Adopting a framework or replacing an existing one - Changing authentication or authorization approach -- Introducing a new API design convention (REST vs GraphQL vs gRPC) -- Choosing between competing architectural patterns (microservices vs monolith, event-driven vs request-driven) -- Adding significant new infrastructure (Kubernetes, Terraform, etc.) -- Adopting a new testing strategy or quality gate -- Choosing a programming language or runtime for a new service - -These changes typically do **not** warrant an ADR: -- Bug fixes that don't involve design trade-offs +- New API design convention (REST vs GraphQL vs gRPC) +- Competing architectural patterns (microservices vs monolith, event-driven vs request-driven) +- Significant new infrastructure (Kubernetes, Terraform, etc.) +- New testing strategy or quality gate +- Programming language or runtime for a new service + +Do **not** warrant an ADR: +- Bug fixes without design trade-offs - Minor refactors within existing patterns - Documentation updates -- Dependency version bumps (unless adopting a major new dependency) +- Dependency version bumps (unless major new dependency) - Code style or formatting changes diff --git a/.github/agents/developer.instructions.md b/.github/agents/developer.instructions.md index 7f0b875ac67..ba330dadd5d 100644 --- a/.github/agents/developer.instructions.md +++ b/.github/agents/developer.instructions.md @@ -5,7 +5,7 @@ applyTo: "**/*" # Developer Instructions -This document consolidates development guidelines, architectural patterns, and implementation standards for GitHub Agentic Workflows. It provides guidance for contributing to the codebase while maintaining consistency, security, and code quality. +Development guidelines, architectural patterns, and implementation standards for GitHub Agentic Workflows. --- @@ -13,8 +13,6 @@ This document consolidates development guidelines, architectural patterns, and i ### Recommended Patterns -The codebase exhibits several well-organized patterns that should be emulated: - #### 1. Create Functions Pattern (`create_*.go`) **Pattern**: One file per GitHub entity creation operation @@ -31,11 +29,11 @@ The codebase exhibits several well-organized patterns that should be emulated: **Pattern**: Each AI engine has its own file with shared helpers in `engine_helpers.go` **Examples**: -- `copilot_engine.go` (971 lines) - GitHub Copilot engine -- `claude_engine.go` (340 lines) - Claude engine -- `codex_engine.go` (639 lines) - Codex engine -- `custom_engine.go` (300 lines) - Custom engine support -- `engine_helpers.go` (424 lines) - Shared engine utilities +- `copilot_engine.go` — GitHub Copilot engine +- `claude_engine.go` — Claude engine +- `codex_engine.go` — Codex engine +- `custom_engine.go` — Custom engine support +- `engine_helpers.go` — Shared engine utilities #### 3. Test Organization Pattern @@ -73,10 +71,10 @@ graph TD ## Validation Architecture -The validation system ensures workflow configurations are correct, secure, and compatible with GitHub Actions before compilation. Validation is organized into two main patterns: +Validation ensures workflow configurations are correct before compilation. Two patterns: -1. **Centralized validation** - General-purpose validation in `validation.go` -2. **Domain-specific validation** - Specialized validation in dedicated files +1. **Centralized validation** — `validation.go` +2. **Domain-specific validation** — dedicated files ### Validation Flow @@ -98,38 +96,34 @@ graph TD J -->|No| L[Error Report] ``` -### Centralized Validation: `validation.go` - -**Location**: `pkg/workflow/validation.go` (782 lines) +### Centralized Validation: `pkg/workflow/validation.go` -**Purpose**: General-purpose validation that applies across the entire workflow system +General-purpose validation across the workflow system: -**Key Validation Functions**: -- `validateExpressionSizes()` - Ensures GitHub Actions expression size limits -- `validateContainerImages()` - Verifies Docker images exist and are accessible -- `validateRuntimePackages()` - Validates runtime package dependencies -- `validateGitHubActionsSchema()` - Validates against GitHub Actions YAML schema -- `validateNoDuplicateCacheIDs()` - Ensures unique cache identifiers -- `validateSecretReferences()` - Validates secret reference syntax -- `validateRepositoryFeatures()` - Checks repository capabilities (issues, discussions) +- `validateExpressionSizes()` — GitHub Actions expression size limits +- `validateContainerImages()` — Docker images exist and are accessible +- `validateRuntimePackages()` — runtime package dependencies +- `validateGitHubActionsSchema()` — GitHub Actions YAML schema +- `validateNoDuplicateCacheIDs()` — unique cache identifiers +- `validateSecretReferences()` — secret reference syntax +- `validateRepositoryFeatures()` — repository capabilities (issues, discussions) ### Domain-Specific Validation -#### Strict Mode Validation: `strict_mode_validation.go` +#### Strict Mode: `strict_mode_validation.go` -**Purpose**: Enforces security and safety constraints in strict mode +Enforces security and safety constraints in strict mode: -**Validation Functions**: -- `validateStrictMode()` - Main strict mode orchestrator -- `validateStrictPermissions()` - Refuses write permissions -- `validateStrictNetwork()` - Requires explicit network configuration -- `validateStrictMCPNetwork()` - Requires network config on custom MCP servers -- `validateStrictBashTools()` - Refuses bash wildcard tools +- `validateStrictMode()` — main strict mode orchestrator +- `validateStrictPermissions()` — refuses write permissions +- `validateStrictNetwork()` — requires explicit network configuration +- `validateStrictMCPNetwork()` — requires network config on custom MCP servers +- `validateStrictBashTools()` — refuses bash wildcard tools #### Package Validation -- **Python/pip**: `pip.go` - Validates Python package availability on PyPI -- **Node.js/npm**: `npm.go` - Validates npm packages used with npx +- **Python/pip**: `pip.go` — package availability on PyPI +- **Node.js/npm**: `npm.go` — npm packages used with npx ### Where to Add Validation @@ -188,19 +182,15 @@ graph TD H --> K[normalizeLineEndings] ``` -**Sanitize**: Remove or replace characters that could cause security issues or break GitHub API constraints - -**Key Functions**: -- `sanitizeGitHubLabel()` - Ensures labels meet GitHub requirements (no emoji, length limits) -- `sanitizeGitHubBranch()` - Validates branch names against Git ref rules -- `sanitizeGitHubIssueTitle()` - Ensures issue titles don't contain problematic characters +**Sanitize** — replace characters that cause security issues or break GitHub API constraints: +- `sanitizeGitHubLabel()` — labels meet GitHub requirements (no emoji, length limits) +- `sanitizeGitHubBranch()` — branch names against Git ref rules +- `sanitizeGitHubIssueTitle()` — issue titles avoid problematic characters -**Normalize**: Standardize format for consistency without security implications - -**Key Functions**: -- `normalizeWhitespace()` - Standardizes whitespace (spaces, tabs, newlines) -- `normalizeLineEndings()` - Converts CRLF to LF -- `normalizeMarkdown()` - Standardizes markdown formatting +**Normalize** — standardize format for consistency, no security implications: +- `normalizeWhitespace()` — whitespace (spaces, tabs, newlines) +- `normalizeLineEndings()` — CRLF to LF +- `normalizeMarkdown()` — markdown formatting --- ## YAML Handling @@ -232,7 +222,7 @@ err := yaml.Unmarshal(data, &workflow) ## Safe Output Messages -The safe output message system provides structured communication between AI agents and GitHub API operations. +Structured communication between AI agents and GitHub API operations. ### Message Categories @@ -245,7 +235,7 @@ The safe output message system provides structured communication between AI agen ### Staged Mode Indicator -The 🎭 emoji consistently marks preview mode across all safe output types, enabling clear distinction between test runs and live operations. +🎭 marks preview mode across all safe output types. ### Message Structure @@ -278,7 +268,7 @@ graph LR ### Build System -The custom actions build system is **entirely implemented in Go** in `pkg/cli/actions_build_command.go`. There are no JavaScript build scripts. +Implemented in Go at `pkg/cli/actions_build_command.go`. No JavaScript build scripts. **Key Commands**: - `make actions-build` - Build all custom actions @@ -339,8 +329,6 @@ steps: ## Testing Framework -### Test Strategy - ### Test Types | Test Type | Purpose | Location | Run Frequency | @@ -353,7 +341,7 @@ steps: ### Visual Regression Testing -Visual regression tests ensure console output formatting remains consistent across code changes. The system uses golden files to capture expected output for table layouts, box rendering, tree structures, and error formatting. +Golden files capture expected console output for tables, boxes, trees, and error formatting. **Golden Test Commands**: ```bash @@ -364,14 +352,6 @@ go test -v ./pkg/console -run='^TestGolden_' make update-golden ``` -**Test Coverage**: -- Table rendering with various configurations -- Box formatting with different widths and content -- Tree structures for hierarchical data -- Error messages with context and suggestions -- Message formatting (success, info, warning, error) -- Layout composition and emphasis boxes - **When to Update Golden Files**: - ✅ Intentionally improving console output formatting - ✅ Fixing visual bugs in rendering @@ -382,7 +362,7 @@ make update-golden ## Repo-Memory System -The repo-memory feature provides persistent, git-backed storage for AI agents across workflow runs. Agents can maintain state, notes, and artifacts in dedicated git branches with automatic synchronization. +Persistent, git-backed storage for AI agents across workflow runs. Maintains state in dedicated git branches with automatic synchronization. ### Architecture Overview @@ -408,11 +388,11 @@ graph TD ### Data Flow -1. **Clone Phase**: Clones `memory/{id}` branch to local directory -2. **Execution Phase**: Agent reads/writes files in memory directory -3. **Upload Phase**: Uploads directory as GitHub Actions artifact -4. **Download Phase**: Downloads artifact and validates constraints -5. **Push Phase**: Commits files to `memory/{id}` branch and pushes +1. **Clone**: clone `memory/{id}` branch to local directory +2. **Execution**: agent reads/writes files in memory directory +3. **Upload**: upload directory as GitHub Actions artifact +4. **Download**: download artifact and validate constraints +5. **Push**: commit to `memory/{id}` branch and push ### Key Configuration @@ -428,18 +408,12 @@ repo-memory: max-files: 100 ``` -**Validation Constraints**: -- Maximum file size limits -- Maximum file count limits -- Allowed/blocked file patterns -- Size and count tracking in commit messages +**Validation Constraints**: max file size, max file count, allowed/blocked patterns, size/count tracking in commit messages. --- ## Hierarchical Agent Management -The hierarchical agent system provides meta-orchestration capabilities to manage multiple agents and workflows at scale. Specialized meta-orchestrator workflows oversee, coordinate, and optimize the agent ecosystem. - -### Meta-Orchestrator Architecture +Meta-orchestrator workflows manage multiple agents and workflows at scale. ### Meta-Orchestrator Roles @@ -453,7 +427,7 @@ The hierarchical agent system provides meta-orchestration capabilities to manage ### Changesets -Use changesets to document changes and manage versioning: +Document changes and manage versioning: ```bash # Create a changeset @@ -480,17 +454,15 @@ Brief description of the change ### End-to-End Feature Testing -For manual feature testing in pull requests: - 1. Use `.github/workflows/dev.md` as test workflow 2. Add test scenarios as comments in PR 3. Dev Hawk will analyze and verify behavior -4. Do not merge dev.md changes - it remains a reusable test harness +4. Do not merge dev.md changes — it remains a reusable test harness --- ## Scope Hints for Complex Workflows -When creating agentic workflows for complex analysis tasks, provide concrete constraints upfront to avoid agent timeouts and vague output. Open-ended prompts force the agent to explore multiple implementation paths, which can exhaust the available time budget. +Provide concrete constraints upfront to avoid agent timeouts and vague output. ### General Rule @@ -542,7 +514,7 @@ Create a workflow that compares branches and reports differences. ### Timeout Prevention Checklist -Before submitting a complex workflow request, confirm you have specified: +Before submitting a complex workflow request, confirm: - [ ] **Input file path and format** — e.g. `coverage/lcov.info` in lcov format - [ ] **Triggering event** — e.g. `pull_request`, `push to main`, `schedule` @@ -553,22 +525,22 @@ Before submitting a complex workflow request, confirm you have specified: ## PR Deduplication Protocol -Repeated closed PR attempts on the same topic waste CI resources and agent context. Follow this protocol every time you are about to create a pull request. +Repeated closed PR attempts on the same topic waste CI and context. Run this protocol before every PR. ### Pre-flight Duplicate PR Check -Before opening a PR, search for existing closed PRs with a similar topic using the GitHub MCP `search_pull_requests` tool: +Search for existing closed PRs with a similar topic using the GitHub MCP `search_pull_requests` tool: 1. Extract 2–4 keywords from the feature/fix title. 2. Run a search such as: - `is:pr is:closed head:copilot/ ` - `is:pr is:closed ` -3. If **no** closed PR is found, proceed normally. -4. If **one or more** closed PRs are found, move to the [Prior Failure Analysis](#prior-failure-analysis) step before writing any code. +3. If none found, proceed normally. +4. If one or more found, do [Prior Failure Analysis](#prior-failure-analysis) before writing any code. ### Prior Failure Analysis -When a closed PR exists on the same topic, perform this analysis at the start of the session — before any code exploration or implementation: +When a closed PR exists on the same topic, do this at session start — before any code exploration: 1. Read the closed PR description, review comments, and timeline. 2. Identify the **root cause of closure**: @@ -607,8 +579,6 @@ If **two or more** closed PRs already exist on the same topic: --- - - ### File Locations | Feature | Implementation File | Test File | From 55663beea624bfa2e740b54eea3f8972ed9dff2d Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Fri, 8 May 2026 16:29:52 -0700 Subject: [PATCH 6/8] Add explicit top-level ET budget control and ET-limit failure attribution (#31094) --- actions/setup/js/handle_agent_failure.cjs | 31 ++++++++ actions/setup/js/parse_mcp_gateway_log.cjs | 40 +++++++++++ .../setup/js/parse_mcp_gateway_log.test.cjs | 18 +++++ actions/setup/md/agent_failure_comment.md | 2 +- actions/setup/md/agent_failure_issue.md | 2 +- pkg/constants/constants.go | 3 + pkg/parser/schemas/main_workflow_schema.json | 15 ++++ pkg/workflow/awf_config.go | 10 ++- pkg/workflow/awf_config_test.go | 21 ++++++ pkg/workflow/compiler_main_job.go | 3 + pkg/workflow/compiler_orchestrator_engine.go | 9 +++ pkg/workflow/engine.go | 72 ++++++++++++++----- pkg/workflow/engine_config_test.go | 34 +++++++++ pkg/workflow/notify_comment.go | 11 +++ pkg/workflow/schemas/awf-config.schema.json | 5 ++ .../basic-copilot.golden | 3 +- .../playwright-cli-mode.golden | 3 +- .../smoke-copilot.golden | 3 +- .../with-imports.golden | 3 +- pkg/workflow/threat_detection.go | 17 ++--- 20 files changed, 274 insertions(+), 31 deletions(-) diff --git a/actions/setup/js/handle_agent_failure.cjs b/actions/setup/js/handle_agent_failure.cjs index ed27b851a2d..747796c4be3 100644 --- a/actions/setup/js/handle_agent_failure.cjs +++ b/actions/setup/js/handle_agent_failure.cjs @@ -837,6 +837,26 @@ function buildModelNotSupportedErrorContext(hasModelNotSupportedError) { } } +/** + * Build a context string when ET budget exhaustion/rate-limit is detected from gateway logs. + * @param {boolean} hasEffectiveTokensRateLimitError + * @param {string} effectiveTokens + * @param {string} maxEffectiveTokens + * @param {string} runUrl + * @returns {string} + */ +function buildEffectiveTokensRateLimitErrorContext(hasEffectiveTokensRateLimitError, effectiveTokens, maxEffectiveTokens, runUrl) { + if (!hasEffectiveTokensRateLimitError) { + return ""; + } + + const usageLine = effectiveTokens ? `\n- Effective tokens used: \`${effectiveTokens}\`` : ""; + const budgetLine = maxEffectiveTokens ? `\n- Configured ET budget: \`${maxEffectiveTokens}\`` : ""; + const runLine = runUrl ? `\n- Run: ${runUrl}` : ""; + + return `\n**⛔ Effective Token Budget Exhausted**: The run failed due to effective-token budget/rate-limit enforcement in the API proxy.${usageLine}${budgetLine}${runLine}\n\nPrefer ET budget controls for diagnosis instead of run-count heuristics. You can tune this limit with \`max-effective-tokens\` in workflow frontmatter.\n`; +} + /** * Build a context string when a GitHub App token minting step failed. * @param {boolean} hasAppTokenMintingFailed - Whether any GitHub App token minting step failed @@ -1293,6 +1313,9 @@ async function main() { const codePushFailureCount = process.env.GH_AW_CODE_PUSH_FAILURE_COUNT || "0"; const checkoutPRSuccess = process.env.GH_AW_CHECKOUT_PR_SUCCESS || ""; const timeoutMinutes = process.env.GH_AW_TIMEOUT_MINUTES || ""; + const effectiveTokens = process.env.GH_AW_EFFECTIVE_TOKENS || ""; + const maxEffectiveTokens = process.env.GH_AW_MAX_EFFECTIVE_TOKENS || ""; + const effectiveTokensRateLimitError = process.env.GH_AW_EFFECTIVE_TOKENS_RATE_LIMIT_ERROR === "true"; const inferenceAccessError = process.env.GH_AW_INFERENCE_ACCESS_ERROR === "true"; const mcpPolicyError = process.env.GH_AW_MCP_POLICY_ERROR === "true"; const agenticEngineTimeout = process.env.GH_AW_AGENTIC_ENGINE_TIMEOUT === "true"; @@ -1351,6 +1374,9 @@ async function main() { core.info(`Create discussion error count: ${createDiscussionErrorCount}`); core.info(`Code push failure count: ${codePushFailureCount}`); core.info(`Checkout PR success: ${checkoutPRSuccess}`); + core.info(`Effective tokens: ${effectiveTokens || "(none)"}`); + core.info(`Configured max effective tokens: ${maxEffectiveTokens || "(none)"}`); + core.info(`Effective tokens rate-limit error: ${effectiveTokensRateLimitError}`); core.info(`Inference access error: ${inferenceAccessError}`); core.info(`MCP policy error: ${mcpPolicyError}`); core.info(`Agentic engine timeout: ${agenticEngineTimeout}`); @@ -1509,6 +1535,7 @@ async function main() { !hasStaleLockFileFailed && !hasReportIncomplete && !hasCacheMissMisconfiguration && + !effectiveTokensRateLimitError && !hasMissingTool && !hasMissingData ) { @@ -1703,6 +1730,7 @@ async function main() { // Build model not supported error context const modelNotSupportedErrorContext = buildModelNotSupportedErrorContext(modelNotSupportedError); + const effectiveTokensRateLimitErrorContext = buildEffectiveTokensRateLimitErrorContext(effectiveTokensRateLimitError, effectiveTokens, maxEffectiveTokens, runUrl); // Build GitHub App token minting failure context const appTokenMintingFailedContext = buildAppTokenMintingFailedContext(hasAppTokenMintingFailed); @@ -1748,6 +1776,7 @@ async function main() { inference_access_error_context: inferenceAccessErrorContext, mcp_policy_error_context: mcpPolicyErrorContext, model_not_supported_error_context: modelNotSupportedErrorContext, + effective_tokens_rate_limit_error_context: effectiveTokensRateLimitErrorContext, app_token_minting_failed_context: appTokenMintingFailedContext, lockdown_check_failed_context: lockdownCheckFailedContext, stale_lock_file_failed_context: staleLockFileFailedContext, @@ -1872,6 +1901,7 @@ async function main() { // Build model not supported error context const modelNotSupportedErrorContext = buildModelNotSupportedErrorContext(modelNotSupportedError); + const effectiveTokensRateLimitErrorContext = buildEffectiveTokensRateLimitErrorContext(effectiveTokensRateLimitError, effectiveTokens, maxEffectiveTokens, runUrl); // Build GitHub App token minting failure context const appTokenMintingFailedContext = buildAppTokenMintingFailedContext(hasAppTokenMintingFailed); @@ -1918,6 +1948,7 @@ async function main() { inference_access_error_context: inferenceAccessErrorContext, mcp_policy_error_context: mcpPolicyErrorContext, model_not_supported_error_context: modelNotSupportedErrorContext, + effective_tokens_rate_limit_error_context: effectiveTokensRateLimitErrorContext, app_token_minting_failed_context: appTokenMintingFailedContext, lockdown_check_failed_context: lockdownCheckFailedContext, stale_lock_file_failed_context: staleLockFileFailedContext, diff --git a/actions/setup/js/parse_mcp_gateway_log.cjs b/actions/setup/js/parse_mcp_gateway_log.cjs index 029d6900794..ed02d08fe35 100644 --- a/actions/setup/js/parse_mcp_gateway_log.cjs +++ b/actions/setup/js/parse_mcp_gateway_log.cjs @@ -22,6 +22,15 @@ const MAX_RPC_SUMMARY_DETAILS_LENGTH = 120; const MAX_RPC_SUMMARY_GENERIC_LENGTH = 160; const MAX_RPC_MESSAGE_LABEL_LENGTH = 80; const TOP_LEVEL_RPC_IGNORED_KEYS = new Set(["timestamp", "direction", "type", "server_id", "payload"]); +// ET/rate-limit indicators seen in gateway/runtime logs, e.g.: +// - "effective_tokens limit exceeded" +// - "rate limit ... effective tokens" +// - "429 too many requests ... ET budget" +const ET_RATE_LIMIT_PATTERNS = [ + /effective[\s_-]*tokens?.*(?:rate[\s-]*limit|limit exceeded|budget exceeded|exceeded)/i, + /(?:rate[\s-]*limit|too many requests).*(?:effective[\s_-]*tokens?|et budget)/i, + /\b429\b.*(?:rate[\s-]*limit|too many requests|effective[\s_-]*tokens?)/i, +]; /** * Formats milliseconds as a human-readable duration string. @@ -201,6 +210,26 @@ function writeStepSummaryWithTokenUsage(coreObj) { coreObj.summary.write(); } +/** + * Detects ET-budget/rate-limit failures from gateway-related logs. + * @param {string[]} contents + * @returns {boolean} + */ +function hasEffectiveTokensRateLimitError(contents) { + const joined = contents.filter(Boolean).join("\n"); + if (!joined) return false; + return ET_RATE_LIMIT_PATTERNS.some(pattern => pattern.test(joined)); +} + +/** + * Exports effective_tokens_rate_limit_error output. + * @param {typeof import('@actions/core')} coreObj + * @param {boolean} value + */ +function setEffectiveTokensRateLimitOutput(coreObj, value) { + coreObj.setOutput("effective_tokens_rate_limit_error", value ? "true" : "false"); +} + /** * Prints all gateway-related files to core.info for debugging */ @@ -618,6 +647,7 @@ async function main() { const gatewayMdPath = "/tmp/gh-aw/mcp-logs/gateway.md"; const gatewayLogPath = "/tmp/gh-aw/mcp-logs/gateway.log"; const stderrLogPath = "/tmp/gh-aw/mcp-logs/stderr.log"; + let effectiveTokensRateLimitError = false; // Parse DIFC_FILTERED events from gateway.jsonl (preferred) or rpc-messages.jsonl (fallback). // Both files use the same JSONL format with DIFC_FILTERED entries interleaved. @@ -627,6 +657,7 @@ async function main() { const jsonlContent = fs.readFileSync(gatewayJsonlPath, "utf8"); core.info(`Found gateway.jsonl (${jsonlContent.length} bytes)`); difcFilteredEvents = parseGatewayJsonlForDifcFiltered(jsonlContent); + effectiveTokensRateLimitError ||= hasEffectiveTokensRateLimitError([jsonlContent]); if (difcFilteredEvents.length > 0) { core.info(`Found ${difcFilteredEvents.length} DIFC_FILTERED event(s) in gateway.jsonl`); } @@ -634,6 +665,7 @@ async function main() { rpcMessagesContent = fs.readFileSync(rpcMessagesPath, "utf8"); core.info(`Found rpc-messages.jsonl (${rpcMessagesContent.length} bytes)`); difcFilteredEvents = parseGatewayJsonlForDifcFiltered(rpcMessagesContent); + effectiveTokensRateLimitError ||= hasEffectiveTokensRateLimitError([rpcMessagesContent]); if (difcFilteredEvents.length > 0) { core.info(`Found ${difcFilteredEvents.length} DIFC_FILTERED event(s) in rpc-messages.jsonl`); } @@ -646,6 +678,7 @@ async function main() { const gatewayMdContent = fs.readFileSync(gatewayMdPath, "utf8"); if (gatewayMdContent && gatewayMdContent.trim().length > 0) { core.info(`Found gateway.md (${gatewayMdContent.length} bytes)`); + effectiveTokensRateLimitError ||= hasEffectiveTokensRateLimitError([gatewayMdContent]); // Write the markdown directly to the step summary core.summary.addRaw(gatewayMdContent.endsWith("\n") ? gatewayMdContent : gatewayMdContent + "\n"); @@ -656,6 +689,7 @@ async function main() { core.summary.addRaw(difcSummary); } + setEffectiveTokensRateLimitOutput(core, effectiveTokensRateLimitError); writeStepSummaryWithTokenUsage(core); return; } @@ -679,6 +713,7 @@ async function main() { } else { core.info("rpc-messages.jsonl is present but contains no renderable messages"); } + setEffectiveTokensRateLimitOutput(core, effectiveTokensRateLimitError); writeStepSummaryWithTokenUsage(core); return; } @@ -691,6 +726,7 @@ async function main() { if (fs.existsSync(gatewayLogPath)) { gatewayLogContent = fs.readFileSync(gatewayLogPath, "utf8"); core.info(`Found gateway.log (${gatewayLogContent.length} bytes)`); + effectiveTokensRateLimitError ||= hasEffectiveTokensRateLimitError([gatewayLogContent]); } else { core.info(`No gateway.log found at: ${gatewayLogPath}`); } @@ -699,6 +735,7 @@ async function main() { if (fs.existsSync(stderrLogPath)) { stderrLogContent = fs.readFileSync(stderrLogPath, "utf8"); core.info(`Found stderr.log (${stderrLogContent.length} bytes)`); + effectiveTokensRateLimitError ||= hasEffectiveTokensRateLimitError([stderrLogContent]); } else { core.info(`No stderr.log found at: ${stderrLogPath}`); } @@ -706,6 +743,7 @@ async function main() { // If no legacy log content and no DIFC events, check if token usage is available if ((!gatewayLogContent || gatewayLogContent.trim().length === 0) && (!stderrLogContent || stderrLogContent.trim().length === 0) && difcFilteredEvents.length === 0) { core.info("MCP gateway log files are empty or missing"); + setEffectiveTokensRateLimitOutput(core, effectiveTokensRateLimitError); writeStepSummaryWithTokenUsage(core); return; } @@ -724,6 +762,7 @@ async function main() { if (fullSummary.length > 0) { core.summary.addRaw(fullSummary); } + setEffectiveTokensRateLimitOutput(core, effectiveTokensRateLimitError); writeStepSummaryWithTokenUsage(core); } catch (error) { core.setFailed(`${ERR_PARSE}: ${getErrorMessage(error)}`); @@ -848,6 +887,7 @@ if (typeof module !== "undefined" && module.exports) { parseTokenUsageJsonl, generateTokenUsageSummary, formatDurationMs, + hasEffectiveTokensRateLimitError, }; } diff --git a/actions/setup/js/parse_mcp_gateway_log.test.cjs b/actions/setup/js/parse_mcp_gateway_log.test.cjs index 247f5e4c35c..3b17d143207 100644 --- a/actions/setup/js/parse_mcp_gateway_log.test.cjs +++ b/actions/setup/js/parse_mcp_gateway_log.test.cjs @@ -14,6 +14,7 @@ const { parseTokenUsageJsonl, generateTokenUsageSummary, formatDurationMs, + hasEffectiveTokensRateLimitError, } = require("./parse_mcp_gateway_log.cjs"); describe("parse_mcp_gateway_log", () => { @@ -1202,4 +1203,21 @@ not-json expect(summary.totalEffectiveTokens).toBe(m1ET + m2ET); }); }); + + describe("hasEffectiveTokensRateLimitError", () => { + test("detects explicit ET budget exhaustion message", () => { + const hasError = hasEffectiveTokensRateLimitError(["effective_tokens limit exceeded for this run"]); + expect(hasError).toBe(true); + }); + + test("detects HTTP 429 rate-limit text tied to ET", () => { + const hasError = hasEffectiveTokensRateLimitError(["429 too many requests while enforcing ET budget"]); + expect(hasError).toBe(true); + }); + + test("returns false for unrelated logs", () => { + const hasError = hasEffectiveTokensRateLimitError(["gateway started", "request succeeded"]); + expect(hasError).toBe(false); + }); + }); }); diff --git a/actions/setup/md/agent_failure_comment.md b/actions/setup/md/agent_failure_comment.md index ab54d66ab74..8222d541d27 100644 --- a/actions/setup/md/agent_failure_comment.md +++ b/actions/setup/md/agent_failure_comment.md @@ -1,3 +1,3 @@ Agent job [{run_id}]({run_url}) failed. -{secret_verification_context}{credential_auth_error_context}{inference_access_error_context}{mcp_policy_error_context}{model_not_supported_error_context}{app_token_minting_failed_context}{lockdown_check_failed_context}{stale_lock_file_failed_context}{assignment_errors_context}{assign_copilot_failure_context}{create_discussion_errors_context}{code_push_failure_context}{repo_memory_validation_context}{push_repo_memory_failure_context}{missing_data_context}{missing_tool_context}{missing_safe_outputs_context}{engine_failure_context}{timeout_context}{fork_context} +{secret_verification_context}{credential_auth_error_context}{inference_access_error_context}{mcp_policy_error_context}{model_not_supported_error_context}{effective_tokens_rate_limit_error_context}{app_token_minting_failed_context}{lockdown_check_failed_context}{stale_lock_file_failed_context}{assignment_errors_context}{assign_copilot_failure_context}{create_discussion_errors_context}{code_push_failure_context}{repo_memory_validation_context}{push_repo_memory_failure_context}{missing_data_context}{missing_tool_context}{missing_safe_outputs_context}{engine_failure_context}{timeout_context}{fork_context} diff --git a/actions/setup/md/agent_failure_issue.md b/actions/setup/md/agent_failure_issue.md index cf07cc129ee..4b87be032eb 100644 --- a/actions/setup/md/agent_failure_issue.md +++ b/actions/setup/md/agent_failure_issue.md @@ -4,7 +4,7 @@ **Branch:** {branch} **Run:** {run_url}{pull_request_info} -{secret_verification_context}{credential_auth_error_context}{inference_access_error_context}{mcp_policy_error_context}{model_not_supported_error_context}{app_token_minting_failed_context}{lockdown_check_failed_context}{stale_lock_file_failed_context}{assignment_errors_context}{assign_copilot_failure_context}{create_discussion_errors_context}{code_push_failure_context}{repo_memory_validation_context}{push_repo_memory_failure_context}{missing_data_context}{missing_tool_context}{missing_safe_outputs_context}{engine_failure_context}{timeout_context}{fork_context} +{secret_verification_context}{credential_auth_error_context}{inference_access_error_context}{mcp_policy_error_context}{model_not_supported_error_context}{effective_tokens_rate_limit_error_context}{app_token_minting_failed_context}{lockdown_check_failed_context}{stale_lock_file_failed_context}{assignment_errors_context}{assign_copilot_failure_context}{create_discussion_errors_context}{code_push_failure_context}{repo_memory_validation_context}{push_repo_memory_failure_context}{missing_data_context}{missing_tool_context}{missing_safe_outputs_context}{engine_failure_context}{timeout_context}{fork_context} ### Action Required diff --git a/pkg/constants/constants.go b/pkg/constants/constants.go index c85f1926468..a091e4dcef2 100644 --- a/pkg/constants/constants.go +++ b/pkg/constants/constants.go @@ -228,6 +228,9 @@ const DefaultToolTimeout = 60 * time.Second // DefaultMCPStartupTimeout is the default timeout for MCP server startup const DefaultMCPStartupTimeout = 120 * time.Second +// DefaultMaxEffectiveTokens is the default ET budget enforced by the AWF API proxy. +const DefaultMaxEffectiveTokens int64 = 10000000 + // MCPSessionTimeoutMin is the minimum allowed value for engine.mcp.session-timeout (5 minutes). const MCPSessionTimeoutMin = 5 * time.Minute diff --git a/pkg/parser/schemas/main_workflow_schema.json b/pkg/parser/schemas/main_workflow_schema.json index 19a0279e517..2cd5a6a9806 100644 --- a/pkg/parser/schemas/main_workflow_schema.json +++ b/pkg/parser/schemas/main_workflow_schema.json @@ -3675,6 +3675,21 @@ ], "$ref": "#/$defs/engine_config" }, + "max-effective-tokens": { + "oneOf": [ + { + "type": "integer", + "minimum": 1, + "description": "Maximum effective-token (ET) budget for AWF API proxy enforcement." + }, + { + "type": "string", + "pattern": "^[0-9]+$", + "description": "Maximum effective-token (ET) budget as a numeric string." + } + ], + "description": "Explicit ET budget control for firewall cost enforcement. Defaults to 10000000 when omitted." + }, "mcp-servers": { "type": "object", "description": "MCP server definitions", diff --git a/pkg/workflow/awf_config.go b/pkg/workflow/awf_config.go index b51db5ce34b..75a957b76c7 100644 --- a/pkg/workflow/awf_config.go +++ b/pkg/workflow/awf_config.go @@ -151,6 +151,9 @@ type AWFAPIProxyConfig struct { // Maps to: --enable-api-proxy Enabled bool `json:"enabled"` + // MaxEffectiveTokens is the explicit ET budget enforced by the API proxy. + MaxEffectiveTokens int64 `json:"maxEffectiveTokens,omitempty"` + // Targets holds per-provider API target overrides. // Supported keys: "openai", "anthropic", "copilot", "gemini" Targets map[string]*AWFAPITargetConfig `json:"targets,omitempty"` @@ -239,8 +242,13 @@ func BuildAWFConfigJSON(config AWFCommandConfig) (string, error) { } // ── API proxy section ───────────────────────────────────────────────────── + maxEffectiveTokens := constants.DefaultMaxEffectiveTokens + if config.WorkflowData != nil && config.WorkflowData.EngineConfig != nil { + maxEffectiveTokens = config.WorkflowData.EngineConfig.GetMaxEffectiveTokens() + } apiProxy := &AWFAPIProxyConfig{ - Enabled: true, + Enabled: true, + MaxEffectiveTokens: maxEffectiveTokens, } targets := map[string]*AWFAPITargetConfig{} diff --git a/pkg/workflow/awf_config_test.go b/pkg/workflow/awf_config_test.go index 0a81d815caa..d5c5a5a1cdf 100644 --- a/pkg/workflow/awf_config_test.go +++ b/pkg/workflow/awf_config_test.go @@ -45,6 +45,7 @@ func TestBuildAWFConfigJSON(t *testing.T) { // apiProxy section with enabled: true assert.Contains(t, jsonStr, `"apiProxy"`, "should include apiProxy section") assert.Contains(t, jsonStr, `"enabled":true`, "apiProxy should be enabled") + assert.Contains(t, jsonStr, `"maxEffectiveTokens":10000000`, "apiProxy should include default ET budget") // container.imageTag assert.Contains(t, jsonStr, `"imageTag"`, "should include imageTag") @@ -95,6 +96,26 @@ func TestBuildAWFConfigJSON(t *testing.T) { assert.Contains(t, jsonStr, "my-proxy.internal.example.com", "should include the openai host") }) + t.Run("configured max-effective-tokens overrides default apiProxy budget", func(t *testing.T) { + config := AWFCommandConfig{ + EngineName: "copilot", + AllowedDomains: "github.com", + WorkflowData: &WorkflowData{ + EngineConfig: &EngineConfig{ + ID: "copilot", + MaxEffectiveTokens: 424242, + }, + NetworkPermissions: &NetworkPermissions{ + Firewall: &FirewallConfig{Enabled: true}, + }, + }, + } + + jsonStr, err := BuildAWFConfigJSON(config) + require.NoError(t, err) + assert.Contains(t, jsonStr, `"maxEffectiveTokens":424242`, "apiProxy should use configured ET budget") + }) + t.Run("anthropic API target is included in apiProxy targets", func(t *testing.T) { config := AWFCommandConfig{ EngineName: "claude", diff --git a/pkg/workflow/compiler_main_job.go b/pkg/workflow/compiler_main_job.go index 791534a5c15..dc1d8851edf 100644 --- a/pkg/workflow/compiler_main_job.go +++ b/pkg/workflow/compiler_main_job.go @@ -203,6 +203,9 @@ func (c *Compiler) buildMainJob(data *WorkflowData, activationJobCreated bool) ( // It is exposed here so that the safe_outputs job can set GH_AW_EFFECTIVE_TOKENS and render // the {effective_tokens_suffix} template expression in footer templates. "effective_tokens": fmt.Sprintf("${{ steps.%s.outputs.effective_tokens }}", constants.ParseMCPGatewayStepID), + // effective_tokens_rate_limit_error is true when MCP gateway logs indicate ET budget + // exhaustion or API rate limiting attributable to ET constraints. + "effective_tokens_rate_limit_error": fmt.Sprintf("${{ steps.%s.outputs.effective_tokens_rate_limit_error || 'false' }}", constants.ParseMCPGatewayStepID), // setup-trace-id propagates the shared OTLP trace ID to downstream jobs (detection, safe_outputs, cache, etc.) "setup-trace-id": "${{ steps.setup.outputs.trace-id }}", } diff --git a/pkg/workflow/compiler_orchestrator_engine.go b/pkg/workflow/compiler_orchestrator_engine.go index 39c81734ea7..0ef3f40d273 100644 --- a/pkg/workflow/compiler_orchestrator_engine.go +++ b/pkg/workflow/compiler_orchestrator_engine.go @@ -36,6 +36,12 @@ func (c *Compiler) setupEngineAndImports(result *parser.FrontmatterResult, clean // Extract AI engine setting from frontmatter engineSetting, engineConfig := c.ExtractEngineConfig(result.Frontmatter) + // Preserve the top-level ET budget before string-form engine handling may + // intentionally clear engineConfig while converting "engine: " into an import. + preservedMaxEffectiveTokens := int64(0) + if engineConfig != nil { + preservedMaxEffectiveTokens = engineConfig.MaxEffectiveTokens + } // Validate and register inline engine definitions (engine.runtime sub-object). // Must happen before catalog resolution so the inline definition is visible to Resolve(). @@ -272,6 +278,9 @@ func (c *Compiler) setupEngineAndImports(result *parser.FrontmatterResult, clean if engineConfig == nil { engineConfig = &EngineConfig{ID: engineSetting} } + if preservedMaxEffectiveTokens > 0 { + engineConfig.MaxEffectiveTokens = preservedMaxEffectiveTokens + } if engineConfig.MCPToolTimeout == "" && importsResult.MergedEngineMCPToolTimeout != "" { engineConfig.MCPToolTimeout = importsResult.MergedEngineMCPToolTimeout orchestratorEngineLog.Printf("Applied engine.mcp.tool-timeout from import: %s", engineConfig.MCPToolTimeout) diff --git a/pkg/workflow/engine.go b/pkg/workflow/engine.go index 87e504c6481..12d3b4d2d32 100644 --- a/pkg/workflow/engine.go +++ b/pkg/workflow/engine.go @@ -5,6 +5,7 @@ import ( "fmt" "strconv" + "github.com/github/gh-aw/pkg/constants" "github.com/github/gh-aw/pkg/logger" "github.com/github/gh-aw/pkg/stringutil" "github.com/github/gh-aw/pkg/types" @@ -15,21 +16,22 @@ var engineLog = logger.New("workflow:engine") // EngineConfig represents the parsed engine configuration type EngineConfig struct { - ID string - Version string - Model string - MaxTurns string - MaxContinuations int // Maximum number of continuations for autopilot mode (copilot engine only; > 1 enables --autopilot) - Concurrency string // Agent job-level concurrency configuration (YAML format) - UserAgent string - Command string // Custom executable path (when set, skip installation steps) - HarnessScript string // Custom Node.js harness script filename (replaces engine default harness script when supported) - Env map[string]string - Config string - Args []string - Agent string // Agent identifier for copilot --agent flag (copilot engine only) - APITarget string // Custom API endpoint hostname (e.g., "api.acme.ghe.com" or "api.enterprise.githubcopilot.com") - Bare bool // When true, disables automatic loading of context/instructions (copilot: --no-custom-instructions, claude: --bare, codex: --no-system-prompt, gemini: GEMINI_SYSTEM_MD=/dev/null) + ID string + Version string + Model string + MaxTurns string + MaxContinuations int // Maximum number of continuations for autopilot mode (copilot engine only; > 1 enables --autopilot) + MaxEffectiveTokens int64 // Maximum allowed effective tokens (ET) budget for AWF apiProxy firewall enforcement + Concurrency string // Agent job-level concurrency configuration (YAML format) + UserAgent string + Command string // Custom executable path (when set, skip installation steps) + HarnessScript string // Custom Node.js harness script filename (replaces engine default harness script when supported) + Env map[string]string + Config string + Args []string + Agent string // Agent identifier for copilot --agent flag (copilot engine only) + APITarget string // Custom API endpoint hostname (e.g., "api.acme.ghe.com" or "api.enterprise.githubcopilot.com") + Bare bool // When true, disables automatic loading of context/instructions (copilot: --no-custom-instructions, claude: --bare, codex: --no-system-prompt, gemini: GEMINI_SYSTEM_MD=/dev/null) // TokenWeights provides custom model cost data for effective token computation. // When set, overrides or extends the built-in model_multipliers.json values. TokenWeights *types.TokenWeights @@ -99,15 +101,47 @@ type EngineNetworkConfig struct { Network *NetworkPermissions } +// GetMaxEffectiveTokens returns the configured engine ET budget, falling back to the default. +func (e *EngineConfig) GetMaxEffectiveTokens() int64 { + if e == nil || e.MaxEffectiveTokens <= 0 { + return constants.DefaultMaxEffectiveTokens + } + return e.MaxEffectiveTokens +} + +// parseMaxEffectiveTokensValue parses max-effective-tokens from either integer +// or numeric-string frontmatter values. +// +// A return value of 0 is a sentinel that means "not configured" (missing or +// invalid); explicit zero is not a valid user value because schema validation +// enforces minimum 1 before this parser path runs. +func parseMaxEffectiveTokensValue(raw any) int64 { + if val, ok := typeutil.ParseIntValue(raw); ok && val > 0 { + return int64(val) + } + if rawStr, ok := raw.(string); ok { + if parsed, err := strconv.ParseInt(rawStr, 10, 64); err == nil && parsed > 0 { + return parsed + } + engineLog.Printf("Ignoring invalid max-effective-tokens value: %q", rawStr) + } + return 0 +} + // ExtractEngineConfig extracts engine configuration from frontmatter, supporting both string and object formats func (c *Compiler) ExtractEngineConfig(frontmatter map[string]any) (string, *EngineConfig) { + topLevelMaxEffectiveTokens := parseMaxEffectiveTokensValue(frontmatter["max-effective-tokens"]) + if engine, exists := frontmatter["engine"]; exists { engineLog.Print("Extracting engine configuration from frontmatter") // Handle string format (backwards compatibility) if engineStr, ok := engine.(string); ok { engineLog.Printf("Found engine in string format: %s", engineStr) - return engineStr, &EngineConfig{ID: engineStr} + return engineStr, &EngineConfig{ + ID: engineStr, + MaxEffectiveTokens: topLevelMaxEffectiveTokens, + } } // Handle object format @@ -170,6 +204,7 @@ func (c *Compiler) ExtractEngineConfig(frontmatter map[string]any) (string, *Eng engineLog.Printf("Extracted bare mode (inline): %v", config.Bare) } } + config.MaxEffectiveTokens = topLevelMaxEffectiveTokens engineLog.Printf("Extracted inline engine definition: runtimeID=%s, providerID=%s", config.ID, config.InlineProviderID) return config.ID, config @@ -371,11 +406,16 @@ func (c *Compiler) ExtractEngineConfig(frontmatter map[string]any) (string, *Eng } // Return the ID as the engineSetting for backwards compatibility + config.MaxEffectiveTokens = topLevelMaxEffectiveTokens engineLog.Printf("Extracted engine configuration: ID=%s", config.ID) return config.ID, config } } + if topLevelMaxEffectiveTokens > 0 { + return "", &EngineConfig{MaxEffectiveTokens: topLevelMaxEffectiveTokens} + } + // No engine specified engineLog.Print("No engine configuration found in frontmatter") return "", nil diff --git a/pkg/workflow/engine_config_test.go b/pkg/workflow/engine_config_test.go index 5d0f1700138..e696d19dcf9 100644 --- a/pkg/workflow/engine_config_test.go +++ b/pkg/workflow/engine_config_test.go @@ -28,6 +28,14 @@ func TestExtractEngineConfig(t *testing.T) { expectedEngineSetting: "", expectedConfig: nil, }, + { + name: "top-level max-effective-tokens without engine", + frontmatter: map[string]any{ + "max-effective-tokens": 10000000, + }, + expectedEngineSetting: "", + expectedConfig: &EngineConfig{MaxEffectiveTokens: 10000000}, + }, { name: "string format - claude", frontmatter: map[string]any{"engine": "claude"}, @@ -128,6 +136,28 @@ func TestExtractEngineConfig(t *testing.T) { expectedEngineSetting: "claude", expectedConfig: &EngineConfig{ID: "claude", MaxTurns: "5"}, }, + { + name: "object format - with top-level max-effective-tokens", + frontmatter: map[string]any{ + "engine": map[string]any{ + "id": "claude", + }, + "max-effective-tokens": 10000000, + }, + expectedEngineSetting: "claude", + expectedConfig: &EngineConfig{ID: "claude", MaxEffectiveTokens: 10000000}, + }, + { + name: "object format - with top-level max-effective-tokens as string", + frontmatter: map[string]any{ + "engine": map[string]any{ + "id": "claude", + }, + "max-effective-tokens": "10000000", + }, + expectedEngineSetting: "claude", + expectedConfig: &EngineConfig{ID: "claude", MaxEffectiveTokens: 10000000}, + }, { name: "object format - complete with max-turns", frontmatter: map[string]any{ @@ -271,6 +301,10 @@ func TestExtractEngineConfig(t *testing.T) { t.Errorf("Expected config.MaxTurns '%s', got '%s'", test.expectedConfig.MaxTurns, config.MaxTurns) } + if config.MaxEffectiveTokens != test.expectedConfig.MaxEffectiveTokens { + t.Errorf("Expected config.MaxEffectiveTokens '%d', got '%d'", test.expectedConfig.MaxEffectiveTokens, config.MaxEffectiveTokens) + } + if config.UserAgent != test.expectedConfig.UserAgent { t.Errorf("Expected config.UserAgent '%s', got '%s'", test.expectedConfig.UserAgent, config.UserAgent) } diff --git a/pkg/workflow/notify_comment.go b/pkg/workflow/notify_comment.go index c00cc1cca46..9bd733cd5c9 100644 --- a/pkg/workflow/notify_comment.go +++ b/pkg/workflow/notify_comment.go @@ -250,6 +250,10 @@ func (c *Compiler) buildConclusionJob(data *WorkflowData, mainJobName string, sa agentFailureEnvVars = append(agentFailureEnvVars, fmt.Sprintf(" GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.%s.outputs.checkout_pr_success }}\n", mainJobName)) } + // Pass ET usage and ET rate-limit detection outputs from the agent job. + agentFailureEnvVars = append(agentFailureEnvVars, fmt.Sprintf(" GH_AW_EFFECTIVE_TOKENS: ${{ needs.%s.outputs.effective_tokens || '' }}\n", mainJobName)) + agentFailureEnvVars = append(agentFailureEnvVars, fmt.Sprintf(" GH_AW_EFFECTIVE_TOKENS_RATE_LIMIT_ERROR: ${{ needs.%s.outputs.effective_tokens_rate_limit_error || 'false' }}\n", mainJobName)) + // Pass Copilot-engine-specific error detection outputs to the conclusion job. // These are set by the detect-copilot-errors step in the agent job and cover: // - inference_access_error: token lacks inference access @@ -380,6 +384,13 @@ func (c *Compiler) buildConclusionJob(data *WorkflowData, mainJobName string, sa agentFailureEnvVars = append(agentFailureEnvVars, fmt.Sprintf(" GH_AW_TIMEOUT_MINUTES: %q\n", timeoutValue)) } + // Pass configured ET budget so failure reporting can attribute ET budget exhaustion accurately. + maxEffectiveTokens := constants.DefaultMaxEffectiveTokens + if data.EngineConfig != nil { + maxEffectiveTokens = data.EngineConfig.GetMaxEffectiveTokens() + } + agentFailureEnvVars = append(agentFailureEnvVars, fmt.Sprintf(" GH_AW_MAX_EFFECTIVE_TOKENS: %q\n", strconv.FormatInt(maxEffectiveTokens, 10))) + // Pass cache-memory availability flag so the failure handler can detect cache-miss // misconfigurations: a cache_miss reported by the agent despite cache-memory being available // indicates the prompt is referencing an incorrect file path within the cache directory. diff --git a/pkg/workflow/schemas/awf-config.schema.json b/pkg/workflow/schemas/awf-config.schema.json index e82a50864e4..43ca2823334 100644 --- a/pkg/workflow/schemas/awf-config.schema.json +++ b/pkg/workflow/schemas/awf-config.schema.json @@ -51,6 +51,11 @@ "type": "boolean", "description": "Enable the API proxy sidecar container." }, + "maxEffectiveTokens": { + "type": "integer", + "minimum": 1, + "description": "Maximum effective-token (ET) budget enforced by the API proxy." + }, "enableOpenCode": { "type": "boolean", "description": "Enable the OpenCode API proxy endpoint (port 10004)." diff --git a/pkg/workflow/testdata/TestWasmGolden_CompileFixtures/basic-copilot.golden b/pkg/workflow/testdata/TestWasmGolden_CompileFixtures/basic-copilot.golden index 90fb4da5fed..3b79e36f852 100644 --- a/pkg/workflow/testdata/TestWasmGolden_CompileFixtures/basic-copilot.golden +++ b/pkg/workflow/testdata/TestWasmGolden_CompileFixtures/basic-copilot.golden @@ -259,6 +259,7 @@ jobs: agentic_engine_timeout: ${{ steps.detect-copilot-errors.outputs.agentic_engine_timeout || 'false' }} checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} effective_tokens: ${{ steps.parse-mcp-gateway.outputs.effective_tokens }} + effective_tokens_rate_limit_error: ${{ steps.parse-mcp-gateway.outputs.effective_tokens_rate_limit_error || 'false' }} inference_access_error: ${{ steps.detect-copilot-errors.outputs.inference_access_error || 'false' }} mcp_policy_error: ${{ steps.detect-copilot-errors.outputs.mcp_policy_error || 'false' }} model: ${{ needs.activation.outputs.model }} @@ -429,7 +430,7 @@ jobs: GH_AW_NODE_BIN=$(command -v node 2>/dev/null || true) export GH_AW_NODE_BIN (umask 177 && touch /tmp/gh-aw/agent-stdio.log) - printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.41/awf-config.schema.json","network":{"allowDomains":["api.business.githubcopilot.com","api.enterprise.githubcopilot.com","api.github.com","api.githubcopilot.com","api.individual.githubcopilot.com","api.snapcraft.io","archive.ubuntu.com","azure.archive.ubuntu.com","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","github.com","host.docker.internal","json-schema.org","json.schemastore.org","keyserver.ubuntu.com","ocsp.digicert.com","ocsp.geotrust.com","ocsp.globalsign.com","ocsp.identrust.com","ocsp.sectigo.com","ocsp.ssl.com","ocsp.thawte.com","ocsp.usertrust.com","ocsp.verisign.com","packagecloud.io","packages.cloud.google.com","packages.microsoft.com","ppa.launchpad.net","raw.githubusercontent.com","registry.npmjs.org","s.symcb.com","s.symcd.com","security.ubuntu.com","telemetry.enterprise.githubcopilot.com","ts-crl.ws.symantec.com","ts-ocsp.ws.symantec.com","www.googleapis.com"]},"apiProxy":{"enabled":true,"models":{"auto":["large"],"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*"],"gemini-flash":["copilot/gemini-*flash*","google/gemini-*flash*","gemini/gemini-*flash*"],"gemini-pro":["copilot/gemini-*pro*","google/gemini-*pro*","gemini/gemini-*pro*"],"gpt-4.1":["copilot/gpt-4.1*","openai/gpt-4.1*"],"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*"],"haiku":["copilot/*haiku*","anthropic/*haiku*"],"large":["sonnet","gpt-5-pro","gpt-5","gemini-pro"],"mini":["haiku","gpt-5-mini","gpt-5-nano","gemini-flash"],"opus":["copilot/*opus*","anthropic/*opus*"],"reasoning":["copilot/o1*","copilot/o3*","copilot/o4*","openai/o1*","openai/o3*","openai/o4*"],"small":["mini"],"sonnet":["copilot/*sonnet*","anthropic/*sonnet*"]}},"container":{"imageTag":"0.25.41"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json" && cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json + printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.41/awf-config.schema.json","network":{"allowDomains":["api.business.githubcopilot.com","api.enterprise.githubcopilot.com","api.github.com","api.githubcopilot.com","api.individual.githubcopilot.com","api.snapcraft.io","archive.ubuntu.com","azure.archive.ubuntu.com","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","github.com","host.docker.internal","json-schema.org","json.schemastore.org","keyserver.ubuntu.com","ocsp.digicert.com","ocsp.geotrust.com","ocsp.globalsign.com","ocsp.identrust.com","ocsp.sectigo.com","ocsp.ssl.com","ocsp.thawte.com","ocsp.usertrust.com","ocsp.verisign.com","packagecloud.io","packages.cloud.google.com","packages.microsoft.com","ppa.launchpad.net","raw.githubusercontent.com","registry.npmjs.org","s.symcb.com","s.symcd.com","security.ubuntu.com","telemetry.enterprise.githubcopilot.com","ts-crl.ws.symantec.com","ts-ocsp.ws.symantec.com","www.googleapis.com"]},"apiProxy":{"enabled":true,"maxEffectiveTokens":10000000,"models":{"auto":["large"],"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*"],"gemini-flash":["copilot/gemini-*flash*","google/gemini-*flash*","gemini/gemini-*flash*"],"gemini-pro":["copilot/gemini-*pro*","google/gemini-*pro*","gemini/gemini-*pro*"],"gpt-4.1":["copilot/gpt-4.1*","openai/gpt-4.1*"],"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*"],"haiku":["copilot/*haiku*","anthropic/*haiku*"],"large":["sonnet","gpt-5-pro","gpt-5","gemini-pro"],"mini":["haiku","gpt-5-mini","gpt-5-nano","gemini-flash"],"opus":["copilot/*opus*","anthropic/*opus*"],"reasoning":["copilot/o1*","copilot/o3*","copilot/o4*","openai/o1*","openai/o3*","openai/o4*"],"small":["mini"],"sonnet":["copilot/*sonnet*","anthropic/*sonnet*"]}},"container":{"imageTag":"0.25.41"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json" && cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json # shellcheck disable=SC1003 sudo -E 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" --env-all --exclude-env COPILOT_GITHUB_TOKEN --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --skip-pull \ -- /bin/bash -c 'export PATH="$(find /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 4 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/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 || echo node)"; fi; "$GH_AW_NODE_EXEC" ${RUNNER_TEMP}/gh-aw/actions/copilot_harness.cjs /usr/local/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 diff --git a/pkg/workflow/testdata/TestWasmGolden_CompileFixtures/playwright-cli-mode.golden b/pkg/workflow/testdata/TestWasmGolden_CompileFixtures/playwright-cli-mode.golden index 50a94a09f08..94f39b805c6 100644 --- a/pkg/workflow/testdata/TestWasmGolden_CompileFixtures/playwright-cli-mode.golden +++ b/pkg/workflow/testdata/TestWasmGolden_CompileFixtures/playwright-cli-mode.golden @@ -269,6 +269,7 @@ jobs: agentic_engine_timeout: ${{ steps.detect-copilot-errors.outputs.agentic_engine_timeout || 'false' }} checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} effective_tokens: ${{ steps.parse-mcp-gateway.outputs.effective_tokens }} + effective_tokens_rate_limit_error: ${{ steps.parse-mcp-gateway.outputs.effective_tokens_rate_limit_error || 'false' }} inference_access_error: ${{ steps.detect-copilot-errors.outputs.inference_access_error || 'false' }} mcp_policy_error: ${{ steps.detect-copilot-errors.outputs.mcp_policy_error || 'false' }} model: ${{ needs.activation.outputs.model }} @@ -443,7 +444,7 @@ jobs: GH_AW_NODE_BIN=$(command -v node 2>/dev/null || true) export GH_AW_NODE_BIN (umask 177 && touch /tmp/gh-aw/agent-stdio.log) - printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.41/awf-config.schema.json","network":{"allowDomains":["api.business.githubcopilot.com","api.enterprise.githubcopilot.com","api.github.com","api.githubcopilot.com","api.individual.githubcopilot.com","api.snapcraft.io","archive.ubuntu.com","azure.archive.ubuntu.com","cdn.playwright.dev","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","github.com","host.docker.internal","json-schema.org","json.schemastore.org","keyserver.ubuntu.com","ocsp.digicert.com","ocsp.geotrust.com","ocsp.globalsign.com","ocsp.identrust.com","ocsp.sectigo.com","ocsp.ssl.com","ocsp.thawte.com","ocsp.usertrust.com","ocsp.verisign.com","packagecloud.io","packages.cloud.google.com","packages.microsoft.com","playwright.download.prss.microsoft.com","ppa.launchpad.net","raw.githubusercontent.com","registry.npmjs.org","s.symcb.com","s.symcd.com","security.ubuntu.com","telemetry.enterprise.githubcopilot.com","ts-crl.ws.symantec.com","ts-ocsp.ws.symantec.com","www.googleapis.com"]},"apiProxy":{"enabled":true,"models":{"auto":["large"],"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*"],"gemini-flash":["copilot/gemini-*flash*","google/gemini-*flash*","gemini/gemini-*flash*"],"gemini-pro":["copilot/gemini-*pro*","google/gemini-*pro*","gemini/gemini-*pro*"],"gpt-4.1":["copilot/gpt-4.1*","openai/gpt-4.1*"],"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*"],"haiku":["copilot/*haiku*","anthropic/*haiku*"],"large":["sonnet","gpt-5-pro","gpt-5","gemini-pro"],"mini":["haiku","gpt-5-mini","gpt-5-nano","gemini-flash"],"opus":["copilot/*opus*","anthropic/*opus*"],"reasoning":["copilot/o1*","copilot/o3*","copilot/o4*","openai/o1*","openai/o3*","openai/o4*"],"small":["mini"],"sonnet":["copilot/*sonnet*","anthropic/*sonnet*"]}},"container":{"imageTag":"0.25.41"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json" && cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json + printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.41/awf-config.schema.json","network":{"allowDomains":["api.business.githubcopilot.com","api.enterprise.githubcopilot.com","api.github.com","api.githubcopilot.com","api.individual.githubcopilot.com","api.snapcraft.io","archive.ubuntu.com","azure.archive.ubuntu.com","cdn.playwright.dev","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","github.com","host.docker.internal","json-schema.org","json.schemastore.org","keyserver.ubuntu.com","ocsp.digicert.com","ocsp.geotrust.com","ocsp.globalsign.com","ocsp.identrust.com","ocsp.sectigo.com","ocsp.ssl.com","ocsp.thawte.com","ocsp.usertrust.com","ocsp.verisign.com","packagecloud.io","packages.cloud.google.com","packages.microsoft.com","playwright.download.prss.microsoft.com","ppa.launchpad.net","raw.githubusercontent.com","registry.npmjs.org","s.symcb.com","s.symcd.com","security.ubuntu.com","telemetry.enterprise.githubcopilot.com","ts-crl.ws.symantec.com","ts-ocsp.ws.symantec.com","www.googleapis.com"]},"apiProxy":{"enabled":true,"maxEffectiveTokens":10000000,"models":{"auto":["large"],"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*"],"gemini-flash":["copilot/gemini-*flash*","google/gemini-*flash*","gemini/gemini-*flash*"],"gemini-pro":["copilot/gemini-*pro*","google/gemini-*pro*","gemini/gemini-*pro*"],"gpt-4.1":["copilot/gpt-4.1*","openai/gpt-4.1*"],"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*"],"haiku":["copilot/*haiku*","anthropic/*haiku*"],"large":["sonnet","gpt-5-pro","gpt-5","gemini-pro"],"mini":["haiku","gpt-5-mini","gpt-5-nano","gemini-flash"],"opus":["copilot/*opus*","anthropic/*opus*"],"reasoning":["copilot/o1*","copilot/o3*","copilot/o4*","openai/o1*","openai/o3*","openai/o4*"],"small":["mini"],"sonnet":["copilot/*sonnet*","anthropic/*sonnet*"]}},"container":{"imageTag":"0.25.41"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json" && cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json # shellcheck disable=SC1003 sudo -E 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" --env-all --exclude-env COPILOT_GITHUB_TOKEN --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --skip-pull \ -- /bin/bash -c 'export PATH="$(find /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 4 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/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 || echo node)"; fi; "$GH_AW_NODE_EXEC" ${RUNNER_TEMP}/gh-aw/actions/copilot_harness.cjs /usr/local/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 diff --git a/pkg/workflow/testdata/TestWasmGolden_CompileFixtures/smoke-copilot.golden b/pkg/workflow/testdata/TestWasmGolden_CompileFixtures/smoke-copilot.golden index e49a5baa85f..00b8e2c0dd9 100644 --- a/pkg/workflow/testdata/TestWasmGolden_CompileFixtures/smoke-copilot.golden +++ b/pkg/workflow/testdata/TestWasmGolden_CompileFixtures/smoke-copilot.golden @@ -375,6 +375,7 @@ jobs: agentic_engine_timeout: ${{ steps.detect-copilot-errors.outputs.agentic_engine_timeout || 'false' }} checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} effective_tokens: ${{ steps.parse-mcp-gateway.outputs.effective_tokens }} + effective_tokens_rate_limit_error: ${{ steps.parse-mcp-gateway.outputs.effective_tokens_rate_limit_error || 'false' }} inference_access_error: ${{ steps.detect-copilot-errors.outputs.inference_access_error || 'false' }} mcp_policy_error: ${{ steps.detect-copilot-errors.outputs.mcp_policy_error || 'false' }} model: ${{ needs.activation.outputs.model }} @@ -675,7 +676,7 @@ jobs: GH_AW_NODE_BIN=$(command -v node 2>/dev/null || true) export GH_AW_NODE_BIN (umask 177 && touch /tmp/gh-aw/agent-stdio.log) - printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.41/awf-config.schema.json","network":{"allowDomains":["*.githubusercontent.com","api.business.githubcopilot.com","api.enterprise.githubcopilot.com","api.github.com","api.githubcopilot.com","api.individual.githubcopilot.com","api.npms.io","api.snapcraft.io","archive.ubuntu.com","azure.archive.ubuntu.com","bun.sh","cdn.jsdelivr.net","cdn.playwright.dev","codeload.github.com","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","deb.nodesource.com","deno.land","docs.github.com","esm.sh","get.pnpm.io","github-cloud.githubusercontent.com","github-cloud.s3.amazonaws.com","github.blog","github.com","github.githubassets.com","go.dev","golang.org","googleapis.deno.dev","googlechromelabs.github.io","goproxy.io","host.docker.internal","json-schema.org","json.schemastore.org","jsr.io","keyserver.ubuntu.com","lfs.github.com","nodejs.org","npm.pkg.github.com","npmjs.com","npmjs.org","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","packagecloud.io","packages.cloud.google.com","packages.microsoft.com","pkg.go.dev","playwright.download.prss.microsoft.com","ppa.launchpad.net","proxy.golang.org","raw.githubusercontent.com","registry.bower.io","registry.npmjs.com","registry.npmjs.org","registry.yarnpkg.com","repo.yarnpkg.com","s.symcb.com","s.symcd.com","security.ubuntu.com","skimdb.npmjs.com","storage.googleapis.com","sum.golang.org","telemetry.enterprise.githubcopilot.com","telemetry.vercel.com","ts-crl.ws.symantec.com","ts-ocsp.ws.symantec.com","www.googleapis.com","www.npmjs.com","www.npmjs.org","yarnpkg.com"]},"apiProxy":{"enabled":true,"models":{"auto":["large"],"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*"],"gemini-flash":["copilot/gemini-*flash*","google/gemini-*flash*","gemini/gemini-*flash*"],"gemini-pro":["copilot/gemini-*pro*","google/gemini-*pro*","gemini/gemini-*pro*"],"gpt-4.1":["copilot/gpt-4.1*","openai/gpt-4.1*"],"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*"],"haiku":["copilot/*haiku*","anthropic/*haiku*"],"large":["sonnet","gpt-5-pro","gpt-5","gemini-pro"],"mini":["haiku","gpt-5-mini","gpt-5-nano","gemini-flash"],"opus":["copilot/*opus*","anthropic/*opus*"],"reasoning":["copilot/o1*","copilot/o3*","copilot/o4*","openai/o1*","openai/o3*","openai/o4*"],"small":["mini"],"sonnet":["copilot/*sonnet*","anthropic/*sonnet*"]}},"container":{"imageTag":"0.25.41"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json" && cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json + printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.41/awf-config.schema.json","network":{"allowDomains":["*.githubusercontent.com","api.business.githubcopilot.com","api.enterprise.githubcopilot.com","api.github.com","api.githubcopilot.com","api.individual.githubcopilot.com","api.npms.io","api.snapcraft.io","archive.ubuntu.com","azure.archive.ubuntu.com","bun.sh","cdn.jsdelivr.net","cdn.playwright.dev","codeload.github.com","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","deb.nodesource.com","deno.land","docs.github.com","esm.sh","get.pnpm.io","github-cloud.githubusercontent.com","github-cloud.s3.amazonaws.com","github.blog","github.com","github.githubassets.com","go.dev","golang.org","googleapis.deno.dev","googlechromelabs.github.io","goproxy.io","host.docker.internal","json-schema.org","json.schemastore.org","jsr.io","keyserver.ubuntu.com","lfs.github.com","nodejs.org","npm.pkg.github.com","npmjs.com","npmjs.org","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","packagecloud.io","packages.cloud.google.com","packages.microsoft.com","pkg.go.dev","playwright.download.prss.microsoft.com","ppa.launchpad.net","proxy.golang.org","raw.githubusercontent.com","registry.bower.io","registry.npmjs.com","registry.npmjs.org","registry.yarnpkg.com","repo.yarnpkg.com","s.symcb.com","s.symcd.com","security.ubuntu.com","skimdb.npmjs.com","storage.googleapis.com","sum.golang.org","telemetry.enterprise.githubcopilot.com","telemetry.vercel.com","ts-crl.ws.symantec.com","ts-ocsp.ws.symantec.com","www.googleapis.com","www.npmjs.com","www.npmjs.org","yarnpkg.com"]},"apiProxy":{"enabled":true,"maxEffectiveTokens":10000000,"models":{"auto":["large"],"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*"],"gemini-flash":["copilot/gemini-*flash*","google/gemini-*flash*","gemini/gemini-*flash*"],"gemini-pro":["copilot/gemini-*pro*","google/gemini-*pro*","gemini/gemini-*pro*"],"gpt-4.1":["copilot/gpt-4.1*","openai/gpt-4.1*"],"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*"],"haiku":["copilot/*haiku*","anthropic/*haiku*"],"large":["sonnet","gpt-5-pro","gpt-5","gemini-pro"],"mini":["haiku","gpt-5-mini","gpt-5-nano","gemini-flash"],"opus":["copilot/*opus*","anthropic/*opus*"],"reasoning":["copilot/o1*","copilot/o3*","copilot/o4*","openai/o1*","openai/o3*","openai/o4*"],"small":["mini"],"sonnet":["copilot/*sonnet*","anthropic/*sonnet*"]}},"container":{"imageTag":"0.25.41"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json" && cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json # shellcheck disable=SC1003 sudo -E 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" --env-all --exclude-env COPILOT_GITHUB_TOKEN --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --skip-pull \ -- /bin/bash -c 'export PATH="$(find /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 4 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/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 || echo node)"; fi; "$GH_AW_NODE_EXEC" ${RUNNER_TEMP}/gh-aw/actions/copilot_harness.cjs /usr/local/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 diff --git a/pkg/workflow/testdata/TestWasmGolden_CompileFixtures/with-imports.golden b/pkg/workflow/testdata/TestWasmGolden_CompileFixtures/with-imports.golden index 944b5448e07..c8665631b3f 100644 --- a/pkg/workflow/testdata/TestWasmGolden_CompileFixtures/with-imports.golden +++ b/pkg/workflow/testdata/TestWasmGolden_CompileFixtures/with-imports.golden @@ -260,6 +260,7 @@ jobs: agentic_engine_timeout: ${{ steps.detect-copilot-errors.outputs.agentic_engine_timeout || 'false' }} checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} effective_tokens: ${{ steps.parse-mcp-gateway.outputs.effective_tokens }} + effective_tokens_rate_limit_error: ${{ steps.parse-mcp-gateway.outputs.effective_tokens_rate_limit_error || 'false' }} inference_access_error: ${{ steps.detect-copilot-errors.outputs.inference_access_error || 'false' }} mcp_policy_error: ${{ steps.detect-copilot-errors.outputs.mcp_policy_error || 'false' }} model: ${{ needs.activation.outputs.model }} @@ -430,7 +431,7 @@ jobs: GH_AW_NODE_BIN=$(command -v node 2>/dev/null || true) export GH_AW_NODE_BIN (umask 177 && touch /tmp/gh-aw/agent-stdio.log) - printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.41/awf-config.schema.json","network":{"allowDomains":["api.business.githubcopilot.com","api.enterprise.githubcopilot.com","api.github.com","api.githubcopilot.com","api.individual.githubcopilot.com","api.snapcraft.io","archive.ubuntu.com","azure.archive.ubuntu.com","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","github.com","host.docker.internal","json-schema.org","json.schemastore.org","keyserver.ubuntu.com","ocsp.digicert.com","ocsp.geotrust.com","ocsp.globalsign.com","ocsp.identrust.com","ocsp.sectigo.com","ocsp.ssl.com","ocsp.thawte.com","ocsp.usertrust.com","ocsp.verisign.com","packagecloud.io","packages.cloud.google.com","packages.microsoft.com","ppa.launchpad.net","raw.githubusercontent.com","registry.npmjs.org","s.symcb.com","s.symcd.com","security.ubuntu.com","telemetry.enterprise.githubcopilot.com","ts-crl.ws.symantec.com","ts-ocsp.ws.symantec.com","www.googleapis.com"]},"apiProxy":{"enabled":true,"models":{"auto":["large"],"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*"],"gemini-flash":["copilot/gemini-*flash*","google/gemini-*flash*","gemini/gemini-*flash*"],"gemini-pro":["copilot/gemini-*pro*","google/gemini-*pro*","gemini/gemini-*pro*"],"gpt-4.1":["copilot/gpt-4.1*","openai/gpt-4.1*"],"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*"],"haiku":["copilot/*haiku*","anthropic/*haiku*"],"large":["sonnet","gpt-5-pro","gpt-5","gemini-pro"],"mini":["haiku","gpt-5-mini","gpt-5-nano","gemini-flash"],"opus":["copilot/*opus*","anthropic/*opus*"],"reasoning":["copilot/o1*","copilot/o3*","copilot/o4*","openai/o1*","openai/o3*","openai/o4*"],"small":["mini"],"sonnet":["copilot/*sonnet*","anthropic/*sonnet*"]}},"container":{"imageTag":"0.25.41"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json" && cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json + printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.41/awf-config.schema.json","network":{"allowDomains":["api.business.githubcopilot.com","api.enterprise.githubcopilot.com","api.github.com","api.githubcopilot.com","api.individual.githubcopilot.com","api.snapcraft.io","archive.ubuntu.com","azure.archive.ubuntu.com","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","github.com","host.docker.internal","json-schema.org","json.schemastore.org","keyserver.ubuntu.com","ocsp.digicert.com","ocsp.geotrust.com","ocsp.globalsign.com","ocsp.identrust.com","ocsp.sectigo.com","ocsp.ssl.com","ocsp.thawte.com","ocsp.usertrust.com","ocsp.verisign.com","packagecloud.io","packages.cloud.google.com","packages.microsoft.com","ppa.launchpad.net","raw.githubusercontent.com","registry.npmjs.org","s.symcb.com","s.symcd.com","security.ubuntu.com","telemetry.enterprise.githubcopilot.com","ts-crl.ws.symantec.com","ts-ocsp.ws.symantec.com","www.googleapis.com"]},"apiProxy":{"enabled":true,"maxEffectiveTokens":10000000,"models":{"auto":["large"],"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*"],"gemini-flash":["copilot/gemini-*flash*","google/gemini-*flash*","gemini/gemini-*flash*"],"gemini-pro":["copilot/gemini-*pro*","google/gemini-*pro*","gemini/gemini-*pro*"],"gpt-4.1":["copilot/gpt-4.1*","openai/gpt-4.1*"],"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*"],"haiku":["copilot/*haiku*","anthropic/*haiku*"],"large":["sonnet","gpt-5-pro","gpt-5","gemini-pro"],"mini":["haiku","gpt-5-mini","gpt-5-nano","gemini-flash"],"opus":["copilot/*opus*","anthropic/*opus*"],"reasoning":["copilot/o1*","copilot/o3*","copilot/o4*","openai/o1*","openai/o3*","openai/o4*"],"small":["mini"],"sonnet":["copilot/*sonnet*","anthropic/*sonnet*"]}},"container":{"imageTag":"0.25.41"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json" && cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json # shellcheck disable=SC1003 sudo -E 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" --env-all --exclude-env COPILOT_GITHUB_TOKEN --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --skip-pull \ -- /bin/bash -c 'export PATH="$(find /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 4 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/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 || echo node)"; fi; "$GH_AW_NODE_EXEC" ${RUNNER_TEMP}/gh-aw/actions/copilot_harness.cjs /usr/local/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 diff --git a/pkg/workflow/threat_detection.go b/pkg/workflow/threat_detection.go index 8ed7c3db183..6ec554734aa 100644 --- a/pkg/workflow/threat_detection.go +++ b/pkg/workflow/threat_detection.go @@ -608,14 +608,15 @@ func (c *Compiler) buildDetectionEngineExecutionStep(data *WorkflowData) []strin detectionEngineConfig = &EngineConfig{ID: engineSetting} } else { detectionEngineConfig = &EngineConfig{ - ID: detectionEngineConfig.ID, - Model: detectionEngineConfig.Model, - Version: detectionEngineConfig.Version, - Env: detectionEngineConfig.Env, - Config: detectionEngineConfig.Config, - Args: detectionEngineConfig.Args, - APITarget: detectionEngineConfig.APITarget, - HarnessScript: detectionEngineConfig.HarnessScript, + ID: detectionEngineConfig.ID, + Model: detectionEngineConfig.Model, + Version: detectionEngineConfig.Version, + Env: detectionEngineConfig.Env, + Config: detectionEngineConfig.Config, + Args: detectionEngineConfig.Args, + APITarget: detectionEngineConfig.APITarget, + MaxEffectiveTokens: detectionEngineConfig.MaxEffectiveTokens, + HarnessScript: detectionEngineConfig.HarnessScript, } } From e8b26329381bec1883ea134d8b4babfb4932b825 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Fri, 8 May 2026 16:31:01 -0700 Subject: [PATCH 7/8] Allow `engine.model` without `engine.id` (#31090) --- pkg/parser/import_field_extractor.go | 25 +++++-- pkg/parser/import_processor.go | 1 + pkg/parser/schemas/main_workflow_schema.json | 12 +++ pkg/workflow/compiler_orchestrator_engine.go | 16 ++++ pkg/workflow/engine_catalog_test.go | 14 +++- pkg/workflow/engine_validation.go | 60 +++++++++++++-- pkg/workflow/engine_validation_test.go | 49 ++++++++++++- pkg/workflow/imports_test.go | 77 ++++++++++++++++++++ 8 files changed, 238 insertions(+), 16 deletions(-) diff --git a/pkg/parser/import_field_extractor.go b/pkg/parser/import_field_extractor.go index 527d247003c..a62cc8eb1c9 100644 --- a/pkg/parser/import_field_extractor.go +++ b/pkg/parser/import_field_extractor.go @@ -68,6 +68,9 @@ type importAccumulator struct { // First engine.mcp.tool-timeout / engine.mcp.session-timeout found across all imported files (first-wins strategy) mergedEngineMCPToolTimeout string // Go duration string (e.g. "10m", "30s") mergedEngineMCPSessionTimeout string // Go duration string (e.g. "4h", "30m") + // First engine.model found in imports that have no engine.id (first-wins strategy). + // These express a model preference without selecting a specific engine. + mergedEngineModel string // Best-effort sub-agent frontmatter warnings collected during BFS traversal. warnings []string } @@ -265,15 +268,26 @@ func (acc *importAccumulator) extractAllImportFields(content []byte, item import } } } - // Only add to engines list if this config specifies an actual engine. - // Configs with only `mcp` settings are purely MCP gateway configuration + // Only add to engines list if this config specifies an actual engine + // (i.e. it carries an 'id' or 'runtime' field). Configs with only + // 'model' or 'mcp' settings are preferences, not engine selections, // and must not trigger the "multiple engine fields" validation error. - _, hasMCP := v["mcp"] - isMCPOnly := hasMCP && len(v) == 1 - if !isMCPOnly { + _, hasID := v["id"] + _, hasRuntime := v["runtime"] + if hasID || hasRuntime { if engineJSON, merr := json.Marshal(v); merr == nil { acc.engines = append(acc.engines, string(engineJSON)) } + } else { + // No engine ID or runtime — this is a model/MCP-only preference. + // Extract the model hint (first-wins) so it can be applied to the + // resolved engine after all imports are processed. + if modelStr, ok := v["model"].(string); ok && modelStr != "" { + if acc.mergedEngineModel == "" { + acc.mergedEngineModel = modelStr + log.Printf("Extracted engine.model preference from import %s: %s", item.fullPath, modelStr) + } + } } default: // Unexpected type — marshal and add to preserve existing behavior. @@ -615,6 +629,7 @@ func (acc *importAccumulator) toImportsResult(topologicalOrder []string) *Import MergedCheckout: strings.Join(acc.checkouts, "\n"), MergedEngineMCPToolTimeout: acc.mergedEngineMCPToolTimeout, MergedEngineMCPSessionTimeout: acc.mergedEngineMCPSessionTimeout, + MergedEngineModel: acc.mergedEngineModel, Warnings: acc.warnings, } } diff --git a/pkg/parser/import_processor.go b/pkg/parser/import_processor.go index 63ca7dcba51..d6479291f10 100644 --- a/pkg/parser/import_processor.go +++ b/pkg/parser/import_processor.go @@ -51,6 +51,7 @@ type ImportsResult struct { MergedObservability string // Merged observability config (JSON) from all imports as an endpoint array (deduped by URL) MergedEngineMCPToolTimeout string // First engine.mcp.tool-timeout found across all imports (Go duration string, e.g. "10m") MergedEngineMCPSessionTimeout string // First engine.mcp.session-timeout found across all imports (Go duration string, e.g. "4h") + MergedEngineModel string // First engine.model found in imports that have no engine.id (model preference without engine selection) ImportedFiles []string // List of imported file paths (for manifest) AgentFile string // Path to custom agent file (if imported) AgentImportSpec string // Original import specification for agent file (e.g., "owner/repo/path@ref") diff --git a/pkg/parser/schemas/main_workflow_schema.json b/pkg/parser/schemas/main_workflow_schema.json index 2cd5a6a9806..6d4a3c88906 100644 --- a/pkg/parser/schemas/main_workflow_schema.json +++ b/pkg/parser/schemas/main_workflow_schema.json @@ -10482,6 +10482,18 @@ }, "required": ["mcp"], "additionalProperties": false + }, + { + "type": "object", + "description": "Engine object with only a model preference (no engine.id). Allows workflow authors to express a model-size hint (e.g. 'small', 'large') without committing to a specific engine. The runtime selects an appropriate engine using its default, and the model preference is applied to it.", + "properties": { + "model": { + "type": "string", + "description": "Model preference or size category (e.g. 'small', 'large', 'gpt-4.1'). Applied to the default engine when engine.id is not specified." + } + }, + "required": ["model"], + "additionalProperties": false } ] }, diff --git a/pkg/workflow/compiler_orchestrator_engine.go b/pkg/workflow/compiler_orchestrator_engine.go index 0ef3f40d273..7680345221d 100644 --- a/pkg/workflow/compiler_orchestrator_engine.go +++ b/pkg/workflow/compiler_orchestrator_engine.go @@ -270,6 +270,16 @@ func (c *Compiler) setupEngineAndImports(result *parser.FrontmatterResult, clean } } + // Normalize: if the main workflow declared a preference-only engine object (e.g. + // engine: {model: small}) then engineConfig is non-nil but has an empty ID. + // Set the ID from the resolved engineSetting so that downstream code which reads + // engineConfig.ID (e.g. metadata env vars, threat-detection engine selection) gets + // the correct engine identifier rather than an empty string. + if engineConfig != nil && engineConfig.ID == "" && engineSetting != "" { + engineConfig.ID = engineSetting + orchestratorEngineLog.Printf("Normalized engineConfig.ID from engineSetting: %s", engineSetting) + } + // Merge engine.mcp.* settings from imports (consumer-specified values take precedence). // Shared workflows can declare engine.mcp.tool-timeout / engine.mcp.session-timeout to // propagate MCP gateway timeout configuration to consumers without requiring consumers @@ -289,6 +299,12 @@ func (c *Compiler) setupEngineAndImports(result *parser.FrontmatterResult, clean engineConfig.MCPSessionTimeout = importsResult.MergedEngineMCPSessionTimeout orchestratorEngineLog.Printf("Applied engine.mcp.session-timeout from import: %s", engineConfig.MCPSessionTimeout) } + // Apply model preference from imports that declare engine.model without engine.id. + // The consuming workflow's own model setting takes precedence (first-wins). + if engineConfig.Model == "" && importsResult.MergedEngineModel != "" { + engineConfig.Model = importsResult.MergedEngineModel + orchestratorEngineLog.Printf("Applied engine.model preference from import: %s", engineConfig.Model) + } // Validate the engine setting and resolve the runtime adapter via the catalog. // This performs exact catalog lookup, prefix fallback, and returns a formatted diff --git a/pkg/workflow/engine_catalog_test.go b/pkg/workflow/engine_catalog_test.go index b00848aafdc..8baf81707d3 100644 --- a/pkg/workflow/engine_catalog_test.go +++ b/pkg/workflow/engine_catalog_test.go @@ -97,7 +97,7 @@ func TestEngineCatalog_BuiltInsPresent(t *testing.T) { func TestEngineCatalogMatchesSchema(t *testing.T) { variants := engineSchemaOneOfVariants(t) - require.Len(t, variants, 5, "engine_config oneOf should have exactly 5 variants: string, object-with-id, object-with-runtime, engine-definition, mcp-only") + require.Len(t, variants, 6, "engine_config oneOf should have exactly 6 variants: string, object-with-id, object-with-runtime, engine-definition, mcp-only, model-only") // Variant 0: plain string (no enum — allows built-ins and custom named catalog entries) assert.Equal(t, "string", variants[0]["type"], @@ -145,4 +145,16 @@ func TestEngineCatalogMatchesSchema(t *testing.T) { "mcp-only variant should have an 'mcp' property") assert.NotContains(t, props4, "id", "mcp-only variant must NOT have an 'id' property") + + // Variant 5: model-only form — expresses a model preference without specifying an engine id + assert.Equal(t, "object", variants[5]["type"], + "sixth variant should be type object (model-only preference)") + props5, ok := variants[5]["properties"].(map[string]any) + require.True(t, ok, "sixth variant should have properties") + assert.Contains(t, props5, "model", + "model-only variant should have a 'model' property") + assert.NotContains(t, props5, "id", + "model-only variant must NOT have an 'id' property") + assert.NotContains(t, props5, "runtime", + "model-only variant must NOT have a 'runtime' property") } diff --git a/pkg/workflow/engine_validation.go b/pkg/workflow/engine_validation.go index 31ffb6d1f04..9b3ad8a7256 100644 --- a/pkg/workflow/engine_validation.go +++ b/pkg/workflow/engine_validation.go @@ -304,25 +304,71 @@ func (c *Compiler) validateEngineAuthDefinition(config *EngineConfig) error { return nil } +// isModelOnlyEngineJSON reports whether engineJSON represents an engine object that +// contains only preference settings (no 'id' or 'runtime' field). Such configs express +// a preference (e.g., model size or MCP timeouts) without selecting a specific engine, +// and must not be counted as engine specifications in conflict detection. +// Only objects whose keys are exclusively from {"model", "mcp"} (with at least one) +// are considered preference-only; other objects (including empty objects or objects +// with unknown keys) fall through to normal validation. +func isModelOnlyEngineJSON(engineJSON string) bool { + var obj map[string]any + if err := json.Unmarshal([]byte(engineJSON), &obj); err != nil { + return false // Not a JSON object; let normal validation handle it + } + _, hasID := obj["id"] + _, hasRuntime := obj["runtime"] + if hasID || hasRuntime { + return false + } + // Require at least one known preference key; reject empty objects or unknown keys. + hasPreference := false + for k := range obj { + switch k { + case "model", "mcp": + hasPreference = true + default: + return false // Unknown key — not a preference-only object + } + } + return hasPreference +} + // validateSingleEngineSpecification validates that only one engine field exists across all files func (c *Compiler) validateSingleEngineSpecification(mainEngineSetting string, includedEnginesJSON []string) (string, error) { var allEngines []string + // firstIncludedRealEngine holds the raw JSON of the first non-model-only engine spec + // from included files. It is used below to extract the engine ID when the single + // engine specification originates from an included file rather than the main workflow. + var firstIncludedRealEngine string // Add main engine if specified if mainEngineSetting != "" { allEngines = append(allEngines, mainEngineSetting) } - // Add included engines + // Add included engines — skip preference-only configs (objects with only 'model'/'mcp' + // keys and no 'id' or 'runtime'). These express a model or MCP preference without + // selecting an engine and must not be counted as engine specifications (avoids spurious + // "multiple engine fields" errors when a shared workflow only declares engine.model + // without engine.id). Objects with unknown keys or empty objects are not skipped + // and will continue through normal validation. for _, engineJSON := range includedEnginesJSON { - if engineJSON != "" { - allEngines = append(allEngines, engineJSON) + if engineJSON == "" { + continue + } + if isModelOnlyEngineJSON(engineJSON) { + continue + } + allEngines = append(allEngines, engineJSON) + if firstIncludedRealEngine == "" { + firstIncludedRealEngine = engineJSON } } - // Check count + // Check count (only counting real engine specifications) if len(allEngines) == 0 { - return "", nil // No engine specified anywhere, will use default + return "", nil // No engine specification found anywhere; will use default } if len(allEngines) > 1 { @@ -334,9 +380,9 @@ func (c *Compiler) validateSingleEngineSpecification(mainEngineSetting string, i return mainEngineSetting, nil } - // Must be from included file + // Must be from included file - parse the first real included engine specification var firstEngine any - if err := json.Unmarshal([]byte(includedEnginesJSON[0]), &firstEngine); err != nil { + if err := json.Unmarshal([]byte(firstIncludedRealEngine), &firstEngine); err != nil { return "", fmt.Errorf("failed to parse included engine configuration: %w. Expected string or object format.\n\nExample (string):\nengine: copilot\n\nExample (object):\nengine:\n id: copilot\n model: gpt-4\n\nSee: %s", err, constants.DocsEnginesURL) } diff --git a/pkg/workflow/engine_validation_test.go b/pkg/workflow/engine_validation_test.go index 13b10f146fb..a5a9f0eb326 100644 --- a/pkg/workflow/engine_validation_test.go +++ b/pkg/workflow/engine_validation_test.go @@ -87,10 +87,53 @@ func TestValidateSingleEngineSpecification(t *testing.T) { errorMsg: "failed to parse", }, { - name: "included engine with invalid object format (no id)", + // Model preference (no id) is valid — returns "" so the compiler uses the default + // engine. The model value flows through separately; see TestCompileWorkflowWithModelOnlyEngine. + name: "included engine with model-only (no id) is a preference, not a spec", mainEngineSetting: "", includedEnginesJSON: []string{`{"model": "gpt-4"}`}, expectedEngine: "", + expectError: false, + }, + { + name: "included engine with model size hint 'small' is allowed without id", + mainEngineSetting: "", + includedEnginesJSON: []string{`{"model": "small"}`}, + expectedEngine: "", + expectError: false, + }, + { + name: "model-only included engine does not conflict with main engine", + mainEngineSetting: "copilot", + includedEnginesJSON: []string{`{"model": "small"}`}, + expectedEngine: "copilot", + expectError: false, + }, + { + name: "model-only included engine does not conflict with real included engine", + mainEngineSetting: "", + includedEnginesJSON: []string{`{"id": "copilot"}`, `{"model": "small"}`}, + expectedEngine: "copilot", + expectError: false, + }, + { + // An empty object {} has no id/runtime but also no known preference keys; + // it must NOT be silently skipped — it should be treated as an engine spec + // and trigger a validation error (missing id field). + name: "empty object is not a preference-only engine and triggers error", + mainEngineSetting: "", + includedEnginesJSON: []string{`{}`}, + expectedEngine: "", + expectError: true, + errorMsg: "invalid engine configuration", + }, + { + // An object with an unknown key has no id/runtime but must NOT be silently + // skipped — it should pass through to normal validation. + name: "object with unknown key is not a preference-only engine and triggers error", + mainEngineSetting: "", + includedEnginesJSON: []string{`{"foo": 1}`}, + expectedEngine: "", expectError: true, errorMsg: "invalid engine configuration", }, @@ -187,10 +230,10 @@ func TestValidateSingleEngineSpecificationErrorMessageQuality(t *testing.T) { }) t.Run("invalid configuration error includes format examples", func(t *testing.T) { - _, err := compiler.validateSingleEngineSpecification("", []string{`{"model": "gpt-4"}`}) + _, err := compiler.validateSingleEngineSpecification("", []string{`{"id": 123}`}) if err == nil { - t.Fatal("Expected validation to fail for configuration without id") + t.Fatal("Expected validation to fail for configuration with non-string id") } errorMsg := err.Error() diff --git a/pkg/workflow/imports_test.go b/pkg/workflow/imports_test.go index a11e6684cd6..aa6d38311c0 100644 --- a/pkg/workflow/imports_test.go +++ b/pkg/workflow/imports_test.go @@ -246,3 +246,80 @@ This is a test workflow with imported MCP server. t.Error("Expected tavily to be configured as HTTP MCP server") } } + +// TestCompileWorkflowWithModelOnlyEngine verifies that a workflow declaring +// engine.model without engine.id compiles successfully. This allows workflow +// authors to express a model-size preference (e.g. "small") without committing +// to a specific engine, letting the runtime select the appropriate engine. +func TestCompileWorkflowWithModelOnlyEngine(t *testing.T) { + tempDir := testutil.TempDir(t, "test-*") + + workflowPath := filepath.Join(tempDir, "test-workflow.md") + workflowContent := `--- +on: issues +permissions: + contents: read + issues: read + pull-requests: read +engine: + model: small +--- + +# Test Workflow + +This workflow expresses a model-size preference without specifying an engine id. +` + if err := os.WriteFile(workflowPath, []byte(workflowContent), 0644); err != nil { + t.Fatalf("Failed to write workflow file: %v", err) + } + + compiler := workflow.NewCompiler() + if err := compiler.CompileWorkflow(workflowPath); err != nil { + t.Fatalf("CompileWorkflow failed for engine.model without engine.id: %v", err) + } +} + +// TestCompileWorkflowWithImportedModelOnlyEngine verifies that a workflow importing +// a shared file that declares engine.model (without engine.id) compiles successfully. +// This is the primary use case: gh aw add / gh aw add-wizard add shared workflows that +// only express a model preference, not a specific engine selection. +func TestCompileWorkflowWithImportedModelOnlyEngine(t *testing.T) { + tempDir := testutil.TempDir(t, "test-*") + + // Shared workflow that only declares a model preference (no engine.id) + sharedPath := filepath.Join(tempDir, "shared-workflow.md") + sharedContent := `--- +on: push +engine: + model: small +--- +` + if err := os.WriteFile(sharedPath, []byte(sharedContent), 0644); err != nil { + t.Fatalf("Failed to write shared workflow file: %v", err) + } + + workflowPath := filepath.Join(tempDir, "test-workflow.md") + workflowContent := `--- +on: issues +permissions: + contents: read + issues: read + pull-requests: read +engine: copilot +imports: + - shared-workflow.md +--- + +# Test Workflow + +This workflow imports a shared file that declares a model preference. +` + if err := os.WriteFile(workflowPath, []byte(workflowContent), 0644); err != nil { + t.Fatalf("Failed to write workflow file: %v", err) + } + + compiler := workflow.NewCompiler() + if err := compiler.CompileWorkflow(workflowPath); err != nil { + t.Fatalf("CompileWorkflow failed when imported shared workflow has engine.model without engine.id: %v", err) + } +} From 136a3fee26047182aa7e26343cfed3dc9e9ffa7f Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Fri, 8 May 2026 16:44:36 -0700 Subject: [PATCH 8/8] Respect frontmatter `redirect:` during `gh aw add` and `gh aw add-wizard` resolution (#31076) --- .../docs/reference/frontmatter-full.md | 6 +- .../src/content/docs/reference/frontmatter.md | 2 +- docs/src/content/docs/setup/cli.md | 4 +- pkg/cli/add_integration_test.go | 46 ++++++++ pkg/cli/add_workflow_resolution.go | 65 +++++++++- .../add_workflow_resolution_redirect_test.go | 111 ++++++++++++++++++ 6 files changed, 225 insertions(+), 9 deletions(-) create mode 100644 pkg/cli/add_workflow_resolution_redirect_test.go diff --git a/docs/src/content/docs/reference/frontmatter-full.md b/docs/src/content/docs/reference/frontmatter-full.md index 528759cafed..69a370b3d2c 100644 --- a/docs/src/content/docs/reference/frontmatter-full.md +++ b/docs/src/content/docs/reference/frontmatter-full.md @@ -34,10 +34,10 @@ description: "Description of the workflow" # (optional) source: "example-value" -# Optional workflow location redirect for updates. Format: workflow spec or GitHub +# Optional workflow location redirect for add/add-wizard/update. Format: workflow spec or GitHub # URL (e.g., owner/repo/path@ref or -# https://github.com/owner/repo/blob/main/path.md). When present, update follows -# this location and rewrites source. +# https://github.com/owner/repo/blob/main/path.md). When present, remote add/add-wizard/update +# follows this location and writes/rewrites source. # (optional) redirect: "example-value" diff --git a/docs/src/content/docs/reference/frontmatter.md b/docs/src/content/docs/reference/frontmatter.md index dc39c2e7332..ff2e52a35f4 100644 --- a/docs/src/content/docs/reference/frontmatter.md +++ b/docs/src/content/docs/reference/frontmatter.md @@ -64,7 +64,7 @@ source: "githubnext/agentics/workflows/ci-doctor.md@v1.0.0" ### Redirect (`redirect:`) -Specifies a new canonical location when a workflow has been moved or renamed. When `gh aw update` encounters a workflow with a `redirect` field, it follows the redirect chain to the resolved location, rewrites the local `source` field to point to the new location, and emits a warning for each redirect hop. Redirect loops are detected and reported as errors. +Specifies a new canonical location when a workflow has been moved or renamed. `gh aw add`, `gh aw add-wizard`, and `gh aw update` follow redirect chains to the resolved location for remote workflows. During add/update flows, the local `source` field is written (or rewritten) to the resolved location, and redirect loops are detected and reported as errors. ```yaml wrap redirect: "githubnext/agentics/workflows/new-workflow-name.md@main" diff --git a/docs/src/content/docs/setup/cli.md b/docs/src/content/docs/setup/cli.md index 0c2bdaab336..e590d510d21 100644 --- a/docs/src/content/docs/setup/cli.md +++ b/docs/src/content/docs/setup/cli.md @@ -146,7 +146,7 @@ gh aw init --create-pull-request # Initialize and open a pull request #### `add-wizard` -Add a workflow with interactive guided setup. Checks requirements, adds the markdown file, and generates the compiled YAML. Prompts for missing API keys and secrets. +Add a workflow with interactive guided setup. Checks requirements, adds the markdown file, and generates the compiled YAML. Prompts for missing API keys and secrets. For remote workflows, this command follows frontmatter [`redirect`](/gh-aw/reference/frontmatter/#redirect-redirect) declarations before installation. ```bash wrap gh aw add-wizard githubnext/agentics/ci-doctor # Interactive setup @@ -158,7 +158,7 @@ gh aw add-wizard githubnext/agentics/ci-doctor --skip-secret # Skip secret prom #### `add` -Add workflows from The Agentics collection or other repositories to `.github/workflows`. +Add workflows from The Agentics collection or other repositories to `.github/workflows`. For remote workflows, this command follows frontmatter [`redirect`](/gh-aw/reference/frontmatter/#redirect-redirect) declarations before installation. ```bash wrap gh aw add githubnext/agentics/ci-doctor # Add single workflow diff --git a/pkg/cli/add_integration_test.go b/pkg/cli/add_integration_test.go index 00bac20a28a..ea003f2223e 100644 --- a/pkg/cli/add_integration_test.go +++ b/pkg/cli/add_integration_test.go @@ -930,6 +930,52 @@ func TestAddPublicWorkflowUnauthenticated(t *testing.T) { require.NoError(t, err, "downloaded workflow file should exist at %s", workflowFile) } +// TestAddRemoteWorkflowRedirect verifies that gh aw add follows frontmatter +// redirects for remote workflows and writes source metadata for the redirected +// upstream location. +func TestAddRemoteWorkflowRedirect(t *testing.T) { + setup := setupAddIntegrationTest(t) + defer setup.cleanup() + + // Exclude all GitHub auth tokens so this test runs in the same unauthenticated + // environment expected in agentic workflow execution. + var filteredEnv []string + for _, e := range os.Environ() { + switch { + case strings.HasPrefix(e, "GITHUB_TOKEN="), + strings.HasPrefix(e, "GH_TOKEN="), + strings.HasPrefix(e, "GITHUB_ENTERPRISE_TOKEN="), + strings.HasPrefix(e, "GH_ENTERPRISE_TOKEN="): + // Exclude token + default: + filteredEnv = append(filteredEnv, e) + } + } + + // This workflow in github/gh-aw contains redirect frontmatter pointing to + // microsoft/apm/.github/workflows/shared/apm.md. + workflowSpec := "github/gh-aw/.github/workflows/shared/apm.md@main" + + cmd := exec.Command(setup.binaryPath, "add", workflowSpec, "--verbose") + cmd.Dir = setup.tempDir + cmd.Env = filteredEnv + output, err := cmd.CombinedOutput() + outputStr := string(output) + + t.Logf("Command output:\n%s", outputStr) + + require.NoError(t, err, "gh aw add should succeed for redirected public workflow: %s", outputStr) + assert.Contains(t, outputStr, "Workflow redirect:", "verbose output should indicate redirect resolution") + + workflowFile := filepath.Join(setup.tempDir, ".github", "workflows", "apm.md") + content, err := os.ReadFile(workflowFile) + require.NoError(t, err, "redirect target workflow should be written") + contentStr := string(content) + + assert.Contains(t, contentStr, "source: microsoft/apm/.github/workflows/shared/apm.md@", "source should be pinned to redirected upstream workflow") + assert.NotContains(t, contentStr, "source: github/gh-aw/.github/workflows/shared/apm.md@", "source should not remain pinned to pre-redirect location") +} + // TestAddWorkflowWithDispatchWorkflowDependency tests that when a remote workflow is added // that references dispatch-workflow dependencies, those dependency workflows are automatically // fetched alongside the main workflow. diff --git a/pkg/cli/add_workflow_resolution.go b/pkg/cli/add_workflow_resolution.go index 21a21e5e364..8de03841823 100644 --- a/pkg/cli/add_workflow_resolution.go +++ b/pkg/cli/add_workflow_resolution.go @@ -15,6 +15,7 @@ import ( ) var resolutionLog = logger.New("cli:add_workflow_resolution") +var fetchWorkflowFromSourceWithContextFn = FetchWorkflowFromSourceWithContext // ResolvedWorkflow contains metadata about a workflow that has been resolved and is ready to add type ResolvedWorkflow struct { @@ -117,8 +118,8 @@ func ResolveWorkflows(ctx context.Context, workflows []string, verbose bool) (*R hasWorkflowDispatch := false for _, spec := range parsedSpecs { - // Fetch workflow content - FetchWorkflowFromSource handles both local and remote - fetched, err := FetchWorkflowFromSourceWithContext(ctx, spec, verbose) + // Fetch workflow content (including redirect resolution for remote workflows) + resolvedSpec, fetched, err := resolveAddWorkflowSpecAndContent(ctx, spec, verbose) if err != nil { return nil, fmt.Errorf("workflow '%s' not found: %w", spec.String(), err) } @@ -145,7 +146,7 @@ func ResolveWorkflows(ctx context.Context, workflows []string, verbose bool) (*R spec.String(), engine, workflowHasDispatch, len(fetched.Content)) resolvedWorkflows = append(resolvedWorkflows, &ResolvedWorkflow{ - Spec: spec, + Spec: resolvedSpec, Content: fetched.Content, SourceInfo: fetched, Description: description, @@ -165,6 +166,64 @@ func ResolveWorkflows(ctx context.Context, workflows []string, verbose bool) (*R }, nil } +func resolveAddWorkflowSpecAndContent(ctx context.Context, initialSpec *WorkflowSpec, verbose bool) (*WorkflowSpec, *FetchedWorkflow, error) { + currentSpec := *initialSpec + visited := make(map[string]struct{}) + + for range maxRedirectDepth { + // Fetch workflow content - handles both local and remote. + fetched, err := fetchWorkflowFromSourceWithContextFn(ctx, ¤tSpec, verbose) + if err != nil { + return nil, nil, err + } + + // Redirects only apply to remote workflows. + if fetched.IsLocal { + return ¤tSpec, fetched, nil + } + + currentRef := currentSpec.Version + if currentRef == "" { + currentRef = "main" + } + locationKey := fmt.Sprintf("%s/%s@%s", currentSpec.RepoSlug, currentSpec.WorkflowPath, currentRef) + if _, exists := visited[locationKey]; exists { + return nil, nil, fmt.Errorf("redirect loop detected at %s", locationKey) + } + visited[locationKey] = struct{}{} + + redirect, err := extractRedirectFromContent(string(fetched.Content)) + if err != nil { + return nil, nil, err + } + if redirect == "" { + return ¤tSpec, fetched, nil + } + + redirectedSource, err := normalizeRedirectToSourceSpec(redirect) + if err != nil { + return nil, nil, fmt.Errorf("invalid redirect %q in %s: %w", redirect, locationKey, err) + } + + nextSpec := &WorkflowSpec{ + RepoSpec: RepoSpec{ + RepoSlug: redirectedSource.Repo, + Version: redirectedSource.Ref, + }, + WorkflowPath: redirectedSource.Path, + WorkflowName: normalizeWorkflowID(redirectedSource.Path), + Host: currentSpec.Host, + } + resolutionLog.Printf("Following redirect for add: from=%s to=%s", locationKey, nextSpec.String()) + if verbose { + fmt.Fprintln(os.Stderr, console.FormatWarningMessage(fmt.Sprintf("Workflow redirect: %s -> %s", locationKey, nextSpec.String()))) + } + currentSpec = *nextSpec + } + + return nil, nil, fmt.Errorf("redirect chain exceeded maximum depth (%d) for workflow '%s'", maxRedirectDepth, initialSpec.String()) +} + // expandLocalWildcardWorkflows expands wildcard workflow specifications for local workflows only. func expandLocalWildcardWorkflows(specs []*WorkflowSpec, verbose bool) ([]*WorkflowSpec, error) { expandedWorkflows := []*WorkflowSpec{} diff --git a/pkg/cli/add_workflow_resolution_redirect_test.go b/pkg/cli/add_workflow_resolution_redirect_test.go new file mode 100644 index 00000000000..08bb37e7f80 --- /dev/null +++ b/pkg/cli/add_workflow_resolution_redirect_test.go @@ -0,0 +1,111 @@ +//go:build !integration + +package cli + +import ( + "context" + "fmt" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestResolveAddWorkflowSpecAndContent(t *testing.T) { + originalFetchFn := fetchWorkflowFromSourceWithContextFn + t.Cleanup(func() { + fetchWorkflowFromSourceWithContextFn = originalFetchFn + }) + + t.Run("follows redirect chain for remote workflows", func(t *testing.T) { + fetchWorkflowFromSourceWithContextFn = func(_ context.Context, spec *WorkflowSpec, _ bool) (*FetchedWorkflow, error) { + switch spec.String() { + case "owner/repo/workflows/original.md@main": + return &FetchedWorkflow{ + Content: []byte("---\nredirect: owner/repo/workflows/new.md@main\n---\n"), + IsLocal: false, + SourcePath: "workflows/original.md", + }, nil + case "owner/repo/workflows/new.md@main": + return &FetchedWorkflow{ + Content: []byte("---\nname: New Workflow\n---\n"), + IsLocal: false, + SourcePath: "workflows/new.md", + }, nil + default: + return nil, fmt.Errorf("unexpected fetch spec %s", spec.String()) + } + } + + resolvedSpec, fetched, err := resolveAddWorkflowSpecAndContent(context.Background(), &WorkflowSpec{ + RepoSpec: RepoSpec{ + RepoSlug: "owner/repo", + Version: "main", + }, + WorkflowPath: "workflows/original.md", + WorkflowName: "original", + }, false) + require.NoError(t, err, "redirect chain should resolve") + require.NotNil(t, fetched, "resolved fetch should be returned") + assert.Equal(t, "owner/repo", resolvedSpec.RepoSlug, "final repo should be redirected repo") + assert.Equal(t, "workflows/new.md", resolvedSpec.WorkflowPath, "final path should be redirected path") + assert.Equal(t, "new", resolvedSpec.WorkflowName, "workflow name should match redirected workflow") + }) + + t.Run("detects redirect loops", func(t *testing.T) { + fetchWorkflowFromSourceWithContextFn = func(_ context.Context, spec *WorkflowSpec, _ bool) (*FetchedWorkflow, error) { + switch spec.String() { + case "owner/repo/workflows/a.md@main": + return &FetchedWorkflow{Content: []byte("---\nredirect: owner/repo/workflows/b.md@main\n---\n"), IsLocal: false, SourcePath: "workflows/a.md"}, nil + case "owner/repo/workflows/b.md@main": + return &FetchedWorkflow{Content: []byte("---\nredirect: owner/repo/workflows/a.md@main\n---\n"), IsLocal: false, SourcePath: "workflows/b.md"}, nil + default: + return nil, fmt.Errorf("unexpected fetch spec %s", spec.String()) + } + } + + _, _, err := resolveAddWorkflowSpecAndContent(context.Background(), &WorkflowSpec{ + RepoSpec: RepoSpec{RepoSlug: "owner/repo", Version: "main"}, + WorkflowPath: "workflows/a.md", + WorkflowName: "a", + }, false) + require.Error(t, err, "redirect loop should fail") + assert.Contains(t, err.Error(), "redirect loop detected", "error should mention loop detection") + }) + + t.Run("local workflows are not redirected", func(t *testing.T) { + fetchWorkflowFromSourceWithContextFn = func(_ context.Context, _ *WorkflowSpec, _ bool) (*FetchedWorkflow, error) { + return &FetchedWorkflow{ + Content: []byte("---\nredirect: owner/repo/workflows/new.md@main\n---\n"), + IsLocal: true, + SourcePath: "./local.md", + }, nil + } + + resolvedSpec, _, err := resolveAddWorkflowSpecAndContent(context.Background(), &WorkflowSpec{ + WorkflowPath: "./local.md", + WorkflowName: "local", + }, false) + require.NoError(t, err, "local workflow resolution should succeed") + assert.Equal(t, "./local.md", resolvedSpec.WorkflowPath, "local workflow path should be preserved") + }) + + t.Run("ResolveWorkflows uses redirected spec", func(t *testing.T) { + fetchWorkflowFromSourceWithContextFn = func(_ context.Context, spec *WorkflowSpec, _ bool) (*FetchedWorkflow, error) { + switch spec.String() { + case "owner/repo/workflows/original.md@main": + return &FetchedWorkflow{Content: []byte("---\nredirect: owner/repo/workflows/new.md@main\n---\n"), IsLocal: false}, nil + case "owner/repo/workflows/new.md@main": + return &FetchedWorkflow{Content: []byte("---\nname: New Workflow\non: push\n---\n"), IsLocal: false}, nil + default: + return nil, fmt.Errorf("unexpected fetch spec %s", spec.String()) + } + } + + resolved, err := ResolveWorkflows(context.Background(), []string{"owner/repo/workflows/original.md@main"}, false) + require.NoError(t, err, "ResolveWorkflows should follow redirects") + require.Len(t, resolved.Workflows, 1, "one workflow should resolve") + assert.Equal(t, "workflows/new.md", resolved.Workflows[0].Spec.WorkflowPath, "resolved spec should point to redirect destination") + assert.Equal(t, "new", resolved.Workflows[0].Spec.WorkflowName, "resolved workflow name should follow redirect destination") + }) +}