@spardutti/claude-skills 2.33.4 → 2.33.6
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/hooks/ship-gate-projects.sh +16 -0
- package/hooks/ship-gate.sh +11 -19
- package/package.json +1 -1
|
@@ -61,6 +61,22 @@ survivor_list() { # survivor_list <survivors> <tool>
|
|
|
61
61
|
echo " not equivalent — see testing-best-practices/MUTATION-TESTING.md."
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
+
changed_files() {
|
|
65
|
+
{ git diff "$BASE"...HEAD --name-only 2>/dev/null
|
|
66
|
+
git diff HEAD --name-only 2>/dev/null
|
|
67
|
+
git ls-files --others --exclude-standard 2>/dev/null; } | sort -u
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
# Ignored extensions are left out; see the comment where ship-gate.sh first calls this.
|
|
71
|
+
receipt_key() {
|
|
72
|
+
{ printf '%s\n' "$PROJECT_DIR"
|
|
73
|
+
changed_files | grep -viE "\.($GAUNTLET_IGNORE_EXT)$" | while IFS= read -r f; do
|
|
74
|
+
[ -n "$f" ] || continue
|
|
75
|
+
printf '%s\n' "$f"
|
|
76
|
+
[ -f "$f" ] && cat "$f"
|
|
77
|
+
done; } | git hash-object --stdin
|
|
78
|
+
}
|
|
79
|
+
|
|
64
80
|
# A scoped --baseline replaces only the changed modules' names. Rebuilding the whole
|
|
65
81
|
# file re-mutated an entire API to accept eleven of them.
|
|
66
82
|
baseline_write() { # baseline_write <baseline file> <survivors file> <scope regex, or empty>
|
package/hooks/ship-gate.sh
CHANGED
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
# bash .claude/hooks/ship-gate.sh [base-ref]
|
|
10
10
|
# bash .claude/hooks/ship-gate.sh --key print the receipt key and stop
|
|
11
11
|
# bash .claude/hooks/ship-gate.sh --force write a FORCED receipt, run nothing
|
|
12
|
-
# bash .claude/hooks/ship-gate.sh --baseline
|
|
13
|
-
#
|
|
12
|
+
# bash .claude/hooks/ship-gate.sh --baseline accept the survivors as debt, reusing
|
|
13
|
+
# this tree's last run, and write the receipt
|
|
14
14
|
#
|
|
15
15
|
# On completion it writes a RECEIPT at /tmp/claude-shipgate-<key>, and the
|
|
16
16
|
# PreToolUse hook refuses `git commit` / `git push` without a matching one. The
|
|
@@ -95,9 +95,7 @@ if [ -z "$BASE" ]; then
|
|
|
95
95
|
|| git rev-list --max-parents=0 HEAD | head -1)
|
|
96
96
|
fi
|
|
97
97
|
|
|
98
|
-
CHANGED=$(
|
|
99
|
-
git diff HEAD --name-only 2>/dev/null
|
|
100
|
-
git ls-files --others --exclude-standard 2>/dev/null; } | sort -u )
|
|
98
|
+
CHANGED=$(changed_files)
|
|
101
99
|
|
|
102
100
|
# Only the files this gate can actually read go into the key. It used to be every
|
|
103
101
|
# changed file, so a version bump in package.json or a line in a changelog threw
|
|
@@ -106,8 +104,7 @@ CHANGED=$( { git diff "$BASE"...HEAD --name-only 2>/dev/null
|
|
|
106
104
|
# a release is trying to ship. An ignored extension is one no check here opens,
|
|
107
105
|
# so it cannot change a verdict. Unknown extensions stay in, because UNPROVEN is
|
|
108
106
|
# a verdict about exactly those.
|
|
109
|
-
|
|
110
|
-
|
|
107
|
+
#
|
|
111
108
|
# The repo path plus the names and contents of the changed files, in a fixed
|
|
112
109
|
# order. The path is in there because the key is otherwise pure content: two
|
|
113
110
|
# repos holding the same file would share a receipt, and one would be waved
|
|
@@ -115,12 +112,7 @@ KEYED=$(printf '%s\n' "$CHANGED" | grep -viE "\.($GAUNTLET_IGNORE_EXT)$")
|
|
|
115
112
|
# diff-based key changes when the content did not, and the receipt would go stale
|
|
116
113
|
# the moment it was committed. This is identical either side of a commit, and
|
|
117
114
|
# changes the instant any of those files is edited.
|
|
118
|
-
RECEIPT_KEY=$(
|
|
119
|
-
printf '%s\n' "$KEYED" | while IFS= read -r f; do
|
|
120
|
-
[ -n "$f" ] || continue
|
|
121
|
-
printf '%s\n' "$f"
|
|
122
|
-
[ -f "$f" ] && cat "$f"
|
|
123
|
-
done; } | git hash-object --stdin )
|
|
115
|
+
RECEIPT_KEY=$(receipt_key)
|
|
124
116
|
RECEIPT="/tmp/claude-shipgate-$RECEIPT_KEY"
|
|
125
117
|
|
|
126
118
|
if [ "$MODE" = key ]; then printf '%s\n' "$RECEIPT_KEY"; exit 0; fi
|
|
@@ -324,13 +316,16 @@ for owner in $OWNERS; do
|
|
|
324
316
|
continue
|
|
325
317
|
fi
|
|
326
318
|
|
|
327
|
-
# Only a clean run is recorded
|
|
319
|
+
# Only a clean run is recorded. A baseline replays this tree's last mutmut run, log
|
|
320
|
+
# included, rather than repeating it: accepting survivors used to cost two more runs.
|
|
328
321
|
PKEY=""; [ "$TOOL" != config ] && PKEY="/tmp/claude-shipgate-project-$(project_key "$owner" "$TOOL")"
|
|
329
322
|
if [ -n "$PKEY" ] && [ -f "$PKEY" ] && { [ "$TOOL" != mutmut ] || [ "$MODE" != baseline ]; }; then
|
|
330
323
|
echo " $label $TOOL — ok, not re-run: nothing of its kind changed since it passed"
|
|
331
324
|
continue
|
|
332
325
|
fi
|
|
326
|
+
[ "$TOOL" = mutmut ] && [ "$MODE" = baseline ] && [ -f "$PKEY.out" ] && CMD="cp '$PKEY.log' '$MLOG' 2>/dev/null; cat '$PKEY.out'"
|
|
333
327
|
OUT=$(eval "$CMD" 2>&1); RC=$?
|
|
328
|
+
[ "$TOOL" = mutmut ] && [ $RC -eq 0 ] && { printf '%s\n' "$OUT" > "$PKEY.out"; cp "$MLOG" "$PKEY.log" 2>/dev/null; }
|
|
334
329
|
[ -n "$SCOPE_RE" ] && [ $RC -eq 0 ] && OUT=$(printf '%s\n' "$OUT" | grep -E "^[[:space:]]*($SCOPE_RE)\.x")
|
|
335
330
|
# Match a finding, never a summary row. Stryker prints a `# survived` COLUMN
|
|
336
331
|
# HEADER every run and repeats the word in its table, so a bare grep reports
|
|
@@ -458,11 +453,8 @@ if [ -n "$MISSING" ]; then
|
|
|
458
453
|
[ "$STATUS" = 0 ] && STATUS=2
|
|
459
454
|
fi
|
|
460
455
|
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
echo "ship-gate: baselines updated. No receipt written — run the gate for real."
|
|
464
|
-
exit 0
|
|
465
|
-
fi
|
|
456
|
+
# .mutmut-baseline is part of the key, so a baseline's receipt is keyed after it is written.
|
|
457
|
+
[ "$MODE" = baseline ] && RECEIPT="/tmp/claude-shipgate-$(receipt_key)"
|
|
466
458
|
|
|
467
459
|
# The receipt is written by this script and nothing else. A hand-rolled check
|
|
468
460
|
# produces no receipt, which is the whole point: substituting a weaker check is
|