clud-bug 0.6.34 → 0.7.0-rc.11
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/README.md +20 -0
- package/bin/clud-bug.js +10 -1353
- package/data/canonical-v1.json +37 -0
- package/dist/cli/agents-md.d.ts +16 -0
- package/dist/cli/agents-md.d.ts.map +1 -0
- package/dist/cli/agents-md.js +226 -0
- package/dist/cli/agents-md.js.map +1 -0
- package/dist/cli/audit.d.ts +13 -0
- package/dist/cli/audit.d.ts.map +1 -0
- package/dist/cli/audit.js +90 -0
- package/dist/cli/audit.js.map +1 -0
- package/dist/cli/branch-protection.d.ts +57 -0
- package/dist/cli/branch-protection.d.ts.map +1 -0
- package/dist/cli/branch-protection.js +118 -0
- package/dist/cli/branch-protection.js.map +1 -0
- package/dist/cli/configure-github.d.ts +58 -0
- package/dist/cli/configure-github.d.ts.map +1 -0
- package/dist/cli/configure-github.js +242 -0
- package/dist/cli/configure-github.js.map +1 -0
- package/dist/cli/edit-workflow.d.ts +18 -0
- package/dist/cli/edit-workflow.d.ts.map +1 -0
- package/dist/cli/edit-workflow.js +43 -0
- package/dist/cli/edit-workflow.js.map +1 -0
- package/dist/cli/index.d.ts +9 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +19 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/main.d.ts +3 -0
- package/dist/cli/main.d.ts.map +1 -0
- package/dist/cli/main.js +2067 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/cli/skill-usage.d.ts +109 -0
- package/dist/cli/skill-usage.d.ts.map +1 -0
- package/dist/cli/skill-usage.js +380 -0
- package/dist/cli/skill-usage.js.map +1 -0
- package/dist/cli/skills.d.ts +56 -0
- package/dist/cli/skills.d.ts.map +1 -0
- package/dist/cli/skills.js +292 -0
- package/dist/cli/skills.js.map +1 -0
- package/dist/cli/update.d.ts +29 -0
- package/dist/cli/update.d.ts.map +1 -0
- package/dist/cli/update.js +205 -0
- package/dist/cli/update.js.map +1 -0
- package/dist/cli/usage.d.ts +142 -0
- package/dist/cli/usage.d.ts.map +1 -0
- package/dist/cli/usage.js +348 -0
- package/dist/cli/usage.js.map +1 -0
- package/dist/core/audit.d.ts +8 -0
- package/dist/core/audit.d.ts.map +1 -0
- package/dist/core/audit.js +47 -0
- package/dist/core/audit.js.map +1 -0
- package/dist/core/auto-resolve.d.ts +235 -0
- package/dist/core/auto-resolve.d.ts.map +1 -0
- package/dist/core/auto-resolve.js +293 -0
- package/dist/core/auto-resolve.js.map +1 -0
- package/dist/core/configure-github.d.ts +179 -0
- package/dist/core/configure-github.d.ts.map +1 -0
- package/dist/core/configure-github.js +289 -0
- package/dist/core/configure-github.js.map +1 -0
- package/dist/core/detect.d.ts +77 -0
- package/dist/core/detect.d.ts.map +1 -0
- package/dist/core/detect.js +262 -0
- package/dist/core/detect.js.map +1 -0
- package/dist/core/diff-findings.d.ts +96 -0
- package/dist/core/diff-findings.d.ts.map +1 -0
- package/dist/core/diff-findings.js +261 -0
- package/dist/core/diff-findings.js.map +1 -0
- package/dist/core/formal-review.d.ts +79 -0
- package/dist/core/formal-review.d.ts.map +1 -0
- package/dist/core/formal-review.js +71 -0
- package/dist/core/formal-review.js.map +1 -0
- package/dist/core/index.d.ts +17 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +66 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/inline-threads.d.ts +160 -0
- package/dist/core/inline-threads.d.ts.map +1 -0
- package/dist/core/inline-threads.js +369 -0
- package/dist/core/inline-threads.js.map +1 -0
- package/dist/core/prompt-builder.d.ts +164 -0
- package/dist/core/prompt-builder.d.ts.map +1 -0
- package/dist/core/prompt-builder.js +419 -0
- package/dist/core/prompt-builder.js.map +1 -0
- package/dist/core/prompts.d.ts +9 -0
- package/dist/core/prompts.d.ts.map +1 -0
- package/dist/core/prompts.js +401 -0
- package/dist/core/prompts.js.map +1 -0
- package/dist/core/render-review.d.ts +6 -0
- package/dist/core/render-review.d.ts.map +1 -0
- package/dist/core/render-review.js +219 -0
- package/dist/core/render-review.js.map +1 -0
- package/dist/core/render.d.ts +13 -0
- package/dist/core/render.d.ts.map +1 -0
- package/dist/core/render.js +62 -0
- package/dist/core/render.js.map +1 -0
- package/dist/core/resolve-verifier.d.ts +46 -0
- package/dist/core/resolve-verifier.d.ts.map +1 -0
- package/dist/core/resolve-verifier.js +187 -0
- package/dist/core/resolve-verifier.js.map +1 -0
- package/dist/core/review-schema-zod.d.ts +240 -0
- package/dist/core/review-schema-zod.d.ts.map +1 -0
- package/dist/core/review-schema-zod.js +218 -0
- package/dist/core/review-schema-zod.js.map +1 -0
- package/dist/core/review-schema.d.ts +42 -0
- package/dist/core/review-schema.d.ts.map +1 -0
- package/dist/core/review-schema.js +156 -0
- package/dist/core/review-schema.js.map +1 -0
- package/dist/core/review-writeback.d.ts +193 -0
- package/dist/core/review-writeback.d.ts.map +1 -0
- package/dist/core/review-writeback.js +364 -0
- package/dist/core/review-writeback.js.map +1 -0
- package/dist/core/skills.d.ts +147 -0
- package/dist/core/skills.d.ts.map +1 -0
- package/dist/core/skills.js +726 -0
- package/dist/core/skills.js.map +1 -0
- package/dist/core/version.d.ts +2 -0
- package/dist/core/version.d.ts.map +1 -0
- package/dist/core/version.js +4 -0
- package/dist/core/version.js.map +1 -0
- package/package.json +37 -5
- package/{lib/agents-md.js → src/cli/agents-md.ts} +25 -14
- package/{lib/audit.js → src/cli/audit.ts} +37 -44
- package/{lib/branch-protection.js → src/cli/branch-protection.ts} +75 -11
- package/src/cli/configure-github.ts +329 -0
- package/{lib/edit-workflow.js → src/cli/edit-workflow.ts} +32 -11
- package/src/cli/index.ts +107 -0
- package/src/cli/main.ts +2204 -0
- package/{lib/skill-usage.js → src/cli/skill-usage.ts} +168 -94
- package/src/cli/skills.ts +386 -0
- package/{lib/update.js → src/cli/update.ts} +87 -27
- package/{lib/usage.js → src/cli/usage.ts} +167 -76
- package/src/core/audit.ts +53 -0
- package/src/core/auto-resolve.ts +488 -0
- package/src/core/configure-github.ts +497 -0
- package/{lib/detect.js → src/core/detect.ts} +100 -47
- package/src/core/diff-findings.ts +323 -0
- package/src/core/formal-review.ts +168 -0
- package/src/core/index.ts +250 -0
- package/src/core/inline-threads.ts +471 -0
- package/src/core/prompt-builder.ts +561 -0
- package/{lib/prompts.js → src/core/prompts.ts} +16 -2
- package/{lib/render-review.js → src/core/render-review.ts} +57 -25
- package/{lib/render.js → src/core/render.ts} +37 -17
- package/src/core/resolve-verifier.ts +228 -0
- package/src/core/review-schema-zod.ts +262 -0
- package/{lib/review-schema.js → src/core/review-schema.ts} +68 -5
- package/src/core/review-writeback.ts +565 -0
- package/{lib/skills.js → src/core/skills.ts} +456 -342
- package/src/core/version.ts +3 -0
- package/templates/clud-bug-review.md.tmpl +115 -0
- package/templates/workflow-py.yml.tmpl +80 -3
- package/templates/workflow-ts.yml.tmpl +80 -3
- package/templates/workflow.yml.tmpl +175 -8
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Review the current branch's open PR locally, in this Claude Code session
|
|
3
|
+
argument-hint: "[pr-number]"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
<!-- clud-bug-local-version: v1 -->
|
|
7
|
+
|
|
8
|
+
You are running **clud-bug** as a local code review — inside this Claude Code
|
|
9
|
+
session, using this session's own model tokens (Max or API, whatever you have).
|
|
10
|
+
No hosted App, no extra auth: you already have `gh`, `git`, and file access.
|
|
11
|
+
|
|
12
|
+
## 1. Find the PR
|
|
13
|
+
|
|
14
|
+
PR number: `$ARGUMENTS`
|
|
15
|
+
|
|
16
|
+
If `$ARGUMENTS` is empty, detect the current branch's open PR:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
gh pr list --head "$(git branch --show-current)" --state open --json number --jq '.[0].number'
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
If there is no open PR, stop and tell the user to open one (or pass a PR number).
|
|
23
|
+
|
|
24
|
+
## 2. Load the review skills
|
|
25
|
+
|
|
26
|
+
Read the manifest and every referenced skill body from the checkout:
|
|
27
|
+
|
|
28
|
+
- `.claude/skills/.clud-bug.json` — which skills are installed, plus `strictMode`.
|
|
29
|
+
- For each installed skill, `.claude/skills/<name>/SKILL.md` — the discipline to apply.
|
|
30
|
+
|
|
31
|
+
Load skills **before** the diff. At minimum the baseline set applies:
|
|
32
|
+
**critical-issues-only** (flag only correctness / security / performance — skip
|
|
33
|
+
nits), **evidence-based-review** (quote the exact line you criticize — no
|
|
34
|
+
hand-waving), **respect-existing-conventions** (don't fight the codebase's
|
|
35
|
+
established patterns).
|
|
36
|
+
|
|
37
|
+
## 3. Fetch the diff
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
gh pr diff <PR_NUMBER>
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## 4. Review
|
|
44
|
+
|
|
45
|
+
Review the diff against every loaded skill. For each finding record: `file`,
|
|
46
|
+
`line`, `severity` (`critical` | `minor` | `preexisting`), the `skill` that
|
|
47
|
+
motivated it, and a one-line `summary`. Apply the skills strictly — especially
|
|
48
|
+
critical-issues-only (no nits) and evidence-based-review (quote the code).
|
|
49
|
+
|
|
50
|
+
## 5. Render the review comment
|
|
51
|
+
|
|
52
|
+
Build the body in clud-bug's standard shape (omit any empty findings section):
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
## 🐛 Clud Bug review — <clean | critical findings>
|
|
56
|
+
|
|
57
|
+
**This round:** N critical · N minor · N resolved from prior · N still open
|
|
58
|
+
|
|
59
|
+
Found: N 🔴 / N 🟡 / N 🟣
|
|
60
|
+
|
|
61
|
+
### Per-skill scan
|
|
62
|
+
- [<skill>]: <one line on what it scanned + found>
|
|
63
|
+
|
|
64
|
+
### Critical findings
|
|
65
|
+
🔴 [<skill>]: <summary> (<file>:<line>).
|
|
66
|
+
|
|
67
|
+
### Minor findings
|
|
68
|
+
🟡 [<skill>]: <summary> (<file>:<line>).
|
|
69
|
+
|
|
70
|
+
### Pre-existing findings
|
|
71
|
+
🟣 [<skill>]: <summary> (<file>:<line>).
|
|
72
|
+
|
|
73
|
+
Skills referenced: [<skill>, <skill>]
|
|
74
|
+
|
|
75
|
+
<!-- written-by: @<your-gh-login> (clud-bug local-mode) -->
|
|
76
|
+
<!-- review-sha: <HEAD_SHA> -->
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Get your gh login with `gh api user --jq .login` and the head sha with
|
|
80
|
+
`git rev-parse HEAD`. The `written-by` marker **MUST** end with
|
|
81
|
+
`(clud-bug local-mode)` so the bot's auto-resolve never mistakes this for a
|
|
82
|
+
`clud-bug[bot]` comment.
|
|
83
|
+
|
|
84
|
+
## 6. Post (or update) the comment
|
|
85
|
+
|
|
86
|
+
Look for an existing local-mode comment and edit it in place (one rolling review
|
|
87
|
+
comment), otherwise post a fresh one. Use the **REST** issues-comments endpoint
|
|
88
|
+
for the lookup — its `.id` is the **integer** comment id the PATCH endpoint needs.
|
|
89
|
+
(Do NOT use `gh pr view --json comments`; that returns GraphQL node IDs, which
|
|
90
|
+
404 on the REST PATCH and cause duplicate comments.) `gh` fills `{owner}/{repo}`.
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
# existing local-mode comment id (integer), if any:
|
|
94
|
+
EXISTING_ID=$(gh api --paginate "repos/{owner}/{repo}/issues/<PR_NUMBER>/comments" \
|
|
95
|
+
--jq '[.[] | select(.body | test("written-by: @.* \\(clud-bug local-mode\\)"))] | first | .id // empty')
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
- `$EXISTING_ID` empty → `gh pr comment <PR_NUMBER> --body-file <body.md>`
|
|
99
|
+
- `$EXISTING_ID` set → `gh api "repos/{owner}/{repo}/issues/comments/$EXISTING_ID" -X PATCH -F body=@<body.md>`
|
|
100
|
+
|
|
101
|
+
## 7. Summarize
|
|
102
|
+
|
|
103
|
+
Print one line:
|
|
104
|
+
`clud-bug local-review: N critical · N minor · N preexisting — <PASS | FAIL (strictMode) | advisory>`
|
|
105
|
+
|
|
106
|
+
If `.clud-bug.json` has `strictMode: true` and there are critical findings, say
|
|
107
|
+
**FAIL** and tell the user to fix them before merging.
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
_Optional: if the `clud-bug-mcp` MCP server is connected, you may use its
|
|
112
|
+
structured tools (`load_skills_from_pr_base`, `fetch_pr_diff`,
|
|
113
|
+
`partition_findings_by_severity`, `emit_review_comment`) in place of the raw
|
|
114
|
+
`gh`/`git` calls above — same flow, with the base-ref skill read and the exact
|
|
115
|
+
review rendering done for you._
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# clud-bug-template-version:
|
|
1
|
+
# clud-bug-template-version: v14
|
|
2
2
|
name: Clud Bug 🐛 Crawls Your Code
|
|
3
3
|
|
|
4
4
|
on:
|
|
@@ -222,7 +222,7 @@ jobs:
|
|
|
222
222
|
# HEAD_SHA (v0.6.10+) — see workflow.yml.tmpl for design notes.
|
|
223
223
|
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
|
224
224
|
# Per-section byte budgets — see workflow.yml.tmpl for design notes.
|
|
225
|
-
MAX_DIFF_BYTES: '
|
|
225
|
+
MAX_DIFF_BYTES: '5000000'
|
|
226
226
|
MAX_COMMENT_BYTES: '20000'
|
|
227
227
|
MAX_SKILL_BYTES: '4000'
|
|
228
228
|
# Thinking-budget cap (v0.6.8) — see workflow.yml.tmpl for design notes.
|
|
@@ -283,6 +283,40 @@ jobs:
|
|
|
283
283
|
|
|
284
284
|
$CALIBRATION"
|
|
285
285
|
|
|
286
|
+
# Wave 5a (D.2.X) — see workflow.yml.tmpl for design notes.
|
|
287
|
+
- name: Post inline review threads
|
|
288
|
+
if: success() && steps.clud-bug-review.outputs.structured_output != ''
|
|
289
|
+
continue-on-error: true
|
|
290
|
+
env:
|
|
291
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
292
|
+
REPO: ${{ github.repository }}
|
|
293
|
+
PR_NUMBER: ${{ github.event.pull_request.number }}
|
|
294
|
+
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
|
295
|
+
STRUCTURED: ${{ steps.clud-bug-review.outputs.structured_output }}
|
|
296
|
+
run: |
|
|
297
|
+
set -euo pipefail
|
|
298
|
+
RESULT=$(printf '%s\n' "$STRUCTURED" | npx --yes clud-bug@{{CLUD_BUG_VERSION}} post-inline-threads --stdin)
|
|
299
|
+
echo "::notice title=inline-threads::$RESULT"
|
|
300
|
+
|
|
301
|
+
# Wave 5b (D.2.6) — see workflow.yml.tmpl for design notes.
|
|
302
|
+
- name: Auto-resolve fixed threads
|
|
303
|
+
if: success() && github.event.action == 'synchronize'
|
|
304
|
+
continue-on-error: true
|
|
305
|
+
env:
|
|
306
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
307
|
+
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
308
|
+
REPO: ${{ github.repository }}
|
|
309
|
+
PR_NUMBER: ${{ github.event.pull_request.number }}
|
|
310
|
+
# Optional fine-grained PAT (Pull requests: write). Present → the
|
|
311
|
+
# workflow resolves fixed threads like the hosted App. Absent (the
|
|
312
|
+
# default; an unset secret renders empty) → graceful "verified fixed"
|
|
313
|
+
# reply only, since the Actions GITHUB_TOKEN can't resolve threads.
|
|
314
|
+
CLUD_BUG_RESOLVE_PAT: ${{ secrets.CLUD_BUG_RESOLVE_PAT }}
|
|
315
|
+
run: |
|
|
316
|
+
set -euo pipefail
|
|
317
|
+
RESULT=$(npx --yes clud-bug@{{CLUD_BUG_VERSION}} resolve-threads)
|
|
318
|
+
echo "::notice title=auto-resolve::$RESULT"
|
|
319
|
+
|
|
286
320
|
# v0.6.29 / Component 4 — see workflow.yml.tmpl for design notes.
|
|
287
321
|
- name: Update skill-usage tracking
|
|
288
322
|
if: success() && steps.clud-bug-review.outputs.structured_output != ''
|
|
@@ -366,9 +400,52 @@ jobs:
|
|
|
366
400
|
# Strict-mode gate — composite action; see workflow.yml.tmpl for design notes.
|
|
367
401
|
- name: Strict mode — fail check on critical findings
|
|
368
402
|
if: success()
|
|
369
|
-
uses: thrillmade/clud-bug/.github/actions/strict-mode-gate@v0.
|
|
403
|
+
uses: thrillmade/clud-bug/.github/actions/strict-mode-gate@v0.7.0-rc.11
|
|
370
404
|
with:
|
|
371
405
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
372
406
|
# v0.6.22 / 0.0.O: summary now posted by github-actions[bot].
|
|
373
407
|
# See workflow.yml.tmpl for design notes.
|
|
374
408
|
bot-login: 'github-actions[bot]'
|
|
409
|
+
|
|
410
|
+
# v0.7.0-rc.3 — SPEC §7.2.1 formal-review event poster.
|
|
411
|
+
# See workflow.yml.tmpl for full design rationale; this step
|
|
412
|
+
# bridges the canonical-ruleset `required_approving_review_count: 1`
|
|
413
|
+
# floor on the npm workflow path. Best-effort: never fails the
|
|
414
|
+
# workflow (continue-on-error). Drive-by exploit guard: external
|
|
415
|
+
# contributors NEVER get APPROVE.
|
|
416
|
+
- name: Formal review — APPROVE / REQUEST_CHANGES / COMMENT
|
|
417
|
+
if: always() && steps.clud-bug-review.outputs.structured_output != ''
|
|
418
|
+
continue-on-error: true
|
|
419
|
+
env:
|
|
420
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
421
|
+
PR_NUMBER: ${{ github.event.pull_request.number }}
|
|
422
|
+
REPO: ${{ github.repository }}
|
|
423
|
+
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
|
424
|
+
STRUCTURED: ${{ steps.clud-bug-review.outputs.structured_output }}
|
|
425
|
+
PR_AUTHOR_LOGIN: ${{ github.event.pull_request.user.login }}
|
|
426
|
+
PR_AUTHOR_ASSOCIATION: ${{ github.event.pull_request.author_association }}
|
|
427
|
+
BASE_REF: ${{ github.event.pull_request.base.ref }}
|
|
428
|
+
run: |
|
|
429
|
+
set -uo pipefail
|
|
430
|
+
STRICT_MODE=false
|
|
431
|
+
if git show "origin/${BASE_REF}:.claude/skills/.clud-bug.json" > /tmp/base-manifest.json 2>/dev/null; then
|
|
432
|
+
if jq -e '.strictMode == true' /tmp/base-manifest.json > /dev/null 2>&1; then
|
|
433
|
+
STRICT_MODE=true
|
|
434
|
+
fi
|
|
435
|
+
fi
|
|
436
|
+
export STRICT_MODE
|
|
437
|
+
VERDICT=$(printf '%s\n' "$STRUCTURED" \
|
|
438
|
+
| npx --yes clud-bug@{{CLUD_BUG_VERSION}} select-review-event --stdin \
|
|
439
|
+
| tail -n1)
|
|
440
|
+
VERDICT="${VERDICT:-skip}"
|
|
441
|
+
echo "::notice title=Clud Bug 🐛::Formal review verdict: $VERDICT (strictMode=$STRICT_MODE, author_assoc=$PR_AUTHOR_ASSOCIATION)"
|
|
442
|
+
if [ "$VERDICT" = "skip" ]; then
|
|
443
|
+
exit 0
|
|
444
|
+
fi
|
|
445
|
+
BODY=$(printf 'Automated formal review by clud-bug — see the summary comment for the substantive findings.\n\nVerdict: **%s**\n\n<!-- clud-bug-formal-review: workflow-path v0.7.0-rc.3 -->' "$VERDICT")
|
|
446
|
+
gh api -X POST "/repos/$REPO/pulls/$PR_NUMBER/reviews" \
|
|
447
|
+
-f event="$VERDICT" \
|
|
448
|
+
-f commit_id="$HEAD_SHA" \
|
|
449
|
+
-f body="$BODY" \
|
|
450
|
+
> /dev/null \
|
|
451
|
+
|| echo "::warning title=Clud Bug 🐛::Formal review POST failed (likely 422 self-PR or missing perms); degrading to comment-only."
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# clud-bug-template-version:
|
|
1
|
+
# clud-bug-template-version: v14
|
|
2
2
|
name: Clud Bug 🐛 Crawls Your Code
|
|
3
3
|
|
|
4
4
|
on:
|
|
@@ -222,7 +222,7 @@ jobs:
|
|
|
222
222
|
# HEAD_SHA (v0.6.10+) — see workflow.yml.tmpl for design notes.
|
|
223
223
|
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
|
224
224
|
# Per-section byte budgets — see workflow.yml.tmpl for design notes.
|
|
225
|
-
MAX_DIFF_BYTES: '
|
|
225
|
+
MAX_DIFF_BYTES: '5000000'
|
|
226
226
|
MAX_COMMENT_BYTES: '20000'
|
|
227
227
|
MAX_SKILL_BYTES: '4000'
|
|
228
228
|
# Thinking-budget cap (v0.6.8) — see workflow.yml.tmpl for design notes.
|
|
@@ -283,6 +283,40 @@ jobs:
|
|
|
283
283
|
|
|
284
284
|
$CALIBRATION"
|
|
285
285
|
|
|
286
|
+
# Wave 5a (D.2.X) — see workflow.yml.tmpl for design notes.
|
|
287
|
+
- name: Post inline review threads
|
|
288
|
+
if: success() && steps.clud-bug-review.outputs.structured_output != ''
|
|
289
|
+
continue-on-error: true
|
|
290
|
+
env:
|
|
291
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
292
|
+
REPO: ${{ github.repository }}
|
|
293
|
+
PR_NUMBER: ${{ github.event.pull_request.number }}
|
|
294
|
+
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
|
295
|
+
STRUCTURED: ${{ steps.clud-bug-review.outputs.structured_output }}
|
|
296
|
+
run: |
|
|
297
|
+
set -euo pipefail
|
|
298
|
+
RESULT=$(printf '%s\n' "$STRUCTURED" | npx --yes clud-bug@{{CLUD_BUG_VERSION}} post-inline-threads --stdin)
|
|
299
|
+
echo "::notice title=inline-threads::$RESULT"
|
|
300
|
+
|
|
301
|
+
# Wave 5b (D.2.6) — see workflow.yml.tmpl for design notes.
|
|
302
|
+
- name: Auto-resolve fixed threads
|
|
303
|
+
if: success() && github.event.action == 'synchronize'
|
|
304
|
+
continue-on-error: true
|
|
305
|
+
env:
|
|
306
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
307
|
+
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
308
|
+
REPO: ${{ github.repository }}
|
|
309
|
+
PR_NUMBER: ${{ github.event.pull_request.number }}
|
|
310
|
+
# Optional fine-grained PAT (Pull requests: write). Present → the
|
|
311
|
+
# workflow resolves fixed threads like the hosted App. Absent (the
|
|
312
|
+
# default; an unset secret renders empty) → graceful "verified fixed"
|
|
313
|
+
# reply only, since the Actions GITHUB_TOKEN can't resolve threads.
|
|
314
|
+
CLUD_BUG_RESOLVE_PAT: ${{ secrets.CLUD_BUG_RESOLVE_PAT }}
|
|
315
|
+
run: |
|
|
316
|
+
set -euo pipefail
|
|
317
|
+
RESULT=$(npx --yes clud-bug@{{CLUD_BUG_VERSION}} resolve-threads)
|
|
318
|
+
echo "::notice title=auto-resolve::$RESULT"
|
|
319
|
+
|
|
286
320
|
# v0.6.29 / Component 4 — see workflow.yml.tmpl for design notes.
|
|
287
321
|
- name: Update skill-usage tracking
|
|
288
322
|
if: success() && steps.clud-bug-review.outputs.structured_output != ''
|
|
@@ -366,9 +400,52 @@ jobs:
|
|
|
366
400
|
# Strict-mode gate — composite action; see workflow.yml.tmpl for design notes.
|
|
367
401
|
- name: Strict mode — fail check on critical findings
|
|
368
402
|
if: success()
|
|
369
|
-
uses: thrillmade/clud-bug/.github/actions/strict-mode-gate@v0.
|
|
403
|
+
uses: thrillmade/clud-bug/.github/actions/strict-mode-gate@v0.7.0-rc.11
|
|
370
404
|
with:
|
|
371
405
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
372
406
|
# v0.6.22 / 0.0.O: summary now posted by github-actions[bot].
|
|
373
407
|
# See workflow.yml.tmpl for design notes.
|
|
374
408
|
bot-login: 'github-actions[bot]'
|
|
409
|
+
|
|
410
|
+
# v0.7.0-rc.3 — SPEC §7.2.1 formal-review event poster.
|
|
411
|
+
# See workflow.yml.tmpl for full design rationale; this step
|
|
412
|
+
# bridges the canonical-ruleset `required_approving_review_count: 1`
|
|
413
|
+
# floor on the npm workflow path. Best-effort: never fails the
|
|
414
|
+
# workflow (continue-on-error). Drive-by exploit guard: external
|
|
415
|
+
# contributors NEVER get APPROVE.
|
|
416
|
+
- name: Formal review — APPROVE / REQUEST_CHANGES / COMMENT
|
|
417
|
+
if: always() && steps.clud-bug-review.outputs.structured_output != ''
|
|
418
|
+
continue-on-error: true
|
|
419
|
+
env:
|
|
420
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
421
|
+
PR_NUMBER: ${{ github.event.pull_request.number }}
|
|
422
|
+
REPO: ${{ github.repository }}
|
|
423
|
+
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
|
424
|
+
STRUCTURED: ${{ steps.clud-bug-review.outputs.structured_output }}
|
|
425
|
+
PR_AUTHOR_LOGIN: ${{ github.event.pull_request.user.login }}
|
|
426
|
+
PR_AUTHOR_ASSOCIATION: ${{ github.event.pull_request.author_association }}
|
|
427
|
+
BASE_REF: ${{ github.event.pull_request.base.ref }}
|
|
428
|
+
run: |
|
|
429
|
+
set -uo pipefail
|
|
430
|
+
STRICT_MODE=false
|
|
431
|
+
if git show "origin/${BASE_REF}:.claude/skills/.clud-bug.json" > /tmp/base-manifest.json 2>/dev/null; then
|
|
432
|
+
if jq -e '.strictMode == true' /tmp/base-manifest.json > /dev/null 2>&1; then
|
|
433
|
+
STRICT_MODE=true
|
|
434
|
+
fi
|
|
435
|
+
fi
|
|
436
|
+
export STRICT_MODE
|
|
437
|
+
VERDICT=$(printf '%s\n' "$STRUCTURED" \
|
|
438
|
+
| npx --yes clud-bug@{{CLUD_BUG_VERSION}} select-review-event --stdin \
|
|
439
|
+
| tail -n1)
|
|
440
|
+
VERDICT="${VERDICT:-skip}"
|
|
441
|
+
echo "::notice title=Clud Bug 🐛::Formal review verdict: $VERDICT (strictMode=$STRICT_MODE, author_assoc=$PR_AUTHOR_ASSOCIATION)"
|
|
442
|
+
if [ "$VERDICT" = "skip" ]; then
|
|
443
|
+
exit 0
|
|
444
|
+
fi
|
|
445
|
+
BODY=$(printf 'Automated formal review by clud-bug — see the summary comment for the substantive findings.\n\nVerdict: **%s**\n\n<!-- clud-bug-formal-review: workflow-path v0.7.0-rc.3 -->' "$VERDICT")
|
|
446
|
+
gh api -X POST "/repos/$REPO/pulls/$PR_NUMBER/reviews" \
|
|
447
|
+
-f event="$VERDICT" \
|
|
448
|
+
-f commit_id="$HEAD_SHA" \
|
|
449
|
+
-f body="$BODY" \
|
|
450
|
+
> /dev/null \
|
|
451
|
+
|| echo "::warning title=Clud Bug 🐛::Formal review POST failed (likely 422 self-PR or missing perms); degrading to comment-only."
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# clud-bug-template-version:
|
|
1
|
+
# clud-bug-template-version: v14
|
|
2
2
|
name: Clud Bug 🐛 Crawls Your Code
|
|
3
3
|
|
|
4
4
|
on:
|
|
@@ -396,12 +396,21 @@ jobs:
|
|
|
396
396
|
# <prior_sha>..HEAD` (delta) when the SHA is still in HEAD's
|
|
397
397
|
# ancestry. Fix-push reviews ingest only the new bytes.
|
|
398
398
|
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
|
399
|
-
# Per-section byte budgets (v0.6.4
|
|
400
|
-
# Claude to cap each per-PR input fetch
|
|
401
|
-
# covers the stable system prefix; capping
|
|
402
|
-
# suffix (diff, comments, skills). Override
|
|
403
|
-
# these env vars in the consuming workflow if
|
|
404
|
-
|
|
399
|
+
# Per-section byte budgets (v0.6.4, MAX_DIFF_BYTES bumped 2026-06-08).
|
|
400
|
+
# The system-prompt instructs Claude to cap each per-PR input fetch
|
|
401
|
+
# with `head -c`. Caching covers the stable system prefix; capping
|
|
402
|
+
# covers the variable suffix (diff, comments, skills). Override
|
|
403
|
+
# per-repo by setting these env vars in the consuming workflow if
|
|
404
|
+
# defaults don't fit.
|
|
405
|
+
#
|
|
406
|
+
# 2026-06-08 CEO directive (v0.6.35): MAX_DIFF_BYTES bumped from
|
|
407
|
+
# 80000 (80KB) → 5000000 (5MB). The old default silently truncated
|
|
408
|
+
# any PR diff > 80KB, leading to half-reviews on real-world PRs.
|
|
409
|
+
# CEO: "a large diff should NEVER be a blocker or guard." 5MB is
|
|
410
|
+
# far above realistic single-PR diff sizes but bounded enough that
|
|
411
|
+
# the runner doesn't OOM. Repos that want stricter discipline can
|
|
412
|
+
# still set lower values per-repo.
|
|
413
|
+
MAX_DIFF_BYTES: '5000000'
|
|
405
414
|
MAX_COMMENT_BYTES: '20000'
|
|
406
415
|
MAX_SKILL_BYTES: '4000'
|
|
407
416
|
# MAX_THINKING_TOKENS caps Claude Code's extended-thinking budget per
|
|
@@ -494,6 +503,69 @@ jobs:
|
|
|
494
503
|
|
|
495
504
|
$CALIBRATION"
|
|
496
505
|
|
|
506
|
+
# v0.7.0-rc.7 / Wave 5a (D.2.X): post per-finding inline review
|
|
507
|
+
# threads alongside the summary comment. Each thread is anchored
|
|
508
|
+
# to a file + line in the diff and is a first-class GitHub review
|
|
509
|
+
# thread users can reply to. Each thread body carries a hidden
|
|
510
|
+
# `<!-- finding-id: <hash> -->` marker so Wave 5b (rc.8) auto-
|
|
511
|
+
# resolve can re-match findings on subsequent fix-pushes without
|
|
512
|
+
# any persistent state.
|
|
513
|
+
#
|
|
514
|
+
# Posted IN ADDITION TO the summary comment above — they serve
|
|
515
|
+
# different UX needs: the summary is the at-a-glance digest; the
|
|
516
|
+
# inline threads are where conversation + resolution happens.
|
|
517
|
+
#
|
|
518
|
+
# `continue-on-error` so a partial GraphQL/REST failure doesn't
|
|
519
|
+
# fail the whole review; the verb itself swallows errors into its
|
|
520
|
+
# stdout JSON and exits 0.
|
|
521
|
+
- name: Post inline review threads
|
|
522
|
+
if: success() && steps.clud-bug-review.outputs.structured_output != ''
|
|
523
|
+
continue-on-error: true
|
|
524
|
+
env:
|
|
525
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
526
|
+
REPO: ${{ github.repository }}
|
|
527
|
+
PR_NUMBER: ${{ github.event.pull_request.number }}
|
|
528
|
+
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
|
529
|
+
STRUCTURED: ${{ steps.clud-bug-review.outputs.structured_output }}
|
|
530
|
+
run: |
|
|
531
|
+
set -euo pipefail
|
|
532
|
+
RESULT=$(printf '%s\n' "$STRUCTURED" | npx --yes clud-bug@{{CLUD_BUG_VERSION}} post-inline-threads --stdin)
|
|
533
|
+
echo "::notice title=inline-threads::$RESULT"
|
|
534
|
+
|
|
535
|
+
# v0.7.0-rc.8 / Wave 5b (D.2.6): on fix-push events
|
|
536
|
+
# (pull_request.synchronize), ask the Anthropic Messages API per
|
|
537
|
+
# bot-authored unresolved inline thread whether the new commit
|
|
538
|
+
# addressed the original finding. ADDRESSED → resolve the thread
|
|
539
|
+
# + post a marker reply; UNCERTAIN / NOT_ADDRESSED → leave open.
|
|
540
|
+
# Fail-closed: verifier errors route to UNCERTAIN (never silently
|
|
541
|
+
# dismiss).
|
|
542
|
+
#
|
|
543
|
+
# Gated on `synchronize` because:
|
|
544
|
+
# - `opened` events have no prior threads to resolve.
|
|
545
|
+
# - Re-running on every event would waste verifier $ on unchanged
|
|
546
|
+
# state.
|
|
547
|
+
#
|
|
548
|
+
# The verb re-derives prior-finding context from the
|
|
549
|
+
# `<!-- finding-id: ... -->` markers Wave 5a embeds in each
|
|
550
|
+
# comment body, so no persistent state is needed across pushes.
|
|
551
|
+
- name: Auto-resolve fixed threads
|
|
552
|
+
if: success() && github.event.action == 'synchronize'
|
|
553
|
+
continue-on-error: true
|
|
554
|
+
env:
|
|
555
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
556
|
+
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
557
|
+
REPO: ${{ github.repository }}
|
|
558
|
+
PR_NUMBER: ${{ github.event.pull_request.number }}
|
|
559
|
+
# Optional fine-grained PAT (Pull requests: write). Present → the
|
|
560
|
+
# workflow resolves fixed threads like the hosted App. Absent (the
|
|
561
|
+
# default; an unset secret renders empty) → graceful "verified fixed"
|
|
562
|
+
# reply only, since the Actions GITHUB_TOKEN can't resolve threads.
|
|
563
|
+
CLUD_BUG_RESOLVE_PAT: ${{ secrets.CLUD_BUG_RESOLVE_PAT }}
|
|
564
|
+
run: |
|
|
565
|
+
set -euo pipefail
|
|
566
|
+
RESULT=$(npx --yes clud-bug@{{CLUD_BUG_VERSION}} resolve-threads)
|
|
567
|
+
echo "::notice title=auto-resolve::$RESULT"
|
|
568
|
+
|
|
497
569
|
# v0.6.29 / Component 4: pipe structured_output through
|
|
498
570
|
# `clud-bug update-skill-usage` to compute the per-skill loads +
|
|
499
571
|
# citations delta from this one review. Writes to the ephemeral
|
|
@@ -632,7 +704,7 @@ jobs:
|
|
|
632
704
|
# Letting the action's own failure fail the check is louder and right.
|
|
633
705
|
- name: Strict mode — fail check on critical findings
|
|
634
706
|
if: success()
|
|
635
|
-
uses: thrillmade/clud-bug/.github/actions/strict-mode-gate@v0.
|
|
707
|
+
uses: thrillmade/clud-bug/.github/actions/strict-mode-gate@v0.7.0-rc.11
|
|
636
708
|
with:
|
|
637
709
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
638
710
|
# v0.6.22 / 0.0.O: the summary is now posted by the workflow
|
|
@@ -642,3 +714,98 @@ jobs:
|
|
|
642
714
|
# never matches the new summary author → strict mode falls
|
|
643
715
|
# open advisory for every install that opted in.
|
|
644
716
|
bot-login: 'github-actions[bot]'
|
|
717
|
+
|
|
718
|
+
# v0.7.0-rc.3 — SPEC §7.2.1 formal-review event poster.
|
|
719
|
+
#
|
|
720
|
+
# Why this step exists: the canonical ruleset (SPEC §7.2) pins
|
|
721
|
+
# `required_approving_review_count: 1`. Before this step, the
|
|
722
|
+
# workflow path posted only a summary issue comment + a
|
|
723
|
+
# `clud-bug-review` check-run — neither of which counts as an
|
|
724
|
+
# approving review. So every PR on the workflow path required a
|
|
725
|
+
# human to click Approve, even when the bot's verdict was clean.
|
|
726
|
+
#
|
|
727
|
+
# This step bridges that gap: it pipes the same structured_output
|
|
728
|
+
# the render step consumed through `clud-bug select-review-event`
|
|
729
|
+
# (SPEC §7.2.1 rule table) and, on org-trusted authors, posts a
|
|
730
|
+
# formal `pulls.createReview` with `event=APPROVE` so the
|
|
731
|
+
# `required_approving_review_count: 1` floor flips automatically.
|
|
732
|
+
#
|
|
733
|
+
# Drive-by exploit guard: external contributors NEVER get APPROVE.
|
|
734
|
+
# The select-review-event verdict for any author in
|
|
735
|
+
# {NONE, FIRST_TIME_CONTRIBUTOR, FIRST_TIMER, MANNEQUIN} is forced
|
|
736
|
+
# to COMMENT — a human reviewer must explicitly Approve. See
|
|
737
|
+
# SPEC §7.2.1 precondition #3.
|
|
738
|
+
#
|
|
739
|
+
# Best-effort contract: this step MUST NEVER fail the workflow.
|
|
740
|
+
# `continue-on-error: true` ensures a malformed payload, network
|
|
741
|
+
# blip, or rate-limit on the formal-review API can't undo the
|
|
742
|
+
# already-posted summary comment. Worst case: no formal review is
|
|
743
|
+
# posted, falling back to today's comment-only behavior (= the
|
|
744
|
+
# pre-rc.3 status quo).
|
|
745
|
+
#
|
|
746
|
+
# Self-PR guard: when the PR author is `clud-bug[bot]` (D.7
|
|
747
|
+
# migration fan-out path that clud-bug-app authors), the verdict
|
|
748
|
+
# is "skip" — GitHub returns 422 on self-review, so we short-
|
|
749
|
+
# circuit before the network call.
|
|
750
|
+
- name: Formal review — APPROVE / REQUEST_CHANGES / COMMENT
|
|
751
|
+
if: always() && steps.clud-bug-review.outputs.structured_output != ''
|
|
752
|
+
continue-on-error: true
|
|
753
|
+
env:
|
|
754
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
755
|
+
PR_NUMBER: ${{ github.event.pull_request.number }}
|
|
756
|
+
REPO: ${{ github.repository }}
|
|
757
|
+
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
|
758
|
+
STRUCTURED: ${{ steps.clud-bug-review.outputs.structured_output }}
|
|
759
|
+
# SPEC §7.2.1 fields. The select-review-event command reads
|
|
760
|
+
# these from env (NOT stdin) so the workflow doesn't have to
|
|
761
|
+
# construct a nested JSON shape.
|
|
762
|
+
PR_AUTHOR_LOGIN: ${{ github.event.pull_request.user.login }}
|
|
763
|
+
PR_AUTHOR_ASSOCIATION: ${{ github.event.pull_request.author_association }}
|
|
764
|
+
BASE_REF: ${{ github.event.pull_request.base.ref }}
|
|
765
|
+
run: |
|
|
766
|
+
set -uo pipefail
|
|
767
|
+
|
|
768
|
+
# Resolve strictMode from the BASE ref's manifest — same
|
|
769
|
+
# discipline as strict-mode-gate (a PR can't opt itself out
|
|
770
|
+
# of strict mode by editing its own .clud-bug.json). Best-
|
|
771
|
+
# effort: any error here falls through to STRICT_MODE=false.
|
|
772
|
+
STRICT_MODE=false
|
|
773
|
+
if git show "origin/${BASE_REF}:.claude/skills/.clud-bug.json" > /tmp/base-manifest.json 2>/dev/null; then
|
|
774
|
+
if jq -e '.strictMode == true' /tmp/base-manifest.json > /dev/null 2>&1; then
|
|
775
|
+
STRICT_MODE=true
|
|
776
|
+
fi
|
|
777
|
+
fi
|
|
778
|
+
export STRICT_MODE
|
|
779
|
+
|
|
780
|
+
# Compute the verdict (one of: APPROVE / REQUEST_CHANGES /
|
|
781
|
+
# COMMENT / skip). The command degrades to "skip" on any
|
|
782
|
+
# caller-side error (malformed JSON, missing env), so we never
|
|
783
|
+
# need a fallback in shell.
|
|
784
|
+
VERDICT=$(printf '%s\n' "$STRUCTURED" \
|
|
785
|
+
| npx --yes clud-bug@{{CLUD_BUG_VERSION}} select-review-event --stdin \
|
|
786
|
+
| tail -n1)
|
|
787
|
+
VERDICT="${VERDICT:-skip}"
|
|
788
|
+
|
|
789
|
+
echo "::notice title=Clud Bug 🐛::Formal review verdict: $VERDICT (strictMode=$STRICT_MODE, author_assoc=$PR_AUTHOR_ASSOCIATION)"
|
|
790
|
+
|
|
791
|
+
if [ "$VERDICT" = "skip" ]; then
|
|
792
|
+
# Self-PR or caller-error case. No formal review posted;
|
|
793
|
+
# the summary comment + check-run remain the visible review
|
|
794
|
+
# surface. This is the pre-rc.3 status quo.
|
|
795
|
+
exit 0
|
|
796
|
+
fi
|
|
797
|
+
|
|
798
|
+
# Body is short + machine-pingable: human reviewers see the
|
|
799
|
+
# summary issue comment for the substantive review surface;
|
|
800
|
+
# the formal-review body is a cross-link.
|
|
801
|
+
BODY=$(printf 'Automated formal review by clud-bug — see the summary comment for the substantive findings.\n\nVerdict: **%s**\n\n<!-- clud-bug-formal-review: workflow-path v0.7.0-rc.3 -->' "$VERDICT")
|
|
802
|
+
|
|
803
|
+
# gh api fires `pulls.createReview` with the verdict event.
|
|
804
|
+
# commit_id pins the review to the exact SHA we reviewed so a
|
|
805
|
+
# later push doesn't auto-extend the approval scope.
|
|
806
|
+
gh api -X POST "/repos/$REPO/pulls/$PR_NUMBER/reviews" \
|
|
807
|
+
-f event="$VERDICT" \
|
|
808
|
+
-f commit_id="$HEAD_SHA" \
|
|
809
|
+
-f body="$BODY" \
|
|
810
|
+
> /dev/null \
|
|
811
|
+
|| echo "::warning title=Clud Bug 🐛::Formal review POST failed (likely 422 self-PR or missing perms); degrading to comment-only."
|