diff --git a/.github/workflows/auto-triage-issues.lock.yml b/.github/workflows/auto-triage-issues.lock.yml
index dee80b3908e..75e04625d43 100644
--- a/.github/workflows/auto-triage-issues.lock.yml
+++ b/.github/workflows/auto-triage-issues.lock.yml
@@ -1,4 +1,4 @@
-# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"25ba385233ac59f16b778a09c4c4c4b85d046210322ff53ddd44d988cb26caa5","strict":true,"agent_id":"copilot","agent_model":"gpt-5-mini"}
+# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"44ee7fb4de16d0d981ae932dfa32c8560c65a9fade7a3563dde246dcd7e4c9c6","strict":true,"agent_id":"copilot","agent_model":"gpt-5-mini"}
# gh-aw-manifest: {"version":1,"secrets":["GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_ENDPOINT","GH_AW_OTEL_HEADERS","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.42"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.42"},{"image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.42"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.42"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.6","digest":"sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c"},{"image":"ghcr.io/github/github-mcp-server:v1.0.3","digest":"sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]}
# ___ _ _
# / _ \ | | (_)
@@ -213,20 +213,20 @@ jobs:
run: |
bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh"
{
- cat << 'GH_AW_PROMPT_22c0a58162bb6a9d_EOF'
+ cat << 'GH_AW_PROMPT_11cff80b0d29c151_EOF'
- GH_AW_PROMPT_22c0a58162bb6a9d_EOF
+ GH_AW_PROMPT_11cff80b0d29c151_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_22c0a58162bb6a9d_EOF'
+ cat << 'GH_AW_PROMPT_11cff80b0d29c151_EOF'
Tools: create_discussion, add_labels(max:10), missing_tool, missing_data, noop
- GH_AW_PROMPT_22c0a58162bb6a9d_EOF
+ GH_AW_PROMPT_11cff80b0d29c151_EOF
cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md"
- cat << 'GH_AW_PROMPT_22c0a58162bb6a9d_EOF'
+ cat << 'GH_AW_PROMPT_11cff80b0d29c151_EOF'
The following GitHub context information is available for this workflow:
{{#if __GH_AW_GITHUB_ACTOR__ }}
@@ -255,16 +255,16 @@ jobs:
{{/if}}
- GH_AW_PROMPT_22c0a58162bb6a9d_EOF
+ GH_AW_PROMPT_11cff80b0d29c151_EOF
cat "${RUNNER_TEMP}/gh-aw/prompts/cli_proxy_with_safeoutputs_prompt.md"
- cat << 'GH_AW_PROMPT_22c0a58162bb6a9d_EOF'
+ cat << 'GH_AW_PROMPT_11cff80b0d29c151_EOF'
{{#runtime-import .github/workflows/shared/github-guard-policy.md}}
{{#runtime-import .github/workflows/shared/reporting.md}}
{{#runtime-import .github/workflows/shared/observability-otlp.md}}
{{#runtime-import .github/workflows/shared/noop-reminder.md}}
{{#runtime-import .github/workflows/auto-triage-issues.md}}
- GH_AW_PROMPT_22c0a58162bb6a9d_EOF
+ GH_AW_PROMPT_11cff80b0d29c151_EOF
} > "$GH_AW_PROMPT"
- name: Interpolate variables and render templates
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
@@ -500,9 +500,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_ad7601bdf062f098_EOF'
+ cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_2243e03bdea2bf84_EOF'
{"add_labels":{"max":10},"create_discussion":{"category":"audits","close_older_discussions":true,"expires":24,"fallback_to_issue":true,"max":1,"title_prefix":"[Auto-Triage] "},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}}
- GH_AW_SAFE_OUTPUTS_CONFIG_ad7601bdf062f098_EOF
+ GH_AW_SAFE_OUTPUTS_CONFIG_2243e03bdea2bf84_EOF
- name: Generate Safe Outputs Tools
env:
GH_AW_TOOLS_META_JSON: |
@@ -714,7 +714,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_565c3d3852153a7c_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs"
+ cat << GH_AW_MCP_CONFIG_dc1e7d443e156803_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs"
{
"mcpServers": {
"safeoutputs": {
@@ -745,7 +745,7 @@ jobs:
}
}
}
- GH_AW_MCP_CONFIG_565c3d3852153a7c_EOF
+ GH_AW_MCP_CONFIG_dc1e7d443e156803_EOF
- name: Mount MCP servers as CLIs
id: mount-mcp-clis
continue-on-error: true
diff --git a/.github/workflows/auto-triage-issues.md b/.github/workflows/auto-triage-issues.md
index ed0c3669e09..d94eb79520b 100644
--- a/.github/workflows/auto-triage-issues.md
+++ b/.github/workflows/auto-triage-issues.md
@@ -53,6 +53,7 @@ safe-outputs:
category: "audits"
close-older-discussions: true
max: 1
+ noop:
timeout-minutes: 15
features:
copilot-requests: true
@@ -97,9 +98,13 @@ When running on schedule:
When triggered manually as a backfill pass:
1. **Fetch ALL open issues without any labels** using GitHub tools — do not limit to a fixed count
-2. **Process up to 10 unlabeled issues** in this run (respecting safe-output limits); if more exist, note the remainder in the report
-3. **Apply labels** to each issue based on classification rules below, using title/body heuristics and existing triage rules
-4. **Create a summary report** as a discussion listing every issue processed, the labels applied, and how many unlabeled issues (if any) still remain for the next pass
+2. **If there are no unlabeled issues**, call `noop` with "No unlabeled issues found during manual backfill — no action needed" and stop. Do not create a discussion.
+
+When unlabeled issues exist:
+
+3. **Process up to 10 unlabeled issues** in this run (respecting safe-output limits); if more exist, note the remainder in the report
+4. **Apply labels** to each issue based on classification rules below, using title/body heuristics and existing triage rules
+5. **Create a summary report** as a discussion listing every issue processed, the labels applied, and how many unlabeled issues (if any) still remain for the next pass
## Classification Rules
@@ -287,6 +292,16 @@ When running on schedule, create a discussion report following these formatting
- **Learn from patterns** - Over time, notice which types of issues are frequently unlabeled
- **Human override** - Maintainers can change labels; this is automation assistance, not replacement
+## Mandatory Completion Rule
+
+**Before finishing, check whether you called any safe-output tool in this run.** If you did NOT call `add_labels` or `create_discussion`, you MUST call `noop`. Every run MUST end with at least one safe-output call — failing to do so causes the workflow to fail with a safe-output compliance error.
+
+Situations that require a `noop` call:
+- No unlabeled issues were found (all trigger types)
+- The triggering issue already had appropriate labels
+- All issues analyzed were already labeled or had been processed
+- You were uncertain and chose not to label rather than guess incorrectly
+
## Success Metrics
- Reduce unlabeled issue percentage from 8.6% to <5%
diff --git a/.github/workflows/unbloat-docs.lock.yml b/.github/workflows/unbloat-docs.lock.yml
index 49acd0434cb..97cda0479c1 100644
--- a/.github/workflows/unbloat-docs.lock.yml
+++ b/.github/workflows/unbloat-docs.lock.yml
@@ -1,4 +1,4 @@
-# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"74cfec818687614eb034b1fcb3b261722ba9804a51ecc2ed6cef09ac0e0c6515","strict":true,"agent_id":"claude"}
+# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"7f58bc4a3041899fa0a0d8e5845e1b89e4f77795d39e817841e96332573b3e0e","strict":true,"agent_id":"claude"}
# gh-aw-manifest: {"version":1,"secrets":["ANTHROPIC_API_KEY","GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_ENDPOINT","GH_AW_OTEL_HEADERS","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.42"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.42"},{"image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.42"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.42"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.6","digest":"sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c"},{"image":"ghcr.io/github/github-mcp-server:v1.0.3","digest":"sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]}
# ___ _ _
# / _ \ | | (_)
@@ -256,27 +256,27 @@ jobs:
run: |
bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh"
{
- cat << 'GH_AW_PROMPT_4c45bf75252ca186_EOF'
+ cat << 'GH_AW_PROMPT_9189f0a2e98a4f36_EOF'
- GH_AW_PROMPT_4c45bf75252ca186_EOF
+ GH_AW_PROMPT_9189f0a2e98a4f36_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/playwright_prompt.md"
cat "${RUNNER_TEMP}/gh-aw/prompts/cache_memory_prompt.md"
cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md"
- cat << 'GH_AW_PROMPT_4c45bf75252ca186_EOF'
+ cat << 'GH_AW_PROMPT_9189f0a2e98a4f36_EOF'
Tools: add_comment, create_pull_request, upload_asset(max:10), missing_tool, missing_data, noop
- GH_AW_PROMPT_4c45bf75252ca186_EOF
+ GH_AW_PROMPT_9189f0a2e98a4f36_EOF
cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_create_pull_request.md"
- cat << 'GH_AW_PROMPT_4c45bf75252ca186_EOF'
+ cat << 'GH_AW_PROMPT_9189f0a2e98a4f36_EOF'
upload_asset: provide a file path; returns a URL; assets are published after the workflow completes (safeoutputs).
- GH_AW_PROMPT_4c45bf75252ca186_EOF
+ GH_AW_PROMPT_9189f0a2e98a4f36_EOF
cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md"
- cat << 'GH_AW_PROMPT_4c45bf75252ca186_EOF'
+ cat << 'GH_AW_PROMPT_9189f0a2e98a4f36_EOF'
The following GitHub context information is available for this workflow:
{{#if __GH_AW_GITHUB_ACTOR__ }}
@@ -305,9 +305,9 @@ jobs:
{{/if}}
- GH_AW_PROMPT_4c45bf75252ca186_EOF
+ GH_AW_PROMPT_9189f0a2e98a4f36_EOF
cat "${RUNNER_TEMP}/gh-aw/prompts/cli_proxy_with_safeoutputs_prompt.md"
- cat << 'GH_AW_PROMPT_4c45bf75252ca186_EOF'
+ cat << 'GH_AW_PROMPT_9189f0a2e98a4f36_EOF'
{{#runtime-import .github/workflows/shared/docs-server-lifecycle.md}}
{{#runtime-import .github/workflows/shared/observability-otlp.md}}
@@ -315,7 +315,7 @@ jobs:
{{#runtime-import .github/workflows/shared/reporting.md}}
{{#runtime-import .github/workflows/shared/noop-reminder.md}}
{{#runtime-import .github/workflows/unbloat-docs.md}}
- GH_AW_PROMPT_4c45bf75252ca186_EOF
+ GH_AW_PROMPT_9189f0a2e98a4f36_EOF
} > "$GH_AW_PROMPT"
- name: Interpolate variables and render templates
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
@@ -567,11 +567,11 @@ jobs:
- name: Pre-flight checks
run: "mkdir -p /tmp/gh-aw/agent\n\n# Check 1: verify docs directory structure exists\nDIR_COUNT=$(find docs/src/content/docs -maxdepth 1 -type d 2>/dev/null | wc -l)\nif [ \"$DIR_COUNT\" -eq 0 ]; then\n echo '{\"pass\":false,\"reason\":\"Pre-flight failed: docs/src/content/docs directory not found — documentation structure is missing or repository is not set up correctly.\"}' \\\n > /tmp/gh-aw/agent/preflight.json\n exit 0\nfi\n\n# Check 2: count editable markdown files\nTOTAL=$(find docs/src/content/docs -path '*/blog*' -prune \\\n -o -name '*.md' -type f ! -name 'frontmatter-full.md' -print \\\n | xargs grep -rL 'disable-agentic-editing: true' 2>/dev/null \\\n | wc -l)\nif [ \"$TOTAL\" -eq 0 ]; then\n echo '{\"pass\":false,\"reason\":\"Pre-flight failed: no editable markdown files found in docs/src/content/docs (all files may be protected or excluded).\"}' \\\n > /tmp/gh-aw/agent/preflight.json\n exit 0\nfi\n\n# Check 3: count uncleaned candidates (not cleaned in the past 7 days)\nRECENT_CUTOFF=$(date -d '7 days ago' '+%Y-%m-%d' 2>/dev/null \\\n || date -v-7d '+%Y-%m-%d' 2>/dev/null \\\n || echo \"0000-00-00\")\nCLEANED=$(awk -v cutoff=\"$RECENT_CUTOFF\" \\\n 'NF>0 && $1>=cutoff{count++} END{print count+0}' \\\n /tmp/gh-aw/cache-memory/cleaned-files.txt 2>/dev/null || echo \"0\")\nUNCLEANED=$(( TOTAL - CLEANED ))\nif [ \"$UNCLEANED\" -le 0 ]; then\n echo '{\"pass\":false,\"reason\":\"Pre-flight check: all eligible documentation files were cleaned recently — nothing to do this run.\"}' \\\n > /tmp/gh-aw/agent/preflight.json\n exit 0\nfi\n\n# All checks passed — write candidate file list and preflight result\nfind docs/src/content/docs -path '*/blog*' -prune \\\n -o -name '*.md' -type f ! -name 'frontmatter-full.md' -print \\\n | xargs grep -rL 'disable-agentic-editing: true' 2>/dev/null \\\n > /tmp/gh-aw/agent/candidate-files.txt\nprintf '{\"pass\":true,\"reason\":\"All pre-flight checks passed. %d uncleaned candidates available.\",\"uncleaned\":%d,\"total\":%d}\\n' \\\n \"$UNCLEANED\" \"$UNCLEANED\" \"$TOTAL\" \\\n > /tmp/gh-aw/agent/preflight.json\n\necho \"Pre-flight passed: $UNCLEANED uncleaned candidates out of $TOTAL eligible files\"\necho \"Candidate files written to /tmp/gh-aw/agent/candidate-files.txt\"\n"
- name: Start documentation dev server
- run: "mkdir -p /tmp/gh-aw\ncd docs\nnohup npm run dev -- --host 0.0.0.0 --port 4321 > /tmp/gh-aw/preview.log 2>&1 &\nPID=$!\necho $PID > /tmp/gh-aw/server.pid\necho \"Dev server started (PID: $PID)\"\n"
+ run: "# Skip if pre-flight check failed — no need to start the server\nif [ \"$(jq -r '.pass' /tmp/gh-aw/agent/preflight.json 2>/dev/null)\" != \"true\" ]; then\n echo \"Pre-flight check failed, skipping server startup\"\n exit 0\nfi\nmkdir -p /tmp/gh-aw\ncd docs\nnohup npm run dev -- --host 0.0.0.0 --port 4321 > /tmp/gh-aw/preview.log 2>&1 &\nPID=$!\necho $PID > /tmp/gh-aw/server.pid\necho \"Dev server started (PID: $PID)\"\n"
- name: Wait for documentation server readiness
- run: "URL=\"http://localhost:4321/gh-aw/\"\nSTATUS=\"\"\necho \"Readiness check target: $URL\"\necho \"Preview log: /tmp/gh-aw/preview.log\"\nfor i in $(seq 1 45); do\n STATUS=$(curl -sS -o /dev/null -w \"%{http_code}\" --connect-timeout 5 --max-time 5 \"$URL\" || true)\n [ \"$STATUS\" = \"200\" ] && echo \"Server ready at $URL\" && break\n if [ -z \"$STATUS\" ]; then STATUS=\"curl_error\"; fi\n echo \"Waiting for server... ($i/45) (status: $STATUS)\"\n sleep 3\ndone\nif [ \"$STATUS\" != \"200\" ]; then\n echo \"Dev server failed to start after 135 seconds:\"\n echo \"Final readiness status: $STATUS\"\n cat /tmp/gh-aw/preview.log || true\n exit 1\nfi\n"
+ run: "# Skip if pre-flight check failed — server was not started\nif [ \"$(jq -r '.pass' /tmp/gh-aw/agent/preflight.json 2>/dev/null)\" != \"true\" ]; then\n echo \"Pre-flight check failed, skipping server readiness check\"\n exit 0\nfi\nURL=\"http://localhost:4321/gh-aw/\"\nSTATUS=\"\"\necho \"Readiness check target: $URL\"\necho \"Preview log: /tmp/gh-aw/preview.log\"\nfor i in $(seq 1 45); do\n STATUS=$(curl -sS -o /dev/null -w \"%{http_code}\" --connect-timeout 5 --max-time 5 \"$URL\" || true)\n [ \"$STATUS\" = \"200\" ] && echo \"Server ready at $URL\" && break\n if [ -z \"$STATUS\" ]; then STATUS=\"curl_error\"; fi\n echo \"Waiting for server... ($i/45) (status: $STATUS)\"\n sleep 3\ndone\nif [ \"$STATUS\" != \"200\" ]; then\n echo \"Dev server failed to start after 135 seconds:\"\n echo \"Final readiness status: $STATUS\"\n cat /tmp/gh-aw/preview.log || true\n exit 1\nfi\n"
- name: Write Playwright base URL
- run: "mkdir -p /tmp/gh-aw/agent\necho \"http://localhost:4321/gh-aw/\" > /tmp/gh-aw/agent/playwright-base-url.txt\necho \"Playwright base URL: http://localhost:4321/gh-aw/\"\n"
+ run: "# Skip if pre-flight check failed — server was not started\nif [ \"$(jq -r '.pass' /tmp/gh-aw/agent/preflight.json 2>/dev/null)\" != \"true\" ]; then\n echo \"Pre-flight check failed, skipping Playwright base URL setup\"\n exit 0\nfi\nmkdir -p /tmp/gh-aw/agent\necho \"http://localhost:4321/gh-aw/\" > /tmp/gh-aw/agent/playwright-base-url.txt\necho \"Playwright base URL: http://localhost:4321/gh-aw/\"\n"
- name: Download container images
run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.25.42 ghcr.io/github/gh-aw-firewall/api-proxy:0.25.42 ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.42 ghcr.io/github/gh-aw-firewall/squid:0.25.42 ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959 node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f
@@ -582,9 +582,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_f296a80275c5ed4e_EOF
+ cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << GH_AW_SAFE_OUTPUTS_CONFIG_1b9d75dd88ccaf40_EOF
{"add_comment":{"max":1},"create_pull_request":{"auto_merge":true,"draft":true,"expires":48,"fallback_as_issue":false,"labels":["documentation","automation","doc-unbloat"],"max":1,"max_patch_files":100,"max_patch_size":1024,"protect_top_level_dot_folders":true,"protected_files":["package.json","bun.lockb","bunfig.toml","deno.json","deno.jsonc","deno.lock","global.json","NuGet.Config","Directory.Packages.props","mix.exs","mix.lock","go.mod","go.sum","stack.yaml","stack.yaml.lock","pom.xml","build.gradle","build.gradle.kts","settings.gradle","settings.gradle.kts","gradle.properties","package-lock.json","yarn.lock","pnpm-lock.yaml","npm-shrinkwrap.json","requirements.txt","Pipfile","Pipfile.lock","pyproject.toml","setup.py","setup.cfg","Gemfile","Gemfile.lock","uv.lock","CODEOWNERS","DESIGN.md","README.md","CONTRIBUTING.md","CHANGELOG.md","SECURITY.md","CODE_OF_CONDUCT.md","CLAUDE.md","AGENTS.md"],"reviewers":["copilot"],"title_prefix":"[docs] "},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{},"upload_asset":{"allowed-exts":[".png",".jpg",".jpeg",".svg"],"branch":"assets/${GITHUB_WORKFLOW}","max":10,"max-size":10240}}
- GH_AW_SAFE_OUTPUTS_CONFIG_f296a80275c5ed4e_EOF
+ GH_AW_SAFE_OUTPUTS_CONFIG_1b9d75dd88ccaf40_EOF
- name: Generate Safe Outputs Tools
env:
GH_AW_TOOLS_META_JSON: |
@@ -826,7 +826,7 @@ jobs:
export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v /var/run/docker.sock:/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -e GITHUB_AW_OTEL_TRACE_ID -e GITHUB_AW_OTEL_PARENT_SPAN_ID -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.3.6'
GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node)
- cat << GH_AW_MCP_CONFIG_4d4edb42845b5641_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs"
+ cat << GH_AW_MCP_CONFIG_370d51e4f92ff7c4_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs"
{
"mcpServers": {
"safeoutputs": {
@@ -857,7 +857,7 @@ jobs:
}
}
}
- GH_AW_MCP_CONFIG_4d4edb42845b5641_EOF
+ GH_AW_MCP_CONFIG_370d51e4f92ff7c4_EOF
- name: Mount MCP servers as CLIs
id: mount-mcp-clis
continue-on-error: true
diff --git a/.github/workflows/unbloat-docs.md b/.github/workflows/unbloat-docs.md
index 3212773ee04..ed7cf9f6e87 100644
--- a/.github/workflows/unbloat-docs.md
+++ b/.github/workflows/unbloat-docs.md
@@ -172,6 +172,11 @@ pre-agent-steps:
- name: Start documentation dev server
run: |
+ # Skip if pre-flight check failed — no need to start the server
+ if [ "$(jq -r '.pass' /tmp/gh-aw/agent/preflight.json 2>/dev/null)" != "true" ]; then
+ echo "Pre-flight check failed, skipping server startup"
+ exit 0
+ fi
mkdir -p /tmp/gh-aw
cd docs
nohup npm run dev -- --host 0.0.0.0 --port 4321 > /tmp/gh-aw/preview.log 2>&1 &
@@ -181,6 +186,11 @@ pre-agent-steps:
- name: Wait for documentation server readiness
run: |
+ # Skip if pre-flight check failed — server was not started
+ if [ "$(jq -r '.pass' /tmp/gh-aw/agent/preflight.json 2>/dev/null)" != "true" ]; then
+ echo "Pre-flight check failed, skipping server readiness check"
+ exit 0
+ fi
URL="http://localhost:4321/gh-aw/"
STATUS=""
echo "Readiness check target: $URL"
@@ -201,6 +211,11 @@ pre-agent-steps:
- name: Write Playwright base URL
run: |
+ # Skip if pre-flight check failed — server was not started
+ if [ "$(jq -r '.pass' /tmp/gh-aw/agent/preflight.json 2>/dev/null)" != "true" ]; then
+ echo "Pre-flight check failed, skipping Playwright base URL setup"
+ exit 0
+ fi
mkdir -p /tmp/gh-aw/agent
echo "http://localhost:4321/gh-aw/" > /tmp/gh-aw/agent/playwright-base-url.txt
echo "Playwright base URL: http://localhost:4321/gh-aw/"
@@ -237,7 +252,7 @@ You are a technical documentation editor focused on **clarity and conciseness**.
## 0. Pre-flight Validation
-Read `/tmp/gh-aw/agent/preflight.json`. If `"pass"` is `false`, call `noop` with the `"reason"` value and stop.
+Read `/tmp/gh-aw/agent/preflight.json`. If `"pass"` is `false`, **immediately** call `noop` with the `"reason"` value and stop — do not read any other files beyond `preflight.json`, do not proceed with any further steps. This is mandatory: failing to call `noop` when preflight fails causes a safe-output compliance error.
Only proceed if `"pass"` is `true`.
The list of candidate files is already available at `/tmp/gh-aw/agent/candidate-files.txt` (one path per line).