clud-bug 0.5.15 → 0.5.16

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 CHANGED
@@ -572,13 +572,47 @@ export function isCriticalReviewHeader(headerLine) {
572
572
  export function classifyPerSkillOutcome(outcomeLine) {
573
573
  if (outcomeLine == null) return 'failure';
574
574
  const text = String(outcomeLine);
575
- // 0 findings / 0 finding — anchored: NOT preceded by a digit. So "10 findings"
576
- // doesn't match (the `0 findings` substring has `1` before it), and "0
577
- // findings" / " 0 findings." both match.
578
- if (/(^|[^0-9])0\s+findings?\b/i.test(text)) return 'success';
579
- // n/a anchored on word boundaries either side (so "n/a." at sentence end
580
- // matches but "diagnostics" would not contain a matching n/a).
575
+
576
+ // HARD-FAILURE OVERRIDE: any positive finding count failure.
577
+ // `\b[1-9]\d*\s+(?:\w+\s+){0,3}finding` matches "1 finding",
578
+ // "2 critical findings", "10 findings", "100 minor findings below".
579
+ // Up to 3 intermediate words allow modifiers like "critical"/"minor".
580
+ // The `\b[1-9]` anchor (vs `[0-9]`) excludes `0` so this never
581
+ // shadows the "0 findings" success case below. Also: "10 findings"
582
+ // is correctly classified failure because `\b1` matches at the
583
+ // word boundary before `1`, then `\d*` consumes `0`.
584
+ if (/\b[1-9]\d*\s+(?:\w+\s+){0,3}finding/i.test(text)) return 'failure';
585
+
586
+ // SUCCESS PATTERNS — broadened in v0.5.16 to handle natural bot
587
+ // phrasings without enumerating every synonym. The bot's review
588
+ // prompt encourages canonical "0 findings" wording but variance
589
+ // is real (e.g. "no findings to anchor", "0 critical findings").
590
+
591
+ // (1) Zero-finding count, optionally with up to 3 modifier words.
592
+ // Matches: "0 findings", "0 critical findings", "no findings",
593
+ // "zero performance findings", "no findings to anchor".
594
+ // Does NOT match: "10 findings" (handled above), "all findings",
595
+ // "applied to all findings".
596
+ if (/\b(?:0|no|zero)\s+(?:\S+\s+){0,3}finding/i.test(text)) return 'success';
597
+
598
+ // (2) n/a — word-bounded. Matches "n/a.", "n/a — no surface here",
599
+ // " n/a " surrounded by anything. Excludes "diagnostics" etc.
581
600
  if (/\bn\/a\b/i.test(text)) return 'success';
601
+
602
+ // (3) "not applicable" — explicit phrase.
603
+ if (/\bnot\s+applicable\b/i.test(text)) return 'success';
604
+
605
+ // (4) Checkmark (✓) as the bot's universal clean signal. Anchored on
606
+ // whitespace/punctuation on both sides so accidental ✓ inside
607
+ // other content (e.g. quoting a checkbox list) doesn't trip it.
608
+ // Matches "applied to all findings. ✓ all anchored." but not
609
+ // "see ✓item-marker in unicode" or similar.
610
+ if (/(?:^|\s)✓(?:\s|$|[.,;:])/.test(text)) return 'success';
611
+
612
+ // Skill-specific vocabulary like "0 pattern fights" (no `finding` word)
613
+ // falls through to failure here. Skill authors should prefer the
614
+ // canonical "0 findings" wording in their per-skill scan lines so
615
+ // this classifier doesn't need per-skill vocabulary knowledge.
582
616
  return 'failure';
583
617
  }
584
618
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clud-bug",
3
- "version": "0.5.15",
3
+ "version": "0.5.16",
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/thrillmot/clud-bug/issues",
@@ -1,4 +1,4 @@
1
- # clud-bug-template-version: v9
1
+ # clud-bug-template-version: v10
2
2
  name: Clud Bug 🐛 Crawls Your Code
3
3
 
4
4
  on:
@@ -281,6 +281,6 @@ jobs:
281
281
  # Strict-mode gate — composite action; see workflow.yml.tmpl for design notes.
282
282
  - name: Strict mode — fail check on critical findings
283
283
  if: success()
284
- uses: thrillmot/clud-bug/.github/actions/strict-mode-gate@v0.5.15
284
+ uses: thrillmot/clud-bug/.github/actions/strict-mode-gate@v0.5.16
285
285
  with:
286
286
  github-token: ${{ secrets.GITHUB_TOKEN }}
@@ -1,4 +1,4 @@
1
- # clud-bug-template-version: v9
1
+ # clud-bug-template-version: v10
2
2
  name: Clud Bug 🐛 Crawls Your Code
3
3
 
4
4
  on:
@@ -282,6 +282,6 @@ jobs:
282
282
  # Strict-mode gate — composite action; see workflow.yml.tmpl for design notes.
283
283
  - name: Strict mode — fail check on critical findings
284
284
  if: success()
285
- uses: thrillmot/clud-bug/.github/actions/strict-mode-gate@v0.5.15
285
+ uses: thrillmot/clud-bug/.github/actions/strict-mode-gate@v0.5.16
286
286
  with:
287
287
  github-token: ${{ secrets.GITHUB_TOKEN }}
@@ -1,4 +1,4 @@
1
- # clud-bug-template-version: v9
1
+ # clud-bug-template-version: v10
2
2
  name: Clud Bug 🐛 Crawls Your Code
3
3
 
4
4
  on:
@@ -316,6 +316,6 @@ jobs:
316
316
  # Letting the action's own failure fail the check is louder and right.
317
317
  - name: Strict mode — fail check on critical findings
318
318
  if: success()
319
- uses: thrillmot/clud-bug/.github/actions/strict-mode-gate@v0.5.15
319
+ uses: thrillmot/clud-bug/.github/actions/strict-mode-gate@v0.5.16
320
320
  with:
321
321
  github-token: ${{ secrets.GITHUB_TOKEN }}