clud-bug 0.6.13 → 0.6.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clud-bug",
3
- "version": "0.6.13",
3
+ "version": "0.6.15",
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",
@@ -6,7 +6,78 @@ on:
6
6
  types: [opened, synchronize]
7
7
 
8
8
  jobs:
9
+ # Pre-flight (v0.6.14 / 0.0.W + v0.6.15 / 0.0.R) — see workflow.yml.tmpl.
10
+ paths-check:
11
+ runs-on: ubuntu-latest
12
+ permissions:
13
+ contents: read
14
+ pull-requests: read
15
+ outputs:
16
+ is_workflow_only: ${{ steps.classify.outputs.is_workflow_only }}
17
+ model: ${{ steps.classify.outputs.model }}
18
+ steps:
19
+ - name: Classify PR diff
20
+ id: classify
21
+ env:
22
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
23
+ PR_NUMBER: ${{ github.event.pull_request.number }}
24
+ REPO: ${{ github.repository }}
25
+ PR_AUTHOR: ${{ github.event.pull_request.user.login }}
26
+ run: |
27
+ CHANGED=$(gh pr diff "$PR_NUMBER" -R "$REPO" --name-only)
28
+ MODEL=claude-sonnet-4-6
29
+ if [ -z "$CHANGED" ]; then
30
+ echo "is_workflow_only=false" >> "$GITHUB_OUTPUT"
31
+ echo "model=$MODEL" >> "$GITHUB_OUTPUT"
32
+ exit 0
33
+ fi
34
+ IS_WORKFLOW_ONLY=true
35
+ while IFS= read -r f; do
36
+ case "$f" in
37
+ .github/workflows/clud-bug-*.yml) ;;
38
+ .github/actions/strict-mode-gate/*) ;;
39
+ *) IS_WORKFLOW_ONLY=false; break ;;
40
+ esac
41
+ done <<< "$CHANGED"
42
+ echo "is_workflow_only=$IS_WORKFLOW_ONLY" >> "$GITHUB_OUTPUT"
43
+ if [ "$IS_WORKFLOW_ONLY" = "true" ]; then
44
+ echo "::notice title=Clud Bug 🐛::Skipping LLM review — workflow-only PR."
45
+ echo "model=$MODEL" >> "$GITHUB_OUTPUT"
46
+ exit 0
47
+ fi
48
+ # Triviality (0.0.R): dep-bumping bot OR small dep-manifest diff.
49
+ IS_TRIVIAL=false
50
+ case "$PR_AUTHOR" in
51
+ dependabot\[bot\]|renovate\[bot\]) IS_TRIVIAL=true ;;
52
+ esac
53
+ if [ "$IS_TRIVIAL" = "false" ]; then
54
+ DIFF_SIZE=$(gh pr diff "$PR_NUMBER" -R "$REPO" | wc -c | tr -d ' ')
55
+ if [ "$DIFF_SIZE" -lt 2048 ]; then
56
+ ALL_TRIVIAL=true
57
+ while IFS= read -r f; do
58
+ case "$f" in
59
+ package.json|*/package.json|package-lock.json|*/package-lock.json) ;;
60
+ pnpm-lock.yaml|*/pnpm-lock.yaml|yarn.lock|*/yarn.lock) ;;
61
+ requirements*.txt|*/requirements*.txt) ;;
62
+ pyproject.toml|*/pyproject.toml|poetry.lock|*/poetry.lock|uv.lock|*/uv.lock) ;;
63
+ Gemfile|*/Gemfile|Gemfile.lock|*/Gemfile.lock) ;;
64
+ go.mod|*/go.mod|go.sum|*/go.sum) ;;
65
+ Cargo.toml|*/Cargo.toml|Cargo.lock|*/Cargo.lock) ;;
66
+ *) ALL_TRIVIAL=false; break ;;
67
+ esac
68
+ done <<< "$CHANGED"
69
+ [ "$ALL_TRIVIAL" = "true" ] && IS_TRIVIAL=true
70
+ fi
71
+ fi
72
+ if [ "$IS_TRIVIAL" = "true" ]; then
73
+ MODEL=claude-haiku-4-5-20251001
74
+ echo "::notice title=Clud Bug 🐛::Trivial PR — routing to Haiku."
75
+ fi
76
+ echo "model=$MODEL" >> "$GITHUB_OUTPUT"
77
+
9
78
  clud-bug-review:
79
+ needs: paths-check
80
+ if: needs.paths-check.outputs.is_workflow_only != 'true'
10
81
  runs-on: ubuntu-latest
11
82
  permissions:
12
83
  contents: read
@@ -73,7 +144,7 @@ jobs:
73
144
  track_progress: true
74
145
  show_full_output: true
75
146
  claude_args: |
76
- --model claude-sonnet-4-6
147
+ --model ${{ needs.paths-check.outputs.model }}
77
148
  --max-turns 15
78
149
  --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(git diff:*),Bash(git merge-base:*),Bash(cat .claude/skills/.clud-bug.json),Bash(cat .claude/skills/*/SKILL.md),Bash(head:*)"
79
150
  prompt: |
@@ -85,6 +156,6 @@ jobs:
85
156
  # Strict-mode gate — composite action; see workflow.yml.tmpl for design notes.
86
157
  - name: Strict mode — fail check on critical findings
87
158
  if: success()
88
- uses: thrillmade/clud-bug/.github/actions/strict-mode-gate@v0.6.13
159
+ uses: thrillmade/clud-bug/.github/actions/strict-mode-gate@v0.6.15
89
160
  with:
90
161
  github-token: ${{ secrets.GITHUB_TOKEN }}
@@ -6,7 +6,78 @@ on:
6
6
  types: [opened, synchronize]
7
7
 
8
8
  jobs:
9
+ # Pre-flight (v0.6.14 / 0.0.W + v0.6.15 / 0.0.R) — see workflow.yml.tmpl.
10
+ paths-check:
11
+ runs-on: ubuntu-latest
12
+ permissions:
13
+ contents: read
14
+ pull-requests: read
15
+ outputs:
16
+ is_workflow_only: ${{ steps.classify.outputs.is_workflow_only }}
17
+ model: ${{ steps.classify.outputs.model }}
18
+ steps:
19
+ - name: Classify PR diff
20
+ id: classify
21
+ env:
22
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
23
+ PR_NUMBER: ${{ github.event.pull_request.number }}
24
+ REPO: ${{ github.repository }}
25
+ PR_AUTHOR: ${{ github.event.pull_request.user.login }}
26
+ run: |
27
+ CHANGED=$(gh pr diff "$PR_NUMBER" -R "$REPO" --name-only)
28
+ MODEL=claude-sonnet-4-6
29
+ if [ -z "$CHANGED" ]; then
30
+ echo "is_workflow_only=false" >> "$GITHUB_OUTPUT"
31
+ echo "model=$MODEL" >> "$GITHUB_OUTPUT"
32
+ exit 0
33
+ fi
34
+ IS_WORKFLOW_ONLY=true
35
+ while IFS= read -r f; do
36
+ case "$f" in
37
+ .github/workflows/clud-bug-*.yml) ;;
38
+ .github/actions/strict-mode-gate/*) ;;
39
+ *) IS_WORKFLOW_ONLY=false; break ;;
40
+ esac
41
+ done <<< "$CHANGED"
42
+ echo "is_workflow_only=$IS_WORKFLOW_ONLY" >> "$GITHUB_OUTPUT"
43
+ if [ "$IS_WORKFLOW_ONLY" = "true" ]; then
44
+ echo "::notice title=Clud Bug 🐛::Skipping LLM review — workflow-only PR."
45
+ echo "model=$MODEL" >> "$GITHUB_OUTPUT"
46
+ exit 0
47
+ fi
48
+ # Triviality (0.0.R): dep-bumping bot OR small dep-manifest diff.
49
+ IS_TRIVIAL=false
50
+ case "$PR_AUTHOR" in
51
+ dependabot\[bot\]|renovate\[bot\]) IS_TRIVIAL=true ;;
52
+ esac
53
+ if [ "$IS_TRIVIAL" = "false" ]; then
54
+ DIFF_SIZE=$(gh pr diff "$PR_NUMBER" -R "$REPO" | wc -c | tr -d ' ')
55
+ if [ "$DIFF_SIZE" -lt 2048 ]; then
56
+ ALL_TRIVIAL=true
57
+ while IFS= read -r f; do
58
+ case "$f" in
59
+ package.json|*/package.json|package-lock.json|*/package-lock.json) ;;
60
+ pnpm-lock.yaml|*/pnpm-lock.yaml|yarn.lock|*/yarn.lock) ;;
61
+ requirements*.txt|*/requirements*.txt) ;;
62
+ pyproject.toml|*/pyproject.toml|poetry.lock|*/poetry.lock|uv.lock|*/uv.lock) ;;
63
+ Gemfile|*/Gemfile|Gemfile.lock|*/Gemfile.lock) ;;
64
+ go.mod|*/go.mod|go.sum|*/go.sum) ;;
65
+ Cargo.toml|*/Cargo.toml|Cargo.lock|*/Cargo.lock) ;;
66
+ *) ALL_TRIVIAL=false; break ;;
67
+ esac
68
+ done <<< "$CHANGED"
69
+ [ "$ALL_TRIVIAL" = "true" ] && IS_TRIVIAL=true
70
+ fi
71
+ fi
72
+ if [ "$IS_TRIVIAL" = "true" ]; then
73
+ MODEL=claude-haiku-4-5-20251001
74
+ echo "::notice title=Clud Bug 🐛::Trivial PR — routing to Haiku."
75
+ fi
76
+ echo "model=$MODEL" >> "$GITHUB_OUTPUT"
77
+
9
78
  clud-bug-review:
79
+ needs: paths-check
80
+ if: needs.paths-check.outputs.is_workflow_only != 'true'
10
81
  runs-on: ubuntu-latest
11
82
  permissions:
12
83
  contents: read
@@ -73,7 +144,7 @@ jobs:
73
144
  track_progress: true
74
145
  show_full_output: true
75
146
  claude_args: |
76
- --model claude-sonnet-4-6
147
+ --model ${{ needs.paths-check.outputs.model }}
77
148
  --max-turns 15
78
149
  --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(git diff:*),Bash(git merge-base:*),Bash(cat .claude/skills/.clud-bug.json),Bash(cat .claude/skills/*/SKILL.md),Bash(head:*)"
79
150
  prompt: |
@@ -85,6 +156,6 @@ jobs:
85
156
  # Strict-mode gate — composite action; see workflow.yml.tmpl for design notes.
86
157
  - name: Strict mode — fail check on critical findings
87
158
  if: success()
88
- uses: thrillmade/clud-bug/.github/actions/strict-mode-gate@v0.6.13
159
+ uses: thrillmade/clud-bug/.github/actions/strict-mode-gate@v0.6.15
89
160
  with:
90
161
  github-token: ${{ secrets.GITHUB_TOKEN }}
@@ -6,7 +6,105 @@ on:
6
6
  types: [opened, synchronize]
7
7
 
8
8
  jobs:
9
+ # Pre-flight: classify the PR diff to decide (a) whether to skip the
10
+ # LLM review entirely, and (b) which model to route to.
11
+ #
12
+ # (a) Workflow-only PRs (v0.6.14 / 0.0.W): if every changed file
13
+ # matches `.github/workflows/clud-bug-*.yml` or
14
+ # `.github/actions/strict-mode-gate/**`, the LLM call is skipped
15
+ # entirely — claude-code-action would refuse anyway (self-modification
16
+ # guard), and template re-renders have no useful review surface.
17
+ # Skipping converts what were admin-bypass merges into normal ones.
18
+ #
19
+ # (b) Trivial PRs (v0.6.15 / 0.0.R): if the PR author is a dep-bumping
20
+ # bot (dependabot, renovate) OR the diff is small (<2KB) AND only
21
+ # touches dependency-manifest files, route the review to Haiku
22
+ # ($0.80/MTok input vs Sonnet's $3) — another ~75% cost reduction on
23
+ # this PR class. Sonnet remains the default for everything else.
24
+ paths-check:
25
+ runs-on: ubuntu-latest
26
+ permissions:
27
+ contents: read
28
+ pull-requests: read
29
+ outputs:
30
+ is_workflow_only: ${{ steps.classify.outputs.is_workflow_only }}
31
+ model: ${{ steps.classify.outputs.model }}
32
+ steps:
33
+ - name: Classify PR diff
34
+ id: classify
35
+ env:
36
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
37
+ PR_NUMBER: ${{ github.event.pull_request.number }}
38
+ REPO: ${{ github.repository }}
39
+ PR_AUTHOR: ${{ github.event.pull_request.user.login }}
40
+ run: |
41
+ CHANGED=$(gh pr diff "$PR_NUMBER" -R "$REPO" --name-only)
42
+ MODEL=claude-sonnet-4-6 # default
43
+ if [ -z "$CHANGED" ]; then
44
+ echo "is_workflow_only=false" >> "$GITHUB_OUTPUT"
45
+ echo "model=$MODEL" >> "$GITHUB_OUTPUT"
46
+ exit 0
47
+ fi
48
+
49
+ # --- (a) workflow-only classifier ---
50
+ IS_WORKFLOW_ONLY=true
51
+ while IFS= read -r f; do
52
+ case "$f" in
53
+ .github/workflows/clud-bug-*.yml) ;;
54
+ .github/actions/strict-mode-gate/*) ;;
55
+ *) IS_WORKFLOW_ONLY=false; break ;;
56
+ esac
57
+ done <<< "$CHANGED"
58
+ echo "is_workflow_only=$IS_WORKFLOW_ONLY" >> "$GITHUB_OUTPUT"
59
+ if [ "$IS_WORKFLOW_ONLY" = "true" ]; then
60
+ echo "::notice title=Clud Bug 🐛::Skipping LLM review — PR only touches workflow files."
61
+ echo "model=$MODEL" >> "$GITHUB_OUTPUT"
62
+ exit 0
63
+ fi
64
+
65
+ # --- (b) triviality classifier ---
66
+ IS_TRIVIAL=false
67
+ # Bot authors that exclusively open dep-bump PRs go straight
68
+ # to Haiku regardless of diff size — lockfile churn can be huge
69
+ # but the review surface is shallow.
70
+ case "$PR_AUTHOR" in
71
+ dependabot\[bot\]|renovate\[bot\]) IS_TRIVIAL=true ;;
72
+ esac
73
+ # Otherwise: diff < 2KB AND every file matches the dep-manifest
74
+ # allow-list. Manual lockfile fixes / small version pins
75
+ # qualify; real feature work does not.
76
+ if [ "$IS_TRIVIAL" = "false" ]; then
77
+ DIFF_SIZE=$(gh pr diff "$PR_NUMBER" -R "$REPO" | wc -c | tr -d ' ')
78
+ if [ "$DIFF_SIZE" -lt 2048 ]; then
79
+ ALL_TRIVIAL=true
80
+ while IFS= read -r f; do
81
+ case "$f" in
82
+ package.json|*/package.json) ;;
83
+ package-lock.json|*/package-lock.json) ;;
84
+ pnpm-lock.yaml|*/pnpm-lock.yaml) ;;
85
+ yarn.lock|*/yarn.lock) ;;
86
+ requirements*.txt|*/requirements*.txt) ;;
87
+ pyproject.toml|*/pyproject.toml) ;;
88
+ poetry.lock|*/poetry.lock) ;;
89
+ uv.lock|*/uv.lock) ;;
90
+ Gemfile|*/Gemfile|Gemfile.lock|*/Gemfile.lock) ;;
91
+ go.mod|*/go.mod|go.sum|*/go.sum) ;;
92
+ Cargo.toml|*/Cargo.toml|Cargo.lock|*/Cargo.lock) ;;
93
+ *) ALL_TRIVIAL=false; break ;;
94
+ esac
95
+ done <<< "$CHANGED"
96
+ [ "$ALL_TRIVIAL" = "true" ] && IS_TRIVIAL=true
97
+ fi
98
+ fi
99
+ if [ "$IS_TRIVIAL" = "true" ]; then
100
+ MODEL=claude-haiku-4-5-20251001
101
+ echo "::notice title=Clud Bug 🐛::Trivial PR detected (dep bump / bot author) — routing to Haiku for ~75% cost reduction."
102
+ fi
103
+ echo "model=$MODEL" >> "$GITHUB_OUTPUT"
104
+
9
105
  clud-bug-review:
106
+ needs: paths-check
107
+ if: needs.paths-check.outputs.is_workflow_only != 'true'
10
108
  runs-on: ubuntu-latest
11
109
  permissions:
12
110
  contents: read
@@ -120,8 +218,12 @@ jobs:
120
218
  # cache_creation_input_tokens in the run's result JSON so we can
121
219
  # measure caching effectiveness post-rollout (per v0.6.3 plan).
122
220
  show_full_output: true
221
+ # v0.6.15 / 0.0.R: --model is dynamic. paths-check classifies
222
+ # the PR as trivial (Haiku) or default (Sonnet). Override
223
+ # per-repo by editing the rendered workflow if you want a
224
+ # specific model for a specific repo.
123
225
  claude_args: |
124
- --model claude-sonnet-4-6
226
+ --model ${{ needs.paths-check.outputs.model }}
125
227
  --max-turns 15
126
228
  --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(git diff:*),Bash(git merge-base:*),Bash(cat .claude/skills/.clud-bug.json),Bash(cat .claude/skills/*/SKILL.md),Bash(head:*)"
127
229
  prompt: |
@@ -145,6 +247,6 @@ jobs:
145
247
  # Letting the action's own failure fail the check is louder and right.
146
248
  - name: Strict mode — fail check on critical findings
147
249
  if: success()
148
- uses: thrillmade/clud-bug/.github/actions/strict-mode-gate@v0.6.13
250
+ uses: thrillmade/clud-bug/.github/actions/strict-mode-gate@v0.6.15
149
251
  with:
150
252
  github-token: ${{ secrets.GITHUB_TOKEN }}