Port gh-aw workflows from copilot to claude (CLAUDE_CODE_OAUTH_TOKEN)#274
Conversation
…_OAUTH_TOKEN Switch all 10 agentic workflows from engine: copilot to engine: claude, authenticating against an Anthropic Max/Teams subscription via CLAUDE_CODE_OAUTH_TOKEN. gh-aw does not support this token natively, so CI builds a patched gh-aw at the pinned tag. Patch (.github/gh-aw-patches/claude-oauth-token.patch, applied at v0.77.5): - required-secret + secret-validation: ANTHROPIC_API_KEY -> CLAUDE_CODE_OAUTH_TOKEN - agent-step env: ANTHROPIC_API_KEY -> CLAUDE_CODE_OAUTH_TOKEN - AWF firewall exclude list -> nil (the OAuth token has no api-proxy sidecar; it must stay in the agent container or the CLI reports apiKeySource: none) - EngineOptions Claude SecretName -> CLAUDE_CODE_OAUTH_TOKEN Model pins (Copilot dotted -> Anthropic dashed): - distillery-sync, sdd-execute-haiku: claude-haiku-4.5 -> claude-haiku-4-5 - sdd-execute-sonnet: claude-sonnet-4.6 -> claude-sonnet-4-6 - sdd-execute-opus: claude-opus-4.6 -> claude-opus-4-8 (current tier) - sample, sdd-dispatch, sdd-review, sdd-spec, sdd-triage, sdd-validate: unpinned, resolve via vars.GH_AW_MODEL_AGENT_CLAUDE CI (lint.yml compile gate + recompile-locks.yml auto-recompile): replace the stock `gh extension install github/gh-aw --pin` with a setup-go + build-patched step (clone pin, apply patch, ldflags -X main.version=v0.77.5), and invoke the standalone `gh-aw` binary. Stock gh-aw would regenerate ANTHROPIC_API_KEY locks and redden the stale-lock gate / clobber the OAuth locks on auto-recompile. Locks recompiled with the patched binary: zero ANTHROPIC_API_KEY, zero COPILOT_GITHUB_TOKEN, CLAUDE_CODE_OAUTH_TOKEN wired in every lock, token not in any AWF --exclude-env. Linux build reproduces these byte-for-byte. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
📝 WalkthroughSummary by CodeRabbit
WalkthroughThe PR migrates all agentic GitHub Actions workflows from GitHub Copilot CLI to Claude Code. A local patch renames the credential from ChangesCopilot → Claude Code engine migration
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 6
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (9)
.github/workflows/lint.yml (1)
77-77:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winUpdate the contributor hint to the patched compile command.
Line 77 still instructs
gh aw compile, but this repo now requires the patched localgh-awbinary path. Keeping the old hint will send contributors down a failing path.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/lint.yml at line 77, The error message on line 77 in the lint.yml workflow file instructs users to run 'gh aw compile', but this is outdated since the repo now requires using the patched local gh-aw binary instead. Update the echo statement to instruct contributors to use the correct patched local gh-aw binary path (typically something like ./gh-aw compile or similar, depending on the repo's setup) rather than the generic 'gh aw compile' command, so contributors follow the correct compilation process..github/workflows/distillery-sync.md (1)
27-29:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winAlign prose/verification references with the migrated Claude model naming.
Frontmatter now pins
claude-haiku-4-5(Line 34), but these sections still referenceGH_AW_DEFAULT_MODEL_COPILOTandclaude-haiku-4.5. Please update the text so operational guidance matches actual engine/model behavior.Also applies to: 33-34, 408-411
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/distillery-sync.md around lines 27 - 29, Update the documentation prose in `.github/workflows/distillery-sync.md` to align with the migrated Claude model naming. At lines 27-29, replace references to `GH_AW_DEFAULT_MODEL_COPILOT` and `claude-haiku-4.5` with the current model naming that matches the frontmatter specification of `claude-haiku-4-5`. Apply the same updates at lines 33-34 and lines 408-411, ensuring all text references to the Copilot model and engine naming are consistent with the actual configured model identifier throughout the document..github/workflows/sdd-triage.md (1)
18-32:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winUpdate the backstop comment to stop naming Copilot.
The
max-runsrationale still says Copilot lacks per-turnmax-turns, which is stale after the engine switch. Reword it generically so the comment matches the config.♻️ Suggested wording update
-# copilot does not support the per-turn `max-turns` field, so the +# the engine does not support the per-turn `max-turns` field, so the🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/sdd-triage.md around lines 18 - 32, The max-runs comment block in the sdd-triage.md file contains a stale reference to Copilot lacking per-turn max-turns support, which is no longer accurate after switching the engine to Claude. Remove or rephrase the sentence that specifically names Copilot and its limitations, and instead use generic language that explains why the invocation cap is the available lever without referencing any specific engine's capabilities or constraints..github/workflows/sdd-execute-opus.lock.yml (4)
17-20:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winUpdate the generated compile hint for the patched gh-aw flow.
This header still points contributors at stock
gh aw compile, but this PR requires the locally patched binary to regenerate locks without reverting to the old secret wiring. Update the generator/patch output or add the patched command here when regenerating.🛠️ Proposed generated text
-# To update this file, edit the corresponding .md file and run: -# gh aw compile +# To update this file, edit the corresponding .md file, build the patched gh-aw binary, +# and run: +# gh-aw compile --no-check-update🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/sdd-execute-opus.lock.yml around lines 17 - 20, The header comment in the sdd-execute-opus.lock.yml file at lines 17-20 provides outdated regeneration instructions that point to the standard gh aw compile command, but this PR uses a locally patched gh-aw binary that requires different invocation. Update the compilation hint in the header to direct contributors to use the patched command instead of the stock gh aw compile, ensuring the instructions accurately reflect how to regenerate this lock file without reverting to the old secret wiring.
3203-3230:⚠️ Potential issue | 🔴 Critical | ⚡ Quick winRedact the Claude OAuth token before uploading detection artifacts.
The detection job runs Claude with
CLAUDE_CODE_OAUTH_TOKENin the environment, writes the transcript todetection.log, then uploads that file without the redaction step used by the agent job. Artifact contents are not automatically GitHub-masked, so a transcript that prints env or echoes the token can leak the credential.🛡️ Proposed fix
RUNNER_TEMP: ${{ runner.temp }} + - name: Redact secrets in threat detection logs + if: always() && steps.detection_guard.outputs.run_detection == 'true' + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/redact_secrets.cjs'); + await main(); + env: + GH_AW_SECRET_NAMES: 'CLAUDE_CODE_OAUTH_TOKEN' + SECRET_CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} - name: Upload threat detection log if: always() && steps.detection_guard.outputs.run_detection == 'true' uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/sdd-execute-opus.lock.yml around lines 3203 - 3230, The detection job passes the CLAUDE_CODE_OAUTH_TOKEN as an environment variable that could be printed to detection.log, but unlike the agent job, no redaction step is performed before uploading the artifact. Add a redaction step before the "Upload threat detection log" action that removes any instances of the CLAUDE_CODE_OAUTH_TOKEN from the detection.log file using sed or similar text replacement, ensuring the sensitive credential cannot be leaked through artifact uploads.
1032-1039:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winUpdate the in-prompt Opus model name to
claude-opus-4-8.The workflow metadata/env run
claude-opus-4-8, but the agent prompt still says this variant runs/declaresclaude-opus-4.6. Fix the source prompt text and regenerate the lock so the agent’s own context matches the runtime.📝 Proposed source-text fix
- variant runs the `claude-opus-4.6` model and selects only tasks carrying the + variant runs the `claude-opus-4-8` model and selects only tasks carrying the ... - - This variant's frontmatter declares the `claude-opus-4.6` engine model and + - This variant's frontmatter declares the `claude-opus-4-8` engine model andAlso applies to: 1754-1760
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/sdd-execute-opus.lock.yml around lines 1032 - 1039, Update all references to the Opus model version in the agent prompt documentation from `claude-opus-4.6` to `claude-opus-4-8` to match the actual workflow environment configuration. Find and replace the outdated model version string in the documentation text for this variant to ensure the agent's own context accurately reflects the runtime configuration, then regenerate the lock file to persist these changes.
1407-1410:⚠️ Potential issue | 🟠 MajorIncrease
BASH_MAX_TIMEOUT_MSto match the 10-minute verify script contract.The workflow requires
timeout 10m bash .github/sdd/verify.sh, butBASH_MAX_TIMEOUT_MSis set to 60,000 ms (60 seconds). According to Claude Code CLI documentation, this value should be 600,000 ms (10 minutes) to permit the full timeout duration. Valid verification scripts exceeding 60 seconds will be prematurely terminated.Proposed fix
ANTHROPIC_MODEL: claude-opus-4-8 BASH_DEFAULT_TIMEOUT_MS: 60000 - BASH_MAX_TIMEOUT_MS: 60000 + BASH_MAX_TIMEOUT_MS: 600000 CLAUDE_CODE_DISABLE_FAST_MODE: 1Also applies to: 2627-2630
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/sdd-execute-opus.lock.yml around lines 1407 - 1410, The BASH_MAX_TIMEOUT_MS environment variable is currently set to 60,000 ms (60 seconds), but the verification script contract requires a 10-minute timeout (600 seconds). Locate BASH_MAX_TIMEOUT_MS at lines 1407-1410 and also at lines 2627-2630 in the workflow file, and update its value from 60,000 to 600,000 in both locations to match the timeout 10m requirement for the verify.sh script execution and prevent premature termination of valid verification scripts that exceed 60 seconds..github/workflows/sdd-execute-sonnet.lock.yml (2)
3203-3230:⚠️ Potential issue | 🟠 Major | ⚡ Quick winRedact the Claude OAuth token before uploading the detection log.
The detection Claude step runs with
CLAUDE_CODE_OAUTH_TOKENin its environment and tees stdout/stderr into/tmp/gh-aw/threat-detection/detection.log, but that log is uploaded without the redaction step used by the main agent job. Any accidental env/debug dump in detection becomes a raw artifact.Suggested generated-output shape
+ - name: Redact secrets in threat detection logs + if: always() && steps.detection_guard.outputs.run_detection == 'true' + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_SECRET_NAMES: 'CLAUDE_CODE_OAUTH_TOKEN' + SECRET_CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/redact_secrets.cjs'); + await main(); - name: Upload threat detection log if: always() && steps.detection_guard.outputs.run_detection == 'true' uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1Based on learnings,
.github/workflows/*.lock.ymlfiles are generated bygh aw compile; update the source/generator and regenerate rather than hand-editing this lock.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/sdd-execute-sonnet.lock.yml around lines 3203 - 3230, The "Upload threat detection log" step uploads the detection.log file without redacting the CLAUDE_CODE_OAUTH_TOKEN that may appear in debug output or environment dumps. Add a redaction step before the artifact upload that removes the token from the detection.log file, similar to how the main agent job handles token redaction. Since this is a generated lock file, update the source workflow generator configuration and regenerate using gh aw compile rather than manually editing this lock file.Source: Learnings
1032-1039:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winUpdate the prompt prose to the dashed Sonnet model ID.
The generated metadata/env uses
claude-sonnet-4-6, but the prompt still saysclaude-sonnet-4.6in the tier description and verification notes. That leaves the agent-facing prompt contradicting the runtime model.Suggested generated-output shape
- variant runs the `claude-sonnet-4.6` model and selects only tasks carrying the + variant runs the `claude-sonnet-4-6` model and selects only tasks carrying the ... - - This variant's frontmatter declares the `claude-sonnet-4.6` engine model and + - This variant's frontmatter declares the `claude-sonnet-4-6` engine model andBased on learnings,
.github/workflows/*.lock.ymlfiles are generated bygh aw compile; update the source markdown/import and regenerate rather than hand-editing this lock.Also applies to: 1756-1760
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/sdd-execute-sonnet.lock.yml around lines 1032 - 1039, The generated workflow file contains inconsistent model naming where the runtime uses claude-sonnet-4-6 (dashed format) but the prompt prose still references claude-sonnet-4.6 (dotted format), creating a contradiction in the agent-facing documentation. Since this is a generated file from gh aw compile, locate the source markdown or import file that generates the sdd-execute-sonnet.lock.yml variant and update all references from claude-sonnet-4.6 to claude-sonnet-4-6 to match the dashed format. After updating the source, regenerate the lock files using gh aw compile to propagate the changes consistently across all affected locations.Source: Learnings
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/lint.yml:
- Around line 52-60: Replace the `git clone --branch "${GH_AW_PIN}"` command
with one that pins to a specific commit SHA instead of a movable tag reference.
After cloning, add a commit SHA verification step to assert the checked-out
commit matches the expected immutable SHA value before the subsequent `go build`
command executes. This ensures the workflow always compiles and executes the
exact code version intended, preventing tag retargeting attacks that could
compromise repository token access.
In @.github/workflows/recompile-locks.yml:
- Around line 67-77: The workflow pins gh-aw using a mutable tag reference
(GH_AW_PIN: v0.77.5) before cloning and building executable code that will be
committed to main, which creates a security risk. Replace the mutable tag
reference in the GH_AW_PIN variable with an immutable commit SHA, and update the
git clone command to use that commit SHA (by using the commit hash directly
instead of the --branch parameter) to ensure the exact source being built is
pinned and verified.
In @.github/workflows/sdd-execute-haiku.md:
- Around line 19-23: The file `.github/workflows/sdd-execute-haiku.md` contains
stale documentation that references outdated model identifiers and Copilot-proxy
terminology. Update all occurrences of the model identifier from
`claude-haiku-4.5` to match the correct identifier `claude-haiku-4-5` used in
the configuration at lines 19-23. Additionally, remove or update any references
to the Copilot-proxy default baseline in the prose at lines 19-23, 173-174, and
893-895 to reflect the current runtime setup. Ensure all documentation strings
accurately reflect the actual model being used and remove any legacy Copilot-era
wording throughout these sections.
In @.github/workflows/sdd-execute-opus.md:
- Around line 19-23: The documentation prose in
.github/workflows/sdd-execute-opus.md contains outdated references to the legacy
model name `claude-opus-4.6` and Copilot-proxy baseline language that no longer
align with the current configuration showing `claude-opus-4-8` on line 20.
Update all references to the legacy model version and the Copilot-proxy baseline
language description to reflect the current Claude migration and engine reality.
This requires changes at lines 19-23 (anchor location with the current model
specification), lines 173-174 (first sibling site with outdated references), and
lines 893-895 (second sibling site with outdated references). Ensure the prose
consistently reflects the current model and runtime configuration throughout the
file.
In @.github/workflows/sdd-execute-sonnet.lock.yml:
- Around line 2628-2629: The BASH_DEFAULT_TIMEOUT_MS and BASH_MAX_TIMEOUT_MS
environment variables are set to 60000ms in the generated lock file, which caps
Claude's Bash tool timeout below the workflow's required 10-minute verification
gate. Since these files are generated by the gh-aw compilation tool, do not edit
the lock file directly. Instead, locate the compilation configuration that feeds
into the gh-aw tool (referenced in recompile-locks.yml) and update the
BASH_DEFAULT_TIMEOUT_MS and BASH_MAX_TIMEOUT_MS settings to 600000 (the
10-minute default), then run gh-aw compile to regenerate the lock files.
In @.github/workflows/sdd-execute-sonnet.md:
- Around line 18-20: The engine model configuration has been updated to
claude-sonnet-4-6, but the prose in the file still references the old model ID
claude-sonnet-4.6. Update all references to the model in the description and
Verification sections to use the new consistent model ID claude-sonnet-4-6 to
match the configuration change and eliminate the self-contradiction in the file.
---
Outside diff comments:
In @.github/workflows/distillery-sync.md:
- Around line 27-29: Update the documentation prose in
`.github/workflows/distillery-sync.md` to align with the migrated Claude model
naming. At lines 27-29, replace references to `GH_AW_DEFAULT_MODEL_COPILOT` and
`claude-haiku-4.5` with the current model naming that matches the frontmatter
specification of `claude-haiku-4-5`. Apply the same updates at lines 33-34 and
lines 408-411, ensuring all text references to the Copilot model and engine
naming are consistent with the actual configured model identifier throughout the
document.
In @.github/workflows/lint.yml:
- Line 77: The error message on line 77 in the lint.yml workflow file instructs
users to run 'gh aw compile', but this is outdated since the repo now requires
using the patched local gh-aw binary instead. Update the echo statement to
instruct contributors to use the correct patched local gh-aw binary path
(typically something like ./gh-aw compile or similar, depending on the repo's
setup) rather than the generic 'gh aw compile' command, so contributors follow
the correct compilation process.
In @.github/workflows/sdd-execute-opus.lock.yml:
- Around line 17-20: The header comment in the sdd-execute-opus.lock.yml file at
lines 17-20 provides outdated regeneration instructions that point to the
standard gh aw compile command, but this PR uses a locally patched gh-aw binary
that requires different invocation. Update the compilation hint in the header to
direct contributors to use the patched command instead of the stock gh aw
compile, ensuring the instructions accurately reflect how to regenerate this
lock file without reverting to the old secret wiring.
- Around line 3203-3230: The detection job passes the CLAUDE_CODE_OAUTH_TOKEN as
an environment variable that could be printed to detection.log, but unlike the
agent job, no redaction step is performed before uploading the artifact. Add a
redaction step before the "Upload threat detection log" action that removes any
instances of the CLAUDE_CODE_OAUTH_TOKEN from the detection.log file using sed
or similar text replacement, ensuring the sensitive credential cannot be leaked
through artifact uploads.
- Around line 1032-1039: Update all references to the Opus model version in the
agent prompt documentation from `claude-opus-4.6` to `claude-opus-4-8` to match
the actual workflow environment configuration. Find and replace the outdated
model version string in the documentation text for this variant to ensure the
agent's own context accurately reflects the runtime configuration, then
regenerate the lock file to persist these changes.
- Around line 1407-1410: The BASH_MAX_TIMEOUT_MS environment variable is
currently set to 60,000 ms (60 seconds), but the verification script contract
requires a 10-minute timeout (600 seconds). Locate BASH_MAX_TIMEOUT_MS at lines
1407-1410 and also at lines 2627-2630 in the workflow file, and update its value
from 60,000 to 600,000 in both locations to match the timeout 10m requirement
for the verify.sh script execution and prevent premature termination of valid
verification scripts that exceed 60 seconds.
In @.github/workflows/sdd-execute-sonnet.lock.yml:
- Around line 3203-3230: The "Upload threat detection log" step uploads the
detection.log file without redacting the CLAUDE_CODE_OAUTH_TOKEN that may appear
in debug output or environment dumps. Add a redaction step before the artifact
upload that removes the token from the detection.log file, similar to how the
main agent job handles token redaction. Since this is a generated lock file,
update the source workflow generator configuration and regenerate using gh aw
compile rather than manually editing this lock file.
- Around line 1032-1039: The generated workflow file contains inconsistent model
naming where the runtime uses claude-sonnet-4-6 (dashed format) but the prompt
prose still references claude-sonnet-4.6 (dotted format), creating a
contradiction in the agent-facing documentation. Since this is a generated file
from gh aw compile, locate the source markdown or import file that generates the
sdd-execute-sonnet.lock.yml variant and update all references from
claude-sonnet-4.6 to claude-sonnet-4-6 to match the dashed format. After
updating the source, regenerate the lock files using gh aw compile to propagate
the changes consistently across all affected locations.
In @.github/workflows/sdd-triage.md:
- Around line 18-32: The max-runs comment block in the sdd-triage.md file
contains a stale reference to Copilot lacking per-turn max-turns support, which
is no longer accurate after switching the engine to Claude. Remove or rephrase
the sentence that specifically names Copilot and its limitations, and instead
use generic language that explains why the invocation cap is the available lever
without referencing any specific engine's capabilities or constraints.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: dd707090-24d8-4d63-b17d-a930afd4275d
📒 Files selected for processing (23)
.github/gh-aw-patches/claude-oauth-token.patch.github/workflows/distillery-sync.lock.yml.github/workflows/distillery-sync.md.github/workflows/lint.yml.github/workflows/recompile-locks.yml.github/workflows/sample.lock.yml.github/workflows/sample.md.github/workflows/sdd-dispatch.lock.yml.github/workflows/sdd-dispatch.md.github/workflows/sdd-execute-haiku.lock.yml.github/workflows/sdd-execute-haiku.md.github/workflows/sdd-execute-opus.lock.yml.github/workflows/sdd-execute-opus.md.github/workflows/sdd-execute-sonnet.lock.yml.github/workflows/sdd-execute-sonnet.md.github/workflows/sdd-review.lock.yml.github/workflows/sdd-review.md.github/workflows/sdd-spec.lock.yml.github/workflows/sdd-spec.md.github/workflows/sdd-triage.lock.yml.github/workflows/sdd-triage.md.github/workflows/sdd-validate.lock.yml.github/workflows/sdd-validate.md
| GH_AW_PIN: v0.77.5 | ||
| run: | | ||
| set -euo pipefail | ||
| # Stock gh-aw ignores CLAUDE_CODE_OAUTH_TOKEN and would regenerate | ||
| # ANTHROPIC_API_KEY locks, reddening this gate. Build the pinned tag | ||
| # with our OAuth-token patch. Version ldflags MUST equal the pin so the | ||
| # lock output is byte-identical to the committed locks this job diffs. | ||
| git clone --depth 1 --branch "${GH_AW_PIN}" \ | ||
| https://github.com/github/gh-aw "${RUNNER_TEMP}/gh-aw-src" |
There was a problem hiding this comment.
Pin gh-aw source by immutable commit SHA, not only tag.
git clone --branch "${GH_AW_PIN}" trusts a movable ref. If the tag is retargeted, this job compiles and executes different code with repository token access (Line 51). Add a pinned commit assertion (or fetch by SHA directly) before go build.
Suggested hardening
- name: Build patched gh-aw
env:
GH_TOKEN: ${{ github.token }}
GH_AW_PIN: v0.77.5
+ GH_AW_PIN_SHA: <expected-gh-aw-commit-sha-for-v0.77.5>
run: |
set -euo pipefail
@@
git clone --depth 1 --branch "${GH_AW_PIN}" \
https://github.com/github/gh-aw "${RUNNER_TEMP}/gh-aw-src"
+ test "$(git -C "${RUNNER_TEMP}/gh-aw-src" rev-parse HEAD)" = "${GH_AW_PIN_SHA}"
git -C "${RUNNER_TEMP}/gh-aw-src" apply \
"${GITHUB_WORKSPACE}/.github/gh-aw-patches/claude-oauth-token.patch"📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| GH_AW_PIN: v0.77.5 | |
| run: | | |
| set -euo pipefail | |
| # Stock gh-aw ignores CLAUDE_CODE_OAUTH_TOKEN and would regenerate | |
| # ANTHROPIC_API_KEY locks, reddening this gate. Build the pinned tag | |
| # with our OAuth-token patch. Version ldflags MUST equal the pin so the | |
| # lock output is byte-identical to the committed locks this job diffs. | |
| git clone --depth 1 --branch "${GH_AW_PIN}" \ | |
| https://github.com/github/gh-aw "${RUNNER_TEMP}/gh-aw-src" | |
| GH_AW_PIN: v0.77.5 | |
| GH_AW_PIN_SHA: <expected-gh-aw-commit-sha-for-v0.77.5> | |
| run: | | |
| set -euo pipefail | |
| # Stock gh-aw ignores CLAUDE_CODE_OAUTH_TOKEN and would regenerate | |
| # ANTHROPIC_API_KEY locks, reddening this gate. Build the pinned tag | |
| # with our OAuth-token patch. Version ldflags MUST equal the pin so the | |
| # lock output is byte-identical to the committed locks this job diffs. | |
| git clone --depth 1 --branch "${GH_AW_PIN}" \ | |
| https://github.com/github/gh-aw "${RUNNER_TEMP}/gh-aw-src" | |
| test "$(git -C "${RUNNER_TEMP}/gh-aw-src" rev-parse HEAD)" = "${GH_AW_PIN_SHA}" |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/lint.yml around lines 52 - 60, Replace the `git clone
--branch "${GH_AW_PIN}"` command with one that pins to a specific commit SHA
instead of a movable tag reference. After cloning, add a commit SHA verification
step to assert the checked-out commit matches the expected immutable SHA value
before the subsequent `go build` command executes. This ensures the workflow
always compiles and executes the exact code version intended, preventing tag
retargeting attacks that could compromise repository token access.
| GH_AW_PIN: v0.77.5 | ||
| run: | | ||
| set -euo pipefail | ||
| # Stock gh-aw ignores CLAUDE_CODE_OAUTH_TOKEN and would clobber the | ||
| # OAuth-token locks with ANTHROPIC_API_KEY ones on auto-recompile. | ||
| # Build the pinned tag with our patch. Version ldflags MUST equal the | ||
| # pin so regenerated locks are byte-identical to the committed ones. | ||
| git clone --depth 1 --branch "${GH_AW_PIN}" \ | ||
| https://github.com/github/gh-aw "${RUNNER_TEMP}/gh-aw-src" | ||
| git -C "${RUNNER_TEMP}/gh-aw-src" apply \ | ||
| "${GITHUB_WORKSPACE}/.github/gh-aw-patches/claude-oauth-token.patch" |
There was a problem hiding this comment.
Use an immutable commit pin for gh-aw source in auto-recompile.
This workflow also clones by tag (GH_AW_PIN) before building executable code. Since this job ultimately pushes to main, mutable-ref trust is especially risky. Pin/verify the exact commit SHA before building.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/recompile-locks.yml around lines 67 - 77, The workflow
pins gh-aw using a mutable tag reference (GH_AW_PIN: v0.77.5) before cloning and
building executable code that will be committed to main, which creates a
security risk. Replace the mutable tag reference in the GH_AW_PIN variable with
an immutable commit SHA, and update the git clone command to use that commit SHA
(by using the commit hash directly instead of the --branch parameter) to ensure
the exact source being built is pinned and verified.
| id: claude | ||
| model: claude-haiku-4-5 | ||
| # Agent-firewall egress allow-list. `defaults` keeps gh-aw's baseline host set | ||
| # (GitHub APIs, the Copilot proxy, the npm registry, the Ubuntu/Microsoft | ||
| # package mirrors); the two crates.io hosts let a Rust consumer's toolchain |
There was a problem hiding this comment.
Refresh stale Copilot-era wording and old model identifiers.
This file now configures claude-haiku-4-5 (Line 20), but the prose still references claude-haiku-4.5 and a Copilot-proxy default baseline. Update these strings to keep runtime expectations and troubleshooting notes accurate.
Also applies to: 173-174, 893-895
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/sdd-execute-haiku.md around lines 19 - 23, The file
`.github/workflows/sdd-execute-haiku.md` contains stale documentation that
references outdated model identifiers and Copilot-proxy terminology. Update all
occurrences of the model identifier from `claude-haiku-4.5` to match the correct
identifier `claude-haiku-4-5` used in the configuration at lines 19-23.
Additionally, remove or update any references to the Copilot-proxy default
baseline in the prose at lines 19-23, 173-174, and 893-895 to reflect the
current runtime setup. Ensure all documentation strings accurately reflect the
actual model being used and remove any legacy Copilot-era wording throughout
these sections.
| id: claude | ||
| model: claude-opus-4-8 | ||
| # Agent-firewall egress allow-list. `defaults` keeps gh-aw's baseline host set | ||
| # (GitHub APIs, the Copilot proxy, the npm registry, the Ubuntu/Microsoft | ||
| # package mirrors); the two crates.io hosts let a Rust consumer's toolchain |
There was a problem hiding this comment.
Update legacy model/proxy references to match the Claude migration.
Frontmatter now pins claude-opus-4-8 (Line 20), but these sections still mention claude-opus-4.6 and Copilot-proxy baseline language. Please align the prose with current engine/runtime reality.
Also applies to: 173-174, 893-895
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/sdd-execute-opus.md around lines 19 - 23, The
documentation prose in .github/workflows/sdd-execute-opus.md contains outdated
references to the legacy model name `claude-opus-4.6` and Copilot-proxy baseline
language that no longer align with the current configuration showing
`claude-opus-4-8` on line 20. Update all references to the legacy model version
and the Copilot-proxy baseline language description to reflect the current
Claude migration and engine reality. This requires changes at lines 19-23
(anchor location with the current model specification), lines 173-174 (first
sibling site with outdated references), and lines 893-895 (second sibling site
with outdated references). Ensure the prose consistently reflects the current
model and runtime configuration throughout the file.
| BASH_DEFAULT_TIMEOUT_MS: 60000 | ||
| BASH_MAX_TIMEOUT_MS: 60000 |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Read-only check: find Claude Bash timeout caps and the prompt-level 10-minute gate.
rg -n 'BASH_(DEFAULT|MAX)_TIMEOUT_MS|timeout 10m bash \.github/sdd/verify\.sh' .github/workflowsRepository: norrietaylor/spectacles
Length of output: 4044
🏁 Script executed:
# Find source generator files or patterns for these lock files
fd -e md '.github/workflows' | head -20Repository: norrietaylor/spectacles
Length of output: 441
🏁 Script executed:
# Check if there's a generator or source file for sdd-execute-sonnet
rg -l 'sdd-execute-sonnet' .github --type md --type yml | grep -v lock.yml | head -10Repository: norrietaylor/spectacles
Length of output: 95
🌐 Web query:
Claude Code BASH_MAX_TIMEOUT_MS environment variable documentation default value
💡 Result:
The environment variable BASH_MAX_TIMEOUT_MS is used to configure the maximum timeout that the model can set for long-running bash commands in Claude Code [1][2]. The default value for BASH_MAX_TIMEOUT_MS is 600,000 milliseconds, which is equivalent to 10 minutes [1][2][3]. Users can override this limit by setting the BASH_MAX_TIMEOUT_MS environment variable to a different value in milliseconds before launching Claude Code [4]. This variable acts as the upper ceiling for command execution times [3][4]. Additionally, the BASH_DEFAULT_TIMEOUT_MS environment variable can be used to set the default timeout (which defaults to 120,000 milliseconds or 2 minutes) [1][2].
Citations:
- 1: https://code.claude.com/docs/en/env-vars.md
- 2: https://claude-code.mintlify.app/en/env-vars
- 3: https://www.mintlify.com/VineeTagarwaL-code/claude-code/reference/tools/bash
- 4: https://claudecodeguides.com/claude-code-timeout-2m-fix/
🏁 Script executed:
# Find source markdown files in .github/workflows that might be generators
fd . '.github/workflows' -e mdRepository: norrietaylor/spectacles
Length of output: 411
🏁 Script executed:
# Check for any generator scripts or templates
rg -l 'sdd-execute' .github --type md | head -10Repository: norrietaylor/spectacles
Length of output: 346
🏁 Script executed:
# Look for README or docs about the workflow generation process
find .github -name "*README*" -o -name "*generator*" -o -name "*compile*"Repository: norrietaylor/spectacles
Length of output: 105
🏁 Script executed:
# Check the source .md file for the timeout values
rg -n 'BASH_(DEFAULT|MAX)_TIMEOUT_MS' .github/workflows/sdd-execute-sonnet.md -A 1 -B 1Repository: norrietaylor/spectacles
Length of output: 49
🏁 Script executed:
# Verify the exact line numbers in the lock file around 2628-2629 and 3205-3206
sed -n '2625,2635p' .github/workflows/sdd-execute-sonnet.lock.yml | cat -nRepository: norrietaylor/spectacles
Length of output: 4518
🏁 Script executed:
# Check if the second occurrence at 3205-3206 is in a similar context
sed -n '3202,3212p' .github/workflows/sdd-execute-sonnet.lock.yml | cat -nRepository: norrietaylor/spectacles
Length of output: 1656
🏁 Script executed:
# Search more broadly in the source .md file for timeout or environment settings
cat .github/workflows/sdd-execute-sonnet.md | grep -n -i 'bash_.*timeout\|env:' | head -20Repository: norrietaylor/spectacles
Length of output: 81
🏁 Script executed:
# Get context around the Agent execution step in the source .md
rg -n 'ANTHROPIC_MODEL' .github/workflows/sdd-execute-sonnet.md -B 5 -A 10 | head -40Repository: norrietaylor/spectacles
Length of output: 49
🏁 Script executed:
# Check the recompile-locks workflow to understand how values are injected
cat .github/workflows/recompile-locks.ymlRepository: norrietaylor/spectacles
Length of output: 5301
🏁 Script executed:
# Look for any configuration files that might set these defaults
find .github -name "*.json" -o -name "*.yaml" -o -name "*.yml" | grep -v lock | head -20Repository: norrietaylor/spectacles
Length of output: 962
🏁 Script executed:
# Check the shared/ directory for any workflow or configuration files
find shared -type f | head -30Repository: norrietaylor/spectacles
Length of output: 453
🏁 Script executed:
# Look for any references to BASH_DEFAULT_TIMEOUT_MS in shared or scripts
rg 'BASH_DEFAULT_TIMEOUT_MS\|BASH_MAX_TIMEOUT_MS\|60000' shared scriptsRepository: norrietaylor/spectacles
Length of output: 49
Don't cap Claude's Bash tool below the workflow's 10-minute verification gate.
These environment variables limit Claude Code Bash calls to 60 seconds, but the prompt requires commands such as timeout 10m bash .github/sdd/verify.sh; normal build/test gates can now be killed before the workflow's own contract runs. Claude Code documents BASH_MAX_TIMEOUT_MS as the maximum Bash timeout the model can set, with a 600,000ms default (10 minutes), so the generated locks should preserve the default here.
The timeout values at lines 2628–2629 and 3205–3206 appear to be injected by the gh-aw compilation tool (v0.77.5 in recompile-locks.yml). Since .github/workflows/*.lock.yml files are generated, do not hand-edit them; instead, update the compilation configuration to ensure BASH_DEFAULT_TIMEOUT_MS and BASH_MAX_TIMEOUT_MS are set to 600000 during lock generation, then run gh-aw compile to regenerate.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/sdd-execute-sonnet.lock.yml around lines 2628 - 2629, The
BASH_DEFAULT_TIMEOUT_MS and BASH_MAX_TIMEOUT_MS environment variables are set to
60000ms in the generated lock file, which caps Claude's Bash tool timeout below
the workflow's required 10-minute verification gate. Since these files are
generated by the gh-aw compilation tool, do not edit the lock file directly.
Instead, locate the compilation configuration that feeds into the gh-aw tool
(referenced in recompile-locks.yml) and update the BASH_DEFAULT_TIMEOUT_MS and
BASH_MAX_TIMEOUT_MS settings to 600000 (the 10-minute default), then run gh-aw
compile to regenerate the lock files.
Source: Learnings
| engine: | ||
| id: copilot | ||
| model: claude-sonnet-4.6 | ||
| id: claude | ||
| model: claude-sonnet-4-6 |
There was a problem hiding this comment.
Keep the model id consistent in the prose.
The config change is fine, but the surrounding text still refers to claude-sonnet-4.6 in the description and Verification section. That leaves the file self-contradictory after the engine update.
♻️ Suggested wording update
-This variant runs the `claude-sonnet-4.6` model and selects only tasks carrying the
+This variant runs the `claude-sonnet-4-6` model and selects only tasks carrying the
-This variant's frontmatter declares the `claude-sonnet-4.6` engine model and selects only `model:sonnet` tasks.
+This variant's frontmatter declares the `claude-sonnet-4-6` engine model and selects only `model:sonnet` tasks.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/sdd-execute-sonnet.md around lines 18 - 20, The engine
model configuration has been updated to claude-sonnet-4-6, but the prose in the
file still references the old model ID claude-sonnet-4.6. Update all references
to the model in the description and Verification sections to use the new
consistent model ID claude-sonnet-4-6 to match the configuration change and
eliminate the self-contradiction in the file.
Switch all 10 agentic workflows from
engine: copilottoengine: claude, authenticating against an Anthropic Max/Teams subscription viaCLAUDE_CODE_OAUTH_TOKEN. gh-aw does not support this token natively, so CI builds a patched gh-aw at the pinned tagv0.77.5.Patch
.github/gh-aw-patches/claude-oauth-token.patch(applied togithub/gh-aw@v0.77.5):ANTHROPIC_API_KEY→CLAUDE_CODE_OAUTH_TOKENANTHROPIC_API_KEY→CLAUDE_CODE_OAUTH_TOKENnil. The OAuth token has no api-proxy sidecar, so excluding it strips the only in-container credential →apiKeySource: none/Not logged in. It must stay in the agent container (the CLI calls allow-listedapi.anthropic.comdirectly).EngineOptionsClaudeSecretName→CLAUDE_CODE_OAUTH_TOKENModel pins (Copilot dotted → Anthropic dashed)
claude-haiku-4.5claude-haiku-4-5claude-sonnet-4.6claude-sonnet-4-6claude-opus-4.6claude-opus-4-8(current tier)vars.GH_AW_MODEL_AGENT_CLAUDECI
lint.yml(stale-lock gate) andrecompile-locks.yml(auto-recompile→main) replacegh extension install github/gh-aw --pinwith setup-go + a build-patched step (clone pin, apply patch,ldflags -X main.version=v0.77.5 -X main.isRelease=true), then invoke the standalonegh-awbinary. Stock gh-aw would regenerateANTHROPIC_API_KEYlocks (reddening the gate) and clobber the OAuth locks on auto-recompile.Verification
ANTHROPIC_API_KEY, zeroCOPILOT_GITHUB_TOKEN,CLAUDE_CODE_OAUTH_TOKENin every lock, token never in an AWF--exclude-env.v0.77.5clone; a linux build with identical ldflags reproduces the committed locks byte-for-byte (this PR's validate job is the live gate).Prerequisites before dispatch (repo/org settings — not in this PR)
CLAUDE_CODE_OAUTH_TOKEN(claude setup-token).GH_AW_MODEL_AGENT_CLAUDEfor the six unpinned workflows.Stale comments left in place (flagged, not rewritten)
distillery-sync.md:27,409–410— prose referencesGH_AW_DEFAULT_MODEL_COPILOT/COPILOT_MODEL, moot under the claude engine.sdd-execute-{haiku,sonnet,opus}.md:22— egress comment says "the Copilot proxy"; claude callsapi.anthropic.comdirectly.lint.yml:77error hint says "Rungh aw compile" — local contributors now need the patched binary.🤖 Generated with Claude Code