safeword 0.2.4 → 0.2.5

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 (235) hide show
  1. package/dist/check-3NGQ4NR5.js +129 -0
  2. package/dist/check-3NGQ4NR5.js.map +1 -0
  3. package/dist/chunk-2XWIUEQK.js +190 -0
  4. package/dist/chunk-2XWIUEQK.js.map +1 -0
  5. package/dist/chunk-GZRQL3SX.js +146 -0
  6. package/dist/chunk-GZRQL3SX.js.map +1 -0
  7. package/dist/chunk-ORQHKDT2.js +10 -0
  8. package/dist/chunk-ORQHKDT2.js.map +1 -0
  9. package/dist/chunk-W66Z3C5H.js +21 -0
  10. package/dist/chunk-W66Z3C5H.js.map +1 -0
  11. package/dist/cli.d.ts +1 -0
  12. package/dist/cli.js +34 -0
  13. package/dist/cli.js.map +1 -0
  14. package/dist/diff-Y6QTAW4O.js +166 -0
  15. package/dist/diff-Y6QTAW4O.js.map +1 -0
  16. package/dist/index.d.ts +11 -0
  17. package/dist/index.js +7 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/reset-3ACTIYYE.js +143 -0
  20. package/dist/reset-3ACTIYYE.js.map +1 -0
  21. package/dist/setup-RR4M334C.js +266 -0
  22. package/dist/setup-RR4M334C.js.map +1 -0
  23. package/dist/upgrade-6AR3DHUV.js +134 -0
  24. package/dist/upgrade-6AR3DHUV.js.map +1 -0
  25. package/package.json +44 -19
  26. package/{.safeword → templates}/hooks/agents-md-check.sh +0 -0
  27. package/{.safeword → templates}/hooks/post-tool.sh +0 -0
  28. package/{.safeword → templates}/hooks/pre-commit.sh +0 -0
  29. package/.claude/commands/arch-review.md +0 -32
  30. package/.claude/commands/lint.md +0 -6
  31. package/.claude/commands/quality-review.md +0 -13
  32. package/.claude/commands/setup-linting.md +0 -6
  33. package/.claude/hooks/auto-lint.sh +0 -6
  34. package/.claude/hooks/auto-quality-review.sh +0 -170
  35. package/.claude/hooks/check-linting-sync.sh +0 -17
  36. package/.claude/hooks/inject-timestamp.sh +0 -6
  37. package/.claude/hooks/question-protocol.sh +0 -12
  38. package/.claude/hooks/run-linters.sh +0 -8
  39. package/.claude/hooks/run-quality-review.sh +0 -76
  40. package/.claude/hooks/version-check.sh +0 -10
  41. package/.claude/mcp/README.md +0 -96
  42. package/.claude/mcp/arcade.sample.json +0 -9
  43. package/.claude/mcp/context7.sample.json +0 -7
  44. package/.claude/mcp/playwright.sample.json +0 -7
  45. package/.claude/settings.json +0 -62
  46. package/.claude/skills/quality-reviewer/SKILL.md +0 -190
  47. package/.claude/skills/safeword-quality-reviewer/SKILL.md +0 -13
  48. package/.env.arcade.example +0 -4
  49. package/.env.example +0 -11
  50. package/.gitmodules +0 -4
  51. package/.safeword/SAFEWORD.md +0 -33
  52. package/.safeword/eslint/eslint-base.mjs +0 -101
  53. package/.safeword/guides/architecture-guide.md +0 -404
  54. package/.safeword/guides/code-philosophy.md +0 -174
  55. package/.safeword/guides/context-files-guide.md +0 -405
  56. package/.safeword/guides/data-architecture-guide.md +0 -183
  57. package/.safeword/guides/design-doc-guide.md +0 -165
  58. package/.safeword/guides/learning-extraction.md +0 -515
  59. package/.safeword/guides/llm-instruction-design.md +0 -239
  60. package/.safeword/guides/llm-prompting.md +0 -95
  61. package/.safeword/guides/tdd-best-practices.md +0 -570
  62. package/.safeword/guides/test-definitions-guide.md +0 -243
  63. package/.safeword/guides/testing-methodology.md +0 -573
  64. package/.safeword/guides/user-story-guide.md +0 -237
  65. package/.safeword/guides/zombie-process-cleanup.md +0 -214
  66. package/.safeword/planning/002-user-story-quality-evaluation.md +0 -1840
  67. package/.safeword/planning/003-langsmith-eval-setup-prompt.md +0 -363
  68. package/.safeword/planning/004-llm-eval-test-cases.md +0 -3226
  69. package/.safeword/planning/005-architecture-enforcement-system.md +0 -169
  70. package/.safeword/planning/006-reactive-fix-prevention-research.md +0 -135
  71. package/.safeword/planning/011-cli-ux-vision.md +0 -330
  72. package/.safeword/planning/012-project-structure-cleanup.md +0 -154
  73. package/.safeword/planning/README.md +0 -39
  74. package/.safeword/planning/automation-plan-v2.md +0 -1225
  75. package/.safeword/planning/automation-plan-v3.md +0 -1291
  76. package/.safeword/planning/automation-plan.md +0 -3058
  77. package/.safeword/planning/design/005-cli-implementation.md +0 -343
  78. package/.safeword/planning/design/013-cli-self-contained-templates.md +0 -596
  79. package/.safeword/planning/design/013a-eslint-plugin-suite.md +0 -256
  80. package/.safeword/planning/design/013b-implementation-snippets.md +0 -385
  81. package/.safeword/planning/design/013c-config-isolation-strategy.md +0 -242
  82. package/.safeword/planning/design/code-philosophy-improvements.md +0 -60
  83. package/.safeword/planning/mcp-analysis.md +0 -545
  84. package/.safeword/planning/phase2-subagents-vs-skills-analysis.md +0 -451
  85. package/.safeword/planning/settings-improvements.md +0 -970
  86. package/.safeword/planning/test-definitions/005-cli-implementation.md +0 -1301
  87. package/.safeword/planning/test-definitions/cli-self-contained-templates.md +0 -205
  88. package/.safeword/planning/user-stories/001-guides-review-user-stories.md +0 -1381
  89. package/.safeword/planning/user-stories/003-reactive-fix-prevention.md +0 -132
  90. package/.safeword/planning/user-stories/004-technical-constraints.md +0 -86
  91. package/.safeword/planning/user-stories/005-cli-implementation.md +0 -311
  92. package/.safeword/planning/user-stories/cli-self-contained-templates.md +0 -172
  93. package/.safeword/planning/versioned-distribution.md +0 -740
  94. package/.safeword/prompts/arch-review.md +0 -43
  95. package/.safeword/prompts/quality-review.md +0 -11
  96. package/.safeword/scripts/arch-review.sh +0 -235
  97. package/.safeword/scripts/check-linting-sync.sh +0 -58
  98. package/.safeword/scripts/setup-linting.sh +0 -559
  99. package/.safeword/templates/architecture-template.md +0 -136
  100. package/.safeword/templates/ci/architecture-check.yml +0 -79
  101. package/.safeword/templates/design-doc-template.md +0 -127
  102. package/.safeword/templates/test-definitions-feature.md +0 -100
  103. package/.safeword/templates/ticket-template.md +0 -74
  104. package/.safeword/templates/user-stories-template.md +0 -82
  105. package/.safeword/tickets/001-guides-review-user-stories.md +0 -83
  106. package/.safeword/tickets/002-architecture-enforcement.md +0 -211
  107. package/.safeword/tickets/003-reactive-fix-prevention.md +0 -57
  108. package/.safeword/tickets/004-technical-constraints-in-user-stories.md +0 -39
  109. package/.safeword/tickets/005-cli-implementation.md +0 -248
  110. package/.safeword/tickets/006-flesh-out-skills.md +0 -43
  111. package/.safeword/tickets/007-flesh-out-questioning.md +0 -44
  112. package/.safeword/tickets/008-upgrade-questioning.md +0 -58
  113. package/.safeword/tickets/009-naming-conventions.md +0 -41
  114. package/.safeword/tickets/010-safeword-md-cleanup.md +0 -34
  115. package/.safeword/tickets/011-cursor-setup.md +0 -86
  116. package/.safeword/tickets/README.md +0 -73
  117. package/.safeword/version +0 -1
  118. package/AGENTS.md +0 -59
  119. package/CLAUDE.md +0 -12
  120. package/README.md +0 -347
  121. package/docs/001-cli-implementation-plan.md +0 -856
  122. package/docs/elite-dx-implementation-plan.md +0 -1034
  123. package/framework/README.md +0 -131
  124. package/framework/mcp/README.md +0 -96
  125. package/framework/mcp/arcade.sample.json +0 -8
  126. package/framework/mcp/context7.sample.json +0 -6
  127. package/framework/mcp/playwright.sample.json +0 -6
  128. package/framework/scripts/arch-review.sh +0 -235
  129. package/framework/scripts/check-linting-sync.sh +0 -58
  130. package/framework/scripts/load-env.sh +0 -49
  131. package/framework/scripts/setup-claude.sh +0 -223
  132. package/framework/scripts/setup-linting.sh +0 -559
  133. package/framework/scripts/setup-quality.sh +0 -477
  134. package/framework/scripts/setup-safeword.sh +0 -550
  135. package/framework/templates/ci/architecture-check.yml +0 -78
  136. package/learnings/ai-sdk-v5-breaking-changes.md +0 -178
  137. package/learnings/e2e-test-zombie-processes.md +0 -231
  138. package/learnings/milkdown-crepe-editor-property.md +0 -96
  139. package/learnings/prosemirror-fragment-traversal.md +0 -119
  140. package/packages/cli/AGENTS.md +0 -1
  141. package/packages/cli/ARCHITECTURE.md +0 -279
  142. package/packages/cli/package.json +0 -51
  143. package/packages/cli/src/cli.ts +0 -63
  144. package/packages/cli/src/commands/check.ts +0 -166
  145. package/packages/cli/src/commands/diff.ts +0 -209
  146. package/packages/cli/src/commands/reset.ts +0 -190
  147. package/packages/cli/src/commands/setup.ts +0 -325
  148. package/packages/cli/src/commands/upgrade.ts +0 -163
  149. package/packages/cli/src/index.ts +0 -3
  150. package/packages/cli/src/templates/config.ts +0 -58
  151. package/packages/cli/src/templates/content.ts +0 -18
  152. package/packages/cli/src/templates/index.ts +0 -12
  153. package/packages/cli/src/utils/agents-md.ts +0 -66
  154. package/packages/cli/src/utils/fs.ts +0 -179
  155. package/packages/cli/src/utils/git.ts +0 -124
  156. package/packages/cli/src/utils/hooks.ts +0 -29
  157. package/packages/cli/src/utils/output.ts +0 -60
  158. package/packages/cli/src/utils/project-detector.test.ts +0 -185
  159. package/packages/cli/src/utils/project-detector.ts +0 -44
  160. package/packages/cli/src/utils/version.ts +0 -28
  161. package/packages/cli/src/version.ts +0 -6
  162. package/packages/cli/templates/SAFEWORD.md +0 -776
  163. package/packages/cli/templates/doc-templates/architecture-template.md +0 -136
  164. package/packages/cli/templates/doc-templates/design-doc-template.md +0 -134
  165. package/packages/cli/templates/doc-templates/test-definitions-feature.md +0 -131
  166. package/packages/cli/templates/doc-templates/ticket-template.md +0 -82
  167. package/packages/cli/templates/doc-templates/user-stories-template.md +0 -92
  168. package/packages/cli/templates/guides/architecture-guide.md +0 -423
  169. package/packages/cli/templates/guides/code-philosophy.md +0 -195
  170. package/packages/cli/templates/guides/context-files-guide.md +0 -457
  171. package/packages/cli/templates/guides/data-architecture-guide.md +0 -200
  172. package/packages/cli/templates/guides/design-doc-guide.md +0 -171
  173. package/packages/cli/templates/guides/learning-extraction.md +0 -552
  174. package/packages/cli/templates/guides/llm-instruction-design.md +0 -248
  175. package/packages/cli/templates/guides/llm-prompting.md +0 -102
  176. package/packages/cli/templates/guides/tdd-best-practices.md +0 -615
  177. package/packages/cli/templates/guides/test-definitions-guide.md +0 -334
  178. package/packages/cli/templates/guides/testing-methodology.md +0 -618
  179. package/packages/cli/templates/guides/user-story-guide.md +0 -256
  180. package/packages/cli/templates/guides/zombie-process-cleanup.md +0 -219
  181. package/packages/cli/templates/hooks/agents-md-check.sh +0 -27
  182. package/packages/cli/templates/hooks/post-tool.sh +0 -4
  183. package/packages/cli/templates/hooks/pre-commit.sh +0 -10
  184. package/packages/cli/templates/prompts/arch-review.md +0 -43
  185. package/packages/cli/templates/prompts/quality-review.md +0 -10
  186. package/packages/cli/templates/skills/safeword-quality-reviewer/SKILL.md +0 -207
  187. package/packages/cli/tests/commands/check.test.ts +0 -129
  188. package/packages/cli/tests/commands/cli.test.ts +0 -89
  189. package/packages/cli/tests/commands/diff.test.ts +0 -115
  190. package/packages/cli/tests/commands/reset.test.ts +0 -310
  191. package/packages/cli/tests/commands/self-healing.test.ts +0 -170
  192. package/packages/cli/tests/commands/setup-blocking.test.ts +0 -71
  193. package/packages/cli/tests/commands/setup-core.test.ts +0 -135
  194. package/packages/cli/tests/commands/setup-git.test.ts +0 -139
  195. package/packages/cli/tests/commands/setup-hooks.test.ts +0 -334
  196. package/packages/cli/tests/commands/setup-linting.test.ts +0 -189
  197. package/packages/cli/tests/commands/setup-noninteractive.test.ts +0 -80
  198. package/packages/cli/tests/commands/setup-templates.test.ts +0 -181
  199. package/packages/cli/tests/commands/upgrade.test.ts +0 -215
  200. package/packages/cli/tests/helpers.ts +0 -243
  201. package/packages/cli/tests/npm-package.test.ts +0 -83
  202. package/packages/cli/tests/technical-constraints.test.ts +0 -96
  203. package/packages/cli/tsconfig.json +0 -25
  204. package/packages/cli/tsup.config.ts +0 -11
  205. package/packages/cli/vitest.config.ts +0 -23
  206. package/promptfoo.yaml +0 -3270
  207. /package/{framework → templates}/SAFEWORD.md +0 -0
  208. /package/{packages/cli/templates → templates}/commands/arch-review.md +0 -0
  209. /package/{packages/cli/templates → templates}/commands/lint.md +0 -0
  210. /package/{packages/cli/templates → templates}/commands/quality-review.md +0 -0
  211. /package/{framework/templates → templates/doc-templates}/architecture-template.md +0 -0
  212. /package/{framework/templates → templates/doc-templates}/design-doc-template.md +0 -0
  213. /package/{framework/templates → templates/doc-templates}/test-definitions-feature.md +0 -0
  214. /package/{framework/templates → templates/doc-templates}/ticket-template.md +0 -0
  215. /package/{framework/templates → templates/doc-templates}/user-stories-template.md +0 -0
  216. /package/{framework → templates}/guides/architecture-guide.md +0 -0
  217. /package/{framework → templates}/guides/code-philosophy.md +0 -0
  218. /package/{framework → templates}/guides/context-files-guide.md +0 -0
  219. /package/{framework → templates}/guides/data-architecture-guide.md +0 -0
  220. /package/{framework → templates}/guides/design-doc-guide.md +0 -0
  221. /package/{framework → templates}/guides/learning-extraction.md +0 -0
  222. /package/{framework → templates}/guides/llm-instruction-design.md +0 -0
  223. /package/{framework → templates}/guides/llm-prompting.md +0 -0
  224. /package/{framework → templates}/guides/tdd-best-practices.md +0 -0
  225. /package/{framework → templates}/guides/test-definitions-guide.md +0 -0
  226. /package/{framework → templates}/guides/testing-methodology.md +0 -0
  227. /package/{framework → templates}/guides/user-story-guide.md +0 -0
  228. /package/{framework → templates}/guides/zombie-process-cleanup.md +0 -0
  229. /package/{packages/cli/templates → templates}/hooks/inject-timestamp.sh +0 -0
  230. /package/{packages/cli/templates → templates}/lib/common.sh +0 -0
  231. /package/{packages/cli/templates → templates}/lib/jq-fallback.sh +0 -0
  232. /package/{packages/cli/templates → templates}/markdownlint.jsonc +0 -0
  233. /package/{framework → templates}/prompts/arch-review.md +0 -0
  234. /package/{framework → templates}/prompts/quality-review.md +0 -0
  235. /package/{framework/skills/quality-reviewer → templates/skills/safeword-quality-reviewer}/SKILL.md +0 -0
@@ -1,477 +0,0 @@
1
- #!/bin/bash
2
- ################################################################################
3
- # Claude Code Quality Review Hook Setup Script
4
- #
5
- # This script configures quality review hooks to automatically trigger
6
- # when Claude Code makes or proposes changes to your project files.
7
- #
8
- # Usage:
9
- # bash setup-quality.sh
10
- #
11
- # What it does:
12
- # - Creates auto-quality-review.sh (Stop hook - detects changes)
13
- # - Creates run-quality-review.sh (quality review prompt)
14
- # - Creates /quality-review slash command
15
- # - Updates .claude/settings.json with Stop hook
16
- #
17
- # All files are created project-local (no global dependencies).
18
- ################################################################################
19
-
20
- set -e # Exit on error
21
-
22
- VERSION="v1.0.0"
23
-
24
- # Version header for generated files
25
- # Note: This script is project-local; the header records the generator name.
26
- VERSION_HEADER="# Generated by setup-quality.sh $VERSION
27
- # To upgrade: Re-run setup script in this project
28
- #"
29
-
30
- echo "================================="
31
- echo "Claude Code Quality Review Setup"
32
- echo "Version: $VERSION"
33
- echo "================================="
34
- echo ""
35
-
36
- # Check if we're in a directory where we can write
37
- if [ ! -w "." ]; then
38
- echo "ERROR: Cannot write to current directory. Please cd to your project root."
39
- exit 1
40
- fi
41
-
42
- PROJECT_ROOT="$(pwd)"
43
- echo "Setting up quality review in: $PROJECT_ROOT"
44
- echo ""
45
-
46
- # ============================================================================
47
- # Step 1: Check dependencies
48
- # ============================================================================
49
- echo "[1/4] Checking dependencies..."
50
-
51
- # Check if jq is available (REQUIRED for settings.json merging)
52
- if ! command -v jq &> /dev/null; then
53
- echo "ERROR: jq is required for settings.json merging."
54
- echo "Install it:"
55
- echo " • macOS: brew install jq"
56
- echo " • Ubuntu/Debian: sudo apt-get install jq"
57
- echo " • Other: https://jqlang.github.io/jq/download/"
58
- exit 1
59
- fi
60
-
61
- echo " ✓ Dependencies checked"
62
- echo ""
63
-
64
- # ============================================================================
65
- # Step 2: Create .claude directory structure
66
- # ============================================================================
67
- echo "[2/4] Creating directory structure..."
68
-
69
- mkdir -p .claude/hooks
70
- mkdir -p .claude/commands
71
-
72
- echo " ✓ Created .claude/hooks and .claude/commands"
73
- echo ""
74
-
75
- # ============================================================================
76
- # Step 3: Generate hook files
77
- # ============================================================================
78
- echo "[3/4] Generating quality review hooks..."
79
-
80
- # Create auto-quality-review.sh (Stop hook)
81
- {
82
- echo '#!/bin/bash'
83
- echo "$VERSION_HEADER"
84
- cat << 'EOF'
85
- # Auto Quality Review Stop Hook
86
- # Triggers quality review when changes are proposed or made
87
- # Only runs for projects with SAFEWORD.md or CLAUDE.md (searches upward)
88
- # Looks for {"proposedChanges": ..., "madeChanges": ...} JSON blob
89
-
90
- # Debug logging (persistent across reboots, user-specific)
91
- DEBUG_DIR="$HOME/.cache/claude-hooks"
92
- mkdir -p "$DEBUG_DIR" 2>/dev/null || DEBUG_DIR="/tmp"
93
- DEBUG_LOG="$DEBUG_DIR/auto-quality-review-debug.log"
94
- echo "=== Hook triggered at $(date) ===" >> "$DEBUG_LOG"
95
- echo "PWD: $PWD" >> "$DEBUG_LOG"
96
-
97
- # Read hook input from stdin
98
- input=$(cat)
99
- echo "Input: $input" >> "$DEBUG_LOG"
100
-
101
- # Check for project-level SAFEWORD.md or CLAUDE.md
102
- # Search upward from current directory (supports monorepos)
103
- current_dir="$PWD"
104
- echo "Searching for SAFEWORD.md or CLAUDE.md..." >> "$DEBUG_LOG"
105
- while true; do
106
- if [ -f "$current_dir/SAFEWORD.md" ] || [ -f "$current_dir/CLAUDE.md" ]; then
107
- echo "Found context file in: $current_dir" >> "$DEBUG_LOG"
108
- break # Found context file
109
- fi
110
-
111
- # Reached root without finding context file
112
- if [ "$current_dir" = "/" ]; then
113
- echo "No SAFEWORD.md or CLAUDE.md found, exiting" >> "$DEBUG_LOG"
114
- exit 0
115
- fi
116
-
117
- current_dir=$(dirname "$current_dir")
118
- done
119
-
120
- # Read project config (defaults: enabled=true, ask_questions=true)
121
- config_file="$current_dir/.auto-quality-review.config"
122
- enabled=true
123
- ask_questions=true
124
-
125
- if [ -f "$config_file" ]; then
126
- while IFS='=' read -r key value; do
127
- # Skip empty lines and comments
128
- [[ -z "$key" || "$key" =~ ^# ]] && continue
129
- # Trim whitespace
130
- key=$(echo "$key" | xargs)
131
- value=$(echo "$value" | xargs)
132
-
133
- case "$key" in
134
- enabled)
135
- enabled="$value"
136
- ;;
137
- ask_questions)
138
- ask_questions="$value"
139
- ;;
140
- esac
141
- done < "$config_file"
142
- fi
143
-
144
- # Exit if disabled for this project
145
- echo "Config: enabled=$enabled, ask_questions=$ask_questions" >> "$DEBUG_LOG"
146
- if [ "$enabled" != "true" ]; then
147
- echo "Hook disabled for this project, exiting" >> "$DEBUG_LOG"
148
- exit 0
149
- fi
150
-
151
- # Get transcript path
152
- if ! transcript_path=$(echo "$input" | jq -r '.transcript_path // empty' 2>/dev/null); then
153
- echo "ERROR: jq failed to extract transcript_path from hook input." >&2
154
- echo "ERROR: jq failed to parse input" >> "$DEBUG_LOG"
155
- exit 2
156
- fi
157
-
158
- echo "Transcript path: $transcript_path" >> "$DEBUG_LOG"
159
- if [ -z "$transcript_path" ] || [ ! -f "$transcript_path" ]; then
160
- echo "No transcript or file doesn't exist, exiting" >> "$DEBUG_LOG"
161
- exit 0
162
- fi
163
-
164
- # Extract last assistant message from transcript
165
- # Transcript is JSONL format - each line is a message
166
- last_assistant_msg=$(grep '"role":"assistant"' "$transcript_path" | tail -1)
167
-
168
- echo "Last assistant message length: ${#last_assistant_msg}" >> "$DEBUG_LOG"
169
- if [ -z "$last_assistant_msg" ]; then
170
- # Normal case: No assistant messages yet
171
- echo "No assistant messages found, exiting" >> "$DEBUG_LOG"
172
- exit 0
173
- fi
174
-
175
- # Extract the text content from the message
176
- # Looking for the final JSON blob: {"proposedChanges": ..., "madeChanges": ...}
177
- if ! msg_text=$(echo "$last_assistant_msg" | jq -r '.message.content[]? | select(.type == "text") | .text' 2>/dev/null); then
178
- echo "ERROR: jq failed to parse assistant message structure. Transcript format may have changed." >&2
179
- echo "DEBUG: Message structure: $(echo "$last_assistant_msg" | jq -r '.message.content[].type' 2>/dev/null)" >> "$DEBUG_LOG"
180
- exit 2
181
- fi
182
-
183
- if [ -z "$msg_text" ]; then
184
- # Normal case: Message has no text content
185
- exit 0
186
- fi
187
-
188
- # Extract the JSON blob from the end of the message
189
- # Pattern: {"proposedChanges": boolean, "madeChanges": boolean, "askedQuestion": boolean}
190
- json_blob=$(echo "$msg_text" | grep -oE '\{"proposedChanges":\s*(true|false)\s*,\s*"madeChanges":\s*(true|false)\s*,\s*"askedQuestion":\s*(true|false)\s*\}' | tail -1)
191
-
192
- echo "JSON blob: $json_blob" >> "$DEBUG_LOG"
193
- if [ -z "$json_blob" ]; then
194
- # Check if this looks like a substantive response (>100 chars)
195
- # If so, remind agent to include JSON payload
196
- msg_length=${#msg_text}
197
- echo "No JSON blob found, message length: $msg_length" >> "$DEBUG_LOG"
198
-
199
- if [ "$msg_length" -gt 100 ]; then
200
- echo "Substantive response without JSON payload, sending reminder" >> "$DEBUG_LOG"
201
- echo "Missing required JSON response format. Please include: {\"proposedChanges\": bool, \"madeChanges\": bool, \"askedQuestion\": bool}" >&2
202
- exit 2
203
- fi
204
-
205
- # Short message without JSON is fine (acknowledgments, etc)
206
- echo "Short message without JSON, exiting" >> "$DEBUG_LOG"
207
- exit 0
208
- fi
209
-
210
- # Parse the boolean values
211
- if ! proposed_changes=$(echo "$json_blob" | jq -r '.proposedChanges // false' 2>/dev/null); then
212
- echo "ERROR: jq failed to parse proposedChanges field from JSON blob." >&2
213
- exit 2
214
- fi
215
-
216
- if ! made_changes=$(echo "$json_blob" | jq -r '.madeChanges // false' 2>/dev/null); then
217
- echo "ERROR: jq failed to parse madeChanges field from JSON blob." >&2
218
- exit 2
219
- fi
220
-
221
- if ! asked_question=$(echo "$json_blob" | jq -r '.askedQuestion // false' 2>/dev/null); then
222
- echo "ERROR: jq failed to parse askedQuestion field from JSON blob." >&2
223
- exit 2
224
- fi
225
-
226
- # If asked question, skip quality review (waiting for user response)
227
- echo "proposedChanges=$proposed_changes, madeChanges=$made_changes, askedQuestion=$asked_question" >> "$DEBUG_LOG"
228
- if [ "$asked_question" = "true" ]; then
229
- echo "Agent asked question, skipping quality review" >> "$DEBUG_LOG"
230
- exit 0
231
- fi
232
-
233
- # If either proposed or made changes, trigger quality review
234
- if [ "$proposed_changes" = "true" ] || [ "$made_changes" = "true" ]; then
235
- # Block and request quality review
236
- echo "TRIGGERING QUALITY REVIEW" >> "$DEBUG_LOG"
237
-
238
- # Find the shared quality review script (same directory as this hook)
239
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
240
-
241
- # Call shared quality review script
242
- if [ "$ask_questions" = "true" ]; then
243
- exec "$SCRIPT_DIR/run-quality-review.sh"
244
- else
245
- exec "$SCRIPT_DIR/run-quality-review.sh" --no-questions
246
- fi
247
- fi
248
-
249
- # No changes proposed or made - allow continuation
250
- exit 0
251
- EOF
252
- } > .claude/hooks/auto-quality-review.sh
253
-
254
- chmod +x .claude/hooks/auto-quality-review.sh
255
-
256
- # Create run-quality-review.sh (quality review prompt)
257
- {
258
- echo '#!/bin/bash'
259
- echo "$VERSION_HEADER"
260
- cat << 'EOF'
261
- # Shared Quality Review Script
262
- #
263
- # Prompts for a quality review with configurable questions.
264
- # Used by both Stop hooks and manual /quality-review command.
265
- #
266
- # Usage:
267
- # run-quality-review.sh # With questions enabled
268
- # run-quality-review.sh --no-questions # Without "ask me" prompt
269
- #
270
- # Environment variables:
271
- # CLAUDE_PROJECT_DIR - Project root (for finding config and prompts)
272
-
273
- # Default: ask questions enabled
274
- ask_questions=true
275
-
276
- # Parse command line arguments
277
- for arg in "$@"; do
278
- case "$arg" in
279
- --no-questions)
280
- ask_questions=false
281
- ;;
282
- esac
283
- done
284
-
285
- # Try to read project config if CLAUDE_PROJECT_DIR is set
286
- if [ -n "$CLAUDE_PROJECT_DIR" ]; then
287
- config_file="$CLAUDE_PROJECT_DIR/.auto-quality-review.config"
288
-
289
- if [ -f "$config_file" ]; then
290
- while IFS='=' read -r key value; do
291
- # Skip empty lines and comments
292
- [[ -z "$key" || "$key" =~ ^# ]] && continue
293
- # Trim whitespace
294
- key=$(echo "$key" | xargs)
295
- value=$(echo "$value" | xargs)
296
-
297
- case "$key" in
298
- ask_questions)
299
- ask_questions="$value"
300
- ;;
301
- esac
302
- done < "$config_file"
303
- fi
304
- fi
305
-
306
- # Try to read prompt from .safeword/prompts/quality-review.md
307
- PROMPT_FILE=""
308
- if [ -n "$CLAUDE_PROJECT_DIR" ] && [ -f "$CLAUDE_PROJECT_DIR/.safeword/prompts/quality-review.md" ]; then
309
- PROMPT_FILE="$CLAUDE_PROJECT_DIR/.safeword/prompts/quality-review.md"
310
- fi
311
-
312
- if [ -n "$PROMPT_FILE" ]; then
313
- # Read prompt from file, skip the header line
314
- tail -n +3 "$PROMPT_FILE" >&2
315
- else
316
- # Fallback to hardcoded prompt
317
- echo "Double check and critique your work just in case." >&2
318
- echo "" >&2
319
- echo "- Is it correct?" >&2
320
- echo "- Is it elegant?" >&2
321
- echo "- Does it adhere to the latest documentation and best practices for the relevant stack items, UX principles, domain requirements, and testing practices?" >&2
322
-
323
- if [ "$ask_questions" = "true" ]; then
324
- echo "- Ask me any non-obvious questions you can't research yourself in the codebase or online." >&2
325
- fi
326
-
327
- echo "- Think hard." >&2
328
- echo "- Avoid bloat." >&2
329
- fi
330
-
331
- # Exit with code 2 to block (Stop hook behavior)
332
- exit 2
333
- EOF
334
- } > .claude/hooks/run-quality-review.sh
335
-
336
- chmod +x .claude/hooks/run-quality-review.sh
337
-
338
- echo " ✓ Created auto-quality-review.sh (Stop hook)"
339
- echo " ✓ Created run-quality-review.sh (quality review prompt)"
340
-
341
- # Create quality-review slash command
342
- cat > .claude/commands/quality-review.md << 'EOF'
343
- Trigger a quality review to double-check your work.
344
-
345
- Execute:
346
- ```bash
347
- bash .claude/hooks/run-quality-review.sh
348
- ```
349
-
350
- This will prompt you to:
351
- - Verify correctness
352
- - Check elegance
353
- - Validate against latest docs and best practices
354
- - Consider asking clarifying questions
355
- - Think deeply and avoid bloat
356
- EOF
357
-
358
- echo " ✓ Created quality-review slash command"
359
-
360
- # Create version-check SessionStart hook
361
- {
362
- echo '#!/bin/bash'
363
- echo "$VERSION_HEADER"
364
- cat << 'EOF'
365
- # SAFE WORD Claude Config - SessionStart Hook
366
- # Injects version and status into Claude's context (silent - not displayed to user)
367
-
368
- echo "SAFE WORD Claude Config v1.0.0 installed - auto-linting and quality review active"
369
-
370
- exit 0
371
- EOF
372
- } > .claude/hooks/version-check.sh
373
-
374
- chmod +x .claude/hooks/version-check.sh
375
-
376
- echo " ✓ Created version-check SessionStart hook"
377
-
378
- # Create inject-timestamp UserPromptSubmit hook
379
- {
380
- echo '#!/bin/bash'
381
- echo "$VERSION_HEADER"
382
- cat << 'EOF'
383
- # Inject Timestamp - UserPromptSubmit Hook
384
- # Outputs current Unix timestamp for Claude's context awareness
385
- # Helps with accurate ticket timestamps and time-based reasoning
386
-
387
- echo "Current time: $(date +%s) ($(date -u +%Y-%m-%dT%H:%M:%SZ))"
388
- EOF
389
- } > .claude/hooks/inject-timestamp.sh
390
-
391
- chmod +x .claude/hooks/inject-timestamp.sh
392
-
393
- echo " ✓ Created inject-timestamp UserPromptSubmit hook"
394
- echo ""
395
-
396
- # ============================================================================
397
- # Step 4: Update settings.json
398
- # ============================================================================
399
- echo "[4/4] Updating .claude/settings.json..."
400
-
401
- # Create base settings.json if doesn't exist
402
- if [ ! -f .claude/settings.json ]; then
403
- echo '{"hooks": {}}' > .claude/settings.json
404
- echo " ✓ Created .claude/settings.json"
405
- fi
406
-
407
- # Check if auto-quality-review hook already exists in Stop
408
- if jq -e '.hooks.Stop[]?.hooks[]? | select(.command == "$CLAUDE_PROJECT_DIR/.claude/hooks/auto-quality-review.sh")' .claude/settings.json > /dev/null 2>&1; then
409
- echo " ✓ Stop hook already exists (skipped)"
410
- else
411
- # Append to Stop array (or create if doesn't exist)
412
- jq '.hooks.Stop = (.hooks.Stop // []) + [{"hooks": [{"type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/auto-quality-review.sh"}]}]' \
413
- .claude/settings.json > .claude/settings.json.tmp
414
- mv .claude/settings.json.tmp .claude/settings.json
415
- echo " ✓ Added Stop hook to settings.json"
416
- fi
417
-
418
- # Check if version-check hook already exists in SessionStart
419
- if jq -e '.hooks.SessionStart[]?.hooks[]? | select(.command == "$CLAUDE_PROJECT_DIR/.claude/hooks/version-check.sh")' .claude/settings.json > /dev/null 2>&1; then
420
- echo " ✓ SessionStart hook already exists (skipped)"
421
- else
422
- # Append to SessionStart array (or create if doesn't exist)
423
- jq '.hooks.SessionStart = (.hooks.SessionStart // []) + [{"hooks": [{"type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/version-check.sh"}]}]' \
424
- .claude/settings.json > .claude/settings.json.tmp
425
- mv .claude/settings.json.tmp .claude/settings.json
426
- echo " ✓ Added SessionStart hook to settings.json"
427
- fi
428
-
429
- # Check if inject-timestamp hook already exists in UserPromptSubmit
430
- if jq -e '.hooks.UserPromptSubmit[]?.hooks[]? | select(.command == "$CLAUDE_PROJECT_DIR/.claude/hooks/inject-timestamp.sh")' .claude/settings.json > /dev/null 2>&1; then
431
- echo " ✓ UserPromptSubmit hook already exists (skipped)"
432
- else
433
- # Append to UserPromptSubmit array (or create if doesn't exist)
434
- jq '.hooks.UserPromptSubmit = (.hooks.UserPromptSubmit // []) + [{"hooks": [{"type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/inject-timestamp.sh"}]}]' \
435
- .claude/settings.json > .claude/settings.json.tmp
436
- mv .claude/settings.json.tmp .claude/settings.json
437
- echo " ✓ Added UserPromptSubmit hook to settings.json"
438
- fi
439
- echo ""
440
-
441
- echo "================================="
442
- echo "✓ Setup Complete!"
443
- echo "================================="
444
- echo ""
445
- echo "What was configured:"
446
- echo " • Quality review hooks installed (triggers on changes)"
447
- echo " • Version display on session start"
448
- echo " • Timestamp injection on every prompt"
449
- echo " • /quality-review command available"
450
- echo " • All files are project-local and standalone"
451
- echo ""
452
- echo "⚠ IMPORTANT:"
453
- echo " • COMMIT .safeword/ and .claude/ to your repo for team consistency"
454
- echo " • Claude Code will read @./.safeword/SAFEWORD.md via SAFEWORD.md or CLAUDE.md reference"
455
- echo " • No external dependencies - project is fully portable"
456
- echo ""
457
- echo "Hook behavior:"
458
- echo " • Only runs in projects with SAFEWORD.md or CLAUDE.md"
459
- echo " • Triggers when Claude proposes or makes changes"
460
- echo " • Skips if Claude asks a question (waits for your answer)"
461
- echo " • Can be disabled per-project: create .auto-quality-review.config"
462
- echo ""
463
- echo "To customize:"
464
- echo " • Edit .claude/hooks/run-quality-review.sh for review prompt"
465
- echo " • Edit .claude/hooks/auto-quality-review.sh for trigger logic"
466
- echo " • Edit .claude/settings.json for hook configuration"
467
- echo ""
468
- echo "Test it:"
469
- echo " • Ask Claude to create or modify a file"
470
- echo " • Watch for quality review prompt after the change"
471
- echo ""
472
-
473
-
474
-
475
-
476
-
477
-