specweave 1.0.31 → 1.0.33
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-plugin/marketplace.json +1 -1
- package/CLAUDE.md +205 -148
- package/README.md +0 -2
- package/bin/specweave.js +11 -0
- package/dist/src/cli/commands/init.js +1 -1
- package/dist/src/cli/commands/init.js.map +1 -1
- package/dist/src/cli/commands/update-instructions.d.ts +16 -0
- package/dist/src/cli/commands/update-instructions.d.ts.map +1 -0
- package/dist/src/cli/commands/update-instructions.js +134 -0
- package/dist/src/cli/commands/update-instructions.js.map +1 -0
- package/dist/src/cli/helpers/init/directory-structure.d.ts +28 -1
- package/dist/src/cli/helpers/init/directory-structure.d.ts.map +1 -1
- package/dist/src/cli/helpers/init/directory-structure.js +163 -33
- package/dist/src/cli/helpers/init/directory-structure.js.map +1 -1
- package/dist/src/cli/helpers/init/index.d.ts +2 -1
- package/dist/src/cli/helpers/init/index.d.ts.map +1 -1
- package/dist/src/cli/helpers/init/index.js +3 -1
- package/dist/src/cli/helpers/init/index.js.map +1 -1
- package/dist/src/cli/helpers/init/instruction-file-merger.d.ts +23 -0
- package/dist/src/cli/helpers/init/instruction-file-merger.d.ts.map +1 -0
- package/dist/src/cli/helpers/init/instruction-file-merger.js +243 -0
- package/dist/src/cli/helpers/init/instruction-file-merger.js.map +1 -0
- package/dist/src/cli/helpers/init/plugin-installer.js +49 -0
- package/dist/src/cli/helpers/init/plugin-installer.js.map +1 -1
- package/dist/src/config/types.d.ts +2 -2
- package/dist/src/core/living-docs/external-sync-orchestrator.d.ts +26 -0
- package/dist/src/core/living-docs/external-sync-orchestrator.d.ts.map +1 -1
- package/dist/src/core/living-docs/external-sync-orchestrator.js +61 -0
- package/dist/src/core/living-docs/external-sync-orchestrator.js.map +1 -1
- package/dist/src/core/living-docs/scaffolding/index.d.ts +12 -0
- package/dist/src/core/living-docs/scaffolding/index.d.ts.map +1 -0
- package/dist/src/core/living-docs/scaffolding/index.js +15 -0
- package/dist/src/core/living-docs/scaffolding/index.js.map +1 -0
- package/dist/src/core/living-docs/scaffolding/merger.d.ts +183 -0
- package/dist/src/core/living-docs/scaffolding/merger.d.ts.map +1 -0
- package/dist/src/core/living-docs/scaffolding/merger.js +523 -0
- package/dist/src/core/living-docs/scaffolding/merger.js.map +1 -0
- package/dist/src/core/living-docs/scaffolding/scaffold.d.ts +102 -0
- package/dist/src/core/living-docs/scaffolding/scaffold.d.ts.map +1 -0
- package/dist/src/core/living-docs/scaffolding/scaffold.js +346 -0
- package/dist/src/core/living-docs/scaffolding/scaffold.js.map +1 -0
- package/dist/src/core/living-docs/scaffolding/template-engine.d.ts +108 -0
- package/dist/src/core/living-docs/scaffolding/template-engine.d.ts.map +1 -0
- package/dist/src/core/living-docs/scaffolding/template-engine.js +204 -0
- package/dist/src/core/living-docs/scaffolding/template-engine.js.map +1 -0
- package/dist/src/core/living-docs/sync-helpers/generators.d.ts +38 -2
- package/dist/src/core/living-docs/sync-helpers/generators.d.ts.map +1 -1
- package/dist/src/core/living-docs/sync-helpers/generators.js +65 -10
- package/dist/src/core/living-docs/sync-helpers/generators.js.map +1 -1
- package/dist/src/core/living-docs/sync-helpers/index.d.ts +1 -1
- package/dist/src/core/living-docs/sync-helpers/index.d.ts.map +1 -1
- package/dist/src/core/living-docs/sync-helpers/index.js.map +1 -1
- package/dist/src/core/tools/index.d.ts +11 -0
- package/dist/src/core/tools/index.d.ts.map +1 -0
- package/dist/src/core/tools/index.js +10 -0
- package/dist/src/core/tools/index.js.map +1 -0
- package/dist/src/core/tools/tool-event-bus.d.ts +33 -0
- package/dist/src/core/tools/tool-event-bus.d.ts.map +1 -0
- package/dist/src/core/tools/tool-event-bus.js +84 -0
- package/dist/src/core/tools/tool-event-bus.js.map +1 -0
- package/dist/src/core/tools/tool-index-builder.d.ts +27 -0
- package/dist/src/core/tools/tool-index-builder.d.ts.map +1 -0
- package/dist/src/core/tools/tool-index-builder.js +289 -0
- package/dist/src/core/tools/tool-index-builder.js.map +1 -0
- package/dist/src/core/tools/tool-registry.d.ts +51 -0
- package/dist/src/core/tools/tool-registry.d.ts.map +1 -0
- package/dist/src/core/tools/tool-registry.js +224 -0
- package/dist/src/core/tools/tool-registry.js.map +1 -0
- package/dist/src/core/tools/tool-search-engine.d.ts +22 -0
- package/dist/src/core/tools/tool-search-engine.d.ts.map +1 -0
- package/dist/src/core/tools/tool-search-engine.js +174 -0
- package/dist/src/core/tools/tool-search-engine.js.map +1 -0
- package/dist/src/core/tools/types/tool-registry-types.d.ts +112 -0
- package/dist/src/core/tools/types/tool-registry-types.d.ts.map +1 -0
- package/dist/src/core/tools/types/tool-registry-types.js +7 -0
- package/dist/src/core/tools/types/tool-registry-types.js.map +1 -0
- package/dist/src/init/compliance/types.d.ts +1 -1
- package/package.json +1 -1
- package/plugins/specweave/hooks/hooks.json +3 -13
- package/plugins/specweave/hooks/lib/common-setup.sh +47 -321
- package/plugins/specweave/hooks/lib/migrate-increment-work.sh +5 -5
- package/plugins/specweave/hooks/lib/sync-spec-content.sh +5 -5
- package/plugins/specweave/hooks/universal/dispatcher.mjs +4 -5
- package/plugins/specweave/hooks/universal/fail-fast-wrapper.sh +43 -296
- package/plugins/specweave/hooks/universal/hook-wrapper.sh +3 -1
- package/plugins/specweave/hooks/user-prompt-submit.sh +1 -1
- package/plugins/specweave/hooks/v2/dispatchers/post-tool-use.sh +2 -2
- package/plugins/specweave/hooks/v2/dispatchers/session-start.sh +1 -10
- package/plugins/specweave/hooks/v2/guards/completion-guard.sh +12 -29
- package/plugins/specweave/hooks/v2/guards/increment-duplicate-guard.sh +27 -29
- package/plugins/specweave/hooks/v2/guards/metadata-json-guard.sh +10 -4
- package/plugins/specweave/hooks/v2/guards/spec-validation-guard.sh +139 -0
- package/plugins/specweave/hooks/v2/guards/task-ac-sync-guard.sh +4 -2
- package/plugins/specweave/hooks/v2/session-end.sh +3 -1
- package/plugins/specweave/hooks/v2/session-start.sh +3 -1
- package/plugins/specweave/skills/increment-planner/templates/plan.md +14 -0
- package/plugins/specweave/skills/update-instructions/SKILL.md +80 -0
- package/plugins/specweave-ado/hooks/post-living-docs-update.sh +1 -1
- package/plugins/specweave-mobile/README.md +55 -35
- package/plugins/specweave-mobile/agents/mobile-architect/AGENT.md +805 -329
- package/plugins/specweave-mobile/skills/expo-workflow/SKILL.md +226 -9
- package/plugins/specweave-mobile/skills/native-modules/SKILL.md +221 -20
- package/plugins/specweave-mobile/skills/performance-optimization/SKILL.md +186 -14
- package/plugins/specweave-mobile/skills/react-native-setup/SKILL.md +151 -54
- package/plugins/specweave-release/commands/npm.md +61 -17
- package/plugins/specweave-release/hooks/post-task-completion.sh +2 -3
- package/src/templates/AGENTS.md.template +34 -0
- package/src/templates/CLAUDE.md.template +121 -155
- package/plugins/specweave/hooks/config-env-separator.sh +0 -99
- package/plugins/specweave/hooks/github-metadata-guard.sh +0 -73
- package/plugins/specweave/hooks/lib/circuit-breaker.sh +0 -381
- package/plugins/specweave/hooks/lib/crash-prevention.sh +0 -336
- package/plugins/specweave/hooks/lib/logging.sh +0 -231
- package/plugins/specweave/hooks/lib/metrics.sh +0 -347
- package/plugins/specweave/hooks/lib/semaphore.sh +0 -216
- package/plugins/specweave/hooks/project-folder-guard.sh +0 -274
- package/plugins/specweave/hooks/spec-project-validator.sh +0 -210
- package/plugins/specweave/hooks/v2/guards/bash-file-guard.sh +0 -212
- package/plugins/specweave/hooks/v2/guards/bash-file-guard.test.sh +0 -163
- package/plugins/specweave/hooks/v2/guards/features-folder-guard.sh +0 -51
- package/plugins/specweave/hooks/v2/guards/increment-root-guard.sh +0 -63
- package/plugins/specweave/hooks/v2/guards/per-us-project-validator.sh +0 -335
- package/plugins/specweave/hooks/v2/guards/per-us-project-validator.test.sh +0 -406
|
@@ -1,406 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# Comprehensive test suite for per-us-project-validator.sh
|
|
3
|
-
# Tests that each User Story in spec.md has **Project**: (and **Board**: for 2-level)
|
|
4
|
-
#
|
|
5
|
-
# Usage: bash per-us-project-validator.test.sh
|
|
6
|
-
#
|
|
7
|
-
# v0.34.0 - Initial test suite with all US formats
|
|
8
|
-
|
|
9
|
-
set -e
|
|
10
|
-
|
|
11
|
-
GUARD="$(dirname "$0")/per-us-project-validator.sh"
|
|
12
|
-
TEST_DIR=$(mktemp -d)
|
|
13
|
-
PASS=0
|
|
14
|
-
FAIL=0
|
|
15
|
-
TOTAL=0
|
|
16
|
-
|
|
17
|
-
# Colors for output
|
|
18
|
-
RED='\033[0;31m'
|
|
19
|
-
GREEN='\033[0;32m'
|
|
20
|
-
YELLOW='\033[1;33m'
|
|
21
|
-
NC='\033[0m' # No Color
|
|
22
|
-
|
|
23
|
-
cleanup() {
|
|
24
|
-
rm -rf "$TEST_DIR"
|
|
25
|
-
}
|
|
26
|
-
trap cleanup EXIT
|
|
27
|
-
|
|
28
|
-
# Test helper: should block
|
|
29
|
-
test_should_block() {
|
|
30
|
-
local name="$1"
|
|
31
|
-
local spec_content="$2"
|
|
32
|
-
TOTAL=$((TOTAL + 1))
|
|
33
|
-
|
|
34
|
-
local file_path="$TEST_DIR/.specweave/increments/0001-test/spec.md"
|
|
35
|
-
mkdir -p "$(dirname "$file_path")"
|
|
36
|
-
|
|
37
|
-
# Build JSON input for the guard
|
|
38
|
-
# Use printf + jq -Rs to properly escape newlines in the content
|
|
39
|
-
local json_input
|
|
40
|
-
json_input=$(printf '%s' "$spec_content" | jq -Rs \
|
|
41
|
-
--arg tool_name "Write" \
|
|
42
|
-
--arg file_path "$file_path" \
|
|
43
|
-
'{tool_name: $tool_name, tool_input: {file_path: $file_path, content: .}}')
|
|
44
|
-
|
|
45
|
-
result=$(echo "$json_input" | bash "$GUARD" 2>&1; echo "EXIT:$?")
|
|
46
|
-
exit_code=$(echo "$result" | grep -o 'EXIT:[0-9]*' | cut -d: -f2)
|
|
47
|
-
|
|
48
|
-
if [[ "$exit_code" == "0" ]] && echo "$result" | grep -q '"decision".*"block"'; then
|
|
49
|
-
echo -e "${GREEN}✓ BLOCKED${NC}: $name"
|
|
50
|
-
PASS=$((PASS + 1))
|
|
51
|
-
else
|
|
52
|
-
echo -e "${RED}✗ NOT BLOCKED${NC}: $name"
|
|
53
|
-
echo " Exit code: $exit_code"
|
|
54
|
-
echo " Result: $(echo "$result" | head -3)"
|
|
55
|
-
FAIL=$((FAIL + 1))
|
|
56
|
-
fi
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
# Test helper: should allow
|
|
60
|
-
test_should_allow() {
|
|
61
|
-
local name="$1"
|
|
62
|
-
local spec_content="$2"
|
|
63
|
-
TOTAL=$((TOTAL + 1))
|
|
64
|
-
|
|
65
|
-
local file_path="$TEST_DIR/.specweave/increments/0001-test/spec.md"
|
|
66
|
-
mkdir -p "$(dirname "$file_path")"
|
|
67
|
-
|
|
68
|
-
# Build JSON input for the guard
|
|
69
|
-
# Use printf + jq -Rs to properly escape newlines in the content
|
|
70
|
-
local json_input
|
|
71
|
-
json_input=$(printf '%s' "$spec_content" | jq -Rs \
|
|
72
|
-
--arg tool_name "Write" \
|
|
73
|
-
--arg file_path "$file_path" \
|
|
74
|
-
'{tool_name: $tool_name, tool_input: {file_path: $file_path, content: .}}')
|
|
75
|
-
|
|
76
|
-
result=$(echo "$json_input" | bash "$GUARD" 2>&1; echo "EXIT:$?")
|
|
77
|
-
exit_code=$(echo "$result" | grep -o 'EXIT:[0-9]*' | cut -d: -f2)
|
|
78
|
-
|
|
79
|
-
if [[ "$exit_code" == "0" ]] && echo "$result" | grep -q '"decision".*"allow"'; then
|
|
80
|
-
echo -e "${GREEN}✓ ALLOWED${NC}: $name"
|
|
81
|
-
PASS=$((PASS + 1))
|
|
82
|
-
else
|
|
83
|
-
echo -e "${RED}✗ WRONGLY BLOCKED${NC}: $name"
|
|
84
|
-
echo " Exit code: $exit_code"
|
|
85
|
-
echo " Result: $(echo "$result" | head -5)"
|
|
86
|
-
FAIL=$((FAIL + 1))
|
|
87
|
-
fi
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
echo "========================================"
|
|
91
|
-
echo " PER-US PROJECT VALIDATOR - COMPREHENSIVE TESTS"
|
|
92
|
-
echo "========================================"
|
|
93
|
-
echo ""
|
|
94
|
-
echo "Test directory: $TEST_DIR"
|
|
95
|
-
echo ""
|
|
96
|
-
|
|
97
|
-
echo -e "${YELLOW}=== SIMPLE US FORMAT (### US-001:) ===${NC}"
|
|
98
|
-
|
|
99
|
-
test_should_allow "Simple US with Project field" '---
|
|
100
|
-
increment: 0001-test
|
|
101
|
-
project: my-app
|
|
102
|
-
---
|
|
103
|
-
# Feature
|
|
104
|
-
|
|
105
|
-
### US-001: Login Form
|
|
106
|
-
**Project**: frontend-app
|
|
107
|
-
|
|
108
|
-
**As a** user
|
|
109
|
-
**I want** to log in
|
|
110
|
-
**So that** I can access the app
|
|
111
|
-
|
|
112
|
-
**Acceptance Criteria**:
|
|
113
|
-
- [ ] **AC-US1-01**: Form exists
|
|
114
|
-
'
|
|
115
|
-
|
|
116
|
-
test_should_block "Simple US WITHOUT Project field" '---
|
|
117
|
-
increment: 0001-test
|
|
118
|
-
project: my-app
|
|
119
|
-
---
|
|
120
|
-
# Feature
|
|
121
|
-
|
|
122
|
-
### US-001: Login Form
|
|
123
|
-
|
|
124
|
-
**As a** user
|
|
125
|
-
**I want** to log in
|
|
126
|
-
**So that** I can access the app
|
|
127
|
-
'
|
|
128
|
-
|
|
129
|
-
echo ""
|
|
130
|
-
echo -e "${YELLOW}=== MULTI-PROJECT US FORMAT (#### US-FE-001:) ===${NC}"
|
|
131
|
-
|
|
132
|
-
test_should_allow "Multi-project US-FE-001 with Project field" '---
|
|
133
|
-
increment: 0001-test
|
|
134
|
-
project: my-app
|
|
135
|
-
multi_project: true
|
|
136
|
-
---
|
|
137
|
-
# Feature
|
|
138
|
-
|
|
139
|
-
#### US-FE-001: Login Form UI
|
|
140
|
-
**Project**: frontend-app
|
|
141
|
-
|
|
142
|
-
**As a** user
|
|
143
|
-
**I want** to see a login form
|
|
144
|
-
|
|
145
|
-
#### US-BE-001: Auth API
|
|
146
|
-
**Project**: backend-api
|
|
147
|
-
|
|
148
|
-
**As a** frontend
|
|
149
|
-
**I want** auth endpoints
|
|
150
|
-
'
|
|
151
|
-
|
|
152
|
-
test_should_block "Multi-project US-FE-001 WITHOUT Project field" '---
|
|
153
|
-
increment: 0001-test
|
|
154
|
-
project: my-app
|
|
155
|
-
multi_project: true
|
|
156
|
-
---
|
|
157
|
-
# Feature
|
|
158
|
-
|
|
159
|
-
#### US-FE-001: Login Form UI
|
|
160
|
-
|
|
161
|
-
**As a** user
|
|
162
|
-
**I want** to see a login form
|
|
163
|
-
'
|
|
164
|
-
|
|
165
|
-
echo ""
|
|
166
|
-
echo -e "${YELLOW}=== MIXED FORMAT (### with prefixes) ===${NC}"
|
|
167
|
-
|
|
168
|
-
test_should_allow "Mixed: ### US-FE-001 with Project" '---
|
|
169
|
-
increment: 0001-test
|
|
170
|
-
project: my-app
|
|
171
|
-
---
|
|
172
|
-
# Feature
|
|
173
|
-
|
|
174
|
-
### US-FE-001: Frontend Story
|
|
175
|
-
**Project**: frontend
|
|
176
|
-
|
|
177
|
-
### US-BE-001: Backend Story
|
|
178
|
-
**Project**: backend
|
|
179
|
-
'
|
|
180
|
-
|
|
181
|
-
test_should_block "Mixed: ### US-FE-001 without Project" '---
|
|
182
|
-
increment: 0001-test
|
|
183
|
-
project: my-app
|
|
184
|
-
---
|
|
185
|
-
# Feature
|
|
186
|
-
|
|
187
|
-
### US-FE-001: Frontend Story
|
|
188
|
-
|
|
189
|
-
### US-BE-001: Backend Story
|
|
190
|
-
**Project**: backend
|
|
191
|
-
'
|
|
192
|
-
|
|
193
|
-
echo ""
|
|
194
|
-
echo -e "${YELLOW}=== SHARED PROJECT PREFIX ===${NC}"
|
|
195
|
-
|
|
196
|
-
test_should_allow "US-SHARED-001 with Project" '---
|
|
197
|
-
increment: 0001-test
|
|
198
|
-
project: my-app
|
|
199
|
-
---
|
|
200
|
-
# Feature
|
|
201
|
-
|
|
202
|
-
#### US-SHARED-001: Shared Types
|
|
203
|
-
**Project**: shared-lib
|
|
204
|
-
|
|
205
|
-
**As a** developer
|
|
206
|
-
**I want** shared types
|
|
207
|
-
'
|
|
208
|
-
|
|
209
|
-
test_should_block "US-SHARED-001 without Project" '---
|
|
210
|
-
increment: 0001-test
|
|
211
|
-
project: my-app
|
|
212
|
-
---
|
|
213
|
-
# Feature
|
|
214
|
-
|
|
215
|
-
#### US-SHARED-001: Shared Types
|
|
216
|
-
|
|
217
|
-
**As a** developer
|
|
218
|
-
**I want** shared types
|
|
219
|
-
'
|
|
220
|
-
|
|
221
|
-
echo ""
|
|
222
|
-
echo -e "${YELLOW}=== MULTIPLE PROJECTS (1:1 VIOLATION - COMMA SEPARATED) ===${NC}"
|
|
223
|
-
|
|
224
|
-
test_should_block "Multiple projects (comma separated) - FORBIDDEN" '---
|
|
225
|
-
increment: 0001-test
|
|
226
|
-
project: my-app
|
|
227
|
-
---
|
|
228
|
-
# Feature
|
|
229
|
-
|
|
230
|
-
### US-001: Cross-cutting Story
|
|
231
|
-
**Project**: frontend-app, backend-api
|
|
232
|
-
|
|
233
|
-
**As a** user
|
|
234
|
-
**I want** everything
|
|
235
|
-
'
|
|
236
|
-
|
|
237
|
-
test_should_block "Multiple projects with spaces" '---
|
|
238
|
-
increment: 0001-test
|
|
239
|
-
project: my-app
|
|
240
|
-
---
|
|
241
|
-
# Feature
|
|
242
|
-
|
|
243
|
-
### US-001: Cross-cutting Story
|
|
244
|
-
**Project**: frontend-app,backend-api,shared
|
|
245
|
-
|
|
246
|
-
**As a** user
|
|
247
|
-
**I want** everything
|
|
248
|
-
'
|
|
249
|
-
|
|
250
|
-
echo ""
|
|
251
|
-
echo -e "${YELLOW}=== NO USER STORIES (should allow) ===${NC}"
|
|
252
|
-
|
|
253
|
-
test_should_allow "Spec without any User Stories" '---
|
|
254
|
-
increment: 0001-test
|
|
255
|
-
project: my-app
|
|
256
|
-
---
|
|
257
|
-
# Feature Overview
|
|
258
|
-
|
|
259
|
-
This is just an overview document.
|
|
260
|
-
|
|
261
|
-
## Goals
|
|
262
|
-
|
|
263
|
-
- Goal 1
|
|
264
|
-
- Goal 2
|
|
265
|
-
'
|
|
266
|
-
|
|
267
|
-
test_should_allow "Tasks-only spec (no US headings)" '---
|
|
268
|
-
increment: 0001-test
|
|
269
|
-
project: my-app
|
|
270
|
-
---
|
|
271
|
-
# Implementation Tasks
|
|
272
|
-
|
|
273
|
-
## T-001: Setup
|
|
274
|
-
|
|
275
|
-
Do setup stuff.
|
|
276
|
-
'
|
|
277
|
-
|
|
278
|
-
echo ""
|
|
279
|
-
echo -e "${YELLOW}=== ALL USER STORIES HAVE PROJECT ===${NC}"
|
|
280
|
-
|
|
281
|
-
test_should_allow "Multiple US, all with Project" '---
|
|
282
|
-
increment: 0001-test
|
|
283
|
-
project: my-app
|
|
284
|
-
---
|
|
285
|
-
# Feature
|
|
286
|
-
|
|
287
|
-
### US-001: First Story
|
|
288
|
-
**Project**: app-a
|
|
289
|
-
|
|
290
|
-
### US-002: Second Story
|
|
291
|
-
**Project**: app-b
|
|
292
|
-
|
|
293
|
-
### US-003: Third Story
|
|
294
|
-
**Project**: app-c
|
|
295
|
-
'
|
|
296
|
-
|
|
297
|
-
test_should_block "Multiple US, one missing Project" '---
|
|
298
|
-
increment: 0001-test
|
|
299
|
-
project: my-app
|
|
300
|
-
---
|
|
301
|
-
# Feature
|
|
302
|
-
|
|
303
|
-
### US-001: First Story
|
|
304
|
-
**Project**: app-a
|
|
305
|
-
|
|
306
|
-
### US-002: Second Story
|
|
307
|
-
|
|
308
|
-
### US-003: Third Story
|
|
309
|
-
**Project**: app-c
|
|
310
|
-
'
|
|
311
|
-
|
|
312
|
-
echo ""
|
|
313
|
-
echo -e "${YELLOW}=== NON-WRITE TOOLS ===${NC}"
|
|
314
|
-
|
|
315
|
-
# Test with Edit tool (should allow - no full content)
|
|
316
|
-
TOTAL=$((TOTAL + 1))
|
|
317
|
-
json_input=$(jq -n \
|
|
318
|
-
--arg tool_name "Edit" \
|
|
319
|
-
--arg file_path "$TEST_DIR/.specweave/increments/0001-test/spec.md" \
|
|
320
|
-
'{tool_name: $tool_name, tool_input: {file_path: $file_path}}')
|
|
321
|
-
|
|
322
|
-
result=$(echo "$json_input" | bash "$GUARD" 2>&1; echo "EXIT:$?")
|
|
323
|
-
exit_code=$(echo "$result" | grep -o 'EXIT:[0-9]*' | cut -d: -f2)
|
|
324
|
-
if [[ "$exit_code" == "0" ]]; then
|
|
325
|
-
echo -e "${GREEN}✓ ALLOWED${NC}: Edit tool (no full content validation)"
|
|
326
|
-
PASS=$((PASS + 1))
|
|
327
|
-
else
|
|
328
|
-
echo -e "${RED}✗ FAILED${NC}: Edit tool should be allowed"
|
|
329
|
-
FAIL=$((FAIL + 1))
|
|
330
|
-
fi
|
|
331
|
-
|
|
332
|
-
echo ""
|
|
333
|
-
echo -e "${YELLOW}=== BYPASS MODES ===${NC}"
|
|
334
|
-
|
|
335
|
-
# Test SPECWEAVE_FORCE_PROJECT bypass
|
|
336
|
-
TOTAL=$((TOTAL + 1))
|
|
337
|
-
spec_content='---
|
|
338
|
-
increment: 0001-test
|
|
339
|
-
---
|
|
340
|
-
### US-001: No Project
|
|
341
|
-
**As a** user
|
|
342
|
-
**I want** something
|
|
343
|
-
'
|
|
344
|
-
json_input=$(jq -n \
|
|
345
|
-
--arg tool_name "Write" \
|
|
346
|
-
--arg file_path "$TEST_DIR/.specweave/increments/0001-test/spec.md" \
|
|
347
|
-
--arg content "$spec_content" \
|
|
348
|
-
'{tool_name: $tool_name, tool_input: {file_path: $file_path, content: $content}}')
|
|
349
|
-
|
|
350
|
-
result=$(SPECWEAVE_FORCE_PROJECT=1 bash -c "echo '$json_input' | bash '$GUARD'" 2>&1; echo "EXIT:$?")
|
|
351
|
-
exit_code=$(echo "$result" | grep -o 'EXIT:[0-9]*' | cut -d: -f2)
|
|
352
|
-
if [[ "$exit_code" == "0" ]] && echo "$result" | grep -q "bypassed"; then
|
|
353
|
-
echo -e "${GREEN}✓ ALLOWED (bypass)${NC}: SPECWEAVE_FORCE_PROJECT=1"
|
|
354
|
-
PASS=$((PASS + 1))
|
|
355
|
-
else
|
|
356
|
-
echo -e "${RED}✗ BYPASS FAILED${NC}: SPECWEAVE_FORCE_PROJECT=1"
|
|
357
|
-
FAIL=$((FAIL + 1))
|
|
358
|
-
fi
|
|
359
|
-
|
|
360
|
-
# Test SPECWEAVE_LEGACY_SPEC bypass
|
|
361
|
-
TOTAL=$((TOTAL + 1))
|
|
362
|
-
result=$(SPECWEAVE_LEGACY_SPEC=1 bash -c "echo '$json_input' | bash '$GUARD'" 2>&1; echo "EXIT:$?")
|
|
363
|
-
exit_code=$(echo "$result" | grep -o 'EXIT:[0-9]*' | cut -d: -f2)
|
|
364
|
-
if [[ "$exit_code" == "0" ]] && echo "$result" | grep -q "legacy"; then
|
|
365
|
-
echo -e "${GREEN}✓ ALLOWED (bypass)${NC}: SPECWEAVE_LEGACY_SPEC=1"
|
|
366
|
-
PASS=$((PASS + 1))
|
|
367
|
-
else
|
|
368
|
-
echo -e "${RED}✗ BYPASS FAILED${NC}: SPECWEAVE_LEGACY_SPEC=1"
|
|
369
|
-
FAIL=$((FAIL + 1))
|
|
370
|
-
fi
|
|
371
|
-
|
|
372
|
-
echo ""
|
|
373
|
-
echo -e "${YELLOW}=== FILES OUTSIDE INCREMENTS ===${NC}"
|
|
374
|
-
|
|
375
|
-
# Test file outside increments folder
|
|
376
|
-
TOTAL=$((TOTAL + 1))
|
|
377
|
-
json_input=$(jq -n \
|
|
378
|
-
--arg tool_name "Write" \
|
|
379
|
-
--arg file_path "$TEST_DIR/other/spec.md" \
|
|
380
|
-
--arg content "no project" \
|
|
381
|
-
'{tool_name: $tool_name, tool_input: {file_path: $file_path, content: $content}}')
|
|
382
|
-
|
|
383
|
-
result=$(echo "$json_input" | bash "$GUARD" 2>&1; echo "EXIT:$?")
|
|
384
|
-
exit_code=$(echo "$result" | grep -o 'EXIT:[0-9]*' | cut -d: -f2)
|
|
385
|
-
if [[ "$exit_code" == "0" ]] && echo "$result" | grep -q '"decision".*"allow"'; then
|
|
386
|
-
echo -e "${GREEN}✓ ALLOWED${NC}: spec.md outside increments folder"
|
|
387
|
-
PASS=$((PASS + 1))
|
|
388
|
-
else
|
|
389
|
-
echo -e "${RED}✗ FAILED${NC}: Files outside increments should be allowed"
|
|
390
|
-
FAIL=$((FAIL + 1))
|
|
391
|
-
fi
|
|
392
|
-
|
|
393
|
-
echo ""
|
|
394
|
-
echo "========================================"
|
|
395
|
-
echo " RESULTS"
|
|
396
|
-
echo "========================================"
|
|
397
|
-
echo -e "Total: $TOTAL"
|
|
398
|
-
echo -e "${GREEN}Passed: $PASS${NC}"
|
|
399
|
-
if [[ $FAIL -gt 0 ]]; then
|
|
400
|
-
echo -e "${RED}Failed: $FAIL${NC}"
|
|
401
|
-
exit 1
|
|
402
|
-
else
|
|
403
|
-
echo -e "Failed: 0"
|
|
404
|
-
echo ""
|
|
405
|
-
echo -e "${GREEN}ALL TESTS PASSED!${NC}"
|
|
406
|
-
fi
|