@spardutti/claude-skills 2.60.3 → 2.60.4
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-hook.sh +15 -3
- package/hooks/ship-log.mjs +12 -0
- package/hooks/ship-prep.sh +5 -2
- package/package.json +1 -1
package/hooks/ship-gate-hook.sh
CHANGED
|
@@ -80,11 +80,18 @@ git rev-parse --git-dir >/dev/null 2>&1 || exit 0
|
|
|
80
80
|
pr_branch() {
|
|
81
81
|
case "$CMD" in
|
|
82
82
|
*"gh pr create"*) printf '%s\n' "$CMD" | sed -nE 's/.*(--head[ =]|-H )"?([^ ;&|"]+).*/\2/p' ;;
|
|
83
|
-
*"gh pr merge"*)
|
|
83
|
+
*"gh pr merge"*) merge_field headRefName ;;
|
|
84
84
|
esac
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
|
|
87
|
+
pr_base() {
|
|
88
|
+
case "$CMD" in
|
|
89
|
+
*"gh pr create"*) printf '%s\n' "$CMD" | sed -nE 's/.*(--base[ =]|-B )"?([^ ;&|"]+).*/\2/p' ;;
|
|
90
|
+
*"gh pr merge"*) merge_field baseRefName ;;
|
|
91
|
+
esac
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
merge_field() { # merge_field <gh pr field>
|
|
88
95
|
local pr="" repo="" next=""
|
|
89
96
|
for t in $(printf '%s\n' "$CMD" | sed 's/.*gh pr merge//; s/[;&|].*//'); do
|
|
90
97
|
if [ "$next" = repo ]; then repo=$t; next=""; continue; fi
|
|
@@ -96,7 +103,7 @@ merge_branch() {
|
|
|
96
103
|
esac
|
|
97
104
|
done
|
|
98
105
|
[ -n "$pr" ] || return 0
|
|
99
|
-
gh pr view "$pr" ${repo:+-R "$repo"} --json
|
|
106
|
+
gh pr view "$pr" ${repo:+-R "$repo"} --json "$1" -q ".$1" 2>/dev/null
|
|
100
107
|
}
|
|
101
108
|
|
|
102
109
|
worktree_of() {
|
|
@@ -111,6 +118,11 @@ case "$CMD" in *"gh pr create"*)
|
|
|
111
118
|
CWD_TOP=$(git -C "${CWD:-.}" rev-parse --show-toplevel 2>/dev/null) && [ -n "$CWD_TOP" ] && TARGET="$CWD_TOP" ;;
|
|
112
119
|
esac
|
|
113
120
|
BRANCH=$(pr_branch)
|
|
121
|
+
# A release PR carries only work each feature PR already gated, and the gate on the
|
|
122
|
+
# trunk measures it against itself, so a receipt there proves nothing.
|
|
123
|
+
case "$BRANCH" in dev|develop|development)
|
|
124
|
+
case "$(pr_base)" in main|master) exit 0 ;; esac ;;
|
|
125
|
+
esac
|
|
114
126
|
[ -n "$BRANCH" ] && WT=$(worktree_of "$BRANCH") && [ -n "$WT" ] && TARGET="$WT"
|
|
115
127
|
|
|
116
128
|
# Ask the gate for the key rather than recomputing it here. Two implementations
|
package/hooks/ship-log.mjs
CHANGED
|
@@ -45,7 +45,19 @@ function summarize(record) {
|
|
|
45
45
|
return { minutes: Math.round(minutes * 10) / 10, gateRuns: record.gate.length, gateSeconds: record.gate.reduce((n, r) => n + (r.seconds ?? 0), 0), findings: by };
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
// Survivors fixed but never logged: a FAIL that a later PASS cleared, with no mutation finding since.
|
|
49
|
+
function settleSurvivors(record) {
|
|
50
|
+
const i = record.gate.findLastIndex((g) => g.verdict === "FAIL" && g.projects?.some((p) => p.survivors?.length));
|
|
51
|
+
if (i < 0 || !record.gate.slice(i + 1).some((g) => g.verdict === "PASS")) return;
|
|
52
|
+
if (record.findings.some((f) => f.by === "mutation" && f.ts >= record.gate[i].ts)) return;
|
|
53
|
+
for (const s of record.gate[i].projects.flatMap((p) => p.survivors ?? [])) {
|
|
54
|
+
record.findings.push({ ts: now(), by: "mutation", what: `${s.mutator ?? s.kind} at ${s.at}`, file: s.at.split(":")[0],
|
|
55
|
+
verdict: "confirmed", fixed: true, note: "logged by ship-log: a later gate run passed" });
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
48
59
|
function finalize(dir, path, record, tag, status, reason, at) {
|
|
60
|
+
settleSurvivors(record);
|
|
49
61
|
Object.assign(record, { status, reason: reason ?? null, finished: at ?? now() });
|
|
50
62
|
record.summary = summarize(record);
|
|
51
63
|
const stem = `${record.app}_${record.finished.slice(0, 10)}_${tag}`;
|
package/hooks/ship-prep.sh
CHANGED
|
@@ -69,8 +69,11 @@ scope() {
|
|
|
69
69
|
fi
|
|
70
70
|
echo "diff $diff"
|
|
71
71
|
echo "review /code-review medium origin/$(base_branch)...$branch"
|
|
72
|
-
|
|
73
|
-
|
|
72
|
+
# A release branch skips the audit and the review, so starting them left steps that never end.
|
|
73
|
+
case "$branch" in chore/release-*) ;; *)
|
|
74
|
+
node "$HERE/ship-log.mjs" step audit start >/dev/null 2>&1
|
|
75
|
+
node "$HERE/ship-log.mjs" step review start >/dev/null 2>&1 ;;
|
|
76
|
+
esac
|
|
74
77
|
return 0
|
|
75
78
|
}
|
|
76
79
|
|