From 632b95a901ca4520f5e3258d6048a9f96dccdf3b Mon Sep 17 00:00:00 2001 From: Nathan Heskew Date: Wed, 22 Apr 2026 10:19:06 -0700 Subject: [PATCH 1/3] workflow: scale agent turn budgets + skip validation for doc-only tasks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two fixes driven by the PR #50 mention retry hitting the 30-turn cap mid-work (eyes emoji appeared, nothing committed or posted). 1. Turn budgets now scale with the amount of work each workflow has to do. Agent work is strictly a superset of review work (all the reading + making changes + validating + committing + pushing), so a 1.25x ratio wasn't real headroom. Review 24 (baseline) — read + summarize Mention 30 → 48 (2x) — iterate on existing PR Issue-to-PR 40 → 72 (3x) — build PR from scratch At ~$0.05/turn Sonnet the worst-case costs are ~$1.20, ~$2.40, ~$3.60 respectively. Concurrency stays 1/PR+issue and the per-job timeout-minutes cap remains the hard safety rail. 2. Validation-scaling in both agent prompts. Previously the prompt always told Claude to run `npm run build`, `npm run lint`, `npm test`, AND `bun test` before committing — four turns of validation for work that may be pure doc edits. Now the prompts tell Claude to scope validation to the change: - Doc-only changes (`*.md`, `docs/**`, `config.yaml`, package.json keyword/description tweaks): only `npm run format:check` + `npm run lint`. - Code or config changes that affect behavior: the full set. Saves ~3-4 turns per doc task. "When in doubt, err toward the fuller validation" keeps the default safe. Doesn't touch claude-review.yml — 24 turns has been sufficient for review work per recent runs on PR #48. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/claude-issue-to-pr.yml | 14 +++++++++++--- .github/workflows/claude-mention.yml | 17 +++++++++++++---- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/.github/workflows/claude-issue-to-pr.yml b/.github/workflows/claude-issue-to-pr.yml index 26e0399..4341b8a 100644 --- a/.github/workflows/claude-issue-to-pr.yml +++ b/.github/workflows/claude-issue-to-pr.yml @@ -75,7 +75,7 @@ jobs: show_full_output: true claude_args: | --model claude-sonnet-4-6 - --max-turns 40 + --max-turns 72 --allowedTools "Read,Write,Edit,Grep,Glob,Bash(gh pr view:*),Bash(gh pr diff:*),Bash(gh pr comment:*),Bash(gh pr create:*),Bash(gh issue view:*),Bash(gh issue comment:*),Bash(git:*),Bash(npm install:*),Bash(npm ci:*),Bash(npm run:*),Bash(npm test:*),Bash(bun install:*),Bash(bun run:*),Bash(bun test:*),Bash(npx:*)" prompt: | You were invoked because issue #${{ github.event.issue.number }} @@ -135,8 +135,16 @@ jobs: 1. Create a branch named `claude/fix-${{ github.event.issue.number }}` (or append `-` if useful). 2. Make the change scoped to the label. - 3. Run `npm run build && npm run lint && npm run format:check && npm test` - and `bun test`. Fix anything that fails. + 3. Validate, scaling to the kind of change you made: + - `claude-fix:typo` / `claude-fix:docs` (doc-only + changes to `*.md`, `docs/**`, `config.yaml`): + run `npm run format:check` and `npm run lint`. + Skip `npm run build` / `npm test` / `bun test` — + they are not affected and waste turns. + - `claude-fix:deps` / `claude-fix:bug` or any change + that touches code: run + `npm run build && npm run lint && npm run format:check && npm test` + and `bun test`. Fix anything that fails. 4. Commit with a descriptive message. 5. Push the branch and open a PR via `gh pr create` with a body that says `Closes #${{ github.event.issue.number }}`. diff --git a/.github/workflows/claude-mention.yml b/.github/workflows/claude-mention.yml index 1390db4..dc946eb 100644 --- a/.github/workflows/claude-mention.yml +++ b/.github/workflows/claude-mention.yml @@ -81,7 +81,7 @@ jobs: show_full_output: true claude_args: | --model claude-sonnet-4-6 - --max-turns 30 + --max-turns 48 --allowedTools "Read,Write,Edit,Grep,Glob,mcp__github_inline_comment__create_inline_comment,Bash(gh pr view:*),Bash(gh pr diff:*),Bash(gh pr comment:*),Bash(gh pr checkout:*),Bash(gh pr create:*),Bash(gh issue view:*),Bash(gh issue comment:*),Bash(git:*),Bash(npm install:*),Bash(npm ci:*),Bash(npm run:*),Bash(npm test:*),Bash(bun install:*),Bash(bun run:*),Bash(bun test:*),Bash(npx:*)" # In agent mode the action uses the triggering comment as the # prompt. The text below layers supplemental context on top. @@ -107,9 +107,18 @@ jobs: ## Before committing - Run `npm run build && npm run lint && npm run format:check && npm test` - in the workspace. Also run `bun test` — Bun is installed in - the runner. Fix anything that fails before committing. + Scale validation to the kind of change you made: + + - Doc-only change (only `*.md`, `docs/**`, `config.yaml`, + or `package.json` keyword/description edits): run + `npm run format:check` and `npm run lint`. Do NOT run + `npm run build` / `npm test` / `bun test` — they are + not affected and waste turns. + - Code or config change that affects behavior: run + `npm run build && npm run lint && npm run format:check && npm test` + and `bun test`. Fix anything that fails. + + When in doubt, err toward the fuller validation. ## Output From a210dceaa6cd56129e72b59f96e81478596e444d Mon Sep 17 00:00:00 2001 From: Nathan Heskew Date: Wed, 22 Apr 2026 10:28:04 -0700 Subject: [PATCH 2/3] workflow: config.yaml is not doc-only; add fallback to issue-to-pr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two findings from Claude's review on this PR. 1. I wrongly classified `config.yaml` as doc-only in both workflows. The actual file declares `pluginModule: 'dist/index.js'` (plugin entry point), `graphqlSchema.files`, and runtime OAuth defaults (`redirectUri`, `scope`, `defaultRole`, `postLoginRedirect`). A wrong `pluginModule` path or malformed `redirectUri` would break the plugin at runtime. Removed from the doc-only bucket in both prompts; explicitly called out as "NOT doc-only" so the next reader doesn't reintroduce the same mistake. 2. The mention prompt ended the validation tree with "When in doubt, err toward the fuller validation." — but the issue-to-pr prompt, which runs more autonomously (no human directing each action), didn't have the tiebreaker. That inverted the expected risk relationship — the more autonomous path should be MORE conservative, not less. Added the same fallback line to the issue-to-pr prompt. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/claude-issue-to-pr.yml | 14 +++++++++----- .github/workflows/claude-mention.yml | 8 ++++++-- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/.github/workflows/claude-issue-to-pr.yml b/.github/workflows/claude-issue-to-pr.yml index 4341b8a..f99f55c 100644 --- a/.github/workflows/claude-issue-to-pr.yml +++ b/.github/workflows/claude-issue-to-pr.yml @@ -137,14 +137,18 @@ jobs: 2. Make the change scoped to the label. 3. Validate, scaling to the kind of change you made: - `claude-fix:typo` / `claude-fix:docs` (doc-only - changes to `*.md`, `docs/**`, `config.yaml`): - run `npm run format:check` and `npm run lint`. - Skip `npm run build` / `npm test` / `bun test` — - they are not affected and waste turns. + changes to `*.md`, `docs/**`, or `package.json` + keyword/description fields): run + `npm run format:check` and `npm run lint`. Skip + `npm run build` / `npm test` / `bun test` — they + are not affected and waste turns. - `claude-fix:deps` / `claude-fix:bug` or any change - that touches code: run + that touches code OR `config.yaml` (plugin entry + point + runtime OAuth defaults — not doc-only): run `npm run build && npm run lint && npm run format:check && npm test` and `bun test`. Fix anything that fails. + + When in doubt, err toward the fuller validation. 4. Commit with a descriptive message. 5. Push the branch and open a PR via `gh pr create` with a body that says `Closes #${{ github.event.issue.number }}`. diff --git a/.github/workflows/claude-mention.yml b/.github/workflows/claude-mention.yml index dc946eb..5c84eed 100644 --- a/.github/workflows/claude-mention.yml +++ b/.github/workflows/claude-mention.yml @@ -109,11 +109,15 @@ jobs: Scale validation to the kind of change you made: - - Doc-only change (only `*.md`, `docs/**`, `config.yaml`, - or `package.json` keyword/description edits): run + - Doc-only change (only `*.md`, `docs/**`, or + `package.json` keyword/description edits): run `npm run format:check` and `npm run lint`. Do NOT run `npm run build` / `npm test` / `bun test` — they are not affected and waste turns. + + `config.yaml` is NOT doc-only — it holds the plugin + entry point (`pluginModule`) and runtime OAuth defaults. + Treat any change there as a code/config change. - Code or config change that affects behavior: run `npm run build && npm run lint && npm run format:check && npm test` and `bun test`. Fix anything that fails. From 7be13675364829d304028ff0fe3fc90ef5d57b39 Mon Sep 17 00:00:00 2001 From: Nathan Heskew Date: Wed, 22 Apr 2026 10:40:35 -0700 Subject: [PATCH 3/3] workflow: promote config.yaml callout in issue-to-pr prompt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Last round of Claude's review on this PR caught a structural asymmetry between the mention and issue-to-pr prompts. The mention prompt has the `config.yaml is NOT doc-only` callout as a standalone note BEFORE the classification bullets. The issue-to-pr prompt had the same info, but buried inside the second bullet — below the `claude-fix:typo / claude-fix:docs` light-path rule. An agent that matches on the label first picks the light path and may never read the content-based override, skipping the full build/test on a config.yaml change filed as a typo. `config.yaml` holds `pluginModule` and runtime OAuth defaults — a typo there breaks the plugin at runtime. Moving the override above the bullets removes the ambiguity. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/claude-issue-to-pr.yml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/.github/workflows/claude-issue-to-pr.yml b/.github/workflows/claude-issue-to-pr.yml index f99f55c..1c07008 100644 --- a/.github/workflows/claude-issue-to-pr.yml +++ b/.github/workflows/claude-issue-to-pr.yml @@ -135,7 +135,13 @@ jobs: 1. Create a branch named `claude/fix-${{ github.event.issue.number }}` (or append `-` if useful). 2. Make the change scoped to the label. - 3. Validate, scaling to the kind of change you made: + 3. Validate, scaling to the kind of change you made. + + **`config.yaml` is NOT doc-only** — it holds the plugin + entry point (`pluginModule`) and runtime OAuth defaults. + Any change that touches `config.yaml` requires the full + validation path regardless of the `claude-fix:*` label. + - `claude-fix:typo` / `claude-fix:docs` (doc-only changes to `*.md`, `docs/**`, or `package.json` keyword/description fields): run @@ -143,8 +149,7 @@ jobs: `npm run build` / `npm test` / `bun test` — they are not affected and waste turns. - `claude-fix:deps` / `claude-fix:bug` or any change - that touches code OR `config.yaml` (plugin entry - point + runtime OAuth defaults — not doc-only): run + that touches code or `config.yaml`: run `npm run build && npm run lint && npm run format:check && npm test` and `bun test`. Fix anything that fails.