diff --git a/.github/workflows/api-consumption-report.md b/.github/workflows/api-consumption-report.md
index b9b6263cfc5..5e237147b87 100644
--- a/.github/workflows/api-consumption-report.md
+++ b/.github/workflows/api-consumption-report.md
@@ -152,6 +152,18 @@ Example structure:
## Step 3 — Update Cache-Memory Trending History
+**Cache validation**: Before appending, check whether the cache was restored from a previous run:
+
+```bash
+history_file="/tmp/gh-aw/cache-memory/trending/api-consumption/history.jsonl"
+if [ -f "$history_file" ] && [ -s "$history_file" ]; then
+ entry_count=$(wc -l < "$history_file")
+ echo "Cache restored from previous run: yes ($entry_count existing entries)"
+else
+ echo "Cache restored from previous run: no (first run or empty cache)"
+fi
+```
+
Append today's summary to the rolling history file:
```
@@ -405,6 +417,7 @@ Create a discussion with the following structure. Replace placeholders with real
📦 Cache Memory Status
- **Location**: `/tmp/gh-aw/cache-memory/trending/api-consumption/history.jsonl`
+- **Cache restored from previous run**: {yes (N entries) / no (first run)}
- **Data points stored**: {data_points}
- **Earliest entry**: {earliest_date}
- **Retention policy**: 90 days
diff --git a/.github/workflows/cloclo.lock.yml b/.github/workflows/cloclo.lock.yml
index 93d68184ceb..83b583eb54d 100644
--- a/.github/workflows/cloclo.lock.yml
+++ b/.github/workflows/cloclo.lock.yml
@@ -1,4 +1,4 @@
-# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"05880052889e3bbb55a9ba4a46ba2573d79401b4fbb53fab9552a56848ce8893","strict":true,"agent_id":"claude"}
+# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"8b86dda695c9490ee6bf58d37aaa2214a88f42af04a109262ac07f3889ad59e6","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","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":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/setup-go","sha":"4a3601121dd01d1626a1e23e37211e3254c1c06c","version":"v6.4.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"docker/build-push-action","sha":"bcafcacb16a39f128d818304e6c9c0c18556b85f","version":"v7.1.0"},{"repo":"docker/setup-buildx-action","sha":"4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd","version":"v4"}],"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.3.0"},{"image":"ghcr.io/github/github-mcp-server:v1.0.2"},{"image":"ghcr.io/github/serena-mcp-server:latest","digest":"sha256:bf343399e3725c45528f531a230f3a04521d4cdef29f9a5af6282ff0d3c393c5","pinned_image":"ghcr.io/github/serena-mcp-server:latest@sha256:bf343399e3725c45528f531a230f3a04521d4cdef29f9a5af6282ff0d3c393c5"},{"image":"mcr.microsoft.com/playwright/mcp","digest":"sha256:7b82f29c6ef83480a97f612d53ac3fd5f30a32df3fea1e06923d4204d3532bb2","pinned_image":"mcr.microsoft.com/playwright/mcp@sha256:7b82f29c6ef83480a97f612d53ac3fd5f30a32df3fea1e06923d4204d3532bb2"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]}
# ___ _ _
# / _ \ | | (_)
@@ -275,9 +275,9 @@ jobs:
run: |
bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh"
{
- cat << 'GH_AW_PROMPT_b5ce1be05f56810c_EOF'
+ cat << 'GH_AW_PROMPT_c0a594c3f146f6fd_EOF'
- GH_AW_PROMPT_b5ce1be05f56810c_EOF
+ GH_AW_PROMPT_c0a594c3f146f6fd_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"
@@ -285,16 +285,16 @@ jobs:
cat "${RUNNER_TEMP}/gh-aw/prompts/agentic_workflows_guide.md"
cat "${RUNNER_TEMP}/gh-aw/prompts/cache_memory_prompt.md"
cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md"
- cat << 'GH_AW_PROMPT_b5ce1be05f56810c_EOF'
+ cat << 'GH_AW_PROMPT_c0a594c3f146f6fd_EOF'
Tools: add_comment, create_pull_request, missing_tool, missing_data, noop
- GH_AW_PROMPT_b5ce1be05f56810c_EOF
+ GH_AW_PROMPT_c0a594c3f146f6fd_EOF
cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_create_pull_request.md"
- cat << 'GH_AW_PROMPT_b5ce1be05f56810c_EOF'
+ cat << 'GH_AW_PROMPT_c0a594c3f146f6fd_EOF'
- GH_AW_PROMPT_b5ce1be05f56810c_EOF
+ GH_AW_PROMPT_c0a594c3f146f6fd_EOF
cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md"
- cat << 'GH_AW_PROMPT_b5ce1be05f56810c_EOF'
+ cat << 'GH_AW_PROMPT_c0a594c3f146f6fd_EOF'
The following GitHub context information is available for this workflow:
{{#if __GH_AW_GITHUB_ACTOR__ }}
@@ -323,12 +323,12 @@ jobs:
{{/if}}
- GH_AW_PROMPT_b5ce1be05f56810c_EOF
+ GH_AW_PROMPT_c0a594c3f146f6fd_EOF
cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md"
if [ "$GITHUB_EVENT_NAME" = "issue_comment" ] && [ -n "$GH_AW_IS_PR_COMMENT" ] || [ "$GITHUB_EVENT_NAME" = "pull_request_review_comment" ] || [ "$GITHUB_EVENT_NAME" = "pull_request_review" ]; then
cat "${RUNNER_TEMP}/gh-aw/prompts/pr_context_prompt.md"
fi
- cat << 'GH_AW_PROMPT_b5ce1be05f56810c_EOF'
+ cat << 'GH_AW_PROMPT_c0a594c3f146f6fd_EOF'
## Serena Code Analysis
@@ -365,7 +365,7 @@ jobs:
{{#runtime-import .github/workflows/shared/mcp/serena-go.md}}
{{#runtime-import .github/workflows/shared/reporting.md}}
{{#runtime-import .github/workflows/cloclo.md}}
- GH_AW_PROMPT_b5ce1be05f56810c_EOF
+ GH_AW_PROMPT_c0a594c3f146f6fd_EOF
} > "$GH_AW_PROMPT"
- name: Interpolate variables and render templates
uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9
@@ -665,9 +665,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_98581509f913d5aa_EOF'
+ cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_9af7e074921cf918_EOF'
{"add_comment":{"max":1},"create_pull_request":{"excluded_files":[".github/workflows/*.lock.yml"],"expires":48,"labels":["automation","cloclo"],"max":1,"max_patch_size":1024,"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","CLAUDE.md","AGENTS.md"],"protected_files_policy":"fallback-to-issue","protected_path_prefixes":[".github/",".agents/",".githooks/",".husky/",".claude/"],"title_prefix":"[cloclo] "},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}}
- GH_AW_SAFE_OUTPUTS_CONFIG_98581509f913d5aa_EOF
+ GH_AW_SAFE_OUTPUTS_CONFIG_9af7e074921cf918_EOF
- name: Write Safe Outputs Tools
env:
GH_AW_TOOLS_META_JSON: |
@@ -901,7 +901,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 -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.0'
GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node)
- cat << GH_AW_MCP_CONFIG_9a4d8800d86c517c_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs"
+ cat << GH_AW_MCP_CONFIG_39c90f8439173991_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs"
{
"mcpServers": {
"agenticworkflows": {
@@ -1009,7 +1009,7 @@ jobs:
"payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}"
}
}
- GH_AW_MCP_CONFIG_9a4d8800d86c517c_EOF
+ GH_AW_MCP_CONFIG_39c90f8439173991_EOF
- name: Mount MCP servers as CLIs
id: mount-mcp-clis
continue-on-error: true
diff --git a/.github/workflows/cloclo.md b/.github/workflows/cloclo.md
index 172e33e904b..110b74681c5 100644
--- a/.github/workflows/cloclo.md
+++ b/.github/workflows/cloclo.md
@@ -27,7 +27,7 @@ tools:
playwright:
bash: true
cache-memory:
- key: cloclo-memory-${{ github.workflow }}-${{ github.run_id }}
+ key: cloclo-memory-${{ github.workflow }}
safe-outputs:
create-pull-request:
expires: 2d
diff --git a/.github/workflows/poem-bot.lock.yml b/.github/workflows/poem-bot.lock.yml
index 4c4f55d8d66..b04cc0e04b2 100644
--- a/.github/workflows/poem-bot.lock.yml
+++ b/.github/workflows/poem-bot.lock.yml
@@ -1,4 +1,4 @@
-# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"f13f798d1656df3e6936f8f8655271763099d96a1a3b64fcd639879a51790f9a","strict":true,"agent_id":"copilot","agent_model":"gpt-5"}
+# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"223e31aa7ed4ac26a21e61cb71d52be240886fc68ef8cebcbda9e2f2f18d2f7a","strict":true,"agent_id":"copilot","agent_model":"gpt-5"}
# gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_AGENT_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","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":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"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.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.3.0"},{"image":"ghcr.io/github/github-mcp-server:v1.0.2"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]}
# ___ _ _
# / _ \ | | (_)
@@ -240,25 +240,25 @@ jobs:
run: |
bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh"
{
- cat << 'GH_AW_PROMPT_b408d9dacab7d48a_EOF'
+ cat << 'GH_AW_PROMPT_6e1306852ad83aaf_EOF'
- GH_AW_PROMPT_b408d9dacab7d48a_EOF
+ GH_AW_PROMPT_6e1306852ad83aaf_EOF
cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md"
cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md"
cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md"
cat "${RUNNER_TEMP}/gh-aw/prompts/cache_memory_prompt.md"
cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md"
- cat << 'GH_AW_PROMPT_b408d9dacab7d48a_EOF'
+ cat << 'GH_AW_PROMPT_6e1306852ad83aaf_EOF'
Tools: add_comment(max:3), create_issue(max:2), update_issue(max:2), create_discussion(max:2), create_agent_session, create_pull_request, close_pull_request(max:2), create_pull_request_review_comment(max:2), add_labels(max:5), push_to_pull_request_branch, link_sub_issue(max:3), missing_tool, missing_data, noop
- GH_AW_PROMPT_b408d9dacab7d48a_EOF
+ GH_AW_PROMPT_6e1306852ad83aaf_EOF
cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_create_pull_request.md"
cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_push_to_pr_branch.md"
- cat << 'GH_AW_PROMPT_b408d9dacab7d48a_EOF'
+ cat << 'GH_AW_PROMPT_6e1306852ad83aaf_EOF'
- GH_AW_PROMPT_b408d9dacab7d48a_EOF
+ GH_AW_PROMPT_6e1306852ad83aaf_EOF
cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md"
- cat << 'GH_AW_PROMPT_b408d9dacab7d48a_EOF'
+ cat << 'GH_AW_PROMPT_6e1306852ad83aaf_EOF'
The following GitHub context information is available for this workflow:
{{#if __GH_AW_GITHUB_ACTOR__ }}
@@ -287,7 +287,7 @@ jobs:
{{/if}}
- GH_AW_PROMPT_b408d9dacab7d48a_EOF
+ GH_AW_PROMPT_6e1306852ad83aaf_EOF
cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md"
if [ "$GITHUB_EVENT_NAME" = "issue_comment" ] && [ -n "$GH_AW_IS_PR_COMMENT" ] || [ "$GITHUB_EVENT_NAME" = "pull_request_review_comment" ] || [ "$GITHUB_EVENT_NAME" = "pull_request_review" ]; then
cat "${RUNNER_TEMP}/gh-aw/prompts/pr_context_prompt.md"
@@ -295,11 +295,11 @@ jobs:
if [ "$GITHUB_EVENT_NAME" = "issue_comment" ] && [ -n "$GH_AW_IS_PR_COMMENT" ] || [ "$GITHUB_EVENT_NAME" = "pull_request_review_comment" ] || [ "$GITHUB_EVENT_NAME" = "pull_request_review" ]; then
cat "${RUNNER_TEMP}/gh-aw/prompts/pr_context_push_to_pr_branch_guidance.md"
fi
- cat << 'GH_AW_PROMPT_b408d9dacab7d48a_EOF'
+ cat << 'GH_AW_PROMPT_6e1306852ad83aaf_EOF'
{{#runtime-import .github/workflows/shared/reporting.md}}
{{#runtime-import .github/workflows/poem-bot.md}}
- GH_AW_PROMPT_b408d9dacab7d48a_EOF
+ GH_AW_PROMPT_6e1306852ad83aaf_EOF
} > "$GH_AW_PROMPT"
- name: Interpolate variables and render templates
uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9
@@ -525,9 +525,9 @@ jobs:
mkdir -p /tmp/gh-aw/safeoutputs
mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs
mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs/upload-artifacts"
- cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_0ea35372bf399405_EOF'
+ cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_94256f3d3f1c6097_EOF'
{"add_comment":{"max":3,"target":"*"},"add_labels":{"allowed":["poetry","creative","automation","ai-generated","epic","haiku","sonnet","limerick"],"max":5},"close_pull_request":{"max":2,"required_labels":["poetry","automation"],"required_title_prefix":"[🎨 POETRY]","target":"*"},"create_agent_session":{"base":"main","max":1},"create_discussion":{"category":"audits","close_older_discussions":true,"expires":24,"fallback_to_issue":true,"labels":["poetry","automation","ai-generated"],"max":2,"title_prefix":"[📜 POETRY] "},"create_issue":{"expires":48,"group":true,"labels":["poetry","automation","ai-generated"],"max":2,"title_prefix":"[🎭 POEM-BOT] "},"create_pull_request":{"draft":false,"expires":48,"labels":["poetry","automation","creative-writing"],"max":1,"max_patch_size":1024,"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","AGENTS.md","CLAUDE.md","GEMINI.md"],"protected_path_prefixes":[".github/",".agents/",".githooks/",".husky/"],"reviewers":["copilot"],"title_prefix":"[🎨 POETRY] "},"create_pull_request_review_comment":{"max":2,"side":"RIGHT"},"create_report_incomplete_issue":{},"link_sub_issue":{"max":3,"parent_required_labels":["poetry","epic"],"parent_title_prefix":"[🎭 POEM-BOT]","sub_required_labels":["poetry"],"sub_title_prefix":"[🎭 POEM-BOT]"},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"push_to_pull_request_branch":{"if_no_changes":"warn","max_patch_size":1024,"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","AGENTS.md","CLAUDE.md","GEMINI.md"],"protected_path_prefixes":[".github/",".agents/",".githooks/",".husky/"]},"report_incomplete":{},"update_issue":{"allow_body":true,"allow_status":true,"allow_title":true,"max":2,"target":"*"},"upload_artifact":{"max-size-bytes":104857600,"max-uploads":1,"retention-days":30}}
- GH_AW_SAFE_OUTPUTS_CONFIG_0ea35372bf399405_EOF
+ GH_AW_SAFE_OUTPUTS_CONFIG_94256f3d3f1c6097_EOF
- name: Write Safe Outputs Tools
env:
GH_AW_TOOLS_META_JSON: |
@@ -1005,7 +1005,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_4ca7187fa45e194b_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs"
+ cat << GH_AW_MCP_CONFIG_b7df822785374805_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs"
{
"mcpServers": {
"github": {
@@ -1046,7 +1046,7 @@ jobs:
"payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}"
}
}
- GH_AW_MCP_CONFIG_4ca7187fa45e194b_EOF
+ GH_AW_MCP_CONFIG_b7df822785374805_EOF
- name: Mount MCP servers as CLIs
id: mount-mcp-clis
continue-on-error: true
diff --git a/.github/workflows/poem-bot.md b/.github/workflows/poem-bot.md
index 479757729cc..486eb163b03 100644
--- a/.github/workflows/poem-bot.md
+++ b/.github/workflows/poem-bot.md
@@ -49,7 +49,7 @@ tools:
- "git"
# Memory cache for persistent AI memory across runs
cache-memory:
- key: poem-memory-${{ github.workflow }}-${{ github.run_id }}
+ key: poem-memory-${{ github.workflow }}
retention-days: 30
# Comprehensive safe-outputs configuration - ALL types with staged mode
diff --git a/.github/workflows/python-data-charts.lock.yml b/.github/workflows/python-data-charts.lock.yml
index 5be1c5616e5..826bff2c4ef 100644
--- a/.github/workflows/python-data-charts.lock.yml
+++ b/.github/workflows/python-data-charts.lock.yml
@@ -1,4 +1,4 @@
-# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"76235d12ff53ff9dc2cc14b00712702c925e4a54b32c3a39f6f4e571d787eb5c","strict":true,"agent_id":"copilot"}
+# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"a9f5127311ce3720bc28d3d4b61584a0e898c0641792d63ddfa31284043e4963","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/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":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/setup-go","sha":"4a3601121dd01d1626a1e23e37211e3254c1c06c","version":"v6.4.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/setup-python","sha":"a309ff8b426b58ec0e2a45f0f869d46889d02405","version":"v6.2.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"docker/build-push-action","sha":"bcafcacb16a39f128d818304e6c9c0c18556b85f","version":"v7.1.0"},{"repo":"docker/setup-buildx-action","sha":"4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd","version":"v4"}],"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.3.0"},{"image":"ghcr.io/github/github-mcp-server:v1.0.2"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]}
# ___ _ _
# / _ \ | | (_)
@@ -184,24 +184,24 @@ jobs:
run: |
bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh"
{
- cat << 'GH_AW_PROMPT_81a8e50872c6de0c_EOF'
+ cat << 'GH_AW_PROMPT_add4675a8ec09a44_EOF'
- GH_AW_PROMPT_81a8e50872c6de0c_EOF
+ GH_AW_PROMPT_add4675a8ec09a44_EOF
cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md"
cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md"
cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md"
cat "${RUNNER_TEMP}/gh-aw/prompts/agentic_workflows_guide.md"
cat "${RUNNER_TEMP}/gh-aw/prompts/cache_memory_prompt.md"
cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md"
- cat << 'GH_AW_PROMPT_81a8e50872c6de0c_EOF'
+ cat << 'GH_AW_PROMPT_add4675a8ec09a44_EOF'
Tools: create_discussion, upload_asset(max:5), missing_tool, missing_data, noop
upload_asset: provide a file path; returns a URL; assets are published after the workflow completes (safeoutputs).
- GH_AW_PROMPT_81a8e50872c6de0c_EOF
+ GH_AW_PROMPT_add4675a8ec09a44_EOF
cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md"
- cat << 'GH_AW_PROMPT_81a8e50872c6de0c_EOF'
+ cat << 'GH_AW_PROMPT_add4675a8ec09a44_EOF'
The following GitHub context information is available for this workflow:
{{#if __GH_AW_GITHUB_ACTOR__ }}
@@ -230,15 +230,15 @@ jobs:
{{/if}}
- GH_AW_PROMPT_81a8e50872c6de0c_EOF
+ GH_AW_PROMPT_add4675a8ec09a44_EOF
cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md"
- cat << 'GH_AW_PROMPT_81a8e50872c6de0c_EOF'
+ cat << 'GH_AW_PROMPT_add4675a8ec09a44_EOF'
{{#runtime-import .github/workflows/shared/charts-with-trending.md}}
{{#runtime-import .github/workflows/shared/python-dataviz.md}}
{{#runtime-import .github/workflows/shared/trends.md}}
{{#runtime-import .github/workflows/python-data-charts.md}}
- GH_AW_PROMPT_81a8e50872c6de0c_EOF
+ GH_AW_PROMPT_add4675a8ec09a44_EOF
} > "$GH_AW_PROMPT"
- name: Interpolate variables and render templates
uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9
@@ -532,9 +532,9 @@ jobs:
mkdir -p /tmp/gh-aw/safeoutputs
mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs
mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs/upload-artifacts"
- cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << GH_AW_SAFE_OUTPUTS_CONFIG_a50c8e475bad7c13_EOF
+ cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << GH_AW_SAFE_OUTPUTS_CONFIG_215e8b901c87e9d1_EOF
{"create_discussion":{"category":"artifacts","expires":24,"fallback_to_issue":true,"max":1},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{},"upload_artifact":{"max-size-bytes":104857600,"max-uploads":3,"retention-days":30,"skip-archive":true},"upload_asset":{"allowed-exts":[".png",".jpg",".jpeg",".svg"],"branch":"assets/${GITHUB_WORKFLOW}","max":5,"max-size":10240}}
- GH_AW_SAFE_OUTPUTS_CONFIG_a50c8e475bad7c13_EOF
+ GH_AW_SAFE_OUTPUTS_CONFIG_215e8b901c87e9d1_EOF
- name: Write Safe Outputs Tools
env:
GH_AW_TOOLS_META_JSON: |
@@ -742,7 +742,7 @@ jobs:
mkdir -p /home/runner/.copilot
GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node)
- cat << GH_AW_MCP_CONFIG_44d0cdc5bdbd6d85_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs"
+ cat << GH_AW_MCP_CONFIG_cbc1ab9ee7a4183a_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs"
{
"mcpServers": {
"agenticworkflows": {
@@ -802,7 +802,7 @@ jobs:
"payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}"
}
}
- GH_AW_MCP_CONFIG_44d0cdc5bdbd6d85_EOF
+ GH_AW_MCP_CONFIG_cbc1ab9ee7a4183a_EOF
- name: Mount MCP servers as CLIs
id: mount-mcp-clis
continue-on-error: true
diff --git a/.github/workflows/shared/charts-with-trending.md b/.github/workflows/shared/charts-with-trending.md
index af895d9d519..a81f7b09a05 100644
--- a/.github/workflows/shared/charts-with-trending.md
+++ b/.github/workflows/shared/charts-with-trending.md
@@ -27,7 +27,7 @@ imports:
tools:
cache-memory:
- key: charts-trending-${{ env.GH_AW_WORKFLOW_ID_SANITIZED }}-${{ github.run_id }}
+ key: charts-trending-${{ env.GH_AW_WORKFLOW_ID_SANITIZED }}
---
# Charts with Trending - Complete Guide
diff --git a/.github/workflows/shared/trending-charts-simple.md b/.github/workflows/shared/trending-charts-simple.md
index e3b559b862e..1e543de8241 100644
--- a/.github/workflows/shared/trending-charts-simple.md
+++ b/.github/workflows/shared/trending-charts-simple.md
@@ -4,7 +4,7 @@
tools:
cache-memory:
- key: trending-data-${{ env.GH_AW_WORKFLOW_ID_SANITIZED }}-${{ github.run_id }}
+ key: trending-data-${{ env.GH_AW_WORKFLOW_ID_SANITIZED }}
bash:
- "*"
diff --git a/.github/workflows/stale-repo-identifier.lock.yml b/.github/workflows/stale-repo-identifier.lock.yml
index fd1fba554dd..f6541fa2046 100644
--- a/.github/workflows/stale-repo-identifier.lock.yml
+++ b/.github/workflows/stale-repo-identifier.lock.yml
@@ -1,4 +1,4 @@
-# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"c9d04cc37c7b87b23c32c61d51aff8bd9c650f40ada0ba452ceaa53244a48a5d","strict":true,"agent_id":"copilot"}
+# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"d244c78cced3a9fe34f29779b857ad7488c36f36c7c24a62b34a83e8f1859244","strict":true,"agent_id":"copilot"}
# gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_ENDPOINT","GH_AW_OTEL_HEADERS","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/setup-python","sha":"a309ff8b426b58ec0e2a45f0f869d46889d02405","version":"v6.2.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/stale-repos","sha":"5f2e18fc5432823f96c1feb69327f665c2acab59","version":"v9.0.8"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.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.3.0"},{"image":"ghcr.io/github/github-mcp-server:v1.0.2"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]}
# ___ _ _
# / _ \ | | (_)
@@ -208,15 +208,15 @@ jobs:
run: |
bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh"
{
- cat << 'GH_AW_PROMPT_e60571291c112fc7_EOF'
+ cat << 'GH_AW_PROMPT_5d9a37b4d9bf19c5_EOF'
- GH_AW_PROMPT_e60571291c112fc7_EOF
+ GH_AW_PROMPT_5d9a37b4d9bf19c5_EOF
cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md"
cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md"
cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md"
cat "${RUNNER_TEMP}/gh-aw/prompts/cache_memory_prompt.md"
cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md"
- cat << 'GH_AW_PROMPT_e60571291c112fc7_EOF'
+ cat << 'GH_AW_PROMPT_5d9a37b4d9bf19c5_EOF'
Tools: create_issue(max:10), create_discussion, upload_asset(max:5), missing_tool, missing_data, noop
@@ -250,9 +250,9 @@ jobs:
{{/if}}
- GH_AW_PROMPT_e60571291c112fc7_EOF
+ GH_AW_PROMPT_5d9a37b4d9bf19c5_EOF
cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md"
- cat << 'GH_AW_PROMPT_e60571291c112fc7_EOF'
+ cat << 'GH_AW_PROMPT_5d9a37b4d9bf19c5_EOF'
{{#runtime-import .github/workflows/shared/github-guard-policy.md}}
{{#runtime-import .github/workflows/shared/jqschema.md}}
@@ -260,7 +260,7 @@ jobs:
{{#runtime-import .github/workflows/shared/reporting.md}}
{{#runtime-import .github/workflows/shared/observability-otlp.md}}
{{#runtime-import .github/workflows/stale-repo-identifier.md}}
- GH_AW_PROMPT_e60571291c112fc7_EOF
+ GH_AW_PROMPT_5d9a37b4d9bf19c5_EOF
} > "$GH_AW_PROMPT"
- name: Interpolate variables and render templates
uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9
@@ -580,9 +580,9 @@ jobs:
mkdir -p /tmp/gh-aw/safeoutputs
mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs
mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs/upload-artifacts"
- cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << GH_AW_SAFE_OUTPUTS_CONFIG_555d5b0a3d5f58b1_EOF
+ cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << GH_AW_SAFE_OUTPUTS_CONFIG_a74e2253525531da_EOF
{"create_discussion":{"category":"audits","close_older_discussions":true,"expires":72,"fallback_to_issue":true,"max":1,"title_prefix":"[stale-repo-identifier] "},"create_issue":{"expires":48,"group":true,"labels":["stale-repository","automated-analysis","cookie"],"max":10,"title_prefix":"[Stale Repository] "},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{},"upload_artifact":{"allowed-paths":["**/*.png","**/*.jpg","**/*.svg"],"max-size-bytes":104857600,"max-uploads":5,"retention-days":30,"skip-archive":true},"upload_asset":{"allowed-exts":[".png",".jpg",".jpeg",".svg"],"branch":"assets/${GITHUB_WORKFLOW}","max":5,"max-size":10240}}
- GH_AW_SAFE_OUTPUTS_CONFIG_555d5b0a3d5f58b1_EOF
+ GH_AW_SAFE_OUTPUTS_CONFIG_a74e2253525531da_EOF
- name: Write Safe Outputs Tools
env:
GH_AW_TOOLS_META_JSON: |
@@ -819,7 +819,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_2052547cc855def1_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs"
+ cat << GH_AW_MCP_CONFIG_ff4c587e437ae9d8_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs"
{
"mcpServers": {
"github": {
@@ -869,7 +869,7 @@ jobs:
}
}
}
- GH_AW_MCP_CONFIG_2052547cc855def1_EOF
+ GH_AW_MCP_CONFIG_ff4c587e437ae9d8_EOF
- name: Clean git credentials
continue-on-error: true
run: bash "${RUNNER_TEMP}/gh-aw/actions/clean_git_credentials.sh"
diff --git a/.github/workflows/stale-repo-identifier.md b/.github/workflows/stale-repo-identifier.md
index 4b45b720a2b..a11c77fe457 100644
--- a/.github/workflows/stale-repo-identifier.md
+++ b/.github/workflows/stale-repo-identifier.md
@@ -66,7 +66,7 @@ tools:
- issues
- pull_requests
cache-memory:
- key: stale-repos-analysis-${{ github.workflow }}-${{ github.run_id }}
+ key: stale-repos-analysis-${{ github.workflow }}
bash:
- "*"
edit:
diff --git a/pkg/workflow/cache.go b/pkg/workflow/cache.go
index 5f8b7498756..6e8469bcede 100644
--- a/pkg/workflow/cache.go
+++ b/pkg/workflow/cache.go
@@ -85,6 +85,9 @@ func parseCacheMemoryEntry(cacheMap map[string]any, defaultID string) (CacheMemo
// Parse custom key
if key, exists := cacheMap["key"]; exists {
if keyStr, ok := key.(string); ok {
+ if err := validateNoCacheKeyRunID(keyStr); err != nil {
+ return entry, err
+ }
entry.Key = keyStr
// Automatically append -${{ github.run_id }} if the key doesn't already end with it
runIdSuffix := "-${{ github.run_id }}"
diff --git a/pkg/workflow/cache_key_validation_test.go b/pkg/workflow/cache_key_validation_test.go
new file mode 100644
index 00000000000..b6aacdd7378
--- /dev/null
+++ b/pkg/workflow/cache_key_validation_test.go
@@ -0,0 +1,126 @@
+//go:build !integration
+
+package workflow
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+// TestCacheKeyRunIDValidationObject tests that github.run_id in a cache key raises
+// a compilation error (object notation).
+func TestCacheKeyRunIDValidationObject(t *testing.T) {
+ tests := []struct {
+ name string
+ key string
+ wantError bool
+ errorText string
+ }{
+ {
+ name: "key without run_id is accepted",
+ key: "trending-data-${{ env.GH_AW_WORKFLOW_ID_SANITIZED }}",
+ wantError: false,
+ },
+ {
+ name: "key with run_id is rejected",
+ key: "trending-data-${{ env.GH_AW_WORKFLOW_ID_SANITIZED }}-${{ github.run_id }}",
+ wantError: true,
+ errorText: "cache key must not reference github.run_id",
+ },
+ {
+ name: "key with only run_id is rejected",
+ key: "${{ github.run_id }}",
+ wantError: true,
+ errorText: "cache key must not reference github.run_id",
+ },
+ {
+ name: "plain key without expressions is accepted",
+ key: "my-stable-cache-key",
+ wantError: false,
+ },
+ {
+ name: "key with github.run_identifier is not a false positive",
+ key: "my-cache-${{ github.run_identifier }}",
+ wantError: false,
+ },
+ {
+ name: "key with github.run_id_backup suffix is not a false positive",
+ key: "my-cache-github.run_id_backup",
+ wantError: false,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ toolsMap := map[string]any{
+ "cache-memory": map[string]any{
+ "key": tt.key,
+ },
+ }
+
+ toolsConfig, err := ParseToolsConfig(toolsMap)
+ require.NoError(t, err, "Should parse tools config")
+
+ compiler := NewCompiler()
+ _, err = compiler.extractCacheMemoryConfig(toolsConfig)
+
+ if tt.wantError {
+ require.Error(t, err, "Should return error for key containing run_id")
+ assert.ErrorContains(t, err, tt.errorText, "Error should contain expected message")
+ } else {
+ assert.NoError(t, err, "Should not return error for valid key")
+ }
+ })
+ }
+}
+
+// TestCacheKeyRunIDValidationArray tests that github.run_id in a cache key raises
+// a compilation error (array notation).
+func TestCacheKeyRunIDValidationArray(t *testing.T) {
+ tests := []struct {
+ name string
+ key string
+ wantError bool
+ errorText string
+ }{
+ {
+ name: "array entry key without run_id is accepted",
+ key: "my-data-${{ env.GH_AW_WORKFLOW_ID_SANITIZED }}",
+ wantError: false,
+ },
+ {
+ name: "array entry key with run_id is rejected",
+ key: "my-data-${{ env.GH_AW_WORKFLOW_ID_SANITIZED }}-${{ github.run_id }}",
+ wantError: true,
+ errorText: "cache key must not reference github.run_id",
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ toolsMap := map[string]any{
+ "cache-memory": []any{
+ map[string]any{
+ "id": "test-cache",
+ "key": tt.key,
+ },
+ },
+ }
+
+ toolsConfig, err := ParseToolsConfig(toolsMap)
+ require.NoError(t, err, "Should parse tools config")
+
+ compiler := NewCompiler()
+ _, err = compiler.extractCacheMemoryConfig(toolsConfig)
+
+ if tt.wantError {
+ require.Error(t, err, "Should return error for key containing run_id")
+ assert.ErrorContains(t, err, tt.errorText, "Error should contain expected message")
+ } else {
+ assert.NoError(t, err, "Should not return error for valid key")
+ }
+ })
+ }
+}
diff --git a/pkg/workflow/cache_validation.go b/pkg/workflow/cache_validation.go
index 82a5efdd5d3..63c104e9541 100644
--- a/pkg/workflow/cache_validation.go
+++ b/pkg/workflow/cache_validation.go
@@ -9,6 +9,7 @@
// # Validation Functions
//
// - validateNoDuplicateCacheIDs() - Ensures each cache entry has a unique ID
+// - validateNoCacheKeyRunID() - Rejects cache keys that reference github.run_id
//
// # When to Add Validation Here
//
@@ -18,6 +19,34 @@
package workflow
+import "regexp"
+
+// cacheKeyRunIDPattern matches github.run_id as a complete token — not as a
+// prefix of a longer identifier like "github.run_identifier".
+// It matches "github.run_id" that is either:
+// - not followed by an underscore or word character (letter/digit/underscore)
+// - at the end of the string
+var cacheKeyRunIDPattern = regexp.MustCompile(`github\.run_id(?:[^_\w]|$)`)
+
+// validateNoCacheKeyRunID returns an error when a user-supplied cache key
+// contains the ${{ github.run_id }} expression.
+//
+// Including run_id in the key means every run writes to a unique cache slot and
+// the cache can never be restored from a previous run. The compiler already
+// appends run_id automatically to the save key while generating a stable
+// restore-keys prefix — users must not add it themselves.
+func validateNoCacheKeyRunID(key string) error {
+ if cacheKeyRunIDPattern.MatchString(key) {
+ return NewValidationError(
+ "tools.cache-memory.key",
+ key,
+ "cache key must not reference github.run_id — every run would write to a unique cache slot, preventing cross-run cache restoration",
+ "Remove github.run_id from the key. The compiler appends it automatically to the save key and generates a stable restore-keys prefix.\n\nExample:\n\ntools:\n cache-memory:\n key: my-data-${{ env.GH_AW_WORKFLOW_ID_SANITIZED }}\n # ✓ compiler adds run_id to the save key; restore-keys prefix enables cross-run restoration",
+ )
+ }
+ return nil
+}
+
// validateNoDuplicateCacheIDs checks for duplicate cache IDs and returns an error if found.
// Uses the generic validateNoDuplicateIDs helper for consistent duplicate detection.
func validateNoDuplicateCacheIDs(caches []CacheMemoryEntry) error {