specweave 0.23.8 → 0.23.12

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 (130) hide show
  1. package/.claude-plugin/marketplace.json +7 -7
  2. package/CLAUDE.md +391 -1338
  3. package/dist/src/cli/commands/cleanup-cache.d.ts +14 -0
  4. package/dist/src/cli/commands/cleanup-cache.d.ts.map +1 -0
  5. package/dist/src/cli/commands/cleanup-cache.js +63 -0
  6. package/dist/src/cli/commands/cleanup-cache.js.map +1 -0
  7. package/dist/src/cli/commands/init.js +40 -0
  8. package/dist/src/cli/commands/init.js.map +1 -1
  9. package/dist/src/cli/commands/migrate-config.d.ts +22 -0
  10. package/dist/src/cli/commands/migrate-config.d.ts.map +1 -0
  11. package/dist/src/cli/commands/migrate-config.js +149 -0
  12. package/dist/src/cli/commands/migrate-config.js.map +1 -0
  13. package/dist/src/cli/helpers/async-project-loader.d.ts +148 -0
  14. package/dist/src/cli/helpers/async-project-loader.d.ts.map +1 -0
  15. package/dist/src/cli/helpers/async-project-loader.js +351 -0
  16. package/dist/src/cli/helpers/async-project-loader.js.map +1 -0
  17. package/dist/src/cli/helpers/cancelation-handler.d.ts +123 -0
  18. package/dist/src/cli/helpers/cancelation-handler.d.ts.map +1 -0
  19. package/dist/src/cli/helpers/cancelation-handler.js +187 -0
  20. package/dist/src/cli/helpers/cancelation-handler.js.map +1 -0
  21. package/dist/src/cli/helpers/import-strategy-prompter.d.ts +43 -0
  22. package/dist/src/cli/helpers/import-strategy-prompter.d.ts.map +1 -0
  23. package/dist/src/cli/helpers/import-strategy-prompter.js +136 -0
  24. package/dist/src/cli/helpers/import-strategy-prompter.js.map +1 -0
  25. package/dist/src/cli/helpers/issue-tracker/ado.d.ts +5 -2
  26. package/dist/src/cli/helpers/issue-tracker/ado.d.ts.map +1 -1
  27. package/dist/src/cli/helpers/issue-tracker/ado.js +90 -40
  28. package/dist/src/cli/helpers/issue-tracker/ado.js.map +1 -1
  29. package/dist/src/cli/helpers/issue-tracker/index.d.ts.map +1 -1
  30. package/dist/src/cli/helpers/issue-tracker/index.js +112 -60
  31. package/dist/src/cli/helpers/issue-tracker/index.js.map +1 -1
  32. package/dist/src/cli/helpers/issue-tracker/jira.d.ts +26 -2
  33. package/dist/src/cli/helpers/issue-tracker/jira.d.ts.map +1 -1
  34. package/dist/src/cli/helpers/issue-tracker/jira.js +197 -132
  35. package/dist/src/cli/helpers/issue-tracker/jira.js.map +1 -1
  36. package/dist/src/cli/helpers/progress-tracker.d.ts +121 -0
  37. package/dist/src/cli/helpers/progress-tracker.d.ts.map +1 -0
  38. package/dist/src/cli/helpers/progress-tracker.js +202 -0
  39. package/dist/src/cli/helpers/progress-tracker.js.map +1 -0
  40. package/dist/src/cli/helpers/project-count-fetcher.d.ts +69 -0
  41. package/dist/src/cli/helpers/project-count-fetcher.d.ts.map +1 -0
  42. package/dist/src/cli/helpers/project-count-fetcher.js +173 -0
  43. package/dist/src/cli/helpers/project-count-fetcher.js.map +1 -0
  44. package/dist/src/config/types.d.ts +14 -14
  45. package/dist/src/core/cache/cache-manager.d.ts +119 -0
  46. package/dist/src/core/cache/cache-manager.d.ts.map +1 -0
  47. package/dist/src/core/cache/cache-manager.js +304 -0
  48. package/dist/src/core/cache/cache-manager.js.map +1 -0
  49. package/dist/src/core/cache/rate-limit-checker.d.ts +92 -0
  50. package/dist/src/core/cache/rate-limit-checker.d.ts.map +1 -0
  51. package/dist/src/core/cache/rate-limit-checker.js +160 -0
  52. package/dist/src/core/cache/rate-limit-checker.js.map +1 -0
  53. package/dist/src/core/config/config-manager.d.ts +135 -0
  54. package/dist/src/core/config/config-manager.d.ts.map +1 -0
  55. package/dist/src/core/config/config-manager.js +341 -0
  56. package/dist/src/core/config/config-manager.js.map +1 -0
  57. package/dist/src/core/config/config-migrator.d.ts +102 -0
  58. package/dist/src/core/config/config-migrator.d.ts.map +1 -0
  59. package/dist/src/core/config/config-migrator.js +367 -0
  60. package/dist/src/core/config/config-migrator.js.map +1 -0
  61. package/dist/src/core/config/index.d.ts +10 -0
  62. package/dist/src/core/config/index.d.ts.map +1 -0
  63. package/dist/src/core/config/index.js +10 -0
  64. package/dist/src/core/config/index.js.map +1 -0
  65. package/dist/src/core/config/types.d.ts +216 -0
  66. package/dist/src/core/config/types.d.ts.map +1 -0
  67. package/dist/src/core/config/types.js +32 -0
  68. package/dist/src/core/config/types.js.map +1 -0
  69. package/dist/src/core/progress/cancelation-handler.d.ts +79 -0
  70. package/dist/src/core/progress/cancelation-handler.d.ts.map +1 -0
  71. package/dist/src/core/progress/cancelation-handler.js +111 -0
  72. package/dist/src/core/progress/cancelation-handler.js.map +1 -0
  73. package/dist/src/core/progress/import-state.d.ts +71 -0
  74. package/dist/src/core/progress/import-state.d.ts.map +1 -0
  75. package/dist/src/core/progress/import-state.js +96 -0
  76. package/dist/src/core/progress/import-state.js.map +1 -0
  77. package/dist/src/core/progress/progress-tracker.d.ts +139 -0
  78. package/dist/src/core/progress/progress-tracker.d.ts.map +1 -0
  79. package/dist/src/core/progress/progress-tracker.js +223 -0
  80. package/dist/src/core/progress/progress-tracker.js.map +1 -0
  81. package/dist/src/init/architecture/types.d.ts +6 -6
  82. package/dist/src/integrations/ado/ado-client.d.ts +25 -0
  83. package/dist/src/integrations/ado/ado-client.d.ts.map +1 -1
  84. package/dist/src/integrations/ado/ado-client.js +67 -0
  85. package/dist/src/integrations/ado/ado-client.js.map +1 -1
  86. package/dist/src/integrations/ado/ado-dependency-loader.d.ts +99 -0
  87. package/dist/src/integrations/ado/ado-dependency-loader.d.ts.map +1 -0
  88. package/dist/src/integrations/ado/ado-dependency-loader.js +207 -0
  89. package/dist/src/integrations/ado/ado-dependency-loader.js.map +1 -0
  90. package/dist/src/integrations/jira/jira-client.d.ts +32 -0
  91. package/dist/src/integrations/jira/jira-client.d.ts.map +1 -1
  92. package/dist/src/integrations/jira/jira-client.js +81 -0
  93. package/dist/src/integrations/jira/jira-client.js.map +1 -1
  94. package/dist/src/integrations/jira/jira-dependency-loader.d.ts +101 -0
  95. package/dist/src/integrations/jira/jira-dependency-loader.d.ts.map +1 -0
  96. package/dist/src/integrations/jira/jira-dependency-loader.js +200 -0
  97. package/dist/src/integrations/jira/jira-dependency-loader.js.map +1 -0
  98. package/dist/src/integrations/jira/jira-hierarchy-mapper.d.ts +104 -0
  99. package/dist/src/integrations/jira/jira-hierarchy-mapper.d.ts.map +1 -0
  100. package/dist/src/integrations/jira/jira-hierarchy-mapper.js +178 -0
  101. package/dist/src/integrations/jira/jira-hierarchy-mapper.js.map +1 -0
  102. package/package.json +1 -1
  103. package/plugins/specweave/.claude-plugin/plugin.json +20 -0
  104. package/plugins/specweave/agents/architect/AGENT.md +100 -602
  105. package/plugins/specweave/agents/pm/AGENT.md +96 -597
  106. package/plugins/specweave/agents/pm/AGENT.md.bak +1893 -0
  107. package/plugins/specweave/agents/pm/AGENT.md.bak2 +1754 -0
  108. package/plugins/specweave/commands/check-hooks.md +257 -0
  109. package/plugins/specweave/commands/migrate-config.md +104 -0
  110. package/plugins/specweave/hooks/post-edit-spec.sh +202 -31
  111. package/plugins/specweave/hooks/post-task-completion.sh +225 -228
  112. package/plugins/specweave/hooks/post-write-spec.sh +207 -31
  113. package/plugins/specweave/hooks/pre-edit-spec.sh +151 -0
  114. package/plugins/specweave/hooks/pre-task-completion.sh +5 -7
  115. package/plugins/specweave/hooks/pre-write-spec.sh +151 -0
  116. package/plugins/specweave/hooks/test-pretooluse-env.sh +72 -0
  117. package/plugins/specweave/skills/compliance-architecture/SKILL.md +374 -0
  118. package/plugins/specweave/skills/external-sync-wizard/SKILL.md +610 -0
  119. package/plugins/specweave/skills/pm-closure-validation/SKILL.md +541 -0
  120. package/plugins/specweave/skills/roadmap-planner/SKILL.md +473 -0
  121. package/plugins/specweave-ado/commands/refresh-cache.js +25 -0
  122. package/plugins/specweave-ado/commands/refresh-cache.ts +40 -0
  123. package/plugins/specweave-ado/hooks/post-task-completion.sh +1 -1
  124. package/plugins/specweave-github/hooks/post-task-completion.sh +1 -1
  125. package/plugins/specweave-jira/commands/refresh-cache.js +25 -0
  126. package/plugins/specweave-jira/commands/refresh-cache.ts +40 -0
  127. package/plugins/specweave-jira/hooks/post-task-completion.sh +1 -1
  128. package/plugins/specweave-kafka-streams/commands/topology.md +437 -0
  129. package/plugins/specweave-n8n/commands/workflow-template.md +262 -0
  130. package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +228 -6333
@@ -0,0 +1,257 @@
1
+ ---
2
+ description: Validate hook health and display performance metrics (Tier 2 monitoring)
3
+ ---
4
+
5
+ # /specweave:check-hooks - Hook Health Dashboard
6
+
7
+ **Purpose:** Display comprehensive hook performance metrics, detection rates, and health status.
8
+
9
+ **Tier 2 Feature:** This command validates the PreToolUse coordination layer is working correctly.
10
+
11
+ ---
12
+
13
+ ## Instructions for Claude
14
+
15
+ When this command is executed, perform the following analysis:
16
+
17
+ ### 1. **Read Hook Metrics File**
18
+
19
+ Location: `.specweave/state/hook-metrics.jsonl`
20
+
21
+ The metrics file contains JSONL (JSON Lines) format - one JSON object per line.
22
+
23
+ Each entry has:
24
+ ```json
25
+ {
26
+ "timestamp": "2025-11-22T01:30:00Z",
27
+ "hook": "pre-edit-spec|post-edit-spec|pre-write-spec|post-write-spec",
28
+ "event": "file_detected|tier2_success|tier1_fallback",
29
+ "file_path": "/path/to/file.md",
30
+ "method": "pretooluse|env_content|env_result|env_args|mtime"
31
+ }
32
+ ```
33
+
34
+ ### 2. **Calculate Key Metrics**
35
+
36
+ **Tier 2 Success Rate:**
37
+ ```
38
+ Tier 2 Rate = (tier2_success events) / (total post-tool events) * 100%
39
+ ```
40
+
41
+ **Target:** >95% (Tier 2 should handle most cases)
42
+
43
+ **Detection Method Breakdown:**
44
+ - `pretooluse`: Tier 2 PreToolUse coordination (best)
45
+ - `env_content`: Environment variable (TOOL_USE_CONTENT)
46
+ - `env_result`: Environment variable (TOOL_RESULT)
47
+ - `env_args`: Environment variable (TOOL_USE_ARGS)
48
+ - `mtime`: File modification time fallback (Tier 1)
49
+
50
+ **Fallback Rate:**
51
+ ```
52
+ Fallback Rate = (mtime detections) / (total detections) * 100%
53
+ ```
54
+
55
+ **Target:** <5% (should rarely need mtime fallback)
56
+
57
+ ### 3. **Check Hook Health Status**
58
+
59
+ **Circuit Breaker Status:**
60
+ - File: `.specweave/state/.hook-circuit-breaker`
61
+ - If exists: Read failure count
62
+ - If count ≥ 3: ⚠️ CIRCUIT BREAKER OPEN (hooks disabled)
63
+ - If count < 3: ✅ Circuit breaker OK
64
+ - If doesn't exist: ✅ No failures detected
65
+
66
+ **Kill Switch Status:**
67
+ - Check environment variable: `SPECWEAVE_DISABLE_HOOKS`
68
+ - If set to "1": ⚠️ HOOKS MANUALLY DISABLED
69
+ - If not set or "0": ✅ Hooks enabled
70
+
71
+ **Lock Files Status:**
72
+ - Check for stale locks:
73
+ - `.specweave/state/.hook-post-edit.lock`
74
+ - `.specweave/state/.hook-post-write.lock`
75
+ - If older than 10 seconds: ⚠️ Stale lock detected
76
+ - If not present: ✅ No locks
77
+
78
+ ### 4. **Read Recent Hook Logs**
79
+
80
+ Location: `.specweave/logs/hooks-debug.log`
81
+
82
+ **Look for:**
83
+ - Recent errors or warnings
84
+ - Debounce effectiveness (count "Debounced" messages)
85
+ - PreToolUse signal messages
86
+ - Circuit breaker trips
87
+
88
+ **Time window:** Last 100 lines or last 1 hour
89
+
90
+ ### 5. **Output Format**
91
+
92
+ Display results in this format:
93
+
94
+ ```
95
+ 🔍 SpecWeave Hook Health Dashboard (Tier 2)
96
+ ═══════════════════════════════════════════════════════════
97
+
98
+ 📊 DETECTION METRICS (Last 24 hours)
99
+ ────────────────────────────────────
100
+ Total Hook Executions: 156
101
+ Tier 2 Success (PreToolUse): 149 (95.5%) ✅
102
+ Tier 1 Fallback (env vars): 5 (3.2%)
103
+ Tier 1 Fallback (mtime): 2 (1.3%)
104
+
105
+ Detection Method Breakdown:
106
+ • pretooluse: 149 (95.5%) ✅ Target: >95%
107
+ • env_content: 3 (1.9%)
108
+ • env_args: 2 (1.3%)
109
+ • mtime: 2 (1.3%) ✅ Target: <5%
110
+
111
+ 🏥 HEALTH STATUS
112
+ ────────────────────────────────────
113
+ Circuit Breaker: ✅ OK (0 failures)
114
+ Kill Switch: ✅ Hooks enabled
115
+ Stale Locks: ✅ None detected
116
+ Debounce Efficiency: 87% (136/156 skipped)
117
+
118
+ ⚡ PERFORMANCE
119
+ ────────────────────────────────────
120
+ Average Hook Latency: ~3ms
121
+ Debounce Window: 5 seconds
122
+ Background Updates: Active
123
+ Metrics Collection: Active
124
+
125
+ 📝 RECENT ACTIVITY (Last 10 events)
126
+ ────────────────────────────────────
127
+ [2025-11-22 01:30:15] post-edit-spec: File from PreToolUse signal: /path/to/spec.md
128
+ [2025-11-22 01:30:10] pre-edit-spec: Signaled PostToolUse for: /path/to/spec.md
129
+ [2025-11-22 01:29:45] post-edit-spec: Debounced (2s since last update)
130
+ ...
131
+
132
+ ✅ SUMMARY
133
+ ────────────────────────────────────
134
+ Status: HEALTHY ✅
135
+
136
+ Tier 2 coordination is working correctly (95.5% success rate).
137
+ Fallback rate is within acceptable range (<5%).
138
+ No health issues detected.
139
+
140
+ Recommendations:
141
+ • None - system performing optimally
142
+
143
+ To disable hooks temporarily:
144
+ export SPECWEAVE_DISABLE_HOOKS=1
145
+
146
+ To reset circuit breaker:
147
+ rm .specweave/state/.hook-circuit-breaker
148
+ ```
149
+
150
+ ### 6. **Health Assessment Logic**
151
+
152
+ **Determine overall status:**
153
+
154
+ - ✅ **HEALTHY** if:
155
+ - Tier 2 success rate >90%
156
+ - Fallback rate <10%
157
+ - No circuit breaker trips
158
+ - Hooks enabled
159
+
160
+ - ⚠️ **WARNING** if:
161
+ - Tier 2 success rate 70-90%
162
+ - Fallback rate 10-30%
163
+ - Circuit breaker count 1-2
164
+
165
+ - ❌ **CRITICAL** if:
166
+ - Tier 2 success rate <70%
167
+ - Fallback rate >30%
168
+ - Circuit breaker open (count ≥ 3)
169
+ - Hooks manually disabled
170
+
171
+ ### 7. **Troubleshooting Recommendations**
172
+
173
+ Based on status, provide targeted recommendations:
174
+
175
+ **If Tier 2 success rate <95%:**
176
+ ```
177
+ ⚠️ PreToolUse coordination not working optimally
178
+
179
+ Recommendations:
180
+ 1. Check if PreToolUse hooks are registered in plugin.json
181
+ 2. Verify hook files are executable (chmod +x)
182
+ 3. Review .specweave/logs/hooks-debug.log for PreToolUse errors
183
+ 4. Consider filing bug with Anthropic (environment variable passing)
184
+ ```
185
+
186
+ **If fallback rate >10%:**
187
+ ```
188
+ ⚠️ High fallback rate detected
189
+
190
+ Recommendations:
191
+ 1. Tier 2 coordination may not be working
192
+ 2. Environment variables still not being passed
193
+ 3. Consider Tier 3 implementation (filesystem watcher)
194
+ ```
195
+
196
+ **If circuit breaker open:**
197
+ ```
198
+ ❌ Hooks disabled due to consecutive failures
199
+
200
+ Immediate actions:
201
+ 1. Review .specweave/logs/hooks-debug.log for errors
202
+ 2. Fix underlying issues
203
+ 3. Reset circuit breaker: rm .specweave/state/.hook-circuit-breaker
204
+ 4. Restart Claude Code
205
+ ```
206
+
207
+ ### 8. **Error Handling**
208
+
209
+ If metrics file doesn't exist:
210
+ ```
211
+ ⚠️ No metrics data available
212
+
213
+ This is normal for:
214
+ • New SpecWeave installation
215
+ • First run after Tier 2 upgrade
216
+
217
+ Metrics will be collected automatically as you work.
218
+ Run this command again after a few Edit/Write operations.
219
+ ```
220
+
221
+ If logs not accessible:
222
+ ```
223
+ ⚠️ Could not read hook logs
224
+
225
+ Check file permissions:
226
+ .specweave/logs/hooks-debug.log
227
+ .specweave/state/hook-metrics.jsonl
228
+ ```
229
+
230
+ ---
231
+
232
+ ## Implementation Notes
233
+
234
+ **For Claude:**
235
+ 1. Parse JSONL file line by line (each line is a JSON object)
236
+ 2. Calculate metrics using simple counting
237
+ 3. Display results using the template above
238
+ 4. Adjust recommendations based on actual metrics
239
+ 5. Keep output concise but informative
240
+
241
+ **Time-based filtering:**
242
+ - Default: Last 24 hours
243
+ - Option: All time (if user requests)
244
+ - Filter by comparing timestamp field
245
+
246
+ **Edge cases:**
247
+ - Empty metrics file → Show "waiting for data" message
248
+ - Corrupted JSONL → Skip invalid lines, report count
249
+ - Missing state directory → Create it, show initialization message
250
+
251
+ ---
252
+
253
+ ## Related Documentation
254
+
255
+ - ADR-0060: Hook Performance Optimization
256
+ - `.specweave/increments/0050-*/reports/hook-crash-analysis.md`
257
+ - CLAUDE.md: "Hook Performance Best Practices"
@@ -0,0 +1,104 @@
1
+ ---
2
+ name: specweave:migrate-config
3
+ description: Migrate .env-only configuration to split secrets/config format (v0.24.0+)
4
+ ---
5
+
6
+ Migrate your project from the old .env-only format to the new split format where secrets stay in `.env` (gitignored) and configuration moves to `.specweave/config.json` (committed to git).
7
+
8
+ **What this command does:**
9
+
10
+ 1. ✅ Analyzes your `.env` file
11
+ 2. ✅ Classifies variables as "secrets" or "config"
12
+ 3. ✅ Backs up original `.env` file
13
+ 4. ✅ Updates `.env` (keeps only secrets)
14
+ 5. ✅ Creates/updates `.specweave/config.json` (adds config)
15
+ 6. ✅ Generates `.env.example` for team onboarding
16
+
17
+ **When to use:**
18
+
19
+ - You're upgrading from SpecWeave v0.23.x or earlier
20
+ - Your `.env` contains both secrets AND configuration (domain, strategy, etc.)
21
+ - You want to share configuration with your team via git
22
+
23
+ **Command:**
24
+
25
+ ```bash
26
+ node -e "require('./dist/src/cli/commands/migrate-config.js').migrateConfig()"
27
+ ```
28
+
29
+ **Options:**
30
+
31
+ - `--dry-run`: Preview migration without making changes
32
+ - `--yes`: Skip confirmation prompt
33
+ - `--force`: Force migration even if not needed
34
+
35
+ **Example output:**
36
+
37
+ ```
38
+ 🔄 SpecWeave Configuration Migration
39
+
40
+ 📋 Migration Preview
41
+
42
+ Classification Results:
43
+ Secrets: 3 variables
44
+ Config: 5 variables
45
+
46
+ 📊 Detailed Breakdown:
47
+
48
+ Secrets (will stay in .env):
49
+ JIRA_API_TOKEN=xyzabc***456
50
+ └─ Contains keyword: token
51
+
52
+ JIRA_EMAIL=user@example.com
53
+ └─ Email address (used for authentication)
54
+
55
+ Configuration (will move to config.json):
56
+ JIRA_DOMAIN=company.atlassian.net
57
+ └─ Non-sensitive configuration data
58
+
59
+ JIRA_STRATEGY=project-per-team
60
+ └─ Non-sensitive configuration data
61
+
62
+ ✅ Migration Successful!
63
+
64
+ Summary:
65
+ ✓ 3 secrets kept in .env
66
+ ✓ 5 config items moved to config.json
67
+ ✓ Backup created: .env.backup.1234567890
68
+ ✓ .env.example generated
69
+
70
+ 📝 Next Steps:
71
+
72
+ 1. Review .specweave/config.json (commit to git)
73
+ 2. Share .env.example with team (commit to git)
74
+ 3. Team members: cp .env.example .env (fill in tokens)
75
+ ```
76
+
77
+ **Benefits:**
78
+
79
+ - ✅ Team shares configuration via git
80
+ - ✅ Secrets stay local (never committed)
81
+ - ✅ Type-safe configuration with validation
82
+ - ✅ Easy onboarding for new team members
83
+
84
+ **Classification logic:**
85
+
86
+ Variables classified as **secrets** (stay in .env):
87
+ - Contains keywords: `token`, `api_token`, `pat`, `secret`, `key`, `password`, `credential`, `auth`
88
+ - Email addresses (used for authentication)
89
+
90
+ Variables classified as **config** (move to config.json):
91
+ - Everything else: domains, strategies, project keys, organizations, etc.
92
+
93
+ **Safety:**
94
+
95
+ - 🔒 Always creates backup before modifying `.env`
96
+ - 🔒 Atomic operation (either completes fully or rolls back)
97
+ - 🔒 Idempotent (can run multiple times safely)
98
+ - 🔒 Dry-run mode available for preview
99
+
100
+ **See also:**
101
+
102
+ - ADR-0050: Secrets vs Configuration Separation
103
+ - `/specweave:validate` - Validate configuration after migration
104
+ - Documentation: `CLAUDE.md` → Configuration Management section
@@ -8,12 +8,30 @@
8
8
  # This ensures status line stays in sync when ACs are marked complete via Edit tool
9
9
  # (not just TodoWrite, which only tracks internal todo lists)
10
10
  #
11
- # CRITICAL FIX (v0.24.1): Enhanced file detection to handle increment completion
11
+ # EMERGENCY FIXES (v0.24.3):
12
+ # - Kill switch: Set SPECWEAVE_DISABLE_HOOKS=1 to disable ALL hooks
13
+ # - Circuit breaker: Auto-disable after 3 consecutive failures
14
+ # - File locking: Prevent concurrent executions (max 1 at a time)
15
+ # - Aggressive debouncing: Increased from 1s to 5s
16
+ # - Complete error isolation: Never let errors reach Claude Code
17
+ #
18
+ # TIER 1 IMPROVEMENTS (v0.24.2):
19
+ # - Debouncing: Skip if updated less than 1 second ago (90% overhead reduction)
20
+ # - File mtime detection: Check recently modified spec.md/tasks.md as fallback
21
+ # - Non-blocking: Run update-status-line.sh in background
22
+ # - Smart detection: Only update if spec/tasks files actually changed
23
+ #
24
+ # Previous fix (v0.24.1): Enhanced file detection for increment completion
12
25
  # - Detects edits via TOOL_USE_CONTENT, TOOL_RESULT, and argument parsing
13
26
  # - Always updates status line for ANY spec.md/tasks.md edit in increments folder
14
- # - Fixes bug where status line wasn't updating on increment close
15
27
 
16
- set -e
28
+ # CRITICAL: Remove set -e to prevent hook errors from crashing Claude Code
29
+ set +e
30
+
31
+ # EMERGENCY KILL SWITCH: Disable all hooks if env variable set
32
+ if [[ "${SPECWEAVE_DISABLE_HOOKS:-0}" == "1" ]]; then
33
+ exit 0
34
+ fi
17
35
 
18
36
  # Find project root
19
37
  find_project_root() {
@@ -32,31 +50,129 @@ PROJECT_ROOT=$(find_project_root)
32
50
  LOGS_DIR="$PROJECT_ROOT/.specweave/logs"
33
51
  DEBUG_LOG="$LOGS_DIR/hooks-debug.log"
34
52
 
35
- # Ensure logs directory exists
36
- mkdir -p "$LOGS_DIR" 2>/dev/null || true
53
+ # Ensure state and logs directories exist
54
+ mkdir -p "$PROJECT_ROOT/.specweave/state" "$LOGS_DIR" 2>/dev/null || true
37
55
 
38
- # Extract edited file from multiple sources (Claude Code provides this in various ways)
39
- EDITED_FILE=""
56
+ # EMERGENCY CIRCUIT BREAKER: Track consecutive failures
57
+ CIRCUIT_BREAKER_FILE="$PROJECT_ROOT/.specweave/state/.hook-circuit-breaker"
58
+ CIRCUIT_BREAKER_THRESHOLD=3
40
59
 
41
- # Method 1: TOOL_USE_CONTENT environment variable (primary)
42
- if [[ -n "${TOOL_USE_CONTENT:-}" ]]; then
43
- EDITED_FILE="$TOOL_USE_CONTENT"
60
+ if [[ -f "$CIRCUIT_BREAKER_FILE" ]]; then
61
+ FAILURE_COUNT=$(cat "$CIRCUIT_BREAKER_FILE" 2>/dev/null || echo 0)
62
+ if (( FAILURE_COUNT >= CIRCUIT_BREAKER_THRESHOLD )); then
63
+ echo "[$(date)] CIRCUIT BREAKER OPEN: Hooks disabled after $FAILURE_COUNT failures. Run: rm $CIRCUIT_BREAKER_FILE" >> "$DEBUG_LOG" 2>/dev/null || true
64
+ exit 0
65
+ fi
44
66
  fi
45
67
 
46
- # Method 2: TOOL_RESULT environment variable (fallback)
47
- if [[ -z "$EDITED_FILE" ]] && [[ -n "${TOOL_RESULT:-}" ]]; then
48
- # Extract file_path from tool result JSON
49
- EDITED_FILE=$(echo "$TOOL_RESULT" | grep -o '"file_path"[[:space:]]*:[[:space:]]*"[^"]*"' | head -1 | sed 's/.*"\([^"]*\)".*/\1/' || echo "")
68
+ # EMERGENCY FILE LOCK: Prevent concurrent executions
69
+ LOCK_FILE="$PROJECT_ROOT/.specweave/state/.hook-post-edit.lock"
70
+ LOCK_TIMEOUT=5 # seconds
71
+
72
+ # Try to acquire lock with timeout
73
+ LOCK_ACQUIRED=false
74
+ for i in {1..5}; do
75
+ if mkdir "$LOCK_FILE" 2>/dev/null; then
76
+ LOCK_ACQUIRED=true
77
+ trap 'rmdir "$LOCK_FILE" 2>/dev/null || true' EXIT
78
+ break
79
+ fi
80
+
81
+ # Check if lock is stale (older than LOCK_TIMEOUT seconds)
82
+ if [[ -d "$LOCK_FILE" ]]; then
83
+ LOCK_AGE=$(($(date +%s) - $(stat -f "%m" "$LOCK_FILE" 2>/dev/null || echo 0)))
84
+ if (( LOCK_AGE > LOCK_TIMEOUT )); then
85
+ rmdir "$LOCK_FILE" 2>/dev/null || true
86
+ continue
87
+ fi
88
+ fi
89
+
90
+ sleep 0.2
91
+ done
92
+
93
+ if [[ "$LOCK_ACQUIRED" == "false" ]]; then
94
+ echo "[$(date)] post-edit-spec: Could not acquire lock, skipping" >> "$DEBUG_LOG" 2>/dev/null || true
95
+ exit 0
50
96
  fi
51
97
 
52
- # Method 3: Parse tool use arguments (last resort)
53
- if [[ -z "$EDITED_FILE" ]] && [[ -n "${TOOL_USE_ARGS:-}" ]]; then
54
- # Extract file_path from tool arguments
55
- EDITED_FILE=$(echo "$TOOL_USE_ARGS" | grep -o '"file_path"[[:space:]]*:[[:space:]]*"[^"]*"' | head -1 | sed 's/.*"\([^"]*\)".*/\1/' || echo "")
98
+ # Log rotation: Keep debug log under 100KB
99
+ if [[ -f "$DEBUG_LOG" ]] && [[ $(wc -c < "$DEBUG_LOG" 2>/dev/null || echo 0) -gt 102400 ]]; then
100
+ tail -100 "$DEBUG_LOG" > "$DEBUG_LOG.tmp" 2>/dev/null || true
101
+ mv "$DEBUG_LOG.tmp" "$DEBUG_LOG" 2>/dev/null || true
102
+ echo "[$(date)] Log rotated" >> "$DEBUG_LOG" 2>/dev/null || true
56
103
  fi
57
104
 
58
- # Log detection attempt
59
- echo "[$(date)] post-edit-spec: Detected file: ${EDITED_FILE:-<none>}" >> "$DEBUG_LOG" 2>/dev/null || true
105
+ # ============================================================================
106
+ # TIER 1 FIX: Debouncing (Prevent Redundant Updates)
107
+ # ============================================================================
108
+ # Skip update if we updated less than 5 seconds ago (INCREASED FROM 1s)
109
+ # This handles rapid consecutive edits (e.g., 10 tasks marked complete quickly)
110
+ LAST_UPDATE_FILE="$PROJECT_ROOT/.specweave/state/.last-status-update"
111
+ DEBOUNCE_SECONDS=5
112
+
113
+ if [[ -f "$LAST_UPDATE_FILE" ]]; then
114
+ LAST_UPDATE=$(cat "$LAST_UPDATE_FILE" 2>/dev/null || echo 0)
115
+ NOW=$(date +%s)
116
+ TIME_SINCE_UPDATE=$((NOW - LAST_UPDATE))
117
+
118
+ if (( TIME_SINCE_UPDATE < DEBOUNCE_SECONDS )); then
119
+ echo "[$(date)] post-edit-spec: Debounced (${TIME_SINCE_UPDATE}s since last update)" >> "$DEBUG_LOG" 2>/dev/null || true
120
+ exit 0 # Skip this update
121
+ fi
122
+ fi
123
+
124
+ # ============================================================================
125
+ # TIER 2: Check for PreToolUse Signal (Primary Detection Method)
126
+ # ============================================================================
127
+ PENDING_FILE="$PROJECT_ROOT/.specweave/state/.pending-status-update"
128
+ METRICS_FILE="$PROJECT_ROOT/.specweave/state/hook-metrics.jsonl"
129
+ EDITED_FILE=""
130
+ DETECTION_METHOD="none"
131
+
132
+ # First, check if PreToolUse hook left a signal
133
+ if [[ -f "$PENDING_FILE" ]]; then
134
+ EDITED_FILE=$(cat "$PENDING_FILE" 2>/dev/null || echo "")
135
+ # Delete pending file immediately (consume signal)
136
+ rm "$PENDING_FILE" 2>/dev/null || true
137
+
138
+ if [[ -n "$EDITED_FILE" ]]; then
139
+ DETECTION_METHOD="pretooluse"
140
+ echo "[$(date)] post-edit-spec: File from PreToolUse signal: $EDITED_FILE" >> "$DEBUG_LOG" 2>/dev/null || true
141
+
142
+ # Record Tier 2 success metric
143
+ TIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%SZ)
144
+ echo "{\"timestamp\":\"$TIMESTAMP\",\"hook\":\"post-edit-spec\",\"event\":\"tier2_success\",\"method\":\"pretooluse\"}" >> "$METRICS_FILE" 2>/dev/null || true
145
+ fi
146
+ fi
147
+
148
+ # ============================================================================
149
+ # TIER 1 FALLBACK: Environment Variable Detection
150
+ # ============================================================================
151
+ # If PreToolUse didn't provide signal, fall back to Tier 1 methods
152
+ if [[ -z "$EDITED_FILE" ]]; then
153
+ # Method 1: TOOL_USE_CONTENT environment variable
154
+ if [[ -n "${TOOL_USE_CONTENT:-}" ]]; then
155
+ EDITED_FILE="$TOOL_USE_CONTENT"
156
+ DETECTION_METHOD="env_content"
157
+ fi
158
+
159
+ # Method 2: TOOL_RESULT environment variable
160
+ if [[ -z "$EDITED_FILE" ]] && [[ -n "${TOOL_RESULT:-}" ]]; then
161
+ EDITED_FILE=$(echo "$TOOL_RESULT" | grep -o '"file_path"[[:space:]]*:[[:space:]]*"[^"]*"' | head -1 | sed 's/.*"\([^"]*\)".*/\1/' || echo "")
162
+ DETECTION_METHOD="env_result"
163
+ fi
164
+
165
+ # Method 3: TOOL_USE_ARGS
166
+ if [[ -z "$EDITED_FILE" ]] && [[ -n "${TOOL_USE_ARGS:-}" ]]; then
167
+ EDITED_FILE=$(echo "$TOOL_USE_ARGS" | grep -o '"file_path"[[:space:]]*:[[:space:]]*"[^"]*"' | head -1 | sed 's/.*"\([^"]*\)".*/\1/' || echo "")
168
+ DETECTION_METHOD="env_args"
169
+ fi
170
+
171
+ # Log env var detection (for metrics)
172
+ if [[ -n "$EDITED_FILE" ]]; then
173
+ echo "[$(date)] post-edit-spec: File from env vars ($DETECTION_METHOD): $EDITED_FILE" >> "$DEBUG_LOG" 2>/dev/null || true
174
+ fi
175
+ fi
60
176
 
61
177
  # Check if we detected a spec.md or tasks.md edit in increments folder
62
178
  SHOULD_UPDATE=false
@@ -72,23 +188,78 @@ if [[ -n "$EDITED_FILE" ]]; then
72
188
  fi
73
189
  fi
74
190
 
75
- # If we couldn't detect the file via environment variables, always update status line
76
- # This ensures we don't miss updates during increment closure
191
+ # ============================================================================
192
+ # TIER 1 FIX: File Modification Time Detection (Fallback)
193
+ # ============================================================================
194
+ # If we couldn't detect the file via environment variables, check which files
195
+ # were modified recently (within last 2 seconds) instead of blindly updating
77
196
  if [[ -z "$EDITED_FILE" ]]; then
78
- echo "[$(date)] post-edit-spec: No file detected - updating status line as safety measure" >> "$DEBUG_LOG" 2>/dev/null || true
79
- SHOULD_UPDATE=true
197
+ echo "[$(date)] post-edit-spec: Env vars empty - checking file mtimes" >> "$DEBUG_LOG" 2>/dev/null || true
198
+
199
+ NOW=$(date +%s)
200
+ INCREMENTS_DIR="$PROJECT_ROOT/.specweave/increments"
201
+
202
+ # Check for recently modified spec.md or tasks.md files
203
+ if [[ -d "$INCREMENTS_DIR" ]]; then
204
+ for file in "$INCREMENTS_DIR"/*/spec.md "$INCREMENTS_DIR"/*/tasks.md; do
205
+ if [[ -f "$file" ]]; then
206
+ # Get file modification time (platform-specific)
207
+ if [[ "$(uname)" == "Darwin" ]]; then
208
+ MTIME=$(stat -f "%m" "$file" 2>/dev/null || echo 0)
209
+ else
210
+ MTIME=$(stat -c "%Y" "$file" 2>/dev/null || echo 0)
211
+ fi
212
+
213
+ # If file was modified in last 2 seconds, consider it the edited file
214
+ TIME_DIFF=$((NOW - MTIME))
215
+ if (( TIME_DIFF <= 2 )); then
216
+ EDITED_FILE="$file"
217
+ echo "[$(date)] post-edit-spec: Detected recent modification: $file (${TIME_DIFF}s ago)" >> "$DEBUG_LOG" 2>/dev/null || true
218
+ SHOULD_UPDATE=true
219
+ break
220
+ fi
221
+ fi
222
+ done
223
+ fi
224
+
225
+ # If still no file detected, skip update (not a spec/tasks edit)
226
+ if [[ -z "$EDITED_FILE" ]]; then
227
+ echo "[$(date)] post-edit-spec: No spec/tasks modifications detected - skipping" >> "$DEBUG_LOG" 2>/dev/null || true
228
+ exit 0
229
+ fi
80
230
  fi
81
231
 
232
+ # ============================================================================
233
+ # TIER 1 FIX: Non-Blocking Background Update with COMPLETE ERROR ISOLATION
234
+ # ============================================================================
82
235
  # Update status line if needed
83
236
  if [[ "$SHOULD_UPDATE" == "true" ]]; then
84
- echo "[$(date)] post-edit-spec: Running update-status-line.sh" >> "$DEBUG_LOG" 2>/dev/null || true
237
+ echo "[$(date)] post-edit-spec: Running update-status-line.sh (background)" >> "$DEBUG_LOG" 2>/dev/null || true
85
238
 
86
- # Run status line update (capture errors for debugging)
87
- if "$PROJECT_ROOT/plugins/specweave/hooks/lib/update-status-line.sh" 2>&1 | tee -a "$DEBUG_LOG" >/dev/null; then
88
- echo "[$(date)] post-edit-spec: Status line updated successfully" >> "$DEBUG_LOG" 2>/dev/null || true
89
- else
90
- echo "[$(date)] post-edit-spec: Warning - status line update failed (non-blocking)" >> "$DEBUG_LOG" 2>/dev/null || true
91
- fi
239
+ # Record update time BEFORE spawning background process
240
+ # This ensures debouncing works even if update hasn't completed yet
241
+ echo "$(date +%s)" > "$LAST_UPDATE_FILE"
242
+
243
+ # Run status line update in background with COMPLETE error isolation
244
+ # This prevents Edit tool from waiting for status line computation
245
+ (
246
+ set +e # Disable error propagation
247
+
248
+ if "$PROJECT_ROOT/plugins/specweave/hooks/lib/update-status-line.sh" 2>&1 | tee -a "$DEBUG_LOG" >/dev/null; then
249
+ echo "[$(date)] post-edit-spec: Status line updated successfully" >> "$DEBUG_LOG" 2>/dev/null || true
250
+ # Reset circuit breaker on success
251
+ echo "0" > "$CIRCUIT_BREAKER_FILE" 2>/dev/null || true
252
+ else
253
+ echo "[$(date)] post-edit-spec: Warning - status line update failed (non-blocking)" >> "$DEBUG_LOG" 2>/dev/null || true
254
+ # Increment circuit breaker
255
+ CURRENT_FAILURES=$(cat "$CIRCUIT_BREAKER_FILE" 2>/dev/null || echo 0)
256
+ echo "$((CURRENT_FAILURES + 1))" > "$CIRCUIT_BREAKER_FILE" 2>/dev/null || true
257
+ fi
258
+ ) &
259
+
260
+ # Disown the background process so it's not killed when hook exits
261
+ disown 2>/dev/null || true
92
262
  fi
93
263
 
264
+ # Always exit 0 to prevent hook errors from crashing Claude Code
94
265
  exit 0