clud-bug 0.5.8 → 0.5.10
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/skills.js +120 -0
- package/package.json +1 -1
- package/templates/skills/baseline/clud-bug-collaboration.md +1 -0
- package/templates/skills/baseline/critical-issues-only.md +1 -0
- package/templates/skills/baseline/evidence-based-review.md +1 -0
- package/templates/skills/baseline/respect-existing-conventions.md +1 -0
- package/templates/workflow-py.yml.tmpl +54 -3
- package/templates/workflow-ts.yml.tmpl +54 -3
- package/templates/workflow.yml.tmpl +56 -3
package/lib/skills.js
CHANGED
|
@@ -348,4 +348,124 @@ function sanitizeSlug(name) {
|
|
|
348
348
|
return name.toLowerCase().replace(/[^a-z0-9-]+/g, '-').replace(/^-+|-+$/g, '');
|
|
349
349
|
}
|
|
350
350
|
|
|
351
|
+
// Extract the `review_mode` field from a SKILL.md's frontmatter.
|
|
352
|
+
//
|
|
353
|
+
// Contract (from the v0.6 plan, option D-unified):
|
|
354
|
+
// - `shared` → the skill loads alongside other shared skills in ONE
|
|
355
|
+
// Claude call. Bug-finding baselines + most skills.sh
|
|
356
|
+
// contributions live here; they benefit from cross-
|
|
357
|
+
// correlation (an evidence-based finding flagged for
|
|
358
|
+
// critical-issues-only also gets the convention check).
|
|
359
|
+
// - `dedicated` → the skill gets its OWN focused Claude call. Reserved
|
|
360
|
+
// for domain-specific skills (brand voice, compliance,
|
|
361
|
+
// API-contract) where attention dilution at high skill
|
|
362
|
+
// counts is the real failure mode.
|
|
363
|
+
// - Missing field → default to `shared`. Conservative: the skill loads,
|
|
364
|
+
// no surprise per-skill API cost. Users opt skills INTO
|
|
365
|
+
// `dedicated` by authoring the field.
|
|
366
|
+
//
|
|
367
|
+
// The CLI runtime (v0.5.9) honors this via prompt restructuring inside a
|
|
368
|
+
// single claude-code-action call. The v0.6 GitHub App will use the same
|
|
369
|
+
// field to route to literal parallel API calls. Single source of truth.
|
|
370
|
+
export function readReviewMode(skillContent) {
|
|
371
|
+
if (typeof skillContent !== 'string') return 'shared';
|
|
372
|
+
// Scope to the YAML frontmatter block (between the first two `---` lines).
|
|
373
|
+
// A `review_mode:` line in the body is documentation, not configuration.
|
|
374
|
+
const fm = skillContent.match(/^---\n([\s\S]*?)\n---/);
|
|
375
|
+
if (!fm) return 'shared';
|
|
376
|
+
const m = fm[1].match(/^review_mode:\s*(\S+)\s*$/m);
|
|
377
|
+
if (!m) return 'shared';
|
|
378
|
+
// Strip optional YAML string-quotes — `review_mode: "dedicated"` and
|
|
379
|
+
// `review_mode: 'dedicated'` are both valid YAML, but the (\S+) capture
|
|
380
|
+
// grabs the quotes too. Without this, quoted forms silently fell back
|
|
381
|
+
// to `shared` even though the author clearly meant dedicated.
|
|
382
|
+
const value = m[1].toLowerCase().replace(/^["']|["']$/g, '');
|
|
383
|
+
return value === 'dedicated' ? 'dedicated' : 'shared';
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// Partition a set of loaded skills into {shared, dedicated} buckets per
|
|
387
|
+
// each skill's review_mode frontmatter. Expects skills with a `content`
|
|
388
|
+
// field (SKILL.md text). Skills without content default to `shared`.
|
|
389
|
+
//
|
|
390
|
+
// Shape: input is the same skill objects produced by loadBaseline /
|
|
391
|
+
// writeSkills / listInstalled. Output is two arrays of the same shape;
|
|
392
|
+
// caller decides what to do with each bucket.
|
|
393
|
+
export function partitionByReviewMode(skills) {
|
|
394
|
+
const shared = [];
|
|
395
|
+
const dedicated = [];
|
|
396
|
+
for (const skill of skills) {
|
|
397
|
+
const mode = readReviewMode(skill?.content);
|
|
398
|
+
(mode === 'dedicated' ? dedicated : shared).push(skill);
|
|
399
|
+
}
|
|
400
|
+
return { shared, dedicated };
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// Pull the line for `skillName` from a clud-bug review's `### Per-skill scan`
|
|
404
|
+
// block. The block format (set by the v3+ prompt) is one line per loaded skill:
|
|
405
|
+
//
|
|
406
|
+
// ### Per-skill scan
|
|
407
|
+
// - [critical-issues-only]: scanned all paths. 2 critical findings below.
|
|
408
|
+
// - [brand-voice-review]: scanned 3 microcopy changes. 1 finding (below).
|
|
409
|
+
// - [pii-and-compliance]: scanned analytics + logging. 0 findings.
|
|
410
|
+
//
|
|
411
|
+
// Returns the OUTCOME portion (everything after the `- [name]: ` prefix), with
|
|
412
|
+
// trailing whitespace stripped. Returns null if the skill isn't mentioned, the
|
|
413
|
+
// comment has no Per-skill scan block, or `comment` is empty.
|
|
414
|
+
//
|
|
415
|
+
// The brackets in the line prefix anchor the match so a partial-name collision
|
|
416
|
+
// (e.g. `brand-voice` finding `brand-voice-review`) is impossible.
|
|
417
|
+
export function extractPerSkillLine(comment, skillName) {
|
|
418
|
+
if (typeof comment !== 'string' || !comment) return null;
|
|
419
|
+
if (typeof skillName !== 'string' || !skillName) return null;
|
|
420
|
+
// Escape regex metacharacters in the skill name. A skill name with a `.` or
|
|
421
|
+
// `+` would otherwise alter the match. Skills are conventionally kebab-case,
|
|
422
|
+
// but defense in depth is cheap.
|
|
423
|
+
const escaped = skillName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
424
|
+
// Anchor on the bracket-prefix; tolerate optional leading whitespace and
|
|
425
|
+
// dash. The OUTCOME is everything from after `]:` to end-of-line.
|
|
426
|
+
const re = new RegExp(`^\\s*-\\s*\\[${escaped}\\]:\\s*(.+?)\\s*$`, 'm');
|
|
427
|
+
const m = comment.match(re);
|
|
428
|
+
return m ? m[1] : null;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
// Classify a Per-skill scan outcome line into the check-run conclusion the
|
|
432
|
+
// composite action will emit for that skill. Source of truth for the BB.3
|
|
433
|
+
// gate decision — the v0.5.10 composite shells out to node + this helper
|
|
434
|
+
// rather than parsing in bash, so the gate has unit-test coverage and the
|
|
435
|
+
// v0.6 App can reuse the same classification when it routes its own
|
|
436
|
+
// parallel calls.
|
|
437
|
+
//
|
|
438
|
+
// Contract:
|
|
439
|
+
// - `null` (skill not mentioned in the review) → 'failure'
|
|
440
|
+
// - line contains "0 findings" / "0 finding" as a STANDALONE TOKEN → 'success'
|
|
441
|
+
// - line contains "n/a" as a standalone token → 'success'
|
|
442
|
+
// - empty line (bot emitted "- [name]:" with no outcome) → 'failure'
|
|
443
|
+
// - otherwise (typically "N finding" / "N findings" with N>0) → 'failure'
|
|
444
|
+
//
|
|
445
|
+
// Why null → failure (not neutral): GitHub's branch-protection contract
|
|
446
|
+
// treats `conclusion: neutral` as PASSING for required status checks —
|
|
447
|
+
// only `failure`, `cancelled`, `timed_out`, `action_required` block merge.
|
|
448
|
+
// A strictSkills entry that doesn't appear in the per-skill scan block
|
|
449
|
+
// (typo, prompt regression, mid-review race) emitting `neutral` would
|
|
450
|
+
// silently pass branch protection, defeating the gate the user opted into.
|
|
451
|
+
// Failing loud is the right posture for a gate that ships with "strict" in
|
|
452
|
+
// its name; the cost is a re-run if a bot mid-review somehow drops a skill.
|
|
453
|
+
//
|
|
454
|
+
// The "0 findings" match is anchored on a leading word boundary so "10
|
|
455
|
+
// findings" / "100 findings" don't substring-match to success — the exact
|
|
456
|
+
// bug that v0.5.10's first revision had, caught by clud-bug-review + claude-
|
|
457
|
+
// review on PR #57.
|
|
458
|
+
export function classifyPerSkillOutcome(outcomeLine) {
|
|
459
|
+
if (outcomeLine == null) return 'failure';
|
|
460
|
+
const text = String(outcomeLine);
|
|
461
|
+
// 0 findings / 0 finding — anchored: NOT preceded by a digit. So "10 findings"
|
|
462
|
+
// doesn't match (the `0 findings` substring has `1` before it), and "0
|
|
463
|
+
// findings" / " 0 findings." both match.
|
|
464
|
+
if (/(^|[^0-9])0\s+findings?\b/i.test(text)) return 'success';
|
|
465
|
+
// n/a — anchored on word boundaries either side (so "n/a." at sentence end
|
|
466
|
+
// matches but "diagnostics" would not contain a matching n/a).
|
|
467
|
+
if (/\bn\/a\b/i.test(text)) return 'success';
|
|
468
|
+
return 'failure';
|
|
469
|
+
}
|
|
470
|
+
|
|
351
471
|
export const _internal = { normalizeList, sanitizeSlug, entryKey, MAX_SKILLS, API_BASE, MANIFEST_FILE };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "clud-bug",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.10",
|
|
4
4
|
"description": "Claude PR review with project-aware skills. CLI installs a working GitHub Actions workflow and curates skills from skills.sh.",
|
|
5
5
|
"homepage": "https://cludbug.dev",
|
|
6
6
|
"bugs": "https://github.com/thrillmot/clud-bug/issues",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: clud-bug-collaboration
|
|
3
3
|
description: How Claude Code agents working in a clud-bug-installed repo should interact with the bot's review threads, strict-mode gate, and skill set. Use this skill whenever you're about to push a commit, address a clud-bug PR review comment, edit anything under .claude/skills/, modify .github/workflows/clud-bug-*.yml, or wonder why a PR check is red. Also use when planning work in a repo that has a `clud-bug-review` workflow installed — even if the user didn't mention clud-bug by name.
|
|
4
|
+
review_mode: shared
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
# Working in a clud-bug-installed repo
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# clud-bug-template-version:
|
|
1
|
+
# clud-bug-template-version: v4
|
|
2
2
|
name: Clud Bug 🐛 Crawls Your Code
|
|
3
3
|
|
|
4
4
|
on:
|
|
@@ -12,6 +12,8 @@ jobs:
|
|
|
12
12
|
contents: read
|
|
13
13
|
pull-requests: write
|
|
14
14
|
id-token: write
|
|
15
|
+
# checks: write — composite emits per-skill check-runs (BB.3).
|
|
16
|
+
checks: write
|
|
15
17
|
|
|
16
18
|
steps:
|
|
17
19
|
- uses: actions/checkout@v6
|
|
@@ -56,7 +58,7 @@ jobs:
|
|
|
56
58
|
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
57
59
|
track_progress: true
|
|
58
60
|
claude_args: |
|
|
59
|
-
--allowedTools "mcp__github_inline_comment__create_inline_comment,Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh api graphql:*),Bash(gh api repos/:*),Bash(git show:*),Bash(cat .claude/skills/.clud-bug.json)"
|
|
61
|
+
--allowedTools "mcp__github_inline_comment__create_inline_comment,Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh api graphql:*),Bash(gh api repos/:*),Bash(git show:*),Bash(cat .claude/skills/.clud-bug.json),Bash(cat .claude/skills/*/SKILL.md)"
|
|
60
62
|
prompt: |
|
|
61
63
|
{{PROJECT_DESCRIPTION}}
|
|
62
64
|
|
|
@@ -80,6 +82,23 @@ jobs:
|
|
|
80
82
|
based-review]: this claim isn't anchored to a line"). Generic
|
|
81
83
|
advice that contradicts a project skill is wrong by definition.
|
|
82
84
|
|
|
85
|
+
Skill routing — shared vs dedicated:
|
|
86
|
+
Each loaded skill carries a `review_mode:` field in its YAML
|
|
87
|
+
frontmatter at .claude/skills/<name>/SKILL.md. Two values:
|
|
88
|
+
|
|
89
|
+
- `review_mode: shared` — bug-finding / convention / evidence
|
|
90
|
+
skills. Their findings bundle into the standard "Critical
|
|
91
|
+
findings" / "Minor findings" sections.
|
|
92
|
+
- `review_mode: dedicated` — domain-specific skills (brand
|
|
93
|
+
voice, compliance, API-contract, test-discipline). Each
|
|
94
|
+
gets its own focused H3 section in the review.
|
|
95
|
+
- Missing field → treat as `shared`.
|
|
96
|
+
|
|
97
|
+
Before writing the review, scan each loaded skill's frontmatter
|
|
98
|
+
(the first `---`-delimited block of its SKILL.md) to identify
|
|
99
|
+
its review_mode. You can read them with:
|
|
100
|
+
cat .claude/skills/*/SKILL.md
|
|
101
|
+
|
|
83
102
|
At the end of every review, append a single-line footer:
|
|
84
103
|
Skills referenced: [skill-name-1, skill-name-2, ...]
|
|
85
104
|
If you genuinely cited none, list "[none]" and explain why no
|
|
@@ -147,6 +166,38 @@ jobs:
|
|
|
147
166
|
open" are both 0. On follow-up reviews after a fix-push,
|
|
148
167
|
"resolved from prior" should typically be positive.
|
|
149
168
|
|
|
169
|
+
Per-skill scan block (required, immediately under the status line):
|
|
170
|
+
After the **This round:** counters, emit a "### Per-skill scan"
|
|
171
|
+
section with ONE line per loaded skill — even silent ones. This
|
|
172
|
+
is the anti-dilution layer: every loaded skill must be
|
|
173
|
+
acknowledged so authors can see their skill ran, even when it
|
|
174
|
+
produced no findings.
|
|
175
|
+
|
|
176
|
+
### Per-skill scan
|
|
177
|
+
- [<skill-name>]: <one-sentence outcome>
|
|
178
|
+
|
|
179
|
+
Examples (mix of shared + dedicated, with and without findings):
|
|
180
|
+
- [critical-issues-only]: scanned all paths. 2 critical findings below.
|
|
181
|
+
- [evidence-based-review]: applied to all findings. ✓ all anchored.
|
|
182
|
+
- [respect-existing-conventions]: scanned for pattern fights. 0 findings.
|
|
183
|
+
- [brand-voice-review]: scanned 3 microcopy changes. 1 finding (below).
|
|
184
|
+
- [pii-and-compliance]: scanned logging + analytics. 0 findings.
|
|
185
|
+
|
|
186
|
+
Per-skill findings sections (dedicated-mode skills only):
|
|
187
|
+
For each dedicated-mode skill that produced one or more
|
|
188
|
+
findings, emit a dedicated H3 section before the standard
|
|
189
|
+
critical/minor buckets:
|
|
190
|
+
|
|
191
|
+
### Brand voice [brand-voice-review]
|
|
192
|
+
- Finding: button label "Click here!" violates verb-noun rule
|
|
193
|
+
(lib/ui/Button.tsx:42). Suggested: "Open settings."
|
|
194
|
+
|
|
195
|
+
Shared-mode skill findings stay in the existing combined
|
|
196
|
+
"Critical findings" / "Minor findings" buckets — they
|
|
197
|
+
cross-correlate (a logging-PII issue belongs in both the
|
|
198
|
+
critical-issues-only and pii-and-compliance lens at once), so
|
|
199
|
+
bundling preserves that signal.
|
|
200
|
+
|
|
150
201
|
Post it via:
|
|
151
202
|
gh pr comment "$PR_NUMBER" --body "<your review>"
|
|
152
203
|
|
|
@@ -171,6 +222,6 @@ jobs:
|
|
|
171
222
|
# Strict-mode gate — composite action; see workflow.yml.tmpl for design notes.
|
|
172
223
|
- name: Strict mode — fail check on critical findings
|
|
173
224
|
if: success()
|
|
174
|
-
uses: thrillmot/clud-bug/.github/actions/strict-mode-gate@v0.5.
|
|
225
|
+
uses: thrillmot/clud-bug/.github/actions/strict-mode-gate@v0.5.10
|
|
175
226
|
with:
|
|
176
227
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# clud-bug-template-version:
|
|
1
|
+
# clud-bug-template-version: v4
|
|
2
2
|
name: Clud Bug 🐛 Crawls Your Code
|
|
3
3
|
|
|
4
4
|
on:
|
|
@@ -12,6 +12,8 @@ jobs:
|
|
|
12
12
|
contents: read
|
|
13
13
|
pull-requests: write
|
|
14
14
|
id-token: write
|
|
15
|
+
# checks: write — composite emits per-skill check-runs (BB.3).
|
|
16
|
+
checks: write
|
|
15
17
|
|
|
16
18
|
steps:
|
|
17
19
|
- uses: actions/checkout@v6
|
|
@@ -56,7 +58,7 @@ jobs:
|
|
|
56
58
|
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
57
59
|
track_progress: true
|
|
58
60
|
claude_args: |
|
|
59
|
-
--allowedTools "mcp__github_inline_comment__create_inline_comment,Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh api graphql:*),Bash(gh api repos/:*),Bash(git show:*),Bash(cat .claude/skills/.clud-bug.json)"
|
|
61
|
+
--allowedTools "mcp__github_inline_comment__create_inline_comment,Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh api graphql:*),Bash(gh api repos/:*),Bash(git show:*),Bash(cat .claude/skills/.clud-bug.json),Bash(cat .claude/skills/*/SKILL.md)"
|
|
60
62
|
prompt: |
|
|
61
63
|
{{PROJECT_DESCRIPTION}}
|
|
62
64
|
|
|
@@ -81,6 +83,23 @@ jobs:
|
|
|
81
83
|
based-review]: this claim isn't anchored to a line"). Generic
|
|
82
84
|
advice that contradicts a project skill is wrong by definition.
|
|
83
85
|
|
|
86
|
+
Skill routing — shared vs dedicated:
|
|
87
|
+
Each loaded skill carries a `review_mode:` field in its YAML
|
|
88
|
+
frontmatter at .claude/skills/<name>/SKILL.md. Two values:
|
|
89
|
+
|
|
90
|
+
- `review_mode: shared` — bug-finding / convention / evidence
|
|
91
|
+
skills. Their findings bundle into the standard "Critical
|
|
92
|
+
findings" / "Minor findings" sections.
|
|
93
|
+
- `review_mode: dedicated` — domain-specific skills (brand
|
|
94
|
+
voice, compliance, API-contract, test-discipline). Each
|
|
95
|
+
gets its own focused H3 section in the review.
|
|
96
|
+
- Missing field → treat as `shared`.
|
|
97
|
+
|
|
98
|
+
Before writing the review, scan each loaded skill's frontmatter
|
|
99
|
+
(the first `---`-delimited block of its SKILL.md) to identify
|
|
100
|
+
its review_mode. You can read them with:
|
|
101
|
+
cat .claude/skills/*/SKILL.md
|
|
102
|
+
|
|
84
103
|
At the end of every review, append a single-line footer:
|
|
85
104
|
Skills referenced: [skill-name-1, skill-name-2, ...]
|
|
86
105
|
If you genuinely cited none, list "[none]" and explain why no
|
|
@@ -148,6 +167,38 @@ jobs:
|
|
|
148
167
|
open" are both 0. On follow-up reviews after a fix-push,
|
|
149
168
|
"resolved from prior" should typically be positive.
|
|
150
169
|
|
|
170
|
+
Per-skill scan block (required, immediately under the status line):
|
|
171
|
+
After the **This round:** counters, emit a "### Per-skill scan"
|
|
172
|
+
section with ONE line per loaded skill — even silent ones. This
|
|
173
|
+
is the anti-dilution layer: every loaded skill must be
|
|
174
|
+
acknowledged so authors can see their skill ran, even when it
|
|
175
|
+
produced no findings.
|
|
176
|
+
|
|
177
|
+
### Per-skill scan
|
|
178
|
+
- [<skill-name>]: <one-sentence outcome>
|
|
179
|
+
|
|
180
|
+
Examples (mix of shared + dedicated, with and without findings):
|
|
181
|
+
- [critical-issues-only]: scanned all paths. 2 critical findings below.
|
|
182
|
+
- [evidence-based-review]: applied to all findings. ✓ all anchored.
|
|
183
|
+
- [respect-existing-conventions]: scanned for pattern fights. 0 findings.
|
|
184
|
+
- [brand-voice-review]: scanned 3 microcopy changes. 1 finding (below).
|
|
185
|
+
- [pii-and-compliance]: scanned logging + analytics. 0 findings.
|
|
186
|
+
|
|
187
|
+
Per-skill findings sections (dedicated-mode skills only):
|
|
188
|
+
For each dedicated-mode skill that produced one or more
|
|
189
|
+
findings, emit a dedicated H3 section before the standard
|
|
190
|
+
critical/minor buckets:
|
|
191
|
+
|
|
192
|
+
### Brand voice [brand-voice-review]
|
|
193
|
+
- Finding: button label "Click here!" violates verb-noun rule
|
|
194
|
+
(lib/ui/Button.tsx:42). Suggested: "Open settings."
|
|
195
|
+
|
|
196
|
+
Shared-mode skill findings stay in the existing combined
|
|
197
|
+
"Critical findings" / "Minor findings" buckets — they
|
|
198
|
+
cross-correlate (a logging-PII issue belongs in both the
|
|
199
|
+
critical-issues-only and pii-and-compliance lens at once), so
|
|
200
|
+
bundling preserves that signal.
|
|
201
|
+
|
|
151
202
|
Post it via:
|
|
152
203
|
gh pr comment "$PR_NUMBER" --body "<your review>"
|
|
153
204
|
|
|
@@ -172,6 +223,6 @@ jobs:
|
|
|
172
223
|
# Strict-mode gate — composite action; see workflow.yml.tmpl for design notes.
|
|
173
224
|
- name: Strict mode — fail check on critical findings
|
|
174
225
|
if: success()
|
|
175
|
-
uses: thrillmot/clud-bug/.github/actions/strict-mode-gate@v0.5.
|
|
226
|
+
uses: thrillmot/clud-bug/.github/actions/strict-mode-gate@v0.5.10
|
|
176
227
|
with:
|
|
177
228
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# clud-bug-template-version:
|
|
1
|
+
# clud-bug-template-version: v4
|
|
2
2
|
name: Clud Bug 🐛 Crawls Your Code
|
|
3
3
|
|
|
4
4
|
on:
|
|
@@ -12,6 +12,10 @@ jobs:
|
|
|
12
12
|
contents: read
|
|
13
13
|
pull-requests: write
|
|
14
14
|
id-token: write
|
|
15
|
+
# checks: write — composite action emits per-skill check-runs via
|
|
16
|
+
# the GitHub Checks API for any skill in .clud-bug.json's strictSkills
|
|
17
|
+
# list (BB.3, v0.5.10+). No-op when strictSkills is unset.
|
|
18
|
+
checks: write
|
|
15
19
|
|
|
16
20
|
steps:
|
|
17
21
|
- uses: actions/checkout@v6
|
|
@@ -80,7 +84,7 @@ jobs:
|
|
|
80
84
|
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
81
85
|
track_progress: true
|
|
82
86
|
claude_args: |
|
|
83
|
-
--allowedTools "mcp__github_inline_comment__create_inline_comment,Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh api graphql:*),Bash(gh api repos/:*),Bash(git show:*),Bash(cat .claude/skills/.clud-bug.json)"
|
|
87
|
+
--allowedTools "mcp__github_inline_comment__create_inline_comment,Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh api graphql:*),Bash(gh api repos/:*),Bash(git show:*),Bash(cat .claude/skills/.clud-bug.json),Bash(cat .claude/skills/*/SKILL.md)"
|
|
84
88
|
prompt: |
|
|
85
89
|
{{PROJECT_DESCRIPTION}}
|
|
86
90
|
|
|
@@ -101,6 +105,23 @@ jobs:
|
|
|
101
105
|
based-review]: this claim isn't anchored to a line"). Generic
|
|
102
106
|
advice that contradicts a project skill is wrong by definition.
|
|
103
107
|
|
|
108
|
+
Skill routing — shared vs dedicated:
|
|
109
|
+
Each loaded skill carries a `review_mode:` field in its YAML
|
|
110
|
+
frontmatter at .claude/skills/<name>/SKILL.md. Two values:
|
|
111
|
+
|
|
112
|
+
- `review_mode: shared` — bug-finding / convention / evidence
|
|
113
|
+
skills. Their findings bundle into the standard "Critical
|
|
114
|
+
findings" / "Minor findings" sections.
|
|
115
|
+
- `review_mode: dedicated` — domain-specific skills (brand
|
|
116
|
+
voice, compliance, API-contract, test-discipline). Each
|
|
117
|
+
gets its own focused H3 section in the review.
|
|
118
|
+
- Missing field → treat as `shared`.
|
|
119
|
+
|
|
120
|
+
Before writing the review, scan each loaded skill's frontmatter
|
|
121
|
+
(the first `---`-delimited block of its SKILL.md) to identify
|
|
122
|
+
its review_mode. You can read them with:
|
|
123
|
+
cat .claude/skills/*/SKILL.md
|
|
124
|
+
|
|
104
125
|
At the end of every review, append a single-line footer:
|
|
105
126
|
Skills referenced: [skill-name-1, skill-name-2, ...]
|
|
106
127
|
If you genuinely cited none, list "[none]" and explain why no
|
|
@@ -168,6 +189,38 @@ jobs:
|
|
|
168
189
|
open" are both 0. On follow-up reviews after a fix-push,
|
|
169
190
|
"resolved from prior" should typically be positive.
|
|
170
191
|
|
|
192
|
+
Per-skill scan block (required, immediately under the status line):
|
|
193
|
+
After the **This round:** counters, emit a "### Per-skill scan"
|
|
194
|
+
section with ONE line per loaded skill — even silent ones. This
|
|
195
|
+
is the anti-dilution layer: every loaded skill must be
|
|
196
|
+
acknowledged so authors can see their skill ran, even when it
|
|
197
|
+
produced no findings.
|
|
198
|
+
|
|
199
|
+
### Per-skill scan
|
|
200
|
+
- [<skill-name>]: <one-sentence outcome>
|
|
201
|
+
|
|
202
|
+
Examples (mix of shared + dedicated, with and without findings):
|
|
203
|
+
- [critical-issues-only]: scanned all paths. 2 critical findings below.
|
|
204
|
+
- [evidence-based-review]: applied to all findings. ✓ all anchored.
|
|
205
|
+
- [respect-existing-conventions]: scanned for pattern fights. 0 findings.
|
|
206
|
+
- [brand-voice-review]: scanned 3 microcopy changes. 1 finding (below).
|
|
207
|
+
- [pii-and-compliance]: scanned logging + analytics. 0 findings.
|
|
208
|
+
|
|
209
|
+
Per-skill findings sections (dedicated-mode skills only):
|
|
210
|
+
For each dedicated-mode skill that produced one or more
|
|
211
|
+
findings, emit a dedicated H3 section before the standard
|
|
212
|
+
critical/minor buckets:
|
|
213
|
+
|
|
214
|
+
### Brand voice [brand-voice-review]
|
|
215
|
+
- Finding: button label "Click here!" violates verb-noun rule
|
|
216
|
+
(lib/ui/Button.tsx:42). Suggested: "Open settings."
|
|
217
|
+
|
|
218
|
+
Shared-mode skill findings stay in the existing combined
|
|
219
|
+
"Critical findings" / "Minor findings" buckets — they
|
|
220
|
+
cross-correlate (a logging-PII issue belongs in both the
|
|
221
|
+
critical-issues-only and pii-and-compliance lens at once), so
|
|
222
|
+
bundling preserves that signal.
|
|
223
|
+
|
|
171
224
|
Post it via:
|
|
172
225
|
gh pr comment "$PR_NUMBER" --body "<your review>"
|
|
173
226
|
|
|
@@ -204,6 +257,6 @@ jobs:
|
|
|
204
257
|
# Letting the action's own failure fail the check is louder and right.
|
|
205
258
|
- name: Strict mode — fail check on critical findings
|
|
206
259
|
if: success()
|
|
207
|
-
uses: thrillmot/clud-bug/.github/actions/strict-mode-gate@v0.5.
|
|
260
|
+
uses: thrillmot/clud-bug/.github/actions/strict-mode-gate@v0.5.10
|
|
208
261
|
with:
|
|
209
262
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|