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.
Files changed (44) hide show
  1. package/dist/{check-3X75X2JL.js → check-X7NR4WAM.js} +5 -4
  2. package/dist/check-X7NR4WAM.js.map +1 -0
  3. package/dist/{chunk-3R26BJXN.js → chunk-TJOHD7CV.js} +56 -5
  4. package/dist/{chunk-3R26BJXN.js.map → chunk-TJOHD7CV.js.map} +1 -1
  5. package/dist/{chunk-O4LAXZK3.js → chunk-XLOXGDJG.js} +103 -41
  6. package/dist/chunk-XLOXGDJG.js.map +1 -0
  7. package/dist/cli.js +6 -6
  8. package/dist/{diff-6HFT7BLG.js → diff-3USPMFT2.js} +2 -2
  9. package/dist/{reset-XFXLQXOC.js → reset-CM3BNT5S.js} +2 -2
  10. package/dist/{setup-C6NF3YJ5.js → setup-C6MJRBGY.js} +5 -18
  11. package/dist/setup-C6MJRBGY.js.map +1 -0
  12. package/dist/{sync-config-PPTR3JPA.js → sync-config-KZE4R47T.js} +2 -2
  13. package/dist/{upgrade-C2I22FAB.js → upgrade-BIMRJENC.js} +12 -6
  14. package/dist/upgrade-BIMRJENC.js.map +1 -0
  15. package/package.json +2 -2
  16. package/templates/hooks/cursor/after-file-edit.ts +47 -0
  17. package/templates/hooks/cursor/stop.ts +73 -0
  18. package/templates/hooks/lib/lint.ts +49 -0
  19. package/templates/hooks/lib/quality.ts +18 -0
  20. package/templates/hooks/post-tool-lint.ts +33 -0
  21. package/templates/hooks/prompt-questions.ts +17 -0
  22. package/templates/hooks/prompt-timestamp.ts +30 -0
  23. package/templates/hooks/session-lint-check.ts +62 -0
  24. package/templates/hooks/session-verify-agents.ts +32 -0
  25. package/templates/hooks/session-version.ts +18 -0
  26. package/templates/hooks/stop-quality.ts +168 -0
  27. package/dist/check-3X75X2JL.js.map +0 -1
  28. package/dist/chunk-O4LAXZK3.js.map +0 -1
  29. package/dist/setup-C6NF3YJ5.js.map +0 -1
  30. package/dist/upgrade-C2I22FAB.js.map +0 -1
  31. package/templates/hooks/cursor/after-file-edit.sh +0 -58
  32. package/templates/hooks/cursor/stop.sh +0 -50
  33. package/templates/hooks/post-tool-lint.sh +0 -51
  34. package/templates/hooks/prompt-questions.sh +0 -27
  35. package/templates/hooks/prompt-timestamp.sh +0 -13
  36. package/templates/hooks/session-lint-check.sh +0 -42
  37. package/templates/hooks/session-verify-agents.sh +0 -31
  38. package/templates/hooks/session-version.sh +0 -17
  39. package/templates/hooks/stop-quality.sh +0 -91
  40. package/templates/lib/common.sh +0 -26
  41. package/templates/lib/jq-fallback.sh +0 -20
  42. /package/dist/{diff-6HFT7BLG.js.map → diff-3USPMFT2.js.map} +0 -0
  43. /package/dist/{reset-XFXLQXOC.js.map → reset-CM3BNT5S.js.map} +0 -0
  44. /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
@@ -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
- }