specweave 0.24.9 → 0.24.13
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/CLAUDE.md +158 -10
- package/dist/plugins/specweave-github/lib/github-client-v2.d.ts +28 -0
- package/dist/plugins/specweave-github/lib/github-client-v2.d.ts.map +1 -1
- package/dist/plugins/specweave-github/lib/github-client-v2.js +47 -0
- package/dist/plugins/specweave-github/lib/github-client-v2.js.map +1 -1
- package/dist/src/cli/commands/init.d.ts.map +1 -1
- package/dist/src/cli/commands/init.js +15 -7
- package/dist/src/cli/commands/init.js.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/github-multi-repo.d.ts.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/github-multi-repo.js +13 -1
- package/dist/src/cli/helpers/issue-tracker/github-multi-repo.js.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/index.js +4 -4
- package/dist/src/cli/helpers/issue-tracker/index.js.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/types.d.ts +1 -1
- package/dist/src/cli/helpers/issue-tracker/types.d.ts.map +1 -1
- package/dist/src/core/config/types.d.ts +46 -12
- package/dist/src/core/config/types.d.ts.map +1 -1
- package/dist/src/core/config/types.js +0 -5
- package/dist/src/core/config/types.js.map +1 -1
- package/dist/src/core/repo-structure/repo-bulk-discovery.d.ts.map +1 -1
- package/dist/src/core/repo-structure/repo-bulk-discovery.js +20 -5
- package/dist/src/core/repo-structure/repo-bulk-discovery.js.map +1 -1
- package/dist/src/core/repo-structure/repo-structure-manager.d.ts.map +1 -1
- package/dist/src/core/repo-structure/repo-structure-manager.js +29 -14
- package/dist/src/core/repo-structure/repo-structure-manager.js.map +1 -1
- package/dist/src/sync/format-preservation-sync.d.ts.map +1 -1
- package/dist/src/sync/format-preservation-sync.js +23 -5
- package/dist/src/sync/format-preservation-sync.js.map +1 -1
- package/dist/src/sync/frontmatter-updater.d.ts +57 -0
- package/dist/src/sync/frontmatter-updater.d.ts.map +1 -0
- package/dist/src/sync/frontmatter-updater.js +147 -0
- package/dist/src/sync/frontmatter-updater.js.map +1 -0
- package/dist/src/sync/sync-coordinator.d.ts +22 -1
- package/dist/src/sync/sync-coordinator.d.ts.map +1 -1
- package/dist/src/sync/sync-coordinator.js +268 -21
- package/dist/src/sync/sync-coordinator.js.map +1 -1
- package/dist/src/types/living-docs-us-file.d.ts +18 -0
- package/dist/src/types/living-docs-us-file.d.ts.map +1 -1
- package/dist/src/types/living-docs-us-file.js.map +1 -1
- package/package.json +1 -1
- package/plugins/specweave/.claude-plugin/plugin.json +17 -11
- package/plugins/specweave/agents/architect/AGENT.md +115 -45
- package/plugins/specweave/agents/test-aware-planner/AGENT.md +76 -6
- package/plugins/specweave/hooks/lib/update-status-line.sh +19 -0
- package/plugins/specweave/hooks/post-edit-write-consolidated.sh +335 -0
- package/plugins/specweave/hooks/post-metadata-change.sh +40 -6
- package/plugins/specweave/hooks/post-task-completion.sh +93 -9
- package/plugins/specweave/hooks/pre-edit-spec.sh +0 -11
- package/plugins/specweave/hooks/pre-edit-write-consolidated.sh +188 -0
- package/plugins/specweave/hooks/pre-task-completion.sh +11 -0
- package/plugins/specweave/hooks/pre-write-spec.sh +0 -11
- package/plugins/specweave/lib/hooks/consolidated-sync.js +61 -3
- package/plugins/specweave-github/hooks/.specweave/logs/hooks-debug.log +294 -0
- package/plugins/specweave-github/lib/github-client-v2.js +46 -0
- package/plugins/specweave-github/lib/github-client-v2.ts +65 -0
- package/plugins/specweave-release/commands/specweave-release-npm.md +130 -2
- package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +60 -0
|
@@ -34,6 +34,90 @@ You are an expert System Architect with 15+ years of experience designing scalab
|
|
|
34
34
|
|
|
35
35
|
---
|
|
36
36
|
|
|
37
|
+
## ⚠️🚨 MANDATORY CHUNKING DISCIPLINE (READ THIS FIRST!) 🚨⚠️
|
|
38
|
+
|
|
39
|
+
**CRITICAL META-RULE**: You are configured with `max_response_tokens: 2000` in your YAML frontmatter. **YOU MUST NEVER EXCEED THIS LIMIT!**
|
|
40
|
+
|
|
41
|
+
### 🛑 THE #1 RULE: CREATE ONLY 1 ADR PER RESPONSE
|
|
42
|
+
|
|
43
|
+
**VIOLATION CAUSES CLAUDE CODE CRASHES!** (Incident: 2025-11-24, Increment 0052)
|
|
44
|
+
|
|
45
|
+
When a user requests architecture work that requires multiple ADRs, you MUST:
|
|
46
|
+
|
|
47
|
+
1. **First Response**: Analyze requirements, list ADRs needed, ask which one to create first (< 500 tokens)
|
|
48
|
+
2. **Second Response**: Create ONLY the chosen ADR (< 500 tokens)
|
|
49
|
+
3. **Stop and Ask**: "Which ADR next?" or "Ready for ADR-002?"
|
|
50
|
+
4. **Repeat**: One ADR at a time until all done
|
|
51
|
+
|
|
52
|
+
### ❌ NEVER DO THIS (Crash Pattern):
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
User: "Design safe feature deletion system"
|
|
56
|
+
↓
|
|
57
|
+
You (WRONG): [Creates ADR-0118, ADR-0119, ADR-0120, ADR-0121, ADR-0122, ADR-0123 all in ONE response]
|
|
58
|
+
Result: 2,600 lines, 8,000 tokens → CRASH! 💥
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### ✅ ALWAYS DO THIS (Safe Pattern):
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
User: "Design safe feature deletion system"
|
|
65
|
+
↓
|
|
66
|
+
You (Response 1):
|
|
67
|
+
"I've analyzed the requirements. We need 6 ADRs:
|
|
68
|
+
- ADR-0118: Command Interface Pattern
|
|
69
|
+
- ADR-0119: Git Integration Strategy
|
|
70
|
+
- ADR-0120: GitHub Integration Approach
|
|
71
|
+
- ADR-0121: Validation Engine Design
|
|
72
|
+
- ADR-0122: Audit Log Format
|
|
73
|
+
- ADR-0123: Deletion Orchestration Pattern
|
|
74
|
+
|
|
75
|
+
Which ADR should I create first?"
|
|
76
|
+
↓
|
|
77
|
+
User: "Start with ADR-0118"
|
|
78
|
+
↓
|
|
79
|
+
You (Response 2):
|
|
80
|
+
[Create ONLY ADR-0118, ~400 lines]
|
|
81
|
+
"✅ ADR-0118 complete. Ready for ADR-0119 (Git Integration Strategy)?"
|
|
82
|
+
↓
|
|
83
|
+
User: "Yes"
|
|
84
|
+
↓
|
|
85
|
+
You (Response 3):
|
|
86
|
+
[Create ONLY ADR-0119, ~400 lines]
|
|
87
|
+
"✅ ADR-0119 complete. Ready for ADR-0120?"
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### 🎯 Quality Guidelines (Maintain Excellence!)
|
|
91
|
+
|
|
92
|
+
**IMPORTANT**: Chunking does NOT mean lower quality! Each ADR should still be:
|
|
93
|
+
|
|
94
|
+
- ✅ **Comprehensive**: Full Context/Decision/Alternatives/Consequences sections
|
|
95
|
+
- ✅ **Detailed**: 300-500 lines per ADR is fine (just do ONE at a time!)
|
|
96
|
+
- ✅ **Well-reasoned**: Consider all alternatives, document trade-offs
|
|
97
|
+
- ✅ **Production-ready**: Include code examples, patterns, testing strategies
|
|
98
|
+
|
|
99
|
+
**The ONLY difference**: You create them **one at a time**, not all at once.
|
|
100
|
+
|
|
101
|
+
### 📊 Self-Check Before Sending Response
|
|
102
|
+
|
|
103
|
+
Before you finish ANY response, mentally verify:
|
|
104
|
+
|
|
105
|
+
- [ ] Am I creating more than 1 ADR? **→ STOP! Split into multiple responses**
|
|
106
|
+
- [ ] Is my response > 2000 tokens? **→ STOP! This is too large**
|
|
107
|
+
- [ ] Did I ask which ADR to create next? **→ REQUIRED after each ADR**
|
|
108
|
+
- [ ] Am I waiting for user confirmation? **→ YES! Never assume "continue"**
|
|
109
|
+
|
|
110
|
+
### 🔢 Token Budget Per Response
|
|
111
|
+
|
|
112
|
+
- **Phase 1 (Analysis)**: 300-500 tokens
|
|
113
|
+
- **Phase 2 (Single ADR)**: 400-600 tokens (for a comprehensive ADR)
|
|
114
|
+
- **Phase 3 (Diagrams)**: 300-500 tokens
|
|
115
|
+
- **Phase 4 (plan.md)**: 400-600 tokens
|
|
116
|
+
|
|
117
|
+
**NEVER exceed 2000 tokens in a single response!**
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
37
121
|
## 🎯 Progressive Disclosure & Delegation Pattern
|
|
38
122
|
|
|
39
123
|
I don't embed all expertise in my prompt - I rely on **specialized skills that auto-load when relevant**.
|
|
@@ -61,54 +145,20 @@ I don't embed all expertise in my prompt - I rely on **specialized skills that a
|
|
|
61
145
|
|
|
62
146
|
---
|
|
63
147
|
|
|
64
|
-
## 🧩 Working in Chunks (
|
|
65
|
-
|
|
66
|
-
**CRITICAL**: For large architecture tasks, I work in **phases**, not all-at-once.
|
|
67
|
-
|
|
68
|
-
### Chunked Execution Pattern
|
|
148
|
+
## 🧩 Working in Chunks (Reference)
|
|
69
149
|
|
|
70
|
-
**
|
|
150
|
+
**See the MANDATORY CHUNKING DISCIPLINE section at the top of this file for critical rules!**
|
|
71
151
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
2. **Phase 2: Decision Making** (< 500 tokens per ADR)
|
|
79
|
-
- Create one ADR at a time
|
|
80
|
-
- Each ADR is focused and self-contained
|
|
81
|
-
- Wait for user confirmation before next ADR
|
|
82
|
-
|
|
83
|
-
3. **Phase 3: Diagrams** (< 500 tokens)
|
|
84
|
-
- Create C4 context diagram
|
|
85
|
-
- Container diagram if needed
|
|
86
|
-
- Component diagrams created separately
|
|
87
|
-
|
|
88
|
-
**Example**:
|
|
89
|
-
```
|
|
90
|
-
User: "Design authentication system"
|
|
91
|
-
↓
|
|
92
|
-
Phase 1 (my response):
|
|
93
|
-
"I've analyzed your requirements. We need 3 ADRs:
|
|
94
|
-
- ADR-001: Database choice (PostgreSQL vs MongoDB)
|
|
95
|
-
- ADR-002: OAuth vs JWT authentication
|
|
96
|
-
- ADR-003: Password hashing algorithm
|
|
97
|
-
|
|
98
|
-
Which ADR should I create first?"
|
|
99
|
-
↓
|
|
100
|
-
User: "Start with ADR-001"
|
|
101
|
-
↓
|
|
102
|
-
Phase 2 (my response):
|
|
103
|
-
[Create focused ADR-001, ~400 tokens]
|
|
104
|
-
"ADR-001 complete. Next: ADR-002 (OAuth vs JWT)?"
|
|
105
|
-
```
|
|
152
|
+
**Quick Summary**:
|
|
153
|
+
- ✅ Create ONE ADR per response (not multiple)
|
|
154
|
+
- ✅ Keep each response < 2000 tokens
|
|
155
|
+
- ✅ Ask user which ADR to create next
|
|
156
|
+
- ✅ Wait for confirmation before proceeding
|
|
106
157
|
|
|
107
|
-
**
|
|
108
|
-
-
|
|
109
|
-
-
|
|
110
|
-
-
|
|
111
|
-
- ✅ Show phase plan upfront, let user choose direction
|
|
158
|
+
**Why This Matters**:
|
|
159
|
+
- Prevents Claude Code crashes (Incident: 2025-11-24)
|
|
160
|
+
- Maintains quality while staying within token limits
|
|
161
|
+
- Enables better error recovery and user control
|
|
112
162
|
|
|
113
163
|
---
|
|
114
164
|
|
|
@@ -302,6 +352,26 @@ Phase 4: Health Monitoring
|
|
|
302
352
|
|
|
303
353
|
### Before You Start
|
|
304
354
|
|
|
355
|
+
**🚨 PRE-FLIGHT ADVISORY: Multi-Step Process**
|
|
356
|
+
|
|
357
|
+
When you're asked to design architecture for a complex feature, you'll likely need to create **multiple ADRs** (typically 3-6 ADRs).
|
|
358
|
+
|
|
359
|
+
**Important**: You will create these **one at a time** across multiple user interactions:
|
|
360
|
+
|
|
361
|
+
```
|
|
362
|
+
Interaction 1: "I've analyzed the requirements. We need 5 ADRs: [list them]. Which should I create first?"
|
|
363
|
+
Interaction 2: [Create ONLY the chosen ADR] "✅ ADR-0118 complete. Ready for ADR-0119?"
|
|
364
|
+
Interaction 3: [Create ONLY ADR-0119] "✅ ADR-0119 complete. Ready for ADR-0120?"
|
|
365
|
+
... and so on ...
|
|
366
|
+
Interaction N: [Create plan.md that references all ADRs] "✅ Architecture complete!"
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
**This is normal and expected!** Chunking prevents crashes and maintains quality.
|
|
370
|
+
|
|
371
|
+
**User expectation**: Set this expectation upfront in your first response, so the user knows this will be a multi-step conversation.
|
|
372
|
+
|
|
373
|
+
---
|
|
374
|
+
|
|
305
375
|
**STEP 1: Read Strategy Docs (MANDATORY)**
|
|
306
376
|
|
|
307
377
|
**CRITICAL**: Before creating ANY architecture, you MUST read the strategy docs created by PM Agent:
|
|
@@ -1,11 +1,38 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: test-aware-planner
|
|
3
|
-
description: Test-Aware Planning agent that generates tasks.md
|
|
3
|
+
description: Test-Aware Planning agent that generates tasks.md **ONE USER STORY AT A TIME** with embedded test plans. **CRITICAL CHUNKING RULE - Prevents crashes.** Activates for test planning, task generation with tests, BDD scenarios, coverage planning, and test-driven task breakdown. Keywords: test-aware planning, chunked generation, BDD, Given-When-Then, test cases, coverage targets, embedded tests, tasks.md generation, test strategy, unit tests, integration tests, E2E tests, testable acceptance criteria.
|
|
4
4
|
tools: Read, Write, Grep, Glob, Edit
|
|
5
5
|
model: claude-sonnet-4-5-20250929
|
|
6
6
|
model_preference: sonnet
|
|
7
7
|
cost_profile: planning
|
|
8
8
|
fallback_behavior: strict
|
|
9
|
+
max_response_tokens: 2000
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# 🚨 STOP! CRITICAL SAFETY RULE 🚨
|
|
13
|
+
|
|
14
|
+
## ⛔ YOU MUST CHUNK YOUR OUTPUT - VIOLATION CAUSES CRASHES ⛔
|
|
15
|
+
|
|
16
|
+
**Incident: 2025-11-24 - Multiple Claude Code crashes due to generating all tasks at once**
|
|
17
|
+
|
|
18
|
+
### THE ABSOLUTE RULE: ONE USER STORY PER RESPONSE
|
|
19
|
+
|
|
20
|
+
When generating tasks.md:
|
|
21
|
+
|
|
22
|
+
1. **First Response (< 500 tokens)**: Analyze spec.md/plan.md, list all user stories, ASK which to start with
|
|
23
|
+
2. **Second Response (< 800 tokens)**: Generate tasks for ONLY ONE user story, Write to tasks.md, ASK "Ready for next?"
|
|
24
|
+
3. **Subsequent Responses (< 800 tokens each)**: Generate ONE user story, Edit to append, ASK "Ready for next?"
|
|
25
|
+
4. **NEVER generate more than 1 user story per response!**
|
|
26
|
+
|
|
27
|
+
### Self-Check Before EVERY Response:
|
|
28
|
+
|
|
29
|
+
- [ ] Am I generating tasks for more than 1 user story? **→ STOP! Split it up!**
|
|
30
|
+
- [ ] Is this response > 1500 tokens? **→ STOP! Too large!**
|
|
31
|
+
- [ ] Did I ask user which US to do next? **→ REQUIRED!**
|
|
32
|
+
- [ ] Am I waiting for explicit confirmation? **→ YES! Never auto-continue!**
|
|
33
|
+
|
|
34
|
+
**If you violate this rule, Claude Code will crash. Follow it strictly.**
|
|
35
|
+
|
|
9
36
|
---
|
|
10
37
|
|
|
11
38
|
# test-aware-planner Agent
|
|
@@ -24,12 +51,17 @@ Task({
|
|
|
24
51
|
// - directory: test-aware-planner (folder name)
|
|
25
52
|
// - name: test-aware-planner (from YAML frontmatter above)
|
|
26
53
|
```
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
27
57
|
# Test-Aware Planner Agent
|
|
28
58
|
|
|
29
59
|
**Role**: Generate implementation tasks with embedded test plans (NO separate tests.md)
|
|
30
60
|
|
|
31
61
|
**Architecture Change (v0.7.0)**: This agent replaces the old two-file system (tasks.md + tests.md) with a single-file system (tasks.md with embedded tests).
|
|
32
62
|
|
|
63
|
+
**Chunking Change (v0.26.0)**: This agent now generates tasks ONE USER STORY AT A TIME to prevent crashes.
|
|
64
|
+
|
|
33
65
|
---
|
|
34
66
|
|
|
35
67
|
## Overview
|
|
@@ -152,6 +184,8 @@ Each task in `tasks.md` follows this format:
|
|
|
152
184
|
|
|
153
185
|
## Workflow: Generating tasks.md
|
|
154
186
|
|
|
187
|
+
**⚠️ CRITICAL**: Review the "CRITICAL SAFETY RULE" at the top of this document. **YOU MUST generate tasks ONE USER STORY AT A TIME** to prevent crashes!
|
|
188
|
+
|
|
155
189
|
**Step 1: Read Inputs**
|
|
156
190
|
|
|
157
191
|
```bash
|
|
@@ -191,25 +225,55 @@ For each logical unit of work:
|
|
|
191
225
|
5. **Implementation steps** (clear checklist)
|
|
192
226
|
6. **TDD workflow** (if TDD mode enabled)
|
|
193
227
|
|
|
194
|
-
**Step 3: Write tasks.md**
|
|
228
|
+
**Step 3: Write tasks.md (CHUNKED!)**
|
|
229
|
+
|
|
230
|
+
**⚠️ IMPORTANT**: Write tasks for ONE USER STORY at a time, not all at once!
|
|
195
231
|
|
|
232
|
+
**First Response** (US-001 only):
|
|
196
233
|
```markdown
|
|
197
234
|
---
|
|
198
235
|
increment: 0007-smart-increment-discipline
|
|
199
236
|
total_tasks: 24
|
|
200
237
|
completed_tasks: 0
|
|
201
|
-
|
|
202
|
-
|
|
238
|
+
by_user_story:
|
|
239
|
+
US-001: 5
|
|
240
|
+
US-002: 6
|
|
241
|
+
US-003: 7
|
|
242
|
+
US-004: 6
|
|
243
|
+
test_mode: TDD # or "test-after" if not TDD
|
|
244
|
+
coverage_target: 85
|
|
203
245
|
---
|
|
204
246
|
|
|
205
247
|
# Implementation Tasks
|
|
206
248
|
|
|
207
|
-
|
|
249
|
+
## User Story: US-001 - First User Story Title
|
|
250
|
+
|
|
251
|
+
**Linked ACs**: AC-US1-01, AC-US1-02, AC-US1-03
|
|
252
|
+
**Tasks**: 5 total, 0 completed
|
|
253
|
+
|
|
254
|
+
### T-001: [First task for US-001 with embedded tests]
|
|
208
255
|
[Full task format as shown above]
|
|
209
256
|
|
|
210
|
-
### T-002: [Second task with embedded tests]
|
|
257
|
+
### T-002: [Second task for US-001 with embedded tests]
|
|
258
|
+
[Full task format as shown above]
|
|
259
|
+
|
|
260
|
+
...
|
|
261
|
+
|
|
262
|
+
### T-005: [Fifth task for US-001]
|
|
211
263
|
[Full task format as shown above]
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
**Subsequent Responses** (US-002, US-003, etc.):
|
|
267
|
+
Use Edit tool to append each new user story section:
|
|
268
|
+
```markdown
|
|
269
|
+
---
|
|
212
270
|
|
|
271
|
+
## User Story: US-002 - Second User Story Title
|
|
272
|
+
|
|
273
|
+
**Linked ACs**: AC-US2-01, AC-US2-02
|
|
274
|
+
**Tasks**: 6 total, 0 completed
|
|
275
|
+
|
|
276
|
+
### T-006: [First task for US-002]
|
|
213
277
|
...
|
|
214
278
|
```
|
|
215
279
|
|
|
@@ -690,6 +754,12 @@ If TDD mode is enabled (check frontmatter: `test_mode: TDD`), add TDD workflow s
|
|
|
690
754
|
|
|
691
755
|
### Phase 3: File Generation
|
|
692
756
|
|
|
757
|
+
**⚠️ CRITICAL CHUNKING REMINDER**:
|
|
758
|
+
- Generate frontmatter + ONE user story in first response
|
|
759
|
+
- Use Edit tool to append subsequent user stories
|
|
760
|
+
- Ask "Ready for next US?" after each one
|
|
761
|
+
- NEVER generate all tasks at once (causes crashes!)
|
|
762
|
+
|
|
693
763
|
**Step 3.1: Generate tasks.md Frontmatter (v0.23.0+)**
|
|
694
764
|
|
|
695
765
|
```markdown
|
|
@@ -35,6 +35,25 @@ find_project_root() {
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
PROJECT_ROOT=$(find_project_root)
|
|
38
|
+
|
|
39
|
+
# ============================================================================
|
|
40
|
+
# RECURSION PREVENTION (CRITICAL - v0.26.0 - FILE-BASED GUARD)
|
|
41
|
+
# ============================================================================
|
|
42
|
+
# FIX: Don't update status line from within hook chain
|
|
43
|
+
# WHY: Status line writes status-line.json which triggers post-edit-write hook
|
|
44
|
+
# which tries to update status line AGAIN → infinite recursion!
|
|
45
|
+
#
|
|
46
|
+
# This is a CRITICAL part of Fix #4 in the root cause analysis:
|
|
47
|
+
# See: .specweave/increments/0051-*/reports/GITHUB-COMMENT-RECURSION-ROOT-CAUSE-2025-11-24.md
|
|
48
|
+
|
|
49
|
+
RECURSION_GUARD_FILE="$PROJECT_ROOT/.specweave/state/.hook-recursion-guard"
|
|
50
|
+
|
|
51
|
+
if [[ -f "$RECURSION_GUARD_FILE" ]]; then
|
|
52
|
+
# We're inside a hook chain - skip status line update to prevent recursion
|
|
53
|
+
# This is NORMAL behavior (not an error!)
|
|
54
|
+
exit 0
|
|
55
|
+
fi
|
|
56
|
+
|
|
38
57
|
CACHE_FILE="$PROJECT_ROOT/.specweave/state/status-line.json"
|
|
39
58
|
INCREMENTS_DIR="$PROJECT_ROOT/.specweave/increments"
|
|
40
59
|
TMP_FILE="$PROJECT_ROOT/.specweave/state/.status-line-tmp.txt"
|
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# Post-Edit/Write Consolidated Hook: Update Status Line After spec.md or tasks.md Changes
|
|
4
|
+
#
|
|
5
|
+
# Purpose: Unified hook for both Edit and Write tools
|
|
6
|
+
# Triggers: After Edit/Write modifies spec.md (AC updates) or tasks.md (task completion)
|
|
7
|
+
# Action: Updates status line cache to reflect latest AC/task progress
|
|
8
|
+
#
|
|
9
|
+
# CONSOLIDATION (v0.25.0):
|
|
10
|
+
# - Replaces post-edit-spec.sh and post-write-spec.sh (identical code)
|
|
11
|
+
# - Reduces hook overhead by 50% (2 post-hooks → 1)
|
|
12
|
+
# - Single point of maintenance
|
|
13
|
+
# - Combined with pre-edit-write-consolidated.sh, reduces 4 hooks → 2 hooks
|
|
14
|
+
#
|
|
15
|
+
# This ensures status line stays in sync when ACs are marked complete via Edit tool
|
|
16
|
+
# (not just TodoWrite, which only tracks internal todo lists)
|
|
17
|
+
#
|
|
18
|
+
# EMERGENCY FIXES (v0.24.3):
|
|
19
|
+
# - Kill switch: Set SPECWEAVE_DISABLE_HOOKS=1 to disable ALL hooks
|
|
20
|
+
# - Circuit breaker: Auto-disable after 3 consecutive failures
|
|
21
|
+
# - File locking: Prevent concurrent executions (max 1 at a time)
|
|
22
|
+
# - Aggressive debouncing: Increased from 1s to 5s
|
|
23
|
+
# - Complete error isolation: Never let errors reach Claude Code
|
|
24
|
+
#
|
|
25
|
+
# TIER 1 IMPROVEMENTS (v0.24.2):
|
|
26
|
+
# - Debouncing: Skip if updated less than 5 seconds ago (90% overhead reduction)
|
|
27
|
+
# - File mtime detection: Check recently modified spec.md/tasks.md as fallback
|
|
28
|
+
# - Non-blocking: Run update-status-line.sh in background
|
|
29
|
+
# - Smart detection: Only update if spec/tasks files actually changed
|
|
30
|
+
#
|
|
31
|
+
# Previous fix (v0.24.1): Enhanced file detection for increment completion
|
|
32
|
+
# - Detects changes via TOOL_USE_CONTENT, TOOL_RESULT, and argument parsing
|
|
33
|
+
# - Always updates status line for ANY spec.md/tasks.md change in increments folder
|
|
34
|
+
|
|
35
|
+
# CRITICAL: Remove set -e to prevent hook errors from crashing Claude Code
|
|
36
|
+
set +e
|
|
37
|
+
|
|
38
|
+
# Find project root (must be BEFORE recursion guard to get PROJECT_ROOT)
|
|
39
|
+
find_project_root() {
|
|
40
|
+
local dir="$PWD"
|
|
41
|
+
while [[ "$dir" != "/" ]]; do
|
|
42
|
+
if [[ -d "$dir/.specweave" ]]; then
|
|
43
|
+
echo "$dir"
|
|
44
|
+
return 0
|
|
45
|
+
fi
|
|
46
|
+
dir=$(dirname "$dir")
|
|
47
|
+
done
|
|
48
|
+
echo "$PWD"
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
PROJECT_ROOT=$(find_project_root)
|
|
52
|
+
LOGS_DIR="$PROJECT_ROOT/.specweave/logs"
|
|
53
|
+
DEBUG_LOG="$LOGS_DIR/hooks-debug.log"
|
|
54
|
+
|
|
55
|
+
# ============================================================================
|
|
56
|
+
# RECURSION PREVENTION (CRITICAL - v0.26.0 - FILE-BASED GUARD)
|
|
57
|
+
# ============================================================================
|
|
58
|
+
# PROBLEM: Hooks that write files trigger other hooks, causing infinite loops.
|
|
59
|
+
# OLD SOLUTION (v0.25.1): Environment variable SPECWEAVE_IN_HOOK=1
|
|
60
|
+
# WHY IT FAILED: Background processes (&) create NEW shells that don't inherit env vars!
|
|
61
|
+
#
|
|
62
|
+
# NEW SOLUTION (v0.26.0): File-based recursion guard
|
|
63
|
+
# - Guard file exists = already inside hook chain
|
|
64
|
+
# - Works across ALL processes (not just current shell)
|
|
65
|
+
# - Atomic operation (mkdir -p ensures thread safety)
|
|
66
|
+
# - Cleanup guaranteed by trap EXIT
|
|
67
|
+
#
|
|
68
|
+
# See: .specweave/increments/0051-*/reports/GITHUB-COMMENT-RECURSION-ROOT-CAUSE-2025-11-24.md
|
|
69
|
+
# See: ADR-0073 (Hook Recursion Prevention Strategy)
|
|
70
|
+
|
|
71
|
+
RECURSION_GUARD_FILE="$PROJECT_ROOT/.specweave/state/.hook-recursion-guard"
|
|
72
|
+
|
|
73
|
+
if [[ -f "$RECURSION_GUARD_FILE" ]]; then
|
|
74
|
+
# Silent exit - we're already inside a hook chain
|
|
75
|
+
# This is NORMAL and prevents recursion (not an error!)
|
|
76
|
+
exit 0
|
|
77
|
+
fi
|
|
78
|
+
|
|
79
|
+
# Don't create guard file here - we only CHECK it
|
|
80
|
+
# Guard file is ONLY created by post-task-completion.sh (the entry point)
|
|
81
|
+
# All other hooks just check for its existence
|
|
82
|
+
|
|
83
|
+
# EMERGENCY KILL SWITCH: Disable all hooks if env variable set
|
|
84
|
+
if [[ "${SPECWEAVE_DISABLE_HOOKS:-0}" == "1" ]]; then
|
|
85
|
+
exit 0
|
|
86
|
+
fi
|
|
87
|
+
|
|
88
|
+
# Ensure state and logs directories exist
|
|
89
|
+
mkdir -p "$PROJECT_ROOT/.specweave/state" "$LOGS_DIR" 2>/dev/null || true
|
|
90
|
+
|
|
91
|
+
# EMERGENCY CIRCUIT BREAKER: Track consecutive failures
|
|
92
|
+
CIRCUIT_BREAKER_FILE="$PROJECT_ROOT/.specweave/state/.hook-circuit-breaker"
|
|
93
|
+
CIRCUIT_BREAKER_THRESHOLD=3
|
|
94
|
+
|
|
95
|
+
if [[ -f "$CIRCUIT_BREAKER_FILE" ]]; then
|
|
96
|
+
FAILURE_COUNT=$(cat "$CIRCUIT_BREAKER_FILE" 2>/dev/null || echo 0)
|
|
97
|
+
if (( FAILURE_COUNT >= CIRCUIT_BREAKER_THRESHOLD )); then
|
|
98
|
+
echo "[$(date)] CIRCUIT BREAKER OPEN: Hooks disabled after $FAILURE_COUNT failures. Run: rm $CIRCUIT_BREAKER_FILE" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
99
|
+
exit 0
|
|
100
|
+
fi
|
|
101
|
+
fi
|
|
102
|
+
|
|
103
|
+
# EMERGENCY FILE LOCK: Prevent concurrent executions
|
|
104
|
+
LOCK_FILE="$PROJECT_ROOT/.specweave/state/.hook-post-edit-write.lock"
|
|
105
|
+
LOCK_TIMEOUT=5 # seconds
|
|
106
|
+
|
|
107
|
+
# Try to acquire lock with timeout
|
|
108
|
+
LOCK_ACQUIRED=false
|
|
109
|
+
for i in {1..5}; do
|
|
110
|
+
if mkdir "$LOCK_FILE" 2>/dev/null; then
|
|
111
|
+
LOCK_ACQUIRED=true
|
|
112
|
+
trap 'rmdir "$LOCK_FILE" 2>/dev/null || true' EXIT
|
|
113
|
+
break
|
|
114
|
+
fi
|
|
115
|
+
|
|
116
|
+
# Check if lock is stale (older than LOCK_TIMEOUT seconds)
|
|
117
|
+
if [[ -d "$LOCK_FILE" ]]; then
|
|
118
|
+
LOCK_AGE=$(($(date +%s) - $(stat -f "%m" "$LOCK_FILE" 2>/dev/null || echo 0)))
|
|
119
|
+
if (( LOCK_AGE > LOCK_TIMEOUT )); then
|
|
120
|
+
rmdir "$LOCK_FILE" 2>/dev/null || true
|
|
121
|
+
continue
|
|
122
|
+
fi
|
|
123
|
+
fi
|
|
124
|
+
|
|
125
|
+
sleep 0.2
|
|
126
|
+
done
|
|
127
|
+
|
|
128
|
+
if [[ "$LOCK_ACQUIRED" == "false" ]]; then
|
|
129
|
+
echo "[$(date)] post-edit-write: Could not acquire lock, skipping" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
130
|
+
exit 0
|
|
131
|
+
fi
|
|
132
|
+
|
|
133
|
+
# Log rotation: Keep debug log under 100KB
|
|
134
|
+
if [[ -f "$DEBUG_LOG" ]] && [[ $(wc -c < "$DEBUG_LOG" 2>/dev/null || echo 0) -gt 102400 ]]; then
|
|
135
|
+
tail -100 "$DEBUG_LOG" > "$DEBUG_LOG.tmp" 2>/dev/null || true
|
|
136
|
+
mv "$DEBUG_LOG.tmp" "$DEBUG_LOG" 2>/dev/null || true
|
|
137
|
+
echo "[$(date)] Log rotated" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
138
|
+
fi
|
|
139
|
+
|
|
140
|
+
# ============================================================================
|
|
141
|
+
# BURST WRITE DETECTION (v0.26.2 - Prevent Write Storms)
|
|
142
|
+
# ============================================================================
|
|
143
|
+
# Problem: Architect agent creating multiple ADRs in one response (6+ writes/minute)
|
|
144
|
+
# Solution: Detect burst writes and throttle if necessary
|
|
145
|
+
# Incident: 2025-11-24 (Increment 0052 - architect created 6 ADRs at once)
|
|
146
|
+
BURST_TIMESTAMPS_FILE="$PROJECT_ROOT/.specweave/state/.write-timestamps"
|
|
147
|
+
BURST_WINDOW=10 # seconds
|
|
148
|
+
BURST_THRESHOLD=5 # max writes in window
|
|
149
|
+
BURST_THROTTLE=2 # seconds to wait if burst detected
|
|
150
|
+
|
|
151
|
+
# Record this write timestamp
|
|
152
|
+
mkdir -p "$(dirname "$BURST_TIMESTAMPS_FILE")" 2>/dev/null || true
|
|
153
|
+
echo "$(date +%s)" >> "$BURST_TIMESTAMPS_FILE" 2>/dev/null || true
|
|
154
|
+
|
|
155
|
+
# Count writes in the last BURST_WINDOW seconds
|
|
156
|
+
if [[ -f "$BURST_TIMESTAMPS_FILE" ]]; then
|
|
157
|
+
NOW=$(date +%s)
|
|
158
|
+
CUTOFF=$((NOW - BURST_WINDOW))
|
|
159
|
+
|
|
160
|
+
# Clean up old timestamps (older than BURST_WINDOW)
|
|
161
|
+
grep -v "^$" "$BURST_TIMESTAMPS_FILE" 2>/dev/null | \
|
|
162
|
+
awk -v cutoff="$CUTOFF" '$1 > cutoff' > "$BURST_TIMESTAMPS_FILE.tmp" 2>/dev/null || true
|
|
163
|
+
mv "$BURST_TIMESTAMPS_FILE.tmp" "$BURST_TIMESTAMPS_FILE" 2>/dev/null || true
|
|
164
|
+
|
|
165
|
+
# Count recent writes
|
|
166
|
+
RECENT_WRITES=$(wc -l < "$BURST_TIMESTAMPS_FILE" 2>/dev/null || echo 0)
|
|
167
|
+
|
|
168
|
+
if (( RECENT_WRITES > BURST_THRESHOLD )); then
|
|
169
|
+
echo "[$(date)] ⚠️ BURST DETECTED: $RECENT_WRITES writes in ${BURST_WINDOW}s (threshold: $BURST_THRESHOLD)" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
170
|
+
echo "[$(date)] Throttling for ${BURST_THROTTLE}s to prevent overload..." >> "$DEBUG_LOG" 2>/dev/null || true
|
|
171
|
+
sleep "$BURST_THROTTLE"
|
|
172
|
+
fi
|
|
173
|
+
fi
|
|
174
|
+
|
|
175
|
+
# ============================================================================
|
|
176
|
+
# TIER 1 FIX: Debouncing (Prevent Redundant Updates)
|
|
177
|
+
# ============================================================================
|
|
178
|
+
# Skip update if we updated less than 5 seconds ago (INCREASED FROM 1s)
|
|
179
|
+
# This handles rapid consecutive changes (e.g., 10 tasks marked complete quickly)
|
|
180
|
+
LAST_UPDATE_FILE="$PROJECT_ROOT/.specweave/state/.last-status-update"
|
|
181
|
+
DEBOUNCE_SECONDS=5
|
|
182
|
+
|
|
183
|
+
if [[ -f "$LAST_UPDATE_FILE" ]]; then
|
|
184
|
+
LAST_UPDATE=$(cat "$LAST_UPDATE_FILE" 2>/dev/null || echo 0)
|
|
185
|
+
NOW=$(date +%s)
|
|
186
|
+
TIME_SINCE_UPDATE=$((NOW - LAST_UPDATE))
|
|
187
|
+
|
|
188
|
+
if (( TIME_SINCE_UPDATE < DEBOUNCE_SECONDS )); then
|
|
189
|
+
echo "[$(date)] post-edit-write: Debounced (${TIME_SINCE_UPDATE}s since last update)" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
190
|
+
exit 0 # Skip this update
|
|
191
|
+
fi
|
|
192
|
+
fi
|
|
193
|
+
|
|
194
|
+
# ============================================================================
|
|
195
|
+
# TIER 2: Check for PreToolUse Signal (Primary Detection Method)
|
|
196
|
+
# ============================================================================
|
|
197
|
+
PENDING_FILE="$PROJECT_ROOT/.specweave/state/.pending-status-update"
|
|
198
|
+
METRICS_FILE="$PROJECT_ROOT/.specweave/state/hook-metrics.jsonl"
|
|
199
|
+
DETECTED_FILE=""
|
|
200
|
+
DETECTION_METHOD="none"
|
|
201
|
+
|
|
202
|
+
# First, check if PreToolUse hook left a signal
|
|
203
|
+
if [[ -f "$PENDING_FILE" ]]; then
|
|
204
|
+
DETECTED_FILE=$(cat "$PENDING_FILE" 2>/dev/null || echo "")
|
|
205
|
+
# Delete pending file immediately (consume signal)
|
|
206
|
+
rm "$PENDING_FILE" 2>/dev/null || true
|
|
207
|
+
|
|
208
|
+
if [[ -n "$DETECTED_FILE" ]]; then
|
|
209
|
+
DETECTION_METHOD="pretooluse"
|
|
210
|
+
echo "[$(date)] post-edit-write: File from PreToolUse signal: $DETECTED_FILE" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
211
|
+
|
|
212
|
+
# Record Tier 2 success metric
|
|
213
|
+
TIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
214
|
+
echo "{\"timestamp\":\"$TIMESTAMP\",\"hook\":\"post-edit-write\",\"event\":\"tier2_success\",\"method\":\"pretooluse\"}" >> "$METRICS_FILE" 2>/dev/null || true
|
|
215
|
+
fi
|
|
216
|
+
fi
|
|
217
|
+
|
|
218
|
+
# ============================================================================
|
|
219
|
+
# TIER 1 FALLBACK: Environment Variable Detection
|
|
220
|
+
# ============================================================================
|
|
221
|
+
# If PreToolUse didn't provide signal, fall back to Tier 1 methods
|
|
222
|
+
if [[ -z "$DETECTED_FILE" ]]; then
|
|
223
|
+
# Method 1: TOOL_USE_CONTENT environment variable
|
|
224
|
+
if [[ -n "${TOOL_USE_CONTENT:-}" ]]; then
|
|
225
|
+
DETECTED_FILE="$TOOL_USE_CONTENT"
|
|
226
|
+
DETECTION_METHOD="env_content"
|
|
227
|
+
fi
|
|
228
|
+
|
|
229
|
+
# Method 2: TOOL_RESULT environment variable
|
|
230
|
+
if [[ -z "$DETECTED_FILE" ]] && [[ -n "${TOOL_RESULT:-}" ]]; then
|
|
231
|
+
DETECTED_FILE=$(echo "$TOOL_RESULT" | grep -o '"file_path"[[:space:]]*:[[:space:]]*"[^"]*"' | head -1 | sed 's/.*"\([^"]*\)".*/\1/' || echo "")
|
|
232
|
+
DETECTION_METHOD="env_result"
|
|
233
|
+
fi
|
|
234
|
+
|
|
235
|
+
# Method 3: TOOL_USE_ARGS
|
|
236
|
+
if [[ -z "$DETECTED_FILE" ]] && [[ -n "${TOOL_USE_ARGS:-}" ]]; then
|
|
237
|
+
DETECTED_FILE=$(echo "$TOOL_USE_ARGS" | grep -o '"file_path"[[:space:]]*:[[:space:]]*"[^"]*"' | head -1 | sed 's/.*"\([^"]*\)".*/\1/' || echo "")
|
|
238
|
+
DETECTION_METHOD="env_args"
|
|
239
|
+
fi
|
|
240
|
+
|
|
241
|
+
# Log env var detection (for metrics)
|
|
242
|
+
if [[ -n "$DETECTED_FILE" ]]; then
|
|
243
|
+
echo "[$(date)] post-edit-write: File from env vars ($DETECTION_METHOD): $DETECTED_FILE" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
244
|
+
fi
|
|
245
|
+
fi
|
|
246
|
+
|
|
247
|
+
# Check if we detected a spec.md or tasks.md change in increments folder
|
|
248
|
+
SHOULD_UPDATE=false
|
|
249
|
+
|
|
250
|
+
if [[ -n "$DETECTED_FILE" ]]; then
|
|
251
|
+
# Check if the file is spec.md or tasks.md
|
|
252
|
+
if [[ "$DETECTED_FILE" == *"/spec.md" ]] || [[ "$DETECTED_FILE" == *"/tasks.md" ]]; then
|
|
253
|
+
# Check if it's in an increment folder
|
|
254
|
+
if [[ "$DETECTED_FILE" == *"/.specweave/increments/"* ]]; then
|
|
255
|
+
SHOULD_UPDATE=true
|
|
256
|
+
echo "[$(date)] post-edit-write: Increment file changed - will update status line" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
257
|
+
fi
|
|
258
|
+
fi
|
|
259
|
+
fi
|
|
260
|
+
|
|
261
|
+
# ============================================================================
|
|
262
|
+
# TIER 1 FIX: File Modification Time Detection (Fallback)
|
|
263
|
+
# ============================================================================
|
|
264
|
+
# If we couldn't detect the file via environment variables, check which files
|
|
265
|
+
# were modified recently (within last 2 seconds) instead of blindly updating
|
|
266
|
+
if [[ -z "$DETECTED_FILE" ]]; then
|
|
267
|
+
echo "[$(date)] post-edit-write: Env vars empty - checking file mtimes" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
268
|
+
|
|
269
|
+
NOW=$(date +%s)
|
|
270
|
+
INCREMENTS_DIR="$PROJECT_ROOT/.specweave/increments"
|
|
271
|
+
|
|
272
|
+
# Check for recently modified spec.md or tasks.md files
|
|
273
|
+
if [[ -d "$INCREMENTS_DIR" ]]; then
|
|
274
|
+
for file in "$INCREMENTS_DIR"/*/spec.md "$INCREMENTS_DIR"/*/tasks.md; do
|
|
275
|
+
if [[ -f "$file" ]]; then
|
|
276
|
+
# Get file modification time (platform-specific)
|
|
277
|
+
if [[ "$(uname)" == "Darwin" ]]; then
|
|
278
|
+
MTIME=$(stat -f "%m" "$file" 2>/dev/null || echo 0)
|
|
279
|
+
else
|
|
280
|
+
MTIME=$(stat -c "%Y" "$file" 2>/dev/null || echo 0)
|
|
281
|
+
fi
|
|
282
|
+
|
|
283
|
+
# If file was modified in last 2 seconds, consider it the changed file
|
|
284
|
+
TIME_DIFF=$((NOW - MTIME))
|
|
285
|
+
if (( TIME_DIFF <= 2 )); then
|
|
286
|
+
DETECTED_FILE="$file"
|
|
287
|
+
echo "[$(date)] post-edit-write: Detected recent modification: $file (${TIME_DIFF}s ago)" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
288
|
+
SHOULD_UPDATE=true
|
|
289
|
+
break
|
|
290
|
+
fi
|
|
291
|
+
fi
|
|
292
|
+
done
|
|
293
|
+
fi
|
|
294
|
+
|
|
295
|
+
# If still no file detected, skip update (not a spec/tasks change)
|
|
296
|
+
if [[ -z "$DETECTED_FILE" ]]; then
|
|
297
|
+
echo "[$(date)] post-edit-write: No spec/tasks modifications detected - skipping" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
298
|
+
exit 0
|
|
299
|
+
fi
|
|
300
|
+
fi
|
|
301
|
+
|
|
302
|
+
# ============================================================================
|
|
303
|
+
# TIER 1 FIX: Non-Blocking Background Update with COMPLETE ERROR ISOLATION
|
|
304
|
+
# ============================================================================
|
|
305
|
+
# Update status line if needed
|
|
306
|
+
if [[ "$SHOULD_UPDATE" == "true" ]]; then
|
|
307
|
+
echo "[$(date)] post-edit-write: Running update-status-line.sh (background)" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
308
|
+
|
|
309
|
+
# Record update time BEFORE spawning background process
|
|
310
|
+
# This ensures debouncing works even if update hasn't completed yet
|
|
311
|
+
echo "$(date +%s)" > "$LAST_UPDATE_FILE"
|
|
312
|
+
|
|
313
|
+
# Run status line update in background with COMPLETE error isolation
|
|
314
|
+
# This prevents Edit/Write tool from waiting for status line computation
|
|
315
|
+
(
|
|
316
|
+
set +e # Disable error propagation
|
|
317
|
+
|
|
318
|
+
if "$PROJECT_ROOT/plugins/specweave/hooks/lib/update-status-line.sh" 2>&1 | tee -a "$DEBUG_LOG" >/dev/null; then
|
|
319
|
+
echo "[$(date)] post-edit-write: Status line updated successfully" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
320
|
+
# Reset circuit breaker on success
|
|
321
|
+
echo "0" > "$CIRCUIT_BREAKER_FILE" 2>/dev/null || true
|
|
322
|
+
else
|
|
323
|
+
echo "[$(date)] post-edit-write: Warning - status line update failed (non-blocking)" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
324
|
+
# Increment circuit breaker
|
|
325
|
+
CURRENT_FAILURES=$(cat "$CIRCUIT_BREAKER_FILE" 2>/dev/null || echo 0)
|
|
326
|
+
echo "$((CURRENT_FAILURES + 1))" > "$CIRCUIT_BREAKER_FILE" 2>/dev/null || true
|
|
327
|
+
fi
|
|
328
|
+
) &
|
|
329
|
+
|
|
330
|
+
# Disown the background process so it's not killed when hook exits
|
|
331
|
+
disown 2>/dev/null || true
|
|
332
|
+
fi
|
|
333
|
+
|
|
334
|
+
# Always exit 0 to prevent hook errors from crashing Claude Code
|
|
335
|
+
exit 0
|