clud-bug 0.6.22 → 0.6.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clud-bug",
3
- "version": "0.6.22",
3
+ "version": "0.6.23",
4
4
  "description": "Skill-driven Claude PR review. Ship a brand-voice skill, get brand reviews. Each finding cites the skill that motivated it. CLI installs the workflow + a baseline kit; add more from skills.sh.",
5
5
  "homepage": "https://cludbug.dev",
6
6
  "bugs": "https://github.com/thrillmade/clud-bug/issues",
@@ -15,6 +15,7 @@ jobs:
15
15
  outputs:
16
16
  is_workflow_only: ${{ steps.classify.outputs.is_workflow_only }}
17
17
  model: ${{ steps.classify.outputs.model }}
18
+ max_turns: ${{ steps.classify.outputs.max_turns }}
18
19
  steps:
19
20
  - name: Classify PR diff
20
21
  id: classify
@@ -29,6 +30,8 @@ jobs:
29
30
  if [ -z "$CHANGED" ]; then
30
31
  echo "is_workflow_only=false" >> "$GITHUB_OUTPUT"
31
32
  echo "model=$MODEL" >> "$GITHUB_OUTPUT"
33
+ # v0.6.23 / §5: max_turns must always be emitted — see workflow.yml.tmpl for design notes.
34
+ echo "max_turns=15" >> "$GITHUB_OUTPUT"
32
35
  exit 0
33
36
  fi
34
37
  IS_WORKFLOW_ONLY=true
@@ -75,6 +78,23 @@ jobs:
75
78
  fi
76
79
  echo "model=$MODEL" >> "$GITHUB_OUTPUT"
77
80
 
81
+ # Adaptive max-turns (v0.6.23 / §5) — see workflow.yml.tmpl for design notes.
82
+ MAX_TURNS=15
83
+ if [ "$IS_TRIVIAL" = "true" ]; then
84
+ MAX_TURNS=10
85
+ else
86
+ FILE_COUNT=$(echo "$CHANGED" | wc -l | tr -d ' ')
87
+ THREAD_COUNT=$(gh api graphql -f query='{repository(owner:"'"$(echo "$REPO" | cut -d/ -f1)"'",name:"'"$(echo "$REPO" | cut -d/ -f2)"'"){pullRequest(number:'"$PR_NUMBER"'){reviewThreads(first:50){nodes{isResolved comments(first:1){nodes{author{login}}}}}}}}' --jq '[.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved == false and (.comments.nodes[0].author.login == "claude" or .comments.nodes[0].author.login == "claude[bot]"))] | length' 2>/dev/null || echo 0)
88
+ THREAD_COUNT=${THREAD_COUNT:-0}
89
+ if [ "$FILE_COUNT" -ge 30 ] || [ "$THREAD_COUNT" -ge 6 ]; then
90
+ MAX_TURNS=40
91
+ elif [ "$FILE_COUNT" -ge 10 ] || [ "$THREAD_COUNT" -ge 3 ]; then
92
+ MAX_TURNS=25
93
+ fi
94
+ echo "::notice title=Clud Bug 🐛::Turn budget: $MAX_TURNS ($FILE_COUNT files, $THREAD_COUNT prior threads)."
95
+ fi
96
+ echo "max_turns=$MAX_TURNS" >> "$GITHUB_OUTPUT"
97
+
78
98
  clud-bug-review:
79
99
  needs: paths-check
80
100
  if: needs.paths-check.outputs.is_workflow_only != 'true'
@@ -85,6 +105,8 @@ jobs:
85
105
  id-token: write
86
106
  # checks: write — composite emits per-skill check-runs (BB.3).
87
107
  checks: write
108
+ # actions: read (v0.6.23 / §5) — github_ci MCP server. See workflow.yml.tmpl for design notes.
109
+ actions: read
88
110
 
89
111
  steps:
90
112
  - uses: actions/checkout@v6
@@ -147,7 +169,7 @@ jobs:
147
169
  # structured output; post-step renders + posts. See workflow.yml.tmpl for design notes.
148
170
  claude_args: |
149
171
  --model ${{ needs.paths-check.outputs.model }}
150
- --max-turns 15
172
+ --max-turns ${{ needs.paths-check.outputs.max_turns }}
151
173
  --allowedTools "mcp__github_inline_comment__create_inline_comment,Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh api graphql:*),Bash(gh api repos/:*),Bash(git show:*),Bash(git diff:*),Bash(git merge-base:*),Bash(cat .claude/skills/.clud-bug.json),Bash(cat .claude/skills/*/SKILL.md),Bash(head:*)"
152
174
  --json-schema '{{REVIEW_SCHEMA}}'
153
175
  prompt: |
@@ -190,7 +212,7 @@ jobs:
190
212
  # Strict-mode gate — composite action; see workflow.yml.tmpl for design notes.
191
213
  - name: Strict mode — fail check on critical findings
192
214
  if: success()
193
- uses: thrillmade/clud-bug/.github/actions/strict-mode-gate@v0.6.22
215
+ uses: thrillmade/clud-bug/.github/actions/strict-mode-gate@v0.6.23
194
216
  with:
195
217
  github-token: ${{ secrets.GITHUB_TOKEN }}
196
218
  # v0.6.22 / 0.0.O: summary now posted by github-actions[bot].
@@ -15,6 +15,7 @@ jobs:
15
15
  outputs:
16
16
  is_workflow_only: ${{ steps.classify.outputs.is_workflow_only }}
17
17
  model: ${{ steps.classify.outputs.model }}
18
+ max_turns: ${{ steps.classify.outputs.max_turns }}
18
19
  steps:
19
20
  - name: Classify PR diff
20
21
  id: classify
@@ -29,6 +30,8 @@ jobs:
29
30
  if [ -z "$CHANGED" ]; then
30
31
  echo "is_workflow_only=false" >> "$GITHUB_OUTPUT"
31
32
  echo "model=$MODEL" >> "$GITHUB_OUTPUT"
33
+ # v0.6.23 / §5: max_turns must always be emitted — see workflow.yml.tmpl for design notes.
34
+ echo "max_turns=15" >> "$GITHUB_OUTPUT"
32
35
  exit 0
33
36
  fi
34
37
  IS_WORKFLOW_ONLY=true
@@ -75,6 +78,23 @@ jobs:
75
78
  fi
76
79
  echo "model=$MODEL" >> "$GITHUB_OUTPUT"
77
80
 
81
+ # Adaptive max-turns (v0.6.23 / §5) — see workflow.yml.tmpl for design notes.
82
+ MAX_TURNS=15
83
+ if [ "$IS_TRIVIAL" = "true" ]; then
84
+ MAX_TURNS=10
85
+ else
86
+ FILE_COUNT=$(echo "$CHANGED" | wc -l | tr -d ' ')
87
+ THREAD_COUNT=$(gh api graphql -f query='{repository(owner:"'"$(echo "$REPO" | cut -d/ -f1)"'",name:"'"$(echo "$REPO" | cut -d/ -f2)"'"){pullRequest(number:'"$PR_NUMBER"'){reviewThreads(first:50){nodes{isResolved comments(first:1){nodes{author{login}}}}}}}}' --jq '[.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved == false and (.comments.nodes[0].author.login == "claude" or .comments.nodes[0].author.login == "claude[bot]"))] | length' 2>/dev/null || echo 0)
88
+ THREAD_COUNT=${THREAD_COUNT:-0}
89
+ if [ "$FILE_COUNT" -ge 30 ] || [ "$THREAD_COUNT" -ge 6 ]; then
90
+ MAX_TURNS=40
91
+ elif [ "$FILE_COUNT" -ge 10 ] || [ "$THREAD_COUNT" -ge 3 ]; then
92
+ MAX_TURNS=25
93
+ fi
94
+ echo "::notice title=Clud Bug 🐛::Turn budget: $MAX_TURNS ($FILE_COUNT files, $THREAD_COUNT prior threads)."
95
+ fi
96
+ echo "max_turns=$MAX_TURNS" >> "$GITHUB_OUTPUT"
97
+
78
98
  clud-bug-review:
79
99
  needs: paths-check
80
100
  if: needs.paths-check.outputs.is_workflow_only != 'true'
@@ -85,6 +105,8 @@ jobs:
85
105
  id-token: write
86
106
  # checks: write — composite emits per-skill check-runs (BB.3).
87
107
  checks: write
108
+ # actions: read (v0.6.23 / §5) — github_ci MCP server. See workflow.yml.tmpl for design notes.
109
+ actions: read
88
110
 
89
111
  steps:
90
112
  - uses: actions/checkout@v6
@@ -147,7 +169,7 @@ jobs:
147
169
  # structured output; post-step renders + posts. See workflow.yml.tmpl for design notes.
148
170
  claude_args: |
149
171
  --model ${{ needs.paths-check.outputs.model }}
150
- --max-turns 15
172
+ --max-turns ${{ needs.paths-check.outputs.max_turns }}
151
173
  --allowedTools "mcp__github_inline_comment__create_inline_comment,Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh api graphql:*),Bash(gh api repos/:*),Bash(git show:*),Bash(git diff:*),Bash(git merge-base:*),Bash(cat .claude/skills/.clud-bug.json),Bash(cat .claude/skills/*/SKILL.md),Bash(head:*)"
152
174
  --json-schema '{{REVIEW_SCHEMA}}'
153
175
  prompt: |
@@ -190,7 +212,7 @@ jobs:
190
212
  # Strict-mode gate — composite action; see workflow.yml.tmpl for design notes.
191
213
  - name: Strict mode — fail check on critical findings
192
214
  if: success()
193
- uses: thrillmade/clud-bug/.github/actions/strict-mode-gate@v0.6.22
215
+ uses: thrillmade/clud-bug/.github/actions/strict-mode-gate@v0.6.23
194
216
  with:
195
217
  github-token: ${{ secrets.GITHUB_TOKEN }}
196
218
  # v0.6.22 / 0.0.O: summary now posted by github-actions[bot].
@@ -29,6 +29,7 @@ jobs:
29
29
  outputs:
30
30
  is_workflow_only: ${{ steps.classify.outputs.is_workflow_only }}
31
31
  model: ${{ steps.classify.outputs.model }}
32
+ max_turns: ${{ steps.classify.outputs.max_turns }}
32
33
  steps:
33
34
  - name: Classify PR diff
34
35
  id: classify
@@ -43,6 +44,13 @@ jobs:
43
44
  if [ -z "$CHANGED" ]; then
44
45
  echo "is_workflow_only=false" >> "$GITHUB_OUTPUT"
45
46
  echo "model=$MODEL" >> "$GITHUB_OUTPUT"
47
+ # v0.6.23 / §5: max_turns must always be emitted because
48
+ # clud-bug-review runs (is_workflow_only=false). Without
49
+ # this, --max-turns ${{ ... }} expands to '--max-turns '
50
+ # (empty), failing the CLI invocation. Empty-CHANGED
51
+ # fires on gh pr diff auth/network failures + the
52
+ # (theoretical) no-changed-files PR.
53
+ echo "max_turns=15" >> "$GITHUB_OUTPUT"
46
54
  exit 0
47
55
  fi
48
56
 
@@ -102,6 +110,38 @@ jobs:
102
110
  fi
103
111
  echo "model=$MODEL" >> "$GITHUB_OUTPUT"
104
112
 
113
+ # --- (c) adaptive max-turns (v0.6.23 / §5) ---
114
+ # Scope-based turn budget so large PRs (many files OR many prior
115
+ # unresolved threads to walk in FIX-PUSH FLOW) don't exhaust the
116
+ # default 15-turn budget. Concrete failure that motivated this:
117
+ # tokenomics PR #18 (23 docs files + 6 prior claude[bot] threads)
118
+ # exhausted the cap under v0.6.12 AND under v0.6.22's
119
+ # structured-output flow.
120
+ #
121
+ # Buckets:
122
+ # Trivial (Haiku) → 10
123
+ # Standard (<10 files AND <3 prior threads) → 15 (current default)
124
+ # Larger (≥10 files OR ≥3 prior threads) → 25
125
+ # Very large (≥30 files OR ≥6 prior threads) → 40
126
+ MAX_TURNS=15
127
+ if [ "$IS_TRIVIAL" = "true" ]; then
128
+ MAX_TURNS=10
129
+ else
130
+ FILE_COUNT=$(echo "$CHANGED" | wc -l | tr -d ' ')
131
+ # Count unresolved claude-bot threads. Best-effort: rate-limit
132
+ # or auth failures default to 0 (no escalation, fall back to
133
+ # file-count tier).
134
+ THREAD_COUNT=$(gh api graphql -f query='{repository(owner:"'"$(echo "$REPO" | cut -d/ -f1)"'",name:"'"$(echo "$REPO" | cut -d/ -f2)"'"){pullRequest(number:'"$PR_NUMBER"'){reviewThreads(first:50){nodes{isResolved comments(first:1){nodes{author{login}}}}}}}}' --jq '[.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved == false and (.comments.nodes[0].author.login == "claude" or .comments.nodes[0].author.login == "claude[bot]"))] | length' 2>/dev/null || echo 0)
135
+ THREAD_COUNT=${THREAD_COUNT:-0}
136
+ if [ "$FILE_COUNT" -ge 30 ] || [ "$THREAD_COUNT" -ge 6 ]; then
137
+ MAX_TURNS=40
138
+ elif [ "$FILE_COUNT" -ge 10 ] || [ "$THREAD_COUNT" -ge 3 ]; then
139
+ MAX_TURNS=25
140
+ fi
141
+ echo "::notice title=Clud Bug 🐛::Turn budget: $MAX_TURNS ($FILE_COUNT files, $THREAD_COUNT prior unresolved claude threads)."
142
+ fi
143
+ echo "max_turns=$MAX_TURNS" >> "$GITHUB_OUTPUT"
144
+
105
145
  clud-bug-review:
106
146
  needs: paths-check
107
147
  if: needs.paths-check.outputs.is_workflow_only != 'true'
@@ -114,6 +154,11 @@ jobs:
114
154
  # the GitHub Checks API for any skill in .clud-bug.json's strictSkills
115
155
  # list (BB.3, v0.5.10+). No-op when strictSkills is unset.
116
156
  checks: write
157
+ # actions: read (v0.6.23 / §5) — claude-code-action's bundled
158
+ # github_ci MCP server needs this to introspect recent CI runs.
159
+ # Per-job GITHUB_TOKEN permissions aren't inherited, so this
160
+ # MUST be on the clud-bug-review job, not paths-check.
161
+ actions: read
117
162
 
118
163
  steps:
119
164
  - uses: actions/checkout@v6
@@ -229,7 +274,7 @@ jobs:
229
274
  # this template at `clud-bug init` time via {{REVIEW_SCHEMA}}.
230
275
  claude_args: |
231
276
  --model ${{ needs.paths-check.outputs.model }}
232
- --max-turns 15
277
+ --max-turns ${{ needs.paths-check.outputs.max_turns }}
233
278
  --allowedTools "mcp__github_inline_comment__create_inline_comment,Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh api graphql:*),Bash(gh api repos/:*),Bash(git show:*),Bash(git diff:*),Bash(git merge-base:*),Bash(cat .claude/skills/.clud-bug.json),Bash(cat .claude/skills/*/SKILL.md),Bash(head:*)"
234
279
  --json-schema '{{REVIEW_SCHEMA}}'
235
280
  prompt: |
@@ -290,7 +335,7 @@ jobs:
290
335
  # Letting the action's own failure fail the check is louder and right.
291
336
  - name: Strict mode — fail check on critical findings
292
337
  if: success()
293
- uses: thrillmade/clud-bug/.github/actions/strict-mode-gate@v0.6.22
338
+ uses: thrillmade/clud-bug/.github/actions/strict-mode-gate@v0.6.23
294
339
  with:
295
340
  github-token: ${{ secrets.GITHUB_TOKEN }}
296
341
  # v0.6.22 / 0.0.O: the summary is now posted by the workflow