Skip to content

Commit 5517fcd

Browse files
rdimitrovclaude
andauthored
Cap skill turns/timeout + sync local HEAD after skill pushes (#783)
* Add turn/timeout caps and sync local HEAD after skill pushes Three defensive additions to the upstream-release-docs pipeline. ## Sync local HEAD with skill-pushed commits claude-code-action works in a sibling scratch checkout (the `.claude-pr/` dir we gitignore) and pushes its commits to origin without advancing the outer workflow checkout's HEAD. Every subsequent step that reads local git state saw stale HEAD at the pre-skill SHA. Symptoms on PR #780: - `skill_commits` counter reported 0 despite commit `d4b3c7c` existing on the PR branch -- triggered the silent-run NOTE on a run that wasn't actually silent. - `autofix` early-exited with "No skill-touched files in scope" because its `git diff BASELINE_SHA..HEAD` returned nothing. 41 unformatted files from the skill landed on CI and failed the Lint and format checks job. Fix: new step between `skill_review` and `skill_commits` that runs `git fetch origin $HEAD_REF && git merge --ff-only`. Local HEAD now reflects whatever the skill pushed, so downstream steps see the truth. ## --max-turns caps Per-session turn ceilings via claude_args: - skill_gen: 500 (baselines: 89 silent → 397 full rebuild) - skill_review: 30 (baseline: 4-5 turns every run) Clips genuine runaway loops without interfering with legitimate complex runs. Hitting a cap fails loudly; we raise deliberately if a release genuinely needs more. ## timeout-minutes per step Wall-clock ceilings: - skill_gen: 45 min (observed: 15-22 min) - skill_review: 10 min (observed: 1-2 min) Kills a stuck process before it burns the full 90-min job budget. ## What this does NOT cover - Legitimate-but-expensive runs (PR #780 at $27 is real work). - Upstream Anthropic pricing changes. - High-frequency workflow triggering. For those: set a monthly spend cap at the Anthropic console. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Fail loudly on sync-step errors (Copilot review) Drops the `|| true` after `git merge --ff-only`. Silently continuing on a failed sync reintroduces the exact skill_commits=0 + autofix-skips-files bugs this step prevents. A no-op fast-forward (local already at origin) still exits 0 cleanly, so the common case is unaffected. Only genuine divergence or merge errors now fail the step. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent b3b2ab5 commit 5517fcd

1 file changed

Lines changed: 48 additions & 1 deletion

File tree

.github/workflows/upstream-release-docs.yml

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,11 @@ jobs:
514514
# verification.
515515
- name: Run upstream-release-docs skill (generation)
516516
id: skill_gen
517+
# Wall-clock ceiling. Observed gen runs take 15–22 min depending
518+
# on release scope; 45 min kills a stuck process before it
519+
# burns the full 90-minute job budget. Paired with --max-turns
520+
# below for a runaway-cost ceiling.
521+
timeout-minutes: 45
517522
uses: anthropics/claude-code-action@38ec876110f9fbf8b950c79f534430740c3ac009 # v1
518523
with:
519524
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
@@ -542,8 +547,15 @@ jobs:
542547
# only, which misses most of the "why" narrative that PR
543548
# authors write at open time. GH_TOKEN for auth is already
544549
# in the job env at the top of this workflow.
550+
#
551+
# --max-turns 500: observed gen baselines are 89 turns
552+
# (silent) to 397 (full content rebuild). 500 gives headroom
553+
# over the worst legitimate run, while clipping a genuine
554+
# runaway before it spirals. Hitting the cap produces a
555+
# loud failure -- raise deliberately if a release needs more.
545556
claude_args: |
546557
--model claude-opus-4-7
558+
--max-turns 500
547559
--allowed-tools "Bash(gh:*)"
548560
prompt: |
549561
You are running in GitHub Actions with no interactive user. Follow
@@ -678,6 +690,11 @@ jobs:
678690
- name: Run docs-review on skill output (fresh context)
679691
id: skill_review
680692
if: always() && steps.skill_gen.conclusion == 'success'
693+
# Editorial review is a short pass: 1-2 min wall clock, 4-5
694+
# turns in every run so far. 10 / 30 are 5-6x buffers over
695+
# baseline -- cheap safety net for the rare case where review
696+
# spirals on a file it can't stop "improving".
697+
timeout-minutes: 10
681698
uses: anthropics/claude-code-action@38ec876110f9fbf8b950c79f534430740c3ac009 # v1
682699
with:
683700
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
@@ -688,9 +705,12 @@ jobs:
688705
display_report: true
689706
# gh access parallels skill_gen so the review pass can
690707
# re-verify claims against PR descriptions and linked
691-
# issues if needed.
708+
# issues if needed. --max-turns 30 is 6x the 4-5-turn
709+
# baseline; if review ever needs more, the cap fails
710+
# loudly and we raise it.
692711
claude_args: |
693712
--model claude-opus-4-7
713+
--max-turns 30
694714
--allowed-tools "Bash(gh:*)"
695715
prompt: |
696716
You are running in GitHub Actions with no interactive user. Follow
@@ -723,6 +743,33 @@ jobs:
723743
if they exist -- they're signal files handed off to the
724744
next workflow step, not part of the docs.
725745
746+
# claude-code-action works in a sibling scratch checkout (the
747+
# .claude-pr/ dir we gitignore) and pushes commits to origin
748+
# directly, without advancing the outer workflow checkout's
749+
# HEAD. Without an explicit sync, every subsequent step that
750+
# reads local git state (skill_commits counter, autofix's git
751+
# diff) sees stale HEAD at the pre-skill SHA -- which is what
752+
# caused PR #780's "skill_commits=0 despite a real skill
753+
# commit" + unformatted files landing on CI unformatted.
754+
#
755+
# Fetch + fast-forward-merge origin so local HEAD reflects
756+
# whatever the skill pushed. Fail loudly on fetch or merge
757+
# errors -- silently continuing on stale HEAD reintroduces
758+
# the exact skill_commits=0 + autofix-skips-files bugs this
759+
# step is meant to prevent. Gated on skill_gen success; if
760+
# gen didn't run, there's nothing for the skill to have
761+
# pushed and this step is skipped.
762+
# A no-op fast-forward (local already at origin, e.g. skill
763+
# made no commits) exits 0 cleanly.
764+
- name: Sync local branch with skill-pushed commits
765+
if: always() && steps.skill_gen.conclusion == 'success'
766+
env:
767+
HEAD_REF: ${{ steps.eff.outputs.head_ref }}
768+
run: |
769+
git fetch origin "$HEAD_REF" --quiet
770+
git merge --ff-only "origin/$HEAD_REF"
771+
echo "Local HEAD after sync: $(git rev-parse HEAD)"
772+
726773
# Mirror of skill_gen_stats for skill_review. Reads the same
727774
# canonical log path, which skill_review overwrote on exit.
728775
- name: Capture skill_review stats

0 commit comments

Comments
 (0)