@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 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.
@@ -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
- FILES=$(printf '%s\\n' "$CHANGED" | grep -E "\\.($GAUNTLET_SOURCE_EXT)$" \\
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
- CMD="\${RUN}npx --no-install stryker run --incremental --force $FLAGS"
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.18.0",
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
  },