@spardutti/claude-skills 2.16.0 → 2.17.0
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/setup-hook.mjs +65 -3
- package/package.json +1 -1
package/lib/setup-hook.mjs
CHANGED
|
@@ -565,6 +565,8 @@ const SHIP_GATE_SCRIPT = `#!/usr/bin/env bash
|
|
|
565
565
|
# bash .claude/hooks/ship-gate.sh [base-ref]
|
|
566
566
|
# bash .claude/hooks/ship-gate.sh --key print the receipt key and stop
|
|
567
567
|
# bash .claude/hooks/ship-gate.sh --force write a FORCED receipt, run nothing
|
|
568
|
+
# bash .claude/hooks/ship-gate.sh --baseline record today's mutmut survivors as
|
|
569
|
+
# accepted debt, write no receipt
|
|
568
570
|
#
|
|
569
571
|
# On completion it writes a RECEIPT at /tmp/claude-shipgate-<key>, and the
|
|
570
572
|
# PreToolUse hook refuses \`git commit\` / \`git push\` without a matching one. The
|
|
@@ -594,7 +596,11 @@ const SHIP_GATE_SCRIPT = `#!/usr/bin/env bash
|
|
|
594
596
|
set -uo pipefail
|
|
595
597
|
|
|
596
598
|
MODE=""
|
|
597
|
-
case "\${1:-}" in
|
|
599
|
+
case "\${1:-}" in
|
|
600
|
+
--key) MODE=key; shift ;;
|
|
601
|
+
--force) MODE=force; shift ;;
|
|
602
|
+
--baseline) MODE=baseline; shift ;;
|
|
603
|
+
esac
|
|
598
604
|
|
|
599
605
|
PROJECT_DIR="\${CLAUDE_PROJECT_DIR:-$PWD}"
|
|
600
606
|
cd "$PROJECT_DIR" 2>/dev/null || { echo "ship-gate: cannot read $PROJECT_DIR"; exit 1; }
|
|
@@ -756,8 +762,15 @@ for owner in $OWNERS; do
|
|
|
756
762
|
# worse than reporting nothing. \`mutmut results\` is the readable source:
|
|
757
763
|
# it prints "<mutant name>: survived" per survivor.
|
|
758
764
|
M="$(py_mutmut "$base")"
|
|
759
|
-
#
|
|
760
|
-
|
|
765
|
+
# mutmut caches verdicts in ./mutants and only invalidates one when the
|
|
766
|
+
# SOURCE of that function changes. Adding a test does not, so it replays the
|
|
767
|
+
# old "survived" and calls mutants the new tests kill still alive — measured
|
|
768
|
+
# at 20 of them on one commit. \`results\` then prints that whole cache, so
|
|
769
|
+
# survivors turn up for files nowhere near the diff. Deleting the dir first
|
|
770
|
+
# makes both describe the tree being shipped; \`mutmut run\` rewrites it
|
|
771
|
+
# anyway, and a cold run is ~35s for ~1000 mutants.
|
|
772
|
+
# One cd for all three: they run in the same shell, already there.
|
|
773
|
+
CMD="\${RUN}rm -rf mutants; $M run >/dev/null 2>&1; $M results"
|
|
761
774
|
else
|
|
762
775
|
MISSING="$MISSING $label needs mutmut:
|
|
763
776
|
uv add --dev mutmut # or: poetry add --group dev mutmut, pip install mutmut
|
|
@@ -781,16 +794,59 @@ for owner in $OWNERS; do
|
|
|
781
794
|
esac
|
|
782
795
|
SURVIVED=$(printf '%s\\n' "$OUT" | grep -E "$PATTERN" \\
|
|
783
796
|
| grep -vE '^[[:space:]]*[#│|+-]|# *surviv' | head -20)
|
|
797
|
+
FIXED=0
|
|
798
|
+
NOTE=""
|
|
799
|
+
|
|
800
|
+
# Stryker takes --mutate per changed hunk, so it already answers "did YOUR
|
|
801
|
+
# change get tested". mutmut cannot be asked that — 3.x dropped 1.x's
|
|
802
|
+
# --use-patch-file and never replaced it — so it mutates all of source_paths
|
|
803
|
+
# and reports the repo's entire backlog. Held to the same bar, the Python half
|
|
804
|
+
# answers "is this repo perfect" instead, which it never is, so it could never
|
|
805
|
+
# go green. The baseline supplies the missing half: survivors recorded once
|
|
806
|
+
# are accepted debt, and only a name that is not in it fails the gate.
|
|
807
|
+
#
|
|
808
|
+
# A mutant name carries an index within its own function, not a line number,
|
|
809
|
+
# so editing elsewhere in the file does not rename it — and editing the
|
|
810
|
+
# function itself DOES, which correctly re-charges its survivors to that edit.
|
|
811
|
+
if [ "$TOOL" = mutmut ]; then
|
|
812
|
+
BL="$base.mutmut-baseline"
|
|
813
|
+
NOWF=$(mktemp)
|
|
814
|
+
printf '%s\\n' "$OUT" \\
|
|
815
|
+
| sed -n 's/^[[:space:]]*\\([^[:space:]]*\\): survived$/\\1/p' | sort -u > "$NOWF"
|
|
816
|
+
if [ "$MODE" = baseline ]; then
|
|
817
|
+
cp "$NOWF" "$BL"
|
|
818
|
+
NOTE=" $label mutmut — baseline set: $(wc -l < "$BL") survivor(s) accepted. Commit $BL."
|
|
819
|
+
SURVIVED=""
|
|
820
|
+
elif [ -f "$BL" ]; then
|
|
821
|
+
# -Fxv against an empty baseline reports every survivor, which is right:
|
|
822
|
+
# an empty baseline means nothing has been accepted.
|
|
823
|
+
SURVIVED=$(grep -Fxv -f "$BL" "$NOWF" | head -20)
|
|
824
|
+
FIXED=$(grep -Fxvc -f "$NOWF" "$BL")
|
|
825
|
+
else
|
|
826
|
+
cp "$NOWF" "$BL"
|
|
827
|
+
NOTE=" $label mutmut — no baseline, so nothing could be compared. Recorded
|
|
828
|
+
$(wc -l < "$BL") existing survivor(s) in $BL — commit it, then run the
|
|
829
|
+
gate again. From here only NEW survivors fail; --baseline accepts more."
|
|
830
|
+
SURVIVED=""
|
|
831
|
+
[ "$STATUS" = 0 ] && STATUS=2
|
|
832
|
+
fi
|
|
833
|
+
rm -f "$NOWF"
|
|
834
|
+
fi
|
|
835
|
+
|
|
784
836
|
if [ -n "$SURVIVED" ]; then
|
|
785
837
|
echo " $label $TOOL — surviving mutants; these lines can break and no test notices:"
|
|
786
838
|
printf '%s\\n' "$SURVIVED" | sed 's/^/ /'
|
|
839
|
+
[ "$FIXED" -gt 0 ] && echo " ($FIXED baselined survivor(s) now killed — --baseline banks them)"
|
|
787
840
|
STATUS=1
|
|
788
841
|
elif [ $RC -ne 0 ]; then
|
|
789
842
|
echo " $label $TOOL — the run failed:"
|
|
790
843
|
printf '%s\\n' "$OUT" | tail -12 | sed 's/^/ /'
|
|
791
844
|
[ "$STATUS" = 0 ] && STATUS=2
|
|
845
|
+
elif [ -n "$NOTE" ]; then
|
|
846
|
+
printf '%s\\n' "$NOTE"
|
|
792
847
|
else
|
|
793
848
|
echo " $label $TOOL — ok, no surviving mutants in the changed lines"
|
|
849
|
+
[ "$FIXED" -gt 0 ] && echo " ($FIXED baselined survivor(s) now killed — --baseline banks them)"
|
|
794
850
|
fi
|
|
795
851
|
done
|
|
796
852
|
|
|
@@ -801,6 +857,12 @@ if [ -n "$MISSING" ]; then
|
|
|
801
857
|
[ "$STATUS" = 0 ] && STATUS=2
|
|
802
858
|
fi
|
|
803
859
|
|
|
860
|
+
if [ "$MODE" = baseline ]; then
|
|
861
|
+
echo
|
|
862
|
+
echo "ship-gate: baselines updated. No receipt written — run the gate for real."
|
|
863
|
+
exit 0
|
|
864
|
+
fi
|
|
865
|
+
|
|
804
866
|
# The receipt is written by this script and nothing else. A hand-rolled check
|
|
805
867
|
# produces no receipt, which is the whole point: substituting a weaker check is
|
|
806
868
|
# a choice that can be argued for, but it cannot be passed off as this one.
|