@spardutti/claude-skills 2.44.0 → 2.44.2
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 +38 -1
- package/hooks/ship-gate.sh +1 -1
- package/hooks/skill-gate.sh +2 -0
- package/package.json +1 -1
package/hooks/ship-gate-hook.sh
CHANGED
|
@@ -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"
|
package/hooks/ship-gate.sh
CHANGED
|
@@ -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 "
|
|
88
|
+
CONF=.claude/gauntlet.conf; [ -f "$CONF" ] || CONF="$HERE/../gauntlet.conf"; [ -f "$CONF" ] && . "$CONF"
|
|
89
89
|
|
|
90
90
|
# ------------------------------------------------------------------- the scope
|
|
91
91
|
BASE="${1:-}"
|
package/hooks/skill-gate.sh
CHANGED
|
@@ -116,6 +116,7 @@ MISSING=""
|
|
|
116
116
|
ACKS=""
|
|
117
117
|
MANIFESTS=""
|
|
118
118
|
if [ -n "$TARGETS" ]; then
|
|
119
|
+
INSTALLED=$(tr -d ' \n' 2>/dev/null < "$PROJECT_DIR/.claude/.claude-skills.json" | grep -o '"skills":\[[^]]*\]')
|
|
119
120
|
MANIFESTS=$(find "$PROJECT_DIR" -maxdepth 4 \( -name node_modules -o -name .git -o -name .venv -o -name dist \) -prune -o \( -name package.json -o -name pyproject.toml -o -name requirements.txt \) -print 2>/dev/null)
|
|
120
121
|
fi
|
|
121
122
|
if [ -n "$TARGETS" ]; then
|
|
@@ -135,6 +136,7 @@ if [ -n "$TARGETS" ]; then
|
|
|
135
136
|
SNAME=$(sed -n 's/^name:[[:space:]]*//p' "$SKILL_FILE" | head -1 | sed "$UNQUOTE")
|
|
136
137
|
[ -z "$SPATHS" ] && continue
|
|
137
138
|
[ -z "$SNAME" ] && continue
|
|
139
|
+
case "$INSTALLED" in *"\"$SNAME\""*) ;; *) continue ;; esac # automark never marks a hand-made skill
|
|
138
140
|
|
|
139
141
|
HIT=""
|
|
140
142
|
for G in $(printf '%s' "$SPATHS" | tr ',' ' '); do
|