diff --git a/.changeset/patch-bump-awf-v0-25-44.md b/.changeset/patch-bump-awf-v0-25-44.md
index 4081ce006d0..e959e566fa9 100644
--- a/.changeset/patch-bump-awf-v0-25-44.md
+++ b/.changeset/patch-bump-awf-v0-25-44.md
@@ -2,4 +2,4 @@
"gh-aw": patch
---
-Token steering (`apiProxy.enableTokenSteering`) is now enabled by default; the `firewall.effective-token-steering` frontmatter key has been removed. Set `max-effective-tokens` to a negative value to disable both budget enforcement and token steering.
+Token steering (`apiProxy.enableTokenSteering`) is now enabled by default; the `firewall.effective-token-steering` frontmatter key has been removed. Set `max-ai-credits` to a negative value to disable both budget enforcement and token steering.
diff --git a/.github/aw/syntax-agentic.md b/.github/aw/syntax-agentic.md
index 55cc26b4e4d..32a286c1210 100644
--- a/.github/aw/syntax-agentic.md
+++ b/.github/aw/syntax-agentic.md
@@ -29,7 +29,7 @@ description: Agentic workflow specific frontmatter fields for GitHub Agentic Wor
- Top-level field mapped to `apiProxy.maxRuns`
- Supported by all engines
- **`max-turns:`** - AWF turn cap applied consistently across all agentic engines (integer or expression, e.g. `${{ inputs.max-turns }}`). The engine-level `engine.max-turns` is a deprecated alias kept for backward compatibility — prefer this top-level field. Not supported by the `gemini` engine.
-- **`max-effective-tokens:`** - Per-run effective-token (ET) budget enforced by the AWF firewall (integer or `K`/`M` short-form string like `100M`; default `25000000`). Set a negative value to disable enforcement and token steering. See [token-optimization.md](token-optimization.md).
+- **`max-ai-credits:`** - Per-run effective-token (ET) budget enforced by the AWF firewall (integer or `K`/`M` short-form string like `100M`; default `25000000`). Set a negative value to disable enforcement and token steering. See [token-optimization.md](token-optimization.md).
- **`max-daily-ai-credits:`** - Per-user 24-hour ET guardrail: activation blocks execution once the triggering user's aggregated ET for this workflow over the last 24h exceeds the threshold (integer or `K`/`M` short-form string, or `-1`). Enabled by default with a system default threshold; set `-1` to disable or an explicit value to override. See [token-optimization.md](token-optimization.md).
- **`user-rate-limit:`** - Rate limiting configuration to prevent users from triggering the workflow too frequently (object)
- **`max-runs-per-window:`** - Maximum runs allowed per user per time window (required, integer 1-10)
diff --git a/.github/aw/token-optimization.md b/.github/aw/token-optimization.md
index ae57a550b1d..859ab5b4903 100644
--- a/.github/aw/token-optimization.md
+++ b/.github/aw/token-optimization.md
@@ -363,11 +363,11 @@ To maximize cache hits:
Two top-level frontmatter fields enforce ET budgets directly, independent of the techniques above. Both accept an integer or a `K`/`M` short-form string (e.g. `100M`, `500K`).
-- **`max-effective-tokens:`** — Per-run ET budget enforced by the AWF firewall/API proxy (default `25000000`). The agent is steered to stay within budget; set a negative value to disable enforcement and steering.
+- **`max-ai-credits:`** — Per-run ET budget enforced by the AWF firewall/API proxy (default `25000000`). The agent is steered to stay within budget; set a negative value to disable enforcement and steering.
- **`max-daily-ai-credits:`** — Per-user 24-hour guardrail. At activation, gh-aw sums the triggering user's ET across their runs of this workflow over the last 24 hours and blocks execution once the total exceeds the threshold. Enabled by default with a system default threshold; set `-1` to disable, or an explicit value to override the default.
```yaml
-max-effective-tokens: 100M # per-run cap (short-form string)
+max-ai-credits: 100M # per-run cap (short-form string)
max-daily-ai-credits: 500M # per-user 24h cap; -1 disables
```
diff --git a/.github/workflows/ab-testing-advisor.lock.yml b/.github/workflows/ab-testing-advisor.lock.yml
index 4268294da4d..936a003af5c 100644
--- a/.github/workflows/ab-testing-advisor.lock.yml
+++ b/.github/workflows/ab-testing-advisor.lock.yml
@@ -877,6 +877,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 30
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1431,6 +1432,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/ace-editor.lock.yml b/.github/workflows/ace-editor.lock.yml
index dfc8d616fa6..3591db4bbf7 100644
--- a/.github/workflows/ace-editor.lock.yml
+++ b/.github/workflows/ace-editor.lock.yml
@@ -779,6 +779,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 10
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/agent-performance-analyzer.lock.yml b/.github/workflows/agent-performance-analyzer.lock.yml
index 96ea9f6a859..67b7aa771c4 100644
--- a/.github/workflows/agent-performance-analyzer.lock.yml
+++ b/.github/workflows/agent-performance-analyzer.lock.yml
@@ -1,4 +1,4 @@
-# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"1aa047b369a726210a6f3e17ed61c09ffde764404196dcdb48860f7dc2f09eae","body_hash":"19e16e74e8f6d860a7b85c3d685a6c5d7a985b29e0270975d1cae6bc8f175712","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.59","copilot-sdk":"1.0.0"}}
+# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"3ec7c40bd1b5e3c6168c27ee1b913eaef26ad07b36f3ff1954438c0a174aa0a7","body_hash":"19e16e74e8f6d860a7b85c3d685a6c5d7a985b29e0270975d1cae6bc8f175712","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.59","copilot-sdk":"1.0.0"}}
# gh-aw-manifest: {"version":1,"secrets":["GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_GRAFANA_AUTHORIZATION","GH_AW_OTEL_GRAFANA_ENDPOINT","GH_AW_OTEL_SENTRY_AUTHORIZATION","GH_AW_OTEL_SENTRY_ENDPOINT","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-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":"f9f3042f7e2789586610d6e8b85c8f03e5195baf","version":"v7.2.0"},{"repo":"docker/setup-buildx-action","sha":"d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5","version":"v4.1.0"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.65"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.65"},{"image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.65"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.65"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.23","digest":"sha256:0dd1bd91a41e24a3ccc31b1ec6cb61d36608997fabf91f2d643b64e3fc33180a","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.23@sha256:0dd1bd91a41e24a3ccc31b1ec6cb61d36608997fabf91f2d643b64e3fc33180a"},{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"},{"image":"node:lts-alpine","digest":"sha256:2bdb65ed1dab192432bc31c95f94155ca5ad7fc1392fb7eb7526ab682fa5bf14","pinned_image":"node:lts-alpine@sha256:2bdb65ed1dab192432bc31c95f94155ca5ad7fc1392fb7eb7526ab682fa5bf14"}]}
# ___ _ _
# / _ \ | | (_)
@@ -986,7 +986,7 @@ jobs:
export GH_AW_NODE_BIN
export COPILOT_API_KEY="$COPILOT_DUMMY_BYOK"
(umask 177 && touch /tmp/gh-aw/agent-stdio.log)
- printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.65/awf-config.schema.json","network":{"allowDomains":["*.grafana.net","*.sentry.io","api.business.githubcopilot.com","api.enterprise.githubcopilot.com","api.github.com","api.githubcopilot.com","api.individual.githubcopilot.com","api.snapcraft.io","archive.ubuntu.com","azure.archive.ubuntu.com","crl.geotrust.com","crl.globalsign.com","crl.identrust.com","crl.sectigo.com","crl.thawte.com","crl.usertrust.com","crl.verisign.com","crl3.digicert.com","crl4.digicert.com","crls.ssl.com","github.com","host.docker.internal","json-schema.org","json.schemastore.org","keyserver.ubuntu.com","ocsp.digicert.com","ocsp.geotrust.com","ocsp.globalsign.com","ocsp.identrust.com","ocsp.sectigo.com","ocsp.ssl.com","ocsp.thawte.com","ocsp.usertrust.com","ocsp.verisign.com","packagecloud.io","packages.cloud.google.com","packages.microsoft.com","ppa.launchpad.net","raw.githubusercontent.com","registry.npmjs.org","s.symcb.com","s.symcd.com","security.ubuntu.com","telemetry.enterprise.githubcopilot.com","ts-crl.ws.symantec.com","ts-ocsp.ws.symantec.com","www.googleapis.com"]},"apiProxy":{"enabled":true,"enableTokenSteering":true,"maxRuns":500,"maxEffectiveTokens":40000000,"maxAiCredits":1000,"models":{"agent":["sonnet-6x","gpt-5.4","gpt-5.3","gemini-pro","any"],"antigravity":["copilot/antigravity*","google/antigravity*","gemini/antigravity*"],"any":["copilot/*","anthropic/*","openai/*","google/*","gemini/*"],"claude":["agent"],"codex":["agent"],"coding":["copilot/gpt-5*codex*","openai/gpt-5*codex*","gpt-5-codex"],"computer-use":["copilot/*computer-use*","google/*computer-use*","gemini/*computer-use*","openai/*computer-use*"],"copilot":["agent"],"deep-research":["copilot/deep-research*","copilot/o3-deep-research*","copilot/o4-mini-deep-research*","google/deep-research*","gemini/deep-research*","openai/o3-deep-research*","openai/o4-mini-deep-research*"],"gemini":["agent"],"gemini-3-flash":["copilot/gemini-3*flash*","google/gemini-3*flash*","gemini/gemini-3*flash*"],"gemini-3-pro":["copilot/gemini-3*pro*","google/gemini-3*pro*","google/nano-banana*","gemini/gemini-3*pro*"],"gemini-3.1-flash":["copilot/gemini-3.1*flash*","google/gemini-3.1*flash*","gemini/gemini-3.1*flash*"],"gemini-3.1-pro":["copilot/gemini-3.1*pro*","google/gemini-3.1*pro*","gemini/gemini-3.1*pro*"],"gemini-3.5-flash":["copilot/gemini-3.5*flash*","google/gemini-3.5*flash*","gemini/gemini-3.5*flash*"],"gemini-flash":["copilot/gemini-*flash*","google/gemini-*flash*","gemini/gemini-*flash*"],"gemini-flash-lite":["copilot/gemini-*flash*lite*","google/gemini-*flash*lite*","gemini/gemini-*flash*lite*"],"gemini-pro":["copilot/gemini-*pro*","google/gemini-*pro*","gemini/gemini-*pro*"],"gemma":["copilot/gemma*","google/gemma*","gemini/gemma*"],"gpt-5":["copilot/gpt-5*","openai/gpt-5*"],"gpt-5-codex":["copilot/gpt-5*codex*","openai/gpt-5*codex*"],"gpt-5-mini":["copilot/gpt-5*mini*","openai/gpt-5*mini*"],"gpt-5-nano":["copilot/gpt-5*nano*","openai/gpt-5*nano*"],"gpt-5-pro":["copilot/gpt-5*pro*","openai/gpt-5*pro*"],"gpt-5.2":["copilot/gpt-5.2*","openai/gpt-5.2*"],"gpt-5.3":["copilot/gpt-5.3*","openai/gpt-5.3*"],"gpt-5.4":["copilot/gpt-5.4*","openai/gpt-5.4*"],"gpt-5.5":["copilot/gpt-5.5*","openai/gpt-5.5*"],"haiku":["copilot/*haiku*","anthropic/*haiku*"],"large":["sonnet","gpt-5-pro","gpt-5","gemini-pro"],"mai-code":["copilot/MAI-Code*","copilot/mai-code*","openai/MAI-Code*"],"mini":["haiku","gpt-5-mini","gpt-5-nano","gemini-flash-lite"],"nano-banana":["copilot/nano-banana*","google/nano-banana*","gemini/nano-banana*"],"opus":["copilot/*opus*","anthropic/*opus*"],"opusplan":["opus?effort=high"],"reasoning":["copilot/o1*","copilot/o3*","copilot/o4*","openai/o1*","openai/o3*","openai/o4*"],"robotics":["copilot/*robotics*","google/*robotics*","gemini/*robotics*"],"small":["mini"],"small-agent":["haiku","gpt-5-mini","gemini-flash","any"],"sonnet":["copilot/*sonnet*","anthropic/*sonnet*"],"sonnet-6x":["copilot/*sonnet-4.5*","copilot/*sonnet-4.6*","copilot/*sonnet-4-5-*","anthropic/*sonnet-4-5-*","copilot/*sonnet-4-6*","anthropic/*sonnet-4-6*"],"summarization":["haiku","gpt-5-mini","gemini-flash-lite","mini"],"vision":["copilot/gemini-*image*","gemini/gemini-*image*","copilot/gemini-*flash*","gemini/gemini-*flash*"]}},"container":{"imageTag":"0.25.65"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json"
+ printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.65/awf-config.schema.json","network":{"allowDomains":["*.grafana.net","*.sentry.io","api.business.githubcopilot.com","api.enterprise.githubcopilot.com","api.github.com","api.githubcopilot.com","api.individual.githubcopilot.com","api.snapcraft.io","archive.ubuntu.com","azure.archive.ubuntu.com","crl.geotrust.com","crl.globalsign.com","crl.identrust.com","crl.sectigo.com","crl.thawte.com","crl.usertrust.com","crl.verisign.com","crl3.digicert.com","crl4.digicert.com","crls.ssl.com","github.com","host.docker.internal","json-schema.org","json.schemastore.org","keyserver.ubuntu.com","ocsp.digicert.com","ocsp.geotrust.com","ocsp.globalsign.com","ocsp.identrust.com","ocsp.sectigo.com","ocsp.ssl.com","ocsp.thawte.com","ocsp.usertrust.com","ocsp.verisign.com","packagecloud.io","packages.cloud.google.com","packages.microsoft.com","ppa.launchpad.net","raw.githubusercontent.com","registry.npmjs.org","s.symcb.com","s.symcd.com","security.ubuntu.com","telemetry.enterprise.githubcopilot.com","ts-crl.ws.symantec.com","ts-ocsp.ws.symantec.com","www.googleapis.com"]},"apiProxy":{"enabled":true,"enableTokenSteering":true,"maxRuns":500,"maxAiCredits":40000000,"models":{"agent":["sonnet-6x","gpt-5.4","gpt-5.3","gemini-pro","any"],"antigravity":["copilot/antigravity*","google/antigravity*","gemini/antigravity*"],"any":["copilot/*","anthropic/*","openai/*","google/*","gemini/*"],"claude":["agent"],"codex":["agent"],"coding":["copilot/gpt-5*codex*","openai/gpt-5*codex*","gpt-5-codex"],"computer-use":["copilot/*computer-use*","google/*computer-use*","gemini/*computer-use*","openai/*computer-use*"],"copilot":["agent"],"deep-research":["copilot/deep-research*","copilot/o3-deep-research*","copilot/o4-mini-deep-research*","google/deep-research*","gemini/deep-research*","openai/o3-deep-research*","openai/o4-mini-deep-research*"],"gemini":["agent"],"gemini-3-flash":["copilot/gemini-3*flash*","google/gemini-3*flash*","gemini/gemini-3*flash*"],"gemini-3-pro":["copilot/gemini-3*pro*","google/gemini-3*pro*","google/nano-banana*","gemini/gemini-3*pro*"],"gemini-3.1-flash":["copilot/gemini-3.1*flash*","google/gemini-3.1*flash*","gemini/gemini-3.1*flash*"],"gemini-3.1-pro":["copilot/gemini-3.1*pro*","google/gemini-3.1*pro*","gemini/gemini-3.1*pro*"],"gemini-3.5-flash":["copilot/gemini-3.5*flash*","google/gemini-3.5*flash*","gemini/gemini-3.5*flash*"],"gemini-flash":["copilot/gemini-*flash*","google/gemini-*flash*","gemini/gemini-*flash*"],"gemini-flash-lite":["copilot/gemini-*flash*lite*","google/gemini-*flash*lite*","gemini/gemini-*flash*lite*"],"gemini-pro":["copilot/gemini-*pro*","google/gemini-*pro*","gemini/gemini-*pro*"],"gemma":["copilot/gemma*","google/gemma*","gemini/gemma*"],"gpt-5":["copilot/gpt-5*","openai/gpt-5*"],"gpt-5-codex":["copilot/gpt-5*codex*","openai/gpt-5*codex*"],"gpt-5-mini":["copilot/gpt-5*mini*","openai/gpt-5*mini*"],"gpt-5-nano":["copilot/gpt-5*nano*","openai/gpt-5*nano*"],"gpt-5-pro":["copilot/gpt-5*pro*","openai/gpt-5*pro*"],"gpt-5.2":["copilot/gpt-5.2*","openai/gpt-5.2*"],"gpt-5.3":["copilot/gpt-5.3*","openai/gpt-5.3*"],"gpt-5.4":["copilot/gpt-5.4*","openai/gpt-5.4*"],"gpt-5.5":["copilot/gpt-5.5*","openai/gpt-5.5*"],"haiku":["copilot/*haiku*","anthropic/*haiku*"],"large":["sonnet","gpt-5-pro","gpt-5","gemini-pro"],"mai-code":["copilot/MAI-Code*","copilot/mai-code*","openai/MAI-Code*"],"mini":["haiku","gpt-5-mini","gpt-5-nano","gemini-flash-lite"],"nano-banana":["copilot/nano-banana*","google/nano-banana*","gemini/nano-banana*"],"opus":["copilot/*opus*","anthropic/*opus*"],"opusplan":["opus?effort=high"],"reasoning":["copilot/o1*","copilot/o3*","copilot/o4*","openai/o1*","openai/o3*","openai/o4*"],"robotics":["copilot/*robotics*","google/*robotics*","gemini/*robotics*"],"small":["mini"],"small-agent":["haiku","gpt-5-mini","gemini-flash","any"],"sonnet":["copilot/*sonnet*","anthropic/*sonnet*"],"sonnet-6x":["copilot/*sonnet-4.5*","copilot/*sonnet-4.6*","copilot/*sonnet-4-5-*","anthropic/*sonnet-4-5-*","copilot/*sonnet-4-6*","anthropic/*sonnet-4-6*"],"summarization":["haiku","gpt-5-mini","gemini-flash-lite","mini"],"vision":["copilot/gemini-*image*","gemini/gemini-*image*","copilot/gemini-*flash*","gemini/gemini-*flash*"]}},"container":{"imageTag":"0.25.65"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json"
GH_AW_MODEL_MULTIPLIERS_PATH="/tmp/gh-aw/model_multipliers.json" node "${RUNNER_TEMP}/gh-aw/actions/merge_awf_model_multipliers.cjs"
cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json
export GH_AW_MODELS_JSON_PATH="${RUNNER_TEMP}/gh-aw/actions/models.json"
@@ -1021,6 +1021,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 30
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1391,7 +1392,6 @@ jobs:
GH_AW_MISSING_TOOL_REPORT_AS_FAILURE: "true"
GH_AW_MISSING_DATA_REPORT_AS_FAILURE: "true"
GH_AW_TIMEOUT_MINUTES: "30"
- GH_AW_MAX_EFFECTIVE_TOKENS: "40000000"
with:
github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
script: |
@@ -1553,7 +1553,7 @@ jobs:
export GH_AW_NODE_BIN
export COPILOT_API_KEY="$COPILOT_DUMMY_BYOK"
(umask 177 && touch /tmp/gh-aw/threat-detection/detection.log)
- printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.65/awf-config.schema.json","network":{"allowDomains":["api.business.githubcopilot.com","api.enterprise.githubcopilot.com","api.github.com","api.githubcopilot.com","api.individual.githubcopilot.com","github.com","host.docker.internal","registry.npmjs.org","telemetry.enterprise.githubcopilot.com"]},"apiProxy":{"enabled":true,"enableTokenSteering":true,"maxRuns":500,"maxEffectiveTokens":40000000,"maxAiCredits":1000},"container":{"imageTag":"0.25.65"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json"
+ printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.65/awf-config.schema.json","network":{"allowDomains":["api.business.githubcopilot.com","api.enterprise.githubcopilot.com","api.github.com","api.githubcopilot.com","api.individual.githubcopilot.com","github.com","host.docker.internal","registry.npmjs.org","telemetry.enterprise.githubcopilot.com"]},"apiProxy":{"enabled":true,"enableTokenSteering":true,"maxRuns":500,"maxAiCredits":1000},"container":{"imageTag":"0.25.65"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json"
GH_AW_MODEL_MULTIPLIERS_PATH="/tmp/gh-aw/model_multipliers.json" node "${RUNNER_TEMP}/gh-aw/actions/merge_awf_model_multipliers.cjs"
cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json
export GH_AW_MODELS_JSON_PATH="${RUNNER_TEMP}/gh-aw/actions/models.json"
@@ -1582,6 +1582,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/agent-performance-analyzer.md b/.github/workflows/agent-performance-analyzer.md
index bdfc35878cb..99dbc5e0f77 100644
--- a/.github/workflows/agent-performance-analyzer.md
+++ b/.github/workflows/agent-performance-analyzer.md
@@ -40,7 +40,7 @@ safe-outputs:
timeout-minutes: 30
# Raised above 25M default: meta-orchestrator does deep analysis across all agents.
# Caveman experiment aims to reduce by ≥20%; set ceiling to catch runaway loops.
-max-effective-tokens: 40000000
+max-ai-credits: 40000000
experiments:
prompt_compression:
variants: [verbose, caveman]
diff --git a/.github/workflows/agent-persona-explorer.lock.yml b/.github/workflows/agent-persona-explorer.lock.yml
index 7117fbeabd4..5b7219a692e 100644
--- a/.github/workflows/agent-persona-explorer.lock.yml
+++ b/.github/workflows/agent-persona-explorer.lock.yml
@@ -968,6 +968,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 180
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1522,6 +1523,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/agentic-token-audit.lock.yml b/.github/workflows/agentic-token-audit.lock.yml
index 9063d6da001..6363b79e1c4 100644
--- a/.github/workflows/agentic-token-audit.lock.yml
+++ b/.github/workflows/agentic-token-audit.lock.yml
@@ -958,6 +958,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 25
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1508,6 +1509,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/agentic-token-optimizer.lock.yml b/.github/workflows/agentic-token-optimizer.lock.yml
index 818b3e4eac6..e9ae8f469b3 100644
--- a/.github/workflows/agentic-token-optimizer.lock.yml
+++ b/.github/workflows/agentic-token-optimizer.lock.yml
@@ -833,6 +833,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 30
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
diff --git a/.github/workflows/agentic-token-trend-audit.lock.yml b/.github/workflows/agentic-token-trend-audit.lock.yml
index 7c94c366590..ca9ccd3838a 100644
--- a/.github/workflows/agentic-token-trend-audit.lock.yml
+++ b/.github/workflows/agentic-token-trend-audit.lock.yml
@@ -932,6 +932,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 25
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1460,6 +1461,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/archie.lock.yml b/.github/workflows/archie.lock.yml
index 84e2c4d966d..24fe298d586 100644
--- a/.github/workflows/archie.lock.yml
+++ b/.github/workflows/archie.lock.yml
@@ -921,6 +921,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 10
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1475,6 +1476,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/architecture-guardian.lock.yml b/.github/workflows/architecture-guardian.lock.yml
index d2c1187409b..5fcd59cf1ab 100644
--- a/.github/workflows/architecture-guardian.lock.yml
+++ b/.github/workflows/architecture-guardian.lock.yml
@@ -868,6 +868,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1398,6 +1399,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/artifacts-summary.lock.yml b/.github/workflows/artifacts-summary.lock.yml
index b941d94efd6..f8960732e65 100644
--- a/.github/workflows/artifacts-summary.lock.yml
+++ b/.github/workflows/artifacts-summary.lock.yml
@@ -810,6 +810,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 15
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1342,6 +1343,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/auto-triage-issues.lock.yml b/.github/workflows/auto-triage-issues.lock.yml
index 76fc2fb127c..9622468ddc1 100644
--- a/.github/workflows/auto-triage-issues.lock.yml
+++ b/.github/workflows/auto-triage-issues.lock.yml
@@ -886,6 +886,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 15
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1421,6 +1422,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/bot-detection.lock.yml b/.github/workflows/bot-detection.lock.yml
index 26b7e1f388e..5006a697568 100644
--- a/.github/workflows/bot-detection.lock.yml
+++ b/.github/workflows/bot-detection.lock.yml
@@ -905,6 +905,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 10
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/brave.lock.yml b/.github/workflows/brave.lock.yml
index 24c9dafa670..5c4db38facd 100644
--- a/.github/workflows/brave.lock.yml
+++ b/.github/workflows/brave.lock.yml
@@ -895,6 +895,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 10
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1445,6 +1446,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/breaking-change-checker.lock.yml b/.github/workflows/breaking-change-checker.lock.yml
index f1b1e9c3a6b..6a0a1242c15 100644
--- a/.github/workflows/breaking-change-checker.lock.yml
+++ b/.github/workflows/breaking-change-checker.lock.yml
@@ -852,6 +852,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 10
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1387,6 +1388,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/chaos-pr-bundle-fuzzer.lock.yml b/.github/workflows/chaos-pr-bundle-fuzzer.lock.yml
index 9773365458e..c9ce63705ba 100644
--- a/.github/workflows/chaos-pr-bundle-fuzzer.lock.yml
+++ b/.github/workflows/chaos-pr-bundle-fuzzer.lock.yml
@@ -857,6 +857,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 30
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1404,6 +1405,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/ci-coach.lock.yml b/.github/workflows/ci-coach.lock.yml
index d6e93b8de96..30358e78cc5 100644
--- a/.github/workflows/ci-coach.lock.yml
+++ b/.github/workflows/ci-coach.lock.yml
@@ -941,6 +941,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 30
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1505,6 +1506,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/cli-consistency-checker.lock.yml b/.github/workflows/cli-consistency-checker.lock.yml
index cff5e739817..82a0ab3f8f2 100644
--- a/.github/workflows/cli-consistency-checker.lock.yml
+++ b/.github/workflows/cli-consistency-checker.lock.yml
@@ -829,6 +829,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1353,6 +1354,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/code-scanning-fixer.lock.yml b/.github/workflows/code-scanning-fixer.lock.yml
index 631739bbb87..b148d1f0644 100644
--- a/.github/workflows/code-scanning-fixer.lock.yml
+++ b/.github/workflows/code-scanning-fixer.lock.yml
@@ -891,6 +891,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1463,6 +1464,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/code-simplifier.lock.yml b/.github/workflows/code-simplifier.lock.yml
index 6416840634a..d9eb09803c4 100644
--- a/.github/workflows/code-simplifier.lock.yml
+++ b/.github/workflows/code-simplifier.lock.yml
@@ -962,6 +962,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 30
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1499,6 +1500,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/constraint-solving-potd.lock.yml b/.github/workflows/constraint-solving-potd.lock.yml
index 1b2ef6651df..d9957777539 100644
--- a/.github/workflows/constraint-solving-potd.lock.yml
+++ b/.github/workflows/constraint-solving-potd.lock.yml
@@ -819,6 +819,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 30
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1366,6 +1367,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/contribution-check.lock.yml b/.github/workflows/contribution-check.lock.yml
index b4aa6012dfd..b274f264153 100644
--- a/.github/workflows/contribution-check.lock.yml
+++ b/.github/workflows/contribution-check.lock.yml
@@ -945,6 +945,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 30
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1478,6 +1479,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/copilot-cli-deep-research.lock.yml b/.github/workflows/copilot-cli-deep-research.lock.yml
index 5bab0c8563b..0ce80ccd21b 100644
--- a/.github/workflows/copilot-cli-deep-research.lock.yml
+++ b/.github/workflows/copilot-cli-deep-research.lock.yml
@@ -864,6 +864,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1416,6 +1417,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/copilot-opt.lock.yml b/.github/workflows/copilot-opt.lock.yml
index 03489e3e5be..fed37bed93c 100644
--- a/.github/workflows/copilot-opt.lock.yml
+++ b/.github/workflows/copilot-opt.lock.yml
@@ -902,6 +902,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 30
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1452,6 +1453,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/copilot-pr-merged-report.lock.yml b/.github/workflows/copilot-pr-merged-report.lock.yml
index 7e02da4517e..54a027eb3a8 100644
--- a/.github/workflows/copilot-pr-merged-report.lock.yml
+++ b/.github/workflows/copilot-pr-merged-report.lock.yml
@@ -777,6 +777,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 10
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1323,6 +1324,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/copilot-pr-nlp-analysis.lock.yml b/.github/workflows/copilot-pr-nlp-analysis.lock.yml
index c1b77156ed2..8fc2136b23f 100644
--- a/.github/workflows/copilot-pr-nlp-analysis.lock.yml
+++ b/.github/workflows/copilot-pr-nlp-analysis.lock.yml
@@ -939,6 +939,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1516,6 +1517,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/copilot-pr-prompt-analysis.lock.yml b/.github/workflows/copilot-pr-prompt-analysis.lock.yml
index 20b3d16d74d..e2f5714dd38 100644
--- a/.github/workflows/copilot-pr-prompt-analysis.lock.yml
+++ b/.github/workflows/copilot-pr-prompt-analysis.lock.yml
@@ -887,6 +887,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 15
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1454,6 +1455,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/craft.lock.yml b/.github/workflows/craft.lock.yml
index b0c0766c48f..f8321ae7ac9 100644
--- a/.github/workflows/craft.lock.yml
+++ b/.github/workflows/craft.lock.yml
@@ -893,6 +893,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 15
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1449,6 +1450,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/daily-agent-of-the-day-blog-writer.lock.yml b/.github/workflows/daily-agent-of-the-day-blog-writer.lock.yml
index 7f7aee9d877..bbedd27c5c4 100644
--- a/.github/workflows/daily-agent-of-the-day-blog-writer.lock.yml
+++ b/.github/workflows/daily-agent-of-the-day-blog-writer.lock.yml
@@ -1001,6 +1001,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 45
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1570,6 +1571,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/daily-ambient-context-optimizer.lock.yml b/.github/workflows/daily-ambient-context-optimizer.lock.yml
index b886ef5ce1f..10943e23ac3 100644
--- a/.github/workflows/daily-ambient-context-optimizer.lock.yml
+++ b/.github/workflows/daily-ambient-context-optimizer.lock.yml
@@ -912,6 +912,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 45
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1447,6 +1448,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/daily-architecture-diagram.lock.yml b/.github/workflows/daily-architecture-diagram.lock.yml
index 4afe89495b8..fc0edf77b1d 100644
--- a/.github/workflows/daily-architecture-diagram.lock.yml
+++ b/.github/workflows/daily-architecture-diagram.lock.yml
@@ -966,6 +966,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1523,6 +1524,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/daily-assign-issue-to-user.lock.yml b/.github/workflows/daily-assign-issue-to-user.lock.yml
index 9cd0b181efb..2ec4b71876e 100644
--- a/.github/workflows/daily-assign-issue-to-user.lock.yml
+++ b/.github/workflows/daily-assign-issue-to-user.lock.yml
@@ -822,6 +822,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 10
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1353,6 +1354,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/daily-byok-ollama-test.lock.yml b/.github/workflows/daily-byok-ollama-test.lock.yml
index b989ff75228..15ae3d06d79 100644
--- a/.github/workflows/daily-byok-ollama-test.lock.yml
+++ b/.github/workflows/daily-byok-ollama-test.lock.yml
@@ -817,6 +817,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1330,6 +1331,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/daily-cli-performance.lock.yml b/.github/workflows/daily-cli-performance.lock.yml
index 560797b952f..de01db57961 100644
--- a/.github/workflows/daily-cli-performance.lock.yml
+++ b/.github/workflows/daily-cli-performance.lock.yml
@@ -1077,6 +1077,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1645,6 +1646,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/daily-cli-tools-tester.lock.yml b/.github/workflows/daily-cli-tools-tester.lock.yml
index 979e4399ca8..5e9297c2c1e 100644
--- a/.github/workflows/daily-cli-tools-tester.lock.yml
+++ b/.github/workflows/daily-cli-tools-tester.lock.yml
@@ -944,6 +944,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 60
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1471,6 +1472,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/daily-community-attribution.lock.yml b/.github/workflows/daily-community-attribution.lock.yml
index 29476762615..4cdeb55cafc 100644
--- a/.github/workflows/daily-community-attribution.lock.yml
+++ b/.github/workflows/daily-community-attribution.lock.yml
@@ -977,6 +977,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1536,6 +1537,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/daily-compiler-quality.lock.yml b/.github/workflows/daily-compiler-quality.lock.yml
index 53c5741b55f..cd1d126477d 100644
--- a/.github/workflows/daily-compiler-quality.lock.yml
+++ b/.github/workflows/daily-compiler-quality.lock.yml
@@ -981,6 +981,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 30
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1545,6 +1546,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/daily-compiler-threat-spec-optimizer.lock.yml b/.github/workflows/daily-compiler-threat-spec-optimizer.lock.yml
index 927085a1014..54a49fa88cf 100644
--- a/.github/workflows/daily-compiler-threat-spec-optimizer.lock.yml
+++ b/.github/workflows/daily-compiler-threat-spec-optimizer.lock.yml
@@ -895,6 +895,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 30
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1435,6 +1436,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/daily-experiment-report.lock.yml b/.github/workflows/daily-experiment-report.lock.yml
index 5c64ccd2b3a..f4b9c7bad01 100644
--- a/.github/workflows/daily-experiment-report.lock.yml
+++ b/.github/workflows/daily-experiment-report.lock.yml
@@ -941,6 +941,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 30
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1500,6 +1501,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/daily-file-diet.lock.yml b/.github/workflows/daily-file-diet.lock.yml
index 29f48a37b2b..6f27dcd7b38 100644
--- a/.github/workflows/daily-file-diet.lock.yml
+++ b/.github/workflows/daily-file-diet.lock.yml
@@ -918,6 +918,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1452,6 +1453,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/daily-firewall-report.lock.yml b/.github/workflows/daily-firewall-report.lock.yml
index e84520ab69f..791b93086ca 100644
--- a/.github/workflows/daily-firewall-report.lock.yml
+++ b/.github/workflows/daily-firewall-report.lock.yml
@@ -889,6 +889,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 45
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1432,6 +1433,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/daily-geo-optimizer.lock.yml b/.github/workflows/daily-geo-optimizer.lock.yml
index b5ff9e6386e..0d43ef64b75 100644
--- a/.github/workflows/daily-geo-optimizer.lock.yml
+++ b/.github/workflows/daily-geo-optimizer.lock.yml
@@ -847,6 +847,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 30
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1385,6 +1386,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/daily-hippo-learn.lock.yml b/.github/workflows/daily-hippo-learn.lock.yml
index 1b59ecd1fef..0cc09dd0ac5 100644
--- a/.github/workflows/daily-hippo-learn.lock.yml
+++ b/.github/workflows/daily-hippo-learn.lock.yml
@@ -953,6 +953,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 30
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1520,6 +1521,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/daily-issues-report.lock.yml b/.github/workflows/daily-issues-report.lock.yml
index 924501ad2ba..5ba37d12d34 100644
--- a/.github/workflows/daily-issues-report.lock.yml
+++ b/.github/workflows/daily-issues-report.lock.yml
@@ -1090,6 +1090,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 30
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1666,6 +1667,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/daily-malicious-code-scan.lock.yml b/.github/workflows/daily-malicious-code-scan.lock.yml
index ffa77d9b157..3b4ea7fd47d 100644
--- a/.github/workflows/daily-malicious-code-scan.lock.yml
+++ b/.github/workflows/daily-malicious-code-scan.lock.yml
@@ -863,6 +863,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 15
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/daily-mcp-concurrency-analysis.lock.yml b/.github/workflows/daily-mcp-concurrency-analysis.lock.yml
index 43143d7c0e1..98babf245b1 100644
--- a/.github/workflows/daily-mcp-concurrency-analysis.lock.yml
+++ b/.github/workflows/daily-mcp-concurrency-analysis.lock.yml
@@ -980,6 +980,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 45
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1537,6 +1538,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/daily-model-inventory.lock.yml b/.github/workflows/daily-model-inventory.lock.yml
index 9f1eb3ec749..211f38e3034 100644
--- a/.github/workflows/daily-model-inventory.lock.yml
+++ b/.github/workflows/daily-model-inventory.lock.yml
@@ -871,6 +871,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 30
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1699,6 +1700,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/daily-news.lock.yml b/.github/workflows/daily-news.lock.yml
index 73f3a534236..f7024fdeba1 100644
--- a/.github/workflows/daily-news.lock.yml
+++ b/.github/workflows/daily-news.lock.yml
@@ -1053,6 +1053,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 30
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1653,6 +1654,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/daily-observability-report.lock.yml b/.github/workflows/daily-observability-report.lock.yml
index 28914f4e79c..bd03e437343 100644
--- a/.github/workflows/daily-observability-report.lock.yml
+++ b/.github/workflows/daily-observability-report.lock.yml
@@ -1,4 +1,4 @@
-# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"eec38ff2db2d18443c69e9fbf1675b983fbf43e9a30479f42e7fbdb713bee43e","body_hash":"51cd9777f05356b7ce7b83a889ecc1f349e562ae451ee3010c47685b1b58e65a","strict":true,"agent_id":"codex","agent_model":"gpt-5.4","engine_versions":{"codex":"0.137.0"}}
+# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"050560ad945d68225b1e5ba62cc939368f10260aeb0a2b9f82d441c5eefd371b","body_hash":"51cd9777f05356b7ce7b83a889ecc1f349e562ae451ee3010c47685b1b58e65a","strict":true,"agent_id":"codex","agent_model":"gpt-5.4","engine_versions":{"codex":"0.137.0"}}
# gh-aw-manifest: {"version":1,"secrets":["CODEX_API_KEY","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_GRAFANA_AUTHORIZATION","GH_AW_OTEL_GRAFANA_ENDPOINT","GH_AW_OTEL_SENTRY_AUTHORIZATION","GH_AW_OTEL_SENTRY_ENDPOINT","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-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":"f9f3042f7e2789586610d6e8b85c8f03e5195baf","version":"v7.2.0"},{"repo":"docker/setup-buildx-action","sha":"d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5","version":"v4.1.0"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.65"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.65"},{"image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.65"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.65"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.23","digest":"sha256:0dd1bd91a41e24a3ccc31b1ec6cb61d36608997fabf91f2d643b64e3fc33180a","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.23@sha256:0dd1bd91a41e24a3ccc31b1ec6cb61d36608997fabf91f2d643b64e3fc33180a"},{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"},{"image":"node:lts-alpine","digest":"sha256:2bdb65ed1dab192432bc31c95f94155ca5ad7fc1392fb7eb7526ab682fa5bf14","pinned_image":"node:lts-alpine@sha256:2bdb65ed1dab192432bc31c95f94155ca5ad7fc1392fb7eb7526ab682fa5bf14"}]}
# ___ _ _
# / _ \ | | (_)
@@ -921,7 +921,7 @@ jobs:
printf '%s' "$(date +%s%3N)" > /tmp/gh-aw/agent_cli_start_ms.txt
mkdir -p "$CODEX_HOME/logs" && touch /tmp/gh-aw/agent-step-summary.md
(umask 177 && touch /tmp/gh-aw/agent-stdio.log)
- printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.65/awf-config.schema.json","network":{"allowDomains":["*.grafana.net","*.sentry.io","172.30.0.1","api.openai.com","api.snapcraft.io","archive.ubuntu.com","azure.archive.ubuntu.com","chatgpt.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","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","openai.com","packagecloud.io","packages.cloud.google.com","packages.microsoft.com","ppa.launchpad.net","s.symcb.com","s.symcd.com","security.ubuntu.com","ts-crl.ws.symantec.com","ts-ocsp.ws.symantec.com","www.googleapis.com"]},"apiProxy":{"enabled":true,"enableTokenSteering":true,"maxRuns":500,"maxEffectiveTokens":20000000,"maxAiCredits":1000,"models":{"agent":["sonnet-6x","gpt-5.4","gpt-5.3","gemini-pro","any"],"antigravity":["copilot/antigravity*","google/antigravity*","gemini/antigravity*"],"any":["copilot/*","anthropic/*","openai/*","google/*","gemini/*"],"claude":["agent"],"codex":["agent"],"coding":["copilot/gpt-5*codex*","openai/gpt-5*codex*","gpt-5-codex"],"computer-use":["copilot/*computer-use*","google/*computer-use*","gemini/*computer-use*","openai/*computer-use*"],"copilot":["agent"],"deep-research":["copilot/deep-research*","copilot/o3-deep-research*","copilot/o4-mini-deep-research*","google/deep-research*","gemini/deep-research*","openai/o3-deep-research*","openai/o4-mini-deep-research*"],"gemini":["agent"],"gemini-3-flash":["copilot/gemini-3*flash*","google/gemini-3*flash*","gemini/gemini-3*flash*"],"gemini-3-pro":["copilot/gemini-3*pro*","google/gemini-3*pro*","google/nano-banana*","gemini/gemini-3*pro*"],"gemini-3.1-flash":["copilot/gemini-3.1*flash*","google/gemini-3.1*flash*","gemini/gemini-3.1*flash*"],"gemini-3.1-pro":["copilot/gemini-3.1*pro*","google/gemini-3.1*pro*","gemini/gemini-3.1*pro*"],"gemini-3.5-flash":["copilot/gemini-3.5*flash*","google/gemini-3.5*flash*","gemini/gemini-3.5*flash*"],"gemini-flash":["copilot/gemini-*flash*","google/gemini-*flash*","gemini/gemini-*flash*"],"gemini-flash-lite":["copilot/gemini-*flash*lite*","google/gemini-*flash*lite*","gemini/gemini-*flash*lite*"],"gemini-pro":["copilot/gemini-*pro*","google/gemini-*pro*","gemini/gemini-*pro*"],"gemma":["copilot/gemma*","google/gemma*","gemini/gemma*"],"gpt-5":["copilot/gpt-5*","openai/gpt-5*"],"gpt-5-codex":["copilot/gpt-5*codex*","openai/gpt-5*codex*"],"gpt-5-mini":["copilot/gpt-5*mini*","openai/gpt-5*mini*"],"gpt-5-nano":["copilot/gpt-5*nano*","openai/gpt-5*nano*"],"gpt-5-pro":["copilot/gpt-5*pro*","openai/gpt-5*pro*"],"gpt-5.2":["copilot/gpt-5.2*","openai/gpt-5.2*"],"gpt-5.3":["copilot/gpt-5.3*","openai/gpt-5.3*"],"gpt-5.4":["copilot/gpt-5.4*","openai/gpt-5.4*"],"gpt-5.5":["copilot/gpt-5.5*","openai/gpt-5.5*"],"haiku":["copilot/*haiku*","anthropic/*haiku*"],"large":["sonnet","gpt-5-pro","gpt-5","gemini-pro"],"mai-code":["copilot/MAI-Code*","copilot/mai-code*","openai/MAI-Code*"],"mini":["haiku","gpt-5-mini","gpt-5-nano","gemini-flash-lite"],"nano-banana":["copilot/nano-banana*","google/nano-banana*","gemini/nano-banana*"],"opus":["copilot/*opus*","anthropic/*opus*"],"opusplan":["opus?effort=high"],"reasoning":["copilot/o1*","copilot/o3*","copilot/o4*","openai/o1*","openai/o3*","openai/o4*"],"robotics":["copilot/*robotics*","google/*robotics*","gemini/*robotics*"],"small":["mini"],"small-agent":["haiku","gpt-5-mini","gemini-flash","any"],"sonnet":["copilot/*sonnet*","anthropic/*sonnet*"],"sonnet-6x":["copilot/*sonnet-4.5*","copilot/*sonnet-4.6*","copilot/*sonnet-4-5-*","anthropic/*sonnet-4-5-*","copilot/*sonnet-4-6*","anthropic/*sonnet-4-6*"],"summarization":["haiku","gpt-5-mini","gemini-flash-lite","mini"],"vision":["copilot/gemini-*image*","gemini/gemini-*image*","copilot/gemini-*flash*","gemini/gemini-*flash*"]}},"container":{"imageTag":"0.25.65"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json"
+ printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.65/awf-config.schema.json","network":{"allowDomains":["*.grafana.net","*.sentry.io","172.30.0.1","api.openai.com","api.snapcraft.io","archive.ubuntu.com","azure.archive.ubuntu.com","chatgpt.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","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","openai.com","packagecloud.io","packages.cloud.google.com","packages.microsoft.com","ppa.launchpad.net","s.symcb.com","s.symcd.com","security.ubuntu.com","ts-crl.ws.symantec.com","ts-ocsp.ws.symantec.com","www.googleapis.com"]},"apiProxy":{"enabled":true,"enableTokenSteering":true,"maxRuns":500,"maxAiCredits":20000000,"models":{"agent":["sonnet-6x","gpt-5.4","gpt-5.3","gemini-pro","any"],"antigravity":["copilot/antigravity*","google/antigravity*","gemini/antigravity*"],"any":["copilot/*","anthropic/*","openai/*","google/*","gemini/*"],"claude":["agent"],"codex":["agent"],"coding":["copilot/gpt-5*codex*","openai/gpt-5*codex*","gpt-5-codex"],"computer-use":["copilot/*computer-use*","google/*computer-use*","gemini/*computer-use*","openai/*computer-use*"],"copilot":["agent"],"deep-research":["copilot/deep-research*","copilot/o3-deep-research*","copilot/o4-mini-deep-research*","google/deep-research*","gemini/deep-research*","openai/o3-deep-research*","openai/o4-mini-deep-research*"],"gemini":["agent"],"gemini-3-flash":["copilot/gemini-3*flash*","google/gemini-3*flash*","gemini/gemini-3*flash*"],"gemini-3-pro":["copilot/gemini-3*pro*","google/gemini-3*pro*","google/nano-banana*","gemini/gemini-3*pro*"],"gemini-3.1-flash":["copilot/gemini-3.1*flash*","google/gemini-3.1*flash*","gemini/gemini-3.1*flash*"],"gemini-3.1-pro":["copilot/gemini-3.1*pro*","google/gemini-3.1*pro*","gemini/gemini-3.1*pro*"],"gemini-3.5-flash":["copilot/gemini-3.5*flash*","google/gemini-3.5*flash*","gemini/gemini-3.5*flash*"],"gemini-flash":["copilot/gemini-*flash*","google/gemini-*flash*","gemini/gemini-*flash*"],"gemini-flash-lite":["copilot/gemini-*flash*lite*","google/gemini-*flash*lite*","gemini/gemini-*flash*lite*"],"gemini-pro":["copilot/gemini-*pro*","google/gemini-*pro*","gemini/gemini-*pro*"],"gemma":["copilot/gemma*","google/gemma*","gemini/gemma*"],"gpt-5":["copilot/gpt-5*","openai/gpt-5*"],"gpt-5-codex":["copilot/gpt-5*codex*","openai/gpt-5*codex*"],"gpt-5-mini":["copilot/gpt-5*mini*","openai/gpt-5*mini*"],"gpt-5-nano":["copilot/gpt-5*nano*","openai/gpt-5*nano*"],"gpt-5-pro":["copilot/gpt-5*pro*","openai/gpt-5*pro*"],"gpt-5.2":["copilot/gpt-5.2*","openai/gpt-5.2*"],"gpt-5.3":["copilot/gpt-5.3*","openai/gpt-5.3*"],"gpt-5.4":["copilot/gpt-5.4*","openai/gpt-5.4*"],"gpt-5.5":["copilot/gpt-5.5*","openai/gpt-5.5*"],"haiku":["copilot/*haiku*","anthropic/*haiku*"],"large":["sonnet","gpt-5-pro","gpt-5","gemini-pro"],"mai-code":["copilot/MAI-Code*","copilot/mai-code*","openai/MAI-Code*"],"mini":["haiku","gpt-5-mini","gpt-5-nano","gemini-flash-lite"],"nano-banana":["copilot/nano-banana*","google/nano-banana*","gemini/nano-banana*"],"opus":["copilot/*opus*","anthropic/*opus*"],"opusplan":["opus?effort=high"],"reasoning":["copilot/o1*","copilot/o3*","copilot/o4*","openai/o1*","openai/o3*","openai/o4*"],"robotics":["copilot/*robotics*","google/*robotics*","gemini/*robotics*"],"small":["mini"],"small-agent":["haiku","gpt-5-mini","gemini-flash","any"],"sonnet":["copilot/*sonnet*","anthropic/*sonnet*"],"sonnet-6x":["copilot/*sonnet-4.5*","copilot/*sonnet-4.6*","copilot/*sonnet-4-5-*","anthropic/*sonnet-4-5-*","copilot/*sonnet-4-6*","anthropic/*sonnet-4-6*"],"summarization":["haiku","gpt-5-mini","gemini-flash-lite","mini"],"vision":["copilot/gemini-*image*","gemini/gemini-*image*","copilot/gemini-*flash*","gemini/gemini-*flash*"]}},"container":{"imageTag":"0.25.65"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json"
GH_AW_MODEL_MULTIPLIERS_PATH="/tmp/gh-aw/model_multipliers.json" node "${RUNNER_TEMP}/gh-aw/actions/merge_awf_model_multipliers.cjs"
cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json
export GH_AW_MODELS_JSON_PATH="${RUNNER_TEMP}/gh-aw/actions/models.json"
@@ -1286,7 +1286,6 @@ jobs:
GH_AW_MISSING_TOOL_REPORT_AS_FAILURE: "true"
GH_AW_MISSING_DATA_REPORT_AS_FAILURE: "true"
GH_AW_TIMEOUT_MINUTES: "45"
- GH_AW_MAX_EFFECTIVE_TOKENS: "20000000"
with:
github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
script: |
@@ -1510,7 +1509,7 @@ jobs:
printf '%s' "$(date +%s%3N)" > /tmp/gh-aw/agent_cli_start_ms.txt
mkdir -p "$CODEX_HOME/logs" && touch /tmp/gh-aw/agent-step-summary.md && mkdir -p /tmp/gh-aw/threat-detection && printf '%s' '{"type":"object","properties":{"prompt_injection":{"type":"boolean"},"secret_leak":{"type":"boolean"},"malicious_patch":{"type":"boolean"},"reasons":{"type":"array","items":{"type":"string"}}},"required":["prompt_injection","secret_leak","malicious_patch","reasons"],"additionalProperties":false}' > /tmp/gh-aw/threat-detection/detection_schema.json
(umask 177 && touch /tmp/gh-aw/threat-detection/detection.log)
- printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.65/awf-config.schema.json","network":{"allowDomains":["172.30.0.1","api.openai.com","chatgpt.com","host.docker.internal","openai.com"]},"apiProxy":{"enabled":true,"enableTokenSteering":true,"maxRuns":500,"maxEffectiveTokens":20000000,"maxAiCredits":1000},"container":{"imageTag":"0.25.65"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json"
+ printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.65/awf-config.schema.json","network":{"allowDomains":["172.30.0.1","api.openai.com","chatgpt.com","host.docker.internal","openai.com"]},"apiProxy":{"enabled":true,"enableTokenSteering":true,"maxRuns":500,"maxAiCredits":1000},"container":{"imageTag":"0.25.65"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json"
GH_AW_MODEL_MULTIPLIERS_PATH="/tmp/gh-aw/model_multipliers.json" node "${RUNNER_TEMP}/gh-aw/actions/merge_awf_model_multipliers.cjs"
cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json
export GH_AW_MODELS_JSON_PATH="${RUNNER_TEMP}/gh-aw/actions/models.json"
diff --git a/.github/workflows/daily-observability-report.md b/.github/workflows/daily-observability-report.md
index 37dae7c9244..3c962d931ff 100644
--- a/.github/workflows/daily-observability-report.md
+++ b/.github/workflows/daily-observability-report.md
@@ -21,7 +21,7 @@ timeout-minutes: 45
# - run 26424799100: 7,479,570 ET
# - run 26197188358: 7,244,916 ET
# 20M preserves >2.5x headroom over the recent peak while keeping daily budget hygiene.
-max-effective-tokens: 20000000
+max-ai-credits: 20000000
imports:
- uses: shared/meta-analysis-base.md
with:
diff --git a/.github/workflows/daily-performance-summary.lock.yml b/.github/workflows/daily-performance-summary.lock.yml
index a16999f787b..cef54901ece 100644
--- a/.github/workflows/daily-performance-summary.lock.yml
+++ b/.github/workflows/daily-performance-summary.lock.yml
@@ -1366,6 +1366,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 30
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1943,6 +1944,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/daily-regulatory.lock.yml b/.github/workflows/daily-regulatory.lock.yml
index 6788be5f9f9..77ae3cacece 100644
--- a/.github/workflows/daily-regulatory.lock.yml
+++ b/.github/workflows/daily-regulatory.lock.yml
@@ -1330,6 +1330,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 30
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1873,6 +1874,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/daily-repo-chronicle.lock.yml b/.github/workflows/daily-repo-chronicle.lock.yml
index e3c7e66d6d2..e5a1adbf8a0 100644
--- a/.github/workflows/daily-repo-chronicle.lock.yml
+++ b/.github/workflows/daily-repo-chronicle.lock.yml
@@ -882,6 +882,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 45
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1449,6 +1450,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/daily-safe-output-integrator.lock.yml b/.github/workflows/daily-safe-output-integrator.lock.yml
index 1a9ccc98307..b90e7543e73 100644
--- a/.github/workflows/daily-safe-output-integrator.lock.yml
+++ b/.github/workflows/daily-safe-output-integrator.lock.yml
@@ -894,6 +894,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1434,6 +1435,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/daily-safe-output-optimizer.lock.yml b/.github/workflows/daily-safe-output-optimizer.lock.yml
index f2c86972371..569ab11e518 100644
--- a/.github/workflows/daily-safe-output-optimizer.lock.yml
+++ b/.github/workflows/daily-safe-output-optimizer.lock.yml
@@ -1,4 +1,4 @@
-# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"04366649686227e638bb3ed7225f26a146a28ed98e04fcfbfdb81f5958c0846c","body_hash":"da3a8cae1614a1d27ac16c72c961885d27d86a5076895aff36f71b20cdce6e42","strict":true,"agent_id":"claude","engine_versions":{"claude":"2.1.165"}}
+# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"0c22dda43dd65073a3f0cdb7756c1b7b040e38b67ed12dc48891203c4448ce30","body_hash":"da3a8cae1614a1d27ac16c72c961885d27d86a5076895aff36f71b20cdce6e42","strict":true,"agent_id":"claude","engine_versions":{"claude":"2.1.165"}}
# gh-aw-manifest: {"version":1,"secrets":["ANTHROPIC_API_KEY","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_GRAFANA_AUTHORIZATION","GH_AW_OTEL_GRAFANA_ENDPOINT","GH_AW_OTEL_SENTRY_AUTHORIZATION","GH_AW_OTEL_SENTRY_ENDPOINT","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-go","sha":"4a3601121dd01d1626a1e23e37211e3254c1c06c","version":"v6.4.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"docker/build-push-action","sha":"f9f3042f7e2789586610d6e8b85c8f03e5195baf","version":"v7.2.0"},{"repo":"docker/setup-buildx-action","sha":"d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5","version":"v4.1.0"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.65"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.65"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.65"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.23","digest":"sha256:0dd1bd91a41e24a3ccc31b1ec6cb61d36608997fabf91f2d643b64e3fc33180a","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.23@sha256:0dd1bd91a41e24a3ccc31b1ec6cb61d36608997fabf91f2d643b64e3fc33180a"},{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"},{"image":"node:lts-alpine","digest":"sha256:2bdb65ed1dab192432bc31c95f94155ca5ad7fc1392fb7eb7526ab682fa5bf14","pinned_image":"node:lts-alpine@sha256:2bdb65ed1dab192432bc31c95f94155ca5ad7fc1392fb7eb7526ab682fa5bf14"}]}
# ___ _ _
# / _ \ | | (_)
@@ -1047,7 +1047,7 @@ jobs:
printf '%s' "$(date +%s%3N)" > /tmp/gh-aw/agent_cli_start_ms.txt
touch /tmp/gh-aw/agent-step-summary.md
(umask 177 && touch /tmp/gh-aw/agent-stdio.log)
- printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.65/awf-config.schema.json","network":{"allowDomains":["*.githubusercontent.com","*.grafana.net","*.sentry.io","anthropic.com","api.anthropic.com","api.github.com","api.snapcraft.io","archive.ubuntu.com","azure.archive.ubuntu.com","cdn.playwright.dev","codeload.github.com","crl.geotrust.com","crl.globalsign.com","crl.identrust.com","crl.sectigo.com","crl.thawte.com","crl.usertrust.com","crl.verisign.com","crl3.digicert.com","crl4.digicert.com","crls.ssl.com","files.pythonhosted.org","ghcr.io","github-cloud.githubusercontent.com","github-cloud.s3.amazonaws.com","github.com","host.docker.internal","json-schema.org","json.schemastore.org","keyserver.ubuntu.com","lfs.github.com","objects.githubusercontent.com","ocsp.digicert.com","ocsp.geotrust.com","ocsp.globalsign.com","ocsp.identrust.com","ocsp.sectigo.com","ocsp.ssl.com","ocsp.thawte.com","ocsp.usertrust.com","ocsp.verisign.com","packagecloud.io","packages.cloud.google.com","packages.microsoft.com","playwright.download.prss.microsoft.com","ppa.launchpad.net","pypi.org","raw.githubusercontent.com","registry.npmjs.org","s.symcb.com","s.symcd.com","security.ubuntu.com","sentry.io","statsig.anthropic.com","ts-crl.ws.symantec.com","ts-ocsp.ws.symantec.com","www.googleapis.com"]},"apiProxy":{"enabled":true,"enableTokenSteering":true,"maxRuns":200,"maxEffectiveTokens":40000000,"maxAiCredits":1000,"models":{"agent":["sonnet-6x","gpt-5.4","gpt-5.3","gemini-pro","any"],"antigravity":["copilot/antigravity*","google/antigravity*","gemini/antigravity*"],"any":["copilot/*","anthropic/*","openai/*","google/*","gemini/*"],"claude":["agent"],"codex":["agent"],"coding":["copilot/gpt-5*codex*","openai/gpt-5*codex*","gpt-5-codex"],"computer-use":["copilot/*computer-use*","google/*computer-use*","gemini/*computer-use*","openai/*computer-use*"],"copilot":["agent"],"deep-research":["copilot/deep-research*","copilot/o3-deep-research*","copilot/o4-mini-deep-research*","google/deep-research*","gemini/deep-research*","openai/o3-deep-research*","openai/o4-mini-deep-research*"],"gemini":["agent"],"gemini-3-flash":["copilot/gemini-3*flash*","google/gemini-3*flash*","gemini/gemini-3*flash*"],"gemini-3-pro":["copilot/gemini-3*pro*","google/gemini-3*pro*","google/nano-banana*","gemini/gemini-3*pro*"],"gemini-3.1-flash":["copilot/gemini-3.1*flash*","google/gemini-3.1*flash*","gemini/gemini-3.1*flash*"],"gemini-3.1-pro":["copilot/gemini-3.1*pro*","google/gemini-3.1*pro*","gemini/gemini-3.1*pro*"],"gemini-3.5-flash":["copilot/gemini-3.5*flash*","google/gemini-3.5*flash*","gemini/gemini-3.5*flash*"],"gemini-flash":["copilot/gemini-*flash*","google/gemini-*flash*","gemini/gemini-*flash*"],"gemini-flash-lite":["copilot/gemini-*flash*lite*","google/gemini-*flash*lite*","gemini/gemini-*flash*lite*"],"gemini-pro":["copilot/gemini-*pro*","google/gemini-*pro*","gemini/gemini-*pro*"],"gemma":["copilot/gemma*","google/gemma*","gemini/gemma*"],"gpt-5":["copilot/gpt-5*","openai/gpt-5*"],"gpt-5-codex":["copilot/gpt-5*codex*","openai/gpt-5*codex*"],"gpt-5-mini":["copilot/gpt-5*mini*","openai/gpt-5*mini*"],"gpt-5-nano":["copilot/gpt-5*nano*","openai/gpt-5*nano*"],"gpt-5-pro":["copilot/gpt-5*pro*","openai/gpt-5*pro*"],"gpt-5.2":["copilot/gpt-5.2*","openai/gpt-5.2*"],"gpt-5.3":["copilot/gpt-5.3*","openai/gpt-5.3*"],"gpt-5.4":["copilot/gpt-5.4*","openai/gpt-5.4*"],"gpt-5.5":["copilot/gpt-5.5*","openai/gpt-5.5*"],"haiku":["copilot/*haiku*","anthropic/*haiku*"],"large":["sonnet","gpt-5-pro","gpt-5","gemini-pro"],"mai-code":["copilot/MAI-Code*","copilot/mai-code*","openai/MAI-Code*"],"mini":["haiku","gpt-5-mini","gpt-5-nano","gemini-flash-lite"],"nano-banana":["copilot/nano-banana*","google/nano-banana*","gemini/nano-banana*"],"opus":["copilot/*opus*","anthropic/*opus*"],"opusplan":["opus?effort=high"],"reasoning":["copilot/o1*","copilot/o3*","copilot/o4*","openai/o1*","openai/o3*","openai/o4*"],"robotics":["copilot/*robotics*","google/*robotics*","gemini/*robotics*"],"small":["mini"],"small-agent":["haiku","gpt-5-mini","gemini-flash","any"],"sonnet":["copilot/*sonnet*","anthropic/*sonnet*"],"sonnet-6x":["copilot/*sonnet-4.5*","copilot/*sonnet-4.6*","copilot/*sonnet-4-5-*","anthropic/*sonnet-4-5-*","copilot/*sonnet-4-6*","anthropic/*sonnet-4-6*"],"summarization":["haiku","gpt-5-mini","gemini-flash-lite","mini"],"vision":["copilot/gemini-*image*","gemini/gemini-*image*","copilot/gemini-*flash*","gemini/gemini-*flash*"]}},"container":{"imageTag":"0.25.65"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json"
+ printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.65/awf-config.schema.json","network":{"allowDomains":["*.githubusercontent.com","*.grafana.net","*.sentry.io","anthropic.com","api.anthropic.com","api.github.com","api.snapcraft.io","archive.ubuntu.com","azure.archive.ubuntu.com","cdn.playwright.dev","codeload.github.com","crl.geotrust.com","crl.globalsign.com","crl.identrust.com","crl.sectigo.com","crl.thawte.com","crl.usertrust.com","crl.verisign.com","crl3.digicert.com","crl4.digicert.com","crls.ssl.com","files.pythonhosted.org","ghcr.io","github-cloud.githubusercontent.com","github-cloud.s3.amazonaws.com","github.com","host.docker.internal","json-schema.org","json.schemastore.org","keyserver.ubuntu.com","lfs.github.com","objects.githubusercontent.com","ocsp.digicert.com","ocsp.geotrust.com","ocsp.globalsign.com","ocsp.identrust.com","ocsp.sectigo.com","ocsp.ssl.com","ocsp.thawte.com","ocsp.usertrust.com","ocsp.verisign.com","packagecloud.io","packages.cloud.google.com","packages.microsoft.com","playwright.download.prss.microsoft.com","ppa.launchpad.net","pypi.org","raw.githubusercontent.com","registry.npmjs.org","s.symcb.com","s.symcd.com","security.ubuntu.com","sentry.io","statsig.anthropic.com","ts-crl.ws.symantec.com","ts-ocsp.ws.symantec.com","www.googleapis.com"]},"apiProxy":{"enabled":true,"enableTokenSteering":true,"maxRuns":200,"maxAiCredits":40000000,"models":{"agent":["sonnet-6x","gpt-5.4","gpt-5.3","gemini-pro","any"],"antigravity":["copilot/antigravity*","google/antigravity*","gemini/antigravity*"],"any":["copilot/*","anthropic/*","openai/*","google/*","gemini/*"],"claude":["agent"],"codex":["agent"],"coding":["copilot/gpt-5*codex*","openai/gpt-5*codex*","gpt-5-codex"],"computer-use":["copilot/*computer-use*","google/*computer-use*","gemini/*computer-use*","openai/*computer-use*"],"copilot":["agent"],"deep-research":["copilot/deep-research*","copilot/o3-deep-research*","copilot/o4-mini-deep-research*","google/deep-research*","gemini/deep-research*","openai/o3-deep-research*","openai/o4-mini-deep-research*"],"gemini":["agent"],"gemini-3-flash":["copilot/gemini-3*flash*","google/gemini-3*flash*","gemini/gemini-3*flash*"],"gemini-3-pro":["copilot/gemini-3*pro*","google/gemini-3*pro*","google/nano-banana*","gemini/gemini-3*pro*"],"gemini-3.1-flash":["copilot/gemini-3.1*flash*","google/gemini-3.1*flash*","gemini/gemini-3.1*flash*"],"gemini-3.1-pro":["copilot/gemini-3.1*pro*","google/gemini-3.1*pro*","gemini/gemini-3.1*pro*"],"gemini-3.5-flash":["copilot/gemini-3.5*flash*","google/gemini-3.5*flash*","gemini/gemini-3.5*flash*"],"gemini-flash":["copilot/gemini-*flash*","google/gemini-*flash*","gemini/gemini-*flash*"],"gemini-flash-lite":["copilot/gemini-*flash*lite*","google/gemini-*flash*lite*","gemini/gemini-*flash*lite*"],"gemini-pro":["copilot/gemini-*pro*","google/gemini-*pro*","gemini/gemini-*pro*"],"gemma":["copilot/gemma*","google/gemma*","gemini/gemma*"],"gpt-5":["copilot/gpt-5*","openai/gpt-5*"],"gpt-5-codex":["copilot/gpt-5*codex*","openai/gpt-5*codex*"],"gpt-5-mini":["copilot/gpt-5*mini*","openai/gpt-5*mini*"],"gpt-5-nano":["copilot/gpt-5*nano*","openai/gpt-5*nano*"],"gpt-5-pro":["copilot/gpt-5*pro*","openai/gpt-5*pro*"],"gpt-5.2":["copilot/gpt-5.2*","openai/gpt-5.2*"],"gpt-5.3":["copilot/gpt-5.3*","openai/gpt-5.3*"],"gpt-5.4":["copilot/gpt-5.4*","openai/gpt-5.4*"],"gpt-5.5":["copilot/gpt-5.5*","openai/gpt-5.5*"],"haiku":["copilot/*haiku*","anthropic/*haiku*"],"large":["sonnet","gpt-5-pro","gpt-5","gemini-pro"],"mai-code":["copilot/MAI-Code*","copilot/mai-code*","openai/MAI-Code*"],"mini":["haiku","gpt-5-mini","gpt-5-nano","gemini-flash-lite"],"nano-banana":["copilot/nano-banana*","google/nano-banana*","gemini/nano-banana*"],"opus":["copilot/*opus*","anthropic/*opus*"],"opusplan":["opus?effort=high"],"reasoning":["copilot/o1*","copilot/o3*","copilot/o4*","openai/o1*","openai/o3*","openai/o4*"],"robotics":["copilot/*robotics*","google/*robotics*","gemini/*robotics*"],"small":["mini"],"small-agent":["haiku","gpt-5-mini","gemini-flash","any"],"sonnet":["copilot/*sonnet*","anthropic/*sonnet*"],"sonnet-6x":["copilot/*sonnet-4.5*","copilot/*sonnet-4.6*","copilot/*sonnet-4-5-*","anthropic/*sonnet-4-5-*","copilot/*sonnet-4-6*","anthropic/*sonnet-4-6*"],"summarization":["haiku","gpt-5-mini","gemini-flash-lite","mini"],"vision":["copilot/gemini-*image*","gemini/gemini-*image*","copilot/gemini-*flash*","gemini/gemini-*flash*"]}},"container":{"imageTag":"0.25.65"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json"
GH_AW_MODEL_MULTIPLIERS_PATH="/tmp/gh-aw/model_multipliers.json" node "${RUNNER_TEMP}/gh-aw/actions/merge_awf_model_multipliers.cjs"
cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json
export GH_AW_MODELS_JSON_PATH="${RUNNER_TEMP}/gh-aw/actions/models.json"
@@ -1425,7 +1425,6 @@ jobs:
GH_AW_MISSING_TOOL_REPORT_AS_FAILURE: "true"
GH_AW_MISSING_DATA_REPORT_AS_FAILURE: "true"
GH_AW_TIMEOUT_MINUTES: "30"
- GH_AW_MAX_EFFECTIVE_TOKENS: "40000000"
GH_AW_CACHE_MEMORY_ENABLED: "true"
with:
github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
@@ -1588,7 +1587,7 @@ jobs:
printf '%s' "$(date +%s%3N)" > /tmp/gh-aw/agent_cli_start_ms.txt
touch /tmp/gh-aw/agent-step-summary.md
(umask 177 && touch /tmp/gh-aw/threat-detection/detection.log)
- printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.65/awf-config.schema.json","network":{"allowDomains":["*.githubusercontent.com","anthropic.com","api.anthropic.com","api.github.com","api.snapcraft.io","archive.ubuntu.com","azure.archive.ubuntu.com","cdn.playwright.dev","codeload.github.com","crl.geotrust.com","crl.globalsign.com","crl.identrust.com","crl.sectigo.com","crl.thawte.com","crl.usertrust.com","crl.verisign.com","crl3.digicert.com","crl4.digicert.com","crls.ssl.com","files.pythonhosted.org","ghcr.io","github-cloud.githubusercontent.com","github-cloud.s3.amazonaws.com","github.com","host.docker.internal","json-schema.org","json.schemastore.org","keyserver.ubuntu.com","lfs.github.com","objects.githubusercontent.com","ocsp.digicert.com","ocsp.geotrust.com","ocsp.globalsign.com","ocsp.identrust.com","ocsp.sectigo.com","ocsp.ssl.com","ocsp.thawte.com","ocsp.usertrust.com","ocsp.verisign.com","packagecloud.io","packages.cloud.google.com","packages.microsoft.com","playwright.download.prss.microsoft.com","ppa.launchpad.net","pypi.org","raw.githubusercontent.com","registry.npmjs.org","s.symcb.com","s.symcd.com","security.ubuntu.com","sentry.io","statsig.anthropic.com","ts-crl.ws.symantec.com","ts-ocsp.ws.symantec.com"]},"apiProxy":{"enabled":true,"enableTokenSteering":true,"maxRuns":500,"maxEffectiveTokens":40000000,"maxAiCredits":1000},"container":{"imageTag":"0.25.65"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json"
+ printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.65/awf-config.schema.json","network":{"allowDomains":["*.githubusercontent.com","anthropic.com","api.anthropic.com","api.github.com","api.snapcraft.io","archive.ubuntu.com","azure.archive.ubuntu.com","cdn.playwright.dev","codeload.github.com","crl.geotrust.com","crl.globalsign.com","crl.identrust.com","crl.sectigo.com","crl.thawte.com","crl.usertrust.com","crl.verisign.com","crl3.digicert.com","crl4.digicert.com","crls.ssl.com","files.pythonhosted.org","ghcr.io","github-cloud.githubusercontent.com","github-cloud.s3.amazonaws.com","github.com","host.docker.internal","json-schema.org","json.schemastore.org","keyserver.ubuntu.com","lfs.github.com","objects.githubusercontent.com","ocsp.digicert.com","ocsp.geotrust.com","ocsp.globalsign.com","ocsp.identrust.com","ocsp.sectigo.com","ocsp.ssl.com","ocsp.thawte.com","ocsp.usertrust.com","ocsp.verisign.com","packagecloud.io","packages.cloud.google.com","packages.microsoft.com","playwright.download.prss.microsoft.com","ppa.launchpad.net","pypi.org","raw.githubusercontent.com","registry.npmjs.org","s.symcb.com","s.symcd.com","security.ubuntu.com","sentry.io","statsig.anthropic.com","ts-crl.ws.symantec.com","ts-ocsp.ws.symantec.com"]},"apiProxy":{"enabled":true,"enableTokenSteering":true,"maxRuns":500,"maxAiCredits":1000},"container":{"imageTag":"0.25.65"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json"
GH_AW_MODEL_MULTIPLIERS_PATH="/tmp/gh-aw/model_multipliers.json" node "${RUNNER_TEMP}/gh-aw/actions/merge_awf_model_multipliers.cjs"
cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json
export GH_AW_MODELS_JSON_PATH="${RUNNER_TEMP}/gh-aw/actions/models.json"
diff --git a/.github/workflows/daily-safe-output-optimizer.md b/.github/workflows/daily-safe-output-optimizer.md
index dd28fccd7dc..a0edf5a07b8 100644
--- a/.github/workflows/daily-safe-output-optimizer.md
+++ b/.github/workflows/daily-safe-output-optimizer.md
@@ -22,7 +22,7 @@ safe-outputs:
timeout-minutes: 30
max-runs: 200
-max-effective-tokens: 40000000
+max-ai-credits: 40000000
strict: true
imports:
diff --git a/.github/workflows/daily-secrets-analysis.lock.yml b/.github/workflows/daily-secrets-analysis.lock.yml
index ddb7f227952..2624f2feb47 100644
--- a/.github/workflows/daily-secrets-analysis.lock.yml
+++ b/.github/workflows/daily-secrets-analysis.lock.yml
@@ -813,6 +813,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1350,6 +1351,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/daily-security-observability.lock.yml b/.github/workflows/daily-security-observability.lock.yml
index 54e0db18333..f35530439cb 100644
--- a/.github/workflows/daily-security-observability.lock.yml
+++ b/.github/workflows/daily-security-observability.lock.yml
@@ -1009,6 +1009,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 60
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1576,6 +1577,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/daily-semgrep-scan.lock.yml b/.github/workflows/daily-semgrep-scan.lock.yml
index a15dc34ad6f..1c69a9b9692 100644
--- a/.github/workflows/daily-semgrep-scan.lock.yml
+++ b/.github/workflows/daily-semgrep-scan.lock.yml
@@ -897,6 +897,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 30
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1429,6 +1430,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/daily-sentrux-report.lock.yml b/.github/workflows/daily-sentrux-report.lock.yml
index 66c9044e378..abd9eb2306e 100644
--- a/.github/workflows/daily-sentrux-report.lock.yml
+++ b/.github/workflows/daily-sentrux-report.lock.yml
@@ -859,6 +859,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 30
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1406,6 +1407,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/daily-skill-optimizer.lock.yml b/.github/workflows/daily-skill-optimizer.lock.yml
index 661d2cf67c7..57d72494d2f 100644
--- a/.github/workflows/daily-skill-optimizer.lock.yml
+++ b/.github/workflows/daily-skill-optimizer.lock.yml
@@ -840,6 +840,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 45
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1370,6 +1371,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/daily-spdd-spec-planner.lock.yml b/.github/workflows/daily-spdd-spec-planner.lock.yml
index 02782ba9ef5..60f6b40c088 100644
--- a/.github/workflows/daily-spdd-spec-planner.lock.yml
+++ b/.github/workflows/daily-spdd-spec-planner.lock.yml
@@ -876,6 +876,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1431,6 +1432,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/daily-syntax-error-quality.lock.yml b/.github/workflows/daily-syntax-error-quality.lock.yml
index 318b944cf3f..81863eba2e6 100644
--- a/.github/workflows/daily-syntax-error-quality.lock.yml
+++ b/.github/workflows/daily-syntax-error-quality.lock.yml
@@ -865,6 +865,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1394,6 +1395,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/daily-team-status.lock.yml b/.github/workflows/daily-team-status.lock.yml
index 5eed1d6bd1a..8e24fc01978 100644
--- a/.github/workflows/daily-team-status.lock.yml
+++ b/.github/workflows/daily-team-status.lock.yml
@@ -875,6 +875,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 10
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1414,6 +1415,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/daily-testify-uber-super-expert.lock.yml b/.github/workflows/daily-testify-uber-super-expert.lock.yml
index ff4c3e53076..63f66bf1902 100644
--- a/.github/workflows/daily-testify-uber-super-expert.lock.yml
+++ b/.github/workflows/daily-testify-uber-super-expert.lock.yml
@@ -952,6 +952,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1506,6 +1507,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/daily-workflow-updater.lock.yml b/.github/workflows/daily-workflow-updater.lock.yml
index 53721f5cba7..1b3906bbf11 100644
--- a/.github/workflows/daily-workflow-updater.lock.yml
+++ b/.github/workflows/daily-workflow-updater.lock.yml
@@ -824,6 +824,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 15
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1361,6 +1362,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/dataflow-pr-discussion-dataset.lock.yml b/.github/workflows/dataflow-pr-discussion-dataset.lock.yml
index 961139ebd26..67fb19879f5 100644
--- a/.github/workflows/dataflow-pr-discussion-dataset.lock.yml
+++ b/.github/workflows/dataflow-pr-discussion-dataset.lock.yml
@@ -1138,6 +1138,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 30
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1734,6 +1735,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/dead-code-remover.lock.yml b/.github/workflows/dead-code-remover.lock.yml
index 22272f6d7d4..1bbc3872c5d 100644
--- a/.github/workflows/dead-code-remover.lock.yml
+++ b/.github/workflows/dead-code-remover.lock.yml
@@ -876,6 +876,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 30
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1428,6 +1429,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/delight.lock.yml b/.github/workflows/delight.lock.yml
index fc7f6e4b094..0279dad6fd4 100644
--- a/.github/workflows/delight.lock.yml
+++ b/.github/workflows/delight.lock.yml
@@ -908,6 +908,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 30
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1466,6 +1467,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/dependabot-burner.lock.yml b/.github/workflows/dependabot-burner.lock.yml
index 0269879d382..7454a720980 100644
--- a/.github/workflows/dependabot-burner.lock.yml
+++ b/.github/workflows/dependabot-burner.lock.yml
@@ -826,6 +826,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1350,6 +1351,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/dependabot-campaign.lock.yml b/.github/workflows/dependabot-campaign.lock.yml
index b6c3424361a..380fbbac2e5 100644
--- a/.github/workflows/dependabot-campaign.lock.yml
+++ b/.github/workflows/dependabot-campaign.lock.yml
@@ -829,6 +829,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 15
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1387,6 +1388,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/dependabot-go-checker.lock.yml b/.github/workflows/dependabot-go-checker.lock.yml
index e9e7b939274..561d0f4c038 100644
--- a/.github/workflows/dependabot-go-checker.lock.yml
+++ b/.github/workflows/dependabot-go-checker.lock.yml
@@ -888,6 +888,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1419,6 +1420,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/dependabot-repair.lock.yml b/.github/workflows/dependabot-repair.lock.yml
index a5c1bf307c8..0f8d7119896 100644
--- a/.github/workflows/dependabot-repair.lock.yml
+++ b/.github/workflows/dependabot-repair.lock.yml
@@ -926,6 +926,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 45
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1461,6 +1462,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/dependabot-worker.lock.yml b/.github/workflows/dependabot-worker.lock.yml
index f45da7d017b..c8b6cbcd3ed 100644
--- a/.github/workflows/dependabot-worker.lock.yml
+++ b/.github/workflows/dependabot-worker.lock.yml
@@ -974,6 +974,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 30
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1508,6 +1509,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/deployment-incident-monitor.lock.yml b/.github/workflows/deployment-incident-monitor.lock.yml
index f07797b7b6b..b0bcccd112c 100644
--- a/.github/workflows/deployment-incident-monitor.lock.yml
+++ b/.github/workflows/deployment-incident-monitor.lock.yml
@@ -834,6 +834,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 10
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1363,6 +1364,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/designer-drift-audit.lock.yml b/.github/workflows/designer-drift-audit.lock.yml
index ca10148c7ce..01091bcde71 100644
--- a/.github/workflows/designer-drift-audit.lock.yml
+++ b/.github/workflows/designer-drift-audit.lock.yml
@@ -792,6 +792,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1310,6 +1311,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/dev-hawk.lock.yml b/.github/workflows/dev-hawk.lock.yml
index 382f512cab4..725bf80b8e4 100644
--- a/.github/workflows/dev-hawk.lock.yml
+++ b/.github/workflows/dev-hawk.lock.yml
@@ -943,6 +943,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 15
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1475,6 +1476,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/dictation-prompt.lock.yml b/.github/workflows/dictation-prompt.lock.yml
index 0c1d73d91f4..1652db73a2c 100644
--- a/.github/workflows/dictation-prompt.lock.yml
+++ b/.github/workflows/dictation-prompt.lock.yml
@@ -826,6 +826,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 10
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1358,6 +1359,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/discussion-task-miner.lock.yml b/.github/workflows/discussion-task-miner.lock.yml
index a7a65d2de9a..9b3336262c7 100644
--- a/.github/workflows/discussion-task-miner.lock.yml
+++ b/.github/workflows/discussion-task-miner.lock.yml
@@ -889,6 +889,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1448,6 +1449,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/docs-noob-tester.lock.yml b/.github/workflows/docs-noob-tester.lock.yml
index 2a05ec8ba34..3a946390652 100644
--- a/.github/workflows/docs-noob-tester.lock.yml
+++ b/.github/workflows/docs-noob-tester.lock.yml
@@ -873,6 +873,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 30
GH_AW_TOOL_TIMEOUT: 120
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
@@ -1411,6 +1412,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/draft-pr-cleanup.lock.yml b/.github/workflows/draft-pr-cleanup.lock.yml
index 6a1f0bbc09f..8f735698872 100644
--- a/.github/workflows/draft-pr-cleanup.lock.yml
+++ b/.github/workflows/draft-pr-cleanup.lock.yml
@@ -860,6 +860,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1392,6 +1393,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/example-permissions-warning.lock.yml b/.github/workflows/example-permissions-warning.lock.yml
index ae98455324e..0baea874fdf 100644
--- a/.github/workflows/example-permissions-warning.lock.yml
+++ b/.github/workflows/example-permissions-warning.lock.yml
@@ -747,6 +747,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 5
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/firewall-escape.lock.yml b/.github/workflows/firewall-escape.lock.yml
index 5ee49571903..3603a3cc35e 100644
--- a/.github/workflows/firewall-escape.lock.yml
+++ b/.github/workflows/firewall-escape.lock.yml
@@ -882,6 +882,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 60
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1460,6 +1461,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/firewall.lock.yml b/.github/workflows/firewall.lock.yml
index 4024954dae8..9682ed87e08 100644
--- a/.github/workflows/firewall.lock.yml
+++ b/.github/workflows/firewall.lock.yml
@@ -755,6 +755,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 5
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/functional-pragmatist.lock.yml b/.github/workflows/functional-pragmatist.lock.yml
index 8a2e0bb3dd9..9478c90aca4 100644
--- a/.github/workflows/functional-pragmatist.lock.yml
+++ b/.github/workflows/functional-pragmatist.lock.yml
@@ -837,6 +837,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 45
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1369,6 +1370,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/github-remote-mcp-auth-test.lock.yml b/.github/workflows/github-remote-mcp-auth-test.lock.yml
index 7cfb5786d98..86b0a9e9a44 100644
--- a/.github/workflows/github-remote-mcp-auth-test.lock.yml
+++ b/.github/workflows/github-remote-mcp-auth-test.lock.yml
@@ -834,6 +834,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 5
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1361,6 +1362,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/glossary-maintainer.lock.yml b/.github/workflows/glossary-maintainer.lock.yml
index 5166e398f3e..af2cb73cade 100644
--- a/.github/workflows/glossary-maintainer.lock.yml
+++ b/.github/workflows/glossary-maintainer.lock.yml
@@ -966,6 +966,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1538,6 +1539,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/gpclean.lock.yml b/.github/workflows/gpclean.lock.yml
index fb225411ec6..595d583f35f 100644
--- a/.github/workflows/gpclean.lock.yml
+++ b/.github/workflows/gpclean.lock.yml
@@ -897,6 +897,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 30
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1448,6 +1449,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/hippo-embed.lock.yml b/.github/workflows/hippo-embed.lock.yml
index 59b3f2d2484..e2aa72ce49d 100644
--- a/.github/workflows/hippo-embed.lock.yml
+++ b/.github/workflows/hippo-embed.lock.yml
@@ -897,6 +897,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 60
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/issue-monster.lock.yml b/.github/workflows/issue-monster.lock.yml
index b3aaffca617..1afc31571f4 100644
--- a/.github/workflows/issue-monster.lock.yml
+++ b/.github/workflows/issue-monster.lock.yml
@@ -1232,6 +1232,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 30
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1768,6 +1769,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/issue-triage-agent.lock.yml b/.github/workflows/issue-triage-agent.lock.yml
index e76db658d25..cc87d7fa523 100644
--- a/.github/workflows/issue-triage-agent.lock.yml
+++ b/.github/workflows/issue-triage-agent.lock.yml
@@ -811,6 +811,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 5
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1338,6 +1339,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/jsweep.lock.yml b/.github/workflows/jsweep.lock.yml
index 9d3a841d81c..19536ed2482 100644
--- a/.github/workflows/jsweep.lock.yml
+++ b/.github/workflows/jsweep.lock.yml
@@ -864,6 +864,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1421,6 +1422,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/layout-spec-maintainer.lock.yml b/.github/workflows/layout-spec-maintainer.lock.yml
index 4ea33eaece2..350597e2bc1 100644
--- a/.github/workflows/layout-spec-maintainer.lock.yml
+++ b/.github/workflows/layout-spec-maintainer.lock.yml
@@ -872,6 +872,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1409,6 +1410,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/lint-monster.lock.yml b/.github/workflows/lint-monster.lock.yml
index 594471bf86f..bb00019cc50 100644
--- a/.github/workflows/lint-monster.lock.yml
+++ b/.github/workflows/lint-monster.lock.yml
@@ -969,6 +969,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 45
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1508,6 +1509,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/linter-miner.lock.yml b/.github/workflows/linter-miner.lock.yml
index 6b46106bddf..07f316bbeab 100644
--- a/.github/workflows/linter-miner.lock.yml
+++ b/.github/workflows/linter-miner.lock.yml
@@ -920,6 +920,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 120
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1477,6 +1478,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/mattpocock-skills-reviewer.lock.yml b/.github/workflows/mattpocock-skills-reviewer.lock.yml
index a229aa32090..2b77f869eaf 100644
--- a/.github/workflows/mattpocock-skills-reviewer.lock.yml
+++ b/.github/workflows/mattpocock-skills-reviewer.lock.yml
@@ -957,6 +957,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 15
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1509,6 +1510,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/mcp-inspector.lock.yml b/.github/workflows/mcp-inspector.lock.yml
index 7fd153b6d39..3ab33d1a662 100644
--- a/.github/workflows/mcp-inspector.lock.yml
+++ b/.github/workflows/mcp-inspector.lock.yml
@@ -1388,6 +1388,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1951,6 +1952,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/mergefest.lock.yml b/.github/workflows/mergefest.lock.yml
index f490dc8c2d8..c0a574c0aa9 100644
--- a/.github/workflows/mergefest.lock.yml
+++ b/.github/workflows/mergefest.lock.yml
@@ -912,6 +912,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 10
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1464,6 +1465,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/metrics-collector.lock.yml b/.github/workflows/metrics-collector.lock.yml
index ecdceb1ee4d..84117051a71 100644
--- a/.github/workflows/metrics-collector.lock.yml
+++ b/.github/workflows/metrics-collector.lock.yml
@@ -938,6 +938,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 15
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1487,6 +1488,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/notion-issue-summary.lock.yml b/.github/workflows/notion-issue-summary.lock.yml
index bbea1f0b25a..e2bb7518289 100644
--- a/.github/workflows/notion-issue-summary.lock.yml
+++ b/.github/workflows/notion-issue-summary.lock.yml
@@ -831,6 +831,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 5
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1355,6 +1356,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/org-health-report.lock.yml b/.github/workflows/org-health-report.lock.yml
index c8f213f7c7f..0ab8ad98abc 100644
--- a/.github/workflows/org-health-report.lock.yml
+++ b/.github/workflows/org-health-report.lock.yml
@@ -886,6 +886,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 60
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1459,6 +1460,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/otlp-data-quality-validator.lock.yml b/.github/workflows/otlp-data-quality-validator.lock.yml
index b6e54e156c7..45c616e57c0 100644
--- a/.github/workflows/otlp-data-quality-validator.lock.yml
+++ b/.github/workflows/otlp-data-quality-validator.lock.yml
@@ -819,6 +819,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 30
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1354,6 +1355,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/outcome-collector.lock.yml b/.github/workflows/outcome-collector.lock.yml
index f13c241ef0f..8ba6a401325 100644
--- a/.github/workflows/outcome-collector.lock.yml
+++ b/.github/workflows/outcome-collector.lock.yml
@@ -852,6 +852,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1407,6 +1408,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/pdf-summary.lock.yml b/.github/workflows/pdf-summary.lock.yml
index a57969d99b1..cf395bf8f08 100644
--- a/.github/workflows/pdf-summary.lock.yml
+++ b/.github/workflows/pdf-summary.lock.yml
@@ -968,6 +968,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 15
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1539,6 +1540,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/plan.lock.yml b/.github/workflows/plan.lock.yml
index b6e76223ed2..47721d7d985 100644
--- a/.github/workflows/plan.lock.yml
+++ b/.github/workflows/plan.lock.yml
@@ -910,6 +910,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 10
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1463,6 +1464,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/poem-bot.lock.yml b/.github/workflows/poem-bot.lock.yml
index 67bb2df4b69..ee8b7950d98 100644
--- a/.github/workflows/poem-bot.lock.yml
+++ b/.github/workflows/poem-bot.lock.yml
@@ -1226,6 +1226,7 @@ jobs:
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
GH_AW_SAFE_OUTPUTS_STAGED: true
+ GH_AW_TIMEOUT_MINUTES: 10
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1811,6 +1812,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/pr-code-quality-reviewer.lock.yml b/.github/workflows/pr-code-quality-reviewer.lock.yml
index 0a030300262..2834783e0c5 100644
--- a/.github/workflows/pr-code-quality-reviewer.lock.yml
+++ b/.github/workflows/pr-code-quality-reviewer.lock.yml
@@ -923,6 +923,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 15
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1473,6 +1474,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/pr-description-caveman.lock.yml b/.github/workflows/pr-description-caveman.lock.yml
index 21fdb692fad..efb5ac95503 100644
--- a/.github/workflows/pr-description-caveman.lock.yml
+++ b/.github/workflows/pr-description-caveman.lock.yml
@@ -844,6 +844,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 15
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1362,6 +1363,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/pr-nitpick-reviewer.lock.yml b/.github/workflows/pr-nitpick-reviewer.lock.yml
index fb209a19c78..aaf95e264d2 100644
--- a/.github/workflows/pr-nitpick-reviewer.lock.yml
+++ b/.github/workflows/pr-nitpick-reviewer.lock.yml
@@ -954,6 +954,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 15
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1508,6 +1509,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/pr-sous-chef.lock.yml b/.github/workflows/pr-sous-chef.lock.yml
index e264f35913f..73c7ee4f494 100644
--- a/.github/workflows/pr-sous-chef.lock.yml
+++ b/.github/workflows/pr-sous-chef.lock.yml
@@ -953,6 +953,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 25
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1487,6 +1488,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/pr-triage-agent.lock.yml b/.github/workflows/pr-triage-agent.lock.yml
index 9eebb827d27..475f7a2ebad 100644
--- a/.github/workflows/pr-triage-agent.lock.yml
+++ b/.github/workflows/pr-triage-agent.lock.yml
@@ -1,4 +1,4 @@
-# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"86a9f7e28bb033480585d3140a004cc6ae7827d42275a13ea8832d5861fc1775","body_hash":"30e8a94da14ac41b4cfacb616613168f5773e157b09245bc8c45fde456ed19ae","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.59","copilot-sdk":"1.0.0"}}
+# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"ea6804e627f96fe4f14d58291c0606a9b47ce6e9650b0c22b0e2222ba51dff51","body_hash":"30e8a94da14ac41b4cfacb616613168f5773e157b09245bc8c45fde456ed19ae","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.59","copilot-sdk":"1.0.0"}}
# gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_GRAFANA_AUTHORIZATION","GH_AW_OTEL_GRAFANA_ENDPOINT","GH_AW_OTEL_SENTRY_AUTHORIZATION","GH_AW_OTEL_SENTRY_ENDPOINT","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.65"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.65"},{"image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.65"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.65"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.23","digest":"sha256:0dd1bd91a41e24a3ccc31b1ec6cb61d36608997fabf91f2d643b64e3fc33180a","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.23@sha256:0dd1bd91a41e24a3ccc31b1ec6cb61d36608997fabf91f2d643b64e3fc33180a"},{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"},{"image":"node:lts-alpine","digest":"sha256:2bdb65ed1dab192432bc31c95f94155ca5ad7fc1392fb7eb7526ab682fa5bf14","pinned_image":"node:lts-alpine@sha256:2bdb65ed1dab192432bc31c95f94155ca5ad7fc1392fb7eb7526ab682fa5bf14"}]}
# ___ _ _
# / _ \ | | (_)
@@ -925,7 +925,7 @@ jobs:
export GH_AW_NODE_BIN
export COPILOT_API_KEY="$COPILOT_DUMMY_BYOK"
(umask 177 && touch /tmp/gh-aw/agent-stdio.log)
- printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.65/awf-config.schema.json","network":{"allowDomains":["*.grafana.net","*.sentry.io","api.business.githubcopilot.com","api.enterprise.githubcopilot.com","api.github.com","api.githubcopilot.com","api.individual.githubcopilot.com","api.snapcraft.io","archive.ubuntu.com","azure.archive.ubuntu.com","crl.geotrust.com","crl.globalsign.com","crl.identrust.com","crl.sectigo.com","crl.thawte.com","crl.usertrust.com","crl.verisign.com","crl3.digicert.com","crl4.digicert.com","crls.ssl.com","github.com","host.docker.internal","json-schema.org","json.schemastore.org","keyserver.ubuntu.com","ocsp.digicert.com","ocsp.geotrust.com","ocsp.globalsign.com","ocsp.identrust.com","ocsp.sectigo.com","ocsp.ssl.com","ocsp.thawte.com","ocsp.usertrust.com","ocsp.verisign.com","packagecloud.io","packages.cloud.google.com","packages.microsoft.com","ppa.launchpad.net","raw.githubusercontent.com","registry.npmjs.org","s.symcb.com","s.symcd.com","security.ubuntu.com","telemetry.enterprise.githubcopilot.com","ts-crl.ws.symantec.com","ts-ocsp.ws.symantec.com","www.googleapis.com"]},"apiProxy":{"enabled":true,"enableTokenSteering":true,"maxRuns":500,"maxEffectiveTokens":10000000,"maxAiCredits":1000,"models":{"agent":["sonnet-6x","gpt-5.4","gpt-5.3","gemini-pro","any"],"antigravity":["copilot/antigravity*","google/antigravity*","gemini/antigravity*"],"any":["copilot/*","anthropic/*","openai/*","google/*","gemini/*"],"claude":["agent"],"codex":["agent"],"coding":["copilot/gpt-5*codex*","openai/gpt-5*codex*","gpt-5-codex"],"computer-use":["copilot/*computer-use*","google/*computer-use*","gemini/*computer-use*","openai/*computer-use*"],"copilot":["agent"],"deep-research":["copilot/deep-research*","copilot/o3-deep-research*","copilot/o4-mini-deep-research*","google/deep-research*","gemini/deep-research*","openai/o3-deep-research*","openai/o4-mini-deep-research*"],"gemini":["agent"],"gemini-3-flash":["copilot/gemini-3*flash*","google/gemini-3*flash*","gemini/gemini-3*flash*"],"gemini-3-pro":["copilot/gemini-3*pro*","google/gemini-3*pro*","google/nano-banana*","gemini/gemini-3*pro*"],"gemini-3.1-flash":["copilot/gemini-3.1*flash*","google/gemini-3.1*flash*","gemini/gemini-3.1*flash*"],"gemini-3.1-pro":["copilot/gemini-3.1*pro*","google/gemini-3.1*pro*","gemini/gemini-3.1*pro*"],"gemini-3.5-flash":["copilot/gemini-3.5*flash*","google/gemini-3.5*flash*","gemini/gemini-3.5*flash*"],"gemini-flash":["copilot/gemini-*flash*","google/gemini-*flash*","gemini/gemini-*flash*"],"gemini-flash-lite":["copilot/gemini-*flash*lite*","google/gemini-*flash*lite*","gemini/gemini-*flash*lite*"],"gemini-pro":["copilot/gemini-*pro*","google/gemini-*pro*","gemini/gemini-*pro*"],"gemma":["copilot/gemma*","google/gemma*","gemini/gemma*"],"gpt-5":["copilot/gpt-5*","openai/gpt-5*"],"gpt-5-codex":["copilot/gpt-5*codex*","openai/gpt-5*codex*"],"gpt-5-mini":["copilot/gpt-5*mini*","openai/gpt-5*mini*"],"gpt-5-nano":["copilot/gpt-5*nano*","openai/gpt-5*nano*"],"gpt-5-pro":["copilot/gpt-5*pro*","openai/gpt-5*pro*"],"gpt-5.2":["copilot/gpt-5.2*","openai/gpt-5.2*"],"gpt-5.3":["copilot/gpt-5.3*","openai/gpt-5.3*"],"gpt-5.4":["copilot/gpt-5.4*","openai/gpt-5.4*"],"gpt-5.5":["copilot/gpt-5.5*","openai/gpt-5.5*"],"haiku":["copilot/*haiku*","anthropic/*haiku*"],"large":["sonnet","gpt-5-pro","gpt-5","gemini-pro"],"mai-code":["copilot/MAI-Code*","copilot/mai-code*","openai/MAI-Code*"],"mini":["haiku","gpt-5-mini","gpt-5-nano","gemini-flash-lite"],"nano-banana":["copilot/nano-banana*","google/nano-banana*","gemini/nano-banana*"],"opus":["copilot/*opus*","anthropic/*opus*"],"opusplan":["opus?effort=high"],"reasoning":["copilot/o1*","copilot/o3*","copilot/o4*","openai/o1*","openai/o3*","openai/o4*"],"robotics":["copilot/*robotics*","google/*robotics*","gemini/*robotics*"],"small":["mini"],"small-agent":["haiku","gpt-5-mini","gemini-flash","any"],"sonnet":["copilot/*sonnet*","anthropic/*sonnet*"],"sonnet-6x":["copilot/*sonnet-4.5*","copilot/*sonnet-4.6*","copilot/*sonnet-4-5-*","anthropic/*sonnet-4-5-*","copilot/*sonnet-4-6*","anthropic/*sonnet-4-6*"],"summarization":["haiku","gpt-5-mini","gemini-flash-lite","mini"],"vision":["copilot/gemini-*image*","gemini/gemini-*image*","copilot/gemini-*flash*","gemini/gemini-*flash*"]}},"container":{"imageTag":"0.25.65"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json"
+ printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.65/awf-config.schema.json","network":{"allowDomains":["*.grafana.net","*.sentry.io","api.business.githubcopilot.com","api.enterprise.githubcopilot.com","api.github.com","api.githubcopilot.com","api.individual.githubcopilot.com","api.snapcraft.io","archive.ubuntu.com","azure.archive.ubuntu.com","crl.geotrust.com","crl.globalsign.com","crl.identrust.com","crl.sectigo.com","crl.thawte.com","crl.usertrust.com","crl.verisign.com","crl3.digicert.com","crl4.digicert.com","crls.ssl.com","github.com","host.docker.internal","json-schema.org","json.schemastore.org","keyserver.ubuntu.com","ocsp.digicert.com","ocsp.geotrust.com","ocsp.globalsign.com","ocsp.identrust.com","ocsp.sectigo.com","ocsp.ssl.com","ocsp.thawte.com","ocsp.usertrust.com","ocsp.verisign.com","packagecloud.io","packages.cloud.google.com","packages.microsoft.com","ppa.launchpad.net","raw.githubusercontent.com","registry.npmjs.org","s.symcb.com","s.symcd.com","security.ubuntu.com","telemetry.enterprise.githubcopilot.com","ts-crl.ws.symantec.com","ts-ocsp.ws.symantec.com","www.googleapis.com"]},"apiProxy":{"enabled":true,"enableTokenSteering":true,"maxRuns":500,"maxAiCredits":10000000,"models":{"agent":["sonnet-6x","gpt-5.4","gpt-5.3","gemini-pro","any"],"antigravity":["copilot/antigravity*","google/antigravity*","gemini/antigravity*"],"any":["copilot/*","anthropic/*","openai/*","google/*","gemini/*"],"claude":["agent"],"codex":["agent"],"coding":["copilot/gpt-5*codex*","openai/gpt-5*codex*","gpt-5-codex"],"computer-use":["copilot/*computer-use*","google/*computer-use*","gemini/*computer-use*","openai/*computer-use*"],"copilot":["agent"],"deep-research":["copilot/deep-research*","copilot/o3-deep-research*","copilot/o4-mini-deep-research*","google/deep-research*","gemini/deep-research*","openai/o3-deep-research*","openai/o4-mini-deep-research*"],"gemini":["agent"],"gemini-3-flash":["copilot/gemini-3*flash*","google/gemini-3*flash*","gemini/gemini-3*flash*"],"gemini-3-pro":["copilot/gemini-3*pro*","google/gemini-3*pro*","google/nano-banana*","gemini/gemini-3*pro*"],"gemini-3.1-flash":["copilot/gemini-3.1*flash*","google/gemini-3.1*flash*","gemini/gemini-3.1*flash*"],"gemini-3.1-pro":["copilot/gemini-3.1*pro*","google/gemini-3.1*pro*","gemini/gemini-3.1*pro*"],"gemini-3.5-flash":["copilot/gemini-3.5*flash*","google/gemini-3.5*flash*","gemini/gemini-3.5*flash*"],"gemini-flash":["copilot/gemini-*flash*","google/gemini-*flash*","gemini/gemini-*flash*"],"gemini-flash-lite":["copilot/gemini-*flash*lite*","google/gemini-*flash*lite*","gemini/gemini-*flash*lite*"],"gemini-pro":["copilot/gemini-*pro*","google/gemini-*pro*","gemini/gemini-*pro*"],"gemma":["copilot/gemma*","google/gemma*","gemini/gemma*"],"gpt-5":["copilot/gpt-5*","openai/gpt-5*"],"gpt-5-codex":["copilot/gpt-5*codex*","openai/gpt-5*codex*"],"gpt-5-mini":["copilot/gpt-5*mini*","openai/gpt-5*mini*"],"gpt-5-nano":["copilot/gpt-5*nano*","openai/gpt-5*nano*"],"gpt-5-pro":["copilot/gpt-5*pro*","openai/gpt-5*pro*"],"gpt-5.2":["copilot/gpt-5.2*","openai/gpt-5.2*"],"gpt-5.3":["copilot/gpt-5.3*","openai/gpt-5.3*"],"gpt-5.4":["copilot/gpt-5.4*","openai/gpt-5.4*"],"gpt-5.5":["copilot/gpt-5.5*","openai/gpt-5.5*"],"haiku":["copilot/*haiku*","anthropic/*haiku*"],"large":["sonnet","gpt-5-pro","gpt-5","gemini-pro"],"mai-code":["copilot/MAI-Code*","copilot/mai-code*","openai/MAI-Code*"],"mini":["haiku","gpt-5-mini","gpt-5-nano","gemini-flash-lite"],"nano-banana":["copilot/nano-banana*","google/nano-banana*","gemini/nano-banana*"],"opus":["copilot/*opus*","anthropic/*opus*"],"opusplan":["opus?effort=high"],"reasoning":["copilot/o1*","copilot/o3*","copilot/o4*","openai/o1*","openai/o3*","openai/o4*"],"robotics":["copilot/*robotics*","google/*robotics*","gemini/*robotics*"],"small":["mini"],"small-agent":["haiku","gpt-5-mini","gemini-flash","any"],"sonnet":["copilot/*sonnet*","anthropic/*sonnet*"],"sonnet-6x":["copilot/*sonnet-4.5*","copilot/*sonnet-4.6*","copilot/*sonnet-4-5-*","anthropic/*sonnet-4-5-*","copilot/*sonnet-4-6*","anthropic/*sonnet-4-6*"],"summarization":["haiku","gpt-5-mini","gemini-flash-lite","mini"],"vision":["copilot/gemini-*image*","gemini/gemini-*image*","copilot/gemini-*flash*","gemini/gemini-*flash*"]}},"container":{"imageTag":"0.25.65"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json"
GH_AW_MODEL_MULTIPLIERS_PATH="/tmp/gh-aw/model_multipliers.json" node "${RUNNER_TEMP}/gh-aw/actions/merge_awf_model_multipliers.cjs"
cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json
export GH_AW_MODELS_JSON_PATH="${RUNNER_TEMP}/gh-aw/actions/models.json"
@@ -960,6 +960,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 30
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1332,7 +1333,6 @@ jobs:
GH_AW_MISSING_TOOL_REPORT_AS_FAILURE: "true"
GH_AW_MISSING_DATA_REPORT_AS_FAILURE: "true"
GH_AW_TIMEOUT_MINUTES: "30"
- GH_AW_MAX_EFFECTIVE_TOKENS: "10000000"
with:
github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
script: |
@@ -1487,7 +1487,7 @@ jobs:
export GH_AW_NODE_BIN
export COPILOT_API_KEY="$COPILOT_DUMMY_BYOK"
(umask 177 && touch /tmp/gh-aw/threat-detection/detection.log)
- printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.65/awf-config.schema.json","network":{"allowDomains":["api.business.githubcopilot.com","api.enterprise.githubcopilot.com","api.github.com","api.githubcopilot.com","api.individual.githubcopilot.com","github.com","host.docker.internal","registry.npmjs.org","telemetry.enterprise.githubcopilot.com"]},"apiProxy":{"enabled":true,"enableTokenSteering":true,"maxRuns":500,"maxEffectiveTokens":10000000,"maxAiCredits":1000},"container":{"imageTag":"0.25.65"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json"
+ printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.65/awf-config.schema.json","network":{"allowDomains":["api.business.githubcopilot.com","api.enterprise.githubcopilot.com","api.github.com","api.githubcopilot.com","api.individual.githubcopilot.com","github.com","host.docker.internal","registry.npmjs.org","telemetry.enterprise.githubcopilot.com"]},"apiProxy":{"enabled":true,"enableTokenSteering":true,"maxRuns":500,"maxAiCredits":1000},"container":{"imageTag":"0.25.65"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json"
GH_AW_MODEL_MULTIPLIERS_PATH="/tmp/gh-aw/model_multipliers.json" node "${RUNNER_TEMP}/gh-aw/actions/merge_awf_model_multipliers.cjs"
cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json
export GH_AW_MODELS_JSON_PATH="${RUNNER_TEMP}/gh-aw/actions/models.json"
@@ -1516,6 +1516,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/pr-triage-agent.md b/.github/workflows/pr-triage-agent.md
index c50aad11ff6..78af157acca 100644
--- a/.github/workflows/pr-triage-agent.md
+++ b/.github/workflows/pr-triage-agent.md
@@ -43,7 +43,7 @@ safe-outputs:
run-failure: "❌ PR triage failed! [{workflow_name}]({run_url}) {status}. Some PRs may not be triaged."
timeout-minutes: 30
# PR triage does classification work; 10M is a firm ceiling for this 6-hourly workflow.
-max-effective-tokens: 10000000
+max-ai-credits: 10000000
---
diff --git a/.github/workflows/python-data-charts.lock.yml b/.github/workflows/python-data-charts.lock.yml
index bda9e06fc1b..8f21de657ee 100644
--- a/.github/workflows/python-data-charts.lock.yml
+++ b/.github/workflows/python-data-charts.lock.yml
@@ -977,6 +977,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 15
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1543,6 +1544,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/q.lock.yml b/.github/workflows/q.lock.yml
index 24eae3e244a..27f302bb18b 100644
--- a/.github/workflows/q.lock.yml
+++ b/.github/workflows/q.lock.yml
@@ -1054,6 +1054,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 30
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1612,6 +1613,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/refactoring-cadence.lock.yml b/.github/workflows/refactoring-cadence.lock.yml
index 8607214b013..dbfa9b3efa1 100644
--- a/.github/workflows/refactoring-cadence.lock.yml
+++ b/.github/workflows/refactoring-cadence.lock.yml
@@ -846,6 +846,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1401,6 +1402,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/refiner.lock.yml b/.github/workflows/refiner.lock.yml
index 3aa86f47f65..67a966e68b5 100644
--- a/.github/workflows/refiner.lock.yml
+++ b/.github/workflows/refiner.lock.yml
@@ -951,6 +951,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 30
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1488,6 +1489,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/release.lock.yml b/.github/workflows/release.lock.yml
index 5ace9cd86cd..1e6bec5e6fb 100644
--- a/.github/workflows/release.lock.yml
+++ b/.github/workflows/release.lock.yml
@@ -871,6 +871,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/repo-audit-analyzer.lock.yml b/.github/workflows/repo-audit-analyzer.lock.yml
index ca9ea5671f7..e6e01496dee 100644
--- a/.github/workflows/repo-audit-analyzer.lock.yml
+++ b/.github/workflows/repo-audit-analyzer.lock.yml
@@ -849,6 +849,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 45
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1398,6 +1399,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/repo-tree-map.lock.yml b/.github/workflows/repo-tree-map.lock.yml
index f53a8d72d7f..613a2978118 100644
--- a/.github/workflows/repo-tree-map.lock.yml
+++ b/.github/workflows/repo-tree-map.lock.yml
@@ -818,6 +818,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 5
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1345,6 +1346,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/repository-quality-improver.lock.yml b/.github/workflows/repository-quality-improver.lock.yml
index 594cc92a7ad..dd8da570726 100644
--- a/.github/workflows/repository-quality-improver.lock.yml
+++ b/.github/workflows/repository-quality-improver.lock.yml
@@ -847,6 +847,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1399,6 +1400,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/research.lock.yml b/.github/workflows/research.lock.yml
index 797efab3026..57284d0b30d 100644
--- a/.github/workflows/research.lock.yml
+++ b/.github/workflows/research.lock.yml
@@ -846,6 +846,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 10
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1375,6 +1376,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/schema-consistency-checker.lock.yml b/.github/workflows/schema-consistency-checker.lock.yml
index a18c5452ee7..0c8930e20cd 100644
--- a/.github/workflows/schema-consistency-checker.lock.yml
+++ b/.github/workflows/schema-consistency-checker.lock.yml
@@ -1,4 +1,4 @@
-# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"549f48e535fa1147b05fe6a4a9e2aa2365c651f04a1cfb399c3a298ce8b23118","body_hash":"cb14865c3d4baafde419ade423085ec10789ea497611c514a3b7a44192ee69a2","strict":true,"agent_id":"claude","engine_versions":{"claude":"2.1.165"}}
+# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"5895e4628df6f31ee4e4658d4fdc5933a142f44e7a01e3e5fae5b2332c733f6a","body_hash":"cb14865c3d4baafde419ade423085ec10789ea497611c514a3b7a44192ee69a2","strict":true,"agent_id":"claude","engine_versions":{"claude":"2.1.165"}}
# gh-aw-manifest: {"version":1,"secrets":["ANTHROPIC_API_KEY","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_GRAFANA_AUTHORIZATION","GH_AW_OTEL_GRAFANA_ENDPOINT","GH_AW_OTEL_SENTRY_AUTHORIZATION","GH_AW_OTEL_SENTRY_ENDPOINT","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.65"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.65"},{"image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.65"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.65"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.23","digest":"sha256:0dd1bd91a41e24a3ccc31b1ec6cb61d36608997fabf91f2d643b64e3fc33180a","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.23@sha256:0dd1bd91a41e24a3ccc31b1ec6cb61d36608997fabf91f2d643b64e3fc33180a"},{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"},{"image":"node:lts-alpine","digest":"sha256:2bdb65ed1dab192432bc31c95f94155ca5ad7fc1392fb7eb7526ab682fa5bf14","pinned_image":"node:lts-alpine@sha256:2bdb65ed1dab192432bc31c95f94155ca5ad7fc1392fb7eb7526ab682fa5bf14"}]}
# ___ _ _
# / _ \ | | (_)
@@ -891,7 +891,7 @@ jobs:
printf '%s' "$(date +%s%3N)" > /tmp/gh-aw/agent_cli_start_ms.txt
touch /tmp/gh-aw/agent-step-summary.md
(umask 177 && touch /tmp/gh-aw/agent-stdio.log)
- printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.65/awf-config.schema.json","network":{"allowDomains":["*.githubusercontent.com","*.grafana.net","*.sentry.io","anthropic.com","api.anthropic.com","api.github.com","api.snapcraft.io","archive.ubuntu.com","azure.archive.ubuntu.com","cdn.playwright.dev","codeload.github.com","crl.geotrust.com","crl.globalsign.com","crl.identrust.com","crl.sectigo.com","crl.thawte.com","crl.usertrust.com","crl.verisign.com","crl3.digicert.com","crl4.digicert.com","crls.ssl.com","files.pythonhosted.org","ghcr.io","github-cloud.githubusercontent.com","github-cloud.s3.amazonaws.com","github.com","host.docker.internal","json-schema.org","json.schemastore.org","keyserver.ubuntu.com","lfs.github.com","objects.githubusercontent.com","ocsp.digicert.com","ocsp.geotrust.com","ocsp.globalsign.com","ocsp.identrust.com","ocsp.sectigo.com","ocsp.ssl.com","ocsp.thawte.com","ocsp.usertrust.com","ocsp.verisign.com","packagecloud.io","packages.cloud.google.com","packages.microsoft.com","playwright.download.prss.microsoft.com","ppa.launchpad.net","pypi.org","raw.githubusercontent.com","registry.npmjs.org","s.symcb.com","s.symcd.com","security.ubuntu.com","sentry.io","statsig.anthropic.com","ts-crl.ws.symantec.com","ts-ocsp.ws.symantec.com","www.googleapis.com"]},"apiProxy":{"enabled":true,"enableTokenSteering":true,"maxRuns":500,"maxEffectiveTokens":20000000,"maxAiCredits":1000,"models":{"agent":["sonnet-6x","gpt-5.4","gpt-5.3","gemini-pro","any"],"antigravity":["copilot/antigravity*","google/antigravity*","gemini/antigravity*"],"any":["copilot/*","anthropic/*","openai/*","google/*","gemini/*"],"claude":["agent"],"codex":["agent"],"coding":["copilot/gpt-5*codex*","openai/gpt-5*codex*","gpt-5-codex"],"computer-use":["copilot/*computer-use*","google/*computer-use*","gemini/*computer-use*","openai/*computer-use*"],"copilot":["agent"],"deep-research":["copilot/deep-research*","copilot/o3-deep-research*","copilot/o4-mini-deep-research*","google/deep-research*","gemini/deep-research*","openai/o3-deep-research*","openai/o4-mini-deep-research*"],"gemini":["agent"],"gemini-3-flash":["copilot/gemini-3*flash*","google/gemini-3*flash*","gemini/gemini-3*flash*"],"gemini-3-pro":["copilot/gemini-3*pro*","google/gemini-3*pro*","google/nano-banana*","gemini/gemini-3*pro*"],"gemini-3.1-flash":["copilot/gemini-3.1*flash*","google/gemini-3.1*flash*","gemini/gemini-3.1*flash*"],"gemini-3.1-pro":["copilot/gemini-3.1*pro*","google/gemini-3.1*pro*","gemini/gemini-3.1*pro*"],"gemini-3.5-flash":["copilot/gemini-3.5*flash*","google/gemini-3.5*flash*","gemini/gemini-3.5*flash*"],"gemini-flash":["copilot/gemini-*flash*","google/gemini-*flash*","gemini/gemini-*flash*"],"gemini-flash-lite":["copilot/gemini-*flash*lite*","google/gemini-*flash*lite*","gemini/gemini-*flash*lite*"],"gemini-pro":["copilot/gemini-*pro*","google/gemini-*pro*","gemini/gemini-*pro*"],"gemma":["copilot/gemma*","google/gemma*","gemini/gemma*"],"gpt-5":["copilot/gpt-5*","openai/gpt-5*"],"gpt-5-codex":["copilot/gpt-5*codex*","openai/gpt-5*codex*"],"gpt-5-mini":["copilot/gpt-5*mini*","openai/gpt-5*mini*"],"gpt-5-nano":["copilot/gpt-5*nano*","openai/gpt-5*nano*"],"gpt-5-pro":["copilot/gpt-5*pro*","openai/gpt-5*pro*"],"gpt-5.2":["copilot/gpt-5.2*","openai/gpt-5.2*"],"gpt-5.3":["copilot/gpt-5.3*","openai/gpt-5.3*"],"gpt-5.4":["copilot/gpt-5.4*","openai/gpt-5.4*"],"gpt-5.5":["copilot/gpt-5.5*","openai/gpt-5.5*"],"haiku":["copilot/*haiku*","anthropic/*haiku*"],"large":["sonnet","gpt-5-pro","gpt-5","gemini-pro"],"mai-code":["copilot/MAI-Code*","copilot/mai-code*","openai/MAI-Code*"],"mini":["haiku","gpt-5-mini","gpt-5-nano","gemini-flash-lite"],"nano-banana":["copilot/nano-banana*","google/nano-banana*","gemini/nano-banana*"],"opus":["copilot/*opus*","anthropic/*opus*"],"opusplan":["opus?effort=high"],"reasoning":["copilot/o1*","copilot/o3*","copilot/o4*","openai/o1*","openai/o3*","openai/o4*"],"robotics":["copilot/*robotics*","google/*robotics*","gemini/*robotics*"],"small":["mini"],"small-agent":["haiku","gpt-5-mini","gemini-flash","any"],"sonnet":["copilot/*sonnet*","anthropic/*sonnet*"],"sonnet-6x":["copilot/*sonnet-4.5*","copilot/*sonnet-4.6*","copilot/*sonnet-4-5-*","anthropic/*sonnet-4-5-*","copilot/*sonnet-4-6*","anthropic/*sonnet-4-6*"],"summarization":["haiku","gpt-5-mini","gemini-flash-lite","mini"],"vision":["copilot/gemini-*image*","gemini/gemini-*image*","copilot/gemini-*flash*","gemini/gemini-*flash*"]}},"container":{"imageTag":"0.25.65"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json"
+ printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.65/awf-config.schema.json","network":{"allowDomains":["*.githubusercontent.com","*.grafana.net","*.sentry.io","anthropic.com","api.anthropic.com","api.github.com","api.snapcraft.io","archive.ubuntu.com","azure.archive.ubuntu.com","cdn.playwright.dev","codeload.github.com","crl.geotrust.com","crl.globalsign.com","crl.identrust.com","crl.sectigo.com","crl.thawte.com","crl.usertrust.com","crl.verisign.com","crl3.digicert.com","crl4.digicert.com","crls.ssl.com","files.pythonhosted.org","ghcr.io","github-cloud.githubusercontent.com","github-cloud.s3.amazonaws.com","github.com","host.docker.internal","json-schema.org","json.schemastore.org","keyserver.ubuntu.com","lfs.github.com","objects.githubusercontent.com","ocsp.digicert.com","ocsp.geotrust.com","ocsp.globalsign.com","ocsp.identrust.com","ocsp.sectigo.com","ocsp.ssl.com","ocsp.thawte.com","ocsp.usertrust.com","ocsp.verisign.com","packagecloud.io","packages.cloud.google.com","packages.microsoft.com","playwright.download.prss.microsoft.com","ppa.launchpad.net","pypi.org","raw.githubusercontent.com","registry.npmjs.org","s.symcb.com","s.symcd.com","security.ubuntu.com","sentry.io","statsig.anthropic.com","ts-crl.ws.symantec.com","ts-ocsp.ws.symantec.com","www.googleapis.com"]},"apiProxy":{"enabled":true,"enableTokenSteering":true,"maxRuns":500,"maxAiCredits":20000000,"models":{"agent":["sonnet-6x","gpt-5.4","gpt-5.3","gemini-pro","any"],"antigravity":["copilot/antigravity*","google/antigravity*","gemini/antigravity*"],"any":["copilot/*","anthropic/*","openai/*","google/*","gemini/*"],"claude":["agent"],"codex":["agent"],"coding":["copilot/gpt-5*codex*","openai/gpt-5*codex*","gpt-5-codex"],"computer-use":["copilot/*computer-use*","google/*computer-use*","gemini/*computer-use*","openai/*computer-use*"],"copilot":["agent"],"deep-research":["copilot/deep-research*","copilot/o3-deep-research*","copilot/o4-mini-deep-research*","google/deep-research*","gemini/deep-research*","openai/o3-deep-research*","openai/o4-mini-deep-research*"],"gemini":["agent"],"gemini-3-flash":["copilot/gemini-3*flash*","google/gemini-3*flash*","gemini/gemini-3*flash*"],"gemini-3-pro":["copilot/gemini-3*pro*","google/gemini-3*pro*","google/nano-banana*","gemini/gemini-3*pro*"],"gemini-3.1-flash":["copilot/gemini-3.1*flash*","google/gemini-3.1*flash*","gemini/gemini-3.1*flash*"],"gemini-3.1-pro":["copilot/gemini-3.1*pro*","google/gemini-3.1*pro*","gemini/gemini-3.1*pro*"],"gemini-3.5-flash":["copilot/gemini-3.5*flash*","google/gemini-3.5*flash*","gemini/gemini-3.5*flash*"],"gemini-flash":["copilot/gemini-*flash*","google/gemini-*flash*","gemini/gemini-*flash*"],"gemini-flash-lite":["copilot/gemini-*flash*lite*","google/gemini-*flash*lite*","gemini/gemini-*flash*lite*"],"gemini-pro":["copilot/gemini-*pro*","google/gemini-*pro*","gemini/gemini-*pro*"],"gemma":["copilot/gemma*","google/gemma*","gemini/gemma*"],"gpt-5":["copilot/gpt-5*","openai/gpt-5*"],"gpt-5-codex":["copilot/gpt-5*codex*","openai/gpt-5*codex*"],"gpt-5-mini":["copilot/gpt-5*mini*","openai/gpt-5*mini*"],"gpt-5-nano":["copilot/gpt-5*nano*","openai/gpt-5*nano*"],"gpt-5-pro":["copilot/gpt-5*pro*","openai/gpt-5*pro*"],"gpt-5.2":["copilot/gpt-5.2*","openai/gpt-5.2*"],"gpt-5.3":["copilot/gpt-5.3*","openai/gpt-5.3*"],"gpt-5.4":["copilot/gpt-5.4*","openai/gpt-5.4*"],"gpt-5.5":["copilot/gpt-5.5*","openai/gpt-5.5*"],"haiku":["copilot/*haiku*","anthropic/*haiku*"],"large":["sonnet","gpt-5-pro","gpt-5","gemini-pro"],"mai-code":["copilot/MAI-Code*","copilot/mai-code*","openai/MAI-Code*"],"mini":["haiku","gpt-5-mini","gpt-5-nano","gemini-flash-lite"],"nano-banana":["copilot/nano-banana*","google/nano-banana*","gemini/nano-banana*"],"opus":["copilot/*opus*","anthropic/*opus*"],"opusplan":["opus?effort=high"],"reasoning":["copilot/o1*","copilot/o3*","copilot/o4*","openai/o1*","openai/o3*","openai/o4*"],"robotics":["copilot/*robotics*","google/*robotics*","gemini/*robotics*"],"small":["mini"],"small-agent":["haiku","gpt-5-mini","gemini-flash","any"],"sonnet":["copilot/*sonnet*","anthropic/*sonnet*"],"sonnet-6x":["copilot/*sonnet-4.5*","copilot/*sonnet-4.6*","copilot/*sonnet-4-5-*","anthropic/*sonnet-4-5-*","copilot/*sonnet-4-6*","anthropic/*sonnet-4-6*"],"summarization":["haiku","gpt-5-mini","gemini-flash-lite","mini"],"vision":["copilot/gemini-*image*","gemini/gemini-*image*","copilot/gemini-*flash*","gemini/gemini-*flash*"]}},"container":{"imageTag":"0.25.65"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json"
GH_AW_MODEL_MULTIPLIERS_PATH="/tmp/gh-aw/model_multipliers.json" node "${RUNNER_TEMP}/gh-aw/actions/merge_awf_model_multipliers.cjs"
cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json
export GH_AW_MODELS_JSON_PATH="${RUNNER_TEMP}/gh-aw/actions/models.json"
@@ -1273,7 +1273,6 @@ jobs:
GH_AW_MISSING_TOOL_REPORT_AS_FAILURE: "true"
GH_AW_MISSING_DATA_REPORT_AS_FAILURE: "true"
GH_AW_TIMEOUT_MINUTES: "30"
- GH_AW_MAX_EFFECTIVE_TOKENS: "20000000"
GH_AW_CACHE_MEMORY_ENABLED: "true"
with:
github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
@@ -1436,7 +1435,7 @@ jobs:
printf '%s' "$(date +%s%3N)" > /tmp/gh-aw/agent_cli_start_ms.txt
touch /tmp/gh-aw/agent-step-summary.md
(umask 177 && touch /tmp/gh-aw/threat-detection/detection.log)
- printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.65/awf-config.schema.json","network":{"allowDomains":["*.githubusercontent.com","anthropic.com","api.anthropic.com","api.github.com","api.snapcraft.io","archive.ubuntu.com","azure.archive.ubuntu.com","cdn.playwright.dev","codeload.github.com","crl.geotrust.com","crl.globalsign.com","crl.identrust.com","crl.sectigo.com","crl.thawte.com","crl.usertrust.com","crl.verisign.com","crl3.digicert.com","crl4.digicert.com","crls.ssl.com","files.pythonhosted.org","ghcr.io","github-cloud.githubusercontent.com","github-cloud.s3.amazonaws.com","github.com","host.docker.internal","json-schema.org","json.schemastore.org","keyserver.ubuntu.com","lfs.github.com","objects.githubusercontent.com","ocsp.digicert.com","ocsp.geotrust.com","ocsp.globalsign.com","ocsp.identrust.com","ocsp.sectigo.com","ocsp.ssl.com","ocsp.thawte.com","ocsp.usertrust.com","ocsp.verisign.com","packagecloud.io","packages.cloud.google.com","packages.microsoft.com","playwright.download.prss.microsoft.com","ppa.launchpad.net","pypi.org","raw.githubusercontent.com","registry.npmjs.org","s.symcb.com","s.symcd.com","security.ubuntu.com","sentry.io","statsig.anthropic.com","ts-crl.ws.symantec.com","ts-ocsp.ws.symantec.com"]},"apiProxy":{"enabled":true,"enableTokenSteering":true,"maxRuns":500,"maxEffectiveTokens":20000000,"maxAiCredits":1000},"container":{"imageTag":"0.25.65"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json"
+ printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.65/awf-config.schema.json","network":{"allowDomains":["*.githubusercontent.com","anthropic.com","api.anthropic.com","api.github.com","api.snapcraft.io","archive.ubuntu.com","azure.archive.ubuntu.com","cdn.playwright.dev","codeload.github.com","crl.geotrust.com","crl.globalsign.com","crl.identrust.com","crl.sectigo.com","crl.thawte.com","crl.usertrust.com","crl.verisign.com","crl3.digicert.com","crl4.digicert.com","crls.ssl.com","files.pythonhosted.org","ghcr.io","github-cloud.githubusercontent.com","github-cloud.s3.amazonaws.com","github.com","host.docker.internal","json-schema.org","json.schemastore.org","keyserver.ubuntu.com","lfs.github.com","objects.githubusercontent.com","ocsp.digicert.com","ocsp.geotrust.com","ocsp.globalsign.com","ocsp.identrust.com","ocsp.sectigo.com","ocsp.ssl.com","ocsp.thawte.com","ocsp.usertrust.com","ocsp.verisign.com","packagecloud.io","packages.cloud.google.com","packages.microsoft.com","playwright.download.prss.microsoft.com","ppa.launchpad.net","pypi.org","raw.githubusercontent.com","registry.npmjs.org","s.symcb.com","s.symcd.com","security.ubuntu.com","sentry.io","statsig.anthropic.com","ts-crl.ws.symantec.com","ts-ocsp.ws.symantec.com"]},"apiProxy":{"enabled":true,"enableTokenSteering":true,"maxRuns":500,"maxAiCredits":1000},"container":{"imageTag":"0.25.65"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json"
GH_AW_MODEL_MULTIPLIERS_PATH="/tmp/gh-aw/model_multipliers.json" node "${RUNNER_TEMP}/gh-aw/actions/merge_awf_model_multipliers.cjs"
cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json
export GH_AW_MODELS_JSON_PATH="${RUNNER_TEMP}/gh-aw/actions/models.json"
diff --git a/.github/workflows/schema-consistency-checker.md b/.github/workflows/schema-consistency-checker.md
index b127b97b9d4..8c015a5be69 100644
--- a/.github/workflows/schema-consistency-checker.md
+++ b/.github/workflows/schema-consistency-checker.md
@@ -11,7 +11,7 @@ permissions:
pull-requests: read
engine:
id: claude
-max-effective-tokens: 20000000
+max-ai-credits: 20000000
tools:
edit:
bash: ["*"]
diff --git a/.github/workflows/security-compliance.lock.yml b/.github/workflows/security-compliance.lock.yml
index 5be6e730d30..03898c01d6e 100644
--- a/.github/workflows/security-compliance.lock.yml
+++ b/.github/workflows/security-compliance.lock.yml
@@ -856,6 +856,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 30
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1405,6 +1406,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/security-review.lock.yml b/.github/workflows/security-review.lock.yml
index 47512e59203..e32ab2c281f 100644
--- a/.github/workflows/security-review.lock.yml
+++ b/.github/workflows/security-review.lock.yml
@@ -1001,6 +1001,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 15
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1551,6 +1552,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/slide-deck-maintainer.lock.yml b/.github/workflows/slide-deck-maintainer.lock.yml
index 5d9a0430a70..0e854a8301d 100644
--- a/.github/workflows/slide-deck-maintainer.lock.yml
+++ b/.github/workflows/slide-deck-maintainer.lock.yml
@@ -949,6 +949,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 45
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1501,6 +1502,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/smoke-ci.lock.yml b/.github/workflows/smoke-ci.lock.yml
index f442e3de3b3..cc93078a36c 100644
--- a/.github/workflows/smoke-ci.lock.yml
+++ b/.github/workflows/smoke-ci.lock.yml
@@ -1096,6 +1096,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 5
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/smoke-copilot-aoai-apikey.lock.yml b/.github/workflows/smoke-copilot-aoai-apikey.lock.yml
index 2c3a3ade708..0fc27984b85 100644
--- a/.github/workflows/smoke-copilot-aoai-apikey.lock.yml
+++ b/.github/workflows/smoke-copilot-aoai-apikey.lock.yml
@@ -1886,6 +1886,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 15
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -2496,6 +2497,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/smoke-copilot-arm.lock.yml b/.github/workflows/smoke-copilot-arm.lock.yml
index bb00ece0c53..5f6d3950b87 100644
--- a/.github/workflows/smoke-copilot-arm.lock.yml
+++ b/.github/workflows/smoke-copilot-arm.lock.yml
@@ -1765,6 +1765,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 15
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -2350,6 +2351,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/smoke-copilot-sdk.lock.yml b/.github/workflows/smoke-copilot-sdk.lock.yml
index 8ab7c9d8da8..48955a18db7 100644
--- a/.github/workflows/smoke-copilot-sdk.lock.yml
+++ b/.github/workflows/smoke-copilot-sdk.lock.yml
@@ -876,6 +876,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 10
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1410,6 +1411,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/smoke-copilot.lock.yml b/.github/workflows/smoke-copilot.lock.yml
index 274b8149c2c..6a4076200b2 100644
--- a/.github/workflows/smoke-copilot.lock.yml
+++ b/.github/workflows/smoke-copilot.lock.yml
@@ -1890,6 +1890,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 15
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -2499,6 +2500,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/smoke-create-cross-repo-pr.lock.yml b/.github/workflows/smoke-create-cross-repo-pr.lock.yml
index c0b0a84871f..08b38d1411e 100644
--- a/.github/workflows/smoke-create-cross-repo-pr.lock.yml
+++ b/.github/workflows/smoke-create-cross-repo-pr.lock.yml
@@ -1001,6 +1001,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 10
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1562,6 +1563,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/smoke-multi-pr.lock.yml b/.github/workflows/smoke-multi-pr.lock.yml
index ae0ba64c422..f17cf47c280 100644
--- a/.github/workflows/smoke-multi-pr.lock.yml
+++ b/.github/workflows/smoke-multi-pr.lock.yml
@@ -941,6 +941,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 10
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1492,6 +1493,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/smoke-otel-backends.lock.yml b/.github/workflows/smoke-otel-backends.lock.yml
index b6e1de50867..ff2d84a5629 100644
--- a/.github/workflows/smoke-otel-backends.lock.yml
+++ b/.github/workflows/smoke-otel-backends.lock.yml
@@ -1024,6 +1024,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1582,6 +1583,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/smoke-project.lock.yml b/.github/workflows/smoke-project.lock.yml
index f85429bb544..e4dad20282a 100644
--- a/.github/workflows/smoke-project.lock.yml
+++ b/.github/workflows/smoke-project.lock.yml
@@ -1081,6 +1081,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 15
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1633,6 +1634,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/smoke-service-ports.lock.yml b/.github/workflows/smoke-service-ports.lock.yml
index d08dc025c5f..edd2c96a4a3 100644
--- a/.github/workflows/smoke-service-ports.lock.yml
+++ b/.github/workflows/smoke-service-ports.lock.yml
@@ -866,6 +866,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 5
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1415,6 +1416,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/smoke-temporary-id.lock.yml b/.github/workflows/smoke-temporary-id.lock.yml
index d61a8696fad..96d8ef89e22 100644
--- a/.github/workflows/smoke-temporary-id.lock.yml
+++ b/.github/workflows/smoke-temporary-id.lock.yml
@@ -966,6 +966,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 10
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1522,6 +1523,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/smoke-test-tools.lock.yml b/.github/workflows/smoke-test-tools.lock.yml
index 1ee585e7949..cc4f71afe5c 100644
--- a/.github/workflows/smoke-test-tools.lock.yml
+++ b/.github/workflows/smoke-test-tools.lock.yml
@@ -897,6 +897,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 5
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1446,6 +1447,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/smoke-update-cross-repo-pr.lock.yml b/.github/workflows/smoke-update-cross-repo-pr.lock.yml
index b9b2da4d108..d0baa724fef 100644
--- a/.github/workflows/smoke-update-cross-repo-pr.lock.yml
+++ b/.github/workflows/smoke-update-cross-repo-pr.lock.yml
@@ -1013,6 +1013,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 10
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1594,6 +1595,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/smoke-workflow-call-with-inputs.lock.yml b/.github/workflows/smoke-workflow-call-with-inputs.lock.yml
index e7c27f31432..83694f648f9 100644
--- a/.github/workflows/smoke-workflow-call-with-inputs.lock.yml
+++ b/.github/workflows/smoke-workflow-call-with-inputs.lock.yml
@@ -924,6 +924,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 5
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1450,6 +1451,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/smoke-workflow-call.lock.yml b/.github/workflows/smoke-workflow-call.lock.yml
index a5fd6ff1ead..2dea2b9d7c2 100644
--- a/.github/workflows/smoke-workflow-call.lock.yml
+++ b/.github/workflows/smoke-workflow-call.lock.yml
@@ -912,6 +912,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 10
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1441,6 +1442,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/spec-extractor.lock.yml b/.github/workflows/spec-extractor.lock.yml
index 3e8cf12e540..fd7ff358694 100644
--- a/.github/workflows/spec-extractor.lock.yml
+++ b/.github/workflows/spec-extractor.lock.yml
@@ -952,6 +952,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 30
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1509,6 +1510,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/spec-librarian.lock.yml b/.github/workflows/spec-librarian.lock.yml
index 474375b94ee..fdce17b60be 100644
--- a/.github/workflows/spec-librarian.lock.yml
+++ b/.github/workflows/spec-librarian.lock.yml
@@ -933,6 +933,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 25
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1468,6 +1469,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/stale-pr-cleanup.lock.yml b/.github/workflows/stale-pr-cleanup.lock.yml
index 2ae87edf96a..2d4847ea29c 100644
--- a/.github/workflows/stale-pr-cleanup.lock.yml
+++ b/.github/workflows/stale-pr-cleanup.lock.yml
@@ -855,6 +855,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 30
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1387,6 +1388,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/stale-repo-identifier.lock.yml b/.github/workflows/stale-repo-identifier.lock.yml
index 7b572a177e5..22c349e7d43 100644
--- a/.github/workflows/stale-repo-identifier.lock.yml
+++ b/.github/workflows/stale-repo-identifier.lock.yml
@@ -1013,6 +1013,7 @@ jobs:
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
GH_AW_SAFE_OUTPUTS_STAGED: true
+ GH_AW_TIMEOUT_MINUTES: 45
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1584,6 +1585,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/sub-issue-closer.lock.yml b/.github/workflows/sub-issue-closer.lock.yml
index 693bf45fdc2..2197ed44ea8 100644
--- a/.github/workflows/sub-issue-closer.lock.yml
+++ b/.github/workflows/sub-issue-closer.lock.yml
@@ -856,6 +856,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 15
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1387,6 +1388,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/super-linter.lock.yml b/.github/workflows/super-linter.lock.yml
index dc8b45fe2b3..1c3e0aa8b66 100644
--- a/.github/workflows/super-linter.lock.yml
+++ b/.github/workflows/super-linter.lock.yml
@@ -868,6 +868,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 15
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1413,6 +1414,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/technical-doc-writer.lock.yml b/.github/workflows/technical-doc-writer.lock.yml
index 80afb091fef..a3782a425d5 100644
--- a/.github/workflows/technical-doc-writer.lock.yml
+++ b/.github/workflows/technical-doc-writer.lock.yml
@@ -929,6 +929,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 10
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1512,6 +1513,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/terminal-stylist.lock.yml b/.github/workflows/terminal-stylist.lock.yml
index 76b1989c4fe..2e3ce473e96 100644
--- a/.github/workflows/terminal-stylist.lock.yml
+++ b/.github/workflows/terminal-stylist.lock.yml
@@ -872,6 +872,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 10
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1404,6 +1405,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/test-dispatcher.lock.yml b/.github/workflows/test-dispatcher.lock.yml
index 8b2f2c6cab4..5fb382e6d06 100644
--- a/.github/workflows/test-dispatcher.lock.yml
+++ b/.github/workflows/test-dispatcher.lock.yml
@@ -801,6 +801,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 10
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1324,6 +1325,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/test-project-url-default.lock.yml b/.github/workflows/test-project-url-default.lock.yml
index 47524536944..744598058e6 100644
--- a/.github/workflows/test-project-url-default.lock.yml
+++ b/.github/workflows/test-project-url-default.lock.yml
@@ -864,6 +864,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 10
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1388,6 +1389,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/test-quality-sentinel.lock.yml b/.github/workflows/test-quality-sentinel.lock.yml
index 4b4a34c57a1..1e16bffaa86 100644
--- a/.github/workflows/test-quality-sentinel.lock.yml
+++ b/.github/workflows/test-quality-sentinel.lock.yml
@@ -924,6 +924,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 15
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1478,6 +1479,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/test-workflow.lock.yml b/.github/workflows/test-workflow.lock.yml
index 64de9a3ff3b..022304eaa1a 100644
--- a/.github/workflows/test-workflow.lock.yml
+++ b/.github/workflows/test-workflow.lock.yml
@@ -746,6 +746,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 10
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/tidy.lock.yml b/.github/workflows/tidy.lock.yml
index 167dee55b47..a1bb6e427cf 100644
--- a/.github/workflows/tidy.lock.yml
+++ b/.github/workflows/tidy.lock.yml
@@ -953,6 +953,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 10
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1507,6 +1508,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/ubuntu-image-analyzer.lock.yml b/.github/workflows/ubuntu-image-analyzer.lock.yml
index 601274c0b33..295dd25d59c 100644
--- a/.github/workflows/ubuntu-image-analyzer.lock.yml
+++ b/.github/workflows/ubuntu-image-analyzer.lock.yml
@@ -867,6 +867,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 30
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1404,6 +1405,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/uk-ai-operational-resilience.lock.yml b/.github/workflows/uk-ai-operational-resilience.lock.yml
index 0879e82d007..5e048435096 100644
--- a/.github/workflows/uk-ai-operational-resilience.lock.yml
+++ b/.github/workflows/uk-ai-operational-resilience.lock.yml
@@ -847,6 +847,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 30
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1384,6 +1385,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/update-astro.lock.yml b/.github/workflows/update-astro.lock.yml
index 96b6aea57de..e08e4c10c80 100644
--- a/.github/workflows/update-astro.lock.yml
+++ b/.github/workflows/update-astro.lock.yml
@@ -854,6 +854,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 45
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1430,6 +1431,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/video-analyzer.lock.yml b/.github/workflows/video-analyzer.lock.yml
index 862f65e8da7..44d04a5c50e 100644
--- a/.github/workflows/video-analyzer.lock.yml
+++ b/.github/workflows/video-analyzer.lock.yml
@@ -839,6 +839,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 15
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1363,6 +1364,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/visual-regression-checker.lock.yml b/.github/workflows/visual-regression-checker.lock.yml
index 9fbe22d8356..728f623a668 100644
--- a/.github/workflows/visual-regression-checker.lock.yml
+++ b/.github/workflows/visual-regression-checker.lock.yml
@@ -910,6 +910,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 15
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1436,6 +1437,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/weekly-blog-post-writer.lock.yml b/.github/workflows/weekly-blog-post-writer.lock.yml
index 31c396fecfa..3d8ce0d6555 100644
--- a/.github/workflows/weekly-blog-post-writer.lock.yml
+++ b/.github/workflows/weekly-blog-post-writer.lock.yml
@@ -936,6 +936,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 30
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1495,6 +1496,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/weekly-editors-health-check.lock.yml b/.github/workflows/weekly-editors-health-check.lock.yml
index 565c7311fb7..5a07323e851 100644
--- a/.github/workflows/weekly-editors-health-check.lock.yml
+++ b/.github/workflows/weekly-editors-health-check.lock.yml
@@ -897,6 +897,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 30
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1439,6 +1440,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/weekly-issue-summary.lock.yml b/.github/workflows/weekly-issue-summary.lock.yml
index 75f362b9501..f8461688f9e 100644
--- a/.github/workflows/weekly-issue-summary.lock.yml
+++ b/.github/workflows/weekly-issue-summary.lock.yml
@@ -858,6 +858,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1426,6 +1427,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/weekly-safe-outputs-spec-review.lock.yml b/.github/workflows/weekly-safe-outputs-spec-review.lock.yml
index 4723dbf4b83..9d9d29be8a2 100644
--- a/.github/workflows/weekly-safe-outputs-spec-review.lock.yml
+++ b/.github/workflows/weekly-safe-outputs-spec-review.lock.yml
@@ -822,6 +822,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 30
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1361,6 +1362,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/workflow-generator.lock.yml b/.github/workflows/workflow-generator.lock.yml
index 5c2d5036ad6..c79c47724f1 100644
--- a/.github/workflows/workflow-generator.lock.yml
+++ b/.github/workflows/workflow-generator.lock.yml
@@ -895,6 +895,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 5
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1429,6 +1430,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/workflow-health-manager.lock.yml b/.github/workflows/workflow-health-manager.lock.yml
index 680158afe71..4e7d1bd8e62 100644
--- a/.github/workflows/workflow-health-manager.lock.yml
+++ b/.github/workflows/workflow-health-manager.lock.yml
@@ -1,4 +1,4 @@
-# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"a1075b22f1a5cc9ec85385d47a35ba2c047985f69e9e5df9d0abfe95bf5d9071","body_hash":"37f7ee57073d156d65a76a2c237df5bd4d4528003d748631aa865d02c3b152b7","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.59"}}
+# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"0c54923ec404cdb80af4d8a2e532b55917c001cbac9fb1f4ffdaf2a4c9100a6a","body_hash":"37f7ee57073d156d65a76a2c237df5bd4d4528003d748631aa865d02c3b152b7","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.59"}}
# gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_GRAFANA_AUTHORIZATION","GH_AW_OTEL_GRAFANA_ENDPOINT","GH_AW_OTEL_SENTRY_AUTHORIZATION","GH_AW_OTEL_SENTRY_ENDPOINT","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.65"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.65"},{"image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.65"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.65"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.23","digest":"sha256:0dd1bd91a41e24a3ccc31b1ec6cb61d36608997fabf91f2d643b64e3fc33180a","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.23@sha256:0dd1bd91a41e24a3ccc31b1ec6cb61d36608997fabf91f2d643b64e3fc33180a"},{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"},{"image":"node:lts-alpine","digest":"sha256:2bdb65ed1dab192432bc31c95f94155ca5ad7fc1392fb7eb7526ab682fa5bf14","pinned_image":"node:lts-alpine@sha256:2bdb65ed1dab192432bc31c95f94155ca5ad7fc1392fb7eb7526ab682fa5bf14"}]}
# ___ _ _
# / _ \ | | (_)
@@ -897,7 +897,7 @@ jobs:
export GH_AW_NODE_BIN
export COPILOT_API_KEY="$COPILOT_DUMMY_BYOK"
(umask 177 && touch /tmp/gh-aw/agent-stdio.log)
- printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.65/awf-config.schema.json","network":{"allowDomains":["*.grafana.net","*.sentry.io","api.business.githubcopilot.com","api.enterprise.githubcopilot.com","api.github.com","api.githubcopilot.com","api.individual.githubcopilot.com","api.snapcraft.io","archive.ubuntu.com","azure.archive.ubuntu.com","crl.geotrust.com","crl.globalsign.com","crl.identrust.com","crl.sectigo.com","crl.thawte.com","crl.usertrust.com","crl.verisign.com","crl3.digicert.com","crl4.digicert.com","crls.ssl.com","github.com","host.docker.internal","json-schema.org","json.schemastore.org","keyserver.ubuntu.com","ocsp.digicert.com","ocsp.geotrust.com","ocsp.globalsign.com","ocsp.identrust.com","ocsp.sectigo.com","ocsp.ssl.com","ocsp.thawte.com","ocsp.usertrust.com","ocsp.verisign.com","packagecloud.io","packages.cloud.google.com","packages.microsoft.com","ppa.launchpad.net","raw.githubusercontent.com","registry.npmjs.org","s.symcb.com","s.symcd.com","security.ubuntu.com","telemetry.enterprise.githubcopilot.com","ts-crl.ws.symantec.com","ts-ocsp.ws.symantec.com","www.googleapis.com"]},"apiProxy":{"enabled":true,"enableTokenSteering":true,"maxRuns":500,"maxEffectiveTokens":30000000,"maxAiCredits":1000,"models":{"agent":["sonnet-6x","gpt-5.4","gpt-5.3","gemini-pro","any"],"antigravity":["copilot/antigravity*","google/antigravity*","gemini/antigravity*"],"any":["copilot/*","anthropic/*","openai/*","google/*","gemini/*"],"claude":["agent"],"codex":["agent"],"coding":["copilot/gpt-5*codex*","openai/gpt-5*codex*","gpt-5-codex"],"computer-use":["copilot/*computer-use*","google/*computer-use*","gemini/*computer-use*","openai/*computer-use*"],"copilot":["agent"],"deep-research":["copilot/deep-research*","copilot/o3-deep-research*","copilot/o4-mini-deep-research*","google/deep-research*","gemini/deep-research*","openai/o3-deep-research*","openai/o4-mini-deep-research*"],"gemini":["agent"],"gemini-3-flash":["copilot/gemini-3*flash*","google/gemini-3*flash*","gemini/gemini-3*flash*"],"gemini-3-pro":["copilot/gemini-3*pro*","google/gemini-3*pro*","google/nano-banana*","gemini/gemini-3*pro*"],"gemini-3.1-flash":["copilot/gemini-3.1*flash*","google/gemini-3.1*flash*","gemini/gemini-3.1*flash*"],"gemini-3.1-pro":["copilot/gemini-3.1*pro*","google/gemini-3.1*pro*","gemini/gemini-3.1*pro*"],"gemini-3.5-flash":["copilot/gemini-3.5*flash*","google/gemini-3.5*flash*","gemini/gemini-3.5*flash*"],"gemini-flash":["copilot/gemini-*flash*","google/gemini-*flash*","gemini/gemini-*flash*"],"gemini-flash-lite":["copilot/gemini-*flash*lite*","google/gemini-*flash*lite*","gemini/gemini-*flash*lite*"],"gemini-pro":["copilot/gemini-*pro*","google/gemini-*pro*","gemini/gemini-*pro*"],"gemma":["copilot/gemma*","google/gemma*","gemini/gemma*"],"gpt-5":["copilot/gpt-5*","openai/gpt-5*"],"gpt-5-codex":["copilot/gpt-5*codex*","openai/gpt-5*codex*"],"gpt-5-mini":["copilot/gpt-5*mini*","openai/gpt-5*mini*"],"gpt-5-nano":["copilot/gpt-5*nano*","openai/gpt-5*nano*"],"gpt-5-pro":["copilot/gpt-5*pro*","openai/gpt-5*pro*"],"gpt-5.2":["copilot/gpt-5.2*","openai/gpt-5.2*"],"gpt-5.3":["copilot/gpt-5.3*","openai/gpt-5.3*"],"gpt-5.4":["copilot/gpt-5.4*","openai/gpt-5.4*"],"gpt-5.5":["copilot/gpt-5.5*","openai/gpt-5.5*"],"haiku":["copilot/*haiku*","anthropic/*haiku*"],"large":["sonnet","gpt-5-pro","gpt-5","gemini-pro"],"mai-code":["copilot/MAI-Code*","copilot/mai-code*","openai/MAI-Code*"],"mini":["haiku","gpt-5-mini","gpt-5-nano","gemini-flash-lite"],"nano-banana":["copilot/nano-banana*","google/nano-banana*","gemini/nano-banana*"],"opus":["copilot/*opus*","anthropic/*opus*"],"opusplan":["opus?effort=high"],"reasoning":["copilot/o1*","copilot/o3*","copilot/o4*","openai/o1*","openai/o3*","openai/o4*"],"robotics":["copilot/*robotics*","google/*robotics*","gemini/*robotics*"],"small":["mini"],"small-agent":["haiku","gpt-5-mini","gemini-flash","any"],"sonnet":["copilot/*sonnet*","anthropic/*sonnet*"],"sonnet-6x":["copilot/*sonnet-4.5*","copilot/*sonnet-4.6*","copilot/*sonnet-4-5-*","anthropic/*sonnet-4-5-*","copilot/*sonnet-4-6*","anthropic/*sonnet-4-6*"],"summarization":["haiku","gpt-5-mini","gemini-flash-lite","mini"],"vision":["copilot/gemini-*image*","gemini/gemini-*image*","copilot/gemini-*flash*","gemini/gemini-*flash*"]}},"container":{"imageTag":"0.25.65"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json"
+ printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.65/awf-config.schema.json","network":{"allowDomains":["*.grafana.net","*.sentry.io","api.business.githubcopilot.com","api.enterprise.githubcopilot.com","api.github.com","api.githubcopilot.com","api.individual.githubcopilot.com","api.snapcraft.io","archive.ubuntu.com","azure.archive.ubuntu.com","crl.geotrust.com","crl.globalsign.com","crl.identrust.com","crl.sectigo.com","crl.thawte.com","crl.usertrust.com","crl.verisign.com","crl3.digicert.com","crl4.digicert.com","crls.ssl.com","github.com","host.docker.internal","json-schema.org","json.schemastore.org","keyserver.ubuntu.com","ocsp.digicert.com","ocsp.geotrust.com","ocsp.globalsign.com","ocsp.identrust.com","ocsp.sectigo.com","ocsp.ssl.com","ocsp.thawte.com","ocsp.usertrust.com","ocsp.verisign.com","packagecloud.io","packages.cloud.google.com","packages.microsoft.com","ppa.launchpad.net","raw.githubusercontent.com","registry.npmjs.org","s.symcb.com","s.symcd.com","security.ubuntu.com","telemetry.enterprise.githubcopilot.com","ts-crl.ws.symantec.com","ts-ocsp.ws.symantec.com","www.googleapis.com"]},"apiProxy":{"enabled":true,"enableTokenSteering":true,"maxRuns":500,"maxAiCredits":30000000,"models":{"agent":["sonnet-6x","gpt-5.4","gpt-5.3","gemini-pro","any"],"antigravity":["copilot/antigravity*","google/antigravity*","gemini/antigravity*"],"any":["copilot/*","anthropic/*","openai/*","google/*","gemini/*"],"claude":["agent"],"codex":["agent"],"coding":["copilot/gpt-5*codex*","openai/gpt-5*codex*","gpt-5-codex"],"computer-use":["copilot/*computer-use*","google/*computer-use*","gemini/*computer-use*","openai/*computer-use*"],"copilot":["agent"],"deep-research":["copilot/deep-research*","copilot/o3-deep-research*","copilot/o4-mini-deep-research*","google/deep-research*","gemini/deep-research*","openai/o3-deep-research*","openai/o4-mini-deep-research*"],"gemini":["agent"],"gemini-3-flash":["copilot/gemini-3*flash*","google/gemini-3*flash*","gemini/gemini-3*flash*"],"gemini-3-pro":["copilot/gemini-3*pro*","google/gemini-3*pro*","google/nano-banana*","gemini/gemini-3*pro*"],"gemini-3.1-flash":["copilot/gemini-3.1*flash*","google/gemini-3.1*flash*","gemini/gemini-3.1*flash*"],"gemini-3.1-pro":["copilot/gemini-3.1*pro*","google/gemini-3.1*pro*","gemini/gemini-3.1*pro*"],"gemini-3.5-flash":["copilot/gemini-3.5*flash*","google/gemini-3.5*flash*","gemini/gemini-3.5*flash*"],"gemini-flash":["copilot/gemini-*flash*","google/gemini-*flash*","gemini/gemini-*flash*"],"gemini-flash-lite":["copilot/gemini-*flash*lite*","google/gemini-*flash*lite*","gemini/gemini-*flash*lite*"],"gemini-pro":["copilot/gemini-*pro*","google/gemini-*pro*","gemini/gemini-*pro*"],"gemma":["copilot/gemma*","google/gemma*","gemini/gemma*"],"gpt-5":["copilot/gpt-5*","openai/gpt-5*"],"gpt-5-codex":["copilot/gpt-5*codex*","openai/gpt-5*codex*"],"gpt-5-mini":["copilot/gpt-5*mini*","openai/gpt-5*mini*"],"gpt-5-nano":["copilot/gpt-5*nano*","openai/gpt-5*nano*"],"gpt-5-pro":["copilot/gpt-5*pro*","openai/gpt-5*pro*"],"gpt-5.2":["copilot/gpt-5.2*","openai/gpt-5.2*"],"gpt-5.3":["copilot/gpt-5.3*","openai/gpt-5.3*"],"gpt-5.4":["copilot/gpt-5.4*","openai/gpt-5.4*"],"gpt-5.5":["copilot/gpt-5.5*","openai/gpt-5.5*"],"haiku":["copilot/*haiku*","anthropic/*haiku*"],"large":["sonnet","gpt-5-pro","gpt-5","gemini-pro"],"mai-code":["copilot/MAI-Code*","copilot/mai-code*","openai/MAI-Code*"],"mini":["haiku","gpt-5-mini","gpt-5-nano","gemini-flash-lite"],"nano-banana":["copilot/nano-banana*","google/nano-banana*","gemini/nano-banana*"],"opus":["copilot/*opus*","anthropic/*opus*"],"opusplan":["opus?effort=high"],"reasoning":["copilot/o1*","copilot/o3*","copilot/o4*","openai/o1*","openai/o3*","openai/o4*"],"robotics":["copilot/*robotics*","google/*robotics*","gemini/*robotics*"],"small":["mini"],"small-agent":["haiku","gpt-5-mini","gemini-flash","any"],"sonnet":["copilot/*sonnet*","anthropic/*sonnet*"],"sonnet-6x":["copilot/*sonnet-4.5*","copilot/*sonnet-4.6*","copilot/*sonnet-4-5-*","anthropic/*sonnet-4-5-*","copilot/*sonnet-4-6*","anthropic/*sonnet-4-6*"],"summarization":["haiku","gpt-5-mini","gemini-flash-lite","mini"],"vision":["copilot/gemini-*image*","gemini/gemini-*image*","copilot/gemini-*flash*","gemini/gemini-*flash*"]}},"container":{"imageTag":"0.25.65"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json"
GH_AW_MODEL_MULTIPLIERS_PATH="/tmp/gh-aw/model_multipliers.json" node "${RUNNER_TEMP}/gh-aw/actions/merge_awf_model_multipliers.cjs"
cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json
export GH_AW_MODELS_JSON_PATH="${RUNNER_TEMP}/gh-aw/actions/models.json"
@@ -928,6 +928,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 30
GH_AW_VERSION: dev
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
GITHUB_API_URL: ${{ github.api_url }}
@@ -1296,7 +1297,6 @@ jobs:
GH_AW_MISSING_TOOL_REPORT_AS_FAILURE: "true"
GH_AW_MISSING_DATA_REPORT_AS_FAILURE: "true"
GH_AW_TIMEOUT_MINUTES: "30"
- GH_AW_MAX_EFFECTIVE_TOKENS: "30000000"
with:
github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
script: |
@@ -1451,7 +1451,7 @@ jobs:
export GH_AW_NODE_BIN
export COPILOT_API_KEY="$COPILOT_DUMMY_BYOK"
(umask 177 && touch /tmp/gh-aw/threat-detection/detection.log)
- printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.65/awf-config.schema.json","network":{"allowDomains":["api.business.githubcopilot.com","api.enterprise.githubcopilot.com","api.github.com","api.githubcopilot.com","api.individual.githubcopilot.com","github.com","host.docker.internal","registry.npmjs.org","telemetry.enterprise.githubcopilot.com"]},"apiProxy":{"enabled":true,"enableTokenSteering":true,"maxRuns":500,"maxEffectiveTokens":30000000,"maxAiCredits":1000},"container":{"imageTag":"0.25.65"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json"
+ printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.65/awf-config.schema.json","network":{"allowDomains":["api.business.githubcopilot.com","api.enterprise.githubcopilot.com","api.github.com","api.githubcopilot.com","api.individual.githubcopilot.com","github.com","host.docker.internal","registry.npmjs.org","telemetry.enterprise.githubcopilot.com"]},"apiProxy":{"enabled":true,"enableTokenSteering":true,"maxRuns":500,"maxAiCredits":1000},"container":{"imageTag":"0.25.65"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json"
GH_AW_MODEL_MULTIPLIERS_PATH="/tmp/gh-aw/model_multipliers.json" node "${RUNNER_TEMP}/gh-aw/actions/merge_awf_model_multipliers.cjs"
cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json
export GH_AW_MODELS_JSON_PATH="${RUNNER_TEMP}/gh-aw/actions/models.json"
@@ -1480,6 +1480,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/workflow-health-manager.md b/.github/workflows/workflow-health-manager.md
index 70cbd22521b..42549205351 100644
--- a/.github/workflows/workflow-health-manager.md
+++ b/.github/workflows/workflow-health-manager.md
@@ -32,7 +32,7 @@ safe-outputs:
max: 5
timeout-minutes: 30
# Raised above 25M default: meta-orchestrator monitors all workflows; set ceiling to catch runaway health checks.
-max-effective-tokens: 30000000
+max-ai-credits: 30000000
imports:
- shared/reporting.md
- shared/otlp.md
diff --git a/.github/workflows/workflow-normalizer.lock.yml b/.github/workflows/workflow-normalizer.lock.yml
index a3102964d2a..cb3322f3b32 100644
--- a/.github/workflows/workflow-normalizer.lock.yml
+++ b/.github/workflows/workflow-normalizer.lock.yml
@@ -912,6 +912,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 30
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1441,6 +1442,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/.github/workflows/workflow-skill-extractor.lock.yml b/.github/workflows/workflow-skill-extractor.lock.yml
index 1f5f034ec75..1600ceb0cf9 100644
--- a/.github/workflows/workflow-skill-extractor.lock.yml
+++ b/.github/workflows/workflow-skill-extractor.lock.yml
@@ -882,6 +882,7 @@ jobs:
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_TIMEOUT_MINUTES: 30
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
@@ -1409,6 +1410,7 @@ jobs:
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/DICTATION.md b/DICTATION.md
index ee43f3b39ea..2c16d5e9edf 100644
--- a/DICTATION.md
+++ b/DICTATION.md
@@ -150,7 +150,7 @@ lockfile
manifest
markdown
max-continuations
-max-effective-tokens
+max-ai-credits
max-patch-size
max-runs
max-turns
diff --git a/actions/setup/js/collect_ndjson_output.cjs b/actions/setup/js/collect_ndjson_output.cjs
index d7bab7f759b..a25887a601f 100644
--- a/actions/setup/js/collect_ndjson_output.cjs
+++ b/actions/setup/js/collect_ndjson_output.cjs
@@ -323,10 +323,8 @@ async function main() {
}
continue;
}
- // SECURITY: Use normalizedItem (which strips infrastructure-only fields
- // like patch_path, bundle_path, base_commit, diff_size) instead of the
- // original item, to prevent agent-injected transport metadata from
- // reaching the privileged handler.
+ // Use the normalized item (with sanitized/validated fields) rather
+ // than the raw input, so downstream consumers see the canonical form.
core.info(`Line ${i + 1}: Valid ${itemType} item`);
parsedItems.push(validationResult.normalizedItem);
} else {
diff --git a/actions/setup/js/create_pull_request.cjs b/actions/setup/js/create_pull_request.cjs
index 66d930cf0fb..8623f22e6cb 100644
--- a/actions/setup/js/create_pull_request.cjs
+++ b/actions/setup/js/create_pull_request.cjs
@@ -37,6 +37,7 @@ const { withRetry, RATE_LIMIT_RETRY_CONFIG } = require("./error_recovery.cjs");
const { findAgent, getIssueDetails, assignAgentToIssue } = require("./assign_agent_helpers.cjs");
const { ensureFullHistoryForBundle, extractBundlePrerequisiteCommits, isShallowOrSparseCheckout, linearizeRangeAsCommit } = require("./git_helpers.cjs");
const { parseDiffGitHeader: parseDiffGitHeaderPaths, extractDiffGitHeaderEntries } = require("./patch_path_helpers.cjs");
+const { resolveTransportPaths } = require("./resolve_transport_paths.cjs");
const { resolveAllowedMentionsFromPayload } = require("./resolve_mentions_from_payload.cjs");
const {
MANAGED_FALLBACK_ISSUE_LABEL,
@@ -796,12 +797,15 @@ async function main(config = {}) {
core.info(`Processing create_pull_request: title=${pullRequestItem.title || "No title"}, bodyLength=${pullRequestItem.body?.length || 0}`);
- // Determine the patch file path from the message (set by the MCP server handler)
- const patchFilePath = pullRequestItem.patch_path;
+ // Determine the patch and bundle file paths. The MCP server sets these on
+ // the entry it writes, but the validation step strips them as a defense
+ // against agent-forged values. Recover them by re-deriving from `branch`.
+ const transportPaths = resolveTransportPaths(pullRequestItem, defaultTargetRepo);
+ const patchFilePath = transportPaths.patchPath;
core.info(`Patch file path: ${patchFilePath || "(not set)"}`);
// Determine the bundle file path from the message (set when patch-format: bundle is configured)
- const bundleFilePath = pullRequestItem.bundle_path;
+ const bundleFilePath = transportPaths.bundlePath;
if (bundleFilePath) {
core.info(`Bundle file path: ${bundleFilePath}`);
}
@@ -1665,7 +1669,7 @@ gh pr create --title '${title}' --base ${baseBranch} --head ${branchName} --repo
core.info(`Created new branch from base: ${branchName} (${branchBaseRef})`);
// Apply the patch using git CLI (skip if empty)
- if (!isEmpty) {
+ if (!isEmpty && patchFilePath) {
let postApplyBaseRef = null;
const capturePostApplyBaseRef = async () => {
const headResult = await exec.getExecOutput("git", ["rev-parse", "HEAD"]);
diff --git a/actions/setup/js/create_pull_request.test.cjs b/actions/setup/js/create_pull_request.test.cjs
index fee9bdf0755..c5be67fe4bd 100644
--- a/actions/setup/js/create_pull_request.test.cjs
+++ b/actions/setup/js/create_pull_request.test.cjs
@@ -8,6 +8,37 @@ import * as os from "os";
const require = createRequire(import.meta.url);
+const { getPatchPathForBranch, getPatchPathForBranchInRepo } = require("./git_patch_utils.cjs");
+const { getBundlePathForBranch, getBundlePathForBranchInRepo } = require("./generate_git_bundle.cjs");
+
+// The privileged handler derives patch/bundle paths from `branch` (and `repo`)
+// via resolveTransportPaths, so tests must write transport files at the
+// canonical derived location and let the handler discover them.
+function canonicalPatchPath(branch, repo) {
+ fs.mkdirSync("/tmp/gh-aw", { recursive: true });
+ return repo ? getPatchPathForBranchInRepo(branch, repo) : getPatchPathForBranch(branch);
+}
+function canonicalBundlePath(branch, repo) {
+ fs.mkdirSync("/tmp/gh-aw", { recursive: true });
+ return repo ? getBundlePathForBranchInRepo(branch, repo) : getBundlePathForBranch(branch);
+}
+function cleanupCanonicalTransports() {
+ try {
+ for (const f of fs.readdirSync("/tmp/gh-aw")) {
+ if (/^aw-.*\.(patch|bundle)$/.test(f)) {
+ fs.rmSync(`/tmp/gh-aw/${f}`, { force: true });
+ }
+ }
+ } catch {}
+}
+
+beforeEach(() => {
+ cleanupCanonicalTransports();
+});
+afterEach(() => {
+ cleanupCanonicalTransports();
+});
+
describe("create_pull_request - draft policy enforcement", () => {
let tempDir;
let originalEnv;
@@ -226,7 +257,7 @@ describe("create_pull_request - bundle transport shallow checkout", () => {
});
it("should fetch bundle without forcing an unshallow fetch", async () => {
- const patchPath = path.join(tempDir, "test.patch");
+ const patchPath = canonicalPatchPath("feature/test");
fs.writeFileSync(
patchPath,
`From abc123 Mon Sep 17 00:00:00 2001
@@ -245,12 +276,12 @@ index 0000000..abc1234
2.34.1
`
);
- const bundlePath = path.join(tempDir, "test.bundle");
+ const bundlePath = canonicalBundlePath("feature/test");
fs.writeFileSync(bundlePath, "bundle content");
const { main } = require("./create_pull_request.cjs");
const handler = await main({ base_branch: "main", preserve_branch_name: true });
- const result = await handler({ title: "Test PR", body: "Test body", branch: "feature/test", patch_path: patchPath, bundle_path: bundlePath }, {});
+ const result = await handler({ title: "Test PR", body: "Test body", branch: "feature/test" }, {});
expect(result.success).toBe(true);
// Initial bundle fetch is now via getExecOutput (with ignoreReturnCode: true) rather than exec,
@@ -270,7 +301,7 @@ index 0000000..abc1234
});
it("should pass signed_commits false to bundle pushes", async () => {
- const patchPath = path.join(tempDir, "test.patch");
+ const patchPath = canonicalPatchPath("feature/test");
fs.writeFileSync(
patchPath,
`From abc123 Mon Sep 17 00:00:00 2001
@@ -289,19 +320,19 @@ index 0000000..abc1234
2.34.1
`
);
- const bundlePath = path.join(tempDir, "test.bundle");
+ const bundlePath = canonicalBundlePath("feature/test");
fs.writeFileSync(bundlePath, "bundle content");
const { main } = require("./create_pull_request.cjs");
const handler = await main({ base_branch: "main", preserve_branch_name: true, signed_commits: false });
- const result = await handler({ title: "Test PR", body: "Test body", branch: "feature/test", patch_path: patchPath, bundle_path: bundlePath }, {});
+ const result = await handler({ title: "Test PR", body: "Test body", branch: "feature/test" }, {});
expect(result.success).toBe(true);
expect(pushSignedSpy).toHaveBeenCalledWith(expect.objectContaining({ signedCommits: false }));
});
it("should rewrite bundle history to a single commit and retry when signed push rejects merge commits", async () => {
- const patchPath = path.join(tempDir, "test.patch");
+ const patchPath = canonicalPatchPath("feature/test");
fs.writeFileSync(
patchPath,
`From abc123 Mon Sep 17 00:00:00 2001
@@ -320,7 +351,7 @@ index 0000000..abc1234
2.34.1
`
);
- const bundlePath = path.join(tempDir, "test.bundle");
+ const bundlePath = canonicalBundlePath("feature/test");
fs.writeFileSync(bundlePath, "bundle content");
let revParseHeadCallCount = 0;
@@ -353,7 +384,7 @@ index 0000000..abc1234
const { main } = require("./create_pull_request.cjs");
const handler = await main({ base_branch: "main", preserve_branch_name: true });
- const result = await handler({ title: "Test PR", body: "Test body", branch: "feature/test", patch_path: patchPath, bundle_path: bundlePath }, {});
+ const result = await handler({ title: "Test PR", body: "Test body", branch: "feature/test" }, {});
expect(result.success).toBe(true);
expect(result.fallback_used).not.toBe(true);
@@ -364,7 +395,7 @@ index 0000000..abc1234
});
it("should resolve bundle source ref from list-heads when JSONL branch ref is missing in bundle", async () => {
- const patchPath = path.join(tempDir, "test.patch");
+ const patchPath = canonicalPatchPath("ops-review-may09-2026");
fs.writeFileSync(
patchPath,
`From abc123 Mon Sep 17 00:00:00 2001
@@ -383,7 +414,7 @@ index 0000000..abc1234
2.34.1
`
);
- const bundlePath = path.join(tempDir, "test.bundle");
+ const bundlePath = canonicalBundlePath("ops-review-may09-2026");
fs.writeFileSync(bundlePath, "bundle content");
global.exec.getExecOutput.mockImplementation((cmd, args, options) => {
@@ -412,7 +443,7 @@ index 0000000..abc1234
const { main } = require("./create_pull_request.cjs");
const handler = await main({ base_branch: "main", preserve_branch_name: true });
- const result = await handler({ title: "Test PR", body: "Test body", branch: "ops-review-may09-2026", patch_path: patchPath, bundle_path: bundlePath }, {});
+ const result = await handler({ title: "Test PR", body: "Test body", branch: "ops-review-may09-2026" }, {});
expect(result.success).toBe(true);
expect(global.exec.getExecOutput).toHaveBeenCalledWith("git", ["bundle", "list-heads", bundlePath]);
@@ -424,7 +455,7 @@ index 0000000..abc1234
});
it("should fall back to HEAD refspec when bundle contains only HEAD (no refs/heads/* entry)", async () => {
- const patchPath = path.join(tempDir, "test.patch");
+ const patchPath = canonicalPatchPath("docs/update-migration-version-2026-05-19-4fe3b9f7f99fc1d6");
fs.writeFileSync(
patchPath,
`From abc123 Mon Sep 17 00:00:00 2001
@@ -443,7 +474,7 @@ index 0000000..abc1234
2.34.1
`
);
- const bundlePath = path.join(tempDir, "test.bundle");
+ const bundlePath = canonicalBundlePath("docs/update-migration-version-2026-05-19-4fe3b9f7f99fc1d6");
fs.writeFileSync(bundlePath, "bundle content");
global.exec.getExecOutput.mockImplementation((cmd, args, options) => {
@@ -473,7 +504,7 @@ index 0000000..abc1234
const { main } = require("./create_pull_request.cjs");
const handler = await main({ base_branch: "main", preserve_branch_name: true });
- const result = await handler({ title: "Test PR", body: "Test body", branch: "docs/update-migration-version-2026-05-19-4fe3b9f7f99fc1d6", patch_path: patchPath, bundle_path: bundlePath }, {});
+ const result = await handler({ title: "Test PR", body: "Test body", branch: "docs/update-migration-version-2026-05-19-4fe3b9f7f99fc1d6" }, {});
expect(result.success).toBe(true);
expect(global.exec.getExecOutput).toHaveBeenCalledWith("git", ["bundle", "list-heads", bundlePath]);
@@ -486,7 +517,7 @@ index 0000000..abc1234
});
it("should fetch prerequisite commits and retry bundle fetch when prerequisites are missing", async () => {
- const patchPath = path.join(tempDir, "test.patch");
+ const patchPath = canonicalPatchPath("feature/test");
fs.writeFileSync(
patchPath,
`From abc123 Mon Sep 17 00:00:00 2001
@@ -505,7 +536,7 @@ index 0000000..abc1234
2.34.1
`
);
- const bundlePath = path.join(tempDir, "test.bundle");
+ const bundlePath = canonicalBundlePath("feature/test");
fs.writeFileSync(bundlePath, "bundle content");
const missingSha = "256f08b38d9ce40cfa5d46385551caba8642a9df";
@@ -530,7 +561,7 @@ index 0000000..abc1234
const { main } = require("./create_pull_request.cjs");
const handler = await main({ base_branch: "main", preserve_branch_name: true });
- const result = await handler({ title: "Test PR", body: "Test body", branch: "feature/test", patch_path: patchPath, bundle_path: bundlePath }, {});
+ const result = await handler({ title: "Test PR", body: "Test body", branch: "feature/test" }, {});
expect(result.success).toBe(true);
// Prerequisites are fetched from origin via exec with --filter=blob:none to avoid downloading blobs
@@ -542,7 +573,7 @@ index 0000000..abc1234
});
it("should fetch all prerequisite commits in a single origin fetch and retry bundle fetch", async () => {
- const patchPath = path.join(tempDir, "test.patch");
+ const patchPath = canonicalPatchPath("feature/test");
fs.writeFileSync(
patchPath,
`From abc123 Mon Sep 17 00:00:00 2001
@@ -561,7 +592,7 @@ index 0000000..abc1234
2.34.1
`
);
- const bundlePath = path.join(tempDir, "test.bundle");
+ const bundlePath = canonicalBundlePath("feature/test");
fs.writeFileSync(bundlePath, "bundle content");
const missingSha1 = "256f08b38d9ce40cfa5d46385551caba8642a9df";
@@ -584,7 +615,7 @@ index 0000000..abc1234
const { main } = require("./create_pull_request.cjs");
const handler = await main({ base_branch: "main", preserve_branch_name: true });
- const result = await handler({ title: "Test PR", body: "Test body", branch: "feature/test", patch_path: patchPath, bundle_path: bundlePath }, {});
+ const result = await handler({ title: "Test PR", body: "Test body", branch: "feature/test" }, {});
expect(result.success).toBe(true);
expect(global.exec.exec).toHaveBeenCalledWith("git", ["fetch", "--filter=blob:none", "origin", missingSha1, missingSha2]);
@@ -594,7 +625,7 @@ index 0000000..abc1234
});
it("should fail when fetching prerequisite commits from origin fails", async () => {
- const patchPath = path.join(tempDir, "test.patch");
+ const patchPath = canonicalPatchPath("feature/test");
fs.writeFileSync(
patchPath,
`From abc123 Mon Sep 17 00:00:00 2001
@@ -613,7 +644,7 @@ index 0000000..abc1234
2.34.1
`
);
- const bundlePath = path.join(tempDir, "test.bundle");
+ const bundlePath = canonicalBundlePath("feature/test");
fs.writeFileSync(bundlePath, "bundle content");
const missingSha = "256f08b38d9ce40cfa5d46385551caba8642a9df";
@@ -641,7 +672,7 @@ index 0000000..abc1234
const { main } = require("./create_pull_request.cjs");
const handler = await main({ base_branch: "main", preserve_branch_name: true });
- const result = await handler({ title: "Test PR", body: "Test body", branch: "feature/test", patch_path: patchPath, bundle_path: bundlePath }, {});
+ const result = await handler({ title: "Test PR", body: "Test body", branch: "feature/test" }, {});
expect(result.success).toBe(false);
expect(result.error).toBe("Failed to apply bundle");
@@ -652,7 +683,7 @@ index 0000000..abc1234
});
it("should include retry context when bundle fetch still fails after prerequisite recovery", async () => {
- const patchPath = path.join(tempDir, "test.patch");
+ const patchPath = canonicalPatchPath("feature/test");
fs.writeFileSync(
patchPath,
`From abc123 Mon Sep 17 00:00:00 2001
@@ -671,7 +702,7 @@ index 0000000..abc1234
2.34.1
`
);
- const bundlePath = path.join(tempDir, "test.bundle");
+ const bundlePath = canonicalBundlePath("feature/test");
fs.writeFileSync(bundlePath, "bundle content");
const missingSha = "256f08b38d9ce40cfa5d46385551caba8642a9df";
@@ -699,7 +730,7 @@ index 0000000..abc1234
const { main } = require("./create_pull_request.cjs");
const handler = await main({ base_branch: "main", preserve_branch_name: true });
- const result = await handler({ title: "Test PR", body: "Test body", branch: "feature/test", patch_path: patchPath, bundle_path: bundlePath }, {});
+ const result = await handler({ title: "Test PR", body: "Test body", branch: "feature/test" }, {});
expect(result.success).toBe(false);
expect(result.error).toBe("Failed to apply bundle");
@@ -709,7 +740,7 @@ index 0000000..abc1234
});
it("should not fetch a bundle directly into the target branch", async () => {
- const patchPath = path.join(tempDir, "test.patch");
+ const patchPath = canonicalPatchPath("autoloop/perf-comparison");
fs.writeFileSync(
patchPath,
`From abc123 Mon Sep 17 00:00:00 2001
@@ -728,12 +759,12 @@ index 0000000..abc1234
2.34.1
`
);
- const bundlePath = path.join(tempDir, "test.bundle");
+ const bundlePath = canonicalBundlePath("autoloop/perf-comparison");
fs.writeFileSync(bundlePath, "bundle content");
const { main } = require("./create_pull_request.cjs");
const handler = await main({ base_branch: "main", preserve_branch_name: true });
- const result = await handler({ title: "Test PR", body: "Test body\n\nCloses #57\nResolves test-owner/test-repo#58", branch: "autoloop/perf-comparison", patch_path: patchPath, bundle_path: bundlePath }, {});
+ const result = await handler({ title: "Test PR", body: "Test body\n\nCloses #57\nResolves test-owner/test-repo#58", branch: "autoloop/perf-comparison" }, {});
expect(result.success).toBe(true);
// The initial bundle fetch uses getExecOutput (not exec.exec) — ensure it never uses the direct branch refspec
@@ -748,7 +779,7 @@ index 0000000..abc1234
});
it("should give fallback issue bundle instructions that avoid direct branch fetches", async () => {
- const patchPath = path.join(tempDir, "test.patch");
+ const patchPath = canonicalPatchPath("autoloop/perf-comparison");
fs.writeFileSync(
patchPath,
`From abc123 Mon Sep 17 00:00:00 2001
@@ -767,13 +798,13 @@ index 0000000..abc1234
2.34.1
`
);
- const bundlePath = path.join(tempDir, "aw-test.bundle");
+ const bundlePath = canonicalBundlePath("autoloop/perf-comparison");
fs.writeFileSync(bundlePath, "bundle content");
pushSignedSpy.mockRejectedValueOnce(new Error("push rejected"));
const { main } = require("./create_pull_request.cjs");
const handler = await main({ base_branch: "main", preserve_branch_name: true });
- const result = await handler({ title: "Test PR", body: "Test body\n\nCloses #57\nResolves test-owner/test-repo#58", branch: "autoloop/perf-comparison", patch_path: patchPath, bundle_path: bundlePath }, {});
+ const result = await handler({ title: "Test PR", body: "Test body\n\nCloses #57\nResolves test-owner/test-repo#58", branch: "autoloop/perf-comparison" }, {});
expect(result.success).toBe(true);
expect(result.fallback_used).toBe(true);
@@ -1461,8 +1492,8 @@ ${diffs}
`;
}
- function writePatch(content) {
- const p = path.join(tempDir, "test.patch");
+ function writePatch(branch, content) {
+ const p = canonicalPatchPath(branch);
fs.writeFileSync(p, content);
return p;
}
@@ -1473,11 +1504,11 @@ ${diffs}
}
it("should reject files outside the allowed-files allowlist", async () => {
- const patchPath = writePatch(createPatchWithFiles("src/index.js"));
+ const patchPath = writePatch("should-reject-files-outside-the-allowed-files-allowlist", createPatchWithFiles("src/index.js"));
const { main } = require("./create_pull_request.cjs");
const handler = await main({ allowed_files: [".github/aw/**"] });
- const result = await handler({ patch_path: patchPath, title: "Test PR", body: "" }, {});
+ const result = await handler({ title: "Test PR", body: "", branch: "should-reject-files-outside-the-allowed-files-allowlist" }, {});
expect(result.success).toBe(false);
expect(result.error).toContain("outside the allowed-files list");
@@ -1485,11 +1516,11 @@ ${diffs}
});
it("should reject a mixed patch where some files are outside the allowlist", async () => {
- const patchPath = writePatch(createPatchWithFiles(".github/aw/github-agentic-workflows.md", "src/index.js"));
+ const patchPath = writePatch("should-reject-a-mixed-patch-where-some-files-are-outside-the", createPatchWithFiles(".github/aw/github-agentic-workflows.md", "src/index.js"));
const { main } = require("./create_pull_request.cjs");
const handler = await main({ allowed_files: [".github/aw/**"] });
- const result = await handler({ patch_path: patchPath, title: "Test PR", body: "" }, {});
+ const result = await handler({ title: "Test PR", body: "", branch: "should-reject-a-mixed-patch-where-some-files-are-outside-the" }, {});
expect(result.success).toBe(false);
expect(result.error).toContain("outside the allowed-files list");
@@ -1500,7 +1531,7 @@ ${diffs}
it("should still enforce protected-files when allowed-files matches (orthogonal checks)", async () => {
// allowed-files and protected-files are orthogonal: both checks must pass.
// Matching the allowlist does NOT bypass the protected-files policy.
- const patchPath = writePatch(createPatchWithFiles(".github/aw/instructions.md"));
+ const patchPath = writePatch("should-still-enforce-protected-files-when-allowed-files-matc", createPatchWithFiles(".github/aw/instructions.md"));
const { main } = require("./create_pull_request.cjs");
const handler = await main({
@@ -1508,7 +1539,7 @@ ${diffs}
protected_path_prefixes: [".github/"],
protected_files_policy: "blocked",
});
- const result = await handler({ patch_path: patchPath, title: "Test PR", body: "" }, {});
+ const result = await handler({ title: "Test PR", body: "", branch: "should-still-enforce-protected-files-when-allowed-files-matc" }, {});
expect(result.success).toBe(false);
expect(result.error).toContain("protected files");
@@ -1516,7 +1547,7 @@ ${diffs}
it("should allow a protected file when both allowed-files matches and protected-files: allowed is set", async () => {
// Both checks are satisfied explicitly: allowlist scope + protected-files permission.
- const patchPath = writePatch(createPatchWithFiles(".github/aw/instructions.md"));
+ const patchPath = writePatch("should-allow-a-protected-file-when-both-allowed-files-matche", createPatchWithFiles(".github/aw/instructions.md"));
const { main } = require("./create_pull_request.cjs");
const handler = await main({
@@ -1524,7 +1555,7 @@ ${diffs}
protected_path_prefixes: [".github/"],
protected_files_policy: "allowed",
});
- const result = await handler({ patch_path: patchPath, title: "Test PR", body: "" }, {});
+ const result = await handler({ title: "Test PR", body: "", branch: "should-allow-a-protected-file-when-both-allowed-files-matche" }, {});
// Should not be blocked by either check
expect(result.error || "").not.toContain("protected files");
@@ -1532,28 +1563,28 @@ ${diffs}
});
it("should still enforce protected-files when allowed-files is not set", async () => {
- const patchPath = writePatch(createPatchWithFiles(".github/aw/instructions.md"));
+ const patchPath = writePatch("should-still-enforce-protected-files-when-allowed-files-is-n", createPatchWithFiles(".github/aw/instructions.md"));
const { main } = require("./create_pull_request.cjs");
const handler = await main({
protected_path_prefixes: [".github/"],
protected_files_policy: "blocked",
});
- const result = await handler({ patch_path: patchPath, title: "Test PR", body: "" }, {});
+ const result = await handler({ title: "Test PR", body: "", branch: "should-still-enforce-protected-files-when-allowed-files-is-n" }, {});
expect(result.success).toBe(false);
expect(result.error).toContain("protected files");
});
it("should create PR with caution and request-changes review when protected-files is request_review", async () => {
- const patchPath = writePatch(createPatchWithFiles(".github/aw/instructions.md"));
+ const patchPath = writePatch("should-create-pr-with-caution-and-request-changes-review-whe", createPatchWithFiles(".github/aw/instructions.md"));
const { main } = require("./create_pull_request.cjs");
const handler = await main({
protected_path_prefixes: [".github/"],
protected_files_policy: "request_review",
});
- const result = await handler({ patch_path: patchPath, title: "Test PR", body: "Body text" }, {});
+ const result = await handler({ title: "Test PR", body: "Body text", branch: "should-create-pr-with-caution-and-request-changes-review-whe" }, {});
expect(result.success).toBe(true);
expect(global.github.rest.pulls.create).toHaveBeenCalledTimes(1);
@@ -1569,13 +1600,13 @@ ${diffs}
});
it("should default to request_review when protected-files policy is unset", async () => {
- const patchPath = writePatch(createPatchWithFiles(".github/aw/instructions.md"));
+ const patchPath = writePatch("should-default-to-request-review-when-protected-files-policy", createPatchWithFiles(".github/aw/instructions.md"));
const { main } = require("./create_pull_request.cjs");
const handler = await main({
protected_path_prefixes: [".github/"],
});
- const result = await handler({ patch_path: patchPath, title: "Test PR", body: "Body text" }, {});
+ const result = await handler({ title: "Test PR", body: "Body text", branch: "should-default-to-request-review-when-protected-files-policy" }, {});
expect(result.success).toBe(true);
expect(global.github.rest.pulls.create).toHaveBeenCalledTimes(1);
@@ -1585,7 +1616,7 @@ ${diffs}
});
it("should retry with COMMENT when REQUEST_CHANGES review is rejected on own pull request", async () => {
- const patchPath = writePatch(createPatchWithFiles(".github/aw/instructions.md"));
+ const patchPath = writePatch("should-retry-with-comment-when-request-changes-review-is-rej", createPatchWithFiles(".github/aw/instructions.md"));
global.github.rest.pulls.createReview = vi
.fn()
.mockRejectedValueOnce(new Error("Can not request changes on your own pull request"))
@@ -1596,7 +1627,7 @@ ${diffs}
protected_path_prefixes: [".github/"],
protected_files_policy: "request_review",
});
- const result = await handler({ patch_path: patchPath, title: "Test PR", body: "Body text" }, {});
+ const result = await handler({ title: "Test PR", body: "Body text", branch: "should-retry-with-comment-when-request-changes-review-is-rej" }, {});
expect(result.success).toBe(true);
expect(global.github.rest.pulls.createReview).toHaveBeenCalledTimes(2);
@@ -1605,7 +1636,7 @@ ${diffs}
});
it("should push branch with compare URL for protected-files fallback (patch transport)", async () => {
- const patchPath = writePatch(createPatchWithFiles(".github/aw/instructions.md"));
+ const patchPath = writePatch("feature/protected", createPatchWithFiles(".github/aw/instructions.md"));
const promptsDir = path.join(tempDir, "prompts");
fs.mkdirSync(promptsDir, { recursive: true });
const templateSrc = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../md/manifest_protection_create_pr_fallback.md");
@@ -1624,7 +1655,7 @@ ${diffs}
protected_path_prefixes: [".github/"],
protected_files_policy: "fallback-to-issue",
});
- const result = await handler({ patch_path: patchPath, title: "Test PR", body: "Test body", branch: "feature/protected" }, {});
+ const result = await handler({ title: "Test PR", body: "Test body", branch: "feature/protected" }, {});
expect(result.success).toBe(true);
expect(result.fallback_used).toBe(true);
@@ -1643,8 +1674,8 @@ ${diffs}
});
it("should push branch with compare URL for protected-files fallback (bundle transport)", async () => {
- const patchPath = writePatch(createPatchWithFiles(".github/aw/instructions.md"));
- const bundlePath = path.join(tempDir, "aw-protected.bundle");
+ const patchPath = writePatch("feature/protected", createPatchWithFiles(".github/aw/instructions.md"));
+ const bundlePath = canonicalBundlePath("feature/protected");
fs.writeFileSync(bundlePath, "bundle content");
const promptsDir = path.join(tempDir, "prompts");
fs.mkdirSync(promptsDir, { recursive: true });
@@ -1664,7 +1695,7 @@ ${diffs}
protected_path_prefixes: [".github/"],
protected_files_policy: "fallback-to-issue",
});
- const result = await handler({ patch_path: patchPath, bundle_path: bundlePath, title: "Test PR", body: "Test body", branch: "feature/protected" }, {});
+ const result = await handler({ title: "Test PR", body: "Test body", branch: "feature/protected" }, {});
expect(result.success).toBe(true);
expect(result.fallback_used).toBe(true);
@@ -1781,8 +1812,8 @@ ${diffs}
`;
}
- function writePatch(content) {
- const p = path.join(tempDir, "test.patch");
+ function writePatch(branch, content) {
+ const p = canonicalPatchPath(branch);
fs.writeFileSync(p, content);
return p;
}
@@ -1790,27 +1821,27 @@ ${diffs}
it("should ignore files matching excluded-files patterns (not blocked by allowed-files)", async () => {
// excluded-files are excluded at patch generation time via git :(exclude) pathspecs.
// Simulate post-generation: the patch already contains only the non-ignored file.
- const patchPath = writePatch(createPatchWithFiles("src/index.js"));
+ const patchPath = writePatch("should-ignore-files-matching-excluded-files-patterns-not-blo", createPatchWithFiles("src/index.js"));
const { main } = require("./create_pull_request.cjs");
const handler = await main({
excluded_files: ["auto-generated/**"],
allowed_files: ["src/**"],
});
- const result = await handler({ patch_path: patchPath, title: "Test PR", body: "" }, {});
+ const result = await handler({ title: "Test PR", body: "", branch: "should-ignore-files-matching-excluded-files-patterns-not-blo" }, {});
expect(result.error || "").not.toContain("outside the allowed-files list");
});
it("should still block non-ignored files that violate the allowed-files list", async () => {
- const patchPath = writePatch(createPatchWithFiles("src/index.js", "other/file.txt"));
+ const patchPath = writePatch("should-still-block-non-ignored-files-that-violate-the-allowe", createPatchWithFiles("src/index.js", "other/file.txt"));
const { main } = require("./create_pull_request.cjs");
const handler = await main({
excluded_files: ["auto-generated/**"],
allowed_files: ["src/**"],
});
- const result = await handler({ patch_path: patchPath, title: "Test PR", body: "" }, {});
+ const result = await handler({ title: "Test PR", body: "", branch: "should-still-block-non-ignored-files-that-violate-the-allowe" }, {});
expect(result.success).toBe(false);
expect(result.error).toContain("outside the allowed-files list");
@@ -1821,7 +1852,7 @@ ${diffs}
it("should ignore files matching excluded-files patterns (not blocked by protected-files)", async () => {
// excluded-files are excluded at patch generation time via git :(exclude) pathspecs.
// Simulate post-generation: the patch already contains only the non-ignored file.
- const patchPath = writePatch(createPatchWithFiles("src/index.js"));
+ const patchPath = writePatch("should-ignore-files-matching-excluded-files-patterns-not-blo", createPatchWithFiles("src/index.js"));
const { main } = require("./create_pull_request.cjs");
const handler = await main({
@@ -1829,7 +1860,7 @@ ${diffs}
protected_files: ["package.json"],
protected_files_policy: "blocked",
});
- const result = await handler({ patch_path: patchPath, title: "Test PR", body: "" }, {});
+ const result = await handler({ title: "Test PR", body: "", branch: "should-ignore-files-matching-excluded-files-patterns-not-blo" }, {});
expect(result.error || "").not.toContain("protected files");
});
@@ -1843,7 +1874,7 @@ ${diffs}
allowed_files: ["src/**"],
});
// No patch file — simulates all changes being ignored at generation time
- const result = await handler({ patch_path: path.join(tempDir, "nonexistent.patch"), title: "Test PR", body: "" }, {});
+ const result = await handler({ title: "Test PR", body: "", branch: "should-allow-when-all-patch-files-are-ignored-even-with-allo" }, {});
// No patch → treated as no changes, not an allowlist violation
expect(result.error || "").not.toContain("outside the allowed-files list");
@@ -2347,6 +2378,12 @@ describe("create_pull_request - patch apply fallback to original base commit", (
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "create-pr-fallback-test-"));
patchFilePath = path.join(tempDir, "test.patch");
fs.writeFileSync(patchFilePath, PATCH_CONTENT, "utf8");
+ // Write the same patch content at every canonical path consumed by tests in
+ // this describe, so the handler (which re-derives the path from
+ // message.branch) finds it.
+ for (const branch of ["test-branch", "preserve-me", "chaos/preserve-me", "some-branch"]) {
+ fs.writeFileSync(canonicalPatchPath(branch), PATCH_CONTENT, "utf8");
+ }
global.core = {
info: vi.fn(),
@@ -2440,7 +2477,7 @@ describe("create_pull_request - patch apply fallback to original base commit", (
const { main } = require("./create_pull_request.cjs");
const handler = await main({});
- const result = await handler({ title: "Test PR", body: "Test body", patch_path: patchFilePath, branch: "test-branch", base_commit: ` ${MOCK_BASE_COMMIT_SHA} ` }, {});
+ const result = await handler({ title: "Test PR", body: "Test body", branch: "test-branch", base_commit: ` ${MOCK_BASE_COMMIT_SHA} ` }, {});
expect(result.success).toBe(true);
expect(global.exec.exec).toHaveBeenCalledWith("git", ["cat-file", "-e", MOCK_BASE_COMMIT_SHA]);
@@ -2456,7 +2493,7 @@ describe("create_pull_request - patch apply fallback to original base commit", (
const { main } = require("./create_pull_request.cjs");
const handler = await main({});
- const result = await handler({ title: "Test PR", body: "Test body", patch_path: patchFilePath, branch: "test-branch", base_commit: "not-a-sha --bad" }, {});
+ const result = await handler({ title: "Test PR", body: "Test body", branch: "test-branch", base_commit: "not-a-sha --bad" }, {});
expect(result.success).toBe(true);
expect(global.exec.exec).not.toHaveBeenCalledWith("git", ["cat-file", "-e", "not-a-sha --bad"]);
@@ -2476,7 +2513,7 @@ describe("create_pull_request - patch apply fallback to original base commit", (
const { main } = require("./create_pull_request.cjs");
const handler = await main({});
- const result = await handler({ title: "Test PR", body: "Test body", patch_path: patchFilePath, branch: "test-branch", base_commit: MOCK_BASE_COMMIT_SHA }, {});
+ const result = await handler({ title: "Test PR", body: "Test body", branch: "test-branch", base_commit: MOCK_BASE_COMMIT_SHA }, {});
expect(result.success).toBe(true);
expect(global.exec.exec).toHaveBeenCalledWith("git", ["cat-file", "-e", MOCK_BASE_COMMIT_SHA]);
@@ -2503,7 +2540,7 @@ describe("create_pull_request - patch apply fallback to original base commit", (
const { main } = require("./create_pull_request.cjs");
const handler = await main({});
- const result = await handler({ title: "Test PR", body: "Test body", patch_path: patchFilePath, branch: "test-branch", base_commit: MOCK_BASE_COMMIT_SHA }, {});
+ const result = await handler({ title: "Test PR", body: "Test body", branch: "test-branch", base_commit: MOCK_BASE_COMMIT_SHA }, {});
expect(result.success).toBe(true);
// Should warn that the PR will show merge conflicts
@@ -2557,7 +2594,6 @@ describe("create_pull_request - patch apply fallback to original base commit", (
{
title: "Test PR",
body: "Test body",
- patch_path: patchFilePath,
branch: "test-branch",
base_commit: MOCK_BASE_COMMIT_SHA,
},
@@ -2586,7 +2622,7 @@ describe("create_pull_request - patch apply fallback to original base commit", (
const { main } = require("./create_pull_request.cjs");
const handler = await main({});
- const result = await handler({ title: "Test PR", body: "Test body", patch_path: patchFilePath, branch: "test-branch", base_commit: MOCK_BASE_COMMIT_SHA }, {});
+ const result = await handler({ title: "Test PR", body: "Test body", branch: "test-branch", base_commit: MOCK_BASE_COMMIT_SHA }, {});
expect(result.success).toBe(false);
expect(result.error).toBe("Failed to apply patch");
@@ -2624,7 +2660,7 @@ describe("create_pull_request - patch apply fallback to original base commit", (
const { main } = require("./create_pull_request.cjs");
const handler = await main({});
- const result = await handler({ title: "Test PR", body: "Test body", patch_path: patchFilePath, branch: "test-branch", base_commit: MOCK_BASE_COMMIT_SHA }, {});
+ const result = await handler({ title: "Test PR", body: "Test body", branch: "test-branch", base_commit: MOCK_BASE_COMMIT_SHA }, {});
expect(result.success).toBe(true);
expect(global.exec.exec).toHaveBeenCalledWith("git", ["checkout", "--theirs", "--", conflictedPath]);
@@ -2656,7 +2692,7 @@ describe("create_pull_request - patch apply fallback to original base commit", (
const { main } = require("./create_pull_request.cjs");
const handler = await main({});
- const result = await handler({ title: "Test PR", body: "Test body", patch_path: patchFilePath, branch: "test-branch", base_commit: MOCK_BASE_COMMIT_SHA }, {});
+ const result = await handler({ title: "Test PR", body: "Test body", branch: "test-branch", base_commit: MOCK_BASE_COMMIT_SHA }, {});
expect(result.success).toBe(false);
expect(global.core.warning).toHaveBeenCalledWith(expect.stringContaining("Automatic add/add conflict recovery attempt failed"));
@@ -2683,7 +2719,7 @@ describe("create_pull_request - patch apply fallback to original base commit", (
const { main } = require("./create_pull_request.cjs");
const handler = await main({});
- const result = await handler({ title: "Test PR", body: "Test body", patch_path: patchFilePath, branch: "test-branch", base_commit: MOCK_BASE_COMMIT_SHA }, {});
+ const result = await handler({ title: "Test PR", body: "Test body", branch: "test-branch", base_commit: MOCK_BASE_COMMIT_SHA }, {});
expect(result.success).toBe(false);
expect(result.error).toBe("Failed to apply patch");
@@ -2706,7 +2742,7 @@ describe("create_pull_request - patch apply fallback to original base commit", (
const handler = await main({});
// No base_commit provided - fallback should not be possible
- const result = await handler({ title: "Test PR", body: "Test body", patch_path: patchFilePath, branch: "test-branch" }, {});
+ const result = await handler({ title: "Test PR", body: "Test body", branch: "test-branch" }, {});
expect(result.success).toBe(false);
expect(result.error).toBe("Failed to apply patch");
@@ -2736,7 +2772,7 @@ describe("create_pull_request - patch apply fallback to original base commit", (
const { main } = require("./create_pull_request.cjs");
const handler = await main({ preserve_branch_name: true, recreate_ref: true });
- const result = await handler({ title: "Test PR", body: "Test body", patch_path: patchFilePath, branch: "preserve-me", base_commit: MOCK_BASE_COMMIT_SHA }, {});
+ const result = await handler({ title: "Test PR", body: "Test body", branch: "preserve-me", base_commit: MOCK_BASE_COMMIT_SHA }, {});
expect(result.success).toBe(true);
// Should have called deleteRef to force-delete the existing remote branch
@@ -2769,7 +2805,7 @@ describe("create_pull_request - patch apply fallback to original base commit", (
const { main } = require("./create_pull_request.cjs");
const handler = await main({ preserve_branch_name: true, fallback_as_issue: false });
- const result = await handler({ title: "Test PR", body: "Test body", patch_path: patchFilePath, branch: "preserve-me", base_commit: MOCK_BASE_COMMIT_SHA }, {});
+ const result = await handler({ title: "Test PR", body: "Test body", branch: "preserve-me", base_commit: MOCK_BASE_COMMIT_SHA }, {});
expect(result.success).toBe(false);
expect(result.error_type).toBe("push_failed");
@@ -2796,7 +2832,7 @@ describe("create_pull_request - patch apply fallback to original base commit", (
const { main } = require("./create_pull_request.cjs");
const handler = await main({ preserve_branch_name: true, recreate_ref: true, fallback_as_issue: false });
- const result = await handler({ title: "Test PR", body: "Test body", patch_path: patchFilePath, branch: "preserve-me", base_commit: MOCK_BASE_COMMIT_SHA }, {});
+ const result = await handler({ title: "Test PR", body: "Test body", branch: "preserve-me", base_commit: MOCK_BASE_COMMIT_SHA }, {});
expect(result.success).toBe(false);
expect(result.error_type).toBe("push_failed");
@@ -2834,7 +2870,7 @@ describe("create_pull_request - patch apply fallback to original base commit", (
const { main } = require("./create_pull_request.cjs");
const handler = await main({ preserve_branch_name: true, recreate_ref: true });
- const result = await handler({ title: "Test PR", body: "Test body", patch_path: patchFilePath, branch: "chaos/preserve-me", base_commit: MOCK_BASE_COMMIT_SHA }, {});
+ const result = await handler({ title: "Test PR", body: "Test body", branch: "chaos/preserve-me", base_commit: MOCK_BASE_COMMIT_SHA }, {});
expect(result.success).toBe(true);
// Should have attempted to delete the ref
@@ -2879,7 +2915,7 @@ describe("create_pull_request - patch apply fallback to original base commit", (
const { main } = require("./create_pull_request.cjs");
const handler = await main({});
- const result = await handler({ title: "Test PR", body: "Test body", patch_path: patchFilePath, branch: "some-branch", base_commit: MOCK_BASE_COMMIT_SHA }, {});
+ const result = await handler({ title: "Test PR", body: "Test body", branch: "some-branch", base_commit: MOCK_BASE_COMMIT_SHA }, {});
expect(result.success).toBe(true);
expect(renameCalled).toBe(true);
@@ -3158,7 +3194,7 @@ describe("create_pull_request - threat detection caution", () => {
it("should compose one REQUEST_CHANGES review when protected-files and threat warning are both active", async () => {
process.env.GH_AW_DETECTION_CONCLUSION = "warning";
process.env.GH_AW_DETECTION_REASON = "pattern-match";
- const patchPath = path.join(tempDir, "protected.patch");
+ const patchPath = canonicalPatchPath("should-compose-one-request-changes-review-when-protected-fil");
fs.writeFileSync(
patchPath,
`diff --git a/.github/aw/instructions.md b/.github/aw/instructions.md
@@ -3173,7 +3209,7 @@ index 0000000..abc1234
const { main } = require("./create_pull_request.cjs");
const handler = await main({ allow_empty: true, protected_path_prefixes: [".github/"], protected_files_policy: "request_review" });
- await handler({ title: "Test PR", body: "Agent body content", patch_path: patchPath }, {});
+ await handler({ title: "Test PR", body: "Agent body content", branch: "should-compose-one-request-changes-review-when-protected-fil" }, {});
expect(global.github.rest.pulls.createReview).toHaveBeenCalledTimes(1);
const createReviewCall = global.github.rest.pulls.createReview.mock.calls[0][0];
@@ -3633,12 +3669,12 @@ describe("create_pull_request - E003 file-limit fallback-to-issue", () => {
}
it("should create a fallback issue when E003 fires and fallback_as_issue is true (default)", async () => {
- const patchPath = path.join(tempDir, "aw-test.patch");
+ const patchPath = canonicalPatchPath("data/refresh");
fs.writeFileSync(patchPath, buildOversizedPatch(101));
const { main } = require("./create_pull_request.cjs");
const handler = await main({});
- const result = await handler({ title: "Data refresh PR", body: "Daily update", branch: "data/refresh", patch_path: patchPath }, {});
+ const result = await handler({ title: "Data refresh PR", body: "Daily update", branch: "data/refresh" }, {});
expect(result.success).toBe(true);
expect(result.fallback_used).toBe(true);
@@ -3661,12 +3697,12 @@ describe("create_pull_request - E003 file-limit fallback-to-issue", () => {
});
it("should use the actual received file count (not maxFiles*2) as the suggested limit", async () => {
- const patchPath = path.join(tempDir, "aw-test.patch");
+ const patchPath = canonicalPatchPath("api/regen");
fs.writeFileSync(patchPath, buildOversizedPatch(220));
const { main } = require("./create_pull_request.cjs");
const handler = await main({});
- const result = await handler({ title: "API regen PR", body: "Daily update", branch: "api/regen", patch_path: patchPath }, {});
+ const result = await handler({ title: "API regen PR", body: "Daily update", branch: "api/regen" }, {});
expect(result.success).toBe(true);
expect(result.fallback_used).toBe(true);
@@ -3678,12 +3714,12 @@ describe("create_pull_request - E003 file-limit fallback-to-issue", () => {
});
it("should sanitize and apply title prefix to fallback issue title", async () => {
- const patchPath = path.join(tempDir, "aw-test.patch");
+ const patchPath = canonicalPatchPath("data/refresh");
fs.writeFileSync(patchPath, buildOversizedPatch(101));
const { main } = require("./create_pull_request.cjs");
const handler = await main({ title_prefix: "[bot]" });
- const result = await handler({ title: "Data refresh PR", body: "Daily update", branch: "data/refresh", patch_path: patchPath }, {});
+ const result = await handler({ title: "Data refresh PR", body: "Daily update", branch: "data/refresh" }, {});
expect(result.success).toBe(true);
const issueCall = global.github.rest.issues.create.mock.calls[0][0];
@@ -3694,12 +3730,12 @@ describe("create_pull_request - E003 file-limit fallback-to-issue", () => {
it("should return staged preview instead of creating a fallback issue when in staged mode", async () => {
process.env.GH_AW_SAFE_OUTPUTS_STAGED = "true";
- const patchPath = path.join(tempDir, "aw-test.patch");
+ const patchPath = canonicalPatchPath("data/refresh");
fs.writeFileSync(patchPath, buildOversizedPatch(101));
const { main } = require("./create_pull_request.cjs");
const handler = await main({});
- const result = await handler({ title: "Data refresh PR", body: "Daily update", branch: "data/refresh", patch_path: patchPath }, {});
+ const result = await handler({ title: "Data refresh PR", body: "Daily update", branch: "data/refresh" }, {});
// Staged mode: no API side effects, just a preview
expect(result.success).toBe(true);
@@ -3711,12 +3747,12 @@ describe("create_pull_request - E003 file-limit fallback-to-issue", () => {
});
it("should return success: false when E003 fires and fallback_as_issue is false", async () => {
- const patchPath = path.join(tempDir, "aw-test.patch");
+ const patchPath = canonicalPatchPath("data/refresh");
fs.writeFileSync(patchPath, buildOversizedPatch(101));
const { main } = require("./create_pull_request.cjs");
const handler = await main({ fallback_as_issue: false });
- const result = await handler({ title: "Data refresh PR", body: "Daily update", branch: "data/refresh", patch_path: patchPath }, {});
+ const result = await handler({ title: "Data refresh PR", body: "Daily update", branch: "data/refresh" }, {});
expect(result.success).toBe(false);
expect(result.error).toContain("E003");
@@ -3726,12 +3762,12 @@ describe("create_pull_request - E003 file-limit fallback-to-issue", () => {
});
it("should pass when max_patch_files is raised above the file count", async () => {
- const patchPath = path.join(tempDir, "aw-test.patch");
+ const patchPath = canonicalPatchPath("data/refresh");
fs.writeFileSync(patchPath, buildOversizedPatch(150));
const { main } = require("./create_pull_request.cjs");
const handler = await main({ max_patch_files: 200 });
- const result = await handler({ title: "Data refresh PR", body: "Daily update", branch: "data/refresh", patch_path: patchPath }, {});
+ const result = await handler({ title: "Data refresh PR", body: "Daily update", branch: "data/refresh" }, {});
// Should succeed — limit was raised
expect(result.success).toBe(true);
diff --git a/actions/setup/js/find_repo_checkout.test.cjs b/actions/setup/js/find_repo_checkout.test.cjs
index 9c12f6a7b9e..8d97df99e56 100644
--- a/actions/setup/js/find_repo_checkout.test.cjs
+++ b/actions/setup/js/find_repo_checkout.test.cjs
@@ -1,7 +1,7 @@
const fs = require("fs");
const path = require("path");
const { extractRepoSlugFromUrl, normalizeRepoSlug, findGitDirectories, findRepoCheckout, buildRepoCheckoutMap } = require("./find_repo_checkout.cjs");
-const { getPatchPathForRepo, sanitizeBranchNameForPatch, sanitizeRepoSlugForPatch } = require("./generate_git_patch.cjs");
+const { getPatchPathForBranchInRepo, sanitizeBranchNameForPatch, sanitizeRepoSlugForPatch } = require("./generate_git_patch.cjs");
describe("find_repo_checkout", () => {
describe("extractRepoSlugFromUrl", () => {
@@ -212,29 +212,29 @@ describe("find_repo_checkout", () => {
});
describe("generate_git_patch multi-repo support", () => {
- describe("getPatchPathForRepo", () => {
+ describe("getPatchPathForBranchInRepo", () => {
it("should include repo slug in path", () => {
- const filePath = getPatchPathForRepo("feature-branch", "owner/repo");
+ const filePath = getPatchPathForBranchInRepo("feature-branch", "owner/repo");
expect(filePath).toBe("/tmp/gh-aw/aw-owner-repo-feature-branch.patch");
});
it("should sanitize repo slug", () => {
- const filePath = getPatchPathForRepo("main", "org/my-project");
+ const filePath = getPatchPathForBranchInRepo("main", "org/my-project");
expect(filePath).toBe("/tmp/gh-aw/aw-org-my-project-main.patch");
});
it("should sanitize branch name", () => {
- const filePath = getPatchPathForRepo("feature/add-login", "owner/repo");
+ const filePath = getPatchPathForBranchInRepo("feature/add-login", "owner/repo");
expect(filePath).toBe("/tmp/gh-aw/aw-owner-repo-feature-add-login.patch");
});
it("should handle complex repo names", () => {
- const filePath = getPatchPathForRepo("main", "github/gh-aw");
+ const filePath = getPatchPathForBranchInRepo("main", "github/gh-aw");
expect(filePath).toBe("/tmp/gh-aw/aw-github-gh-aw-main.patch");
});
it("should handle uppercase input", () => {
- const filePath = getPatchPathForRepo("Feature-Branch", "Owner/Repo");
+ const filePath = getPatchPathForBranchInRepo("Feature-Branch", "Owner/Repo");
expect(filePath).toBe("/tmp/gh-aw/aw-owner-repo-feature-branch.patch");
});
});
diff --git a/actions/setup/js/generate_git_bundle.cjs b/actions/setup/js/generate_git_bundle.cjs
index cca8c941b1c..b42c03b9dbc 100644
--- a/actions/setup/js/generate_git_bundle.cjs
+++ b/actions/setup/js/generate_git_bundle.cjs
@@ -54,7 +54,7 @@ function sanitizeBranchNameForBundle(branchName) {
* @param {string} branchName - The branch name
* @returns {string} The full bundle file path
*/
-function getBundlePath(branchName) {
+function getBundlePathForBranch(branchName) {
const sanitized = sanitizeBranchNameForBundle(branchName);
return `/tmp/gh-aw/aw-${sanitized}.bundle`;
}
@@ -75,7 +75,7 @@ function sanitizeRepoSlugForBundle(repoSlug) {
* @param {string} repoSlug - The repository slug (owner/repo)
* @returns {string} The full bundle file path including repo disambiguation
*/
-function getBundlePathForRepo(branchName, repoSlug) {
+function getBundlePathForBranchInRepo(branchName, repoSlug) {
const sanitizedBranch = sanitizeBranchNameForBundle(branchName);
const sanitizedRepo = sanitizeRepoSlugForBundle(repoSlug);
return `/tmp/gh-aw/aw-${sanitizedRepo}-${sanitizedBranch}.bundle`;
@@ -106,7 +106,7 @@ async function generateGitBundle(branchName, baseBranch, options = {}) {
// Support custom cwd for multi-repo scenarios
const cwd = options.cwd || process.env.GITHUB_WORKSPACE || process.cwd();
- const bundlePath = options.repoSlug ? getBundlePathForRepo(branchName, options.repoSlug) : getBundlePath(branchName);
+ const bundlePath = options.repoSlug ? getBundlePathForBranchInRepo(branchName, options.repoSlug) : getBundlePathForBranch(branchName);
// Validate baseBranch early to avoid confusing git errors (e.g., origin/undefined)
if (typeof baseBranch !== "string" || baseBranch.trim() === "") {
@@ -431,8 +431,8 @@ async function generateGitBundle(branchName, baseBranch, options = {}) {
module.exports = {
generateGitBundle,
- getBundlePath,
- getBundlePathForRepo,
+ getBundlePathForBranch,
+ getBundlePathForBranchInRepo,
sanitizeBranchNameForBundle,
sanitizeRepoSlugForBundle,
};
diff --git a/actions/setup/js/generate_git_patch.cjs b/actions/setup/js/generate_git_patch.cjs
index 167dc3e972d..f3458105009 100644
--- a/actions/setup/js/generate_git_patch.cjs
+++ b/actions/setup/js/generate_git_patch.cjs
@@ -12,7 +12,7 @@ const path = require("path");
const { getErrorMessage } = require("./error_helpers.cjs");
const { ensureOriginRemoteTrackingRef, execGitSync } = require("./git_helpers.cjs");
const { ERR_SYSTEM } = require("./error_codes.cjs");
-const { sanitizeForFilename, sanitizeBranchNameForPatch, sanitizeRepoSlugForPatch, getPatchPath, getPatchPathForRepo, buildExcludePathspecs, computeIncrementalDiffSize } = require("./git_patch_utils.cjs");
+const { sanitizeForFilename, sanitizeBranchNameForPatch, sanitizeRepoSlugForPatch, getPatchPathForBranch, getPatchPathForBranchInRepo, buildExcludePathspecs, computeIncrementalDiffSize } = require("./git_patch_utils.cjs");
// sanitizeForFilename is re-exported below for backward compatibility with
// existing callers that imported it from this module.
@@ -73,7 +73,7 @@ async function generateGitPatch(branchName, baseBranch, options = {}) {
function excludeArgs() {
return excludeArgsArr;
}
- const patchPath = options.repoSlug ? getPatchPathForRepo(branchName, options.repoSlug) : getPatchPath(branchName);
+ const patchPath = options.repoSlug ? getPatchPathForBranchInRepo(branchName, options.repoSlug) : getPatchPathForBranch(branchName);
if (options.workspacePath !== undefined && options.workspacePath !== null && String(options.workspacePath).trim() !== "") {
const root = path.resolve(workspaceRoot);
@@ -585,8 +585,8 @@ async function generateGitPatch(branchName, baseBranch, options = {}) {
module.exports = {
generateGitPatch,
- getPatchPath,
- getPatchPathForRepo,
+ getPatchPathForBranch,
+ getPatchPathForBranchInRepo,
sanitizeBranchNameForPatch,
sanitizeRepoSlugForPatch,
};
diff --git a/actions/setup/js/generate_git_patch.test.cjs b/actions/setup/js/generate_git_patch.test.cjs
index ff2f9d7eaf5..de9c62fe4f7 100644
--- a/actions/setup/js/generate_git_patch.test.cjs
+++ b/actions/setup/js/generate_git_patch.test.cjs
@@ -453,18 +453,18 @@ describe("generateGitPatch - standardized error codes", () => {
});
});
-describe("getPatchPath", () => {
+describe("getPatchPathForBranch", () => {
it("should return correct path format", async () => {
- const { getPatchPath } = await import("./generate_git_patch.cjs");
+ const { getPatchPathForBranch } = await import("./generate_git_patch.cjs");
- expect(getPatchPath("feature-branch")).toBe("/tmp/gh-aw/aw-feature-branch.patch");
+ expect(getPatchPathForBranch("feature-branch")).toBe("/tmp/gh-aw/aw-feature-branch.patch");
});
it("should sanitize branch name in path", async () => {
- const { getPatchPath } = await import("./generate_git_patch.cjs");
+ const { getPatchPathForBranch } = await import("./generate_git_patch.cjs");
- expect(getPatchPath("feature/branch")).toBe("/tmp/gh-aw/aw-feature-branch.patch");
- expect(getPatchPath("Feature/BRANCH")).toBe("/tmp/gh-aw/aw-feature-branch.patch");
+ expect(getPatchPathForBranch("feature/branch")).toBe("/tmp/gh-aw/aw-feature-branch.patch");
+ expect(getPatchPathForBranch("Feature/BRANCH")).toBe("/tmp/gh-aw/aw-feature-branch.patch");
});
});
diff --git a/actions/setup/js/git_patch_utils.cjs b/actions/setup/js/git_patch_utils.cjs
index b007c0fb1f5..162dbe90aa9 100644
--- a/actions/setup/js/git_patch_utils.cjs
+++ b/actions/setup/js/git_patch_utils.cjs
@@ -67,7 +67,7 @@ function sanitizeRepoSlugForPatch(repoSlug) {
* @param {string} branchName - The branch name
* @returns {string} The full patch file path
*/
-function getPatchPath(branchName) {
+function getPatchPathForBranch(branchName) {
const sanitized = sanitizeBranchNameForPatch(branchName);
return `/tmp/gh-aw/aw-${sanitized}.patch`;
}
@@ -79,7 +79,7 @@ function getPatchPath(branchName) {
* @param {string} repoSlug - The repository slug (owner/repo)
* @returns {string} The full patch file path including repo disambiguation
*/
-function getPatchPathForRepo(branchName, repoSlug) {
+function getPatchPathForBranchInRepo(branchName, repoSlug) {
const sanitizedBranch = sanitizeBranchNameForPatch(branchName);
const sanitizedRepo = sanitizeRepoSlugForPatch(repoSlug);
return `/tmp/gh-aw/aw-${sanitizedRepo}-${sanitizedBranch}.patch`;
@@ -155,8 +155,8 @@ module.exports = {
sanitizeForFilename,
sanitizeBranchNameForPatch,
sanitizeRepoSlugForPatch,
- getPatchPath,
- getPatchPathForRepo,
+ getPatchPathForBranch,
+ getPatchPathForBranchInRepo,
buildExcludePathspecs,
computeIncrementalDiffSize,
};
diff --git a/actions/setup/js/git_patch_utils.test.cjs b/actions/setup/js/git_patch_utils.test.cjs
index 2f859815872..52f5fe247a8 100644
--- a/actions/setup/js/git_patch_utils.test.cjs
+++ b/actions/setup/js/git_patch_utils.test.cjs
@@ -15,7 +15,7 @@ import os from "os";
import path from "path";
import { spawnSync } from "child_process";
-import { sanitizeForFilename, sanitizeBranchNameForPatch, sanitizeRepoSlugForPatch, getPatchPath, getPatchPathForRepo, buildExcludePathspecs, computeIncrementalDiffSize } from "./git_patch_utils.cjs";
+import { sanitizeForFilename, sanitizeBranchNameForPatch, sanitizeRepoSlugForPatch, getPatchPathForBranch, getPatchPathForBranchInRepo, buildExcludePathspecs, computeIncrementalDiffSize } from "./git_patch_utils.cjs";
// computeIncrementalDiffSize delegates to execGitSync from git_helpers.cjs,
// which calls the GitHub Actions `core.debug` / `core.error` globals. Stub
@@ -89,12 +89,12 @@ describe("git_patch_utils - pure helpers", () => {
});
});
- describe("getPatchPath / getPatchPathForRepo", () => {
+ describe("getPatchPathForBranch / getPatchPathForBranchInRepo", () => {
it("returns the /tmp/gh-aw path with the sanitized branch name", () => {
- expect(getPatchPath("feat/foo")).toBe("/tmp/gh-aw/aw-feat-foo.patch");
+ expect(getPatchPathForBranch("feat/foo")).toBe("/tmp/gh-aw/aw-feat-foo.patch");
});
it("includes a sanitized repo slug for multi-repo scenarios", () => {
- expect(getPatchPathForRepo("feat/foo", "github/gh-aw")).toBe("/tmp/gh-aw/aw-github-gh-aw-feat-foo.patch");
+ expect(getPatchPathForBranchInRepo("feat/foo", "github/gh-aw")).toBe("/tmp/gh-aw/aw-github-gh-aw-feat-foo.patch");
});
});
diff --git a/actions/setup/js/handle_agent_failure.test.cjs b/actions/setup/js/handle_agent_failure.test.cjs
index e868dac7835..3f63050d891 100644
--- a/actions/setup/js/handle_agent_failure.test.cjs
+++ b/actions/setup/js/handle_agent_failure.test.cjs
@@ -2908,7 +2908,7 @@ describe("handle_agent_failure", () => {
"Why this happened and how to optimize\n\n" +
"- Learn about [effective tokens]({et_spec_link}).\n" +
"{usage_line}{budget_line}{run_line}\n" +
- "You can tune this limit with `max-effective-tokens` in workflow frontmatter.\n\n" +
+ "You can tune this limit with `max-ai-credits` in workflow frontmatter.\n\n" +
"{et_table_section}\n" +
"- To optimize this workflow, follow the [token optimization instructions]({token_opt_link}).\n" +
"\n"
diff --git a/actions/setup/js/permission_denied_helpers.cjs b/actions/setup/js/permission_denied_helpers.cjs
index 8ffbf12e08e..fbdd02c9194 100644
--- a/actions/setup/js/permission_denied_helpers.cjs
+++ b/actions/setup/js/permission_denied_helpers.cjs
@@ -38,10 +38,7 @@ function extractDeniedCommands(output) {
if (!output) return [];
const lines = output.split("\n");
const deniedCommands = new Set();
- const permissionSummaryPatterns = [
- /permission denied by workflow tool permissions:\s*(.+?)\s*$/i,
- /tool denial \d+\/\d+:\s*permission denied:\s*(.+?)\s*$/i,
- ];
+ const permissionSummaryPatterns = [/permission denied by workflow tool permissions:\s*(.+?)\s*$/i, /tool denial \d+\/\d+:\s*permission denied:\s*(.+?)\s*$/i];
for (let i = 0; i < lines.length; i++) {
let capturedFromLine = false;
for (const pattern of permissionSummaryPatterns) {
diff --git a/actions/setup/js/push_to_pull_request_branch.cjs b/actions/setup/js/push_to_pull_request_branch.cjs
index 85e91339e32..1ac61054a65 100644
--- a/actions/setup/js/push_to_pull_request_branch.cjs
+++ b/actions/setup/js/push_to_pull_request_branch.cjs
@@ -22,6 +22,7 @@ const { normalizeCommitSHA } = require("./commit_sha_helpers.cjs");
const { findRepoCheckout } = require("./find_repo_checkout.cjs");
const { getThreatDetectedMarker } = require("./threat_detection_warning.cjs");
const { attachExecutionState } = require("./safe_output_execution_metadata.cjs");
+const { resolveTransportPaths } = require("./resolve_transport_paths.cjs");
/**
* @typedef {import('./types/handler-factory').HandlerFactoryFunction} HandlerFactoryFunction
@@ -183,12 +184,15 @@ async function main(config = {}) {
processedCount++;
- // Determine the patch file path from the message (set by the MCP server handler)
- const patchFilePath = message.patch_path;
+ // Determine the patch and bundle file paths. The MCP server sets these on
+ // the entry it writes, but the validation step strips them as a defense
+ // against agent-forged values. Recover them by re-deriving from `branch`.
+ const transportPaths = resolveTransportPaths(message, defaultTargetRepo);
+ const patchFilePath = transportPaths.patchPath;
core.info(`Patch file path: ${patchFilePath || "(not set)"}`);
// Determine the bundle file path from the message (set when patch-format: bundle is configured)
- const bundleFilePath = message.bundle_path;
+ const bundleFilePath = transportPaths.bundlePath;
if (bundleFilePath) {
core.info(`Bundle file path: ${bundleFilePath}`);
}
diff --git a/actions/setup/js/push_to_pull_request_branch.test.cjs b/actions/setup/js/push_to_pull_request_branch.test.cjs
index 08a53eb2d8a..829a041114e 100644
--- a/actions/setup/js/push_to_pull_request_branch.test.cjs
+++ b/actions/setup/js/push_to_pull_request_branch.test.cjs
@@ -3,6 +3,37 @@ import * as fs from "fs";
import * as path from "path";
import * as os from "os";
+const { getPatchPathForBranch, getPatchPathForBranchInRepo } = require("./git_patch_utils.cjs");
+const { getBundlePathForBranch, getBundlePathForBranchInRepo } = require("./generate_git_bundle.cjs");
+
+// The privileged handler derives patch/bundle paths from `branch` (and `repo`)
+// via resolveTransportPaths, so tests must write transport files at the
+// canonical derived location and let the handler discover them.
+function canonicalPatchPath(branch, repo) {
+ fs.mkdirSync("/tmp/gh-aw", { recursive: true });
+ return repo ? getPatchPathForBranchInRepo(branch, repo) : getPatchPathForBranch(branch);
+}
+function canonicalBundlePath(branch, repo) {
+ fs.mkdirSync("/tmp/gh-aw", { recursive: true });
+ return repo ? getBundlePathForBranchInRepo(branch, repo) : getBundlePathForBranch(branch);
+}
+function cleanupCanonicalTransports() {
+ try {
+ for (const f of fs.readdirSync("/tmp/gh-aw")) {
+ if (/^aw-.*\.(patch|bundle)$/.test(f)) {
+ fs.rmSync(`/tmp/gh-aw/${f}`, { force: true });
+ }
+ }
+ } catch {}
+}
+
+beforeEach(() => {
+ cleanupCanonicalTransports();
+});
+afterEach(() => {
+ cleanupCanonicalTransports();
+});
+
/**
* Test Matrix for push_to_pull_request_branch.cjs
*
@@ -214,10 +245,12 @@ describe("push_to_pull_request_branch.cjs", () => {
}
/**
- * Helper to create a valid patch file
+ * Helper to create a valid patch file at the canonical path derived from the
+ * message branch. The privileged handler always re-derives the patch path
+ * from the validated branch, so tests must write at that canonical location.
*/
- function createPatchFile(content = null) {
- const patchPath = path.join(tempDir, "test.patch");
+ function createPatchFile(branch, content = null) {
+ const patchPath = canonicalPatchPath(branch);
const defaultPatch = `From abc123 Mon Sep 17 00:00:00 2001
From: Test Author
Date: Mon, 1 Jan 2024 00:00:00 +0000
@@ -329,14 +362,14 @@ index 0000000..abc1234
describe("GitHub Actions context scenarios", () => {
it('should handle pull_request event with target "triggering"', async () => {
mockContext.eventName = "pull_request";
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("should-handle-pull-request-event-with-target-triggering");
// Mock git commands
mockExec.getExecOutput.mockResolvedValue({ exitCode: 0, stdout: "abc123\n", stderr: "" });
const module = await loadModule();
const handler = await module.main({ target: "triggering" });
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-handle-pull-request-event-with-target-triggering" }, {});
expect(result.success).toBe(true);
expect(mockGithub.rest.pulls.get).toHaveBeenCalledWith({
@@ -349,13 +382,13 @@ index 0000000..abc1234
it("should handle issue_comment event (comment on PR)", async () => {
mockContext.eventName = "issue_comment";
mockContext.payload.issue = { number: 123 };
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("should-handle-issue-comment-event-comment-on-pr");
mockExec.getExecOutput.mockResolvedValue({ exitCode: 0, stdout: "abc123\n", stderr: "" });
const module = await loadModule();
const handler = await module.main({ target: "triggering" });
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-handle-issue-comment-event-comment-on-pr" }, {});
expect(result.success).toBe(true);
});
@@ -365,11 +398,11 @@ index 0000000..abc1234
delete mockContext.payload.pull_request;
delete mockContext.payload.issue;
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("should-fail-for-schedule-event-with-target-triggering");
const module = await loadModule();
const handler = await module.main({ target: "triggering" });
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-fail-for-schedule-event-with-target-triggering" }, {});
expect(result.success).toBe(false);
expect(result.error).toContain("pull request context");
@@ -378,11 +411,11 @@ index 0000000..abc1234
it('should fail gracefully with target "triggering" when context is undefined (MCP daemon mode)', async () => {
delete global.context;
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("should-fail-gracefully-with-target-triggering-when-context-i");
const module = await loadModule();
const handler = await module.main({ target: "triggering" });
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-fail-gracefully-with-target-triggering-when-context-i" }, {});
expect(result.success).toBe(false);
expect(result.error).toContain("pull request context");
@@ -391,13 +424,13 @@ index 0000000..abc1234
it('should handle schedule event with target "*" and explicit PR number', async () => {
mockContext.eventName = "schedule";
delete mockContext.payload.pull_request;
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("should-handle-schedule-event-with-target-and-explicit-pr-num");
mockExec.getExecOutput.mockResolvedValue({ exitCode: 0, stdout: "abc123\n", stderr: "" });
const module = await loadModule();
const handler = await module.main({ target: "*" });
- const result = await handler({ patch_path: patchPath, pull_request_number: 456 }, {});
+ const result = await handler({ pull_request_number: 456, branch: "should-handle-schedule-event-with-target-and-explicit-pr-num" }, {});
expect(result.success).toBe(true);
expect(mockGithub.rest.pulls.get).toHaveBeenCalledWith({
@@ -410,13 +443,13 @@ index 0000000..abc1234
it("should handle workflow_dispatch event with explicit PR number", async () => {
mockContext.eventName = "workflow_dispatch";
delete mockContext.payload.pull_request;
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("should-handle-workflow-dispatch-event-with-explicit-pr-numbe");
mockExec.getExecOutput.mockResolvedValue({ exitCode: 0, stdout: "abc123\n", stderr: "" });
const module = await loadModule();
const handler = await module.main({ target: "789" });
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-handle-workflow-dispatch-event-with-explicit-pr-numbe" }, {});
expect(result.success).toBe(true);
expect(mockGithub.rest.pulls.get).toHaveBeenCalledWith({
@@ -436,13 +469,13 @@ index 0000000..abc1234
item_number: "456",
}),
};
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("should-resolve-target-triggering-from-workflow-dispatch-aw-c");
mockExec.getExecOutput.mockResolvedValue({ exitCode: 0, stdout: "abc123\n", stderr: "" });
const module = await loadModule();
const handler = await module.main({ target: "triggering" });
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-resolve-target-triggering-from-workflow-dispatch-aw-c" }, {});
expect(result.success).toBe(true);
expect(mockGithub.rest.pulls.get).toHaveBeenCalledWith({
@@ -462,11 +495,11 @@ index 0000000..abc1234
item_number: "0",
}),
};
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("should-fail-when-workflow-dispatch-aw-context-item-number-is");
const module = await loadModule();
const handler = await module.main({ target: "triggering" });
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-fail-when-workflow-dispatch-aw-context-item-number-is" }, {});
expect(result.success).toBe(false);
expect(result.error).toContain("pull request context");
@@ -502,11 +535,11 @@ index 0000000..abc1234
},
});
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("should-detect-fork-pr-via-different-repository-names-and-fai");
const module = await loadModule();
const handler = await module.main({ target: "triggering" });
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-detect-fork-pr-via-different-repository-names-and-fai" }, {});
// Fork PRs should fail early with a clear error
expect(result.success).toBe(false);
@@ -540,11 +573,11 @@ index 0000000..abc1234
},
});
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("should-not-treat-same-repo-pr-as-fork-even-when-repo-has-for");
const module = await loadModule();
const handler = await module.main({ target: "triggering" });
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-not-treat-same-repo-pr-as-fork-even-when-repo-has-for" }, {});
// Same full_name means same repo — push should proceed, not fail
expect(result.success).toBe(true);
@@ -569,11 +602,11 @@ index 0000000..abc1234
},
});
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("should-handle-deleted-head-repo-likely-a-fork-and-fail-early");
const module = await loadModule();
const handler = await module.main({ target: "triggering" });
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-handle-deleted-head-repo-likely-a-fork-and-fail-early" }, {});
// When head.repo is null, this is likely a deleted fork
// The handler should give a clear error about the fork
@@ -603,10 +636,10 @@ index 0000000..abc1234
});
mockGithub.rest.repos.get.mockResolvedValue({ data: { default_branch: "main" } });
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("main");
const module = await loadModule();
const handler = await module.main({ target: "triggering" });
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "main" }, {});
expect(result.success).toBe(false);
expect(result.error).toContain("default branch");
@@ -619,10 +652,10 @@ index 0000000..abc1234
// Branch has protection rules - getBranchProtection resolves successfully
mockGithub.rest.repos.getBranchProtection.mockResolvedValue({ data: {} });
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("should-block-push-to-a-branch-with-protection-rules");
const module = await loadModule();
const handler = await module.main({ target: "triggering" });
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-block-push-to-a-branch-with-protection-rules" }, {});
expect(result.success).toBe(false);
expect(result.error).toContain("protection rules");
@@ -634,12 +667,12 @@ index 0000000..abc1234
it("should allow push when branch is not default and has no protection rules", async () => {
// Default mock: repos.get returns "main", getBranchProtection returns 404
// PR head is "feature-branch" (not the default)
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("should-allow-push-when-branch-is-not-default-and-has-no-prot");
mockExec.getExecOutput.mockResolvedValue({ exitCode: 0, stdout: "abc123\n", stderr: "" });
const module = await loadModule();
const handler = await module.main({});
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-allow-push-when-branch-is-not-default-and-has-no-prot" }, {});
expect(result.success).toBe(true);
expect(result.branch_name).toBe("feature-branch");
@@ -648,12 +681,12 @@ index 0000000..abc1234
it("should warn and continue when repos.get fails", async () => {
// repos.get fails - cannot determine default branch, warn and continue
mockGithub.rest.repos.get.mockRejectedValue(new Error("API unavailable"));
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("should-warn-and-continue-when-repos-get-fails");
mockExec.getExecOutput.mockResolvedValue({ exitCode: 0, stdout: "abc123\n", stderr: "" });
const module = await loadModule();
const handler = await module.main({});
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-warn-and-continue-when-repos-get-fails" }, {});
// Should warn but still allow the push since we can't confirm it's the default branch
expect(mockCore.warning).toHaveBeenCalledWith(expect.stringContaining("Could not check repository default branch"));
@@ -664,12 +697,12 @@ index 0000000..abc1234
// getBranchProtection returns 403 (no permission to read protection)
// Platform will still enforce protection at push time, so we warn and allow
mockGithub.rest.repos.getBranchProtection.mockRejectedValue(Object.assign(new Error("Forbidden"), { status: 403 }));
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("should-warn-and-continue-when-getbranchprotection-returns-40");
mockExec.getExecOutput.mockResolvedValue({ exitCode: 0, stdout: "abc123\n", stderr: "" });
const module = await loadModule();
const handler = await module.main({});
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-warn-and-continue-when-getbranchprotection-returns-40" }, {});
// Should warn but allow push since the platform still enforces protection at push time
expect(mockCore.warning).toHaveBeenCalledWith(expect.stringContaining("Could not check branch protection rules"));
@@ -679,11 +712,11 @@ index 0000000..abc1234
it("should block push when getBranchProtection returns an unexpected error (fail closed)", async () => {
// getBranchProtection returns 500 - unexpected error, fail closed for security
mockGithub.rest.repos.getBranchProtection.mockRejectedValue(Object.assign(new Error("Internal Server Error"), { status: 500 }));
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("should-block-push-when-getbranchprotection-returns-an-unexpe");
const module = await loadModule();
const handler = await module.main({});
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-block-push-when-getbranchprotection-returns-an-unexpe" }, {});
// Should block the push when branch protection status cannot be verified
expect(result.success).toBe(false);
@@ -700,7 +733,7 @@ index 0000000..abc1234
describe("repository state scenarios", () => {
it("should handle successful normal push", async () => {
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("should-handle-successful-normal-push");
mockExec.getExecOutput
.mockResolvedValueOnce({ exitCode: 0, stdout: "preflight-sha\trefs/heads/feature-branch\n", stderr: "" })
.mockResolvedValueOnce({ exitCode: 0, stdout: "remote-head-before\n", stderr: "" })
@@ -709,7 +742,7 @@ index 0000000..abc1234
const module = await loadModule();
const handler = await module.main({});
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-handle-successful-normal-push" }, {});
expect(result.success).toBe(true);
expect(result.branch_name).toBe("feature-branch");
@@ -719,7 +752,7 @@ index 0000000..abc1234
});
it("should reset to message.base_commit before applying patch transport", async () => {
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("should-reset-to-message-base-commit-before-applying-patch-tr");
const recordedBaseCommit = "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef";
mockExec.getExecOutput.mockResolvedValue({ exitCode: 0, stdout: "abc123\n", stderr: "" });
const pushSignedCommitsModule = require("./push_signed_commits.cjs");
@@ -728,7 +761,7 @@ index 0000000..abc1234
try {
const module = await loadModule();
const handler = await module.main({});
- const result = await handler({ patch_path: patchPath, base_commit: recordedBaseCommit }, {});
+ const result = await handler({ base_commit: recordedBaseCommit, branch: "should-reset-to-message-base-commit-before-applying-patch-tr" }, {});
expect(result.success).toBe(true);
expect(mockExec.exec).toHaveBeenCalledWith("git", ["cat-file", "-e", recordedBaseCommit], expect.any(Object));
@@ -740,7 +773,7 @@ index 0000000..abc1234
});
it("should fall back to current HEAD when base_commit is unavailable for patch transport", async () => {
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("should-fall-back-to-current-head-when-base-commit-is-unavail");
const recordedBaseCommit = "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef";
mockExec.getExecOutput.mockResolvedValue({ exitCode: 0, stdout: "abc123\n", stderr: "" });
mockExec.exec.mockImplementation(async (cmd, args) => {
@@ -756,7 +789,7 @@ index 0000000..abc1234
try {
const module = await loadModule();
const handler = await module.main({});
- const result = await handler({ patch_path: patchPath, base_commit: recordedBaseCommit }, {});
+ const result = await handler({ base_commit: recordedBaseCommit, branch: "should-fall-back-to-current-head-when-base-commit-is-unavail" }, {});
expect(result.success).toBe(true);
expect(mockExec.exec).not.toHaveBeenCalledWith("git", ["reset", "--hard", recordedBaseCommit], expect.any(Object));
@@ -767,12 +800,12 @@ index 0000000..abc1234
});
it("should ignore invalid message.base_commit for patch transport", async () => {
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("should-ignore-invalid-message-base-commit-for-patch-transpor");
mockExec.getExecOutput.mockResolvedValue({ exitCode: 0, stdout: "abc123\n", stderr: "" });
const module = await loadModule();
const handler = await module.main({});
- const result = await handler({ patch_path: patchPath, base_commit: "not-a-sha --bad" }, {});
+ const result = await handler({ base_commit: "not-a-sha --bad", branch: "should-ignore-invalid-message-base-commit-for-patch-transpor" }, {});
expect(result.success).toBe(true);
expect(mockExec.exec).not.toHaveBeenCalledWith("git", ["cat-file", "-e", "not-a-sha --bad"], expect.any(Object));
@@ -781,7 +814,7 @@ index 0000000..abc1234
});
it("should use pushed commit SHA returned by pushSignedCommits for activation comment commit link", async () => {
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("should-use-pushed-commit-sha-returned-by-pushsignedcommits-f");
const updateActivationCommentModule = require("./update_activation_comment.cjs");
const updateCommitSpy = vi.spyOn(updateActivationCommentModule, "updateActivationCommentWithCommit").mockResolvedValue(undefined);
const pushSignedCommitsModule = require("./push_signed_commits.cjs");
@@ -798,7 +831,7 @@ index 0000000..abc1234
const module = await loadModule();
const handler = await module.main({});
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-use-pushed-commit-sha-returned-by-pushsignedcommits-f" }, {});
expect(result.success).toBe(true);
expect(result.commit_sha).toBe("remote-head-after");
@@ -815,7 +848,7 @@ index 0000000..abc1234
});
it("should skip activation comment for empty commits (no file changes)", async () => {
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("should-skip-activation-comment-for-empty-commits-no-file-cha");
const updateActivationCommentModule = require("./update_activation_comment.cjs");
const updateCommitSpy = vi.spyOn(updateActivationCommentModule, "updateActivationCommentWithCommit").mockResolvedValue(undefined);
const pushSignedCommitsModule = require("./push_signed_commits.cjs");
@@ -831,7 +864,7 @@ index 0000000..abc1234
const module = await loadModule();
const handler = await module.main({});
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-skip-activation-comment-for-empty-commits-no-file-cha" }, {});
expect(result.success).toBe(true);
expect(result.commit_sha).toBe("remote-head-after");
@@ -844,13 +877,13 @@ index 0000000..abc1234
});
it("should detect deleted branch before fetch", async () => {
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("should-detect-deleted-branch-before-fetch");
mockExec.getExecOutput.mockResolvedValueOnce({ exitCode: 2, stdout: "", stderr: "fatal: couldn't find remote ref feature-branch" });
const module = await loadModule();
const handler = await module.main({});
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-detect-deleted-branch-before-fetch" }, {});
expect(result.success).toBe(false);
expect(result.error).toContain("no longer exists on origin");
@@ -858,13 +891,13 @@ index 0000000..abc1234
});
it("should skip deleted branch failure when ignore_missing_branch_failure is enabled", async () => {
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("should-skip-deleted-branch-failure-when-ignore-missing-branc");
mockExec.getExecOutput.mockResolvedValueOnce({ exitCode: 2, stdout: "", stderr: "fatal: couldn't find remote ref feature-branch" });
const module = await loadModule();
const handler = await module.main({ ignore_missing_branch_failure: true });
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-skip-deleted-branch-failure-when-ignore-missing-branc" }, {});
expect(result.success).toBe(false);
expect(result.skipped).toBe(true);
@@ -874,13 +907,13 @@ index 0000000..abc1234
});
it("should fail with diagnostic error when branch existence check fails for other reasons", async () => {
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("should-fail-with-diagnostic-error-when-branch-existence-chec");
mockExec.getExecOutput.mockResolvedValueOnce({ exitCode: 128, stdout: "", stderr: "fatal: Authentication failed" });
const module = await loadModule();
const handler = await module.main({});
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-fail-with-diagnostic-error-when-branch-existence-chec" }, {});
expect(result.success).toBe(false);
expect(result.error).toContain("Failed to verify branch");
@@ -889,21 +922,21 @@ index 0000000..abc1234
});
it("should handle git fetch failure", async () => {
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("should-handle-git-fetch-failure");
// First exec call (git fetch) fails
mockExec.exec.mockRejectedValueOnce(new Error("Failed to fetch: network error"));
const module = await loadModule();
const handler = await module.main({});
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-handle-git-fetch-failure" }, {});
expect(result.success).toBe(false);
expect(result.error).toContain("Failed to fetch branch");
});
it("should handle branch not existing on origin", async () => {
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("should-handle-branch-not-existing-on-origin");
// git fetch succeeds, but git rev-parse fails
mockExec.exec.mockResolvedValueOnce(0); // fetch
@@ -911,14 +944,14 @@ index 0000000..abc1234
const module = await loadModule();
const handler = await module.main({});
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-handle-branch-not-existing-on-origin" }, {});
expect(result.success).toBe(false);
expect(result.error).toContain("does not exist on origin");
});
it("should skip rev-parse missing branch failure when ignore_missing_branch_failure is enabled", async () => {
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("should-skip-rev-parse-missing-branch-failure-when-ignore-mis");
// git fetch succeeds, but git rev-parse fails
mockExec.exec.mockResolvedValueOnce(0); // fetch
@@ -926,7 +959,7 @@ index 0000000..abc1234
const module = await loadModule();
const handler = await module.main({ ignore_missing_branch_failure: true });
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-skip-rev-parse-missing-branch-failure-when-ignore-mis" }, {});
expect(result.success).toBe(false);
expect(result.skipped).toBe(true);
@@ -935,7 +968,7 @@ index 0000000..abc1234
});
it("should handle git checkout failure", async () => {
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("should-handle-git-checkout-failure");
mockExec.exec.mockResolvedValueOnce(0); // fetch
mockExec.exec.mockResolvedValueOnce(0); // rev-parse
@@ -943,14 +976,14 @@ index 0000000..abc1234
const module = await loadModule();
const handler = await module.main({});
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-handle-git-checkout-failure" }, {});
expect(result.success).toBe(false);
expect(result.error).toContain("Failed to checkout branch");
});
it("should handle git am (patch apply) failure with investigation", async () => {
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("should-handle-git-am-patch-apply-failure-with-investigation");
// Set up successful fetch, rev-parse, checkout
mockExec.exec.mockResolvedValueOnce(0); // fetch
@@ -975,7 +1008,7 @@ index 0000000..abc1234
const module = await loadModule();
const handler = await module.main({});
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-handle-git-am-patch-apply-failure-with-investigation" }, {});
expect(result.success).toBe(false);
expect(result.error).toContain("Failed to apply patch");
@@ -983,7 +1016,7 @@ index 0000000..abc1234
});
it("should resolve add/add conflicts by preferring patch version and continuing git am", async () => {
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("should-resolve-add-add-conflicts-by-preferring-patch-version");
const pushSignedCommitsModule = require("./push_signed_commits.cjs");
const pushSignedSpy = vi.spyOn(pushSignedCommitsModule, "pushSignedCommits").mockResolvedValue("pushed-sha");
@@ -1024,7 +1057,7 @@ index 0000000..abc1234
const module = await loadModule();
const handler = await module.main({});
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-resolve-add-add-conflicts-by-preferring-patch-version" }, {});
expect(result.success).toBe(true);
expect(mockCore.info).toHaveBeenCalledWith("Patch applied successfully after resolving add/add conflict(s)");
@@ -1037,7 +1070,7 @@ index 0000000..abc1234
});
it("should create fallback pull request on non-fast-forward push rejection by default", async () => {
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("should-create-fallback-pull-request-on-non-fast-forward-push");
// Set up successful operations until push
mockExec.exec.mockResolvedValueOnce(0); // fetch
@@ -1084,7 +1117,7 @@ index 0000000..abc1234
const module = await loadModule();
const handler = await module.main({});
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-create-fallback-pull-request-on-non-fast-forward-push" }, {});
expect(result.success).toBe(true);
expect(result.fallback_used).toBe(true);
@@ -1094,7 +1127,7 @@ index 0000000..abc1234
});
it("should not create fallback pull request when fallback-as-pull-request is disabled", async () => {
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("should-not-create-fallback-pull-request-when-fallback-as-pul");
mockExec.exec.mockResolvedValueOnce(0); // fetch
mockExec.exec.mockResolvedValueOnce(0); // rev-parse
@@ -1137,7 +1170,7 @@ index 0000000..abc1234
const module = await loadModule();
const handler = await module.main({ fallback_as_pull_request: false });
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-not-create-fallback-pull-request-when-fallback-as-pul" }, {});
expect(result.success).toBe(false);
expect(result.error_type).toBe("push_failed");
@@ -1146,7 +1179,7 @@ index 0000000..abc1234
});
it("should diagnose deleted branch when push fails", async () => {
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("should-diagnose-deleted-branch-when-push-fails");
// Set up successful operations until push
mockExec.exec.mockResolvedValueOnce(0); // fetch
@@ -1199,7 +1232,7 @@ index 0000000..abc1234
const module = await loadModule();
const handler = await module.main({});
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-diagnose-deleted-branch-when-push-fails" }, {});
expect(result.success).toBe(false);
expect(result.error_type).toBe("push_failed");
@@ -1207,7 +1240,7 @@ index 0000000..abc1234
});
it("should detect force-pushed branch via ref mismatch", async () => {
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("should-detect-force-pushed-branch-via-ref-mismatch");
// This tests the scenario where the branch SHA we have doesn't match remote
// The current implementation doesn't explicitly detect this, but git operations would fail
@@ -1235,7 +1268,7 @@ index 0000000..abc1234
const module = await loadModule();
const handler = await module.main({});
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-detect-force-pushed-branch-via-ref-mismatch" }, {});
// The push proceeds - force-push detection would need to be added
expect(mockGithub.rest.pulls.get).toHaveBeenCalled();
@@ -1248,11 +1281,11 @@ index 0000000..abc1234
describe("empty commit / no changes handling", () => {
it("should warn when patch is empty and if-no-changes is warn", async () => {
- const patchPath = createPatchFile(""); // Empty patch
+ const patchPath = createPatchFile("should-warn-when-patch-is-empty-and-if-no-changes-is-warn", ""); // Empty patch
const module = await loadModule();
const handler = await module.main({ if_no_changes: "warn" });
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-warn-when-patch-is-empty-and-if-no-changes-is-warn" }, {});
expect(result.success).toBe(false);
expect(result.skipped).toBe(true);
@@ -1260,22 +1293,22 @@ index 0000000..abc1234
});
it("should error when patch is empty and if-no-changes is error", async () => {
- const patchPath = createPatchFile(""); // Empty patch
+ const patchPath = createPatchFile("should-error-when-patch-is-empty-and-if-no-changes-is-error", ""); // Empty patch
const module = await loadModule();
const handler = await module.main({ if_no_changes: "error" });
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-error-when-patch-is-empty-and-if-no-changes-is-error" }, {});
expect(result.success).toBe(false);
expect(result.error).toContain("No changes");
});
it("should silently skip when patch is empty and if-no-changes is ignore", async () => {
- const patchPath = createPatchFile(""); // Empty patch
+ const patchPath = createPatchFile("should-silently-skip-when-patch-is-empty-and-if-no-changes-i", ""); // Empty patch
const module = await loadModule();
const handler = await module.main({ if_no_changes: "ignore" });
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-silently-skip-when-patch-is-empty-and-if-no-changes-i" }, {});
expect(result.success).toBe(false);
expect(result.skipped).toBe(true);
@@ -1284,18 +1317,18 @@ index 0000000..abc1234
it("should handle missing patch file", async () => {
const module = await loadModule();
const handler = await module.main({});
- const result = await handler({ patch_path: "/nonexistent/path.patch" }, {});
+ const result = await handler({ branch: "should-handle-missing-patch-file" }, {});
expect(result.success).toBe(false);
expect(result.error).toContain("No patch file");
});
it("should handle patch file with error message", async () => {
- const patchPath = createPatchFile("Failed to generate patch: some error");
+ const patchPath = createPatchFile("should-handle-patch-file-with-error-message", "Failed to generate patch: some error");
const module = await loadModule();
const handler = await module.main({});
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-handle-patch-file-with-error-message" }, {});
expect(result.success).toBe(false);
expect(result.error).toContain("error message");
@@ -1310,24 +1343,24 @@ index 0000000..abc1234
it("should reject patches exceeding max size", async () => {
// Create a patch larger than 1KB
const largePatch = "x".repeat(2 * 1024 * 1024); // 2MB
- const patchPath = createPatchFile(largePatch);
+ const patchPath = createPatchFile("should-reject-patches-exceeding-max-size", largePatch);
const module = await loadModule();
const handler = await module.main({ max_patch_size: 1024 }); // 1MB max
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-reject-patches-exceeding-max-size" }, {});
expect(result.success).toBe(false);
expect(result.error).toContain("exceeds maximum");
});
it("should accept patches within max size", async () => {
- const patchPath = createPatchFile(); // Small valid patch
+ const patchPath = createPatchFile("should-accept-patches-within-max-size"); // Small valid patch
mockExec.getExecOutput.mockResolvedValue({ exitCode: 0, stdout: "abc123\n", stderr: "" });
const module = await loadModule();
const handler = await module.main({ max_patch_size: 1024 });
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-accept-patches-within-max-size" }, {});
expect(result.success).toBe(true);
expect(mockCore.info).toHaveBeenCalledWith("Patch size validation passed");
@@ -1339,13 +1372,13 @@ index 0000000..abc1234
// tiny incremental net diff (e.g. 5 KB of actual changes since
// origin/). The size check must use diff_size and accept the push.
const largePatch = "x".repeat(2 * 1024 * 1024); // 2 MB format-patch file
- const patchPath = createPatchFile(largePatch);
+ const patchPath = createPatchFile("should-prefer-message-diff-size-incremental-net-diff-over-pa", largePatch);
mockExec.getExecOutput.mockResolvedValue({ exitCode: 0, stdout: "abc123\n", stderr: "" });
const module = await loadModule();
const handler = await module.main({ max_patch_size: 1024 }); // 1 MB max
- const result = await handler({ patch_path: patchPath, diff_size: 5 * 1024 }, {});
+ const result = await handler({ diff_size: 5 * 1024, branch: "should-prefer-message-diff-size-incremental-net-diff-over-pa" }, {});
expect(result.success).toBe(true);
expect(mockCore.info).toHaveBeenCalledWith("Patch size validation passed");
@@ -1358,11 +1391,11 @@ index 0000000..abc1234
// Inverse case: small file (defensive — shouldn't happen in practice)
// but a recorded large diff_size should still cause rejection. This
// proves diff_size is the source of truth for the size check.
- const patchPath = createPatchFile(); // small valid patch
+ const patchPath = createPatchFile("should-reject-when-message-diff-size-exceeds-max-size-even-i"); // small valid patch
const module = await loadModule();
const handler = await module.main({ max_patch_size: 1024 }); // 1 MB max
- const result = await handler({ patch_path: patchPath, diff_size: 2 * 1024 * 1024 }, {});
+ const result = await handler({ diff_size: 2 * 1024 * 1024, branch: "should-reject-when-message-diff-size-exceeds-max-size-even-i" }, {});
expect(result.success).toBe(false);
expect(result.error).toContain("exceeds maximum");
@@ -1373,11 +1406,11 @@ index 0000000..abc1234
// do not set diff_size. The check must continue to work using the patch
// file size as the measurement.
const largePatch = "x".repeat(2 * 1024 * 1024); // 2 MB
- const patchPath = createPatchFile(largePatch);
+ const patchPath = createPatchFile("should-fall-back-to-patch-file-size-when-message-diff-size-i", largePatch);
const module = await loadModule();
const handler = await module.main({ max_patch_size: 1024 }); // 1 MB max
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-fall-back-to-patch-file-size-when-message-diff-size-i" }, {});
expect(result.success).toBe(false);
expect(result.error).toContain("exceeds maximum");
@@ -1386,14 +1419,14 @@ index 0000000..abc1234
it("should enforce max_patch_size against bundle size when bundle transport is used", async () => {
// Bundle transport still includes a patch for policy checks, but the size
// guard falls back to bundle size when diff_size is not provided.
- const bundlePath = path.join(tempDir, "test.bundle");
- const patchPath = createPatchFile("small patch content");
+ const bundlePath = canonicalBundlePath("should-enforce-max-patch-size-against-bundle-size-when-bundl");
+ const patchPath = createPatchFile("should-enforce-max-patch-size-against-bundle-size-when-bundl", "small patch content");
// 2 MB dummy bundle file (contents don't matter; only size is checked)
fs.writeFileSync(bundlePath, Buffer.alloc(2 * 1024 * 1024));
const module = await loadModule();
const handler = await module.main({ max_patch_size: 1024 }); // 1 MB max
- const result = await handler({ patch_path: patchPath, bundle_path: bundlePath }, {});
+ const result = await handler({ branch: "should-enforce-max-patch-size-against-bundle-size-when-bundl" }, {});
expect(result.success).toBe(false);
expect(result.error).toContain("exceeds maximum");
@@ -1404,15 +1437,15 @@ index 0000000..abc1234
// Bundle is 2 MB on disk, but the incremental net diff is only 5 KB:
// the check must accept the push (limit reflects the real change, not the
// compressed transport size).
- const bundlePath = path.join(tempDir, "test.bundle");
- const patchPath = createPatchFile("small patch content");
+ const bundlePath = canonicalBundlePath("should-prefer-diff-size-over-bundle-file-size-for-the-limit-");
+ const patchPath = createPatchFile("should-prefer-diff-size-over-bundle-file-size-for-the-limit-", "small patch content");
fs.writeFileSync(bundlePath, Buffer.alloc(2 * 1024 * 1024));
mockExec.getExecOutput.mockResolvedValue({ exitCode: 0, stdout: "abc123\n", stderr: "" });
const module = await loadModule();
const handler = await module.main({ max_patch_size: 1024 }); // 1 MB max
- const result = await handler({ patch_path: patchPath, bundle_path: bundlePath, diff_size: 5 * 1024 }, {});
+ const result = await handler({ diff_size: 5 * 1024, branch: "should-prefer-diff-size-over-bundle-file-size-for-the-limit-" }, {});
expect(result.success).toBe(true);
expect(mockCore.info).toHaveBeenCalledWith("Patch size validation passed");
@@ -1426,8 +1459,8 @@ index 0000000..abc1234
describe("bundle transport application", () => {
it("should apply bundle transport by updating the branch ref instead of merging", async () => {
- const bundlePath = path.join(tempDir, "test.bundle");
- const patchPath = createPatchFile("small patch content");
+ const bundlePath = canonicalBundlePath("feature-branch");
+ const patchPath = createPatchFile("feature-branch", "small patch content");
fs.writeFileSync(bundlePath, "bundle content");
const pushSignedCommitsModule = require("./push_signed_commits.cjs");
@@ -1452,7 +1485,7 @@ index 0000000..abc1234
const module = await loadModule();
const handler = await module.main({});
- const result = await handler({ branch: "feature-branch", patch_path: patchPath, bundle_path: bundlePath, diff_size: 5 * 1024 }, {});
+ const result = await handler({ branch: "feature-branch", diff_size: 5 * 1024 }, {});
expect(result.success).toBe(true);
// Initial bundle fetch is via getExecOutput (with ignoreReturnCode: true), not exec.exec
@@ -1472,8 +1505,8 @@ index 0000000..abc1234
it("should use sanitized branch name (not agent-supplied message.branch) in bundle fetch refspec", async () => {
// The agent may supply a message.branch value; the bundle fetch must use the
// sanitized branchName from the GitHub API — never the raw agent input.
- const bundlePath = path.join(tempDir, "sanitized-branch.bundle");
- const patchPath = createPatchFile("small patch content");
+ const bundlePath = canonicalBundlePath("feature-branch; rm -rf /");
+ const patchPath = createPatchFile("feature-branch; rm -rf /", "small patch content");
fs.writeFileSync(bundlePath, "bundle content");
const pushSignedCommitsModule = require("./push_signed_commits.cjs");
@@ -1499,7 +1532,7 @@ index 0000000..abc1234
const module = await loadModule();
const handler = await module.main({});
// message.branch contains shell metacharacters; branchName from the GitHub API is "feature-branch"
- const result = await handler({ branch: "feature-branch; rm -rf /", patch_path: patchPath, bundle_path: bundlePath, diff_size: 5 * 1024 }, {});
+ const result = await handler({ branch: "feature-branch; rm -rf /", diff_size: 5 * 1024 }, {});
expect(result.success).toBe(true);
@@ -1516,8 +1549,8 @@ index 0000000..abc1234
});
it("should fetch prerequisite commits and retry bundle fetch when bundle lacks prerequisites", async () => {
- const bundlePath = path.join(tempDir, "test.bundle");
- const patchPath = createPatchFile("small patch content");
+ const bundlePath = canonicalBundlePath("feature-branch");
+ const patchPath = createPatchFile("feature-branch", "small patch content");
fs.writeFileSync(bundlePath, "bundle content");
const missingSha = "172f87a830f57a29470efe7646d141069434a893";
@@ -1544,7 +1577,7 @@ index 0000000..abc1234
const module = await loadModule();
const handler = await module.main({});
- const result = await handler({ branch: "feature-branch", patch_path: patchPath, bundle_path: bundlePath, diff_size: 5 * 1024 }, {});
+ const result = await handler({ branch: "feature-branch", diff_size: 5 * 1024 }, {});
expect(result.success).toBe(true);
// Repo is not shallow and not sparse in this scenario, so no --filter=blob:none is used:
@@ -1564,8 +1597,8 @@ index 0000000..abc1234
// The handler must detect the merge commit in the range and perform a
// soft-reset + recommit to linearize it, then call pushSignedCommits with
// the linearized history.
- const bundlePath = path.join(tempDir, "merge-test.bundle");
- const patchPath = createPatchFile("small patch content");
+ const bundlePath = canonicalBundlePath("feature-branch");
+ const patchPath = createPatchFile("feature-branch", "small patch content");
fs.writeFileSync(bundlePath, "bundle content");
const pushSignedCommitsModule = require("./push_signed_commits.cjs");
@@ -1602,7 +1635,7 @@ index 0000000..abc1234
const module = await loadModule();
const handler = await module.main({});
- const result = await handler({ branch: "feature-branch", patch_path: patchPath, bundle_path: bundlePath, diff_size: 5 * 1024 }, {});
+ const result = await handler({ branch: "feature-branch", diff_size: 5 * 1024 }, {});
expect(result.success).toBe(true);
@@ -1633,8 +1666,8 @@ index 0000000..abc1234
it("should fall back to merge commit message when no non-merge commits exist in range", async () => {
// Scenario: the only commit in the range is the merge commit itself (agent only ran
// `git merge origin/main`, no additional work commits).
- const bundlePath = path.join(tempDir, "only-merge.bundle");
- const patchPath = createPatchFile("small patch content");
+ const bundlePath = canonicalBundlePath("feature-branch");
+ const patchPath = createPatchFile("feature-branch", "small patch content");
fs.writeFileSync(bundlePath, "bundle content");
const pushSignedCommitsModule = require("./push_signed_commits.cjs");
@@ -1674,7 +1707,7 @@ index 0000000..abc1234
const module = await loadModule();
const handler = await module.main({});
- const result = await handler({ branch: "feature-branch", patch_path: patchPath, bundle_path: bundlePath, diff_size: 5 * 1024 }, {});
+ const result = await handler({ branch: "feature-branch", diff_size: 5 * 1024 }, {});
expect(result.success).toBe(true);
@@ -1686,8 +1719,8 @@ index 0000000..abc1234
});
it("should skip linearization when no merge commits are present", async () => {
- const bundlePath = path.join(tempDir, "no-merge.bundle");
- const patchPath = createPatchFile("small patch content");
+ const bundlePath = canonicalBundlePath("feature-branch");
+ const patchPath = createPatchFile("feature-branch", "small patch content");
fs.writeFileSync(bundlePath, "bundle content");
const pushSignedCommitsModule = require("./push_signed_commits.cjs");
@@ -1716,7 +1749,7 @@ index 0000000..abc1234
const module = await loadModule();
const handler = await module.main({});
- const result = await handler({ branch: "feature-branch", patch_path: patchPath, bundle_path: bundlePath, diff_size: 5 * 1024 }, {});
+ const result = await handler({ branch: "feature-branch", diff_size: 5 * 1024 }, {});
expect(result.success).toBe(true);
@@ -1735,8 +1768,8 @@ index 0000000..abc1234
// found afterwards (e.g. the range was already empty / only no-op commits).
// The handler should roll back to the originalHead and warn, then let
// pushSignedCommits proceed (and potentially surface its own error).
- const bundlePath = path.join(tempDir, "empty-range.bundle");
- const patchPath = createPatchFile("small patch content");
+ const bundlePath = canonicalBundlePath("feature-branch");
+ const patchPath = createPatchFile("feature-branch", "small patch content");
fs.writeFileSync(bundlePath, "bundle content");
const pushSignedCommitsModule = require("./push_signed_commits.cjs");
@@ -1772,7 +1805,7 @@ index 0000000..abc1234
const module = await loadModule();
const handler = await module.main({});
- const result = await handler({ branch: "feature-branch", patch_path: patchPath, bundle_path: bundlePath, diff_size: 5 * 1024 }, {});
+ const result = await handler({ branch: "feature-branch", diff_size: 5 * 1024 }, {});
// The overall push should still succeed (warning path, not fatal error)
expect(result.success).toBe(true);
@@ -1811,11 +1844,11 @@ index 0000000..abc1234
},
});
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("should-reject-pr-without-required-title-prefix");
const module = await loadModule();
const handler = await module.main({ title_prefix: "[bot] " });
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-reject-pr-without-required-title-prefix" }, {});
expect(result.success).toBe(false);
expect(result.error).toContain("does not start with required prefix");
@@ -1834,12 +1867,12 @@ index 0000000..abc1234
},
});
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("should-accept-pr-with-required-title-prefix");
mockExec.getExecOutput.mockResolvedValue({ exitCode: 0, stdout: "abc123\n", stderr: "" });
const module = await loadModule();
const handler = await module.main({ title_prefix: "[bot] " });
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-accept-pr-with-required-title-prefix" }, {});
expect(result.success).toBe(true);
expect(mockCore.info).toHaveBeenCalledWith('✓ Title prefix validation passed: "[bot] "');
@@ -1858,11 +1891,11 @@ index 0000000..abc1234
},
});
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("should-reject-pr-without-required-labels");
const module = await loadModule();
const handler = await module.main({ labels: ["automated", "enhancement"] });
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-reject-pr-without-required-labels" }, {});
expect(result.success).toBe(false);
expect(result.error).toContain("missing required labels");
@@ -1881,12 +1914,12 @@ index 0000000..abc1234
},
});
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("should-accept-pr-with-all-required-labels");
mockExec.getExecOutput.mockResolvedValue({ exitCode: 0, stdout: "abc123\n", stderr: "" });
const module = await loadModule();
const handler = await module.main({ labels: ["automated", "enhancement"] });
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-accept-pr-with-all-required-labels" }, {});
expect(result.success).toBe(true);
expect(mockCore.info).toHaveBeenCalledWith("✓ Labels validation passed: automated, enhancement");
@@ -1899,12 +1932,12 @@ index 0000000..abc1234
describe("commit title suffix", () => {
it("should append suffix to commit messages in patch", async () => {
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("should-append-suffix-to-commit-messages-in-patch");
mockExec.getExecOutput.mockResolvedValue({ exitCode: 0, stdout: "abc123\n", stderr: "" });
const module = await loadModule();
const handler = await module.main({ commit_title_suffix: " [skip ci]" });
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-append-suffix-to-commit-messages-in-patch" }, {});
expect(result.success).toBe(true);
expect(mockCore.info).toHaveBeenCalledWith('Appending commit title suffix: " [skip ci]"');
@@ -1922,14 +1955,14 @@ index 0000000..abc1234
describe("staged mode", () => {
it("should generate preview instead of pushing in staged mode", async () => {
process.env.GH_AW_SAFE_OUTPUTS_STAGED = "true";
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("should-generate-preview-instead-of-pushing-in-staged-mode");
// Re-import the module to pick up env var
delete require.cache[require.resolve("./push_to_pull_request_branch.cjs")];
const module = require("./push_to_pull_request_branch.cjs");
const handler = await module.main({});
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-generate-preview-instead-of-pushing-in-staged-mode" }, {});
expect(result.success).toBe(true);
expect(result.staged).toBe(true);
@@ -1944,18 +1977,18 @@ index 0000000..abc1234
describe("max count limiting", () => {
it("should skip messages after max count reached", async () => {
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("should-skip-messages-after-max-count-reached");
mockExec.getExecOutput.mockResolvedValue({ exitCode: 0, stdout: "abc123\n", stderr: "" });
const module = await loadModule();
const handler = await module.main({ max: 1 });
// First call succeeds
- const result1 = await handler({ patch_path: patchPath }, {});
+ const result1 = await handler({ branch: "should-skip-messages-after-max-count-reached" }, {});
expect(result1.success).toBe(true);
// Second call is skipped
- const result2 = await handler({ patch_path: patchPath }, {});
+ const result2 = await handler({ branch: "should-skip-messages-after-max-count-reached" }, {});
expect(result2.success).toBe(false);
expect(result2.skipped).toBe(true);
expect(result2.error).toContain("Max count");
@@ -1980,11 +2013,11 @@ index 0000000..abc1234
},
});
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("should-sanitize-branch-names-with-shell-metacharacters");
const module = await loadModule();
const handler = await module.main({});
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-sanitize-branch-names-with-shell-metacharacters" }, {});
// The normalizeBranchName should sanitize dangerous characters
expect(mockCore.info).toHaveBeenCalledWith(expect.stringContaining("Branch name sanitized"));
@@ -2003,11 +2036,11 @@ index 0000000..abc1234
},
});
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("should-reject-empty-branch-name-after-sanitization");
const module = await loadModule();
const handler = await module.main({});
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-reject-empty-branch-name-after-sanitization" }, {});
expect(result.success).toBe(false);
expect(result.error).toContain("Invalid branch name");
@@ -2022,11 +2055,11 @@ index 0000000..abc1234
it("should handle PR not found error", async () => {
mockGithub.rest.pulls.get.mockRejectedValue(new Error("Not Found"));
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("should-handle-pr-not-found-error");
const module = await loadModule();
const handler = await module.main({});
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-handle-pr-not-found-error" }, {});
expect(result.success).toBe(false);
expect(result.error).toContain("Failed to determine branch name");
@@ -2035,11 +2068,11 @@ index 0000000..abc1234
it("should handle network error fetching PR", async () => {
mockGithub.rest.pulls.get.mockRejectedValue(new Error("Network timeout"));
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("should-handle-network-error-fetching-pr");
const module = await loadModule();
const handler = await module.main({});
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-handle-network-error-fetching-pr" }, {});
expect(result.success).toBe(false);
expect(result.error).toContain("Failed to determine branch name");
@@ -2058,7 +2091,7 @@ index 0000000..abc1234
delete require.cache[require.resolve("./push_to_pull_request_branch.cjs")];
delete require.cache[require.resolve("./extra_empty_commit.cjs")];
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("should-push-extra-empty-commit-when-ci-trigger-token-is-set");
// Mock successful commands
mockExec.exec.mockResolvedValue(0);
@@ -2077,7 +2110,7 @@ index 0000000..abc1234
const module = require("./push_to_pull_request_branch.cjs");
const handler = await module.main({});
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-push-extra-empty-commit-when-ci-trigger-token-is-set" }, {});
expect(result.success).toBe(true);
// The extra empty commit should have been attempted
@@ -2137,11 +2170,11 @@ ${diffs}
}
it("should reject files outside the allowed-files allowlist", async () => {
- const patchPath = createPatchFile(createPatchWithFiles("src/index.js"));
+ const patchPath = createPatchFile("should-reject-files-outside-the-allowed-files-allowlist", createPatchWithFiles("src/index.js"));
const module = await loadModule();
const handler = await module.main({ allowed_files: [".changeset/**"] });
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-reject-files-outside-the-allowed-files-allowlist" }, {});
expect(result.success).toBe(false);
expect(result.error).toContain("outside the allowed-files list");
@@ -2149,7 +2182,7 @@ ${diffs}
});
it("should accept files that match the allowed-files pattern", async () => {
- const patchPath = createPatchFile(createPatchWithFiles(".changeset/my-feature-fix.md"));
+ const patchPath = createPatchFile("should-accept-files-that-match-the-allowed-files-pattern", createPatchWithFiles(".changeset/my-feature-fix.md"));
mockExec.getExecOutput.mockImplementation(async (cmd, args) => {
if (cmd === "git" && Array.isArray(args) && args[0] === "diff" && args[1] === "--name-only" && args[2] === "--no-renames") {
return { exitCode: 0, stdout: ".changeset/my-feature-fix.md\n", stderr: "" };
@@ -2159,7 +2192,7 @@ ${diffs}
const module = await loadModule();
const handler = await module.main({ allowed_files: [".changeset/**"] });
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-accept-files-that-match-the-allowed-files-pattern" }, {});
expect(result.success).toBe(true);
});
@@ -2167,7 +2200,7 @@ ${diffs}
it("should still block a protected file when it is in the allowlist but protected-files: allowed is not set", async () => {
// allowed-files and protected-files are orthogonal: both checks must pass.
// Matching the allowlist does NOT bypass the protected-files policy.
- const patchPath = createPatchFile(createPatchWithFiles("package.json"));
+ const patchPath = createPatchFile("should-still-block-a-protected-file-when-it-is-in-the-allowl", createPatchWithFiles("package.json"));
const module = await loadModule();
const handler = await module.main({
@@ -2175,7 +2208,7 @@ ${diffs}
protected_files: ["package.json"],
protected_files_policy: "blocked",
});
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-still-block-a-protected-file-when-it-is-in-the-allowl" }, {});
expect(result.success).toBe(false);
expect(result.error).toContain("protected files");
@@ -2184,7 +2217,7 @@ ${diffs}
it("should allow a protected file when both allowed-files matches and protected-files: allowed is set", async () => {
// Both checks are satisfied explicitly: allowlist scope + protected-files permission.
- const patchPath = createPatchFile(createPatchWithFiles("package.json"));
+ const patchPath = createPatchFile("should-allow-a-protected-file-when-both-allowed-files-matche", createPatchWithFiles("package.json"));
mockExec.getExecOutput.mockImplementation(async (cmd, args) => {
if (cmd === "git" && Array.isArray(args) && args[0] === "diff" && args[1] === "--name-only" && args[2] === "--no-renames") {
return { exitCode: 0, stdout: "package.json\n", stderr: "" };
@@ -2198,13 +2231,13 @@ ${diffs}
protected_files: ["package.json"],
protected_files_policy: "allowed",
});
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-allow-a-protected-file-when-both-allowed-files-matche" }, {});
expect(result.success).toBe(true);
});
it("should create a fallback issue instead of pushing when post-apply detects protected files", async () => {
- const patchPath = createPatchFile(createPatchWithFiles("README.md"));
+ const patchPath = createPatchFile("should-create-a-fallback-issue-instead-of-pushing-when-post-", createPatchWithFiles("README.md"));
const pushSignedCommitsModule = require("./push_signed_commits.cjs");
const pushSignedSpy = vi.spyOn(pushSignedCommitsModule, "pushSignedCommits").mockResolvedValue("remote-head-after");
const promptsDir = path.join(tempDir, "prompts");
@@ -2230,7 +2263,7 @@ ${diffs}
protected_files_policy: "fallback-to-issue",
});
try {
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-create-a-fallback-issue-instead-of-pushing-when-post-" }, {});
expect(result.success).toBe(true);
expect(result.fallback_used).toBe(true);
@@ -2244,14 +2277,14 @@ ${diffs}
});
it("should block a protected file when no allowed-files list is configured", async () => {
- const patchPath = createPatchFile(createPatchWithFiles("package.json"));
+ const patchPath = createPatchFile("should-block-a-protected-file-when-no-allowed-files-list-is-", createPatchWithFiles("package.json"));
const module = await loadModule();
const handler = await module.main({
protected_files: ["package.json"],
protected_files_policy: "blocked",
});
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-block-a-protected-file-when-no-allowed-files-list-is-" }, {});
expect(result.success).toBe(false);
expect(result.error).toContain("protected files");
@@ -2259,11 +2292,11 @@ ${diffs}
});
it("should reject a mixed patch where at least one file is outside the allowlist", async () => {
- const patchPath = createPatchFile(createPatchWithFiles(".changeset/my-fix.md", "src/index.js"));
+ const patchPath = createPatchFile("should-reject-a-mixed-patch-where-at-least-one-file-is-outsi", createPatchWithFiles(".changeset/my-fix.md", "src/index.js"));
const module = await loadModule();
const handler = await module.main({ allowed_files: [".changeset/**"] });
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-reject-a-mixed-patch-where-at-least-one-file-is-outsi" }, {});
expect(result.success).toBe(false);
expect(result.error).toContain("outside the allowed-files list");
@@ -2306,7 +2339,7 @@ ${diffs}
it("should ignore files matching excluded-files patterns (not blocked by allowed-files)", async () => {
// excluded-files are excluded at patch generation time via git :(exclude) pathspecs.
// Simulate post-generation: the patch already contains only the non-ignored file.
- const patchPath = createPatchFile(createPatchWithFiles("src/index.js"));
+ const patchPath = createPatchFile("should-ignore-files-matching-excluded-files-patterns-not-blo", createPatchWithFiles("src/index.js"));
mockExec.getExecOutput.mockResolvedValue({ exitCode: 0, stdout: "abc123\n", stderr: "" });
const module = await loadModule();
@@ -2314,20 +2347,20 @@ ${diffs}
excluded_files: ["auto-generated/**"],
allowed_files: ["src/**"],
});
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-ignore-files-matching-excluded-files-patterns-not-blo" }, {});
expect(result.error || "").not.toContain("outside the allowed-files list");
});
it("should still block non-ignored files that violate the allowed-files list", async () => {
- const patchPath = createPatchFile(createPatchWithFiles("src/index.js", "other/file.txt"));
+ const patchPath = createPatchFile("should-still-block-non-ignored-files-that-violate-the-allowe", createPatchWithFiles("src/index.js", "other/file.txt"));
const module = await loadModule();
const handler = await module.main({
excluded_files: ["auto-generated/**"],
allowed_files: ["src/**"],
});
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-still-block-non-ignored-files-that-violate-the-allowe" }, {});
expect(result.success).toBe(false);
expect(result.error).toContain("outside the allowed-files list");
@@ -2338,7 +2371,7 @@ ${diffs}
it("should ignore files matching excluded-files patterns (not blocked by protected-files)", async () => {
// excluded-files are excluded at patch generation time via git :(exclude) pathspecs.
// Simulate post-generation: the patch already contains only the non-ignored file.
- const patchPath = createPatchFile(createPatchWithFiles("src/index.js"));
+ const patchPath = createPatchFile("should-ignore-files-matching-excluded-files-patterns-not-blo", createPatchWithFiles("src/index.js"));
mockExec.getExecOutput.mockResolvedValue({ exitCode: 0, stdout: "abc123\n", stderr: "" });
const module = await loadModule();
@@ -2347,7 +2380,7 @@ ${diffs}
protected_files: ["package.json"],
protected_files_policy: "blocked",
});
- const result = await handler({ patch_path: patchPath }, {});
+ const result = await handler({ branch: "should-ignore-files-matching-excluded-files-patterns-not-blo" }, {});
expect(result.error || "").not.toContain("protected files");
});
@@ -2355,14 +2388,14 @@ ${diffs}
it("should allow when all patch files are ignored (even with allowed-files set)", async () => {
// excluded-files are excluded at patch generation time via git :(exclude) pathspecs.
// Simulate post-generation: all files were excluded so no patch file is produced.
- const nonexistentPath = path.join(tempDir, "nonexistent.patch");
+ const nonexistentPath = canonicalPatchPath("should-allow-when-all-patch-files-are-ignored-even-with-allo");
const module = await loadModule();
const handler = await module.main({
excluded_files: ["dist/**"],
allowed_files: ["src/**"],
});
- const result = await handler({ patch_path: nonexistentPath }, {});
+ const result = await handler({ branch: "should-allow-when-all-patch-files-are-ignored-even-with-allo" }, {});
// No patch → treated as no changes, not an allowlist violation
expect(result.error || "").not.toContain("outside the allowed-files list");
@@ -2391,11 +2424,11 @@ ${diffs}
},
});
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("should-return-error-when-target-repo-differs-from-workflow-r");
const module = await loadModule();
const handler = await module.main({ "target-repo": "other-owner/other-repo" });
- const result = await handler({ patch_path: patchPath, pull_request_number: 42 }, {});
+ const result = await handler({ pull_request_number: 42, branch: "should-return-error-when-target-repo-differs-from-workflow-r" }, {});
expect(result.success).toBe(false);
expect(result.error).toContain("other-owner/other-repo");
@@ -2433,11 +2466,11 @@ ${diffs}
mockExec.getExecOutput.mockResolvedValue({ exitCode: 0, stdout: "abc123\n", stderr: "" });
- const patchPath = createPatchFile();
+ const patchPath = createPatchFile("main");
const module = await loadModule();
const handler = await module.main({ "target-repo": "other-owner/other-repo" });
- await handler({ patch_path: patchPath, pull_request_number: 42 }, {});
+ await handler({ pull_request_number: 42, branch: "main" }, {});
// Verify git ls-remote was called with cwd pointing at the subdirectory
expect(mockCore.info).toHaveBeenCalledWith(expect.stringContaining(`Found checkout for other-owner/other-repo at: ${subRepoDir}`));
diff --git a/actions/setup/js/resolve_transport_paths.cjs b/actions/setup/js/resolve_transport_paths.cjs
new file mode 100644
index 00000000000..d09d1d63366
--- /dev/null
+++ b/actions/setup/js/resolve_transport_paths.cjs
@@ -0,0 +1,51 @@
+// @ts-check
+
+/** @type {typeof import("fs")} */
+const fs = require("fs");
+const { getPatchPathForBranch, getPatchPathForBranchInRepo } = require("./git_patch_utils.cjs");
+const { getBundlePathForBranch, getBundlePathForBranchInRepo } = require("./generate_git_bundle.cjs");
+
+/**
+ * Derive patch and bundle file paths for a safe-output message from the
+ * validated `branch` (and optional `repo`) fields.
+ *
+ * Paths are always re-derived from `branch` so that even a malicious agent
+ * cannot point the privileged handler at a file outside the canonical
+ * `/tmp/gh-aw/aw-.{patch,bundle}` prefix. Sanitization in
+ * `getPatchPathForBranch` / `getBundlePathForBranch` enforces that prefix.
+ *
+ * @param {Object} message - The safe-output message
+ * @param {string} [defaultTargetRepo] - Default target repo slug used as a fallback
+ * candidate for multi-repo path computation
+ * @returns {{patchPath: string|undefined, bundlePath: string|undefined}}
+ */
+function resolveTransportPaths(message, defaultTargetRepo) {
+ const branch = message.branch;
+ if (!branch) {
+ return { patchPath: undefined, bundlePath: undefined };
+ }
+ /** @type {(string|null)[]} */
+ const repoCandidates = [];
+ if (message.repo) repoCandidates.push(message.repo);
+ if (defaultTargetRepo && defaultTargetRepo !== message.repo) repoCandidates.push(defaultTargetRepo);
+ repoCandidates.push(null);
+ let patchPath;
+ let bundlePath;
+ for (const repo of repoCandidates) {
+ const p = repo ? getPatchPathForBranchInRepo(branch, repo) : getPatchPathForBranch(branch);
+ if (fs.existsSync(p)) {
+ patchPath = p;
+ break;
+ }
+ }
+ for (const repo of repoCandidates) {
+ const p = repo ? getBundlePathForBranchInRepo(branch, repo) : getBundlePathForBranch(branch);
+ if (fs.existsSync(p)) {
+ bundlePath = p;
+ break;
+ }
+ }
+ return { patchPath, bundlePath };
+}
+
+module.exports = { resolveTransportPaths };
diff --git a/actions/setup/js/resolve_transport_paths.test.cjs b/actions/setup/js/resolve_transport_paths.test.cjs
new file mode 100644
index 00000000000..4dd5a62fa72
--- /dev/null
+++ b/actions/setup/js/resolve_transport_paths.test.cjs
@@ -0,0 +1,95 @@
+// @ts-check
+
+import { describe, it, expect, beforeEach } from "vitest";
+import fs from "fs";
+
+import { resolveTransportPaths } from "./resolve_transport_paths.cjs";
+
+beforeEach(() => {
+ // git_patch_utils.cjs hardcodes /tmp/gh-aw
+ fs.mkdirSync("/tmp/gh-aw", { recursive: true });
+});
+
+describe("resolveTransportPaths", () => {
+ it("returns undefined values when message has no branch", () => {
+ const result = resolveTransportPaths({}, "owner/repo");
+ expect(result.patchPath).toBeUndefined();
+ expect(result.bundlePath).toBeUndefined();
+ });
+
+ it("recovers single-repo patch path from branch when not present on the message", () => {
+ const branch = `resolve-test-${Date.now()}`;
+ const expectedPatch = `/tmp/gh-aw/aw-${branch}.patch`;
+ const expectedBundle = `/tmp/gh-aw/aw-${branch}.bundle`;
+ fs.writeFileSync(expectedPatch, "patch-content");
+ fs.writeFileSync(expectedBundle, "bundle-content");
+ try {
+ const result = resolveTransportPaths({ branch }, undefined);
+ expect(result.patchPath).toBe(expectedPatch);
+ expect(result.bundlePath).toBe(expectedBundle);
+ } finally {
+ fs.rmSync(expectedPatch, { force: true });
+ fs.rmSync(expectedBundle, { force: true });
+ }
+ });
+
+ it("prefers multi-repo path from message.repo when that file exists", () => {
+ const branch = `resolve-multi-${Date.now()}`;
+ const repo = "owner/repo";
+ const sanitizedRepo = "owner-repo";
+ const expectedPatch = `/tmp/gh-aw/aw-${sanitizedRepo}-${branch}.patch`;
+ fs.writeFileSync(expectedPatch, "patch-content");
+ try {
+ const result = resolveTransportPaths({ branch, repo }, undefined);
+ expect(result.patchPath).toBe(expectedPatch);
+ } finally {
+ fs.rmSync(expectedPatch, { force: true });
+ }
+ });
+
+ it("falls back to defaultTargetRepo when message.repo is absent", () => {
+ const branch = `resolve-default-${Date.now()}`;
+ const repo = "owner/defaultrepo";
+ const sanitizedRepo = "owner-defaultrepo";
+ const expectedPatch = `/tmp/gh-aw/aw-${sanitizedRepo}-${branch}.patch`;
+ fs.writeFileSync(expectedPatch, "patch-content");
+ try {
+ const result = resolveTransportPaths({ branch }, repo);
+ expect(result.patchPath).toBe(expectedPatch);
+ } finally {
+ fs.rmSync(expectedPatch, { force: true });
+ }
+ });
+
+ it("falls back to single-repo path when neither multi-repo candidate exists", () => {
+ const branch = `resolve-fallback-${Date.now()}`;
+ const expectedPatch = `/tmp/gh-aw/aw-${branch}.patch`;
+ fs.writeFileSync(expectedPatch, "patch-content");
+ try {
+ const result = resolveTransportPaths({ branch, repo: "owner/nonexistent" }, "owner/alsoNo");
+ expect(result.patchPath).toBe(expectedPatch);
+ } finally {
+ fs.rmSync(expectedPatch, { force: true });
+ }
+ });
+
+ it("returns undefined when no candidate file exists on disk", () => {
+ const branch = `resolve-missing-${Date.now()}`;
+ const result = resolveTransportPaths({ branch }, "owner/repo");
+ expect(result.patchPath).toBeUndefined();
+ expect(result.bundlePath).toBeUndefined();
+ });
+
+ it("recovers bundle path independently of patch path", () => {
+ const branch = `resolve-bundle-only-${Date.now()}`;
+ const expectedBundle = `/tmp/gh-aw/aw-${branch}.bundle`;
+ fs.writeFileSync(expectedBundle, "bundle-content");
+ try {
+ const result = resolveTransportPaths({ branch }, undefined);
+ expect(result.patchPath).toBeUndefined();
+ expect(result.bundlePath).toBe(expectedBundle);
+ } finally {
+ fs.rmSync(expectedBundle, { force: true });
+ }
+ });
+});
diff --git a/actions/setup/js/safe_output_type_validator.cjs b/actions/setup/js/safe_output_type_validator.cjs
index 0196d83d4b5..d9de7359671 100644
--- a/actions/setup/js/safe_output_type_validator.cjs
+++ b/actions/setup/js/safe_output_type_validator.cjs
@@ -545,14 +545,6 @@ function validateItem(item, itemType, lineNum, options) {
}
const normalizedItem = { ...item };
- // SECURITY: Strip infrastructure fields that must only be set by the MCP handler,
- // never by the agent. If an agent injects these via NDJSON output, it could bypass
- // file-protection policy (patch_path/bundle_path point to attacker-controlled files)
- // or circumvent size limits (diff_size).
- delete normalizedItem.patch_path;
- delete normalizedItem.bundle_path;
- delete normalizedItem.base_commit;
- delete normalizedItem.diff_size;
const errors = [];
// Run custom validation first if defined
diff --git a/actions/setup/js/safe_output_type_validator.test.cjs b/actions/setup/js/safe_output_type_validator.test.cjs
index 1b9dfb9abf1..6b4246464bd 100644
--- a/actions/setup/js/safe_output_type_validator.test.cjs
+++ b/actions/setup/js/safe_output_type_validator.test.cjs
@@ -804,40 +804,8 @@ describe("safe_output_type_validator", () => {
});
});
- describe("infrastructure field stripping (security)", () => {
- it("should strip patch_path from normalizedItem", async () => {
- const { validateItem } = await import("./safe_output_type_validator.cjs");
-
- const item = {
- type: "create_pull_request",
- title: "Fix bug",
- body: "Fixes the thing",
- branch: "fix/bug",
- patch_path: "/tmp/evil.patch",
- };
-
- const result = validateItem(item, "create_pull_request", 1);
- expect(result.isValid).toBe(true);
- expect(result.normalizedItem).not.toHaveProperty("patch_path");
- });
-
- it("should strip bundle_path from normalizedItem", async () => {
- const { validateItem } = await import("./safe_output_type_validator.cjs");
-
- const item = {
- type: "create_pull_request",
- title: "Fix bug",
- body: "Fixes the thing",
- branch: "fix/bug",
- bundle_path: "/tmp/evil.bundle",
- };
-
- const result = validateItem(item, "create_pull_request", 1);
- expect(result.isValid).toBe(true);
- expect(result.normalizedItem).not.toHaveProperty("bundle_path");
- });
-
- it("should strip base_commit from normalizedItem", async () => {
+ describe("undeclared field passthrough", () => {
+ it("should preserve base_commit on normalizedItem", async () => {
const { validateItem } = await import("./safe_output_type_validator.cjs");
const item = {
@@ -850,10 +818,10 @@ describe("safe_output_type_validator", () => {
const result = validateItem(item, "create_pull_request", 1);
expect(result.isValid).toBe(true);
- expect(result.normalizedItem).not.toHaveProperty("base_commit");
+ expect(result.normalizedItem.base_commit).toBe("abc123deadbeef");
});
- it("should strip diff_size from normalizedItem", async () => {
+ it("should preserve diff_size on normalizedItem", async () => {
const { validateItem } = await import("./safe_output_type_validator.cjs");
const item = {
@@ -866,35 +834,10 @@ describe("safe_output_type_validator", () => {
const result = validateItem(item, "create_pull_request", 1);
expect(result.isValid).toBe(true);
- expect(result.normalizedItem).not.toHaveProperty("diff_size");
- });
-
- it("should strip all infrastructure fields simultaneously", async () => {
- const { validateItem } = await import("./safe_output_type_validator.cjs");
-
- const item = {
- type: "create_pull_request",
- title: "Fix bug",
- body: "Fixes the thing",
- branch: "fix/bug",
- patch_path: "/tmp/evil.patch",
- bundle_path: "/tmp/evil.bundle",
- base_commit: "abc123",
- diff_size: 999999,
- };
-
- const result = validateItem(item, "create_pull_request", 1);
- expect(result.isValid).toBe(true);
- expect(result.normalizedItem).not.toHaveProperty("patch_path");
- expect(result.normalizedItem).not.toHaveProperty("bundle_path");
- expect(result.normalizedItem).not.toHaveProperty("base_commit");
- expect(result.normalizedItem).not.toHaveProperty("diff_size");
- // Legitimate fields should still be present
- expect(result.normalizedItem.title).toBe("Fix bug");
- expect(result.normalizedItem.branch).toBe("fix/bug");
+ expect(result.normalizedItem.diff_size).toBe(1);
});
- it("should preserve non-infrastructure undeclared fields", async () => {
+ it("should preserve undeclared fields", async () => {
const { validateItem } = await import("./safe_output_type_validator.cjs");
const item = {
@@ -906,7 +849,6 @@ describe("safe_output_type_validator", () => {
const result = validateItem(item, "create_issue", 1);
expect(result.isValid).toBe(true);
- // Non-infrastructure extra fields should pass through
expect(result.normalizedItem.metadata).toEqual({ project: "test" });
});
});
diff --git a/actions/setup/js/safe_outputs_handlers.cjs b/actions/setup/js/safe_outputs_handlers.cjs
index 6620e316a32..cf364bc51e7 100644
--- a/actions/setup/js/safe_outputs_handlers.cjs
+++ b/actions/setup/js/safe_outputs_handlers.cjs
@@ -648,8 +648,9 @@ function createHandlers(server, appendSafeOutput, config = {}) {
// prettier-ignore
server.debug(`Patch generated successfully: ${patchResult.patchPath} (${patchResult.patchSize} bytes, ${patchResult.patchLines} lines)`);
- // Store the patch path in the entry so consumers know which file to use
- entry.patch_path = patchResult.patchPath;
+ // Patch/bundle paths are not transmitted via the safe-output entry: the
+ // privileged safe_outputs job re-derives them from the (validated) branch name
+ // using resolve_transport_paths.
// Store the base commit SHA so the create_pull_request handler can use it
// directly in the fallback path (the From header in format-patch output
@@ -724,8 +725,9 @@ function createHandlers(server, appendSafeOutput, config = {}) {
}
}
- // Store the bundle path in the entry so consumers know which file to use
- entry.bundle_path = bundleResult.bundlePath;
+ // Bundle path is not transmitted via the safe-output entry: the privileged
+ // safe_outputs job re-derives it from the (validated) branch name using
+ // resolve_transport_paths.
// Prefer the base_commit captured from format-patch generation (used by
// patch-based fallback/apply paths). Only fall back to bundle base commit
@@ -1061,8 +1063,9 @@ function createHandlers(server, appendSafeOutput, config = {}) {
// prettier-ignore
server.debug(`Patch generated successfully: ${patchResult.patchPath} (${patchResult.patchSize} bytes, ${patchResult.patchLines} lines, diffSize=${patchResult.diffSize ?? "(n/a)"} bytes)`);
- // Store the patch path in the entry so consumers know which file to use
- entry.patch_path = patchResult.patchPath;
+ // Patch/bundle paths are not transmitted via the safe-output entry: the
+ // privileged safe_outputs job re-derives them from the (validated) branch name
+ // using resolve_transport_paths.
// Store the base commit SHA so the push handler can use it directly
if (patchResult.baseCommit) {
@@ -1144,8 +1147,9 @@ function createHandlers(server, appendSafeOutput, config = {}) {
}
}
- // Store the bundle path in the entry so consumers know which file to use
- entry.bundle_path = bundleResult.bundlePath;
+ // Bundle path is not transmitted via the safe-output entry: the privileged
+ // safe_outputs job re-derives it from the (validated) branch name using
+ // resolve_transport_paths.
// Prefer the base_commit captured from format-patch generation (used by
// patch-based fallback/apply paths). Only fall back to bundle base commit
diff --git a/actions/setup/js/safe_outputs_handlers.test.cjs b/actions/setup/js/safe_outputs_handlers.test.cjs
index 229fd36cb6e..a97a8ce7f08 100644
--- a/actions/setup/js/safe_outputs_handlers.test.cjs
+++ b/actions/setup/js/safe_outputs_handlers.test.cjs
@@ -968,12 +968,10 @@ describe("safe_outputs_handlers", () => {
type: "create_pull_request",
base_branch: "main",
branch: "release-1.12.x",
- patch_path: expect.any(String),
})
);
-
- const appendedEntry = mockAppendSafeOutput.mock.calls.at(-1)[0];
- const patchContent = fs.readFileSync(appendedEntry.patch_path, "utf8");
+ const responseData = JSON.parse(result.content[0].text);
+ const patchContent = fs.readFileSync(responseData.patch.path, "utf8");
// Diffing release-1.12.x against base main includes both release-only commits:
// the tracked release commit and the local-only fix.
expect(patchContent).toContain("local only fix");
@@ -1253,8 +1251,6 @@ describe("safe_outputs_handlers", () => {
expect.objectContaining({
type: "push_to_pull_request_branch",
repo_cwd: targetRepoDir,
- patch_path: expect.stringContaining("aw-test-owner-test-repo-feature-test-change.patch"),
- bundle_path: expect.stringContaining("aw-test-owner-test-repo-feature-test-change.bundle"),
})
);
} finally {
@@ -1420,13 +1416,9 @@ describe("safe_outputs_handlers", () => {
expect(mockAppendSafeOutput).toHaveBeenCalledWith(
expect.objectContaining({
type: "push_to_pull_request_branch",
- patch_path: expect.stringMatching(/\.patch$/),
- bundle_path: expect.stringMatching(/\.bundle$/),
})
);
- // Bundle mode should still include patch_path for policy enforcement checks
const appended = mockAppendSafeOutput.mock.calls[0][0];
- expect(appended.patch_path).toMatch(/\.patch$/);
// diff_size must be recorded so the downstream push step can validate
// max_patch_size against the net incremental diff (not the bundle size,
// which on long-running branches accumulates packed git objects and can
diff --git a/actions/setup/md/effective_tokens_rate_limit_error.md b/actions/setup/md/effective_tokens_rate_limit_error.md
index c893e9e8c50..c91d8b86aa1 100644
--- a/actions/setup/md/effective_tokens_rate_limit_error.md
+++ b/actions/setup/md/effective_tokens_rate_limit_error.md
@@ -5,7 +5,7 @@
- Learn about [effective tokens]({et_spec_link}).
{usage_line}{budget_line}{run_line}
-You can tune this limit with `max-effective-tokens` in workflow frontmatter.
+You can tune this limit with `max-ai-credits` in workflow frontmatter.
{et_table_section}
- To optimize this workflow, follow the [token optimization instructions]({token_opt_link}).
diff --git a/docs/adr/35286-compiler-managed-enterprise-env-controls.md b/docs/adr/35286-compiler-managed-enterprise-env-controls.md
index 47d066afb22..16f4d297da1 100644
--- a/docs/adr/35286-compiler-managed-enterprise-env-controls.md
+++ b/docs/adr/35286-compiler-managed-enterprise-env-controls.md
@@ -10,7 +10,7 @@
### Context
-Enterprise administrators need to set organization- or repository-wide defaults for engine model selection and the `max-effective-tokens` AWF guardrail without editing every individual workflow's frontmatter. Before this change, model fallback expressions were assembled ad-hoc with `fmt.Sprintf("${{ vars.%s || '%s' }}", ...)` scattered across the engine-specific files (`claude_engine.go`, `codex_engine.go`, `copilot_engine_execution.go`, `compiler_yaml.go`), and `max-effective-tokens` was resolved at compile time directly against a hard-coded constant. There was no central enumeration of compiler-managed enterprise variables, and the only override path available to admins was the per-engine `GH_AW_MODEL_AGENT_*` / `GH_AW_MODEL_DETECTION_*` knobs, which still require touching workflow frontmatter to reach a useful default. The team wanted a second-tier "enterprise default" layer plus a single Go-side helper that knows about it for both YAML expression generation and Go-side compile-time resolution.
+Enterprise administrators need to set organization- or repository-wide defaults for engine model selection and the `max-ai-credits` AWF guardrail without editing every individual workflow's frontmatter. Before this change, model fallback expressions were assembled ad-hoc with `fmt.Sprintf("${{ vars.%s || '%s' }}", ...)` scattered across the engine-specific files (`claude_engine.go`, `codex_engine.go`, `copilot_engine_execution.go`, `compiler_yaml.go`), and `max-ai-credits` was resolved at compile time directly against a hard-coded constant. There was no central enumeration of compiler-managed enterprise variables, and the only override path available to admins was the per-engine `GH_AW_MODEL_AGENT_*` / `GH_AW_MODEL_DETECTION_*` knobs, which still require touching workflow frontmatter to reach a useful default. The team wanted a second-tier "enterprise default" layer plus a single Go-side helper that knows about it for both YAML expression generation and Go-side compile-time resolution.
### Decision
@@ -24,7 +24,7 @@ Keep the existing pattern of inline `fmt.Sprintf` expressions, and add the `GH_A
#### Alternative 2: YAML-only enterprise overrides (no Go-side resolver)
-Implement the override chain purely as a `vars.*` expression injected into generated workflow YAML, and resolve everything at GitHub Actions runtime. This was rejected because `max-effective-tokens` is also consumed at compile time inside the Go binary — `BuildAWFConfigJSON` (`pkg/workflow/awf_config.go`) and `buildConclusionJob` (`pkg/workflow/notify_comment.go`) need the numeric value to emit into the AWF config JSON and into the failure-reporting env block. A YAML-only solution would leave those compile-time paths unable to honor the enterprise default, so `ResolveDefaultMaxEffectiveTokens` (a Go-side `os.Getenv` reader) is required.
+Implement the override chain purely as a `vars.*` expression injected into generated workflow YAML, and resolve everything at GitHub Actions runtime. This was rejected because `max-ai-credits` is also consumed at compile time inside the Go binary — `BuildAWFConfigJSON` (`pkg/workflow/awf_config.go`) and `buildConclusionJob` (`pkg/workflow/notify_comment.go`) need the numeric value to emit into the AWF config JSON and into the failure-reporting env block. A YAML-only solution would leave those compile-time paths unable to honor the enterprise default, so `ResolveDefaultMaxEffectiveTokens` (a Go-side `os.Getenv` reader) is required.
#### Alternative 3: Config-file-based enterprise overrides (e.g. `.gh-aw-enterprise.yml`)
diff --git a/docs/src/content/docs/experimental/experiments-specification.md b/docs/src/content/docs/experimental/experiments-specification.md
index 066b04b8d47..c34839c2d85 100644
--- a/docs/src/content/docs/experimental/experiments-specification.md
+++ b/docs/src/content/docs/experimental/experiments-specification.md
@@ -227,7 +227,7 @@ The same minimum-two-variants constraint from R-SCHEMA-005 applies.
|---|---|---|
| `description` | string | Human-readable explanation of what the experiment tests. |
| `hypothesis` | string | Null and alternative hypothesis statements. |
-| `metric` | string | Primary metric name to observe (e.g., `effective_tokens`). |
+| `metric` | string | Primary metric name to observe (e.g., `aic`). |
| `secondary_metrics` | string[] | Additional metrics to collect. |
| `guardrail_metrics` | object[] | Thresholds that must not degrade (see §4.4). |
| `min_samples` | integer ≥ 1 | Minimum runs per variant before analysis is reliable. Defaults to 20. |
@@ -951,8 +951,8 @@ experiments:
prompt_style:
variants: [concise, detailed, step_by_step]
description: "Test whether verbosity level affects output quality"
- hypothesis: "H0: no change in effective_tokens. H1: concise reduces by >=15%"
- metric: effective_tokens
+ hypothesis: "H0: no change in aic. H1: concise reduces by >=15%"
+ metric: aic
secondary_metrics: [duration_ms, discussion_word_count]
guardrail_metrics:
- name: success_rate
diff --git a/docs/src/content/docs/experimental/experiments.md b/docs/src/content/docs/experimental/experiments.md
index 0f8a24c70dc..f145ea80f24 100644
--- a/docs/src/content/docs/experimental/experiments.md
+++ b/docs/src/content/docs/experimental/experiments.md
@@ -46,9 +46,9 @@ engine: copilot
experiments:
prompt_style:
variants: [concise, detailed]
- description: "Test whether a concise prompt reduces token cost without quality loss"
- hypothesis: "H0: no change in effective_tokens. H1: concise reduces tokens by >=15%"
- metric: effective_tokens
+ description: "Test whether a concise prompt reduces cost without quality loss"
+ hypothesis: "H0: no change in aic. H1: concise reduces AIC by >=15%"
+ metric: aic
secondary_metrics: [duration_ms, discussion_word_count]
guardrail_metrics:
- name: success_rate
@@ -170,9 +170,9 @@ prompt_style (target: 25 per variant)
**prompt_style**
-> Test whether a concise prompt reduces token cost without quality loss
+> Test whether a concise prompt reduces cost without quality loss
-**Hypothesis:** H0: no change in effective_tokens. H1: concise reduces tokens by >=15%
+**Hypothesis:** H0: no change in aic. H1: concise reduces AIC by >=15%
**Guardrail metrics:**
- `success_rate` >=0.95
@@ -196,8 +196,8 @@ Tracking issue: [#1234](https://github.com/owner/repo/issues/1234)
|---|---|---|---|
| `variants` | `string[]` | ✅ | Array of two or more variant strings |
| `description` | `string` | | Human-readable explanation of what the experiment tests |
-| `hypothesis` | `string` | | Null and alternative hypothesis (e.g. `"H0: no change. H1: concise reduces tokens by >=15%"`) |
-| `metric` | `string` | | Primary metric to observe (e.g. `effective_tokens`, `duration_ms`) |
+| `hypothesis` | `string` | | Null and alternative hypothesis (e.g. `"H0: no change. H1: concise reduces AIC by >=15%"`) |
+| `metric` | `string` | | Primary metric to observe (e.g. `aic`, `duration_ms`) |
| `secondary_metrics` | `string[]` | | Additional metrics to track alongside the primary metric |
| `guardrail_metrics` | `object[]` | | List of `{name, threshold}` pairs that must not degrade. Threshold is a comparison expression like `>=0.95` or `==0` |
| `min_samples` | `integer` | | Minimum runs per variant required before statistical analysis is considered reliable. The step summary shows a progress bar toward this target. |
diff --git a/docs/src/content/docs/guides/using-at-scale.mdx b/docs/src/content/docs/guides/using-at-scale.mdx
index 56be65a7643..e30770cb7ed 100644
--- a/docs/src/content/docs/guides/using-at-scale.mdx
+++ b/docs/src/content/docs/guides/using-at-scale.mdx
@@ -75,7 +75,6 @@ Running agentic workflows at scale consumes compute and AI inference tokens. Use
- [Rate Limiting Controls](/gh-aw/reference/rate-limiting-controls/) — cap per-user and per-window run counts to prevent runaway spend
- [Cost Management](/gh-aw/reference/cost-management/) — track and budget AI Credits (AIC) across workflows
-- [Effective Tokens Specification](/gh-aw/specs/effective-tokens-specification/) — legacy token-count calculation details
## OpenTelemetry
diff --git a/docs/src/content/docs/index.mdx b/docs/src/content/docs/index.mdx
index 7f6deb8d496..70d9978d6ec 100644
--- a/docs/src/content/docs/index.mdx
+++ b/docs/src/content/docs/index.mdx
@@ -101,7 +101,7 @@ See the [Security Architecture](/gh-aw/introduction/architecture/) for a full br
Cost control starts with visibility. Use `gh aw logs` and `gh aw audit` to find runs consuming the most time, tokens, and AI Credits (AIC), then tighten prompts, triggers, and model choices before spend drifts upward.
-`max-effective-tokens` gives each run a hard budget, while [OpenTelemetry](/gh-aw/reference/open-telemetry/) exports traces and token data to OTLP backends for dashboards, alerting, and cost analysis. For optimization over time, compare cost with [outcomes](/gh-aw/reference/outcomes/) so lower spend still produces useful accepted results.
+`max-ai-credits` gives each run a hard budget, while [OpenTelemetry](/gh-aw/reference/open-telemetry/) exports traces and token data to OTLP backends for dashboards, alerting, and cost analysis. For optimization over time, compare cost with [outcomes](/gh-aw/reference/outcomes/) so lower spend still produces useful accepted results.
@@ -110,8 +110,8 @@ Cost control starts with visibility. Use `gh aw logs` and `gh aw audit` to find
Export workflow traces to OTLP backends for dashboards, alerts, and spend analysis
-
- Cap runaway runs with max-effective-tokens and optimize around effective-token usage
+
+ Cap runaway runs with max-ai-credits and optimize around AI Credits usage
diff --git a/docs/src/content/docs/reference/compiler-enterprise-environment-controls.md b/docs/src/content/docs/reference/compiler-enterprise-environment-controls.md
index c338aa7a652..c2907fc9632 100644
--- a/docs/src/content/docs/reference/compiler-enterprise-environment-controls.md
+++ b/docs/src/content/docs/reference/compiler-enterprise-environment-controls.md
@@ -11,7 +11,7 @@ Use these variables to set organization- or repository-wide defaults without edi
| Variable | Source | Purpose | Applies when |
| --- | --- | --- | --- |
-| `GH_AW_DEFAULT_MAX_EFFECTIVE_TOKENS` | Compiler process environment | Default AWF `apiProxy.maxEffectiveTokens` budget | `max-effective-tokens` is not set in frontmatter |
+| `GH_AW_DEFAULT_MAX_AI_CREDITS` | Compiler process environment | Default AWF `apiProxy.maxAiCredits` budget | `max-ai-credits` is not set in frontmatter |
| `GH_AW_DEFAULT_MAX_DAILY_AI_CREDITS` | Compiler process environment | Default `max-daily-ai-credits` guardrail | `max-daily-ai-credits` is not set in frontmatter |
| `GH_AW_DEFAULT_MAX_TURNS` | Compiler process environment | Default top-level `max-turns` | `max-turns` is not set in frontmatter and the selected engine supports max-turns |
| `GH_AW_DEFAULT_TIMEOUT_MINUTES` | Compiler process environment | Default top-level `timeout-minutes` | `timeout-minutes` is not set in frontmatter |
@@ -23,7 +23,7 @@ Use these variables to set organization- or repository-wide defaults without edi
Use `gh aw env get` and `gh aw env update` to manage these
variables in batch at repo, org, or enterprise scope. The defaults file uses
-`default_`-prefixed keys such as `default_max_effective_tokens`, `default_max_daily_ai_credits`, `default_timeout_minutes`,
+`default_`-prefixed keys such as `default_max_ai_credits`, `default_max_daily_ai_credits`, `default_timeout_minutes`,
`default_model_copilot`, and `default_utc`.
## Project Timezone
@@ -53,17 +53,17 @@ For model selection, precedence is:
3. `GH_AW_DEFAULT_MODEL_*`
4. Built-in compiler fallback
-For max effective tokens, precedence is:
+For max AI credits, precedence is:
-1. `max-effective-tokens` in workflow frontmatter
-2. `GH_AW_DEFAULT_MAX_EFFECTIVE_TOKENS`
+1. `max-ai-credits` in workflow frontmatter
+2. `GH_AW_DEFAULT_MAX_AI_CREDITS`
3. Built-in compiler default
-A negative `GH_AW_DEFAULT_MAX_EFFECTIVE_TOKENS` disables AWF token steering and
-omits the budget limit when frontmatter does not set `max-effective-tokens`.
+A negative `GH_AW_DEFAULT_MAX_AI_CREDITS` disables AWF budget steering and
+omits the budget limit when frontmatter does not set `max-ai-credits`.
Positive values also accept `K`/`M` suffixes such as `100M`.
-For daily effective-token workflow guardrails, precedence is:
+For daily AI credits workflow guardrails, precedence is:
1. `max-daily-ai-credits` in workflow frontmatter
2. `GH_AW_DEFAULT_MAX_DAILY_AI_CREDITS`
@@ -104,17 +104,17 @@ Set an org-wide Codex model fallback:
gh variable set GH_AW_DEFAULT_MODEL_CODEX --org my-org --body "gpt-5.5"
```
-Set an org-wide default max-effective-tokens guardrail:
+Set an org-wide default max-ai-credits guardrail:
```bash
-gh variable set GH_AW_DEFAULT_MAX_EFFECTIVE_TOKENS --org my-org --body "15M"
+gh variable set GH_AW_DEFAULT_MAX_AI_CREDITS --org my-org --body "15M"
```
```bash
-gh variable set GH_AW_DEFAULT_MAX_EFFECTIVE_TOKENS --org my-org --body "100M"
+gh variable set GH_AW_DEFAULT_MAX_AI_CREDITS --org my-org --body "100M"
```
-Set an org-wide default daily workflow ET guardrail:
+Set an org-wide default daily workflow AIC guardrail:
```bash
gh variable set GH_AW_DEFAULT_MAX_DAILY_AI_CREDITS --org my-org --body "15M"
diff --git a/docs/src/content/docs/reference/cost-management.md b/docs/src/content/docs/reference/cost-management.md
index b0dab5dbb77..1fabb4971b2 100644
--- a/docs/src/content/docs/reference/cost-management.md
+++ b/docs/src/content/docs/reference/cost-management.md
@@ -22,9 +22,6 @@ AIC is shown in the `gh aw logs` output table under the **AIC** column, in audit
> [!NOTE]
> AIC values are computed on a best-effort basis using provider pricing data embedded in gh-aw and may not exactly match your provider's actual billing. Always verify charges in your provider's billing dashboard.
-> [!NOTE]
-> Effective Tokens (ET) remain available for backward compatibility. Prefer AIC for cost monitoring, including Copilot workflows. See [Effective Tokens Specification](/gh-aw/specs/effective-tokens-specification/) for the ET definition.
-
## Cost Components
### GitHub Actions Minutes
@@ -99,7 +96,7 @@ Useful episode fields for usage analysis:
| Field | Meaning |
|-------|---------|
| `total_runs` | Workflow runs in the logical execution |
-| `total_tokens` / `total_effective_tokens` | Raw and effective token aggregates |
+| `total_tokens` | Raw token aggregate across grouped runs |
| `total_aic` | Total AI Credits (AIC) for the episode; preferred cost metric |
| `total_duration` | Wall-clock duration across grouped runs |
| `primary_workflow` | Main workflow label |
@@ -143,9 +140,8 @@ The exported spans include workflow and model metadata such as
`gen_ai.usage.input_tokens`, and
`gen_ai.usage.output_tokens`. Use these attributes to group usage
by workflow, engine, model, repository, or team in the backend of
-your choice. For inference cost, the `llm.token.effective_total`
-span attribute carries Effective Tokens; AIC is derived from the
-raw token counts in your observability backend using provider
+your choice. For inference cost, AIC is derived from the raw
+token counts in your observability backend using provider
pricing.
OpenTelemetry is most useful for answering questions such as:
@@ -216,20 +212,18 @@ Reserve frontier models (GPT-5, Claude Sonnet, etc.) for complex tasks. Use ligh
Inference cost scales with prompt size. Write focused prompts, avoid whole-file reads when only a few lines matter, cap result counts in tool calls, and use `imports` to compose a smaller subset of prompt sections at runtime.
-### Cap Effective Tokens per Run
+### Cap AI Credits per Run
-Use the top-level `max-effective-tokens` frontmatter field to cap
-the effective-token budget for a single workflow run. This provides
-a hard stop for unusually expensive runs and a consistent cost
-guardrail across all supported engines. The field accepts plain
-integers or `K`/`M` suffixes such as `100M`.
+Use the top-level `max-ai-credits` frontmatter field to cap
+the AI Credits (AIC) budget for a single workflow run. This
+provides a hard stop for unusually expensive runs and a consistent
+cost guardrail across all supported engines. The field accepts
+plain integers or `K`/`M` suffixes such as `100M`.
```aw wrap
-max-effective-tokens: 5M
+max-ai-credits: 5M
```
-Effective tokens are the normalized usage metric described in the
-[Effective Tokens Specification](/gh-aw/specs/effective-tokens-specification/) (deprecated in favor of AIC for non-Copilot engines).
When the budget is approached, gh-aw emits steering warnings before
the run reaches the limit. Set a negative value only when budget
enforcement must be disabled explicitly.
@@ -313,7 +307,7 @@ gh aw env get defaults.yml --scope org --org MY_ORG
2. Update and apply shared defaults in batch:
```yaml
-default_max_effective_tokens: "5M"
+default_max_ai_credits: "5M"
default_max_daily_ai_credits: "15M"
default_model_copilot: "gpt-5-mini"
default_model_claude: "claude-haiku-4-5"
@@ -328,13 +322,14 @@ gh aw env update defaults.yml --scope org --org MY_ORG
Pass `--yes` to skip the prompt in automation, or `--dry-run` to preview
without changing any variables. Set a field to `null` to delete the
corresponding variable from the target scope. Unknown YAML keys are rejected,
-`default_max_turns` / `default_timeout_minutes` must be positive integers, and
-`default_max_effective_tokens` / `default_max_daily_ai_credits` must be
-non-zero integers (negative values disable the corresponding guardrail).
+`default_max_turns` / `default_timeout_minutes` must be positive integers,
+`default_max_ai_credits` must be a positive integer, and
+`default_max_daily_ai_credits` must be a non-zero integer
+(a negative value disables the daily guardrail).
3. If you compile workflows in CI, pass compiler-read defaults into
the compiler process environment (for example via `${{ vars.* }}`):
-`GH_AW_DEFAULT_MAX_EFFECTIVE_TOKENS`,
+`GH_AW_DEFAULT_MAX_AI_CREDITS`,
`GH_AW_DEFAULT_MAX_DAILY_AI_CREDITS`,
`GH_AW_DEFAULT_MAX_TURNS`,
`GH_AW_DEFAULT_TIMEOUT_MINUTES`,
@@ -382,7 +377,7 @@ See [Schedule Syntax](/gh-aw/reference/schedule-syntax/) for the full fuzzy sche
### Batch Instead of Reacting to Events
-Reactive triggers like `issues` or `pull_request` launch one agent run per event. When many events arrive in a short window, that adds up quickly. A scheduled batch run groups all pending items into a single invocation — and because the shared system prompt and instructions are sent once for the whole batch, AI providers can cache that context across items, further reducing effective token usage.
+Reactive triggers like `issues` or `pull_request` launch one agent run per event. When many events arrive in a short window, that adds up quickly. A scheduled batch run groups all pending items into a single invocation — and because the shared system prompt and instructions are sent once for the whole batch, AI providers can cache that context across items, further reducing AI Credits consumption.
```aw wrap
description: Nightly issue triage (replaces reactive issues trigger)
@@ -480,7 +475,7 @@ tools:
| Signal | Automatic action |
|--------|-----------------|
| High AIC per run (Claude/Codex) | Switch to a smaller model (`gpt-4.1-mini`, `claude-haiku-4-5`) |
-| High effective tokens per run (Copilot) | Switch to a smaller model or reduce context size |
+| High AIC per run (Copilot) | Switch to a smaller model or reduce context size |
| High turn count per run | Set `max-turns` to cap iterations and prevent runaway loops |
| Frequent runs with no safe-output produced | Add or tighten `skip-if-match` |
| Long queue times due to concurrency | Lower `user-rate-limit.max-runs-per-window` or add a `concurrency` group |
@@ -511,7 +506,6 @@ These are rough estimates to help with budgeting. Actual costs vary by prompt si
- [Audit Commands](/gh-aw/reference/audit/) - Single-run analysis, diff, and cross-run reporting
- [Artifacts](/gh-aw/reference/artifacts/) - Artifact names, directory structures, and token usage file locations
-- [Effective Tokens Specification](/gh-aw/specs/effective-tokens-specification/) - How effective token counts are computed (deprecated; AIC is now preferred for non-Copilot engines)
- [OpenTelemetry](/gh-aw/reference/open-telemetry/) - Exporting workflow telemetry to centralized observability backends
- [Triggers](/gh-aw/reference/triggers/) - Configuring workflow triggers and skip conditions
- [Rate Limiting Controls](/gh-aw/reference/rate-limiting-controls/) - Preventing runaway workflows
diff --git a/docs/src/content/docs/reference/engines.md b/docs/src/content/docs/reference/engines.md
index 55ee1aab4ff..3f3aa7b17d0 100644
--- a/docs/src/content/docs/reference/engines.md
+++ b/docs/src/content/docs/reference/engines.md
@@ -44,7 +44,7 @@ Not all features are available across all engines. The table below summarizes pe
| `engine.harness` (custom harness script) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Tools allowlist | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ |
-`max-runs` (default `500`) and `max-effective-tokens` (default `25M`) are top-level frontmatter fields supported by all engines. `max-turns` limits Claude iterations per run; `max-continuations` enables Copilot autopilot mode. Codex `web-search` is opt-in via `tools: web-search:`; other engines use a third-party MCP server — see [Using Web Search](/gh-aw/reference/web-search/). `engine.agent`, `engine.bare`, and `engine.harness` are described below.
+`max-runs` (default `500`) and `max-ai-credits` (default `25M`) are top-level frontmatter fields supported by all engines. `max-turns` limits Claude iterations per run; `max-continuations` enables Copilot autopilot mode. Codex `web-search` is opt-in via `tools: web-search:`; other engines use a third-party MCP server — see [Using Web Search](/gh-aw/reference/web-search/). `engine.agent`, `engine.bare`, and `engine.harness` are described below.
## Extended Coding Agent Configuration
@@ -359,7 +359,7 @@ Defaults to `false`.
### Custom Token Weights (`token-weights`)
-Override the built-in token cost multipliers used when computing [Effective Tokens](/gh-aw/specs/effective-tokens-specification/). Useful when your workflow uses a custom model not in the built-in list, or when you want to adjust the relative cost ratios for your use case.
+Override the built-in token cost multipliers used when computing the AI Credits (AIC) cost for a run. Useful when your workflow uses a custom model not in the built-in list, or when you want to adjust the relative cost ratios for your use case.
```yaml wrap
engine:
diff --git a/docs/src/content/docs/reference/environment-variables.md b/docs/src/content/docs/reference/environment-variables.md
index ea85a2e17c7..7ecddc9fdf6 100644
--- a/docs/src/content/docs/reference/environment-variables.md
+++ b/docs/src/content/docs/reference/environment-variables.md
@@ -177,7 +177,7 @@ COPILOT_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || vars.GH_AW_DEFAULT_MODEL_CO
Use `gh aw env get` / `gh aw env update` to batch-manage
these `GH_AW_DEFAULT_*` variables at repo, org, or enterprise scope with
-`default_`-prefixed YAML keys such as `default_max_effective_tokens`,
+`default_`-prefixed YAML keys such as `default_max_ai_credits`,
`default_max_daily_ai_credits`, and `default_model_copilot`.
### Agent runs
@@ -280,7 +280,7 @@ jobs:
- [Frontmatter Reference](/gh-aw/reference/frontmatter/) - Complete frontmatter configuration
- [Safe Outputs](/gh-aw/reference/safe-outputs/) - Safe output environment configuration
- [Sandbox](/gh-aw/reference/sandbox/) - Sandbox environment variables
-- [Compiler Enterprise Environment Controls](/gh-aw/reference/compiler-enterprise-environment-controls/) - Enterprise defaults for timeout, max-turns, detection model, model fallback, and max-effective-tokens guardrails
+- [Compiler Enterprise Environment Controls](/gh-aw/reference/compiler-enterprise-environment-controls/) - Enterprise defaults for timeout, max-turns, detection model, model fallback, and max-ai-credits guardrails
- [Cost Management](/gh-aw/reference/cost-management/) - Practical model and token guardrail rollout guidance
- [Tools](/gh-aw/reference/tools/) - MCP tool configuration and guard policies
- [MCP Scripts](/gh-aw/reference/mcp-scripts/) - MCP script tool configuration
diff --git a/docs/src/content/docs/reference/frontmatter.md b/docs/src/content/docs/reference/frontmatter.md
index 8cc0b709719..8a74100cbc0 100644
--- a/docs/src/content/docs/reference/frontmatter.md
+++ b/docs/src/content/docs/reference/frontmatter.md
@@ -227,22 +227,22 @@ Environment variables can be defined at multiple scopes (workflow, job, step, en
>
> Use engine-specific secret configuration instead of the `env:` section to pass secrets securely.
-### Effective Token Budget (`max-effective-tokens:`)
+### AI Credits Guardrail (`max-ai-credits:`)
-Sets the AWF effective-token budget used for cost enforcement. Defaults to `25M` when omitted. Token steering (budget-warning messages at 80%, 90%, 95%, and 99% of the budget) is enabled by default. Use plain integers or `K`/`M` suffixes such as `100000K` or `100M`. Set to a negative value to disable both budget enforcement and token steering.
+Sets the AWF AI Credits budget used for cost enforcement. Defaults to `25M` when omitted. Steering (budget-warning messages at 80%, 90%, 95%, and 99% of the budget) is enabled by default. Use plain integers or `K`/`M` suffixes such as `100000K` or `100M`. Set to a negative value to disable both budget enforcement and steering.
```yaml wrap
-max-effective-tokens: 5M
+max-ai-credits: 5M
```
```yaml wrap
# Equivalent shorthand
-max-effective-tokens: 100M
+max-ai-credits: 100M
```
```yaml wrap
-# Disable budget enforcement and token steering
-max-effective-tokens: -1
+# Disable budget enforcement and steering
+max-ai-credits: -1
```
### Daily Per-Workflow AI Credits Guardrail (`max-daily-ai-credits:`)
diff --git a/docs/src/content/docs/reference/glossary.md b/docs/src/content/docs/reference/glossary.md
index b6c47809432..5475ee6e472 100644
--- a/docs/src/content/docs/reference/glossary.md
+++ b/docs/src/content/docs/reference/glossary.md
@@ -491,16 +491,14 @@ Optional workflow metadata for categorization and organization. Enables filterin
A short human-friendly name (such as `sonnet` or `mini`) that gh-aw resolves to the best available concrete model at compile time. Aliases are defined as ordered lists of provider-scoped glob patterns; the first pattern that matches an available model wins. Meta-aliases reference other aliases and are resolved recursively. Built-in vendor aliases and meta-aliases are listed in the [Model Aliases & Multipliers Reference](/gh-aw/reference/model-tables/). Custom aliases can be defined in workflow frontmatter using the [Model Alias Format Specification](/gh-aw/specs/model-alias-specification/).
-### Max Effective Tokens (`max-effective-tokens`)
+### Max AI Credits (`max-ai-credits`)
-A top-level frontmatter field that caps the total effective-token (ET) budget the AWF proxy will spend within a single workflow run. Effective tokens are weighted by model multipliers and are the primary cost proxy for Copilot. Applies to all engines and maps to `apiProxy.maxEffectiveTokens` in the compiled lock file. Defaults to `25M` when omitted. Accepts an integer, an optional `K`/`M` suffix string (for example, `100M`), or a GitHub Actions expression that resolves to an integer at runtime. Example:
+A top-level frontmatter field that caps the total AI Credits (AIC) the AWF proxy will spend within a single workflow run. Applies to all engines and maps to `apiProxy.maxEffectiveTokens` in the compiled lock file. Defaults to `25M` when omitted. Accepts an integer, an optional `K`/`M` suffix string (for example, `100M`), or a GitHub Actions expression that resolves to an integer at runtime. Example:
```aw wrap
-max-effective-tokens: 5M
+max-ai-credits: 5M
```
-See [Effective Tokens Specification](/gh-aw/specs/effective-tokens-specification/) and [Cost Management](/gh-aw/reference/cost-management/).
-
### Max Daily AI Credits (`max-daily-ai-credits`)
A top-level frontmatter field that sets a 24-hour AI Credits cap for a single workflow, aggregated across recent runs of the same workflow triggered by the same user. When the activation job detects that the previous 24 hours already exceed this threshold, it warns, creates an issue, skips the agent job, and reports a specialized failure. Disabled by default when omitted. Set to `-1` to explicitly disable it. Accepts plain integers or `K`/`M` suffixes (e.g., `100M`). Skipped for `workflow_call`, `repository_dispatch`, and `workflow_dispatch` runs carrying internal `aw_context` dispatch metadata. Example:
@@ -693,13 +691,9 @@ A feature of `gh aw logs` that aggregates firewall, MCP, and metrics data across
A CLI command that orchestrates full workflow rollout to a target repository in a single invocation. `gh aw deploy` clones the target repository, runs `update` to refresh any sourced workflows, runs `add` to install the requested workflows, runs `compile --purge` to regenerate lock files and remove stale outputs, then opens a pull request with all changes for review. Replaces the manual sequence of `clone → update → add → compile → pr` commands and skips the add phase for workflows that already carry a `source:` frontmatter field to prevent duplicate installations. Accepts `--repo` to specify the target repository and `--cool-down` to set the default scheduling interval. See [CLI Reference](/gh-aw/setup/cli/).
-### Effective Tokens
-
-A weighted token count that normalizes raw API token usage into a single comparable value for usage monitoring. Computed by applying cache and output multipliers to each token category (input, output, cache read, cache write) and summing the results. Appears in audit reports, `gh aw logs` output, and safe-output message footers (as `{effective_tokens}` and `{effective_tokens_formatted}`). See [Effective Tokens Specification](/gh-aw/specs/effective-tokens-specification/).
-
### Forecast (`gh aw forecast`)
-An experimental CLI command that projects future Effective Token consumption using a Monte Carlo simulation. It samples historical workflow runs, applies a Poisson-bootstrap algorithm to model run frequency, and returns P10/P50/P90 percentile estimates over a configurable time horizon. Supports both local (`.github/workflows/`) and remote (`--repo`) discovery modes. Output is available as a console table or machine-readable JSON (`--json`). Useful for capacity planning, budget governance, and detecting cost regressions before they occur. See [Forecast Specification](/gh-aw/specs/forecast-specification/).
+An experimental CLI command that projects future AI Credits (AIC) consumption using a Monte Carlo simulation. It samples historical workflow runs, applies a Poisson-bootstrap algorithm to model run frequency, and returns P10/P50/P90 percentile estimates over a configurable time horizon. Supports both local (`.github/workflows/`) and remote (`--repo`) discovery modes. Output is available as a console table or machine-readable JSON (`--json`). Useful for capacity planning, budget governance, and detecting cost regressions before they occur. See [Forecast Specification](/gh-aw/specs/forecast-specification/).
### Time Between Turns (TBT)
@@ -759,11 +753,11 @@ The causal graph of edges between workflow runs computed by `gh aw logs --json`.
### Episode
-A deterministic rollup of related workflow runs that belong to a single logical execution. When an orchestrator dispatches workers, all participating runs are grouped into one episode with aggregate metrics including `total_runs`, `total_tokens`, `total_effective_tokens`, and `risky_node_count`. Available under `.episodes[]` in `gh aw logs --json` output. Episodes are more useful than per-run metrics when one logical job spans multiple workflow runs. For Copilot usage analysis, prefer `total_effective_tokens`.
+A deterministic rollup of related workflow runs that belong to a single logical execution. When an orchestrator dispatches workers, all participating runs are grouped into one episode with aggregate metrics including `total_runs`, `total_tokens`, `total_aic`, and `risky_node_count`. Available under `.episodes[]` in `gh aw logs --json` output. Episodes are more useful than per-run metrics when one logical job spans multiple workflow runs. For cost analysis, prefer `total_aic` (AI Credits).
```bash
gh aw logs --start-date -30d --json | \
- jq '.episodes[] | {id: .episode_id, workflow: .primary_workflow, effective_tokens: .total_effective_tokens}'
+ jq '.episodes[] | {id: .episode_id, workflow: .primary_workflow, aic: .total_aic}'
```
### WebAssembly (Wasm)
@@ -850,7 +844,7 @@ A system-injected environment variable containing the comma-separated list of do
### `GH_AW_DEFAULT_*`
-A family of environment variables set in the compiler process environment or as GitHub Actions `vars.*` to apply organization- or repository-wide defaults without editing individual workflow frontmatter. Compiler-process variables (`GH_AW_DEFAULT_MAX_EFFECTIVE_TOKENS`, `GH_AW_DEFAULT_MAX_DAILY_AI_CREDITS`, `GH_AW_DEFAULT_MAX_TURNS`, `GH_AW_DEFAULT_TIMEOUT_MINUTES`, `GH_AW_DEFAULT_DETECTION_MODEL`) inject defaults at compile time; runtime repository variables (`GH_AW_DEFAULT_MODEL_COPILOT`, `GH_AW_DEFAULT_MODEL_CLAUDE`, `GH_AW_DEFAULT_MODEL_CODEX`) provide model fallbacks when per-run model overrides are unset. Frontmatter settings always take precedence over `GH_AW_DEFAULT_*`. Managed in batch via `gh aw env`. See [Compiler Enterprise Environment Controls](/gh-aw/reference/compiler-enterprise-environment-controls/).
+A family of environment variables set in the compiler process environment or as GitHub Actions `vars.*` to apply organization- or repository-wide defaults without editing individual workflow frontmatter. Compiler-process variables (`GH_AW_DEFAULT_MAX_AI_CREDITS`, `GH_AW_DEFAULT_MAX_DAILY_AI_CREDITS`, `GH_AW_DEFAULT_MAX_TURNS`, `GH_AW_DEFAULT_TIMEOUT_MINUTES`, `GH_AW_DEFAULT_DETECTION_MODEL`) inject defaults at compile time; runtime repository variables (`GH_AW_DEFAULT_MODEL_COPILOT`, `GH_AW_DEFAULT_MODEL_CLAUDE`, `GH_AW_DEFAULT_MODEL_CODEX`) provide model fallbacks when per-run model overrides are unset. Frontmatter settings always take precedence over `GH_AW_DEFAULT_*`. Managed in batch via `gh aw env`. See [Compiler Enterprise Environment Controls](/gh-aw/reference/compiler-enterprise-environment-controls/).
### `GH_HOST`
diff --git a/docs/src/content/docs/reference/network.md b/docs/src/content/docs/reference/network.md
index 7733295db3f..935f20c7ae2 100644
--- a/docs/src/content/docs/reference/network.md
+++ b/docs/src/content/docs/reference/network.md
@@ -60,12 +60,6 @@ network:
- "https://*.api.example.com" # HTTPS wildcard
```
-**Compiled to AWF:**
-
-```bash
---allow-domains ...,example.org,http://legacy.example.com,https://secure.api.example.com,...
-```
-
## Content Sanitization
The `network:` configuration also controls which domains are allowed in sanitized content. URLs from domains not in the allowed list are replaced with `(redacted)` to prevent potential data exfiltration through untrusted links.
@@ -219,18 +213,6 @@ network:
**Security**: SSL bump intercepts and decrypts HTTPS as a man-in-the-middle — only enable when URL-level filtering is necessary, and craft `allow-urls` patterns carefully to avoid breaking legitimate connections. Requires AWF v0.9.0+ and does not apply to Sandbox Runtime (SRT). See [Sandbox Configuration](/gh-aw/reference/sandbox/) for full AWF options.
-### Effective Token Steering
-
-The AWF API proxy automatically injects budget-warning system messages as the run approaches its effective-token budget. Warnings fire at 80%, 90%, 95%, and 99% of the configured `max-effective-tokens`, giving the agent a chance to wrap up work before the budget is exhausted. Token steering requires AWF `v0.25.44` or later; for older pinned versions the setting is silently dropped at compile time.
-
-To disable token steering (and budget enforcement entirely), set `max-effective-tokens` to a negative value:
-
-```yaml wrap
-max-effective-tokens: -1
-```
-
-See [Max Effective Tokens](/gh-aw/reference/glossary/#max-effective-tokens-max-effective-tokens) for budget configuration.
-
### Disabling the Firewall
The firewall is enabled by default via `sandbox.agent: awf`. When disabled, network permissions still apply for content sanitization but the agent can make unrestricted network requests. Only disable during development or when AWF is incompatible with your workflow; keep it enabled in production.
diff --git a/pkg/actionpins/data/action_pins.json b/pkg/actionpins/data/action_pins.json
index 385db2d992f..159b83937ff 100644
--- a/pkg/actionpins/data/action_pins.json
+++ b/pkg/actionpins/data/action_pins.json
@@ -173,10 +173,20 @@
"version": "v4.36.0",
"sha": "7211b7c8077ea37d8641b6271f6a365a22a5fbfa"
},
- "github/gh-aw-actions/setup@v0.76.1": {
+ "github/gh-aw-actions/setup-cli@v0.78.2": {
+ "repo": "github/gh-aw-actions/setup-cli",
+ "version": "v0.78.2",
+ "sha": "268bf92726cb8153337c07166f382ee46e4fd897"
+ },
+ "github/gh-aw-actions/setup@v0.78.2": {
"repo": "github/gh-aw-actions/setup",
- "version": "v0.76.1",
- "sha": "46d564922b082d0db93244972e8005ea6904ee5f"
+ "version": "v0.78.2",
+ "sha": "268bf92726cb8153337c07166f382ee46e4fd897"
+ },
+ "github/gh-aw/actions/setup-cli@v0.78.2": {
+ "repo": "github/gh-aw/actions/setup-cli",
+ "version": "v0.78.2",
+ "sha": "a7d4043a8224182262356a32931099b76fd332eb"
},
"github/stale-repos@v9.0.14": {
"repo": "github/stale-repos",
diff --git a/pkg/workflow/data/action_pins.json b/pkg/workflow/data/action_pins.json
index 385db2d992f..159b83937ff 100644
--- a/pkg/workflow/data/action_pins.json
+++ b/pkg/workflow/data/action_pins.json
@@ -173,10 +173,20 @@
"version": "v4.36.0",
"sha": "7211b7c8077ea37d8641b6271f6a365a22a5fbfa"
},
- "github/gh-aw-actions/setup@v0.76.1": {
+ "github/gh-aw-actions/setup-cli@v0.78.2": {
+ "repo": "github/gh-aw-actions/setup-cli",
+ "version": "v0.78.2",
+ "sha": "268bf92726cb8153337c07166f382ee46e4fd897"
+ },
+ "github/gh-aw-actions/setup@v0.78.2": {
"repo": "github/gh-aw-actions/setup",
- "version": "v0.76.1",
- "sha": "46d564922b082d0db93244972e8005ea6904ee5f"
+ "version": "v0.78.2",
+ "sha": "268bf92726cb8153337c07166f382ee46e4fd897"
+ },
+ "github/gh-aw/actions/setup-cli@v0.78.2": {
+ "repo": "github/gh-aw/actions/setup-cli",
+ "version": "v0.78.2",
+ "sha": "a7d4043a8224182262356a32931099b76fd332eb"
},
"github/stale-repos@v9.0.14": {
"repo": "github/stale-repos",
diff --git a/pkg/workflow/engine.go b/pkg/workflow/engine.go
index 45ddc9b1b1c..e64cbd4e4ee 100644
--- a/pkg/workflow/engine.go
+++ b/pkg/workflow/engine.go
@@ -142,15 +142,6 @@ type EngineNetworkConfig struct {
Network *NetworkPermissions
}
-// GetMaxEffectiveTokens returns the configured engine ET budget, falling back to the default.
-// A negative value means "disabled" (no budget enforcement, no token steering).
-func (e *EngineConfig) GetMaxEffectiveTokens() int64 {
- if e == nil || e.MaxEffectiveTokens == 0 {
- return constants.DefaultMaxEffectiveTokens
- }
- return e.MaxEffectiveTokens
-}
-
// GetMaxAICredits returns the configured engine AI credits budget, falling back to the default.
func (e *EngineConfig) GetMaxAICredits() int64 {
if e == nil || e.MaxAICredits == 0 {
diff --git a/pkg/workflow/testdata/TestWasmGolden_AllEngines/copilot.golden b/pkg/workflow/testdata/TestWasmGolden_AllEngines/copilot.golden
index 59d86cdab42..fbba71a1f31 100644
--- a/pkg/workflow/testdata/TestWasmGolden_AllEngines/copilot.golden
+++ b/pkg/workflow/testdata/TestWasmGolden_AllEngines/copilot.golden
@@ -513,6 +513,7 @@ jobs:
GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 10
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/pkg/workflow/testdata/TestWasmGolden_CompileFixtures/basic-copilot.golden b/pkg/workflow/testdata/TestWasmGolden_CompileFixtures/basic-copilot.golden
index 13d6315e426..56542c343e7 100644
--- a/pkg/workflow/testdata/TestWasmGolden_CompileFixtures/basic-copilot.golden
+++ b/pkg/workflow/testdata/TestWasmGolden_CompileFixtures/basic-copilot.golden
@@ -513,6 +513,7 @@ jobs:
GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 10
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/pkg/workflow/testdata/TestWasmGolden_CompileFixtures/playwright-cli-mode.golden b/pkg/workflow/testdata/TestWasmGolden_CompileFixtures/playwright-cli-mode.golden
index ca809fd348e..ca64832c665 100644
--- a/pkg/workflow/testdata/TestWasmGolden_CompileFixtures/playwright-cli-mode.golden
+++ b/pkg/workflow/testdata/TestWasmGolden_CompileFixtures/playwright-cli-mode.golden
@@ -533,6 +533,7 @@ jobs:
GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 20
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/pkg/workflow/testdata/TestWasmGolden_CompileFixtures/smoke-copilot.golden b/pkg/workflow/testdata/TestWasmGolden_CompileFixtures/smoke-copilot.golden
index 41fdd5dcc4f..5f1b907942f 100644
--- a/pkg/workflow/testdata/TestWasmGolden_CompileFixtures/smoke-copilot.golden
+++ b/pkg/workflow/testdata/TestWasmGolden_CompileFixtures/smoke-copilot.golden
@@ -769,6 +769,7 @@ jobs:
GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 15
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/pkg/workflow/testdata/TestWasmGolden_CompileFixtures/with-imports.golden b/pkg/workflow/testdata/TestWasmGolden_CompileFixtures/with-imports.golden
index 6cf127db4a7..35d2f4d2163 100644
--- a/pkg/workflow/testdata/TestWasmGolden_CompileFixtures/with-imports.golden
+++ b/pkg/workflow/testdata/TestWasmGolden_CompileFixtures/with-imports.golden
@@ -514,6 +514,7 @@ jobs:
GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_TIMEOUT_MINUTES: 10
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
diff --git a/scratchpad/token-budget-guidelines.md b/scratchpad/token-budget-guidelines.md
index 8b6ab04db19..ada7e16abc2 100644
--- a/scratchpad/token-budget-guidelines.md
+++ b/scratchpad/token-budget-guidelines.md
@@ -378,7 +378,7 @@ Explicit instructions in workflow prompts to reduce token consumption:
**Configuration (2026-05-20):**
- `timeout-minutes: 30`
-- `max-effective-tokens: 40000000` (40M — raised above default; meta-orchestrator doing deep cross-agent analysis)
+- `max-ai-credits: 40000000` (40M — raised above default; meta-orchestrator doing deep cross-agent analysis)
- `file-glob` narrowed from `"**"` to `["*.json", "*.md"]` — reduces repo-memory context load
- Added `## Token Budget Guidelines` section in both caveman and verbose prompt variants:
- Analyze top 20 agents by output volume; skip zero-output agents
@@ -399,7 +399,7 @@ Explicit instructions in workflow prompts to reduce token consumption:
**Configuration (2026-05-20):**
- `timeout-minutes: 30`
-- `max-effective-tokens: 30000000` (30M — raised above default; monitors all workflows daily)
+- `max-ai-credits: 30000000` (30M — raised above default; monitors all workflows daily)
- `file-glob` narrowed from `"**"` to `["*.json", "*.md"]` — reduces repo-memory context load
- Added `## Token Budget Guidelines` section in prompt:
- Use pre-computed `failing-workflows.json` from pre-agent step
@@ -417,7 +417,7 @@ Explicit instructions in workflow prompts to reduce token consumption:
**Configuration (2026-05-20):**
- `timeout-minutes: 30`
-- `max-effective-tokens: 10000000` (10M — firm ceiling for 6-hourly classification workflow)
+- `max-ai-credits: 10000000` (10M — firm ceiling for 6-hourly classification workflow)
- `file-glob` narrowed from `"**"` to `["*.json", "*.md"]` — reduces repo-memory context load
**Budget Target:**
@@ -425,7 +425,7 @@ Explicit instructions in workflow prompts to reduce token consumption:
- **Alert threshold**: >5M tokens
-| Workflow | Target Tokens | Alert Threshold | Critical Threshold | `max-effective-tokens` |
+| Workflow | Target Tokens | Alert Threshold | Critical Threshold | `max-ai-credits` |
|----------|--------------|-----------------|-------------------|------------------------|
| Agent Persona Explorer | 120K-180K | >200K | >250K | (default) |
| CI Cleaner | 68K-90K | >120K | >150K | (default) |
diff --git a/specs/aw-harness.md b/specs/aw-harness.md
index 5e16a633d11..6be2a26dab4 100644
--- a/specs/aw-harness.md
+++ b/specs/aw-harness.md
@@ -305,7 +305,7 @@ An `engine: aw` workflow document **MUST** include a YAML frontmatter block conf
> # ── Harness config (optional) ───────────────────────────────
> harness:
> budget:
-> max-effective-tokens: 100000
+> max-ai-credits: 100000
>
> context:
> compaction: summarize