From 74270c2c37cc0be7d6d690f4295b732305e951d1 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 23 Apr 2026 17:58:32 +0000
Subject: [PATCH 1/2] Initial plan
From 466bfa229bdb6c223104a805478a012e168c5f25 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 23 Apr 2026 18:18:20 +0000
Subject: [PATCH 2/2] feat: optimize architecture-guardian with bash pre-step
consolidation
- Add bash pre-step that collects all file metrics upfront into
/tmp/gh-aw/agent/arch-metrics.json, replacing ~20-30 per-file
agent turns with a single deterministic bash step
- Remove github: toolsets: [repos] (unused in local static analysis)
- Remove edit: tool (workflow is read-only, tool was never called)
- Simplify violation reporting to 2-line templated format per violation
instead of verbose 3-part narrative suggestions
- Improve Go receiver method detection in awk pattern
- Expand JS function detection to cover arrow functions and exports
- Add comment explaining go list error handling
- Add instruction for agent to replace template placeholders
Estimated savings: ~800K-1.1M tokens per run (~40-55% reduction)
Reduces expected turns from 47 to ~15-20
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/8b9b7035-c5bd-4617-9684-7537d0c6b157
Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
---
.../workflows/architecture-guardian.lock.yml | 53 ++--
.github/workflows/architecture-guardian.md | 298 ++++++++----------
.../src/content/docs/agent-factory-status.mdx | 3 +
.../docs/reference/frontmatter-full.md | 22 +-
4 files changed, 174 insertions(+), 202 deletions(-)
diff --git a/.github/workflows/architecture-guardian.lock.yml b/.github/workflows/architecture-guardian.lock.yml
index db4c8ef18ee..c40fdaffbdc 100644
--- a/.github/workflows/architecture-guardian.lock.yml
+++ b/.github/workflows/architecture-guardian.lock.yml
@@ -1,5 +1,5 @@
-# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"6e058dfe39de24cbb46e8cf0c81f6070575ac7392250c7e4b5e61d68efe6ac44","strict":true,"agent_id":"copilot"}
-# gh-aw-manifest: {"version":1,"secrets":["GH_AW_AGENT_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":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.28","digest":"sha256:a8834e285807654bf680154faa710d43fe4365a0868142f5c20e48c85e137a7a","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.28@sha256:a8834e285807654bf680154faa710d43fe4365a0868142f5c20e48c85e137a7a"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.28","digest":"sha256:93290f2393752252911bd7c39a047f776c0b53063575e7bde4e304962a9a61cb","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.28@sha256:93290f2393752252911bd7c39a047f776c0b53063575e7bde4e304962a9a61cb"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.28","digest":"sha256:844c18280f82cd1b06345eb2f4e91966b34185bfc51c9f237c3e022e848fb474","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.28@sha256:844c18280f82cd1b06345eb2f4e91966b34185bfc51c9f237c3e022e848fb474"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.2.30","digest":"sha256:e950e6d39f003862d33bfb8d4eb93e242d919cf6ca874b90728e5e0ea7434c6f","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.2.30@sha256:e950e6d39f003862d33bfb8d4eb93e242d919cf6ca874b90728e5e0ea7434c6f"},{"image":"ghcr.io/github/github-mcp-server:v1.0.0","digest":"sha256:d2550953f8050bc5a1c8f80d1678766f66f60bbfbcd953fdeaf661fe4269bd95","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.0@sha256:d2550953f8050bc5a1c8f80d1678766f66f60bbfbcd953fdeaf661fe4269bd95"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]}
+# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"1021a0c5d12ef4d0b6f13853aa04edcaa454412f67d8bcba8af9df4231221afd","strict":true,"agent_id":"copilot"}
+# gh-aw-manifest: {"version":1,"secrets":["GH_AW_AGENT_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":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/setup-go","sha":"4a3601121dd01d1626a1e23e37211e3254c1c06c","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.28","digest":"sha256:a8834e285807654bf680154faa710d43fe4365a0868142f5c20e48c85e137a7a","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.28@sha256:a8834e285807654bf680154faa710d43fe4365a0868142f5c20e48c85e137a7a"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.28","digest":"sha256:93290f2393752252911bd7c39a047f776c0b53063575e7bde4e304962a9a61cb","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.28@sha256:93290f2393752252911bd7c39a047f776c0b53063575e7bde4e304962a9a61cb"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.28","digest":"sha256:844c18280f82cd1b06345eb2f4e91966b34185bfc51c9f237c3e022e848fb474","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.28@sha256:844c18280f82cd1b06345eb2f4e91966b34185bfc51c9f237c3e022e848fb474"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.2.30","digest":"sha256:e950e6d39f003862d33bfb8d4eb93e242d919cf6ca874b90728e5e0ea7434c6f","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.2.30@sha256:e950e6d39f003862d33bfb8d4eb93e242d919cf6ca874b90728e5e0ea7434c6f"},{"image":"ghcr.io/github/github-mcp-server:v1.0.0","digest":"sha256:d2550953f8050bc5a1c8f80d1678766f66f60bbfbcd953fdeaf661fe4269bd95","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.0@sha256:d2550953f8050bc5a1c8f80d1678766f66f60bbfbcd953fdeaf661fe4269bd95"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]}
# ___ _ _
# / _ \ | | (_)
# | |_| | __ _ ___ _ __ | |_ _ ___
@@ -38,6 +38,7 @@
# - actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
# - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
# - actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9
+# - actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
# - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
#
# Container images used:
@@ -173,20 +174,20 @@ jobs:
run: |
bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh"
{
- cat << 'GH_AW_PROMPT_596272447b0a6f31_EOF'
+ cat << 'GH_AW_PROMPT_32704be96c42d3fd_EOF'
- GH_AW_PROMPT_596272447b0a6f31_EOF
+ GH_AW_PROMPT_32704be96c42d3fd_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_596272447b0a6f31_EOF'
+ cat << 'GH_AW_PROMPT_32704be96c42d3fd_EOF'
Tools: create_issue, missing_tool, missing_data, noop
- GH_AW_PROMPT_596272447b0a6f31_EOF
+ GH_AW_PROMPT_32704be96c42d3fd_EOF
cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md"
- cat << 'GH_AW_PROMPT_596272447b0a6f31_EOF'
+ cat << 'GH_AW_PROMPT_32704be96c42d3fd_EOF'
The following GitHub context information is available for this workflow:
{{#if __GH_AW_GITHUB_ACTOR__ }}
@@ -215,12 +216,12 @@ jobs:
{{/if}}
- GH_AW_PROMPT_596272447b0a6f31_EOF
+ GH_AW_PROMPT_32704be96c42d3fd_EOF
cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md"
- cat << 'GH_AW_PROMPT_596272447b0a6f31_EOF'
+ cat << 'GH_AW_PROMPT_32704be96c42d3fd_EOF'
{{#runtime-import .github/workflows/architecture-guardian.md}}
- GH_AW_PROMPT_596272447b0a6f31_EOF
+ GH_AW_PROMPT_32704be96c42d3fd_EOF
} > "$GH_AW_PROMPT"
- name: Interpolate variables and render templates
uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9
@@ -349,12 +350,22 @@ jobs:
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
+ - name: Setup Go
+ uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
+ with:
+ go-version: '1.25'
+ cache: false
+ - name: Capture GOROOT for AWF chroot mode
+ run: echo "GOROOT=$(go env GOROOT)" >> "$GITHUB_ENV"
- name: Create gh-aw temp directory
run: bash "${RUNNER_TEMP}/gh-aw/actions/create_gh_aw_tmp_dir.sh"
- name: Configure gh CLI for GitHub Enterprise
run: bash "${RUNNER_TEMP}/gh-aw/actions/configure_gh_for_ghe.sh"
env:
GH_TOKEN: ${{ github.token }}
+ - name: Collect architecture metrics
+ run: "set -euo pipefail\nmkdir -p /tmp/gh-aw/agent\n\n# Read thresholds from .architecture.yml or use defaults\nFILE_LINES_BLOCKER=1000\nFILE_LINES_WARNING=500\nFUNCTION_LINES=80\nMAX_EXPORTS=10\n\nif [ -f .architecture.yml ]; then\n b=$(grep -E '^\\s*file_lines_blocker:' .architecture.yml 2>/dev/null | awk '{print $2}' | tr -d '\"' | head -1 || true)\n w=$(grep -E '^\\s*file_lines_warning:' .architecture.yml 2>/dev/null | awk '{print $2}' | tr -d '\"' | head -1 || true)\n f=$(grep -E '^\\s*function_lines:' .architecture.yml 2>/dev/null | awk '{print $2}' | tr -d '\"' | head -1 || true)\n e=$(grep -E '^\\s*max_exports:' .architecture.yml 2>/dev/null | awk '{print $2}' | tr -d '\"' | head -1 || true)\n [[ -n \"${b:-}\" && \"$b\" =~ ^[0-9]+$ ]] && FILE_LINES_BLOCKER=$b\n [[ -n \"${w:-}\" && \"$w\" =~ ^[0-9]+$ ]] && FILE_LINES_WARNING=$w\n [[ -n \"${f:-}\" && \"$f\" =~ ^[0-9]+$ ]] && FUNCTION_LINES=$f\n [[ -n \"${e:-}\" && \"$e\" =~ ^[0-9]+$ ]] && MAX_EXPORTS=$e\nfi\n\n# Get changed Go/JS files in last 24 hours, excluding tests and vendor paths\nCHANGED_FILES=$(git log --since=\"24 hours ago\" --name-only --pretty=format: \\\n | sort -u \\\n | grep -E '\\.(go|js|cjs|mjs)$' \\\n | grep -vE '(node_modules/|vendor/|\\.git/|_test\\.go$)' \\\n | while IFS= read -r f; do [ -f \"$f\" ] && echo \"$f\"; done \\\n || true)\n\nif [ -z \"$CHANGED_FILES\" ]; then\n jq -n \\\n --argjson blocker \"$FILE_LINES_BLOCKER\" \\\n --argjson warning \"$FILE_LINES_WARNING\" \\\n --argjson func_lines \"$FUNCTION_LINES\" \\\n --argjson max_exports \"$MAX_EXPORTS\" \\\n '{noop: true, thresholds: {file_lines_blocker: $blocker, file_lines_warning: $warning, function_lines: $func_lines, max_exports: $max_exports}, files: [], import_cycles: \"\"}' \\\n > /tmp/gh-aw/agent/arch-metrics.json\n echo \"No changed Go/JS files found in the last 24 hours.\"\n exit 0\nfi\n\n# Build file metrics array\nFILES_JSON=\"[]\"\nwhile IFS= read -r FILE; do\n [ -z \"$FILE\" ] && continue\n LINES=$(wc -l < \"$FILE\" 2>/dev/null | tr -d ' ' || echo 0)\n EXT=\"${FILE##*.}\"\n\n if [[ \"$EXT\" == \"go\" ]]; then\n # Function sizes: \"func declaration\\tline_count\" per function\n # Pattern matches both regular functions (^func Name) and receiver methods (^func (r *T) Name)\n FUNC_DATA=$(awk '/^func /{if(start>0 && name!=\"\") printf \"%s\\t%d\\n\", name, NR-start; name=$0; start=NR} END{if(start>0 && name!=\"\") printf \"%s\\t%d\\n\", name, NR-start+1}' \"$FILE\" 2>/dev/null | head -50 || true)\n # Export count and names (top-level exported identifiers start with uppercase)\n EXPORT_COUNT=$(grep -cE \"^func [A-Z]|^type [A-Z]|^var [A-Z]|^const [A-Z]\" \"$FILE\" 2>/dev/null || echo 0)\n EXPORT_NAMES=$(grep -nE \"^func [A-Z]|^type [A-Z]|^var [A-Z]|^const [A-Z]\" \"$FILE\" 2>/dev/null | head -20 || true)\n else\n # JS/CJS/MJS: capture named functions, arrow functions, and class methods\n FUNC_DATA=$(grep -nE \"^function |^const [a-zA-Z_$][a-zA-Z0-9_$]* = (function|\\(|async \\(|async function)|^(export (default )?function|export const [a-zA-Z_$][a-zA-Z0-9_$]* =)|^[a-zA-Z_$][a-zA-Z0-9_$]*\\s*\\([^)]*\\)\\s*\\{\" \"$FILE\" 2>/dev/null | head -50 || true)\n CJS_COUNT=$(grep -cE \"^module\\.exports|^exports\\.\" \"$FILE\" 2>/dev/null || echo 0)\n ESM_COUNT=$(grep -cE \"^export \" \"$FILE\" 2>/dev/null || echo 0)\n EXPORT_COUNT=$((CJS_COUNT + ESM_COUNT))\n EXPORT_NAMES=$(grep -nE \"^export |^module\\.exports|^exports\\.\" \"$FILE\" 2>/dev/null | head -20 || true)\n fi\n\n FILES_JSON=$(jq \\\n --arg file \"$FILE\" \\\n --argjson lines \"$LINES\" \\\n --argjson exports \"$EXPORT_COUNT\" \\\n --arg func_data \"${FUNC_DATA:-}\" \\\n --arg export_names \"${EXPORT_NAMES:-}\" \\\n '. + [{file: $file, lines: $lines, export_count: $exports, func_data: $func_data, export_names: $export_names}]' \\\n <<< \"$FILES_JSON\")\ndone <<< \"$CHANGED_FILES\"\n\n# Check Go import cycles once across all packages\n# Note: go list may also emit errors for syntax issues; grep filters to only cycle errors\nIMPORT_CYCLES=$(go list ./... 2>&1 | grep -iE \"import cycle|cycle not allowed\" || true)\n\njq -n \\\n --argjson blocker \"$FILE_LINES_BLOCKER\" \\\n --argjson warning \"$FILE_LINES_WARNING\" \\\n --argjson func_lines \"$FUNCTION_LINES\" \\\n --argjson max_exports \"$MAX_EXPORTS\" \\\n --argjson files \"$FILES_JSON\" \\\n --arg import_cycles \"$IMPORT_CYCLES\" \\\n '{noop: false, thresholds: {file_lines_blocker: $blocker, file_lines_warning: $warning, function_lines: $func_lines, max_exports: $max_exports}, files: $files, import_cycles: $import_cycles}' \\\n > /tmp/gh-aw/agent/arch-metrics.json\n\nFILE_COUNT=$(echo \"$CHANGED_FILES\" | wc -l | tr -d ' ')\necho \"✅ Pre-computed metrics for $FILE_COUNT file(s) → /tmp/gh-aw/agent/arch-metrics.json\"\n"
+
- name: Configure Git credentials
env:
REPO_NAME: ${{ github.repository }}
@@ -405,9 +416,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_96d69fc13f9c7deb_EOF'
+ cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_a0a098aec577897c_EOF'
{"create_issue":{"assignees":["copilot"],"max":1},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}}
- GH_AW_SAFE_OUTPUTS_CONFIG_96d69fc13f9c7deb_EOF
+ GH_AW_SAFE_OUTPUTS_CONFIG_a0a098aec577897c_EOF
- name: Write Safe Outputs Tools
env:
GH_AW_TOOLS_META_JSON: |
@@ -606,7 +617,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_192fa1e2d2baec6f_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs"
+ cat << GH_AW_MCP_CONFIG_9f6cb6bd242c59db_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs"
{
"mcpServers": {
"github": {
@@ -616,7 +627,7 @@ jobs:
"GITHUB_HOST": "\${GITHUB_SERVER_URL}",
"GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}",
"GITHUB_READ_ONLY": "1",
- "GITHUB_TOOLSETS": "repos"
+ "GITHUB_TOOLSETS": "context,repos,issues,pull_requests"
},
"guard-policies": {
"allow-only": {
@@ -647,7 +658,7 @@ jobs:
"payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}"
}
}
- GH_AW_MCP_CONFIG_192fa1e2d2baec6f_EOF
+ GH_AW_MCP_CONFIG_9f6cb6bd242c59db_EOF
- name: Mount MCP servers as CLIs
id: mount-mcp-clis
continue-on-error: true
@@ -681,29 +692,19 @@ jobs:
# Copilot CLI tool arguments (sorted):
# --allow-tool github
# --allow-tool safeoutputs
- # --allow-tool shell(awk:*)
# --allow-tool shell(cat)
# --allow-tool shell(cat:*)
# --allow-tool shell(date)
# --allow-tool shell(echo)
- # --allow-tool shell(find:*)
- # --allow-tool shell(git diff:*)
- # --allow-tool shell(git log:*)
- # --allow-tool shell(git show:*)
# --allow-tool shell(grep)
- # --allow-tool shell(grep:*)
# --allow-tool shell(head)
- # --allow-tool shell(head:*)
# --allow-tool shell(ls)
# --allow-tool shell(pwd)
# --allow-tool shell(safeoutputs:*)
- # --allow-tool shell(sed:*)
# --allow-tool shell(sort)
- # --allow-tool shell(sort:*)
# --allow-tool shell(tail)
# --allow-tool shell(uniq)
# --allow-tool shell(wc)
- # --allow-tool shell(wc:*)
# --allow-tool shell(yq)
# --allow-tool write
timeout-minutes: 20
@@ -715,7 +716,7 @@ jobs:
(umask 177 && touch /tmp/gh-aw/agent-stdio.log)
# shellcheck disable=SC1003
sudo -E awf --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 --allow-domains 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 --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 --image-tag 0.25.28,squid=sha256:844c18280f82cd1b06345eb2f4e91966b34185bfc51c9f237c3e022e848fb474,agent=sha256:a8834e285807654bf680154faa710d43fe4365a0868142f5c20e48c85e137a7a,api-proxy=sha256:93290f2393752252911bd7c39a047f776c0b53063575e7bde4e304962a9a61cb,cli-proxy=sha256:fdf310e4678ce58d248c466b89399e9680a3003038fd19322c388559016aaac7 --skip-pull --enable-api-proxy \
- -- /bin/bash -c 'export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && 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_driver.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-tool github --allow-tool safeoutputs --allow-tool '\''shell(awk:*)'\'' --allow-tool '\''shell(cat)'\'' --allow-tool '\''shell(cat:*)'\'' --allow-tool '\''shell(date)'\'' --allow-tool '\''shell(echo)'\'' --allow-tool '\''shell(find:*)'\'' --allow-tool '\''shell(git diff:*)'\'' --allow-tool '\''shell(git log:*)'\'' --allow-tool '\''shell(git show:*)'\'' --allow-tool '\''shell(grep)'\'' --allow-tool '\''shell(grep:*)'\'' --allow-tool '\''shell(head)'\'' --allow-tool '\''shell(head:*)'\'' --allow-tool '\''shell(ls)'\'' --allow-tool '\''shell(pwd)'\'' --allow-tool '\''shell(safeoutputs:*)'\'' --allow-tool '\''shell(sed:*)'\'' --allow-tool '\''shell(sort)'\'' --allow-tool '\''shell(sort:*)'\'' --allow-tool '\''shell(tail)'\'' --allow-tool '\''shell(uniq)'\'' --allow-tool '\''shell(wc)'\'' --allow-tool '\''shell(wc:*)'\'' --allow-tool '\''shell(yq)'\'' --allow-tool write --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
+ -- /bin/bash -c 'export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && 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_driver.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-tool github --allow-tool safeoutputs --allow-tool '\''shell(cat)'\'' --allow-tool '\''shell(cat:*)'\'' --allow-tool '\''shell(date)'\'' --allow-tool '\''shell(echo)'\'' --allow-tool '\''shell(grep)'\'' --allow-tool '\''shell(head)'\'' --allow-tool '\''shell(ls)'\'' --allow-tool '\''shell(pwd)'\'' --allow-tool '\''shell(safeoutputs:*)'\'' --allow-tool '\''shell(sort)'\'' --allow-tool '\''shell(tail)'\'' --allow-tool '\''shell(uniq)'\'' --allow-tool '\''shell(wc)'\'' --allow-tool '\''shell(yq)'\'' --allow-tool write --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
env:
COPILOT_AGENT_RUNNER_TYPE: STANDALONE
COPILOT_API_KEY: dummy-byok-key-for-offline-mode
diff --git a/.github/workflows/architecture-guardian.md b/.github/workflows/architecture-guardian.md
index a7e0d8aa043..8ffe29daa29 100644
--- a/.github/workflows/architecture-guardian.md
+++ b/.github/workflows/architecture-guardian.md
@@ -12,21 +12,8 @@ engine: copilot
tracker-id: architecture-guardian
tools:
mount-as-clis: true
- github:
- toolsets: [repos]
bash:
- - "git log:*"
- - "git diff:*"
- - "git show:*"
- - "find:*"
- - "wc:*"
- - "grep:*"
- "cat:*"
- - "head:*"
- - "awk:*"
- - "sed:*"
- - "sort:*"
- edit:
safe-outputs:
create-issue:
expires: 2d
@@ -45,6 +32,98 @@ timeout-minutes: 20
features:
mcp-cli: true
copilot-requests: true
+steps:
+ - name: Collect architecture metrics
+ run: |
+ set -euo pipefail
+ mkdir -p /tmp/gh-aw/agent
+
+ # Read thresholds from .architecture.yml or use defaults
+ FILE_LINES_BLOCKER=1000
+ FILE_LINES_WARNING=500
+ FUNCTION_LINES=80
+ MAX_EXPORTS=10
+
+ if [ -f .architecture.yml ]; then
+ b=$(grep -E '^\s*file_lines_blocker:' .architecture.yml 2>/dev/null | awk '{print $2}' | tr -d '"' | head -1 || true)
+ w=$(grep -E '^\s*file_lines_warning:' .architecture.yml 2>/dev/null | awk '{print $2}' | tr -d '"' | head -1 || true)
+ f=$(grep -E '^\s*function_lines:' .architecture.yml 2>/dev/null | awk '{print $2}' | tr -d '"' | head -1 || true)
+ e=$(grep -E '^\s*max_exports:' .architecture.yml 2>/dev/null | awk '{print $2}' | tr -d '"' | head -1 || true)
+ [[ -n "${b:-}" && "$b" =~ ^[0-9]+$ ]] && FILE_LINES_BLOCKER=$b
+ [[ -n "${w:-}" && "$w" =~ ^[0-9]+$ ]] && FILE_LINES_WARNING=$w
+ [[ -n "${f:-}" && "$f" =~ ^[0-9]+$ ]] && FUNCTION_LINES=$f
+ [[ -n "${e:-}" && "$e" =~ ^[0-9]+$ ]] && MAX_EXPORTS=$e
+ fi
+
+ # Get changed Go/JS files in last 24 hours, excluding tests and vendor paths
+ CHANGED_FILES=$(git log --since="24 hours ago" --name-only --pretty=format: \
+ | sort -u \
+ | grep -E '\.(go|js|cjs|mjs)$' \
+ | grep -vE '(node_modules/|vendor/|\.git/|_test\.go$)' \
+ | while IFS= read -r f; do [ -f "$f" ] && echo "$f"; done \
+ || true)
+
+ if [ -z "$CHANGED_FILES" ]; then
+ jq -n \
+ --argjson blocker "$FILE_LINES_BLOCKER" \
+ --argjson warning "$FILE_LINES_WARNING" \
+ --argjson func_lines "$FUNCTION_LINES" \
+ --argjson max_exports "$MAX_EXPORTS" \
+ '{noop: true, thresholds: {file_lines_blocker: $blocker, file_lines_warning: $warning, function_lines: $func_lines, max_exports: $max_exports}, files: [], import_cycles: ""}' \
+ > /tmp/gh-aw/agent/arch-metrics.json
+ echo "No changed Go/JS files found in the last 24 hours."
+ exit 0
+ fi
+
+ # Build file metrics array
+ FILES_JSON="[]"
+ while IFS= read -r FILE; do
+ [ -z "$FILE" ] && continue
+ LINES=$(wc -l < "$FILE" 2>/dev/null | tr -d ' ' || echo 0)
+ EXT="${FILE##*.}"
+
+ if [[ "$EXT" == "go" ]]; then
+ # Function sizes: "func declaration\tline_count" per function
+ # Pattern matches both regular functions (^func Name) and receiver methods (^func (r *T) Name)
+ FUNC_DATA=$(awk '/^func /{if(start>0 && name!="") printf "%s\t%d\n", name, NR-start; name=$0; start=NR} END{if(start>0 && name!="") printf "%s\t%d\n", name, NR-start+1}' "$FILE" 2>/dev/null | head -50 || true)
+ # Export count and names (top-level exported identifiers start with uppercase)
+ EXPORT_COUNT=$(grep -cE "^func [A-Z]|^type [A-Z]|^var [A-Z]|^const [A-Z]" "$FILE" 2>/dev/null || echo 0)
+ EXPORT_NAMES=$(grep -nE "^func [A-Z]|^type [A-Z]|^var [A-Z]|^const [A-Z]" "$FILE" 2>/dev/null | head -20 || true)
+ else
+ # JS/CJS/MJS: capture named functions, arrow functions, and class methods
+ FUNC_DATA=$(grep -nE "^function |^const [a-zA-Z_$][a-zA-Z0-9_$]* = (function|\(|async \(|async function)|^(export (default )?function|export const [a-zA-Z_$][a-zA-Z0-9_$]* =)|^[a-zA-Z_$][a-zA-Z0-9_$]*\s*\([^)]*\)\s*\{" "$FILE" 2>/dev/null | head -50 || true)
+ CJS_COUNT=$(grep -cE "^module\.exports|^exports\." "$FILE" 2>/dev/null || echo 0)
+ ESM_COUNT=$(grep -cE "^export " "$FILE" 2>/dev/null || echo 0)
+ EXPORT_COUNT=$((CJS_COUNT + ESM_COUNT))
+ EXPORT_NAMES=$(grep -nE "^export |^module\.exports|^exports\." "$FILE" 2>/dev/null | head -20 || true)
+ fi
+
+ FILES_JSON=$(jq \
+ --arg file "$FILE" \
+ --argjson lines "$LINES" \
+ --argjson exports "$EXPORT_COUNT" \
+ --arg func_data "${FUNC_DATA:-}" \
+ --arg export_names "${EXPORT_NAMES:-}" \
+ '. + [{file: $file, lines: $lines, export_count: $exports, func_data: $func_data, export_names: $export_names}]' \
+ <<< "$FILES_JSON")
+ done <<< "$CHANGED_FILES"
+
+ # Check Go import cycles once across all packages
+ # Note: go list may also emit errors for syntax issues; grep filters to only cycle errors
+ IMPORT_CYCLES=$(go list ./... 2>&1 | grep -iE "import cycle|cycle not allowed" || true)
+
+ jq -n \
+ --argjson blocker "$FILE_LINES_BLOCKER" \
+ --argjson warning "$FILE_LINES_WARNING" \
+ --argjson func_lines "$FUNCTION_LINES" \
+ --argjson max_exports "$MAX_EXPORTS" \
+ --argjson files "$FILES_JSON" \
+ --arg import_cycles "$IMPORT_CYCLES" \
+ '{noop: false, thresholds: {file_lines_blocker: $blocker, file_lines_warning: $warning, function_lines: $func_lines, max_exports: $max_exports}, files: $files, import_cycles: $import_cycles}' \
+ > /tmp/gh-aw/agent/arch-metrics.json
+
+ FILE_COUNT=$(echo "$CHANGED_FILES" | wc -l | tr -d ' ')
+ echo "✅ Pre-computed metrics for $FILE_COUNT file(s) → /tmp/gh-aw/agent/arch-metrics.json"
---
# Architecture Guardian
@@ -56,168 +135,56 @@ You are the Architecture Guardian, a code quality agent that enforces structural
- **Analysis Period**: Last 24 hours
- **Run ID**: ${{ github.run_id }}
-## Step 1: Load Configuration
+## Step 1: Read Pre-Computed Metrics
-Read the `.architecture.yml` configuration file if it exists. This file contains configurable thresholds for the analysis.
+All file metrics have been collected by the pre-step. Read the JSON summary:
```bash
-cat .architecture.yml 2>/dev/null || echo "No .architecture.yml found, using defaults"
+cat /tmp/gh-aw/agent/arch-metrics.json
```
-**Default thresholds** (used when `.architecture.yml` is absent or a value is missing):
+The JSON has this structure:
+- `noop` (bool) — `true` when no Go/JS files changed in the last 24 hours
+- `thresholds` — effective thresholds (from `.architecture.yml` or defaults)
+- `files[]` — one entry per changed file with:
+ - `file` — file path
+ - `lines` — total line count
+ - `export_count` — number of exported identifiers
+ - `func_data` — function declarations with sizes (`name\tline_count` per line for Go; line numbers for JS)
+ - `export_names` — list of exported identifier declarations
+- `import_cycles` — output of `go list ./...` filtered for cycle errors (empty if none)
-| Threshold | Default | Config Key |
-|-----------|---------|------------|
-| File size BLOCKER | 1000 lines | `thresholds.file_lines_blocker` |
-| File size WARNING | 500 lines | `thresholds.file_lines_warning` |
-| Function size | 80 lines | `thresholds.function_lines` |
-| Max public exports | 10 | `thresholds.max_exports` |
-
-Parse the YAML values if the file exists. Fall back to defaults for any missing key.
-
-## Step 2: Identify Files Changed in the Last 24 Hours
-
-Use git to find commits from the last 24 hours and the files they touched:
-
-```bash
-git log --since="24 hours ago" --oneline --name-only
-```
-
-Collect the unique set of changed source files:
-
-```bash
-git log --since="24 hours ago" --name-only --pretty=format: | sort -u | grep -E '\.(go|js|cjs|mjs)$'
-```
-
-If no Go or JavaScript files were changed in the last 24 hours, call the `noop` tool and stop:
+If `noop` is `true`, call the `noop` safe-output tool and stop:
```json
{"noop": {"message": "No Go or JavaScript source files changed in the last 24 hours. Architecture scan skipped."}}
```
-Exclude generated files, test fixtures, and vendor directories (e.g., `node_modules/`, `vendor/`, `.git/`, `*_test.go`).
-
-## Step 3: Run Structural Analysis
-
-For each relevant source file, perform the following checks. Collect all violations in a structured list.
-
-### Check 1: File Size
-
-Count lines in each file:
-
-```bash
-wc -l 2>/dev/null
-```
-
-Classify:
-- Lines > `thresholds.file_lines_blocker` (default 1000) → **BLOCKER**
-- Lines > `thresholds.file_lines_warning` (default 500) → **WARNING**
-
-### Check 2: Function Size (Go)
-
-Find Go function declarations and estimate sizes by counting lines between consecutive `func` markers:
-
-```bash
-# List all func declaration line numbers in a Go file
-grep -n "^func "
-```
-
-Use the line numbers to estimate each function's length. For a more precise count, use `awk`:
-
-```bash
-awk '/^func /{if(start>0) print name, NR-start; name=$0; start=NR} END{if(start>0) print name, NR-start+1}'
-```
-
-Functions exceeding `thresholds.function_lines` (default 80) → **WARNING**
-
-### Check 3: Function Size (JavaScript / CommonJS)
-
-Approximate function sizes in `.js` / `.cjs` / `.mjs` files using grep:
-
-```bash
-# List function declaration line numbers
-grep -n "^function \|^const .* = function\|^const .* = ("
-```
-
-Count lines between consecutive function declarations to estimate length. Functions exceeding `thresholds.function_lines` (default 80) → **WARNING**
+## Step 2: Classify Violations by Severity
-### Check 4: High Public Export Count (Go)
+Using the pre-computed data, classify all findings into three severity tiers.
-In Go, exported identifiers start with an uppercase letter. Count exported top-level functions, types, variables, and constants:
+**Default thresholds** (used when `.architecture.yml` is absent):
-```bash
-# Count exported top-level declarations in a Go file
-grep -c "^func [A-Z]\|^type [A-Z]\|^var [A-Z]\|^const [A-Z]"
-
-# List them for reporting
-grep -n "^func [A-Z]\|^type [A-Z]\|^var [A-Z]\|^const [A-Z]"
-```
-
-For JavaScript files, count module-level exports:
-
-```bash
-# CommonJS
-grep -c "^module\.exports\|^exports\."
-
-# ES modules
-grep -c "^export "
-```
-
-Files with more than `thresholds.max_exports` (default 10) public names → **INFO**
-
-### Check 5: Import Cycles (Go)
-
-Go's toolchain detects import cycles at build time. Use `go list` to surface any cycles across all packages:
-
-```bash
-go list ./... 2>&1 | grep -i "import cycle\|cycle not allowed"
-```
-
-Alternatively, use `go build` which also reports cycles:
-
-```bash
-go build ./... 2>&1 | grep -i "import cycle\|cycle not allowed"
-```
-
-Any output from these commands indicates a circular import dependency → **BLOCKER**
-
-For JavaScript files, detect circular `require()` chains by grepping for cross-file imports and checking for mutual dependencies:
-
-```bash
-# Find all require() calls pointing to local modules
-grep -rn "require('\.\./\|\./" --include="*.js" --include="*.cjs"
-```
-
-Circular dependency cycles → **BLOCKER**
-
-## Step 4: Classify Violations by Severity
-
-Group all findings into three severity tiers:
+| Threshold | Default | Config Key |
+|-----------|---------|------------|
+| File size BLOCKER | 1000 lines | `thresholds.file_lines_blocker` |
+| File size WARNING | 500 lines | `thresholds.file_lines_warning` |
+| Function size | 80 lines | `thresholds.function_lines` |
+| Max public exports | 10 | `thresholds.max_exports` |
### BLOCKER (critical — must be addressed promptly)
-- Circular import / dependency cycles between Go packages
-- Files exceeding 1000 lines (configurable)
+- Non-empty `import_cycles` field → import cycle detected
+- `files[].lines` > `thresholds.file_lines_blocker` (default 1000)
### WARNING (should be addressed soon)
-- Files exceeding 500 lines (configurable)
-- Functions/methods exceeding 80 lines (configurable)
+- `files[].lines` > `thresholds.file_lines_warning` (default 500)
+- Any function in `files[].func_data` with line count > `thresholds.function_lines` (default 80)
### INFO (informational only)
-- Files with more than 10 public exports (configurable)
-
-## Step 5: Generate AI Refactoring Suggestions
-
-For each **BLOCKER** and **WARNING** violation, generate a concise refactoring suggestion that explains:
-
-1. **What the violation is** — e.g., "`pkg/workflow/compiler.go` has 1,247 lines"
-2. **Why it's a problem** — e.g., "Large files are harder to navigate, review, and maintain"
-3. **A concrete plan to fix it** — e.g., "Extract the expression-extraction logic into `pkg/workflow/expression_extraction.go` and move YAML helpers into `pkg/workflow/compiler_yaml.go`"
+- `files[].export_count` > `thresholds.max_exports` (default 10)
-Use your knowledge of software architecture best practices. Be specific and actionable.
-
-For **INFO** violations, provide a brief note about the high export count and suggest whether the module might benefit from splitting.
-
-## Step 6: Post Report
+## Step 3: Post Report
### If NO violations are found
@@ -231,6 +198,8 @@ Call the `noop` safe-output tool:
Create an issue with a structured report. Only create ONE issue (the `max: 1` limit applies and an existing open issue skips the run via `skip-if-match`).
+Replace all `[PLACEHOLDER]` values with actual data from the pre-computed metrics JSON, and replace `N` with actual counts.
+
**Issue title**: Architecture Violations Detected — [DATE]
**Issue body format**:
@@ -255,13 +224,8 @@ Create an issue with a structured report. Only create ONE issue (the `max: 1` li
> These violations indicate serious structural problems that require prompt attention.
-#### [Violation Title]
-
-**File**: `path/to/file.go`
-**Commit**: [sha] — [commit message]
-**Issue**: [Description of the problem]
-**Why it matters**: [Explanation]
-**Suggested fix**: [Concrete refactoring plan]
+- `path/to/file.go` — N lines (limit: 1000) · **Fix**: split into focused sub-files, one responsibility per file
+- Import cycle detected: [cycle description] · **Fix**: introduce an interface or move shared types to a lower-level package
---
@@ -269,12 +233,8 @@ Create an issue with a structured report. Only create ONE issue (the `max: 1` li
> These violations should be addressed soon to prevent further structural debt.
-#### [Violation Title]
-
-**File**: `path/to/file.go` | **Function**: `FunctionName` | **Lines**: N
-**Commit**: [sha] — [commit message]
-**Issue**: [Description]
-**Suggested fix**: [Concrete refactoring plan]
+- `path/to/file.go` — N lines (limit: 500) · **Fix**: extract related functions into a new file
+- `path/to/file.go::FunctionName` — N lines (limit: 80) · **Fix**: decompose into smaller helper functions
---
@@ -282,13 +242,13 @@ Create an issue with a structured report. Only create ONE issue (the `max: 1` li
> Informational findings. Consider addressing in future refactoring.
-- `path/to/file.go`: N exported identifiers — consider splitting into focused packages or sub-packages
+- `path/to/file.go`: N exported identifiers (limit: 10) — consider splitting into focused packages
---
### Configuration
-Thresholds from `.architecture.yml` (or defaults):
+Thresholds (from `.architecture.yml` or defaults):
- File size BLOCKER: N lines
- File size WARNING: N lines
- Function size: N lines
diff --git a/docs/src/content/docs/agent-factory-status.mdx b/docs/src/content/docs/agent-factory-status.mdx
index 16086b0063c..91162f03b61 100644
--- a/docs/src/content/docs/agent-factory-status.mdx
+++ b/docs/src/content/docs/agent-factory-status.mdx
@@ -16,6 +16,7 @@ These are experimental agentic workflows used by the GitHub Next team to learn,
| [Agent Performance Analyzer - Meta-Orchestrator](https://github.com/github/gh-aw/blob/main/.github/workflows/agent-performance-analyzer.md) | copilot | [](https://github.com/github/gh-aw/actions/workflows/agent-performance-analyzer.lock.yml) | - | - |
| [Agent Persona Explorer](https://github.com/github/gh-aw/blob/main/.github/workflows/agent-persona-explorer.md) | copilot | [](https://github.com/github/gh-aw/actions/workflows/agent-persona-explorer.lock.yml) | - | - |
| [Agentic Observability Kit](https://github.com/github/gh-aw/blob/main/.github/workflows/agentic-observability-kit.md) | copilot | [](https://github.com/github/gh-aw/actions/workflows/agentic-observability-kit.lock.yml) | - | - |
+| [Agentic Optimization Kit](https://github.com/github/gh-aw/blob/main/.github/workflows/agentic-optimization-kit.md) | copilot | [](https://github.com/github/gh-aw/actions/workflows/agentic-optimization-kit.lock.yml) | - | - |
| [Agentic Workflow Audit Agent](https://github.com/github/gh-aw/blob/main/.github/workflows/audit-workflows.md) | claude | [](https://github.com/github/gh-aw/actions/workflows/audit-workflows.lock.yml) | - | - |
| [AI Moderator](https://github.com/github/gh-aw/blob/main/.github/workflows/ai-moderator.md) | codex | [](https://github.com/github/gh-aw/actions/workflows/ai-moderator.lock.yml) | - | - |
| [Approach Validator](https://github.com/github/gh-aw/blob/main/.github/workflows/approach-validator.md) | claude | [](https://github.com/github/gh-aw/actions/workflows/approach-validator.lock.yml) | - | - |
@@ -85,10 +86,12 @@ These are experimental agentic workflows used by the GitHub Next team to learn,
| [Daily Secrets Analysis Agent](https://github.com/github/gh-aw/blob/main/.github/workflows/daily-secrets-analysis.md) | copilot | [](https://github.com/github/gh-aw/actions/workflows/daily-secrets-analysis.lock.yml) | - | - |
| [Daily Security Red Team Agent](https://github.com/github/gh-aw/blob/main/.github/workflows/daily-security-red-team.md) | claude | [](https://github.com/github/gh-aw/actions/workflows/daily-security-red-team.lock.yml) | - | - |
| [Daily Semgrep Scan](https://github.com/github/gh-aw/blob/main/.github/workflows/daily-semgrep-scan.md) | copilot | [](https://github.com/github/gh-aw/actions/workflows/daily-semgrep-scan.lock.yml) | - | - |
+| [Daily Skill Optimizer Improvements](https://github.com/github/gh-aw/blob/main/.github/workflows/daily-skill-optimizer.md) | copilot | [](https://github.com/github/gh-aw/actions/workflows/daily-skill-optimizer.lock.yml) | - | - |
| [Daily Syntax Error Quality Check](https://github.com/github/gh-aw/blob/main/.github/workflows/daily-syntax-error-quality.md) | copilot | [](https://github.com/github/gh-aw/actions/workflows/daily-syntax-error-quality.lock.yml) | - | - |
| [Daily Team Evolution Insights](https://github.com/github/gh-aw/blob/main/.github/workflows/daily-team-evolution-insights.md) | claude | [](https://github.com/github/gh-aw/actions/workflows/daily-team-evolution-insights.lock.yml) | - | - |
| [Daily Team Status](https://github.com/github/gh-aw/blob/main/.github/workflows/daily-team-status.md) | copilot | [](https://github.com/github/gh-aw/actions/workflows/daily-team-status.lock.yml) | `daily around 9:00 on weekdays` | - |
| [Daily Testify Uber Super Expert](https://github.com/github/gh-aw/blob/main/.github/workflows/daily-testify-uber-super-expert.md) | copilot | [](https://github.com/github/gh-aw/actions/workflows/daily-testify-uber-super-expert.lock.yml) | - | - |
+| [Daily Token Consumption Report (Sentry OTel)](https://github.com/github/gh-aw/blob/main/.github/workflows/daily-token-consumption-report.md) | claude | [](https://github.com/github/gh-aw/actions/workflows/daily-token-consumption-report.lock.yml) | - | - |
| [Daily Workflow Updater](https://github.com/github/gh-aw/blob/main/.github/workflows/daily-workflow-updater.md) | copilot | [](https://github.com/github/gh-aw/actions/workflows/daily-workflow-updater.lock.yml) | - | - |
| [Dead Code Removal Agent](https://github.com/github/gh-aw/blob/main/.github/workflows/dead-code-remover.md) | copilot | [](https://github.com/github/gh-aw/actions/workflows/dead-code-remover.lock.yml) | - | - |
| [DeepReport - Intelligence Gathering Agent](https://github.com/github/gh-aw/blob/main/.github/workflows/deep-report.md) | claude | [](https://github.com/github/gh-aw/actions/workflows/deep-report.lock.yml) | `daily around 15:00 on weekdays` | - |
diff --git a/docs/src/content/docs/reference/frontmatter-full.md b/docs/src/content/docs/reference/frontmatter-full.md
index c11bd3d2578..e3405f2e3f2 100644
--- a/docs/src/content/docs/reference/frontmatter-full.md
+++ b/docs/src/content/docs/reference/frontmatter-full.md
@@ -899,6 +899,12 @@ on:
# Option 2: undefined
+ # Explicit additional custom workflow jobs that pre_activation and activation
+ # should depend on.
+ # (optional)
+ needs: []
+ # Array of strings
+
# Steps to inject into the pre-activation job. These steps run after all built-in
# checks (membership, stop-time, skip-if, etc.) and their results are exposed as
# pre-activation outputs. Use 'id' on steps to reference their results via
@@ -983,11 +989,6 @@ on:
# (optional)
statuses: "read"
- # Explicit additional custom workflow jobs that pre_activation and activation
- # should depend on.
- # (optional)
- needs: ["secrets_fetcher"]
-
# When set to false, disables the frontmatter hash check step in the activation
# job. Default is true (check is enabled). Useful when the workflow source files
# are managed outside the default GitHub repo context (e.g. cross-repo org
@@ -1469,8 +1470,8 @@ pre-steps:
pre-steps: []
# Array items: undefined
-# Custom workflow steps to run before MCP gateway startup in the agent job,
-# so prerequisite MCP installation/configuration can happen first.
+# Custom workflow steps to run immediately before AI execution, after all
+# initialization and setup steps in the agent job.
# (optional)
# This field supports multiple formats (oneOf):
@@ -3488,6 +3489,13 @@ safe-outputs:
assignees: []
# Array items: string
+ # Optional labels to apply to fallback issues created when pull request creation
+ # cannot proceed. When omitted, fallback issues reuse pull request labels. A
+ # managed label is always added for triage.
+ # (optional)
+ fallback-labels: []
+ # Array of strings
+
# Whether to create pull request as draft (defaults to true). Accepts a boolean or
# a GitHub Actions expression.
# (optional)