clud-bug 0.6.25 → 0.6.27
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/lib/prompts.js +30 -0
- package/package.json +1 -1
- package/templates/workflow-py.yml.tmpl +61 -11
- package/templates/workflow-ts.yml.tmpl +61 -11
- package/templates/workflow.yml.tmpl +140 -17
package/lib/prompts.js
CHANGED
|
@@ -201,6 +201,36 @@ Rules:
|
|
|
201
201
|
every file's verdict so a maintainer can verify nothing was
|
|
202
202
|
skipped.
|
|
203
203
|
|
|
204
|
+
Mid-review self-check-in (v0.6.27 / §5.5 Layer 3):
|
|
205
|
+
After every 5 tool_uses, write a single-line budget heartbeat as a
|
|
206
|
+
free-text "thinking" message (not a tool call — these don't cost a
|
|
207
|
+
turn) of the form:
|
|
208
|
+
|
|
209
|
+
[budget] files_reviewed=X/N, turns_used=Y/M, pace=ok|behind
|
|
210
|
+
|
|
211
|
+
Where:
|
|
212
|
+
- X / N is the count of files you've meaningfully looked at so far
|
|
213
|
+
over the total in this PR's diff.
|
|
214
|
+
- Y / M is your current turn count over max_turns.
|
|
215
|
+
- pace = "ok" when X / N >= Y / (M - 5). The denominator subtracts the
|
|
216
|
+
5-turn emit reservation: over the (M - 5) turns available for file
|
|
217
|
+
review, your file-coverage rate must match where you actually are
|
|
218
|
+
in the budget. (Don't subtract from Y — that would be saying "I've
|
|
219
|
+
used Y minus 5 turns" which double-counts the reservation.)
|
|
220
|
+
pace = "behind" otherwise.
|
|
221
|
+
|
|
222
|
+
When pace = "behind", immediately pivot strategy:
|
|
223
|
+
1. Stop deep-dive analysis on the current file.
|
|
224
|
+
2. Switch to one-sentence verdicts for every remaining file.
|
|
225
|
+
3. Keep going through the whole diff — silent skipping is
|
|
226
|
+
non-negotiable. Cover everything, even if some files only get
|
|
227
|
+
"no issues found in this file" as their verdict.
|
|
228
|
+
|
|
229
|
+
The heartbeat serves two purposes: (a) forces internal pacing — you
|
|
230
|
+
can't drift past budget without noticing; (b) lands in the action's
|
|
231
|
+
streaming output for post-hoc calibration of the per-line cost
|
|
232
|
+
coefficients used by paths-check's Layer 1 estimator.
|
|
233
|
+
|
|
204
234
|
Incremental-diff handshake (v0.6.10+) — emit the SHA marker:
|
|
205
235
|
At the very end of the summary (after the Skills-referenced footer,
|
|
206
236
|
on its own line), append:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "clud-bug",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.27",
|
|
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",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# clud-bug-template-version:
|
|
1
|
+
# clud-bug-template-version: v12
|
|
2
2
|
name: Clud Bug 🐛 Crawls Your Code
|
|
3
3
|
|
|
4
4
|
on:
|
|
@@ -53,17 +53,32 @@ jobs:
|
|
|
53
53
|
} >> "$GITHUB_OUTPUT"
|
|
54
54
|
exit 0
|
|
55
55
|
fi
|
|
56
|
-
|
|
56
|
+
# v0.6.26 / 0.0.W² — see workflow.yml.tmpl for design notes.
|
|
57
|
+
ALL_IN_ALLOWLIST=true
|
|
58
|
+
HAS_WORKFLOW_CHANGE=false
|
|
57
59
|
while IFS= read -r f; do
|
|
58
60
|
case "$f" in
|
|
59
|
-
.github/workflows/clud-bug-*.yml) ;;
|
|
60
|
-
.github/actions/strict-mode-gate/*) ;;
|
|
61
|
-
|
|
61
|
+
.github/workflows/clud-bug-*.yml) HAS_WORKFLOW_CHANGE=true ;;
|
|
62
|
+
.github/actions/strict-mode-gate/*) HAS_WORKFLOW_CHANGE=true ;;
|
|
63
|
+
AGENTS.md) ;;
|
|
64
|
+
.cursorrules|.clinerules|.windsurfrules|.continuerules) ;;
|
|
65
|
+
.github/copilot-instructions.md) ;;
|
|
66
|
+
.claude/skills/.clud-bug.json) ;;
|
|
67
|
+
.claude/skills/critical-issues-only/SKILL.md) ;;
|
|
68
|
+
.claude/skills/evidence-based-review/SKILL.md) ;;
|
|
69
|
+
.claude/skills/respect-existing-conventions/SKILL.md) ;;
|
|
70
|
+
docs/timeline.md|docs/file-structure.md|docs/decisions.md) ;;
|
|
71
|
+
docs/decisions-branches/*.md) ;;
|
|
72
|
+
*) ALL_IN_ALLOWLIST=false; break ;;
|
|
62
73
|
esac
|
|
63
74
|
done <<< "$CHANGED"
|
|
75
|
+
IS_WORKFLOW_ONLY=false
|
|
76
|
+
if [ "$ALL_IN_ALLOWLIST" = "true" ] && [ "$HAS_WORKFLOW_CHANGE" = "true" ]; then
|
|
77
|
+
IS_WORKFLOW_ONLY=true
|
|
78
|
+
fi
|
|
64
79
|
echo "is_workflow_only=$IS_WORKFLOW_ONLY" >> "$GITHUB_OUTPUT"
|
|
65
80
|
if [ "$IS_WORKFLOW_ONLY" = "true" ]; then
|
|
66
|
-
echo "::notice title=Clud Bug 🐛::Skipping LLM review —
|
|
81
|
+
echo "::notice title=Clud Bug 🐛::Skipping LLM review — clud-bug update output."
|
|
67
82
|
echo "model=$MODEL" >> "$GITHUB_OUTPUT"
|
|
68
83
|
exit 0
|
|
69
84
|
fi
|
|
@@ -268,28 +283,63 @@ jobs:
|
|
|
268
283
|
|
|
269
284
|
$CALIBRATION"
|
|
270
285
|
|
|
271
|
-
#
|
|
286
|
+
# v0.6.26 / §5.5 Layer 6 fallback render-from-inlines — see workflow.yml.tmpl for design notes.
|
|
272
287
|
- name: Fallback summary (structured_output empty)
|
|
273
288
|
if: success() && steps.clud-bug-review.outputs.structured_output == ''
|
|
274
289
|
env:
|
|
275
290
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
276
291
|
PR_NUMBER: ${{ github.event.pull_request.number }}
|
|
292
|
+
REPO: ${{ github.repository }}
|
|
293
|
+
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
|
294
|
+
TURNS_ESTIMATED: ${{ needs.paths-check.outputs.turns_estimated }}
|
|
295
|
+
MAX_TURNS: ${{ needs.paths-check.outputs.max_turns }}
|
|
296
|
+
FILES_COUNT: ${{ needs.paths-check.outputs.files_count }}
|
|
297
|
+
LINES_ADDED: ${{ needs.paths-check.outputs.lines_added }}
|
|
298
|
+
LINES_DELETED: ${{ needs.paths-check.outputs.lines_deleted }}
|
|
299
|
+
THREADS_COUNT: ${{ needs.paths-check.outputs.threads_count }}
|
|
277
300
|
run: |
|
|
278
301
|
set -euo pipefail
|
|
279
|
-
gh
|
|
302
|
+
INLINES=$(gh api "repos/$REPO/pulls/$PR_NUMBER/comments?per_page=100" \
|
|
303
|
+
--jq "[.[] | select(.user.login == \"claude[bot]\" and .commit_id == \"$HEAD_SHA\")]")
|
|
304
|
+
INLINE_COUNT=$(echo "$INLINES" | jq 'length')
|
|
305
|
+
CRITICAL=$(echo "$INLINES" | jq '[.[] | select(.body | test("🔴"))] | length')
|
|
306
|
+
MINOR=$(echo "$INLINES" | jq '[.[] | select(.body | test("🟡"))] | length')
|
|
307
|
+
PREEXISTING=$(echo "$INLINES" | jq '[.[] | select(.body | test("🟣"))] | length')
|
|
308
|
+
CALIBRATION="<!-- clud-bug-calibration: turns_estimated=$TURNS_ESTIMATED, max_turns=$MAX_TURNS, files=$FILES_COUNT, lines_added=$LINES_ADDED, lines_deleted=$LINES_DELETED, threads=$THREADS_COUNT, structured_output=empty, inline_findings=$INLINE_COUNT -->"
|
|
309
|
+
if [ "$INLINE_COUNT" -gt 0 ]; then
|
|
310
|
+
STATUS=""
|
|
311
|
+
[ "$CRITICAL" -gt 0 ] && STATUS=" — critical findings"
|
|
312
|
+
gh pr comment "$PR_NUMBER" --body "## 🐛 Clud Bug review${STATUS}
|
|
313
|
+
|
|
314
|
+
**This round:** $CRITICAL critical · $MINOR minor · 0 resolved from prior · 0 still open
|
|
315
|
+
|
|
316
|
+
Found: $CRITICAL 🔴 / $MINOR 🟡 / $PREEXISTING 🟣
|
|
317
|
+
|
|
318
|
+
⚠️ **Synthetic summary** (v0.6.26 §5.5 Layer 6 fallback). Inline findings above ARE the substantive review.
|
|
319
|
+
|
|
320
|
+
<!-- last-reviewed-sha: $HEAD_SHA -->
|
|
321
|
+
|
|
322
|
+
$CALIBRATION"
|
|
323
|
+
else
|
|
324
|
+
gh pr comment "$PR_NUMBER" --body "## 🐛 Clud Bug review
|
|
280
325
|
|
|
281
326
|
**This round:** 0 critical · 0 minor · 0 resolved from prior · 0 still open
|
|
282
327
|
|
|
283
328
|
Found: 0 🔴 / 0 🟡 / 0 🟣
|
|
284
329
|
|
|
285
|
-
⚠️ Structured output (\`--json-schema\`) returned empty
|
|
330
|
+
⚠️ Structured output (\`--json-schema\`) returned empty AND no inline findings posted. Investigate run logs.
|
|
331
|
+
|
|
332
|
+
Skills referenced: [none]
|
|
333
|
+
|
|
334
|
+
<!-- last-reviewed-sha: $HEAD_SHA -->
|
|
286
335
|
|
|
287
|
-
|
|
336
|
+
$CALIBRATION"
|
|
337
|
+
fi
|
|
288
338
|
|
|
289
339
|
# Strict-mode gate — composite action; see workflow.yml.tmpl for design notes.
|
|
290
340
|
- name: Strict mode — fail check on critical findings
|
|
291
341
|
if: success()
|
|
292
|
-
uses: thrillmade/clud-bug/.github/actions/strict-mode-gate@v0.6.
|
|
342
|
+
uses: thrillmade/clud-bug/.github/actions/strict-mode-gate@v0.6.27
|
|
293
343
|
with:
|
|
294
344
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
295
345
|
# v0.6.22 / 0.0.O: summary now posted by github-actions[bot].
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# clud-bug-template-version:
|
|
1
|
+
# clud-bug-template-version: v12
|
|
2
2
|
name: Clud Bug 🐛 Crawls Your Code
|
|
3
3
|
|
|
4
4
|
on:
|
|
@@ -53,17 +53,32 @@ jobs:
|
|
|
53
53
|
} >> "$GITHUB_OUTPUT"
|
|
54
54
|
exit 0
|
|
55
55
|
fi
|
|
56
|
-
|
|
56
|
+
# v0.6.26 / 0.0.W² — see workflow.yml.tmpl for design notes.
|
|
57
|
+
ALL_IN_ALLOWLIST=true
|
|
58
|
+
HAS_WORKFLOW_CHANGE=false
|
|
57
59
|
while IFS= read -r f; do
|
|
58
60
|
case "$f" in
|
|
59
|
-
.github/workflows/clud-bug-*.yml) ;;
|
|
60
|
-
.github/actions/strict-mode-gate/*) ;;
|
|
61
|
-
|
|
61
|
+
.github/workflows/clud-bug-*.yml) HAS_WORKFLOW_CHANGE=true ;;
|
|
62
|
+
.github/actions/strict-mode-gate/*) HAS_WORKFLOW_CHANGE=true ;;
|
|
63
|
+
AGENTS.md) ;;
|
|
64
|
+
.cursorrules|.clinerules|.windsurfrules|.continuerules) ;;
|
|
65
|
+
.github/copilot-instructions.md) ;;
|
|
66
|
+
.claude/skills/.clud-bug.json) ;;
|
|
67
|
+
.claude/skills/critical-issues-only/SKILL.md) ;;
|
|
68
|
+
.claude/skills/evidence-based-review/SKILL.md) ;;
|
|
69
|
+
.claude/skills/respect-existing-conventions/SKILL.md) ;;
|
|
70
|
+
docs/timeline.md|docs/file-structure.md|docs/decisions.md) ;;
|
|
71
|
+
docs/decisions-branches/*.md) ;;
|
|
72
|
+
*) ALL_IN_ALLOWLIST=false; break ;;
|
|
62
73
|
esac
|
|
63
74
|
done <<< "$CHANGED"
|
|
75
|
+
IS_WORKFLOW_ONLY=false
|
|
76
|
+
if [ "$ALL_IN_ALLOWLIST" = "true" ] && [ "$HAS_WORKFLOW_CHANGE" = "true" ]; then
|
|
77
|
+
IS_WORKFLOW_ONLY=true
|
|
78
|
+
fi
|
|
64
79
|
echo "is_workflow_only=$IS_WORKFLOW_ONLY" >> "$GITHUB_OUTPUT"
|
|
65
80
|
if [ "$IS_WORKFLOW_ONLY" = "true" ]; then
|
|
66
|
-
echo "::notice title=Clud Bug 🐛::Skipping LLM review —
|
|
81
|
+
echo "::notice title=Clud Bug 🐛::Skipping LLM review — clud-bug update output."
|
|
67
82
|
echo "model=$MODEL" >> "$GITHUB_OUTPUT"
|
|
68
83
|
exit 0
|
|
69
84
|
fi
|
|
@@ -268,28 +283,63 @@ jobs:
|
|
|
268
283
|
|
|
269
284
|
$CALIBRATION"
|
|
270
285
|
|
|
271
|
-
#
|
|
286
|
+
# v0.6.26 / §5.5 Layer 6 fallback render-from-inlines — see workflow.yml.tmpl for design notes.
|
|
272
287
|
- name: Fallback summary (structured_output empty)
|
|
273
288
|
if: success() && steps.clud-bug-review.outputs.structured_output == ''
|
|
274
289
|
env:
|
|
275
290
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
276
291
|
PR_NUMBER: ${{ github.event.pull_request.number }}
|
|
292
|
+
REPO: ${{ github.repository }}
|
|
293
|
+
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
|
294
|
+
TURNS_ESTIMATED: ${{ needs.paths-check.outputs.turns_estimated }}
|
|
295
|
+
MAX_TURNS: ${{ needs.paths-check.outputs.max_turns }}
|
|
296
|
+
FILES_COUNT: ${{ needs.paths-check.outputs.files_count }}
|
|
297
|
+
LINES_ADDED: ${{ needs.paths-check.outputs.lines_added }}
|
|
298
|
+
LINES_DELETED: ${{ needs.paths-check.outputs.lines_deleted }}
|
|
299
|
+
THREADS_COUNT: ${{ needs.paths-check.outputs.threads_count }}
|
|
277
300
|
run: |
|
|
278
301
|
set -euo pipefail
|
|
279
|
-
gh
|
|
302
|
+
INLINES=$(gh api "repos/$REPO/pulls/$PR_NUMBER/comments?per_page=100" \
|
|
303
|
+
--jq "[.[] | select(.user.login == \"claude[bot]\" and .commit_id == \"$HEAD_SHA\")]")
|
|
304
|
+
INLINE_COUNT=$(echo "$INLINES" | jq 'length')
|
|
305
|
+
CRITICAL=$(echo "$INLINES" | jq '[.[] | select(.body | test("🔴"))] | length')
|
|
306
|
+
MINOR=$(echo "$INLINES" | jq '[.[] | select(.body | test("🟡"))] | length')
|
|
307
|
+
PREEXISTING=$(echo "$INLINES" | jq '[.[] | select(.body | test("🟣"))] | length')
|
|
308
|
+
CALIBRATION="<!-- clud-bug-calibration: turns_estimated=$TURNS_ESTIMATED, max_turns=$MAX_TURNS, files=$FILES_COUNT, lines_added=$LINES_ADDED, lines_deleted=$LINES_DELETED, threads=$THREADS_COUNT, structured_output=empty, inline_findings=$INLINE_COUNT -->"
|
|
309
|
+
if [ "$INLINE_COUNT" -gt 0 ]; then
|
|
310
|
+
STATUS=""
|
|
311
|
+
[ "$CRITICAL" -gt 0 ] && STATUS=" — critical findings"
|
|
312
|
+
gh pr comment "$PR_NUMBER" --body "## 🐛 Clud Bug review${STATUS}
|
|
313
|
+
|
|
314
|
+
**This round:** $CRITICAL critical · $MINOR minor · 0 resolved from prior · 0 still open
|
|
315
|
+
|
|
316
|
+
Found: $CRITICAL 🔴 / $MINOR 🟡 / $PREEXISTING 🟣
|
|
317
|
+
|
|
318
|
+
⚠️ **Synthetic summary** (v0.6.26 §5.5 Layer 6 fallback). Inline findings above ARE the substantive review.
|
|
319
|
+
|
|
320
|
+
<!-- last-reviewed-sha: $HEAD_SHA -->
|
|
321
|
+
|
|
322
|
+
$CALIBRATION"
|
|
323
|
+
else
|
|
324
|
+
gh pr comment "$PR_NUMBER" --body "## 🐛 Clud Bug review
|
|
280
325
|
|
|
281
326
|
**This round:** 0 critical · 0 minor · 0 resolved from prior · 0 still open
|
|
282
327
|
|
|
283
328
|
Found: 0 🔴 / 0 🟡 / 0 🟣
|
|
284
329
|
|
|
285
|
-
⚠️ Structured output (\`--json-schema\`) returned empty
|
|
330
|
+
⚠️ Structured output (\`--json-schema\`) returned empty AND no inline findings posted. Investigate run logs.
|
|
331
|
+
|
|
332
|
+
Skills referenced: [none]
|
|
333
|
+
|
|
334
|
+
<!-- last-reviewed-sha: $HEAD_SHA -->
|
|
286
335
|
|
|
287
|
-
|
|
336
|
+
$CALIBRATION"
|
|
337
|
+
fi
|
|
288
338
|
|
|
289
339
|
# Strict-mode gate — composite action; see workflow.yml.tmpl for design notes.
|
|
290
340
|
- name: Strict mode — fail check on critical findings
|
|
291
341
|
if: success()
|
|
292
|
-
uses: thrillmade/clud-bug/.github/actions/strict-mode-gate@v0.6.
|
|
342
|
+
uses: thrillmade/clud-bug/.github/actions/strict-mode-gate@v0.6.27
|
|
293
343
|
with:
|
|
294
344
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
295
345
|
# v0.6.22 / 0.0.O: summary now posted by github-actions[bot].
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# clud-bug-template-version:
|
|
1
|
+
# clud-bug-template-version: v12
|
|
2
2
|
name: Clud Bug 🐛 Crawls Your Code
|
|
3
3
|
|
|
4
4
|
on:
|
|
@@ -18,12 +18,45 @@ jobs:
|
|
|
18
18
|
# Pre-flight: classify the PR diff to decide (a) whether to skip the
|
|
19
19
|
# LLM review entirely, and (b) which model to route to.
|
|
20
20
|
#
|
|
21
|
-
# (a) Workflow-only PRs (v0.6.14 / 0.0.W
|
|
22
|
-
#
|
|
23
|
-
#
|
|
24
|
-
#
|
|
25
|
-
#
|
|
26
|
-
#
|
|
21
|
+
# (a) Workflow-only / clud-bug-update PRs (v0.6.14 / 0.0.W;
|
|
22
|
+
# v0.6.26 / 0.0.W²): the LLM call is skipped when EITHER condition:
|
|
23
|
+
#
|
|
24
|
+
# - Every changed file matches `.github/workflows/clud-bug-*.yml`
|
|
25
|
+
# or `.github/actions/strict-mode-gate/**` (original 0.0.W —
|
|
26
|
+
# pure workflow PRs that claude-code-action would refuse anyway
|
|
27
|
+
# via its self-modification guard).
|
|
28
|
+
#
|
|
29
|
+
# - The PR is a recognized `clud-bug update` propagation: every
|
|
30
|
+
# changed file is in the clud-bug-update output allowlist AND a
|
|
31
|
+
# workflow file (or strict-mode-gate composite) is part of the
|
|
32
|
+
# change. v0.6.26 / 0.0.W² added this branch so the propagation
|
|
33
|
+
# dance doesn't require admin-bypass every cycle.
|
|
34
|
+
#
|
|
35
|
+
# Allowlist (files `clud-bug update` legitimately touches):
|
|
36
|
+
# .github/workflows/clud-bug-*.yml (workflow re-render)
|
|
37
|
+
# .github/actions/strict-mode-gate/* (composite re-render)
|
|
38
|
+
# AGENTS.md (logmind block + clud-bug stanza)
|
|
39
|
+
# .cursorrules / .clinerules / .windsurfrules / .continuerules
|
|
40
|
+
# .github/copilot-instructions.md
|
|
41
|
+
# .claude/skills/.clud-bug.json (manifest)
|
|
42
|
+
# .claude/skills/{critical-issues-only,evidence-based-review,
|
|
43
|
+
# respect-existing-conventions}/SKILL.md (baselines)
|
|
44
|
+
# docs/timeline.md / docs/file-structure.md / docs/decisions.md
|
|
45
|
+
# docs/decisions-branches/*.md (logmind side-effects)
|
|
46
|
+
#
|
|
47
|
+
# The workflow-change requirement is the SIGNATURE that distinguishes
|
|
48
|
+
# "agent ran clud-bug update" from "user is editing AGENTS.md by hand."
|
|
49
|
+
# An AGENTS.md-only PR (no workflow change) still goes through normal
|
|
50
|
+
# review — this catches the prompt-injection-via-AGENTS.md attack
|
|
51
|
+
# surface that a naive allowlist would open.
|
|
52
|
+
#
|
|
53
|
+
# Safety envelope:
|
|
54
|
+
# - Workflow file is still protected by the App-side guard (it just
|
|
55
|
+
# never runs in this branch).
|
|
56
|
+
# - Files in the allowlist are non-executable; modifying them can't
|
|
57
|
+
# grant code execution.
|
|
58
|
+
# - strictMode toggle is read from BASE ref so a PR can't disable
|
|
59
|
+
# strict-mode on itself.
|
|
27
60
|
#
|
|
28
61
|
# (b) Trivial PRs (v0.6.15 / 0.0.R): if the PR author is a dep-bumping
|
|
29
62
|
# bot (dependabot, renovate) OR the diff is small (<2KB) AND only
|
|
@@ -82,18 +115,49 @@ jobs:
|
|
|
82
115
|
exit 0
|
|
83
116
|
fi
|
|
84
117
|
|
|
85
|
-
# --- (a) workflow-only classifier
|
|
86
|
-
|
|
118
|
+
# --- (a) workflow-only / clud-bug-update classifier
|
|
119
|
+
# (v0.6.14 / 0.0.W; widened in v0.6.26 / 0.0.W²) ---
|
|
120
|
+
# Two-track check:
|
|
121
|
+
# ALL_IN_ALLOWLIST = every changed file is in the
|
|
122
|
+
# clud-bug-update output allowlist (see header design notes
|
|
123
|
+
# for the full list + rationale).
|
|
124
|
+
# HAS_WORKFLOW_CHANGE = at least one workflow-file or
|
|
125
|
+
# strict-mode-gate change is present. This is the signature
|
|
126
|
+
# that distinguishes "clud-bug update output" from "user
|
|
127
|
+
# edited AGENTS.md by hand" — naked AGENTS.md edits go
|
|
128
|
+
# through normal review.
|
|
129
|
+
#
|
|
130
|
+
# Skip when both are true. Backward-compat with v0.6.14's
|
|
131
|
+
# `is_workflow_only` output name preserved (semantic widened to
|
|
132
|
+
# "skip-review-eligible"; the dependent clud-bug-review job
|
|
133
|
+
# gates on this output without needing a rename).
|
|
134
|
+
ALL_IN_ALLOWLIST=true
|
|
135
|
+
HAS_WORKFLOW_CHANGE=false
|
|
87
136
|
while IFS= read -r f; do
|
|
88
137
|
case "$f" in
|
|
89
|
-
.github/workflows/clud-bug-*.yml) ;;
|
|
90
|
-
.github/actions/strict-mode-gate/*) ;;
|
|
91
|
-
|
|
138
|
+
.github/workflows/clud-bug-*.yml) HAS_WORKFLOW_CHANGE=true ;;
|
|
139
|
+
.github/actions/strict-mode-gate/*) HAS_WORKFLOW_CHANGE=true ;;
|
|
140
|
+
# v0.6.26 / 0.0.W² additions — files clud-bug update produces.
|
|
141
|
+
AGENTS.md) ;;
|
|
142
|
+
.cursorrules|.clinerules|.windsurfrules|.continuerules) ;;
|
|
143
|
+
.github/copilot-instructions.md) ;;
|
|
144
|
+
.claude/skills/.clud-bug.json) ;;
|
|
145
|
+
.claude/skills/critical-issues-only/SKILL.md) ;;
|
|
146
|
+
.claude/skills/evidence-based-review/SKILL.md) ;;
|
|
147
|
+
.claude/skills/respect-existing-conventions/SKILL.md) ;;
|
|
148
|
+
# logmind side-effects of `logmind log` on the same commit.
|
|
149
|
+
docs/timeline.md|docs/file-structure.md|docs/decisions.md) ;;
|
|
150
|
+
docs/decisions-branches/*.md) ;;
|
|
151
|
+
*) ALL_IN_ALLOWLIST=false; break ;;
|
|
92
152
|
esac
|
|
93
153
|
done <<< "$CHANGED"
|
|
154
|
+
IS_WORKFLOW_ONLY=false
|
|
155
|
+
if [ "$ALL_IN_ALLOWLIST" = "true" ] && [ "$HAS_WORKFLOW_CHANGE" = "true" ]; then
|
|
156
|
+
IS_WORKFLOW_ONLY=true
|
|
157
|
+
fi
|
|
94
158
|
echo "is_workflow_only=$IS_WORKFLOW_ONLY" >> "$GITHUB_OUTPUT"
|
|
95
159
|
if [ "$IS_WORKFLOW_ONLY" = "true" ]; then
|
|
96
|
-
echo "::notice title=Clud Bug 🐛::Skipping LLM review —
|
|
160
|
+
echo "::notice title=Clud Bug 🐛::Skipping LLM review — clud-bug update output (workflow + allowlist files, no review surface)."
|
|
97
161
|
echo "model=$MODEL" >> "$GITHUB_OUTPUT"
|
|
98
162
|
exit 0
|
|
99
163
|
fi
|
|
@@ -434,22 +498,81 @@ jobs:
|
|
|
434
498
|
# output after max retries (structured_output is empty). Keeps a
|
|
435
499
|
# bare H2 header so the strict-mode gate sees a comment and falls
|
|
436
500
|
# open (advisory) rather than panicking on a missing summary.
|
|
501
|
+
# v0.6.26 / §5.5 Layer 6: when structured_output is empty BUT inline
|
|
502
|
+
# findings were posted before the budget exhausted (tokenomics #21
|
|
503
|
+
# pattern), scrape the inline findings via gh api and render a
|
|
504
|
+
# synthetic summary that cites the real findings. Avoids the
|
|
505
|
+
# "0-findings-shown / 5-inline-posted" failure mode where the
|
|
506
|
+
# maintainer reading the PR sees a meaningless empty summary even
|
|
507
|
+
# though the review actually surfaced issues.
|
|
508
|
+
#
|
|
509
|
+
# If NO inline findings were posted either, falls through to the
|
|
510
|
+
# original advisory bare-H2 (legacy v0.6.22 behaviour).
|
|
437
511
|
- name: Fallback summary (structured_output empty)
|
|
438
512
|
if: success() && steps.clud-bug-review.outputs.structured_output == ''
|
|
439
513
|
env:
|
|
440
514
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
441
515
|
PR_NUMBER: ${{ github.event.pull_request.number }}
|
|
516
|
+
REPO: ${{ github.repository }}
|
|
517
|
+
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
|
518
|
+
TURNS_ESTIMATED: ${{ needs.paths-check.outputs.turns_estimated }}
|
|
519
|
+
MAX_TURNS: ${{ needs.paths-check.outputs.max_turns }}
|
|
520
|
+
FILES_COUNT: ${{ needs.paths-check.outputs.files_count }}
|
|
521
|
+
LINES_ADDED: ${{ needs.paths-check.outputs.lines_added }}
|
|
522
|
+
LINES_DELETED: ${{ needs.paths-check.outputs.lines_deleted }}
|
|
523
|
+
THREADS_COUNT: ${{ needs.paths-check.outputs.threads_count }}
|
|
442
524
|
run: |
|
|
443
525
|
set -euo pipefail
|
|
444
|
-
|
|
526
|
+
|
|
527
|
+
# Layer 6: count inline findings claude[bot] posted on THIS
|
|
528
|
+
# head SHA via the inline-review-thread endpoint. Filter to
|
|
529
|
+
# the current SHA so older review-pass findings don't inflate
|
|
530
|
+
# the count.
|
|
531
|
+
INLINES=$(gh api "repos/$REPO/pulls/$PR_NUMBER/comments?per_page=100" \
|
|
532
|
+
--jq "[.[] | select(.user.login == \"claude[bot]\" and .commit_id == \"$HEAD_SHA\")]")
|
|
533
|
+
INLINE_COUNT=$(echo "$INLINES" | jq 'length')
|
|
534
|
+
CRITICAL=$(echo "$INLINES" | jq '[.[] | select(.body | test("🔴"))] | length')
|
|
535
|
+
MINOR=$(echo "$INLINES" | jq '[.[] | select(.body | test("🟡"))] | length')
|
|
536
|
+
PREEXISTING=$(echo "$INLINES" | jq '[.[] | select(.body | test("🟣"))] | length')
|
|
537
|
+
# Findings with no emoji prefix (cross-cutting / un-prefixed) — count once.
|
|
538
|
+
UNPREFIXED=$(( INLINE_COUNT - CRITICAL - MINOR - PREEXISTING ))
|
|
539
|
+
[ "$UNPREFIXED" -lt 0 ] && UNPREFIXED=0
|
|
540
|
+
|
|
541
|
+
CALIBRATION="<!-- clud-bug-calibration: turns_estimated=$TURNS_ESTIMATED, max_turns=$MAX_TURNS, files=$FILES_COUNT, lines_added=$LINES_ADDED, lines_deleted=$LINES_DELETED, threads=$THREADS_COUNT, structured_output=empty, inline_findings=$INLINE_COUNT -->"
|
|
542
|
+
|
|
543
|
+
if [ "$INLINE_COUNT" -gt 0 ]; then
|
|
544
|
+
# L6 synthetic summary — cites the real inline findings the
|
|
545
|
+
# action managed to post before structured-output emit failed.
|
|
546
|
+
STATUS=""
|
|
547
|
+
[ "$CRITICAL" -gt 0 ] && STATUS=" — critical findings"
|
|
548
|
+
gh pr comment "$PR_NUMBER" --body "## 🐛 Clud Bug review${STATUS}
|
|
549
|
+
|
|
550
|
+
**This round:** $CRITICAL critical · $MINOR minor · 0 resolved from prior · 0 still open
|
|
551
|
+
|
|
552
|
+
Found: $CRITICAL 🔴 / $MINOR 🟡 / $PREEXISTING 🟣
|
|
553
|
+
|
|
554
|
+
⚠️ **Synthetic summary** (v0.6.26 §5.5 Layer 6 fallback) — the action posted $INLINE_COUNT inline finding(s) before the structured-output emit step exhausted its turn budget (or hit schema-validation retries). The inline findings above ARE the substantive review; this summary is reconstructed from them. v0.6.26's Layer 5 (auto-retry on cap-hit) is the more permanent fix; this is the safety net.
|
|
555
|
+
|
|
556
|
+
<!-- last-reviewed-sha: $HEAD_SHA -->
|
|
557
|
+
|
|
558
|
+
$CALIBRATION"
|
|
559
|
+
else
|
|
560
|
+
# No inline findings either — legacy bare-H2 advisory. The
|
|
561
|
+
# action errored before it could post anything substantive.
|
|
562
|
+
gh pr comment "$PR_NUMBER" --body "## 🐛 Clud Bug review
|
|
445
563
|
|
|
446
564
|
**This round:** 0 critical · 0 minor · 0 resolved from prior · 0 still open
|
|
447
565
|
|
|
448
566
|
Found: 0 🔴 / 0 🟡 / 0 🟣
|
|
449
567
|
|
|
450
|
-
⚠️ Structured output (\`--json-schema\`) returned empty
|
|
568
|
+
⚠️ Structured output (\`--json-schema\`) returned empty AND no inline findings were posted. The action likely errored before producing review output — investigate the run logs.
|
|
569
|
+
|
|
570
|
+
Skills referenced: [none]
|
|
451
571
|
|
|
452
|
-
|
|
572
|
+
<!-- last-reviewed-sha: $HEAD_SHA -->
|
|
573
|
+
|
|
574
|
+
$CALIBRATION"
|
|
575
|
+
fi
|
|
453
576
|
|
|
454
577
|
# Strict-mode gate. Fails the check when the BASE ref's manifest
|
|
455
578
|
# has { "strictMode": true } AND the latest clud-bug review's first
|
|
@@ -466,7 +589,7 @@ jobs:
|
|
|
466
589
|
# Letting the action's own failure fail the check is louder and right.
|
|
467
590
|
- name: Strict mode — fail check on critical findings
|
|
468
591
|
if: success()
|
|
469
|
-
uses: thrillmade/clud-bug/.github/actions/strict-mode-gate@v0.6.
|
|
592
|
+
uses: thrillmade/clud-bug/.github/actions/strict-mode-gate@v0.6.27
|
|
470
593
|
with:
|
|
471
594
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
472
595
|
# v0.6.22 / 0.0.O: the summary is now posted by the workflow
|