safeword 0.12.2 → 0.14.0
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/dist/{check-3X75X2JL.js → check-X7NR4WAM.js} +5 -4
- package/dist/check-X7NR4WAM.js.map +1 -0
- package/dist/{chunk-3R26BJXN.js → chunk-TJOHD7CV.js} +56 -5
- package/dist/{chunk-3R26BJXN.js.map → chunk-TJOHD7CV.js.map} +1 -1
- package/dist/{chunk-O4LAXZK3.js → chunk-XLOXGDJG.js} +103 -41
- package/dist/chunk-XLOXGDJG.js.map +1 -0
- package/dist/cli.js +6 -6
- package/dist/{diff-6HFT7BLG.js → diff-3USPMFT2.js} +2 -2
- package/dist/{reset-XFXLQXOC.js → reset-CM3BNT5S.js} +2 -2
- package/dist/{setup-C6NF3YJ5.js → setup-C6MJRBGY.js} +5 -18
- package/dist/setup-C6MJRBGY.js.map +1 -0
- package/dist/{sync-config-PPTR3JPA.js → sync-config-KZE4R47T.js} +2 -2
- package/dist/{upgrade-C2I22FAB.js → upgrade-BIMRJENC.js} +12 -6
- package/dist/upgrade-BIMRJENC.js.map +1 -0
- package/package.json +2 -2
- package/templates/hooks/cursor/after-file-edit.ts +47 -0
- package/templates/hooks/cursor/stop.ts +73 -0
- package/templates/hooks/lib/lint.ts +49 -0
- package/templates/hooks/lib/quality.ts +18 -0
- package/templates/hooks/post-tool-lint.ts +33 -0
- package/templates/hooks/prompt-questions.ts +17 -0
- package/templates/hooks/prompt-timestamp.ts +30 -0
- package/templates/hooks/session-lint-check.ts +62 -0
- package/templates/hooks/session-verify-agents.ts +32 -0
- package/templates/hooks/session-version.ts +18 -0
- package/templates/hooks/stop-quality.ts +168 -0
- package/dist/check-3X75X2JL.js.map +0 -1
- package/dist/chunk-O4LAXZK3.js.map +0 -1
- package/dist/setup-C6NF3YJ5.js.map +0 -1
- package/dist/upgrade-C2I22FAB.js.map +0 -1
- package/templates/hooks/cursor/after-file-edit.sh +0 -58
- package/templates/hooks/cursor/stop.sh +0 -50
- package/templates/hooks/post-tool-lint.sh +0 -51
- package/templates/hooks/prompt-questions.sh +0 -27
- package/templates/hooks/prompt-timestamp.sh +0 -13
- package/templates/hooks/session-lint-check.sh +0 -42
- package/templates/hooks/session-verify-agents.sh +0 -31
- package/templates/hooks/session-version.sh +0 -17
- package/templates/hooks/stop-quality.sh +0 -91
- package/templates/lib/common.sh +0 -26
- package/templates/lib/jq-fallback.sh +0 -20
- /package/dist/{diff-6HFT7BLG.js.map → diff-3USPMFT2.js.map} +0 -0
- /package/dist/{reset-XFXLQXOC.js.map → reset-CM3BNT5S.js.map} +0 -0
- /package/dist/{sync-config-PPTR3JPA.js.map → sync-config-KZE4R47T.js.map} +0 -0
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# Auto Quality Review Stop Hook
|
|
3
|
-
# Triggers quality review when changes are proposed or made
|
|
4
|
-
# Only runs for projects with .safeword/ directory
|
|
5
|
-
# Looks for {"proposedChanges": ..., "madeChanges": ...} JSON blob
|
|
6
|
-
|
|
7
|
-
# Change to project directory if set
|
|
8
|
-
[ -n "$CLAUDE_PROJECT_DIR" ] && cd "$CLAUDE_PROJECT_DIR" || true
|
|
9
|
-
|
|
10
|
-
# Check for .safeword directory
|
|
11
|
-
if [ ! -d ".safeword" ]; then
|
|
12
|
-
exit 0
|
|
13
|
-
fi
|
|
14
|
-
|
|
15
|
-
# Read hook input from stdin
|
|
16
|
-
input=$(cat)
|
|
17
|
-
|
|
18
|
-
# Require jq for JSON parsing
|
|
19
|
-
if ! command -v jq &> /dev/null; then
|
|
20
|
-
exit 0
|
|
21
|
-
fi
|
|
22
|
-
|
|
23
|
-
# Get transcript path
|
|
24
|
-
transcript_path=$(echo "$input" | jq -r '.transcript_path // empty' 2>/dev/null)
|
|
25
|
-
|
|
26
|
-
if [ -z "$transcript_path" ] || [ ! -f "$transcript_path" ]; then
|
|
27
|
-
exit 0
|
|
28
|
-
fi
|
|
29
|
-
|
|
30
|
-
# Extract last assistant message from transcript
|
|
31
|
-
# Transcript is JSONL format - each line is a message
|
|
32
|
-
last_assistant_msg=$(grep '"role":"assistant"' "$transcript_path" | tail -1)
|
|
33
|
-
|
|
34
|
-
if [ -z "$last_assistant_msg" ]; then
|
|
35
|
-
exit 0
|
|
36
|
-
fi
|
|
37
|
-
|
|
38
|
-
# Extract the text content from the message
|
|
39
|
-
msg_text=$(echo "$last_assistant_msg" | jq -r '.message.content[]? | select(.type == "text") | .text' 2>/dev/null)
|
|
40
|
-
|
|
41
|
-
if [ -z "$msg_text" ]; then
|
|
42
|
-
exit 0
|
|
43
|
-
fi
|
|
44
|
-
|
|
45
|
-
# Extract JSON blob containing our required fields (order-independent)
|
|
46
|
-
# Strategy: Use jq to find and validate the response summary object
|
|
47
|
-
# Look for object with exactly our three boolean fields anywhere in the text
|
|
48
|
-
json_blob=$(echo "$msg_text" | grep -oE '\{[^}]+\}' | while IFS= read -r candidate; do
|
|
49
|
-
if echo "$candidate" | jq -e '
|
|
50
|
-
type == "object" and
|
|
51
|
-
(.proposedChanges | type) == "boolean" and
|
|
52
|
-
(.madeChanges | type) == "boolean" and
|
|
53
|
-
(.askedQuestion | type) == "boolean"
|
|
54
|
-
' >/dev/null 2>&1; then
|
|
55
|
-
echo "$candidate"
|
|
56
|
-
fi
|
|
57
|
-
done | tail -1)
|
|
58
|
-
|
|
59
|
-
if [ -z "$json_blob" ]; then
|
|
60
|
-
# No valid JSON blob found - remind about required format
|
|
61
|
-
echo "SAFEWORD: Response missing required JSON summary. Add to end of response:" >&2
|
|
62
|
-
echo '{"proposedChanges": boolean, "madeChanges": boolean, "askedQuestion": boolean}' >&2
|
|
63
|
-
exit 2
|
|
64
|
-
fi
|
|
65
|
-
|
|
66
|
-
# Parse the boolean values (already validated, safe to extract)
|
|
67
|
-
proposed_changes=$(echo "$json_blob" | jq -r '.proposedChanges')
|
|
68
|
-
made_changes=$(echo "$json_blob" | jq -r '.madeChanges')
|
|
69
|
-
asked_question=$(echo "$json_blob" | jq -r '.askedQuestion')
|
|
70
|
-
|
|
71
|
-
# If asked a question, don't trigger review (waiting for user input)
|
|
72
|
-
if [ "$asked_question" = "true" ]; then
|
|
73
|
-
exit 0
|
|
74
|
-
fi
|
|
75
|
-
|
|
76
|
-
# If either proposed or made changes, trigger quality review
|
|
77
|
-
if [ "$proposed_changes" = "true" ] || [ "$made_changes" = "true" ]; then
|
|
78
|
-
echo "SAFEWORD Quality Review:" >&2
|
|
79
|
-
echo "" >&2
|
|
80
|
-
echo "Double check and critique your work again just in case." >&2
|
|
81
|
-
echo "Assume you've never seen it before." >&2
|
|
82
|
-
echo "" >&2
|
|
83
|
-
echo "- Is it correct?" >&2
|
|
84
|
-
echo "- Is it elegant?" >&2
|
|
85
|
-
echo "- Does it follow latest docs/best practices?" >&2
|
|
86
|
-
echo "- Ask me any non-obvious questions." >&2
|
|
87
|
-
echo "- Avoid bloat." >&2
|
|
88
|
-
exit 2
|
|
89
|
-
fi
|
|
90
|
-
|
|
91
|
-
exit 0
|
package/templates/lib/common.sh
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# Safeword common utilities for hook scripts
|
|
3
|
-
|
|
4
|
-
# Output JSON response for Claude Code hooks
|
|
5
|
-
# Usage: json_response '{"key": "value"}'
|
|
6
|
-
json_response() {
|
|
7
|
-
echo "$1"
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
# Check if running in a safeword project
|
|
11
|
-
is_safeword_project() {
|
|
12
|
-
[ -d ".safeword" ]
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
# Get project root (directory containing .safeword)
|
|
16
|
-
get_project_root() {
|
|
17
|
-
local dir="$PWD"
|
|
18
|
-
while [ "$dir" != "/" ]; do
|
|
19
|
-
if [ -d "$dir/.safeword" ]; then
|
|
20
|
-
echo "$dir"
|
|
21
|
-
return 0
|
|
22
|
-
fi
|
|
23
|
-
dir=$(dirname "$dir")
|
|
24
|
-
done
|
|
25
|
-
return 1
|
|
26
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# Fallback JSON output when jq is not available
|
|
3
|
-
# Uses printf for safe JSON string escaping
|
|
4
|
-
|
|
5
|
-
# Escape a string for JSON output
|
|
6
|
-
json_escape() {
|
|
7
|
-
local str="$1"
|
|
8
|
-
str="${str//\\/\\\\}"
|
|
9
|
-
str="${str//\"/\\\"}"
|
|
10
|
-
str="${str//$'\n'/\\n}"
|
|
11
|
-
str="${str//$'\t'/\\t}"
|
|
12
|
-
echo "$str"
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
# Output a simple JSON object with one key-value pair
|
|
16
|
-
json_kv() {
|
|
17
|
-
local key="$1"
|
|
18
|
-
local value="$2"
|
|
19
|
-
printf '{"proposedChanges": false, "madeChanges": false, "askedQuestion": false, "%s": "%s"}\n' "$key" "$(json_escape "$value")"
|
|
20
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|