@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.
@@ -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"*) merge_branch ;;
83
+ *"gh pr merge"*) merge_field headRefName ;;
84
84
  esac
85
85
  }
86
86
 
87
- merge_branch() {
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 headRefName -q .headRefName 2>/dev/null
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
@@ -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}`;
@@ -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
- node "$HERE/ship-log.mjs" step audit start >/dev/null 2>&1
73
- node "$HERE/ship-log.mjs" step review start >/dev/null 2>&1
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
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spardutti/claude-skills",
3
- "version": "2.60.3",
3
+ "version": "2.60.4",
4
4
  "description": "Guardrails for Claude Code — best-practice skills, planning commands, and delivery gates.",
5
5
  "type": "module",
6
6
  "repository": {