@specsafe/cli 0.3.6 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/apply.d.ts +3 -0
- package/dist/commands/apply.d.ts.map +1 -0
- package/dist/commands/apply.js +182 -0
- package/dist/commands/apply.js.map +1 -0
- package/dist/commands/complete.d.ts.map +1 -1
- package/dist/commands/complete.js +4 -1
- package/dist/commands/complete.js.map +1 -1
- package/dist/commands/delta.d.ts +3 -0
- package/dist/commands/delta.d.ts.map +1 -0
- package/dist/commands/delta.js +82 -0
- package/dist/commands/delta.js.map +1 -0
- package/dist/commands/diff.d.ts +3 -0
- package/dist/commands/diff.d.ts.map +1 -0
- package/dist/commands/diff.js +102 -0
- package/dist/commands/diff.js.map +1 -0
- package/dist/commands/done.d.ts +3 -0
- package/dist/commands/done.d.ts.map +1 -0
- package/dist/commands/done.js +237 -0
- package/dist/commands/done.js.map +1 -0
- package/dist/commands/explore.d.ts +3 -0
- package/dist/commands/explore.d.ts.map +1 -0
- package/dist/commands/explore.js +236 -0
- package/dist/commands/explore.js.map +1 -0
- package/dist/commands/init-old.d.ts +3 -0
- package/dist/commands/init-old.d.ts.map +1 -0
- package/dist/commands/init-old.js +146 -0
- package/dist/commands/init-old.js.map +1 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +195 -43
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/new.d.ts.map +1 -1
- package/dist/commands/new.js +332 -29
- package/dist/commands/new.js.map +1 -1
- package/dist/commands/qa.d.ts.map +1 -1
- package/dist/commands/qa.js +37 -1
- package/dist/commands/qa.js.map +1 -1
- package/dist/commands/rules.d.ts.map +1 -1
- package/dist/commands/rules.js +182 -97
- package/dist/commands/rules.js.map +1 -1
- package/dist/commands/spec.d.ts.map +1 -1
- package/dist/commands/spec.js +257 -25
- package/dist/commands/spec.js.map +1 -1
- package/dist/commands/test-apply.d.ts +3 -0
- package/dist/commands/test-apply.d.ts.map +1 -0
- package/dist/commands/test-apply.js +228 -0
- package/dist/commands/test-apply.js.map +1 -0
- package/dist/commands/test-create.d.ts +3 -0
- package/dist/commands/test-create.d.ts.map +1 -0
- package/dist/commands/{test.js → test-create.js} +79 -30
- package/dist/commands/test-create.js.map +1 -0
- package/dist/commands/verify.d.ts +3 -0
- package/dist/commands/verify.d.ts.map +1 -0
- package/dist/commands/verify.js +288 -0
- package/dist/commands/verify.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +58 -6
- package/dist/index.js.map +1 -1
- package/dist/utils/generateToolConfig.d.ts +1 -1
- package/dist/utils/generateToolConfig.d.ts.map +1 -1
- package/dist/utils/generateToolConfig.js +980 -209
- package/dist/utils/generateToolConfig.js.map +1 -1
- package/dist/utils/testRunner.d.ts +39 -0
- package/dist/utils/testRunner.d.ts.map +1 -0
- package/dist/utils/testRunner.js +325 -0
- package/dist/utils/testRunner.js.map +1 -0
- package/package.json +3 -3
- package/dist/commands/code.d.ts +0 -3
- package/dist/commands/code.d.ts.map +0 -1
- package/dist/commands/code.js +0 -53
- package/dist/commands/code.js.map +0 -1
- package/dist/commands/test.d.ts +0 -3
- package/dist/commands/test.d.ts.map +0 -1
- package/dist/commands/test.js.map +0 -1
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import { writeFile, mkdir } from 'fs/promises';
|
|
2
2
|
import { existsSync } from 'fs';
|
|
3
|
+
import { dirname } from 'path';
|
|
4
|
+
import { fileURLToPath } from 'url';
|
|
3
5
|
import chalk from 'chalk';
|
|
6
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
+
const __dirname = dirname(__filename);
|
|
4
8
|
/**
|
|
5
9
|
* Generates configuration files for AI coding tools
|
|
6
10
|
*/
|
|
7
|
-
const cursorRulesContent = `# SpecSafe Rules for Cursor
|
|
8
|
-
|
|
9
|
-
|
|
11
|
+
const cursorRulesContent = `# SpecSafe Rules for Cursor v0.4.0
|
|
12
|
+
# OpenSpec-Style Workflow Configuration
|
|
13
|
+
# https://github.com/luci-efe/specsafe
|
|
10
14
|
|
|
11
15
|
## Always Check PROJECT_STATE.md
|
|
12
16
|
Before making changes, read PROJECT_STATE.md to understand:
|
|
@@ -14,89 +18,590 @@ Before making changes, read PROJECT_STATE.md to understand:
|
|
|
14
18
|
- Which spec is being worked on
|
|
15
19
|
- Requirements that must be satisfied
|
|
16
20
|
|
|
17
|
-
## Spec-Driven Workflow
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
3. Implementation satisfies tests
|
|
21
|
+
## Spec-Driven Development (SDD) Workflow
|
|
22
|
+
|
|
23
|
+
EXPLORE → NEW → SPEC → TEST-CREATE → TEST-APPLY → VERIFY → DONE
|
|
21
24
|
|
|
22
25
|
## Stage-Aware Development
|
|
23
|
-
- SPEC stage: Generate tests from requirements
|
|
24
|
-
- TEST stage: Tests exist, implement code to pass them
|
|
25
|
-
- CODE stage: Implementation in progress, maintain tests
|
|
26
|
-
- QA stage: Validate against scenarios
|
|
27
|
-
- COMPLETE: Feature done, archive spec
|
|
28
26
|
|
|
29
|
-
|
|
27
|
+
| Stage | Description | Your Role |
|
|
28
|
+
|-------|-------------|-----------|
|
|
29
|
+
| EXPLORE | Research & validate ideas | Help evaluate approaches |
|
|
30
|
+
| NEW | PRD with requirements | Create PRD, tech stack, rules |
|
|
31
|
+
| SPEC | Detailed specification | Generate scenarios & acceptance criteria |
|
|
32
|
+
| TEST-CREATE | Test generation | Create tests from Given/When/Then |
|
|
33
|
+
| TEST-APPLY | Implementation | Write code to pass tests |
|
|
34
|
+
| VERIFY | Test validation | Run tests, fix failures, loop |
|
|
35
|
+
| DONE | Completion | Archive, summarize, celebrate |
|
|
36
|
+
|
|
37
|
+
## The 7 OpenSpec-Style Commands
|
|
38
|
+
|
|
39
|
+
### /specsafe:explore — Pre-Spec Exploration
|
|
40
|
+
**When to use:** Before committing to a spec, explore ideas and validate approaches.
|
|
41
|
+
|
|
42
|
+
**Your responsibilities:**
|
|
43
|
+
- Guide problem definition and user identification
|
|
44
|
+
- Research existing solutions and competitors
|
|
45
|
+
- Evaluate technology options with pros/cons
|
|
46
|
+
- Estimate effort (S/M/L/XL)
|
|
47
|
+
- Output: specs/exploration/FEATURE-NAME.md with findings
|
|
48
|
+
|
|
49
|
+
**Decision gate:** Recommend proceed to /specsafe:new or need more research.
|
|
50
|
+
|
|
51
|
+
### /specsafe:new — Initialize Spec with PRD
|
|
52
|
+
**When to use:** Starting a new feature with validated concept.
|
|
53
|
+
|
|
54
|
+
**Your responsibilities:**
|
|
55
|
+
1. Generate spec ID: SPEC-YYYYMMDD-NNN
|
|
56
|
+
2. Create PRD with problem statement, requirements, scenarios
|
|
57
|
+
3. Recommend tech stack and define rules
|
|
58
|
+
4. Output: specs/drafts/SPEC-ID.md + update PROJECT_STATE.md
|
|
59
|
+
|
|
60
|
+
**Always confirm with user before writing files.**
|
|
61
|
+
|
|
62
|
+
### /specsafe:spec — Generate Detailed Spec
|
|
63
|
+
**When to use:** PRD exists, need implementation-ready specification.
|
|
64
|
+
|
|
65
|
+
**Your responsibilities:**
|
|
66
|
+
1. Read PRD from specs/drafts/SPEC-ID.md
|
|
67
|
+
2. Create comprehensive spec with functional requirements (FR-XXX),
|
|
68
|
+
technical requirements (TR-XXX), scenarios, acceptance criteria
|
|
69
|
+
3. Move to specs/active/SPEC-ID.md
|
|
70
|
+
4. Update PROJECT_STATE.md: DRAFT → SPEC stage
|
|
71
|
+
|
|
72
|
+
**Validate:** Every requirement must be testable.
|
|
73
|
+
|
|
74
|
+
### /specsafe:test-create — Create Tests from Spec
|
|
75
|
+
**When to use:** Spec is ready, time to define verification.
|
|
76
|
+
|
|
77
|
+
**Your responsibilities:**
|
|
78
|
+
1. Read spec scenarios from specs/active/SPEC-ID.md
|
|
79
|
+
2. Determine test strategy (unit, integration, E2E)
|
|
80
|
+
3. Generate test files: src/__tests__/SPEC-ID/*.test.ts
|
|
81
|
+
4. Map each scenario to test cases
|
|
82
|
+
5. Update PROJECT_STATE.md: SPEC → TEST-CREATE stage
|
|
83
|
+
6. Output: Test count, coverage expectations
|
|
84
|
+
|
|
85
|
+
### /specsafe:test-apply — Apply Tests (Development Mode)
|
|
86
|
+
**When to use:** Tests exist, implement to make them pass.
|
|
87
|
+
|
|
88
|
+
**Your responsibilities:**
|
|
89
|
+
1. Read spec requirements and test expectations
|
|
90
|
+
2. Guide iterative development: Plan → Implement → Test → Commit
|
|
91
|
+
3. Enforce rules:
|
|
92
|
+
- Every change maps to a requirement
|
|
93
|
+
- Never modify tests to pass (fix code instead)
|
|
94
|
+
- Keep functions small and focused
|
|
95
|
+
4. Update PROJECT_STATE.md: TEST-CREATE → TEST-APPLY stage
|
|
96
|
+
|
|
97
|
+
**Ask:** "Which requirement should we tackle next?"
|
|
98
|
+
|
|
99
|
+
### /specsafe:verify — Verify & Iterate
|
|
100
|
+
**When to use:** Implementation complete, need validation.
|
|
101
|
+
|
|
102
|
+
**Your responsibilities:**
|
|
103
|
+
1. Read spec for expected behavior
|
|
104
|
+
2. Run test suite: npm test -- SPEC-ID
|
|
105
|
+
3. For each failure: identify, map to requirement, fix
|
|
106
|
+
4. Iterate: Run → Analyze → Fix → Run until all pass
|
|
107
|
+
5. Check coverage meets spec requirements
|
|
108
|
+
6. Update PROJECT_STATE.md: TEST-APPLY → VERIFY stage
|
|
109
|
+
|
|
110
|
+
**Output:** Pass rate, coverage %, remaining issues
|
|
111
|
+
|
|
112
|
+
### /specsafe:done — Complete & Archive
|
|
113
|
+
**When to use:** All tests pass, ready to finalize.
|
|
114
|
+
|
|
115
|
+
**Your responsibilities:**
|
|
116
|
+
1. Verify completion checklist
|
|
117
|
+
2. Run final test suite
|
|
118
|
+
3. Move specs/active/SPEC-ID.md → specs/archive/SPEC-ID.md
|
|
119
|
+
4. Update PROJECT_STATE.md: move to COMPLETED
|
|
120
|
+
5. Generate summary: date, files, tests, LOC, notes
|
|
121
|
+
6. Suggest next spec from active list
|
|
122
|
+
|
|
123
|
+
**Ask for confirmation before archiving.**
|
|
124
|
+
|
|
125
|
+
## Critical Rules
|
|
126
|
+
|
|
127
|
+
### ALWAYS
|
|
128
|
+
- Read PROJECT_STATE.md before making changes
|
|
129
|
+
- Ensure implementation satisfies tests
|
|
130
|
+
- Use specsafe CLI commands to advance stages
|
|
131
|
+
- Reference spec ID in commit messages: feat(SPEC-001): add user auth
|
|
132
|
+
- Run tests before marking work complete
|
|
133
|
+
|
|
134
|
+
### NEVER
|
|
30
135
|
- Skip tests to implement faster
|
|
31
136
|
- Modify specs without updating PROJECT_STATE.md
|
|
32
137
|
- Commit code without corresponding spec entry
|
|
138
|
+
- Break the verify loop by ignoring test failures
|
|
139
|
+
- Modify tests to make them pass without discussion
|
|
33
140
|
|
|
34
|
-
##
|
|
35
|
-
|
|
36
|
-
-
|
|
37
|
-
|
|
141
|
+
## File Organization
|
|
142
|
+
|
|
143
|
+
my-project/
|
|
144
|
+
├── specs/
|
|
145
|
+
│ ├── drafts/ # PRD stage specs
|
|
146
|
+
│ ├── active/ # In-progress specs
|
|
147
|
+
│ ├── archive/ # Completed specs
|
|
148
|
+
│ └── exploration/ # Research notes
|
|
149
|
+
├── src/
|
|
150
|
+
│ └── __tests__/ # Test files organized by spec
|
|
151
|
+
├── PROJECT_STATE.md # Central status tracker
|
|
152
|
+
└── specsafe.config.json # Tool configuration
|
|
153
|
+
|
|
154
|
+
## Commit Message Format
|
|
155
|
+
|
|
156
|
+
type(SPEC-ID): brief description
|
|
157
|
+
|
|
158
|
+
- Detailed change 1
|
|
159
|
+
- Detailed change 2
|
|
160
|
+
|
|
161
|
+
Refs: SPEC-ID
|
|
162
|
+
|
|
163
|
+
Types: feat, fix, test, docs, refactor, chore
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
*Version: 0.4.0*
|
|
167
|
+
*OpenSpec-Style Workflow Enabled*
|
|
38
168
|
`;
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
name: 'specsafe',
|
|
43
|
-
description: 'Show current SpecSafe status',
|
|
44
|
-
prompt: 'Read PROJECT_STATE.md and show me the current active specs, their stages, and what needs to be done next.',
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
name: 'spec',
|
|
48
|
-
description: 'Show details for a specific spec',
|
|
49
|
-
prompt: 'Read the spec file for {{input}} from specs/active/ and show me its requirements, scenarios, and current stage.',
|
|
50
|
-
},
|
|
51
|
-
],
|
|
52
|
-
contextProviders: [
|
|
53
|
-
{
|
|
54
|
-
name: 'specsafe-state',
|
|
55
|
-
params: {
|
|
56
|
-
file: 'PROJECT_STATE.md',
|
|
57
|
-
},
|
|
58
|
-
},
|
|
59
|
-
],
|
|
60
|
-
};
|
|
61
|
-
const aiderConfigContent = `# Aider configuration for SpecSafe projects
|
|
169
|
+
const aiderConfigContent = `# Aider configuration for SpecSafe v0.4.0
|
|
170
|
+
# OpenSpec-Style Workflow Configuration
|
|
171
|
+
# https://aider.chat/docs/config/aider_conf.html
|
|
62
172
|
|
|
63
173
|
# Always read PROJECT_STATE.md for context
|
|
64
174
|
read:
|
|
65
175
|
- PROJECT_STATE.md
|
|
176
|
+
- README.md
|
|
177
|
+
- CONVENTIONS.md
|
|
66
178
|
|
|
67
|
-
#
|
|
179
|
+
# Use .aiderignore for file exclusions (gitignore syntax)
|
|
180
|
+
aiderignore: .aiderignore
|
|
181
|
+
|
|
182
|
+
# Don't add .gitignore'd files to aider's scope
|
|
183
|
+
add-gitignore-files: false
|
|
184
|
+
|
|
185
|
+
# AI Assistant Instructions for SpecSafe Workflow
|
|
68
186
|
assistant_prompt: |
|
|
69
|
-
You are working on a SpecSafe project.
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
-
|
|
78
|
-
-
|
|
79
|
-
-
|
|
80
|
-
-
|
|
187
|
+
You are working on a SpecSafe project using spec-driven development (SDD).
|
|
188
|
+
|
|
189
|
+
## The 7 OpenSpec-Style Commands
|
|
190
|
+
|
|
191
|
+
When the user invokes a command, follow the corresponding workflow:
|
|
192
|
+
|
|
193
|
+
### /specsafe:explore — Pre-Spec Exploration
|
|
194
|
+
- Guide problem definition and user research
|
|
195
|
+
- Evaluate technology options with pros/cons
|
|
196
|
+
- Estimate effort (S/M/L/XL)
|
|
197
|
+
- Document in specs/exploration/FEATURE-NAME.md
|
|
198
|
+
- Recommend proceed, research more, or park idea
|
|
199
|
+
|
|
200
|
+
### /specsafe:new — Initialize Spec with PRD
|
|
201
|
+
- Generate spec ID: SPEC-YYYYMMDD-NNN format
|
|
202
|
+
- Create PRD with problem statement, requirements, scenarios
|
|
203
|
+
- Recommend tech stack and define rules
|
|
204
|
+
- Output to specs/drafts/SPEC-ID.md
|
|
205
|
+
- Update PROJECT_STATE.md (status: DRAFT)
|
|
206
|
+
- Confirm details with user before writing
|
|
207
|
+
|
|
208
|
+
### /specsafe:spec — Generate Detailed Spec
|
|
209
|
+
- Read PRD from specs/drafts/SPEC-ID.md
|
|
210
|
+
- Create comprehensive spec:
|
|
211
|
+
* Functional Requirements (FR-001, FR-002...)
|
|
212
|
+
* Technical Requirements (TR-001, TR-002...)
|
|
213
|
+
* Scenarios (Given/When/Then)
|
|
214
|
+
* Acceptance Criteria
|
|
215
|
+
* Architecture Notes
|
|
216
|
+
- Write to specs/active/SPEC-ID.md
|
|
217
|
+
- Update PROJECT_STATE.md: DRAFT → SPEC
|
|
218
|
+
- Ensure every requirement is testable
|
|
219
|
+
|
|
220
|
+
### /specsafe:test-create — Create Tests from Spec
|
|
221
|
+
- Read spec scenarios from specs/active/SPEC-ID.md
|
|
222
|
+
- Generate test files: src/__tests__/SPEC-ID/*.test.ts
|
|
223
|
+
- Map Given/When/Then to test cases
|
|
224
|
+
- Include happy path and edge cases
|
|
225
|
+
- Update PROJECT_STATE.md: SPEC → TEST-CREATE
|
|
226
|
+
- Report test count and coverage expectations
|
|
227
|
+
|
|
228
|
+
### /specsafe:test-apply — Apply Tests (Development Mode)
|
|
229
|
+
- Read spec requirements and test expectations
|
|
230
|
+
- Implement one requirement at a time
|
|
231
|
+
- Follow cycle: Plan → Implement → Test → Commit
|
|
232
|
+
- Map every code change to requirement ID
|
|
233
|
+
- Never modify tests to make them pass
|
|
234
|
+
- Update PROJECT_STATE.md: TEST-CREATE → TEST-APPLY
|
|
235
|
+
- Ask: "Which requirement next?"
|
|
236
|
+
|
|
237
|
+
### /specsafe:verify — Verify and Iterate
|
|
238
|
+
- Run test suite: npm test -- SPEC-ID
|
|
239
|
+
- For each failure: identify, map to requirement, fix
|
|
240
|
+
- Golden rule: Fix code, not tests (unless confirmed wrong)
|
|
241
|
+
- Iterate until all tests pass
|
|
242
|
+
- Check coverage meets requirements
|
|
243
|
+
- Run full suite for regressions
|
|
244
|
+
- Update PROJECT_STATE.md: TEST-APPLY → VERIFY
|
|
245
|
+
- Report: pass rate, coverage %, issues
|
|
246
|
+
|
|
247
|
+
### /specsafe:done — Complete and Archive
|
|
248
|
+
- Verify completion checklist
|
|
249
|
+
- Run final test suite
|
|
250
|
+
- Move specs/active/SPEC-ID.md → specs/archive/SPEC-ID.md
|
|
251
|
+
- Update PROJECT_STATE.md: move to COMPLETED
|
|
252
|
+
- Generate completion summary
|
|
253
|
+
- Suggest next spec from active list
|
|
254
|
+
- Ask for confirmation before archiving
|
|
255
|
+
|
|
256
|
+
## Critical Rules
|
|
257
|
+
|
|
258
|
+
ALWAYS:
|
|
259
|
+
- Check PROJECT_STATE.md before making changes
|
|
260
|
+
- Ensure implementation satisfies tests
|
|
261
|
+
- Use spec ID in commit messages: feat(SPEC-001): description
|
|
262
|
+
- Run tests before marking work complete
|
|
263
|
+
- Fix the code, not the test
|
|
264
|
+
|
|
265
|
+
NEVER:
|
|
266
|
+
- Skip tests to implement faster
|
|
267
|
+
- Modify PROJECT_STATE.md directly (use workflow commands)
|
|
268
|
+
- Break the verify loop by ignoring failures
|
|
269
|
+
- Modify tests without discussion
|
|
270
|
+
- Commit code without spec reference
|
|
271
|
+
|
|
272
|
+
## Workflow Diagram
|
|
273
|
+
|
|
274
|
+
EXPLORE → NEW → SPEC → TEST-CREATE → TEST-APPLY → VERIFY → DONE
|
|
275
|
+
|
|
276
|
+
# Commit message conventions
|
|
277
|
+
commit-prompt: |
|
|
278
|
+
Format: type(SPEC-ID): brief description
|
|
279
|
+
|
|
280
|
+
Types: feat, fix, test, docs, refactor, chore
|
|
281
|
+
Example: feat(SPEC-001): add user authentication
|
|
282
|
+
|
|
283
|
+
Always reference the spec ID in commits.
|
|
284
|
+
`;
|
|
285
|
+
const aiderIgnoreContent = `# Aider ignore patterns for SpecSafe projects
|
|
286
|
+
|
|
287
|
+
# Spec archives (read-only reference)
|
|
288
|
+
specs/archive/
|
|
289
|
+
|
|
290
|
+
# Dependencies
|
|
291
|
+
node_modules/
|
|
292
|
+
vendor/
|
|
293
|
+
|
|
294
|
+
# Build outputs
|
|
295
|
+
dist/
|
|
296
|
+
build/
|
|
297
|
+
*.min.js
|
|
298
|
+
*.min.css
|
|
299
|
+
|
|
300
|
+
# Generated files
|
|
301
|
+
*.generated.ts
|
|
302
|
+
*.generated.js
|
|
303
|
+
|
|
304
|
+
# Logs
|
|
305
|
+
*.log
|
|
306
|
+
logs/
|
|
307
|
+
|
|
308
|
+
# Coverage reports
|
|
309
|
+
coverage/
|
|
310
|
+
.nyc_output/
|
|
311
|
+
|
|
312
|
+
# IDE files
|
|
313
|
+
.vscode/
|
|
314
|
+
.idea/
|
|
315
|
+
*.swp
|
|
316
|
+
*.swo
|
|
317
|
+
|
|
318
|
+
# OS files
|
|
319
|
+
.DS_Store
|
|
320
|
+
Thumbs.db
|
|
321
|
+
|
|
322
|
+
# Test outputs
|
|
323
|
+
test-results/
|
|
324
|
+
playwright-report/
|
|
81
325
|
`;
|
|
82
326
|
const zedSettingsContent = {
|
|
327
|
+
name: "specsafe-zed",
|
|
328
|
+
version: "0.4.0",
|
|
329
|
+
description: "SpecSafe v0.4.0 OpenSpec-Style Workflow for Zed Editor",
|
|
83
330
|
assistant: {
|
|
84
331
|
default_model: {
|
|
85
|
-
provider:
|
|
86
|
-
model:
|
|
332
|
+
provider: "anthropic",
|
|
333
|
+
model: "claude-3-5-sonnet-latest"
|
|
87
334
|
},
|
|
88
|
-
version:
|
|
335
|
+
version: "2"
|
|
89
336
|
},
|
|
90
337
|
context_servers: {
|
|
91
338
|
specsafe: {
|
|
92
|
-
command:
|
|
93
|
-
|
|
339
|
+
command: ["cat", "PROJECT_STATE.md"]
|
|
340
|
+
}
|
|
341
|
+
},
|
|
342
|
+
lsp: {
|
|
343
|
+
specsafe: {
|
|
344
|
+
command: "specsafe",
|
|
345
|
+
args: ["status", "--json"]
|
|
346
|
+
}
|
|
347
|
+
},
|
|
348
|
+
agent: {
|
|
349
|
+
name: "SpecSafe",
|
|
350
|
+
description: "Spec-driven development assistant for OpenSpec-style workflow",
|
|
351
|
+
context: {
|
|
352
|
+
files: [
|
|
353
|
+
"PROJECT_STATE.md",
|
|
354
|
+
"specsafe.config.json"
|
|
355
|
+
],
|
|
356
|
+
directories: [
|
|
357
|
+
"specs/active",
|
|
358
|
+
"specs/drafts"
|
|
359
|
+
]
|
|
360
|
+
},
|
|
361
|
+
commands: {
|
|
362
|
+
"specsafe:explore": {
|
|
363
|
+
description: "Pre-spec exploration and research",
|
|
364
|
+
prompt: "Conduct preliminary exploration before committing to a full spec. Guide problem definition, research technology options, estimate effort, and document findings in specs/exploration/FEATURE-NAME.md. Recommend proceed to spec creation or need more research.",
|
|
365
|
+
context: ["PROJECT_STATE.md"]
|
|
366
|
+
},
|
|
367
|
+
"specsafe:new": {
|
|
368
|
+
description: "Initialize spec with PRD",
|
|
369
|
+
prompt: "Create a new spec with Product Requirements Document. Generate spec ID (SPEC-YYYYMMDD-NNN), create PRD with problem statement, requirements, scenarios, recommend tech stack, and define rules. Output to specs/drafts/SPEC-ID.md and update PROJECT_STATE.md (status: DRAFT). Confirm with user before writing.",
|
|
370
|
+
context: ["PROJECT_STATE.md"]
|
|
371
|
+
},
|
|
372
|
+
"specsafe:spec": {
|
|
373
|
+
description: "Generate detailed spec from PRD",
|
|
374
|
+
prompt: "Read PRD from specs/drafts/SPEC-ID.md and create comprehensive implementation-ready specification. Include functional requirements (FR-XXX), technical requirements (TR-XXX), Given/When/Then scenarios, acceptance criteria, and architecture notes. Write to specs/active/SPEC-ID.md and update PROJECT_STATE.md (DRAFT → SPEC).",
|
|
375
|
+
context: ["PROJECT_STATE.md", "specs/drafts/*.md"]
|
|
376
|
+
},
|
|
377
|
+
"specsafe:test-create": {
|
|
378
|
+
description: "Create tests from spec scenarios",
|
|
379
|
+
prompt: "Read spec from specs/active/SPEC-ID.md and generate comprehensive test suite. Create test files in src/__tests__/SPEC-ID/ mapping Given/When/Then to test cases. Include happy path and edge cases. Update PROJECT_STATE.md (SPEC → TEST-CREATE) and report test count.",
|
|
380
|
+
context: ["PROJECT_STATE.md", "specs/active/*.md"]
|
|
381
|
+
},
|
|
382
|
+
"specsafe:test-apply": {
|
|
383
|
+
description: "Apply tests (development mode for active spec)",
|
|
384
|
+
prompt: "Guide implementation for active spec. Read requirements and tests, implement one requirement at a time following Plan → Implement → Test → Commit cycle. Map changes to requirement IDs. Never modify tests to make them pass. Update PROJECT_STATE.md (TEST-CREATE → TEST-APPLY). Ask which requirement to tackle next.",
|
|
385
|
+
context: ["PROJECT_STATE.md", "specs/active/*.md", "src/__tests__/**/*.test.ts"]
|
|
386
|
+
},
|
|
387
|
+
"specsafe:verify": {
|
|
388
|
+
description: "Run tests and iterate until pass",
|
|
389
|
+
prompt: "Verify implementation by running test suite. Execute npm test -- SPEC-ID, analyze failures, map to requirements, and fix code (not tests). Iterate until all pass. Check coverage, run full suite for regressions. Update PROJECT_STATE.md (TEST-APPLY → VERIFY). Report pass rate, coverage %, and any issues.",
|
|
390
|
+
context: ["PROJECT_STATE.md", "specs/active/*.md", "src/__tests__/**/*.test.ts"]
|
|
391
|
+
},
|
|
392
|
+
"specsafe:done": {
|
|
393
|
+
description: "Complete and archive spec",
|
|
394
|
+
prompt: "Finalize spec after all tests pass. Verify completion checklist, run final test suite, move specs/active/SPEC-ID.md to specs/archive/SPEC-ID.md. Update PROJECT_STATE.md (VERIFY → COMPLETE). Generate completion summary and suggest next spec. Ask for confirmation before archiving.",
|
|
395
|
+
context: ["PROJECT_STATE.md", "specs/active/*.md"]
|
|
396
|
+
},
|
|
397
|
+
specsafe: {
|
|
398
|
+
description: "Show project status",
|
|
399
|
+
prompt: "Read PROJECT_STATE.md and show current active specs, their stages, what needs attention, and recommended next actions. Provide brief SDD workflow reminder (EXPLORE → NEW → SPEC → TEST-CREATE → TEST-APPLY → VERIFY → DONE).",
|
|
400
|
+
context: ["PROJECT_STATE.md"]
|
|
401
|
+
}
|
|
402
|
+
},
|
|
403
|
+
rules: {
|
|
404
|
+
always: [
|
|
405
|
+
"Read PROJECT_STATE.md before making changes",
|
|
406
|
+
"Ensure implementation satisfies tests",
|
|
407
|
+
"Use spec ID in commit messages: type(SPEC-XXX): description",
|
|
408
|
+
"Run tests before marking work complete"
|
|
409
|
+
],
|
|
410
|
+
never: [
|
|
411
|
+
"Skip tests to implement faster",
|
|
412
|
+
"Modify PROJECT_STATE.md directly (use commands)",
|
|
413
|
+
"Break verify loop by ignoring failures",
|
|
414
|
+
"Modify tests without discussion",
|
|
415
|
+
"Commit code without spec reference"
|
|
416
|
+
]
|
|
94
417
|
},
|
|
418
|
+
workflow: {
|
|
419
|
+
stages: ["EXPLORE", "NEW", "SPEC", "TEST-CREATE", "TEST-APPLY", "VERIFY", "COMPLETE"],
|
|
420
|
+
transitions: {
|
|
421
|
+
EXPLORE: ["NEW"],
|
|
422
|
+
NEW: ["SPEC"],
|
|
423
|
+
SPEC: ["TEST-CREATE"],
|
|
424
|
+
"TEST-CREATE": ["TEST-APPLY"],
|
|
425
|
+
"TEST-APPLY": ["VERIFY"],
|
|
426
|
+
VERIFY: ["COMPLETE", "TEST-APPLY"],
|
|
427
|
+
COMPLETE: []
|
|
428
|
+
}
|
|
429
|
+
}
|
|
95
430
|
},
|
|
431
|
+
file_types: {
|
|
432
|
+
"SpecSafe Spec": {
|
|
433
|
+
path_suffixes: [".specsafe.md"],
|
|
434
|
+
grammar: "markdown"
|
|
435
|
+
}
|
|
436
|
+
}
|
|
96
437
|
};
|
|
438
|
+
// Skill content for Claude Code slash commands
|
|
439
|
+
const claudeSkillSpecsafeContent = `---
|
|
440
|
+
name: specsafe
|
|
441
|
+
description: Show SpecSafe project status and workflow guidance
|
|
442
|
+
disable-model-invocation: true
|
|
443
|
+
---
|
|
444
|
+
|
|
445
|
+
You are in a SpecSafe project using spec-driven development.
|
|
446
|
+
|
|
447
|
+
Read PROJECT_STATE.md and provide:
|
|
448
|
+
1. Summary of active specs and their current stages
|
|
449
|
+
2. Which specs need attention
|
|
450
|
+
3. Recommended next actions based on the project state
|
|
451
|
+
4. Brief reminder of the SDD workflow (EXPLORE → NEW → SPEC → TEST-CREATE → TEST-APPLY → VERIFY → DONE)
|
|
452
|
+
`;
|
|
453
|
+
const claudeSkillExploreContent = `---
|
|
454
|
+
name: specsafe-explore
|
|
455
|
+
description: Pre-spec exploration and research mode
|
|
456
|
+
argument-hint: "[feature-name]"
|
|
457
|
+
disable-model-invocation: true
|
|
458
|
+
---
|
|
459
|
+
|
|
460
|
+
You are in exploration mode. Guide the user through pre-spec research.
|
|
461
|
+
|
|
462
|
+
**Activities:**
|
|
463
|
+
- Define the problem and identify target users
|
|
464
|
+
- Research existing solutions and competitors
|
|
465
|
+
- Evaluate technology options with pros/cons
|
|
466
|
+
- Estimate effort (S/M/L/XL)
|
|
467
|
+
- Document risks and constraints
|
|
468
|
+
|
|
469
|
+
**Output:** Create specs/exploration/{feature-name}.md with findings.
|
|
470
|
+
|
|
471
|
+
**Decision Gate:** Recommend proceeding to /specsafe:new or gathering more information.
|
|
472
|
+
`;
|
|
473
|
+
const claudeSkillNewContent = `---
|
|
474
|
+
name: specsafe-new
|
|
475
|
+
description: Initialize spec with PRD
|
|
476
|
+
argument-hint: "[feature-name]"
|
|
477
|
+
disable-model-invocation: true
|
|
478
|
+
---
|
|
479
|
+
|
|
480
|
+
Create a new spec with Product Requirements Document.
|
|
481
|
+
|
|
482
|
+
**Steps:**
|
|
483
|
+
1. Generate spec ID: SPEC-YYYYMMDD-NNN
|
|
484
|
+
2. Create PRD with problem statement, requirements, scenarios
|
|
485
|
+
3. Recommend tech stack and define rules
|
|
486
|
+
4. Output to specs/drafts/SPEC-ID.md
|
|
487
|
+
5. Update PROJECT_STATE.md (status: DRAFT)
|
|
488
|
+
|
|
489
|
+
Always confirm with user before writing files.
|
|
490
|
+
`;
|
|
491
|
+
const claudeSkillSpecContent = `---
|
|
492
|
+
name: specsafe-spec
|
|
493
|
+
description: Generate detailed spec from PRD
|
|
494
|
+
argument-hint: "[spec-id]"
|
|
495
|
+
disable-model-invocation: true
|
|
496
|
+
---
|
|
497
|
+
|
|
498
|
+
Read PRD from specs/drafts/$ARGUMENTS.md and create comprehensive specification.
|
|
499
|
+
|
|
500
|
+
**Include:**
|
|
501
|
+
- Functional Requirements (FR-001, FR-002...)
|
|
502
|
+
- Technical Requirements (TR-001, TR-002...)
|
|
503
|
+
- Scenarios (Given/When/Then)
|
|
504
|
+
- Acceptance Criteria
|
|
505
|
+
- Architecture Notes
|
|
506
|
+
|
|
507
|
+
Move to specs/active/SPEC-ID.md and update PROJECT_STATE.md (DRAFT → SPEC).
|
|
508
|
+
|
|
509
|
+
If no argument provided, list available drafts.
|
|
510
|
+
`;
|
|
511
|
+
const claudeSkillTestCreateContent = `---
|
|
512
|
+
name: specsafe-test-create
|
|
513
|
+
description: Create tests from spec scenarios
|
|
514
|
+
argument-hint: "[spec-id]"
|
|
515
|
+
disable-model-invocation: true
|
|
516
|
+
---
|
|
517
|
+
|
|
518
|
+
Generate comprehensive test suite from the active spec.
|
|
519
|
+
|
|
520
|
+
**Process:**
|
|
521
|
+
1. Read spec from specs/active/$ARGUMENTS.md
|
|
522
|
+
2. Generate test files in src/__tests__/$ARGUMENTS/
|
|
523
|
+
3. Map Given/When/Then to test cases
|
|
524
|
+
4. Include happy path and edge cases
|
|
525
|
+
5. Update PROJECT_STATE.md (SPEC → TEST-CREATE)
|
|
526
|
+
|
|
527
|
+
Report test count and coverage expectations.
|
|
528
|
+
`;
|
|
529
|
+
const claudeSkillTestApplyContent = `---
|
|
530
|
+
name: specsafe-test-apply
|
|
531
|
+
description: Apply tests - development mode to pass tests
|
|
532
|
+
argument-hint: "[spec-id]"
|
|
533
|
+
disable-model-invocation: true
|
|
534
|
+
---
|
|
535
|
+
|
|
536
|
+
Guide implementation for active spec.
|
|
537
|
+
|
|
538
|
+
**Development Cycle:**
|
|
539
|
+
1. Plan - Identify smallest slice of functionality
|
|
540
|
+
2. Implement - Write code for one requirement at a time
|
|
541
|
+
3. Test - Run tests, fix failures
|
|
542
|
+
4. Commit - Small commits with spec reference
|
|
543
|
+
|
|
544
|
+
**Rules:**
|
|
545
|
+
- Never modify tests to make them pass (fix the code)
|
|
546
|
+
- Map every change to a requirement ID
|
|
547
|
+
- Update PROJECT_STATE.md (TEST-CREATE → TEST-APPLY)
|
|
548
|
+
|
|
549
|
+
Ask: "Which requirement should we tackle next?"
|
|
550
|
+
`;
|
|
551
|
+
const claudeSkillVerifyContent = `---
|
|
552
|
+
name: specsafe-verify
|
|
553
|
+
description: Verify implementation by running tests
|
|
554
|
+
argument-hint: "[spec-id]"
|
|
555
|
+
disable-model-invocation: true
|
|
556
|
+
---
|
|
557
|
+
|
|
558
|
+
Run tests and iterate until implementation is correct.
|
|
559
|
+
|
|
560
|
+
**Process:**
|
|
561
|
+
1. Execute test suite: npm test -- $ARGUMENTS
|
|
562
|
+
2. Analyze failures and map to requirements
|
|
563
|
+
3. Fix code (not tests) and re-run
|
|
564
|
+
4. Iterate until all pass
|
|
565
|
+
5. Check coverage and run full suite for regressions
|
|
566
|
+
|
|
567
|
+
Update PROJECT_STATE.md (TEST-APPLY → VERIFY).
|
|
568
|
+
Report pass rate, coverage %, and any issues.
|
|
569
|
+
`;
|
|
570
|
+
const claudeSkillDoneContent = `---
|
|
571
|
+
name: specsafe-done
|
|
572
|
+
description: Complete and archive spec
|
|
573
|
+
argument-hint: "[spec-id]"
|
|
574
|
+
disable-model-invocation: true
|
|
575
|
+
---
|
|
576
|
+
|
|
577
|
+
Finalize spec after all tests pass.
|
|
578
|
+
|
|
579
|
+
**Completion Checklist:**
|
|
580
|
+
- [ ] All requirements implemented
|
|
581
|
+
- [ ] All tests passing
|
|
582
|
+
- [ ] Code reviewed (if required)
|
|
583
|
+
- [ ] Documentation updated
|
|
584
|
+
- [ ] No TODO/debug code
|
|
585
|
+
|
|
586
|
+
**Archive:**
|
|
587
|
+
- Move specs/active/$ARGUMENTS.md → specs/archive/$ARGUMENTS.md
|
|
588
|
+
- Update PROJECT_STATE.md (VERIFY → COMPLETE)
|
|
589
|
+
- Generate completion summary
|
|
590
|
+
|
|
591
|
+
Ask for confirmation before archiving.
|
|
592
|
+
`;
|
|
593
|
+
const claudeSkillValidateContent = `---
|
|
594
|
+
name: specsafe-validate
|
|
595
|
+
description: Validate current implementation against active spec
|
|
596
|
+
disable-model-invocation: true
|
|
597
|
+
---
|
|
598
|
+
|
|
599
|
+
Check if the current code changes satisfy the requirements in the active spec.
|
|
600
|
+
Point out any gaps or issues that need to be addressed before completing.
|
|
601
|
+
`;
|
|
97
602
|
/**
|
|
98
603
|
* Generate configuration for a specific tool
|
|
99
|
-
* @param tool - The tool name (cursor, continue, aider, zed, claude-code, crush)
|
|
604
|
+
* @param tool - The tool name (cursor, continue, aider, zed, claude-code, crush, git-hooks)
|
|
100
605
|
* @param projectDir - The project directory path
|
|
101
606
|
*/
|
|
102
607
|
export async function generateToolConfig(tool, projectDir = '.') {
|
|
@@ -119,6 +624,9 @@ export async function generateToolConfig(tool, projectDir = '.') {
|
|
|
119
624
|
case 'crush':
|
|
120
625
|
await generateCrushConfig(projectDir);
|
|
121
626
|
break;
|
|
627
|
+
case 'git-hooks':
|
|
628
|
+
await generateGitHooks(projectDir);
|
|
629
|
+
break;
|
|
122
630
|
default:
|
|
123
631
|
throw new Error(`Unknown tool: ${tool}`);
|
|
124
632
|
}
|
|
@@ -130,26 +638,213 @@ async function generateCursorConfig(projectDir) {
|
|
|
130
638
|
return;
|
|
131
639
|
}
|
|
132
640
|
await writeFile(configPath, cursorRulesContent);
|
|
641
|
+
console.log(chalk.green('✓ Created .cursorrules'));
|
|
133
642
|
}
|
|
134
643
|
async function generateContinueConfig(projectDir) {
|
|
135
644
|
const configDir = `${projectDir}/.continue`;
|
|
136
|
-
const
|
|
645
|
+
const promptsDir = `${configDir}/prompts`;
|
|
137
646
|
if (!existsSync(configDir)) {
|
|
138
647
|
await mkdir(configDir, { recursive: true });
|
|
139
648
|
}
|
|
140
|
-
if (existsSync(
|
|
141
|
-
|
|
142
|
-
|
|
649
|
+
if (!existsSync(promptsDir)) {
|
|
650
|
+
await mkdir(promptsDir, { recursive: true });
|
|
651
|
+
}
|
|
652
|
+
// Create config.yaml
|
|
653
|
+
const configPath = `${configDir}/config.yaml`;
|
|
654
|
+
if (!existsSync(configPath)) {
|
|
655
|
+
const continueConfigContent = `# Continue.dev configuration for SpecSafe v0.4.0
|
|
656
|
+
# Generated by SpecSafe
|
|
657
|
+
|
|
658
|
+
name: SpecSafe
|
|
659
|
+
version: 0.4.0
|
|
660
|
+
schema: v1
|
|
661
|
+
|
|
662
|
+
prompts:
|
|
663
|
+
- uses: file://prompts/specsafe.md
|
|
664
|
+
- uses: file://prompts/spec.md
|
|
665
|
+
- uses: file://prompts/validate.md
|
|
666
|
+
- uses: file://prompts/specsafe-explore.md
|
|
667
|
+
- uses: file://prompts/specsafe-new.md
|
|
668
|
+
- uses: file://prompts/specsafe-spec.md
|
|
669
|
+
- uses: file://prompts/specsafe-test-create.md
|
|
670
|
+
- uses: file://prompts/specsafe-test-apply.md
|
|
671
|
+
- uses: file://prompts/specsafe-verify.md
|
|
672
|
+
- uses: file://prompts/specsafe-done.md
|
|
673
|
+
|
|
674
|
+
context:
|
|
675
|
+
include:
|
|
676
|
+
- PROJECT_STATE.md
|
|
677
|
+
- specs/active/*.md
|
|
678
|
+
- specs/drafts/*.md
|
|
679
|
+
`;
|
|
680
|
+
await writeFile(configPath, continueConfigContent);
|
|
681
|
+
console.log(chalk.green('✓ Created .continue/config.yaml'));
|
|
682
|
+
}
|
|
683
|
+
else {
|
|
684
|
+
console.log(chalk.yellow('⚠ .continue/config.yaml already exists, skipping'));
|
|
685
|
+
}
|
|
686
|
+
// Create basic prompt files
|
|
687
|
+
const promptFiles = {
|
|
688
|
+
'specsafe.md': `---
|
|
689
|
+
name: specsafe
|
|
690
|
+
description: Show SpecSafe project status
|
|
691
|
+
invokable: true
|
|
692
|
+
---
|
|
693
|
+
|
|
694
|
+
Read PROJECT_STATE.md and summarize:
|
|
695
|
+
1) Active specs and their stages
|
|
696
|
+
2) What spec is currently being worked on
|
|
697
|
+
3) What the next steps should be
|
|
698
|
+
`,
|
|
699
|
+
'spec.md': `---
|
|
700
|
+
name: spec
|
|
701
|
+
description: Show details for a specific spec
|
|
702
|
+
invokable: true
|
|
703
|
+
---
|
|
704
|
+
|
|
705
|
+
Read the spec file for {{input}} from specs/active/ and show its requirements, scenarios, and current stage.
|
|
706
|
+
`,
|
|
707
|
+
'validate.md': `---
|
|
708
|
+
name: validate
|
|
709
|
+
description: Validate implementation against spec
|
|
710
|
+
invokable: true
|
|
711
|
+
---
|
|
712
|
+
|
|
713
|
+
Check if the current implementation satisfies the active spec requirements.
|
|
714
|
+
`,
|
|
715
|
+
'specsafe-explore.md': `---
|
|
716
|
+
name: specsafe-explore
|
|
717
|
+
description: Pre-Spec Exploration
|
|
718
|
+
invokable: true
|
|
719
|
+
---
|
|
720
|
+
|
|
721
|
+
You are in exploration mode. Guide pre-spec research:
|
|
722
|
+
- Define problem and identify users
|
|
723
|
+
- Research existing solutions
|
|
724
|
+
- Evaluate technology options
|
|
725
|
+
- Estimate effort (S/M/L/XL)
|
|
726
|
+
|
|
727
|
+
Output: specs/exploration/FEATURE-NAME.md
|
|
728
|
+
`,
|
|
729
|
+
'specsafe-new.md': `---
|
|
730
|
+
name: specsafe-new
|
|
731
|
+
description: Initialize Spec with PRD
|
|
732
|
+
invokable: true
|
|
733
|
+
---
|
|
734
|
+
|
|
735
|
+
Create a new spec:
|
|
736
|
+
1. Generate spec ID: SPEC-YYYYMMDD-NNN
|
|
737
|
+
2. Create PRD with requirements and scenarios
|
|
738
|
+
3. Recommend tech stack
|
|
739
|
+
4. Output: specs/drafts/SPEC-ID.md
|
|
740
|
+
5. Update PROJECT_STATE.md (status: DRAFT)
|
|
741
|
+
|
|
742
|
+
Confirm before writing.
|
|
743
|
+
`,
|
|
744
|
+
'specsafe-spec.md': `---
|
|
745
|
+
name: specsafe-spec
|
|
746
|
+
description: Generate Detailed Spec
|
|
747
|
+
invokable: true
|
|
748
|
+
---
|
|
749
|
+
|
|
750
|
+
Convert PRD to comprehensive spec:
|
|
751
|
+
- Functional Requirements (FR-XXX)
|
|
752
|
+
- Technical Requirements (TR-XXX)
|
|
753
|
+
- Scenarios (Given/When/Then)
|
|
754
|
+
- Acceptance Criteria
|
|
755
|
+
- Architecture Notes
|
|
756
|
+
|
|
757
|
+
Move: specs/drafts/ → specs/active/
|
|
758
|
+
Update: PROJECT_STATE.md (DRAFT → SPEC)
|
|
759
|
+
`,
|
|
760
|
+
'specsafe-test-create.md': `---
|
|
761
|
+
name: specsafe-test-create
|
|
762
|
+
description: Create Tests from Spec
|
|
763
|
+
invokable: true
|
|
764
|
+
---
|
|
765
|
+
|
|
766
|
+
Generate test suite:
|
|
767
|
+
1. Read spec scenarios
|
|
768
|
+
2. Create src/__tests__/SPEC-ID/*.test.ts
|
|
769
|
+
3. Map Given/When/Then to test cases
|
|
770
|
+
4. Include happy path and edge cases
|
|
771
|
+
5. Update PROJECT_STATE.md (SPEC → TEST-CREATE)
|
|
772
|
+
|
|
773
|
+
Report: test count and coverage
|
|
774
|
+
`,
|
|
775
|
+
'specsafe-test-apply.md': `---
|
|
776
|
+
name: specsafe-test-apply
|
|
777
|
+
description: Apply Tests (Development Mode)
|
|
778
|
+
invokable: true
|
|
779
|
+
---
|
|
780
|
+
|
|
781
|
+
Guide implementation:
|
|
782
|
+
- Plan → Implement → Test → Commit
|
|
783
|
+
- Map changes to requirement IDs
|
|
784
|
+
- Never modify tests to pass (fix code)
|
|
785
|
+
- Update PROJECT_STATE.md (TEST-CREATE → TEST-APPLY)
|
|
786
|
+
|
|
787
|
+
Ask: "Which requirement next?"
|
|
788
|
+
`,
|
|
789
|
+
'specsafe-verify.md': `---
|
|
790
|
+
name: specsafe-verify
|
|
791
|
+
description: Verify and Iterate
|
|
792
|
+
invokable: true
|
|
793
|
+
---
|
|
794
|
+
|
|
795
|
+
Run tests and fix failures:
|
|
796
|
+
1. Execute: npm test -- SPEC-ID
|
|
797
|
+
2. Map failures to requirements
|
|
798
|
+
3. Fix code (not tests)
|
|
799
|
+
4. Iterate until all pass
|
|
800
|
+
5. Check coverage
|
|
801
|
+
|
|
802
|
+
Update PROJECT_STATE.md (TEST-APPLY → VERIFY)
|
|
803
|
+
`,
|
|
804
|
+
'specsafe-done.md': `---
|
|
805
|
+
name: specsafe-done
|
|
806
|
+
description: Complete and Archive
|
|
807
|
+
invokable: true
|
|
808
|
+
---
|
|
809
|
+
|
|
810
|
+
Finalize spec:
|
|
811
|
+
- Verify completion checklist
|
|
812
|
+
- Run final test suite
|
|
813
|
+
- Move: specs/active/ → specs/archive/
|
|
814
|
+
- Update PROJECT_STATE.md (VERIFY → COMPLETE)
|
|
815
|
+
- Generate summary
|
|
816
|
+
|
|
817
|
+
Confirm before archiving.
|
|
818
|
+
`
|
|
819
|
+
};
|
|
820
|
+
for (const [filename, content] of Object.entries(promptFiles)) {
|
|
821
|
+
const targetPath = `${promptsDir}/${filename}`;
|
|
822
|
+
if (!existsSync(targetPath)) {
|
|
823
|
+
await writeFile(targetPath, content);
|
|
824
|
+
console.log(chalk.green(`✓ Created .continue/prompts/${filename}`));
|
|
825
|
+
}
|
|
826
|
+
else {
|
|
827
|
+
console.log(chalk.yellow(`⚠ .continue/prompts/${filename} already exists, skipping`));
|
|
828
|
+
}
|
|
143
829
|
}
|
|
144
|
-
await writeFile(configPath, JSON.stringify(continueConfigContent, null, 2));
|
|
145
830
|
}
|
|
146
831
|
async function generateAiderConfig(projectDir) {
|
|
147
832
|
const configPath = `${projectDir}/.aider.conf.yml`;
|
|
833
|
+
const ignorePath = `${projectDir}/.aiderignore`;
|
|
148
834
|
if (existsSync(configPath)) {
|
|
149
835
|
console.log(chalk.yellow('⚠ .aider.conf.yml already exists, skipping'));
|
|
150
|
-
return;
|
|
151
836
|
}
|
|
152
|
-
|
|
837
|
+
else {
|
|
838
|
+
await writeFile(configPath, aiderConfigContent);
|
|
839
|
+
console.log(chalk.green('✓ Created .aider.conf.yml'));
|
|
840
|
+
}
|
|
841
|
+
if (existsSync(ignorePath)) {
|
|
842
|
+
console.log(chalk.yellow('⚠ .aiderignore already exists, skipping'));
|
|
843
|
+
}
|
|
844
|
+
else {
|
|
845
|
+
await writeFile(ignorePath, aiderIgnoreContent);
|
|
846
|
+
console.log(chalk.green('✓ Created .aiderignore'));
|
|
847
|
+
}
|
|
153
848
|
}
|
|
154
849
|
async function generateZedConfig(projectDir) {
|
|
155
850
|
const configDir = `${projectDir}/.zed`;
|
|
@@ -162,100 +857,71 @@ async function generateZedConfig(projectDir) {
|
|
|
162
857
|
return;
|
|
163
858
|
}
|
|
164
859
|
await writeFile(configPath, JSON.stringify(zedSettingsContent, null, 2));
|
|
860
|
+
console.log(chalk.green('✓ Created .zed/settings.json'));
|
|
165
861
|
}
|
|
166
|
-
// Skill content for Claude Code slash commands
|
|
167
|
-
const claudeSkillSpecsafeContent = `---
|
|
168
|
-
name: specsafe
|
|
169
|
-
description: Show SpecSafe project status and workflow guidance
|
|
170
|
-
disable-model-invocation: true
|
|
171
|
-
---
|
|
172
|
-
|
|
173
|
-
You are in a SpecSafe project using spec-driven development.
|
|
174
|
-
|
|
175
|
-
Read PROJECT_STATE.md and provide:
|
|
176
|
-
1. Summary of active specs and their current stages
|
|
177
|
-
2. Which specs need attention
|
|
178
|
-
3. Recommended next actions based on the project state
|
|
179
|
-
4. Brief reminder of the SDD workflow (SPEC → TEST → CODE → QA → COMPLETE)
|
|
180
|
-
`;
|
|
181
|
-
const claudeSkillSpecContent = `---
|
|
182
|
-
name: specsafe-spec
|
|
183
|
-
description: Show details for a specific spec by ID
|
|
184
|
-
argument-hint: "[spec-id]"
|
|
185
|
-
disable-model-invocation: true
|
|
186
|
-
---
|
|
187
|
-
|
|
188
|
-
Read the spec file from specs/active/$ARGUMENTS.md and show:
|
|
189
|
-
- Requirements
|
|
190
|
-
- Scenarios/acceptance criteria
|
|
191
|
-
- Current stage
|
|
192
|
-
- Implementation files referenced
|
|
193
|
-
|
|
194
|
-
If no argument provided, list available specs.
|
|
195
|
-
`;
|
|
196
|
-
const claudeSkillValidateContent = `---
|
|
197
|
-
name: specsafe-validate
|
|
198
|
-
description: Validate current implementation against active spec
|
|
199
|
-
disable-model-invocation: true
|
|
200
|
-
---
|
|
201
|
-
|
|
202
|
-
Check if the current code changes satisfy the requirements in the active spec.
|
|
203
|
-
Point out any gaps or issues that need to be addressed before completing.
|
|
204
|
-
`;
|
|
205
862
|
async function generateClaudeCodeConfig(projectDir) {
|
|
206
863
|
// Create CLAUDE.md project context file
|
|
207
864
|
const configPath = `${projectDir}/CLAUDE.md`;
|
|
208
865
|
if (!existsSync(configPath)) {
|
|
209
|
-
const claudeContent = `# SpecSafe Project
|
|
866
|
+
const claudeContent = `# SpecSafe Project - Claude Code Configuration
|
|
210
867
|
|
|
211
868
|
You are working on a SpecSafe project using spec-driven development (SDD).
|
|
212
869
|
|
|
213
870
|
## Project Context
|
|
214
871
|
|
|
215
|
-
**PROJECT_STATE.md**
|
|
872
|
+
**PROJECT_STATE.md** - Always read this file first. It contains:
|
|
216
873
|
- Active specs and their current stages
|
|
217
874
|
- Which spec is being worked on
|
|
218
875
|
- Overall project status
|
|
219
876
|
|
|
220
|
-
**Specs directory**
|
|
877
|
+
**Specs directory** - specs/active/*.md contains detailed spec files with:
|
|
221
878
|
- Requirements (must be satisfied)
|
|
222
879
|
- Scenarios (acceptance criteria)
|
|
223
|
-
- Current stage
|
|
880
|
+
- Current stage
|
|
224
881
|
|
|
225
882
|
## Spec-Driven Development Workflow
|
|
226
883
|
|
|
227
|
-
1. **
|
|
228
|
-
2. **
|
|
229
|
-
3. **
|
|
230
|
-
4. **
|
|
231
|
-
5. **
|
|
884
|
+
1. **EXPLORE**: Research and validate ideas
|
|
885
|
+
2. **NEW**: PRD with requirements
|
|
886
|
+
3. **SPEC**: Detailed specification
|
|
887
|
+
4. **TEST-CREATE**: Generate tests from spec
|
|
888
|
+
5. **TEST-APPLY**: Implement to pass tests
|
|
889
|
+
6. **VERIFY**: Validate all tests pass
|
|
890
|
+
7. **DONE**: Complete and archive
|
|
232
891
|
|
|
233
892
|
## Critical Rules
|
|
234
893
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
894
|
+
ALWAYS read PROJECT_STATE.md before making changes
|
|
895
|
+
ALWAYS ensure implementation satisfies tests
|
|
896
|
+
ALWAYS use specsafe CLI commands to advance stages
|
|
897
|
+
ALWAYS reference spec ID in commit messages
|
|
239
898
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
899
|
+
NEVER modify PROJECT_STATE.md directly (use CLI)
|
|
900
|
+
NEVER skip tests to implement faster
|
|
901
|
+
NEVER modify tests to make them pass without discussion
|
|
243
902
|
|
|
244
903
|
## SpecSafe CLI Reference
|
|
245
904
|
|
|
246
|
-
-
|
|
247
|
-
-
|
|
248
|
-
-
|
|
249
|
-
-
|
|
250
|
-
-
|
|
251
|
-
-
|
|
905
|
+
- specsafe status - Show current project status
|
|
906
|
+
- specsafe explore <name> - Start exploration
|
|
907
|
+
- specsafe new <name> - Create PRD
|
|
908
|
+
- specsafe spec <id> - Generate detailed spec
|
|
909
|
+
- specsafe test-create <id> - Create tests
|
|
910
|
+
- specsafe test-apply <id> - Start implementation
|
|
911
|
+
- specsafe verify <id> - Run validation
|
|
912
|
+
- specsafe done <id> - Complete spec
|
|
252
913
|
|
|
253
914
|
## Claude Code Skills
|
|
254
915
|
|
|
255
916
|
This project includes Claude Code skills for slash commands:
|
|
256
|
-
-
|
|
257
|
-
-
|
|
258
|
-
-
|
|
917
|
+
- /specsafe - Show project status
|
|
918
|
+
- /specsafe-explore - Pre-spec exploration
|
|
919
|
+
- /specsafe-new - Initialize spec with PRD
|
|
920
|
+
- /specsafe-spec - Generate detailed spec
|
|
921
|
+
- /specsafe-test-create - Create tests
|
|
922
|
+
- /specsafe-test-apply - Development mode
|
|
923
|
+
- /specsafe-verify - Run verification
|
|
924
|
+
- /specsafe-done - Complete and archive
|
|
259
925
|
`;
|
|
260
926
|
await writeFile(configPath, claudeContent);
|
|
261
927
|
console.log(chalk.green('✓ Created CLAUDE.md'));
|
|
@@ -268,44 +934,30 @@ This project includes Claude Code skills for slash commands:
|
|
|
268
934
|
if (!existsSync(skillsDir)) {
|
|
269
935
|
await mkdir(skillsDir, { recursive: true });
|
|
270
936
|
}
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
937
|
+
const skills = [
|
|
938
|
+
{ name: 'specsafe', content: claudeSkillSpecsafeContent },
|
|
939
|
+
{ name: 'specsafe-explore', content: claudeSkillExploreContent },
|
|
940
|
+
{ name: 'specsafe-new', content: claudeSkillNewContent },
|
|
941
|
+
{ name: 'specsafe-spec', content: claudeSkillSpecContent },
|
|
942
|
+
{ name: 'specsafe-test-create', content: claudeSkillTestCreateContent },
|
|
943
|
+
{ name: 'specsafe-test-apply', content: claudeSkillTestApplyContent },
|
|
944
|
+
{ name: 'specsafe-verify', content: claudeSkillVerifyContent },
|
|
945
|
+
{ name: 'specsafe-done', content: claudeSkillDoneContent },
|
|
946
|
+
{ name: 'specsafe-validate', content: claudeSkillValidateContent },
|
|
947
|
+
];
|
|
948
|
+
for (const skill of skills) {
|
|
949
|
+
const skillDir = `${skillsDir}/${skill.name}`;
|
|
950
|
+
const skillPath = `${skillDir}/SKILL.md`;
|
|
951
|
+
if (!existsSync(skillPath)) {
|
|
952
|
+
if (!existsSync(skillDir)) {
|
|
953
|
+
await mkdir(skillDir, { recursive: true });
|
|
954
|
+
}
|
|
955
|
+
await writeFile(skillPath, skill.content);
|
|
956
|
+
console.log(chalk.green(`✓ Created .claude/skills/${skill.name}/SKILL.md`));
|
|
277
957
|
}
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
}
|
|
281
|
-
else {
|
|
282
|
-
console.log(chalk.yellow('⚠ .claude/skills/specsafe/SKILL.md already exists, skipping'));
|
|
283
|
-
}
|
|
284
|
-
// Create spec skill
|
|
285
|
-
const specSkillDir = `${skillsDir}/specsafe-spec`;
|
|
286
|
-
const specSkillPath = `${specSkillDir}/SKILL.md`;
|
|
287
|
-
if (!existsSync(specSkillPath)) {
|
|
288
|
-
if (!existsSync(specSkillDir)) {
|
|
289
|
-
await mkdir(specSkillDir, { recursive: true });
|
|
958
|
+
else {
|
|
959
|
+
console.log(chalk.yellow(`⚠ .claude/skills/${skill.name}/SKILL.md already exists, skipping`));
|
|
290
960
|
}
|
|
291
|
-
await writeFile(specSkillPath, claudeSkillSpecContent);
|
|
292
|
-
console.log(chalk.green('✓ Created .claude/skills/specsafe-spec/SKILL.md'));
|
|
293
|
-
}
|
|
294
|
-
else {
|
|
295
|
-
console.log(chalk.yellow('⚠ .claude/skills/specsafe-spec/SKILL.md already exists, skipping'));
|
|
296
|
-
}
|
|
297
|
-
// Create validate skill
|
|
298
|
-
const validateSkillDir = `${skillsDir}/specsafe-validate`;
|
|
299
|
-
const validateSkillPath = `${validateSkillDir}/SKILL.md`;
|
|
300
|
-
if (!existsSync(validateSkillPath)) {
|
|
301
|
-
if (!existsSync(validateSkillDir)) {
|
|
302
|
-
await mkdir(validateSkillDir, { recursive: true });
|
|
303
|
-
}
|
|
304
|
-
await writeFile(validateSkillPath, claudeSkillValidateContent);
|
|
305
|
-
console.log(chalk.green('✓ Created .claude/skills/specsafe-validate/SKILL.md'));
|
|
306
|
-
}
|
|
307
|
-
else {
|
|
308
|
-
console.log(chalk.yellow('⚠ .claude/skills/specsafe-validate/SKILL.md already exists, skipping'));
|
|
309
961
|
}
|
|
310
962
|
}
|
|
311
963
|
async function generateCrushConfig(projectDir) {
|
|
@@ -314,27 +966,17 @@ async function generateCrushConfig(projectDir) {
|
|
|
314
966
|
if (!existsSync(commandsDir)) {
|
|
315
967
|
await mkdir(commandsDir, { recursive: true });
|
|
316
968
|
}
|
|
317
|
-
// Create
|
|
318
|
-
const
|
|
319
|
-
|
|
320
|
-
const specsafeContent = `Show SpecSafe project status and workflow guidance
|
|
969
|
+
// Create basic command files
|
|
970
|
+
const commandFiles = {
|
|
971
|
+
'specsafe.md': `Show SpecSafe project status
|
|
321
972
|
|
|
322
973
|
Read PROJECT_STATE.md and provide:
|
|
323
974
|
1. Summary of active specs and their current stages
|
|
324
975
|
2. Which specs need attention
|
|
325
|
-
3. Recommended next actions
|
|
326
|
-
4.
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
console.log(chalk.green('✓ Created .opencode/commands/specsafe.md'));
|
|
330
|
-
}
|
|
331
|
-
else {
|
|
332
|
-
console.log(chalk.yellow('⚠ .opencode/commands/specsafe.md already exists, skipping'));
|
|
333
|
-
}
|
|
334
|
-
// Create spec command
|
|
335
|
-
const specCmdPath = `${commandsDir}/spec.md`;
|
|
336
|
-
if (!existsSync(specCmdPath)) {
|
|
337
|
-
const specContent = `Show details for a specific spec by ID
|
|
976
|
+
3. Recommended next actions
|
|
977
|
+
4. SDD workflow reminder
|
|
978
|
+
`,
|
|
979
|
+
'spec.md': `Show details for a specific spec by ID
|
|
338
980
|
|
|
339
981
|
Read the spec file from specs/active/$SPEC_ID.md and show:
|
|
340
982
|
- Requirements
|
|
@@ -343,26 +985,97 @@ Read the spec file from specs/active/$SPEC_ID.md and show:
|
|
|
343
985
|
- Implementation files referenced
|
|
344
986
|
|
|
345
987
|
If no SPEC_ID provided, list available specs.
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
console.log(chalk.green('✓ Created .opencode/commands/spec.md'));
|
|
349
|
-
}
|
|
350
|
-
else {
|
|
351
|
-
console.log(chalk.yellow('⚠ .opencode/commands/spec.md already exists, skipping'));
|
|
352
|
-
}
|
|
353
|
-
// Create validate command
|
|
354
|
-
const validateCmdPath = `${commandsDir}/validate.md`;
|
|
355
|
-
if (!existsSync(validateCmdPath)) {
|
|
356
|
-
const validateContent = `Validate current implementation against active spec
|
|
988
|
+
`,
|
|
989
|
+
'validate.md': `Validate current implementation against active spec
|
|
357
990
|
|
|
358
991
|
Check if the current code changes satisfy the requirements in the active spec.
|
|
359
992
|
Point out any gaps or issues that need to be addressed before completing.
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
993
|
+
`,
|
|
994
|
+
'specsafe-explore.md': `Pre-Spec Exploration and Research Mode
|
|
995
|
+
|
|
996
|
+
Guide the user through pre-spec research:
|
|
997
|
+
- Define problem and identify users
|
|
998
|
+
- Research existing solutions
|
|
999
|
+
- Evaluate technology options
|
|
1000
|
+
- Estimate effort (S/M/L/XL)
|
|
1001
|
+
- Output: specs/exploration/FEATURE-NAME.md
|
|
1002
|
+
`,
|
|
1003
|
+
'specsafe-new.md': `Initialize Spec with Product Requirements Document
|
|
1004
|
+
|
|
1005
|
+
Create a new spec:
|
|
1006
|
+
1. Generate spec ID: SPEC-YYYYMMDD-NNN
|
|
1007
|
+
2. Create PRD with requirements, scenarios
|
|
1008
|
+
3. Recommend tech stack
|
|
1009
|
+
4. Output: specs/drafts/SPEC-ID.md
|
|
1010
|
+
5. Update PROJECT_STATE.md (status: DRAFT)
|
|
1011
|
+
|
|
1012
|
+
Confirm before writing.
|
|
1013
|
+
`,
|
|
1014
|
+
'specsafe-spec.md': `Generate Detailed Spec from PRD
|
|
1015
|
+
|
|
1016
|
+
Convert PRD to comprehensive spec:
|
|
1017
|
+
- Functional Requirements (FR-XXX)
|
|
1018
|
+
- Technical Requirements (TR-XXX)
|
|
1019
|
+
- Scenarios (Given/When/Then)
|
|
1020
|
+
- Acceptance Criteria
|
|
1021
|
+
- Architecture Notes
|
|
1022
|
+
|
|
1023
|
+
Move: specs/drafts/ → specs/active/
|
|
1024
|
+
Update: PROJECT_STATE.md (DRAFT → SPEC)
|
|
1025
|
+
`,
|
|
1026
|
+
'specsafe-test-create.md': `Create Tests from Spec Scenarios
|
|
1027
|
+
|
|
1028
|
+
Generate test suite:
|
|
1029
|
+
1. Read spec scenarios
|
|
1030
|
+
2. Create src/__tests__/SPEC-ID/*.test.ts
|
|
1031
|
+
3. Map Given/When/Then to test cases
|
|
1032
|
+
4. Include happy path and edge cases
|
|
1033
|
+
5. Update PROJECT_STATE.md (SPEC → TEST-CREATE)
|
|
1034
|
+
|
|
1035
|
+
Report: test count and coverage
|
|
1036
|
+
`,
|
|
1037
|
+
'specsafe-test-apply.md': `Apply Tests - Development Mode
|
|
1038
|
+
|
|
1039
|
+
Guide implementation:
|
|
1040
|
+
- Plan → Implement → Test → Commit
|
|
1041
|
+
- Map changes to requirement IDs
|
|
1042
|
+
- Never modify tests to pass (fix code)
|
|
1043
|
+
- Update PROJECT_STATE.md (TEST-CREATE → TEST-APPLY)
|
|
1044
|
+
|
|
1045
|
+
Ask: "Which requirement next?"
|
|
1046
|
+
`,
|
|
1047
|
+
'specsafe-verify.md': `Verify Implementation and Iterate
|
|
1048
|
+
|
|
1049
|
+
Run tests and fix:
|
|
1050
|
+
1. Execute: npm test -- SPEC-ID
|
|
1051
|
+
2. Map failures to requirements
|
|
1052
|
+
3. Fix code (not tests)
|
|
1053
|
+
4. Iterate until all pass
|
|
1054
|
+
5. Check coverage
|
|
1055
|
+
|
|
1056
|
+
Update PROJECT_STATE.md (TEST-APPLY → VERIFY)
|
|
1057
|
+
`,
|
|
1058
|
+
'specsafe-done.md': `Complete and Archive Spec
|
|
1059
|
+
|
|
1060
|
+
Finalize:
|
|
1061
|
+
- Verify completion checklist
|
|
1062
|
+
- Run final test suite
|
|
1063
|
+
- Move: specs/active/ → specs/archive/
|
|
1064
|
+
- Update PROJECT_STATE.md (VERIFY → COMPLETE)
|
|
1065
|
+
- Generate summary
|
|
1066
|
+
|
|
1067
|
+
Confirm before archiving.
|
|
1068
|
+
`
|
|
1069
|
+
};
|
|
1070
|
+
for (const [filename, content] of Object.entries(commandFiles)) {
|
|
1071
|
+
const targetPath = `${commandsDir}/${filename}`;
|
|
1072
|
+
if (!existsSync(targetPath)) {
|
|
1073
|
+
await writeFile(targetPath, content);
|
|
1074
|
+
console.log(chalk.green(`✓ Created .opencode/commands/${filename}`));
|
|
1075
|
+
}
|
|
1076
|
+
else {
|
|
1077
|
+
console.log(chalk.yellow(`⚠ .opencode/commands/${filename} already exists, skipping`));
|
|
1078
|
+
}
|
|
366
1079
|
}
|
|
367
1080
|
}
|
|
368
1081
|
/**
|
|
@@ -376,20 +1089,77 @@ export async function generateGitHooks(projectDir) {
|
|
|
376
1089
|
await mkdir(hooksDir, { recursive: true });
|
|
377
1090
|
}
|
|
378
1091
|
const preCommitContent = `#!/bin/bash
|
|
379
|
-
# SpecSafe pre-commit hook
|
|
1092
|
+
# SpecSafe pre-commit hook v0.4.0
|
|
1093
|
+
# Enhanced verification for OpenSpec-style workflow
|
|
380
1094
|
|
|
381
|
-
|
|
1095
|
+
set -e
|
|
382
1096
|
|
|
383
|
-
|
|
1097
|
+
echo "Running SpecSafe pre-commit checks..."
|
|
1098
|
+
|
|
1099
|
+
FAILED=0
|
|
1100
|
+
|
|
1101
|
+
# Check 1: Validate PROJECT_STATE.md exists
|
|
1102
|
+
echo "Checking PROJECT_STATE.md..."
|
|
384
1103
|
if [ ! -f "PROJECT_STATE.md" ]; then
|
|
385
|
-
|
|
386
|
-
|
|
1104
|
+
echo "PROJECT_STATE.md not found. Run 'specsafe init' first."
|
|
1105
|
+
FAILED=1
|
|
1106
|
+
else
|
|
1107
|
+
echo "PROJECT_STATE.md exists"
|
|
387
1108
|
fi
|
|
388
1109
|
|
|
389
|
-
#
|
|
390
|
-
|
|
1110
|
+
# Check 2: Verify specs directory structure
|
|
1111
|
+
echo "Checking specs directory structure..."
|
|
1112
|
+
if [ -d "specs" ]; then
|
|
1113
|
+
for subdir in drafts active archive exploration; do
|
|
1114
|
+
if [ ! -d "specs/\$subdir" ]; then
|
|
1115
|
+
echo "Missing specs/\$subdir directory - creating"
|
|
1116
|
+
mkdir -p "specs/\$subdir"
|
|
1117
|
+
fi
|
|
1118
|
+
done
|
|
1119
|
+
echo "Specs directory structure valid"
|
|
1120
|
+
else
|
|
1121
|
+
echo "No specs directory found. Run 'specsafe init'."
|
|
1122
|
+
fi
|
|
391
1123
|
|
|
392
|
-
|
|
1124
|
+
# Check 3: Check for TODO/FIXME in staged files
|
|
1125
|
+
echo "Checking for TODO/FIXME markers..."
|
|
1126
|
+
STAGED_FILES=\$(git diff --cached --name-only --diff-filter=ACM 2>/dev/null || true)
|
|
1127
|
+
|
|
1128
|
+
if [ -n "\$STAGED_FILES" ]; then
|
|
1129
|
+
TODO_FOUND=0
|
|
1130
|
+
for file in \$STAGED_FILES; do
|
|
1131
|
+
if echo "\$file" | grep -qE '\\.(ts|tsx|js|jsx|py|java|go|rs|cpp|c|h|php|rb)\$'; then
|
|
1132
|
+
if git diff --cached "\$file" | grep -i "TODO\\|FIXME\\|XXX\\|HACK" > /dev/null 2>&1; then
|
|
1133
|
+
echo "Warning: \$file contains TODO/FIXME markers"
|
|
1134
|
+
TODO_FOUND=1
|
|
1135
|
+
fi
|
|
1136
|
+
fi
|
|
1137
|
+
done
|
|
1138
|
+
|
|
1139
|
+
if [ \$TODO_FOUND -eq 1 ]; then
|
|
1140
|
+
echo "Consider resolving these before committing"
|
|
1141
|
+
fi
|
|
1142
|
+
fi
|
|
1143
|
+
|
|
1144
|
+
# Check 4: Run specsafe doctor if available
|
|
1145
|
+
if command -v specsafe >/dev/null 2>&1; then
|
|
1146
|
+
echo "Running SpecSafe validation..."
|
|
1147
|
+
if specsafe doctor --silent 2>/dev/null; then
|
|
1148
|
+
echo "SpecSafe doctor passed"
|
|
1149
|
+
else
|
|
1150
|
+
echo "SpecSafe doctor found issues. Run 'specsafe doctor' for details."
|
|
1151
|
+
fi
|
|
1152
|
+
fi
|
|
1153
|
+
|
|
1154
|
+
# Final status
|
|
1155
|
+
echo ""
|
|
1156
|
+
if [ \$FAILED -eq 0 ]; then
|
|
1157
|
+
echo "All pre-commit checks passed"
|
|
1158
|
+
exit 0
|
|
1159
|
+
else
|
|
1160
|
+
echo "Some pre-commit checks failed"
|
|
1161
|
+
exit 1
|
|
1162
|
+
fi
|
|
393
1163
|
`;
|
|
394
1164
|
if (existsSync(preCommitPath)) {
|
|
395
1165
|
console.log(chalk.yellow('⚠ .githooks/pre-commit already exists, skipping'));
|
|
@@ -400,9 +1170,10 @@ echo "✅ Pre-commit checks passed"
|
|
|
400
1170
|
try {
|
|
401
1171
|
const { exec } = await import('child_process');
|
|
402
1172
|
exec(`chmod +x ${preCommitPath}`);
|
|
1173
|
+
console.log(chalk.green('✓ Created .githooks/pre-commit'));
|
|
403
1174
|
}
|
|
404
1175
|
catch {
|
|
405
|
-
|
|
1176
|
+
console.log(chalk.yellow('⚠ Could not make pre-commit executable'));
|
|
406
1177
|
}
|
|
407
1178
|
}
|
|
408
1179
|
//# sourceMappingURL=generateToolConfig.js.map
|