From 2696dc4f3b70c7eb99ebeb4088bad34bc8ca7ef4 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sun, 31 May 2026 13:15:03 +0000
Subject: [PATCH 1/3] Initial plan
From 01af3646b3a141c7bbaf1edf2f2fac6e9eca23b9 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sun, 31 May 2026 13:19:43 +0000
Subject: [PATCH 2/3] chore: optimize export-audit token budget
---
.github/workflows/export-audit.lock.yml | 375 ++++++++++++++++-------
.github/workflows/export-audit.md | 49 ++-
scripts/ci/export-audit-workflow.test.ts | 33 ++
3 files changed, 334 insertions(+), 123 deletions(-)
create mode 100644 scripts/ci/export-audit-workflow.test.ts
diff --git a/.github/workflows/export-audit.lock.yml b/.github/workflows/export-audit.lock.yml
index 54aa84171..1336235e0 100644
--- a/.github/workflows/export-audit.lock.yml
+++ b/.github/workflows/export-audit.lock.yml
@@ -1,5 +1,5 @@
-# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"8aefa3ac7dcee3d54723b8155afc998c881dd970dfb07122e258d13fd6c7a4ef","compiler_version":"v0.76.1","strict":true,"agent_id":"copilot"}
-# gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","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"},{"repo":"github/gh-aw-actions/setup","sha":"46d564922b082d0db93244972e8005ea6904ee5f","version":"v0.76.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.55"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.55"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.55"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.19"},{"image":"ghcr.io/github/github-mcp-server:v1.0.4","digest":"sha256:e3816a476a977cfb836e7d221510011436c654d11861db66ecfd826601aba6a4","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.4@sha256:e3816a476a977cfb836e7d221510011436c654d11861db66ecfd826601aba6a4"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]}
+# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"8e8de5a131f42f2c3bbf62fef1f1a8ffc769fa58ac53eea7ee484de17fc6e6f3","compiler_version":"v0.76.1","strict":true,"agent_id":"claude"}
+# gh-aw-manifest: {"version":1,"secrets":["ANTHROPIC_API_KEY","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","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"},{"repo":"github/gh-aw-actions/setup","sha":"46d564922b082d0db93244972e8005ea6904ee5f","version":"v0.76.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.55"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.55"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.55"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.19"},{"image":"ghcr.io/github/github-mcp-server:v1.0.4","digest":"sha256:e3816a476a977cfb836e7d221510011436c654d11861db66ecfd826601aba6a4","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.4@sha256:e3816a476a977cfb836e7d221510011436c654d11861db66ecfd826601aba6a4"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]}
# ___ _ _
# / _ \ | | (_)
# | |_| | __ _ ___ _ __ | |_ _ ___
@@ -28,7 +28,7 @@
# to keep the API surface clean and prevent dead-code accumulation.
#
# Secrets used:
-# - COPILOT_GITHUB_TOKEN
+# - ANTHROPIC_API_KEY
# - GH_AW_GITHUB_MCP_SERVER_TOKEN
# - GH_AW_GITHUB_TOKEN
# - GITHUB_TOKEN
@@ -101,17 +101,17 @@ jobs:
env:
GH_AW_SETUP_WORKFLOW_NAME: "API Surface & Export Audit"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/export-audit.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.52"
+ GH_AW_INFO_VERSION: "2.1.150"
GH_AW_INFO_AWF_VERSION: "v0.25.55"
- GH_AW_INFO_ENGINE_ID: "copilot"
+ GH_AW_INFO_ENGINE_ID: "claude"
- name: Generate agentic run info
id: generate_aw_info
env:
- GH_AW_INFO_ENGINE_ID: "copilot"
- GH_AW_INFO_ENGINE_NAME: "GitHub Copilot CLI"
- GH_AW_INFO_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || 'claude-sonnet-4.6' }}
- GH_AW_INFO_VERSION: "1.0.52"
- GH_AW_INFO_AGENT_VERSION: "1.0.52"
+ GH_AW_INFO_ENGINE_ID: "claude"
+ GH_AW_INFO_ENGINE_NAME: "Claude Code"
+ GH_AW_INFO_MODEL: ${{ vars.GH_AW_MODEL_AGENT_CLAUDE || 'agent' }}
+ GH_AW_INFO_VERSION: "2.1.150"
+ GH_AW_INFO_AGENT_VERSION: "2.1.150"
GH_AW_INFO_CLI_VERSION: "v0.76.1"
GH_AW_INFO_WORKFLOW_NAME: "API Surface & Export Audit"
GH_AW_INFO_EXPERIMENTAL: "false"
@@ -130,11 +130,11 @@ jobs:
setupGlobals(core, github, context, exec, io, getOctokit);
const { main } = require('${{ runner.temp }}/gh-aw/actions/generate_aw_info.cjs');
await main(core, context);
- - name: Validate COPILOT_GITHUB_TOKEN secret
+ - name: Validate ANTHROPIC_API_KEY secret
id: validate-secret
- run: bash "${RUNNER_TEMP}/gh-aw/actions/validate_multi_secret.sh" COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://github.github.com/gh-aw/reference/engines/#github-copilot-default
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/validate_multi_secret.sh" ANTHROPIC_API_KEY 'Claude Code' https://github.github.com/gh-aw/reference/engines/#anthropic-claude-code
env:
- COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
+ ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
- name: Checkout .github and .agents folders
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
@@ -198,24 +198,25 @@ jobs:
GH_AW_STEPS_NAMING_AUDIT_OUTPUTS_NAMING_ISSUES: ${{ steps.naming_audit.outputs.NAMING_ISSUES }}
GH_AW_STEPS_TEST_IMPORTS_OUTPUTS_TEST_IMPORTS: ${{ steps.test_imports.outputs.TEST_IMPORTS }}
GH_AW_STEPS_UNUSED_EXPORTS_OUTPUTS_UNUSED_EXPORTS: ${{ steps.unused_exports.outputs.UNUSED_EXPORTS }}
+ GH_AW_STEPS_VERIFIED_UNUSED_OUTPUTS_VERIFIED_UNUSED: ${{ steps.verified_unused.outputs.VERIFIED_UNUSED }}
# poutine:ignore untrusted_checkout_exec
run: |
bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh"
{
- cat << 'GH_AW_PROMPT_867465bd313589e9_EOF'
+ cat << 'GH_AW_PROMPT_9918201839a3620e_EOF'
- GH_AW_PROMPT_867465bd313589e9_EOF
+ GH_AW_PROMPT_9918201839a3620e_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_867465bd313589e9_EOF'
+ cat << 'GH_AW_PROMPT_9918201839a3620e_EOF'
Tools: create_issue(max:5), missing_tool, missing_data, noop
- GH_AW_PROMPT_867465bd313589e9_EOF
+ GH_AW_PROMPT_9918201839a3620e_EOF
cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md"
- cat << 'GH_AW_PROMPT_867465bd313589e9_EOF'
+ cat << 'GH_AW_PROMPT_9918201839a3620e_EOF'
The following GitHub context information is available for this workflow:
{{#if github.actor}}
@@ -244,18 +245,18 @@ jobs:
{{/if}}
- GH_AW_PROMPT_867465bd313589e9_EOF
+ GH_AW_PROMPT_9918201839a3620e_EOF
cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md"
- cat << 'GH_AW_PROMPT_867465bd313589e9_EOF'
+ cat << 'GH_AW_PROMPT_9918201839a3620e_EOF'
{{#runtime-import .github/workflows/export-audit.md}}
- GH_AW_PROMPT_867465bd313589e9_EOF
+ GH_AW_PROMPT_9918201839a3620e_EOF
} > "$GH_AW_PROMPT"
- name: Interpolate variables and render templates
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
- GH_AW_ENGINE_ID: "copilot"
+ GH_AW_ENGINE_ID: "claude"
GH_AW_GITHUB_REPOSITORY: ${{ github.repository }}
GH_AW_STEPS_APIP_EXPORTS_OUTPUTS_APIP_EXPORTS: ${{ steps.apip_exports.outputs.APIP_EXPORTS }}
GH_AW_STEPS_CIRCULAR_DEPS_OUTPUTS_CIRCULAR_DEPS: ${{ steps.circular_deps.outputs.CIRCULAR_DEPS }}
@@ -264,6 +265,7 @@ jobs:
GH_AW_STEPS_TEST_IMPORTS_OUTPUTS_TEST_IMPORTS: ${{ steps.test_imports.outputs.TEST_IMPORTS }}
GH_AW_EXPR_A04AFDAF: ${{ steps.ts-errors.outputs.TS_ERRORS }}
GH_AW_STEPS_UNUSED_EXPORTS_OUTPUTS_UNUSED_EXPORTS: ${{ steps.unused_exports.outputs.UNUSED_EXPORTS }}
+ GH_AW_STEPS_VERIFIED_UNUSED_OUTPUTS_VERIFIED_UNUSED: ${{ steps.verified_unused.outputs.VERIFIED_UNUSED }}
with:
script: |
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
@@ -291,6 +293,7 @@ jobs:
GH_AW_STEPS_NAMING_AUDIT_OUTPUTS_NAMING_ISSUES: ${{ steps.naming_audit.outputs.NAMING_ISSUES }}
GH_AW_STEPS_TEST_IMPORTS_OUTPUTS_TEST_IMPORTS: ${{ steps.test_imports.outputs.TEST_IMPORTS }}
GH_AW_STEPS_UNUSED_EXPORTS_OUTPUTS_UNUSED_EXPORTS: ${{ steps.unused_exports.outputs.UNUSED_EXPORTS }}
+ GH_AW_STEPS_VERIFIED_UNUSED_OUTPUTS_VERIFIED_UNUSED: ${{ steps.verified_unused.outputs.VERIFIED_UNUSED }}
with:
script: |
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
@@ -318,7 +321,8 @@ jobs:
GH_AW_STEPS_EXPORTS_OUTPUTS_EXPORTS: process.env.GH_AW_STEPS_EXPORTS_OUTPUTS_EXPORTS,
GH_AW_STEPS_NAMING_AUDIT_OUTPUTS_NAMING_ISSUES: process.env.GH_AW_STEPS_NAMING_AUDIT_OUTPUTS_NAMING_ISSUES,
GH_AW_STEPS_TEST_IMPORTS_OUTPUTS_TEST_IMPORTS: process.env.GH_AW_STEPS_TEST_IMPORTS_OUTPUTS_TEST_IMPORTS,
- GH_AW_STEPS_UNUSED_EXPORTS_OUTPUTS_UNUSED_EXPORTS: process.env.GH_AW_STEPS_UNUSED_EXPORTS_OUTPUTS_UNUSED_EXPORTS
+ GH_AW_STEPS_UNUSED_EXPORTS_OUTPUTS_UNUSED_EXPORTS: process.env.GH_AW_STEPS_UNUSED_EXPORTS_OUTPUTS_UNUSED_EXPORTS,
+ GH_AW_STEPS_VERIFIED_UNUSED_OUTPUTS_VERIFIED_UNUSED: process.env.GH_AW_STEPS_VERIFIED_UNUSED_OUTPUTS_VERIFIED_UNUSED
}
});
- name: Validate prompt placeholders
@@ -344,8 +348,8 @@ jobs:
/tmp/gh-aw/aw-prompts/prompt-import-tree.json
/tmp/gh-aw/github_rate_limits.jsonl
/tmp/gh-aw/base
- /tmp/gh-aw/.github/agents
- /tmp/gh-aw/.github/skills
+ /tmp/gh-aw/.claude/agents
+ /tmp/gh-aw/.claude/skills
if-no-files-found: ignore
retention-days: 1
@@ -363,15 +367,11 @@ jobs:
GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs
GH_AW_WORKFLOW_ID_SANITIZED: exportaudit
outputs:
- agentic_engine_timeout: ${{ steps.detect-agent-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' }}
has_patch: ${{ steps.collect_output.outputs.has_patch }}
- inference_access_error: ${{ steps.detect-agent-errors.outputs.inference_access_error || 'false' }}
- mcp_policy_error: ${{ steps.detect-agent-errors.outputs.mcp_policy_error || 'false' }}
model: ${{ needs.activation.outputs.model }}
- model_not_supported_error: ${{ steps.detect-agent-errors.outputs.model_not_supported_error || 'false' }}
output: ${{ steps.collect_output.outputs.output }}
output_types: ${{ steps.collect_output.outputs.output_types }}
setup-parent-span-id: ${{ steps.setup.outputs.parent-span-id || steps.setup.outputs.span-id }}
@@ -389,9 +389,9 @@ jobs:
env:
GH_AW_SETUP_WORKFLOW_NAME: "API Surface & Export Audit"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/export-audit.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.52"
+ GH_AW_INFO_VERSION: "2.1.150"
GH_AW_INFO_AWF_VERSION: "v0.25.55"
- GH_AW_INFO_ENGINE_ID: "copilot"
+ GH_AW_INFO_ENGINE_ID: "claude"
- name: Set runtime paths
id: set-runtime-paths
run: |
@@ -422,25 +422,129 @@ jobs:
run: set -o pipefail && npm run build 2>&1 | tail -10
- id: exports
name: Collect export inventory
- run: "{\n echo \"EXPORTS<> \"$GITHUB_OUTPUT\"\n"
+ run: |
+ {
+ echo "EXPORTS<> "$GITHUB_OUTPUT"
- id: ts-errors
name: Check for TypeScript compiler errors
- run: "{\n echo \"TS_ERRORS<&1 | head -40 || true\n echo \"EOF\"\n} >> \"$GITHUB_OUTPUT\"\n"
+ run: |
+ {
+ echo "TS_ERRORS<&1 | head -40 || true
+ echo "EOF"
+ } >> "$GITHUB_OUTPUT"
- id: unused_exports
name: Detect unused exports (ts-prune)
- run: "{\n echo \"UNUSED_EXPORTS<&1 | tail -5\n if command -v ts-prune >/dev/null 2>&1; then\n ts-prune | grep -v \"\\.test\\.ts\" | head -40\n else\n echo \"ts-prune unavailable, falling back to grep analysis\"\n grep -rn \"^export \" src/ --include=\"*.ts\" | grep -v \"\\.test\\.ts\" | \\\n while IFS=: read -r file line rest; do\n name=$(echo \"$rest\" | sed -n 's/.*export \\(function\\|class\\|const\\|type\\|interface\\|enum\\) \\([a-zA-Z_][a-zA-Z0-9_]*\\).*/\\2/p')\n [ -z \"$name\" ] && continue\n count=$(grep -rwn \"${name}\" src/ --include=\"*.ts\" 2>/dev/null | grep -v \"^${file}:\" | wc -l)\n [ \"$count\" -eq 0 ] && echo \"UNUSED: $name ($file:$line)\"\n done | head -30\n fi\n echo \"EOF\"\n} >> \"$GITHUB_OUTPUT\"\n"
+ run: |
+ {
+ echo "UNUSED_EXPORTS<&1 | tail -5
+ if command -v ts-prune >/dev/null 2>&1; then
+ ts-prune | grep -v "\.test\.ts" | head -40
+ else
+ echo "ts-prune unavailable, falling back to grep analysis"
+ grep -rn "^export " src/ --include="*.ts" | grep -v "\.test\.ts" | \
+ while IFS=: read -r file line rest; do
+ name=$(echo "$rest" | sed -n 's/.*export \(function\|class\|const\|type\|interface\|enum\) \([a-zA-Z_][a-zA-Z0-9_]*\).*/\2/p')
+ [ -z "$name" ] && continue
+ count=$(grep -rwn "${name}" src/ --include="*.ts" 2>/dev/null | grep -v "^${file}:" | wc -l)
+ [ "$count" -eq 0 ] && echo "UNUSED: $name ($file:$line)"
+ done | head -30
+ fi
+ echo "EOF"
+ } >> "$GITHUB_OUTPUT"
+ - env:
+ GH_AW_STEPS_UNUSED_EXPORTS_OUTPUTS_UNUSED_EXPORTS: ${{ steps.unused_exports.outputs.UNUSED_EXPORTS }}
+ id: verified_unused
+ name: Pre-verify unused exports (top 10)
+ run: |
+ {
+ echo "VERIFIED_UNUSED</dev/null | \
+ grep -v "\.test\.ts" | wc -l)
+ echo "${sym}: used_in=${count}_files"
+ done
+ fi
+ echo "EOF"
+ } >> "$GITHUB_OUTPUT"
- id: circular_deps
name: Detect circular dependencies (madge)
- run: "{\n echo \"CIRCULAR_DEPS<&1 | tail -5\n if command -v madge >/dev/null 2>&1; then\n madge --circular src/ 2>&1 | head -20\n else\n echo \"madge unavailable, cannot check circular deps\"\n fi\n echo \"EOF\"\n} >> \"$GITHUB_OUTPUT\"\n"
+ run: |
+ {
+ echo "CIRCULAR_DEPS<&1 | tail -5
+ if command -v madge >/dev/null 2>&1; then
+ madge --circular src/ 2>&1 | head -20
+ else
+ echo "madge unavailable, cannot check circular deps"
+ fi
+ echo "EOF"
+ } >> "$GITHUB_OUTPUT"
- id: naming_audit
name: Naming convention audit
- run: "{\n echo \"NAMING_ISSUES<> \"$GITHUB_OUTPUT\"\n"
+ run: |
+ {
+ echo "NAMING_ISSUES<> "$GITHUB_OUTPUT"
- id: test_imports
name: Audit test file imports
- run: "{\n echo \"TEST_IMPORTS</dev/null | head -5\n done\n echo \"=== Check for tests importing from dist/ ===\"\n grep -rn \"from '.*dist/\\|require('.*dist/\" src/ --include=\"*.test.ts\" | head -10\n echo \"=== Check for tests reaching into private implementation ===\"\n grep -rn \"from '\\.\\.\\/\\.\\.\\/\" src/ --include=\"*.test.ts\" | head -10\n echo \"EOF\"\n} >> \"$GITHUB_OUTPUT\"\n"
+ run: |
+ {
+ echo "TEST_IMPORTS</dev/null | head -5
+ done
+ echo "=== Check for tests importing from dist/ ==="
+ grep -rn "from '.*dist/\|require('.*dist/" src/ --include="*.test.ts" | head -10
+ echo "=== Check for tests reaching into private implementation ==="
+ grep -rn "from '\.\.\/\.\.\/" src/ --include="*.test.ts" | head -10
+ echo "EOF"
+ } >> "$GITHUB_OUTPUT"
- id: apip_exports
name: Audit api-proxy module exports
- run: "{\n echo \"APIP_EXPORTS</dev/null | grep -n \"require\\|createAdapter\\|register\" | head -20\n echo \"=== server.js: imports from providers ===\"\n grep -n \"require.*providers\\|from.*providers\" containers/api-proxy/server.js 2>/dev/null | head -10\n echo \"EOF\"\n} >> \"$GITHUB_OUTPUT\"\n"
+ run: |
+ {
+ echo "APIP_EXPORTS</dev/null | grep -n "require\|createAdapter\|register" | head -20
+ echo "=== server.js: imports from providers ==="
+ grep -n "require.*providers\|from.*providers" containers/api-proxy/server.js 2>/dev/null | head -10
+ echo "EOF"
+ } >> "$GITHUB_OUTPUT"
- name: Configure Git credentials
env:
@@ -469,12 +573,15 @@ jobs:
setupGlobals(core, github, context, exec, io, getOctokit);
const { main } = require('${{ runner.temp }}/gh-aw/actions/checkout_pr_branch.cjs');
await main();
- - name: Install GitHub Copilot CLI
- run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.52
- env:
- GH_HOST: github.com
+ - name: Setup Node.js
+ uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
+ with:
+ node-version: '24'
+ package-manager-cache: false
- name: Install AWF binary
run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.25.55
+ - name: Install Claude Code CLI
+ run: npm install -g @anthropic-ai/claude-code@2.1.150
- name: Determine automatic lockdown mode for GitHub MCP Server
id: determine-automatic-lockdown
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 (source v9)
@@ -498,12 +605,12 @@ jobs:
run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_base_github_folders.sh"
- name: Restore inline sub-agents from activation artifact
env:
- GH_AW_SUB_AGENT_DIR: ".github/agents"
- GH_AW_SUB_AGENT_EXT: ".agent.md"
+ GH_AW_SUB_AGENT_DIR: ".claude/agents"
+ GH_AW_SUB_AGENT_EXT: ".md"
run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_inline_sub_agents.sh"
- name: Restore inline skills from activation artifact
env:
- GH_AW_SKILL_DIR: ".github/skills"
+ GH_AW_SKILL_DIR: ".claude/skills"
run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_inline_skills.sh"
- name: Download container images
run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.25.55 ghcr.io/github/gh-aw-firewall/api-proxy:0.25.55 ghcr.io/github/gh-aw-firewall/squid:0.25.55 ghcr.io/github/gh-aw-mcpg:v0.3.19 ghcr.io/github/github-mcp-server:v1.0.4@sha256:e3816a476a977cfb836e7d221510011436c654d11861db66ecfd826601aba6a4 node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f
@@ -512,9 +619,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_d9d66562d2801fb9_EOF'
+ cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_a58ea953901a5d88_EOF'
{"create_issue":{"expires":720,"labels":["code-quality"],"max":5,"title_prefix":"[Export Audit] "},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}}
- GH_AW_SAFE_OUTPUTS_CONFIG_d9d66562d2801fb9_EOF
+ GH_AW_SAFE_OUTPUTS_CONFIG_a58ea953901a5d88_EOF
- name: Generate Safe Outputs Tools
env:
GH_AW_TOOLS_META_JSON: |
@@ -709,7 +816,7 @@ jobs:
export MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD="524288"
export DEBUG="*"
- export GH_AW_ENGINE="copilot"
+ export GH_AW_ENGINE="claude"
MCP_GATEWAY_UID=$(id -u 2>/dev/null || echo '0')
MCP_GATEWAY_GID=$(id -g 2>/dev/null || echo '0')
case "${DOCKER_HOST:-}" in
@@ -720,17 +827,15 @@ jobs:
DOCKER_SOCK_GID=$(stat -c '%g' "$DOCKER_SOCK_PATH" 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 '"${DOCKER_SOCK_PATH}"':/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DOCKER_HOST=unix:///var/run/docker.sock -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_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 -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.19'
- 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_ee75605cd3eea274_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs"
+ cat << GH_AW_MCP_CONFIG_4d2b998142875e8a_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs"
{
"mcpServers": {
"github": {
- "type": "stdio",
"container": "ghcr.io/github/github-mcp-server:v1.0.4",
"env": {
- "GITHUB_HOST": "\${GITHUB_SERVER_URL}",
- "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}",
+ "GITHUB_HOST": "$GITHUB_SERVER_URL",
+ "GITHUB_PERSONAL_ACCESS_TOKEN": "$GITHUB_MCP_SERVER_TOKEN",
"GITHUB_READ_ONLY": "1",
"GITHUB_TOOLSETS": "issues"
},
@@ -745,7 +850,7 @@ jobs:
"type": "http",
"url": "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT",
"headers": {
- "Authorization": "\${GH_AW_SAFE_OUTPUTS_API_KEY}"
+ "Authorization": "$GH_AW_SAFE_OUTPUTS_API_KEY"
},
"guard-policies": {
"write-sink": {
@@ -763,7 +868,7 @@ jobs:
"payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}"
}
}
- GH_AW_MCP_CONFIG_ee75605cd3eea274_EOF
+ GH_AW_MCP_CONFIG_4d2b998142875e8a_EOF
- name: Mount MCP servers as CLIs
id: mount-mcp-clis
continue-on-error: true
@@ -785,57 +890,124 @@ jobs:
id: pre_agent_audit
continue-on-error: true
run: bash "${RUNNER_TEMP}/gh-aw/actions/audit_pre_agent_workspace.sh"
- - name: Execute GitHub Copilot CLI
+ - name: Execute Claude Code CLI
id: agentic_execution
- # Copilot CLI tool arguments (sorted):
+ # Allowed tools (sorted):
+ # - Bash
+ # - BashOutput
+ # - Edit
+ # - Edit(/tmp/*)
+ # - Edit(/tmp/gh-aw/agent/*)
+ # - ExitPlanMode
+ # - Glob
+ # - Grep
+ # - KillBash
+ # - LS
+ # - MultiEdit
+ # - MultiEdit(/tmp/*)
+ # - MultiEdit(/tmp/gh-aw/agent/*)
+ # - NotebookEdit
+ # - NotebookRead
+ # - Read
+ # - Read(/tmp/*)
+ # - Read(/tmp/gh-aw/agent/*)
+ # - Task
+ # - TodoWrite
+ # - Write
+ # - Write(/tmp/*)
+ # - Write(/tmp/gh-aw/agent/*)
+ # - mcp__github__download_workflow_run_artifact
+ # - mcp__github__get_code_scanning_alert
+ # - mcp__github__get_commit
+ # - mcp__github__get_dependabot_alert
+ # - mcp__github__get_discussion
+ # - mcp__github__get_discussion_comments
+ # - mcp__github__get_file_contents
+ # - mcp__github__get_job_logs
+ # - mcp__github__get_label
+ # - mcp__github__get_latest_release
+ # - mcp__github__get_me
+ # - mcp__github__get_notification_details
+ # - mcp__github__get_pull_request
+ # - mcp__github__get_pull_request_comments
+ # - mcp__github__get_pull_request_diff
+ # - mcp__github__get_pull_request_files
+ # - mcp__github__get_pull_request_review_comments
+ # - mcp__github__get_pull_request_reviews
+ # - mcp__github__get_pull_request_status
+ # - mcp__github__get_release_by_tag
+ # - mcp__github__get_secret_scanning_alert
+ # - mcp__github__get_tag
+ # - mcp__github__get_workflow_run
+ # - mcp__github__get_workflow_run_logs
+ # - mcp__github__get_workflow_run_usage
+ # - mcp__github__issue_read
+ # - mcp__github__list_branches
+ # - mcp__github__list_code_scanning_alerts
+ # - mcp__github__list_commits
+ # - mcp__github__list_dependabot_alerts
+ # - mcp__github__list_discussion_categories
+ # - mcp__github__list_discussions
+ # - mcp__github__list_issue_types
+ # - mcp__github__list_issues
+ # - mcp__github__list_label
+ # - mcp__github__list_notifications
+ # - mcp__github__list_pull_requests
+ # - mcp__github__list_releases
+ # - mcp__github__list_secret_scanning_alerts
+ # - mcp__github__list_starred_repositories
+ # - mcp__github__list_tags
+ # - mcp__github__list_workflow_jobs
+ # - mcp__github__list_workflow_run_artifacts
+ # - mcp__github__list_workflow_runs
+ # - mcp__github__list_workflows
+ # - mcp__github__pull_request_read
+ # - mcp__github__search_code
+ # - mcp__github__search_issues
+ # - mcp__github__search_orgs
+ # - mcp__github__search_pull_requests
+ # - mcp__github__search_repositories
+ # - mcp__github__search_users
+ # - mcp__safeoutputs
timeout-minutes: 20
run: |
set -o pipefail
printf '%s' "$(date +%s%3N)" > /tmp/gh-aw/agent_cli_start_ms.txt
touch /tmp/gh-aw/agent-step-summary.md
- GH_AW_NODE_BIN=$(command -v node 2>/dev/null || true)
- export GH_AW_NODE_BIN
- export COPILOT_API_KEY="$COPILOT_DUMMY_BYOK"
(umask 177 && touch /tmp/gh-aw/agent-stdio.log)
- printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.55/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","codeload.github.com","docs.github.com","github-cloud.githubusercontent.com","github-cloud.s3.amazonaws.com","github.blog","github.com","github.githubassets.com","host.docker.internal","lfs.github.com","objects.githubusercontent.com","patch-diff.githubusercontent.com","raw.githubusercontent.com","registry.npmjs.org","telemetry.enterprise.githubcopilot.com"]},"apiProxy":{"enabled":true,"enableTokenSteering":true,"maxRuns":500,"maxEffectiveTokens":25000000,"models":{"agent":["sonnet-6x","gpt-5.4","gpt-5.3","gemini-pro","any"],"antigravity":["copilot/antigravity*","google/antigravity*","gemini/antigravity*"],"any":["copilot/*","anthropic/*","openai/*","google/*","gemini/*"],"claude":["agent"],"codex":["agent"],"coding":["copilot/gpt-5*codex*","openai/gpt-5*codex*","gpt-5-codex"],"computer-use":["copilot/*computer-use*","google/*computer-use*","gemini/*computer-use*","openai/*computer-use*"],"copilot":["agent"],"deep-research":["copilot/deep-research*","copilot/o3-deep-research*","copilot/o4-mini-deep-research*","google/deep-research*","gemini/deep-research*","openai/o3-deep-research*","openai/o4-mini-deep-research*"],"gemini":["agent"],"gemini-3-flash":["copilot/gemini-3*flash*","google/gemini-3*flash*","gemini/gemini-3*flash*"],"gemini-3-pro":["copilot/gemini-3*pro*","google/gemini-3*pro*","gemini/gemini-3*pro*"],"gemini-3.1-flash":["copilot/gemini-3.1*flash*","google/gemini-3.1*flash*","gemini/gemini-3.1*flash*"],"gemini-3.1-pro":["copilot/gemini-3.1*pro*","google/gemini-3.1*pro*","gemini/gemini-3.1*pro*"],"gemini-3.5-flash":["copilot/gemini-3.5*flash*","google/gemini-3.5*flash*","gemini/gemini-3.5*flash*"],"gemini-flash":["copilot/gemini-*flash*","google/gemini-*flash*","gemini/gemini-*flash*"],"gemini-flash-lite":["copilot/gemini-*flash*lite*","google/gemini-*flash*lite*","gemini/gemini-*flash*lite*"],"gemini-pro":["copilot/gemini-*pro*","google/gemini-*pro*","gemini/gemini-*pro*"],"gemma":["copilot/gemma*","google/gemma*","gemini/gemma*"],"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*"],"gpt-5.2":["copilot/gpt-5.2*","openai/gpt-5.2*"],"gpt-5.3":["copilot/gpt-5.3*","openai/gpt-5.3*"],"gpt-5.4":["copilot/gpt-5.4*","openai/gpt-5.4*"],"gpt-5.5":["copilot/gpt-5.5*","openai/gpt-5.5*"],"haiku":["copilot/*haiku*","anthropic/*haiku*"],"large":["sonnet","gpt-5-pro","gpt-5","gemini-pro"],"mini":["haiku","gpt-5-mini","gpt-5-nano","gemini-flash-lite"],"opus":["copilot/*opus*","anthropic/*opus*"],"opusplan":["opus?effort=high"],"reasoning":["copilot/o1*","copilot/o3*","copilot/o4*","openai/o1*","openai/o3*","openai/o4*"],"robotics":["copilot/*robotics*","google/*robotics*","gemini/*robotics*"],"small":["mini"],"sonnet":["copilot/*sonnet*","anthropic/*sonnet*"],"sonnet-6x":["copilot/*sonnet-4-5-*","anthropic/*sonnet-4-5-*","copilot/*sonnet-4-6*","anthropic/*sonnet-4-6*"],"summarization":["haiku","gpt-5-mini","gemini-flash-lite","mini"],"vision":["copilot/gemini-*image*","gemini/gemini-*image*","copilot/gemini-*flash*","gemini/gemini-*flash*"]}},"container":{"imageTag":"0.25.55"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json"
+ printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.55/awf-config.schema.json","network":{"allowDomains":["*.githubusercontent.com","anthropic.com","api.anthropic.com","api.github.com","api.snapcraft.io","archive.ubuntu.com","azure.archive.ubuntu.com","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","docs.github.com","files.pythonhosted.org","ghcr.io","github-cloud.githubusercontent.com","github-cloud.s3.amazonaws.com","github.blog","github.com","github.githubassets.com","host.docker.internal","json-schema.org","json.schemastore.org","keyserver.ubuntu.com","lfs.github.com","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","patch-diff.githubusercontent.com","playwright.download.prss.microsoft.com","ppa.launchpad.net","pypi.org","raw.githubusercontent.com","registry.npmjs.org","s.symcb.com","s.symcd.com","security.ubuntu.com","sentry.io","statsig.anthropic.com","ts-crl.ws.symantec.com","ts-ocsp.ws.symantec.com"]},"apiProxy":{"enabled":true,"enableTokenSteering":true,"maxRuns":500,"maxEffectiveTokens":25000000,"models":{"agent":["sonnet-6x","gpt-5.4","gpt-5.3","gemini-pro","any"],"antigravity":["copilot/antigravity*","google/antigravity*","gemini/antigravity*"],"any":["copilot/*","anthropic/*","openai/*","google/*","gemini/*"],"claude":["agent"],"codex":["agent"],"coding":["copilot/gpt-5*codex*","openai/gpt-5*codex*","gpt-5-codex"],"computer-use":["copilot/*computer-use*","google/*computer-use*","gemini/*computer-use*","openai/*computer-use*"],"copilot":["agent"],"deep-research":["copilot/deep-research*","copilot/o3-deep-research*","copilot/o4-mini-deep-research*","google/deep-research*","gemini/deep-research*","openai/o3-deep-research*","openai/o4-mini-deep-research*"],"gemini":["agent"],"gemini-3-flash":["copilot/gemini-3*flash*","google/gemini-3*flash*","gemini/gemini-3*flash*"],"gemini-3-pro":["copilot/gemini-3*pro*","google/gemini-3*pro*","gemini/gemini-3*pro*"],"gemini-3.1-flash":["copilot/gemini-3.1*flash*","google/gemini-3.1*flash*","gemini/gemini-3.1*flash*"],"gemini-3.1-pro":["copilot/gemini-3.1*pro*","google/gemini-3.1*pro*","gemini/gemini-3.1*pro*"],"gemini-3.5-flash":["copilot/gemini-3.5*flash*","google/gemini-3.5*flash*","gemini/gemini-3.5*flash*"],"gemini-flash":["copilot/gemini-*flash*","google/gemini-*flash*","gemini/gemini-*flash*"],"gemini-flash-lite":["copilot/gemini-*flash*lite*","google/gemini-*flash*lite*","gemini/gemini-*flash*lite*"],"gemini-pro":["copilot/gemini-*pro*","google/gemini-*pro*","gemini/gemini-*pro*"],"gemma":["copilot/gemma*","google/gemma*","gemini/gemma*"],"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*"],"gpt-5.2":["copilot/gpt-5.2*","openai/gpt-5.2*"],"gpt-5.3":["copilot/gpt-5.3*","openai/gpt-5.3*"],"gpt-5.4":["copilot/gpt-5.4*","openai/gpt-5.4*"],"gpt-5.5":["copilot/gpt-5.5*","openai/gpt-5.5*"],"haiku":["copilot/*haiku*","anthropic/*haiku*"],"large":["sonnet","gpt-5-pro","gpt-5","gemini-pro"],"mini":["haiku","gpt-5-mini","gpt-5-nano","gemini-flash-lite"],"opus":["copilot/*opus*","anthropic/*opus*"],"opusplan":["opus?effort=high"],"reasoning":["copilot/o1*","copilot/o3*","copilot/o4*","openai/o1*","openai/o3*","openai/o4*"],"robotics":["copilot/*robotics*","google/*robotics*","gemini/*robotics*"],"small":["mini"],"sonnet":["copilot/*sonnet*","anthropic/*sonnet*"],"sonnet-6x":["copilot/*sonnet-4-5-*","anthropic/*sonnet-4-5-*","copilot/*sonnet-4-6*","anthropic/*sonnet-4-6*"],"summarization":["haiku","gpt-5-mini","gemini-flash-lite","mini"],"vision":["copilot/gemini-*image*","gemini/gemini-*image*","copilot/gemini-*flash*","gemini/gemini-*flash*"]}},"container":{"imageTag":"0.25.55"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json"
cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json
GH_AW_DOCKER_HOST_PATH_PREFIX_ARGS=""
if [[ "${DOCKER_HOST:-}" =~ ^tcp:// ]]; then
GH_AW_DOCKER_HOST_PATH_PREFIX_ARGS="--docker-host-path-prefix /tmp/gh-aw"
fi
# 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" ${GH_AW_DOCKER_HOST_PATH_PREFIX_ARGS} --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="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && export PATH="$(find /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 5 -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 || true)"; fi; if [ -z "$GH_AW_NODE_EXEC" ]; then echo "node runtime missing on this runner — check runtimes.node in workflow YAML" >&2; exit 127; fi; "$GH_AW_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
+ 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" ${GH_AW_DOCKER_HOST_PATH_PREFIX_ARGS} --tty --env-all --exclude-env ANTHROPIC_API_KEY --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="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && export PATH="$(find /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 5 -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 || true)"; fi; if [ -z "$GH_AW_NODE_EXEC" ]; then echo "node runtime missing on this runner — check runtimes.node in workflow YAML" >&2; exit 127; fi; "$GH_AW_NODE_EXEC" ${RUNNER_TEMP}/gh-aw/actions/claude_harness.cjs claude --print --no-chrome --max-turns 12 --allowed-tools '\''Bash,BashOutput,Edit,Edit(/tmp/*),Edit(/tmp/gh-aw/agent/*),ExitPlanMode,Glob,Grep,KillBash,LS,MultiEdit,MultiEdit(/tmp/*),MultiEdit(/tmp/gh-aw/agent/*),NotebookEdit,NotebookRead,Read,Read(/tmp/*),Read(/tmp/gh-aw/agent/*),Task,TodoWrite,Write,Write(/tmp/*),Write(/tmp/gh-aw/agent/*),mcp__github__download_workflow_run_artifact,mcp__github__get_code_scanning_alert,mcp__github__get_commit,mcp__github__get_dependabot_alert,mcp__github__get_discussion,mcp__github__get_discussion_comments,mcp__github__get_file_contents,mcp__github__get_job_logs,mcp__github__get_label,mcp__github__get_latest_release,mcp__github__get_me,mcp__github__get_notification_details,mcp__github__get_pull_request,mcp__github__get_pull_request_comments,mcp__github__get_pull_request_diff,mcp__github__get_pull_request_files,mcp__github__get_pull_request_review_comments,mcp__github__get_pull_request_reviews,mcp__github__get_pull_request_status,mcp__github__get_release_by_tag,mcp__github__get_secret_scanning_alert,mcp__github__get_tag,mcp__github__get_workflow_run,mcp__github__get_workflow_run_logs,mcp__github__get_workflow_run_usage,mcp__github__issue_read,mcp__github__list_branches,mcp__github__list_code_scanning_alerts,mcp__github__list_commits,mcp__github__list_dependabot_alerts,mcp__github__list_discussion_categories,mcp__github__list_discussions,mcp__github__list_issue_types,mcp__github__list_issues,mcp__github__list_label,mcp__github__list_notifications,mcp__github__list_pull_requests,mcp__github__list_releases,mcp__github__list_secret_scanning_alerts,mcp__github__list_starred_repositories,mcp__github__list_tags,mcp__github__list_workflow_jobs,mcp__github__list_workflow_run_artifacts,mcp__github__list_workflow_runs,mcp__github__list_workflows,mcp__github__pull_request_read,mcp__github__search_code,mcp__github__search_issues,mcp__github__search_orgs,mcp__github__search_pull_requests,mcp__github__search_repositories,mcp__github__search_users,mcp__safeoutputs'\'' --debug-file /tmp/gh-aw/agent-stdio.log --verbose --permission-mode acceptEdits --output-format stream-json --mcp-config "${RUNNER_TEMP}/gh-aw/mcp-config/mcp-servers.json" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt${GH_AW_MODEL_AGENT_CLAUDE:+ --model "$GH_AW_MODEL_AGENT_CLAUDE"}' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log
env:
- AWF_REFLECT_ENABLED: 1
- COPILOT_AGENT_RUNNER_TYPE: STANDALONE
- COPILOT_DUMMY_BYOK: dummy-byok-key-for-offline-mode
- COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
- COPILOT_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || 'claude-sonnet-4.6' }}
- GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json
+ ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
+ BASH_DEFAULT_TIMEOUT_MS: 60000
+ BASH_MAX_TIMEOUT_MS: 60000
+ CLAUDE_CODE_DISABLE_FAST_MODE: 1
+ DISABLE_BUG_COMMAND: 1
+ DISABLE_ERROR_REPORTING: 1
+ DISABLE_TELEMETRY: 1
+ GH_AW_MAX_TURNS: 12
+ GH_AW_MCP_CONFIG: ${{ runner.temp }}/gh-aw/mcp-config/mcp-servers.json
+ GH_AW_MODEL_AGENT_CLAUDE: ${{ vars.GH_AW_MODEL_AGENT_CLAUDE || '' }}
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
GH_AW_VERSION: v0.76.1
- GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
- GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows
- GITHUB_HEAD_REF: ${{ github.head_ref }}
- GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
- GITHUB_REF_NAME: ${{ github.ref_name }}
- GITHUB_SERVER_URL: ${{ github.server_url }}
GITHUB_STEP_SUMMARY: /tmp/gh-aw/agent-step-summary.md
GITHUB_WORKSPACE: ${{ github.workspace }}
GIT_AUTHOR_EMAIL: github-actions[bot]@users.noreply.github.com
GIT_AUTHOR_NAME: github-actions[bot]
GIT_COMMITTER_EMAIL: github-actions[bot]@users.noreply.github.com
GIT_COMMITTER_NAME: github-actions[bot]
- XDG_CONFIG_HOME: /home/runner
- - name: Detect agent errors
- if: always()
- id: detect-agent-errors
- continue-on-error: true
- run: node "${RUNNER_TEMP}/gh-aw/actions/detect_agent_errors.cjs"
+ MCP_TIMEOUT: 120000
+ MCP_TOOL_TIMEOUT: 60000
- name: Configure Git credentials
env:
REPO_NAME: ${{ github.repository }}
@@ -849,10 +1021,6 @@ jobs:
SERVER_URL_STRIPPED="${SERVER_URL#https://}"
git remote set-url origin "https://x-access-token:${GITHUB_TOKEN}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git"
echo "Git configured with standard GitHub Actions identity"
- - name: Copy Copilot session state files to logs
- if: always()
- continue-on-error: true
- run: bash "${RUNNER_TEMP}/gh-aw/actions/copy_copilot_session_state.sh"
- name: Stop MCP Gateway
if: always()
continue-on-error: true
@@ -872,8 +1040,8 @@ jobs:
const { main } = require('${{ runner.temp }}/gh-aw/actions/redact_secrets.cjs');
await main();
env:
- GH_AW_SECRET_NAMES: 'COPILOT_GITHUB_TOKEN,GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN'
- SECRET_COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
+ GH_AW_SECRET_NAMES: 'ANTHROPIC_API_KEY,GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN'
+ SECRET_ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
SECRET_GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }}
SECRET_GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }}
SECRET_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -893,7 +1061,7 @@ jobs:
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
- GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,codeload.github.com,docs.github.com,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.blog,github.com,github.githubassets.com,host.docker.internal,lfs.github.com,objects.githubusercontent.com,patch-diff.githubusercontent.com,raw.githubusercontent.com,registry.npmjs.org,telemetry.enterprise.githubcopilot.com"
+ GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,anthropic.com,api.anthropic.com,api.github.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,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,docs.github.com,files.pythonhosted.org,ghcr.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.blog,github.com,github.githubassets.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,lfs.github.com,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,patch-diff.githubusercontent.com,playwright.download.prss.microsoft.com,ppa.launchpad.net,pypi.org,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,sentry.io,statsig.anthropic.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com"
GITHUB_SERVER_URL: ${{ github.server_url }}
GITHUB_API_URL: ${{ github.api_url }}
with:
@@ -906,12 +1074,12 @@ jobs:
if: always()
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
- GH_AW_AGENT_OUTPUT: /tmp/gh-aw/sandbox/agent/logs/
+ GH_AW_AGENT_OUTPUT: /tmp/gh-aw/agent-stdio.log
with:
script: |
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
setupGlobals(core, github, context, exec, io, getOctokit);
- const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_copilot_log.cjs');
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_claude_log.cjs');
await main();
- name: Parse MCP Gateway logs for step summary
if: always()
@@ -972,8 +1140,6 @@ jobs:
name: agent
path: |
/tmp/gh-aw/aw-prompts/prompt.txt
- /tmp/gh-aw/sandbox/agent/logs/
- /tmp/gh-aw/redacted-urls.log
/tmp/gh-aw/mcp-logs/
/tmp/gh-aw/agent_usage.json
/tmp/gh-aw/agent-stdio.log
@@ -1021,9 +1187,9 @@ jobs:
env:
GH_AW_SETUP_WORKFLOW_NAME: "API Surface & Export Audit"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/export-audit.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.52"
+ GH_AW_INFO_VERSION: "2.1.150"
GH_AW_INFO_AWF_VERSION: "v0.25.55"
- GH_AW_INFO_ENGINE_ID: "copilot"
+ GH_AW_INFO_ENGINE_ID: "claude"
- name: Download agent output artifact
id: download-agent-output
continue-on-error: true
@@ -1098,16 +1264,12 @@ jobs:
GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }}
GH_AW_WORKFLOW_ID: "export-audit"
GH_AW_ACTION_FAILURE_ISSUE_EXPIRES_HOURS: "168"
- GH_AW_ENGINE_ID: "copilot"
+ GH_AW_ENGINE_ID: "claude"
GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.activation.outputs.secret_verification_result }}
GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }}
GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens || '' }}
GH_AW_EFFECTIVE_TOKENS_RATE_LIMIT_ERROR: ${{ needs.agent.outputs.effective_tokens_rate_limit_error || 'false' }}
- GH_AW_INFERENCE_ACCESS_ERROR: ${{ needs.agent.outputs.inference_access_error }}
- GH_AW_MCP_POLICY_ERROR: ${{ needs.agent.outputs.mcp_policy_error }}
- GH_AW_AGENTIC_ENGINE_TIMEOUT: ${{ needs.agent.outputs.agentic_engine_timeout }}
- GH_AW_MODEL_NOT_SUPPORTED_ERROR: ${{ needs.agent.outputs.model_not_supported_error }}
- GH_AW_ENGINE_API_HOSTS: "api.enterprise.githubcopilot.com,api.githubcopilot.com,api.business.githubcopilot.com,api.individual.githubcopilot.com"
+ GH_AW_ENGINE_API_HOSTS: "api.anthropic.com"
GH_AW_LOCKDOWN_CHECK_FAILED: ${{ needs.activation.outputs.lockdown_check_failed }}
GH_AW_STALE_LOCK_FILE_FAILED: ${{ needs.activation.outputs.stale_lock_file_failed }}
GH_AW_GROUP_REPORTS: "false"
@@ -1142,9 +1304,9 @@ jobs:
env:
GH_AW_SETUP_WORKFLOW_NAME: "API Surface & Export Audit"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/export-audit.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.52"
+ GH_AW_INFO_VERSION: "2.1.150"
GH_AW_INFO_AWF_VERSION: "v0.25.55"
- GH_AW_INFO_ENGINE_ID: "copilot"
+ GH_AW_INFO_ENGINE_ID: "claude"
- name: Check team membership for workflow
id: check_membership
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
@@ -1171,9 +1333,8 @@ jobs:
env:
GH_AW_CALLER_WORKFLOW_ID: "${{ github.repository }}/export-audit"
GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens }}
- GH_AW_ENGINE_ID: "copilot"
+ GH_AW_ENGINE_ID: "claude"
GH_AW_ENGINE_MODEL: ${{ needs.agent.outputs.model }}
- GH_AW_ENGINE_VERSION: "1.0.52"
GH_AW_WORKFLOW_ID: "export-audit"
GH_AW_WORKFLOW_NAME: "API Surface & Export Audit"
GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/export-audit.md"
@@ -1198,9 +1359,9 @@ jobs:
env:
GH_AW_SETUP_WORKFLOW_NAME: "API Surface & Export Audit"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/export-audit.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.52"
+ GH_AW_INFO_VERSION: "2.1.150"
GH_AW_INFO_AWF_VERSION: "v0.25.55"
- GH_AW_INFO_ENGINE_ID: "copilot"
+ GH_AW_INFO_ENGINE_ID: "claude"
- name: Download agent output artifact
id: download-agent-output
continue-on-error: true
@@ -1230,7 +1391,7 @@ jobs:
env:
GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }}
GH_AW_COMMENT_ID: ${{ needs.activation.outputs.comment_id }}
- GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,codeload.github.com,docs.github.com,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.blog,github.com,github.githubassets.com,host.docker.internal,lfs.github.com,objects.githubusercontent.com,patch-diff.githubusercontent.com,raw.githubusercontent.com,registry.npmjs.org,telemetry.enterprise.githubcopilot.com"
+ GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,anthropic.com,api.anthropic.com,api.github.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,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,docs.github.com,files.pythonhosted.org,ghcr.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.blog,github.com,github.githubassets.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,lfs.github.com,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,patch-diff.githubusercontent.com,playwright.download.prss.microsoft.com,ppa.launchpad.net,pypi.org,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,sentry.io,statsig.anthropic.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com"
GITHUB_SERVER_URL: ${{ github.server_url }}
GITHUB_API_URL: ${{ github.api_url }}
GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_issue\":{\"expires\":720,\"labels\":[\"code-quality\"],\"max\":5,\"title_prefix\":\"[Export Audit] \"},\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"true\"},\"report_incomplete\":{}}"
diff --git a/.github/workflows/export-audit.md b/.github/workflows/export-audit.md
index b3b071a4e..86f0db6d7 100644
--- a/.github/workflows/export-audit.md
+++ b/.github/workflows/export-audit.md
@@ -14,6 +14,10 @@ permissions:
contents: read
issues: read
+engine:
+ id: claude
+ max-turns: 12
+
sandbox:
agent:
id: awf
@@ -88,6 +92,23 @@ steps:
echo "EOF"
} >> "$GITHUB_OUTPUT"
+ - name: Pre-verify unused exports (top 10)
+ id: verified_unused
+ run: |
+ {
+ echo "VERIFIED_UNUSED</dev/null | \
+ grep -v "\.test\.ts" | wc -l)
+ echo "${sym}: used_in=${count}_files"
+ done
+ fi
+ echo "EOF"
+ } >> "$GITHUB_OUTPUT"
+
- name: Detect circular dependencies (madge)
id: circular_deps
run: |
@@ -170,7 +191,7 @@ This is **gh-aw-firewall**, a network firewall for GitHub Copilot CLI. The TypeS
## Phase 1: Review Unused Exports
-The pre-computed unused exports analysis is provided in the **Pre-computed Data** section below (`UNUSED_EXPORTS`). Review the results and verify each finding by checking all import sites, including test files and barrel exports (`index.ts`). Pay special attention to multi-line import blocks — TypeScript imports often list each symbol on its own line, which a single-line grep will miss. Use `grep -w` (whole-word matching) for verification.
+The pre-computed unused exports analysis is provided in the **Pre-computed Data** section below (`UNUSED_EXPORTS` and `VERIFIED_UNUSED`). Use `VERIFIED_UNUSED` directly as pre-confirmed evidence and do **not** run additional bash to re-verify those symbols. Only run bash if you need information not present in the pre-computed data.
## Phase 2: Review Naming Conventions
@@ -221,10 +242,11 @@ File issues only for findings with score ≥ 3. Cap at 5 issues per run.
## Verification Budget
-To control token usage, limit verification to the **top 5 candidates** by score. For each candidate:
-- Run at most 2 bash commands to confirm (one bounded recursive `grep -rw` over relevant source paths, one targeted check)
-- If not confirmed in 2 checks, mark as "unconfirmed" and skip filing
-- Do NOT loop over all files for each candidate — use one whole-word grep across relevant source directories only (for example `src/`, `lib/`, `app/`, `test/`) or explicitly exclude generated/dependency directories such as `node_modules/`, `dist/`, `build/`, and `coverage/`
+**STRICT token budget**: Verify at most **3 candidates total** (not 5). For each candidate:
+- Run **exactly 1 bash command** — a single `grep -rw src/ --include="*.ts" | grep -v "test\|index"` across relevant source directories only
+- If not confirmed in that 1 check, immediately mark as "unconfirmed" and move on — **do NOT run a second command**
+- After verifying 3 candidates, file issues for confirmed ones and stop — **do not verify more candidates**
+- **Total bash commands for verification: maximum 3** across all phases combined
### Issue Format
@@ -246,13 +268,6 @@ Unused export / Naming inconsistency / Circular dependency / Import path issue
-### Recommended Fix
-
-1. For **unused exports**: Remove the `export` keyword or delete the symbol if it's dead code
-2. For **naming inconsistencies**: Rename to follow convention (types: PascalCase, functions: camelCase)
-3. For **circular dependencies**: Extract the shared dependency into a new module
-4. For **test imports**: Update the import path to reference the correct module
-
### Impact
- Dead code risk:
- Maintenance burden:
@@ -271,10 +286,7 @@ Unused export / Naming inconsistency / Circular dependency / Import path issue
## Edge Cases
-- **Build fails (TypeScript errors)**: Report the build errors in the log; skip the audit since analysis would be unreliable. Do NOT create issues for TypeScript errors — those are tracked separately.
-- **ts-prune / madge unavailable**: Fall back to grep-based analysis with a note that results may be incomplete
-- **All findings already tracked**: Skip creation and log that existing issues cover the findings
-- **No issues found**: Log a summary and exit without creating issues
+If the build fails, report TypeScript errors and skip audit issue creation. If `ts-prune` or `madge` is unavailable, use the existing fallback output and note reduced confidence. If findings are already tracked or no actionable findings remain, log a concise summary and exit without creating issues.
---
@@ -295,6 +307,11 @@ Unused exports:
${{ steps.unused_exports.outputs.UNUSED_EXPORTS }}
```
+Verified unused exports:
+```
+${{ steps.verified_unused.outputs.VERIFIED_UNUSED }}
+```
+
Circular dependencies:
```
${{ steps.circular_deps.outputs.CIRCULAR_DEPS }}
diff --git a/scripts/ci/export-audit-workflow.test.ts b/scripts/ci/export-audit-workflow.test.ts
new file mode 100644
index 000000000..4190641ce
--- /dev/null
+++ b/scripts/ci/export-audit-workflow.test.ts
@@ -0,0 +1,33 @@
+import * as fs from 'fs';
+import * as path from 'path';
+
+const workflowsDir = path.resolve(__dirname, '../../.github/workflows');
+const sourcePath = path.join(workflowsDir, 'export-audit.md');
+const lockPath = path.join(workflowsDir, 'export-audit.lock.yml');
+
+describe('export audit workflow optimization config', () => {
+ it('applies turn cap and strict verification constraints in source workflow', () => {
+ const source = fs.readFileSync(sourcePath, 'utf-8');
+
+ expect(source).toContain('max-turns: 12');
+ expect(source).toContain('Pre-verify unused exports (top 10)');
+ expect(source).toContain('id: verified_unused');
+ expect(source).toContain('VERIFIED_UNUSED< {
+ const lock = fs.readFileSync(lockPath, 'utf-8');
+
+ expect(lock).toContain('--max-turns 12');
+ expect(lock).toContain('GH_AW_STEPS_VERIFIED_UNUSED_OUTPUTS_VERIFIED_UNUSED');
+ expect(lock).toContain('Pre-verify unused exports (top 10)');
+ });
+});
From 9d7f2ea4c8ca0a80e905fcb6201b23b6522e50f8 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sun, 31 May 2026 14:03:42 +0000
Subject: [PATCH 3/3] Fix export-audit pre-verification parsing and guidance
---
.github/workflows/export-audit.lock.yml | 51 ++++++++++++++++--------
.github/workflows/export-audit.md | 29 +++++++++++---
scripts/ci/export-audit-workflow.test.ts | 6 +++
3 files changed, 63 insertions(+), 23 deletions(-)
diff --git a/.github/workflows/export-audit.lock.yml b/.github/workflows/export-audit.lock.yml
index 1336235e0..7f8e3ca72 100644
--- a/.github/workflows/export-audit.lock.yml
+++ b/.github/workflows/export-audit.lock.yml
@@ -1,4 +1,4 @@
-# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"8e8de5a131f42f2c3bbf62fef1f1a8ffc769fa58ac53eea7ee484de17fc6e6f3","compiler_version":"v0.76.1","strict":true,"agent_id":"claude"}
+# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"4ce6fff6ee2476affd460258de6e79ad8c850d0d436076792a9474904c3fa12a","compiler_version":"v0.76.1","strict":true,"agent_id":"claude"}
# gh-aw-manifest: {"version":1,"secrets":["ANTHROPIC_API_KEY","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","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"},{"repo":"github/gh-aw-actions/setup","sha":"46d564922b082d0db93244972e8005ea6904ee5f","version":"v0.76.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.55"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.55"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.55"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.19"},{"image":"ghcr.io/github/github-mcp-server:v1.0.4","digest":"sha256:e3816a476a977cfb836e7d221510011436c654d11861db66ecfd826601aba6a4","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.4@sha256:e3816a476a977cfb836e7d221510011436c654d11861db66ecfd826601aba6a4"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]}
# ___ _ _
# / _ \ | | (_)
@@ -203,20 +203,20 @@ jobs:
run: |
bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh"
{
- cat << 'GH_AW_PROMPT_9918201839a3620e_EOF'
+ cat << 'GH_AW_PROMPT_3e84c9458501f30e_EOF'
- GH_AW_PROMPT_9918201839a3620e_EOF
+ GH_AW_PROMPT_3e84c9458501f30e_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_9918201839a3620e_EOF'
+ cat << 'GH_AW_PROMPT_3e84c9458501f30e_EOF'
Tools: create_issue(max:5), missing_tool, missing_data, noop
- GH_AW_PROMPT_9918201839a3620e_EOF
+ GH_AW_PROMPT_3e84c9458501f30e_EOF
cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md"
- cat << 'GH_AW_PROMPT_9918201839a3620e_EOF'
+ cat << 'GH_AW_PROMPT_3e84c9458501f30e_EOF'
The following GitHub context information is available for this workflow:
{{#if github.actor}}
@@ -245,12 +245,12 @@ jobs:
{{/if}}
- GH_AW_PROMPT_9918201839a3620e_EOF
+ GH_AW_PROMPT_3e84c9458501f30e_EOF
cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md"
- cat << 'GH_AW_PROMPT_9918201839a3620e_EOF'
+ cat << 'GH_AW_PROMPT_3e84c9458501f30e_EOF'
{{#runtime-import .github/workflows/export-audit.md}}
- GH_AW_PROMPT_9918201839a3620e_EOF
+ GH_AW_PROMPT_3e84c9458501f30e_EOF
} > "$GH_AW_PROMPT"
- name: Interpolate variables and render templates
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
@@ -469,11 +469,28 @@ jobs:
echo "VERIFIED_UNUSED</dev/null | \
- grep -v "\.test\.ts" | wc -l)
- echo "${sym}: used_in=${count}_files"
+ grep -v "\.test\.ts" | \
+ awk -v file="$file" '$0 != file' | \
+ wc -l)
+ echo "${sym}: used_outside_defining_file=${count}_files"
done
fi
echo "EOF"
@@ -619,9 +636,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_a58ea953901a5d88_EOF'
+ cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_eda9f239c9abeb8e_EOF'
{"create_issue":{"expires":720,"labels":["code-quality"],"max":5,"title_prefix":"[Export Audit] "},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}}
- GH_AW_SAFE_OUTPUTS_CONFIG_a58ea953901a5d88_EOF
+ GH_AW_SAFE_OUTPUTS_CONFIG_eda9f239c9abeb8e_EOF
- name: Generate Safe Outputs Tools
env:
GH_AW_TOOLS_META_JSON: |
@@ -828,7 +845,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 '"${DOCKER_SOCK_PATH}"':/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DOCKER_HOST=unix:///var/run/docker.sock -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_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 -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.19'
GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node)
- cat << GH_AW_MCP_CONFIG_4d2b998142875e8a_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs"
+ cat << GH_AW_MCP_CONFIG_b7a2483d07dd9048_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs"
{
"mcpServers": {
"github": {
@@ -868,7 +885,7 @@ jobs:
"payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}"
}
}
- GH_AW_MCP_CONFIG_4d2b998142875e8a_EOF
+ GH_AW_MCP_CONFIG_b7a2483d07dd9048_EOF
- name: Mount MCP servers as CLIs
id: mount-mcp-clis
continue-on-error: true
diff --git a/.github/workflows/export-audit.md b/.github/workflows/export-audit.md
index 86f0db6d7..f3831d2bf 100644
--- a/.github/workflows/export-audit.md
+++ b/.github/workflows/export-audit.md
@@ -99,11 +99,28 @@ steps:
echo "VERIFIED_UNUSED</dev/null | \
- grep -v "\.test\.ts" | wc -l)
- echo "${sym}: used_in=${count}_files"
+ grep -v "\.test\.ts" | \
+ awk -v file="$file" '$0 != file' | \
+ wc -l)
+ echo "${sym}: used_outside_defining_file=${count}_files"
done
fi
echo "EOF"
@@ -191,7 +208,7 @@ This is **gh-aw-firewall**, a network firewall for GitHub Copilot CLI. The TypeS
## Phase 1: Review Unused Exports
-The pre-computed unused exports analysis is provided in the **Pre-computed Data** section below (`UNUSED_EXPORTS` and `VERIFIED_UNUSED`). Use `VERIFIED_UNUSED` directly as pre-confirmed evidence and do **not** run additional bash to re-verify those symbols. Only run bash if you need information not present in the pre-computed data.
+The pre-computed unused exports analysis is provided in the **Pre-computed Data** section below (`UNUSED_EXPORTS` and `VERIFIED_UNUSED`). Use `VERIFIED_UNUSED` directly as pre-confirmed evidence and do **not** run additional bash to re-verify those symbols. `VERIFIED_UNUSED` reports `used_outside_defining_file=N_files`; `used_outside_defining_file=0_files` means no external usage beyond the defining file. If `VERIFIED_UNUSED` is empty, fall back to the normal verification flow within the strict command budget.
## Phase 2: Review Naming Conventions
@@ -243,7 +260,7 @@ File issues only for findings with score ≥ 3. Cap at 5 issues per run.
## Verification Budget
**STRICT token budget**: Verify at most **3 candidates total** (not 5). For each candidate:
-- Run **exactly 1 bash command** — a single `grep -rw src/ --include="*.ts" | grep -v "test\|index"` across relevant source directories only
+- Run **exactly 1 bash command** — a single `grep -rw src/ --include="*.ts" | grep -vE "test|index"` across relevant source directories only
- If not confirmed in that 1 check, immediately mark as "unconfirmed" and move on — **do NOT run a second command**
- After verifying 3 candidates, file issues for confirmed ones and stop — **do not verify more candidates**
- **Total bash commands for verification: maximum 3** across all phases combined
diff --git a/scripts/ci/export-audit-workflow.test.ts b/scripts/ci/export-audit-workflow.test.ts
index 4190641ce..fb414387b 100644
--- a/scripts/ci/export-audit-workflow.test.ts
+++ b/scripts/ci/export-audit-workflow.test.ts
@@ -14,8 +14,12 @@ describe('export audit workflow optimization config', () => {
expect(source).toContain('id: verified_unused');
expect(source).toContain('VERIFIED_UNUSED< {
expect(lock).toContain('--max-turns 12');
expect(lock).toContain('GH_AW_STEPS_VERIFIED_UNUSED_OUTPUTS_VERIFIED_UNUSED');
expect(lock).toContain('Pre-verify unused exports (top 10)');
+ expect(lock).toContain('used_outside_defining_file=${count}_files');
+ expect(lock).toContain("^UNUSED: [^[:space:]]+ \\([^)]*\\)$");
});
});