@spardutti/claude-skills 2.18.0 → 2.19.1
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 +9 -0
- package/lib/setup-hook.mjs +44 -2
- package/package.json +5 -1
package/README.md
CHANGED
|
@@ -299,8 +299,17 @@ GAUNTLET_REQUIRE_TESTS=1 # block when the runner matched 0 test file
|
|
|
299
299
|
GAUNTLET_MAX_LINES=200 # per-file limit; 0 turns the check off
|
|
300
300
|
GAUNTLET_SOURCE_EXT='ts|tsx|py' # what counts as SOURCE — not the same question
|
|
301
301
|
GAUNTLET_MUTATE='bash mutate.sh' # replace per-project mutation detection
|
|
302
|
+
GAUNTLET_IGNORE_FILES='*.gen.ts' # globs that are never gated — see below
|
|
302
303
|
```
|
|
303
304
|
|
|
305
|
+
`GAUNTLET_IGNORE_FILES` holds files nobody wrote, so the line limit and mutation both
|
|
306
|
+
skip them. It defaults to `*.gen.ts *.gen.tsx *.generated.* */migrations/*.py
|
|
307
|
+
*/alembic/versions/*.py */components/ui/*.tsx` — a TanStack `routeTree.gen.ts`, a Django
|
|
308
|
+
or Alembic migration, and a vendored shadcn component are all over 200 lines, none of
|
|
309
|
+
them can be split, and gating them only teaches `--force`. Every skipped file is named in
|
|
310
|
+
the output. Patterns match against `/<path>`, so `*/components/ui/*.tsx` covers the repo
|
|
311
|
+
root and `apps/web/src` alike. Set it to `""` to gate everything.
|
|
312
|
+
|
|
304
313
|
`GAUNTLET_SOURCE_EXT` is separate from `GAUNTLET_CODE_EXT` on purpose. The Stop hook asks
|
|
305
314
|
"did anything worth checking change", so a docs repo sets `CODE_EXT` to include `.md`. The
|
|
306
315
|
line limit and mutation ask about source code, where that answer is wrong.
|
package/lib/setup-hook.mjs
CHANGED
|
@@ -591,6 +591,10 @@ const SHIP_GATE_SCRIPT = `#!/usr/bin/env bash
|
|
|
591
591
|
# different question, and a docs repo sets it to .md
|
|
592
592
|
# GAUNTLET_IGNORE_EXT=... extensions that need no gate at all. An extension in
|
|
593
593
|
# neither list is reported UNPROVEN rather than passed
|
|
594
|
+
# GAUNTLET_IGNORE_FILES=.. space-separated globs, matched against /<path>, for
|
|
595
|
+
# files nobody wrote: generated code and vendored
|
|
596
|
+
# components. They are named in the output, never
|
|
597
|
+
# dropped silently. Set it to "" to gate everything
|
|
594
598
|
# GAUNTLET_MUTATE="cmd" one explicit mutation command for the whole repo,
|
|
595
599
|
# replacing per-project detection. $MUTATE_FLAGS holds
|
|
596
600
|
# the --mutate flags, $FILES the changed files.
|
|
@@ -625,6 +629,7 @@ GAUNTLET_MAX_LINES=200
|
|
|
625
629
|
GAUNTLET_MUTATE=""
|
|
626
630
|
GAUNTLET_SOURCE_EXT="ts|tsx|js|jsx|mjs|cjs|py|go|rs|java|kt|rb|php|c|h|cpp|hpp|cs|swift|gd"
|
|
627
631
|
GAUNTLET_IGNORE_EXT="md|mdx|txt|rst|adoc|json|ya?ml|toml|lock|cfg|ini|env|csv|tsv|sql|html|css|scss|svg|png|jpg|jpeg|gif|webp|ico|pdf|woff2?|ttf|otf|mp3|mp4|wav|zip|gz|tres|tscn|import|godot"
|
|
632
|
+
GAUNTLET_IGNORE_FILES="*.gen.ts *.gen.tsx *.generated.* */migrations/*.py */alembic/versions/*.py */components/ui/*.tsx"
|
|
628
633
|
[ -n "\${HOME:-}" ] && [ -f "$HOME/.claude/gauntlet.conf" ] && . "$HOME/.claude/gauntlet.conf"
|
|
629
634
|
[ -f ".claude/gauntlet.conf" ] && . ".claude/gauntlet.conf"
|
|
630
635
|
|
|
@@ -661,11 +666,39 @@ if [ "$MODE" = force ]; then
|
|
|
661
666
|
echo "ship-gate: FORCED — receipt written without running any check."
|
|
662
667
|
exit 0
|
|
663
668
|
fi
|
|
664
|
-
|
|
669
|
+
SOURCED=$(printf '%s\\n' "$CHANGED" | grep -E "\\.($GAUNTLET_SOURCE_EXT)$" \\
|
|
665
670
|
| grep -vE '(\\.|_)(test|spec)\\.[^.]+$|(^|/)tests?/|(^|/)\\.stryker-tmp/' | while read -r f; do
|
|
666
671
|
[ -f "$f" ] && printf '%s\\n' "$f"
|
|
667
672
|
done)
|
|
668
673
|
|
|
674
|
+
# A generated file cannot be split and a vendored one is not ours to split, so
|
|
675
|
+
# the length check fires on every route regeneration and teaches people to
|
|
676
|
+
# --force. A gate that is always forced is not a gate. These are held out of
|
|
677
|
+
# both checks — and printed, because a silent skip is the same lie as a fake
|
|
678
|
+
# PASS. The leading / is what lets one pattern match components/ui at the repo
|
|
679
|
+
# root and apps/web/src/components/ui alike.
|
|
680
|
+
# set -f matters: an unquoted list is glob-expanded before it is split, so
|
|
681
|
+
# */components/ui/*.tsx turned itself into the very path it was meant to match
|
|
682
|
+
# and then matched nothing.
|
|
683
|
+
is_ignored() {
|
|
684
|
+
set -f
|
|
685
|
+
for pat in $GAUNTLET_IGNORE_FILES; do
|
|
686
|
+
case "/$1" in $pat) set +f; return 0 ;; esac
|
|
687
|
+
done
|
|
688
|
+
set +f
|
|
689
|
+
return 1
|
|
690
|
+
}
|
|
691
|
+
FILES=$(printf '%s\\n' "$SOURCED" | while IFS= read -r f; do
|
|
692
|
+
[ -n "$f" ] && ! is_ignored "$f" && printf '%s\\n' "$f"
|
|
693
|
+
done)
|
|
694
|
+
IGNORED=$(printf '%s\\n' "$SOURCED" | while IFS= read -r f; do
|
|
695
|
+
[ -n "$f" ] && is_ignored "$f" && printf '%s\\n' "$f"
|
|
696
|
+
done)
|
|
697
|
+
if [ -n "$IGNORED" ]; then
|
|
698
|
+
echo "ship-gate: not gated, matched GAUNTLET_IGNORE_FILES:"
|
|
699
|
+
printf '%s\\n' "$IGNORED" | sed 's/^/ /'
|
|
700
|
+
fi
|
|
701
|
+
|
|
669
702
|
if [ -z "$FILES" ]; then
|
|
670
703
|
# "I recognised nothing" is not "there is nothing", and the gate used to report
|
|
671
704
|
# both as a PASS. A Godot repo changed only .gd files, which no extension in
|
|
@@ -777,7 +810,16 @@ for owner in $OWNERS; do
|
|
|
777
810
|
TOOL="stryker"
|
|
778
811
|
# From inside the owning package: npx resolves against ITS node_modules, and
|
|
779
812
|
# stryker.config.json lives there too. A monorepo root usually has neither.
|
|
780
|
-
|
|
813
|
+
#
|
|
814
|
+
# Deliberately NOT --incremental. --force does rerun every mutant in scope,
|
|
815
|
+
# so the diff itself was always judged fresh — but incremental mode still
|
|
816
|
+
# merges reports/stryker-incremental.json into the REPORT for everything
|
|
817
|
+
# out of scope, and this gate greps the whole report. Survivors recorded
|
|
818
|
+
# months ago came back as findings against a diff that never touched them:
|
|
819
|
+
# 8 of them on one commit, all long since killed. --mutate already scopes
|
|
820
|
+
# the run to the changed hunks, so incremental buys nothing here and costs
|
|
821
|
+
# a cache that goes stale exactly the way mutmut's did.
|
|
822
|
+
CMD="\${RUN}npx --no-install stryker run $FLAGS"
|
|
781
823
|
elif [ -f "$base"package.json ]; then
|
|
782
824
|
MISSING="$MISSING $label needs Stryker:
|
|
783
825
|
npm --prefix \${owner} i -D @stryker-mutator/core @stryker-mutator/vitest-runner
|
package/package.json
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spardutti/claude-skills",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.19.1",
|
|
4
4
|
"description": "CLI to install Claude Code skills from the claude-skills collection",
|
|
5
5
|
"type": "module",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/Spardutti/claude-skills.git"
|
|
9
|
+
},
|
|
6
10
|
"bin": {
|
|
7
11
|
"claude-skills": "bin/cli.mjs"
|
|
8
12
|
},
|