@spardutti/claude-skills 2.44.1 → 2.44.3

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.
@@ -46,9 +46,42 @@ GATE="$PROJECT_DIR/.claude/hooks/ship-gate.sh"
46
46
  [ -x "$GATE" ] || exit 0
47
47
  git rev-parse --git-dir >/dev/null 2>&1 || exit 0
48
48
 
49
+ pr_branch() {
50
+ case "$CMD" in
51
+ *"gh pr create"*) printf '%s\n' "$CMD" | sed -nE 's/.*(--head[ =]|-H )([^ ;&|]+).*/\2/p' ;;
52
+ *"gh pr merge"*) merge_branch ;;
53
+ esac
54
+ }
55
+
56
+ merge_branch() {
57
+ local pr="" repo="" next=""
58
+ for t in $(printf '%s\n' "$CMD" | sed 's/.*gh pr merge//; s/[;&|].*//'); do
59
+ if [ "$next" = repo ]; then repo=$t; next=""; continue; fi
60
+ case "$t" in
61
+ -R|--repo) next=repo ;;
62
+ --repo=*) repo=${t#--repo=} ;;
63
+ -*) ;;
64
+ *) [ -z "$pr" ] && pr=$t ;;
65
+ esac
66
+ done
67
+ [ -n "$pr" ] || return 0
68
+ gh pr view "$pr" ${repo:+-R "$repo"} --json headRefName -q .headRefName 2>/dev/null
69
+ }
70
+
71
+ worktree_of() {
72
+ git worktree list --porcelain 2>/dev/null \
73
+ | awk -v b="refs/heads/$1" '/^worktree /{w=substr($0,10)} $0=="branch " b {print w; exit}'
74
+ }
75
+
76
+ # A PR from a worktree ships that folder's diff, so its receipt is keyed there,
77
+ # not in the folder this session started in.
78
+ TARGET="$PROJECT_DIR"
79
+ BRANCH=$(pr_branch)
80
+ [ -n "$BRANCH" ] && WT=$(worktree_of "$BRANCH") && [ -n "$WT" ] && TARGET="$WT"
81
+
49
82
  # Ask the gate for the key rather than recomputing it here. Two implementations
50
83
  # of the same rule drift, and the drift is silent.
51
- KEY=$(bash "$GATE" --key 2>/dev/null)
84
+ KEY=$(CLAUDE_PROJECT_DIR="$TARGET" bash "$GATE" --key 2>/dev/null)
52
85
  [ -z "$KEY" ] && exit 0
53
86
 
54
87
  RECEIPT="/tmp/claude-shipgate-$KEY"
@@ -70,6 +103,10 @@ previous receipt on purpose.
70
103
  Do NOT hand-roll a substitute check: only ship-gate.sh writes a receipt, so a
71
104
  weaker check you designed yourself cannot be passed off as this one.
72
105
 
106
+ From a worktree, run the gate there and name the branch with --head:
107
+
108
+ CLAUDE_PROJECT_DIR=<worktree> bash $GATE
109
+
73
110
  To publish without the gate, say so out loud and run:
74
111
 
75
112
  bash .claude/hooks/ship-gate.sh --force"
@@ -103,3 +103,10 @@ structure_fail() {
103
103
  rm -f "$RECEIPT"
104
104
  exit 1
105
105
  }
106
+
107
+ # An agent that pipes the gate through `tail` cuts the findings off; the last line still says where they are.
108
+ gate_report() {
109
+ REPORT="/tmp/claude-shipgate-$1.log"
110
+ exec > >(tee "$REPORT") 2>&1
111
+ trap 'echo "ship-gate: full output in $REPORT"' EXIT
112
+ }
@@ -85,7 +85,7 @@ GAUNTLET_IGNORE_FILES="*.gen.ts *.gen.tsx *.generated.* */migrations/*.py */alem
85
85
  # Override in .claude/gauntlet.conf to mutate components too.
86
86
  GAUNTLET_NO_MUTATE='\.(tsx|jsx)$'
87
87
  [ -n "${HOME:-}" ] && [ -f "$HOME/.claude/gauntlet.conf" ] && . "$HOME/.claude/gauntlet.conf"
88
- [ -f ".claude/gauntlet.conf" ] && . ".claude/gauntlet.conf"
88
+ CONF=.claude/gauntlet.conf; [ -f "$CONF" ] || CONF="$HERE/../gauntlet.conf"; [ -f "$CONF" ] && . "$CONF"
89
89
 
90
90
  # ------------------------------------------------------------------- the scope
91
91
  BASE="${1:-}"
@@ -112,8 +112,7 @@ CHANGED=$(changed_files)
112
112
  # diff-based key changes when the content did not, and the receipt would go stale
113
113
  # the moment it was committed. This is identical either side of a commit, and
114
114
  # changes the instant any of those files is edited.
115
- RECEIPT_KEY=$(receipt_key)
116
- RECEIPT="/tmp/claude-shipgate-$RECEIPT_KEY"
115
+ RECEIPT_KEY=$(receipt_key); RECEIPT="/tmp/claude-shipgate-$RECEIPT_KEY"
117
116
 
118
117
  if [ "$MODE" = key ]; then printf '%s\n' "$RECEIPT_KEY"; exit 0; fi
119
118
  if [ "$MODE" = force ]; then
@@ -121,6 +120,7 @@ if [ "$MODE" = force ]; then
121
120
  echo "ship-gate: FORCED — receipt written without running any check."
122
121
  exit 0
123
122
  fi
123
+ gate_report "$RECEIPT_KEY"
124
124
  SOURCED=$(printf '%s\n' "$CHANGED" | grep -E "\.($GAUNTLET_SOURCE_EXT)$" \
125
125
  | grep -vE '(\.|_)(test|spec)\.[^.]+$|(^|/)tests?/|(^|/)\.stryker-tmp/' | while read -r f; do
126
126
  [ -f "$f" ] && printf '%s\n' "$f"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spardutti/claude-skills",
3
- "version": "2.44.1",
3
+ "version": "2.44.3",
4
4
  "description": "Guardrails for Claude Code — best-practice skills, planning commands, and delivery gates.",
5
5
  "type": "module",
6
6
  "repository": {