@specsafe/core 0.4.0 → 0.6.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/agents/adapters/base.d.ts +44 -0
- package/dist/agents/adapters/base.d.ts.map +1 -0
- package/dist/agents/adapters/base.js +164 -0
- package/dist/agents/adapters/base.js.map +1 -0
- package/dist/agents/adapters/claude-code.d.ts +14 -0
- package/dist/agents/adapters/claude-code.d.ts.map +1 -0
- package/dist/agents/adapters/claude-code.js +120 -0
- package/dist/agents/adapters/claude-code.js.map +1 -0
- package/dist/agents/adapters/copilot.d.ts +13 -0
- package/dist/agents/adapters/copilot.d.ts.map +1 -0
- package/dist/agents/adapters/copilot.js +115 -0
- package/dist/agents/adapters/copilot.js.map +1 -0
- package/dist/agents/adapters/cursor.d.ts +13 -0
- package/dist/agents/adapters/cursor.d.ts.map +1 -0
- package/dist/agents/adapters/cursor.js +105 -0
- package/dist/agents/adapters/cursor.js.map +1 -0
- package/dist/agents/adapters/gemini-cli.d.ts +13 -0
- package/dist/agents/adapters/gemini-cli.d.ts.map +1 -0
- package/dist/agents/adapters/gemini-cli.js +79 -0
- package/dist/agents/adapters/gemini-cli.js.map +1 -0
- package/dist/agents/adapters/index.d.ts +16 -0
- package/dist/agents/adapters/index.d.ts.map +1 -0
- package/dist/agents/adapters/index.js +47 -0
- package/dist/agents/adapters/index.js.map +1 -0
- package/dist/agents/adapters/opencode.d.ts +13 -0
- package/dist/agents/adapters/opencode.d.ts.map +1 -0
- package/dist/agents/adapters/opencode.js +67 -0
- package/dist/agents/adapters/opencode.js.map +1 -0
- package/dist/agents/index.d.ts +8 -0
- package/dist/agents/index.d.ts.map +1 -0
- package/dist/agents/index.js +9 -0
- package/dist/agents/index.js.map +1 -0
- package/dist/agents/registry.d.ts +70 -0
- package/dist/agents/registry.d.ts.map +1 -0
- package/dist/agents/registry.js +194 -0
- package/dist/agents/registry.js.map +1 -0
- package/dist/agents/types.d.ts +71 -0
- package/dist/agents/types.d.ts.map +1 -0
- package/dist/agents/types.js +6 -0
- package/dist/agents/types.js.map +1 -0
- package/dist/delta/merger.d.ts +36 -0
- package/dist/delta/merger.d.ts.map +1 -0
- package/dist/delta/merger.js +264 -0
- package/dist/delta/merger.js.map +1 -0
- package/dist/delta/parser.d.ts +27 -0
- package/dist/delta/parser.d.ts.map +1 -0
- package/dist/delta/parser.js +196 -0
- package/dist/delta/parser.js.map +1 -0
- package/dist/delta/types.d.ts +39 -0
- package/dist/delta/types.d.ts.map +1 -0
- package/dist/delta/types.js +6 -0
- package/dist/delta/types.js.map +1 -0
- package/dist/ears/index.d.ts +11 -0
- package/dist/ears/index.d.ts.map +1 -0
- package/dist/ears/index.js +11 -0
- package/dist/ears/index.js.map +1 -0
- package/dist/ears/parser.d.ts +22 -0
- package/dist/ears/parser.d.ts.map +1 -0
- package/dist/ears/parser.js +273 -0
- package/dist/ears/parser.js.map +1 -0
- package/dist/ears/template.d.ts +20 -0
- package/dist/ears/template.d.ts.map +1 -0
- package/dist/ears/template.js +364 -0
- package/dist/ears/template.js.map +1 -0
- package/dist/ears/types.d.ts +58 -0
- package/dist/ears/types.d.ts.map +1 -0
- package/dist/ears/types.js +6 -0
- package/dist/ears/types.js.map +1 -0
- package/dist/ears/validator.d.ts +37 -0
- package/dist/ears/validator.d.ts.map +1 -0
- package/dist/ears/validator.js +234 -0
- package/dist/ears/validator.js.map +1 -0
- package/dist/elicitation/engine.d.ts +75 -0
- package/dist/elicitation/engine.d.ts.map +1 -0
- package/dist/elicitation/engine.js +174 -0
- package/dist/elicitation/engine.js.map +1 -0
- package/dist/elicitation/flows.d.ts +18 -0
- package/dist/elicitation/flows.d.ts.map +1 -0
- package/dist/elicitation/flows.js +331 -0
- package/dist/elicitation/flows.js.map +1 -0
- package/dist/elicitation/generator.d.ts +20 -0
- package/dist/elicitation/generator.d.ts.map +1 -0
- package/dist/elicitation/generator.js +260 -0
- package/dist/elicitation/generator.js.map +1 -0
- package/dist/elicitation/index.d.ts +27 -0
- package/dist/elicitation/index.d.ts.map +1 -0
- package/dist/elicitation/index.js +29 -0
- package/dist/elicitation/index.js.map +1 -0
- package/dist/elicitation/types.d.ts +69 -0
- package/dist/elicitation/types.d.ts.map +1 -0
- package/dist/elicitation/types.js +6 -0
- package/dist/elicitation/types.js.map +1 -0
- package/dist/extensions/builtins/complexity.d.ts +7 -0
- package/dist/extensions/builtins/complexity.d.ts.map +1 -0
- package/dist/extensions/builtins/complexity.js +97 -0
- package/dist/extensions/builtins/complexity.js.map +1 -0
- package/dist/extensions/builtins/owasp.d.ts +7 -0
- package/dist/extensions/builtins/owasp.d.ts.map +1 -0
- package/dist/extensions/builtins/owasp.js +76 -0
- package/dist/extensions/builtins/owasp.js.map +1 -0
- package/dist/extensions/index.d.ts +54 -0
- package/dist/extensions/index.d.ts.map +1 -0
- package/dist/extensions/index.js +72 -0
- package/dist/extensions/index.js.map +1 -0
- package/dist/extensions/loader.d.ts +28 -0
- package/dist/extensions/loader.d.ts.map +1 -0
- package/dist/extensions/loader.js +62 -0
- package/dist/extensions/loader.js.map +1 -0
- package/dist/extensions/registry.d.ts +74 -0
- package/dist/extensions/registry.d.ts.map +1 -0
- package/dist/extensions/registry.js +159 -0
- package/dist/extensions/registry.js.map +1 -0
- package/dist/extensions/types.d.ts +70 -0
- package/dist/extensions/types.d.ts.map +1 -0
- package/dist/extensions/types.js +2 -0
- package/dist/extensions/types.js.map +1 -0
- package/dist/governance/builtins.d.ts +7 -0
- package/dist/governance/builtins.d.ts.map +1 -0
- package/dist/governance/builtins.js +105 -0
- package/dist/governance/builtins.js.map +1 -0
- package/dist/governance/constitution.d.ts +23 -0
- package/dist/governance/constitution.d.ts.map +1 -0
- package/dist/governance/constitution.js +245 -0
- package/dist/governance/constitution.js.map +1 -0
- package/dist/governance/index.d.ts +3 -0
- package/dist/governance/index.d.ts.map +1 -0
- package/dist/governance/index.js +2 -0
- package/dist/governance/index.js.map +1 -0
- package/dist/governance/template.d.ts +12 -0
- package/dist/governance/template.d.ts.map +1 -0
- package/dist/governance/template.js +84 -0
- package/dist/governance/template.js.map +1 -0
- package/dist/governance/types.d.ts +64 -0
- package/dist/governance/types.d.ts.map +1 -0
- package/dist/governance/types.js +2 -0
- package/dist/governance/types.js.map +1 -0
- package/dist/index.d.ts +23 -18
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -18
- package/dist/index.js.map +1 -1
- package/dist/templates/checklist.d.ts +7 -0
- package/dist/templates/checklist.d.ts.map +1 -0
- package/dist/templates/checklist.js +131 -0
- package/dist/templates/checklist.js.map +1 -0
- package/dist/templates/delta-template.d.ts +18 -0
- package/dist/templates/delta-template.d.ts.map +1 -0
- package/dist/templates/delta-template.js +191 -0
- package/dist/templates/delta-template.js.map +1 -0
- package/dist/templates/engine.d.ts +20 -0
- package/dist/templates/engine.d.ts.map +1 -0
- package/dist/templates/engine.js +187 -0
- package/dist/templates/engine.js.map +1 -0
- package/dist/templates/types.d.ts +67 -0
- package/dist/templates/types.d.ts.map +1 -0
- package/dist/templates/types.js +5 -0
- package/dist/templates/types.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Built-in Elicitation Flows
|
|
3
|
+
* Provides pre-configured flows for common spec creation scenarios
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Quick flow: 5 essential questions for rapid spec creation
|
|
7
|
+
*/
|
|
8
|
+
export const quickFlow = {
|
|
9
|
+
id: 'quick',
|
|
10
|
+
name: 'Quick Spec',
|
|
11
|
+
description: 'Fast spec creation with minimal questions (5 steps)',
|
|
12
|
+
steps: [
|
|
13
|
+
{
|
|
14
|
+
id: 'name',
|
|
15
|
+
prompt: 'What is the name of this feature or change?',
|
|
16
|
+
type: 'text',
|
|
17
|
+
required: true,
|
|
18
|
+
validate: (value) => {
|
|
19
|
+
if (typeof value !== 'string' || value.trim().length === 0) {
|
|
20
|
+
return 'Name is required';
|
|
21
|
+
}
|
|
22
|
+
if (value.trim().length < 3) {
|
|
23
|
+
return 'Name must be at least 3 characters';
|
|
24
|
+
}
|
|
25
|
+
return true;
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
id: 'description',
|
|
30
|
+
prompt: 'Provide a brief description',
|
|
31
|
+
type: 'text',
|
|
32
|
+
required: true,
|
|
33
|
+
validate: (value) => {
|
|
34
|
+
if (typeof value !== 'string' || value.trim().length === 0) {
|
|
35
|
+
return 'Description is required';
|
|
36
|
+
}
|
|
37
|
+
return true;
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
id: 'type',
|
|
42
|
+
prompt: 'What type of change is this?',
|
|
43
|
+
type: 'choice',
|
|
44
|
+
choices: ['feature', 'bugfix', 'migration', 'security'],
|
|
45
|
+
default: 'feature',
|
|
46
|
+
required: true,
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
id: 'priority',
|
|
50
|
+
prompt: 'What is the priority?',
|
|
51
|
+
type: 'choice',
|
|
52
|
+
choices: ['critical', 'high', 'medium', 'low'],
|
|
53
|
+
default: 'medium',
|
|
54
|
+
required: true,
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
id: 'requirements',
|
|
58
|
+
prompt: 'List the key requirements (one per line)',
|
|
59
|
+
type: 'text',
|
|
60
|
+
required: true,
|
|
61
|
+
validate: (value) => {
|
|
62
|
+
if (typeof value !== 'string' || value.trim().length === 0) {
|
|
63
|
+
return 'At least one requirement is needed';
|
|
64
|
+
}
|
|
65
|
+
return true;
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* Full flow: Comprehensive spec elicitation (15+ steps)
|
|
72
|
+
*/
|
|
73
|
+
export const fullFlow = {
|
|
74
|
+
id: 'full',
|
|
75
|
+
name: 'Full Spec',
|
|
76
|
+
description: 'Complete spec creation with comprehensive questions',
|
|
77
|
+
steps: [
|
|
78
|
+
{
|
|
79
|
+
id: 'name',
|
|
80
|
+
prompt: 'What is the name of this feature or change?',
|
|
81
|
+
type: 'text',
|
|
82
|
+
required: true,
|
|
83
|
+
validate: (value) => {
|
|
84
|
+
if (typeof value !== 'string' || value.trim().length === 0) {
|
|
85
|
+
return 'Name is required';
|
|
86
|
+
}
|
|
87
|
+
if (value.trim().length < 3) {
|
|
88
|
+
return 'Name must be at least 3 characters';
|
|
89
|
+
}
|
|
90
|
+
return true;
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
id: 'description',
|
|
95
|
+
prompt: 'Provide a detailed description',
|
|
96
|
+
type: 'text',
|
|
97
|
+
required: true,
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
id: 'type',
|
|
101
|
+
prompt: 'What type of change is this?',
|
|
102
|
+
type: 'choice',
|
|
103
|
+
choices: ['feature', 'bugfix', 'migration', 'security', 'performance', 'refactoring'],
|
|
104
|
+
default: 'feature',
|
|
105
|
+
required: true,
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
id: 'priority',
|
|
109
|
+
prompt: 'What is the priority?',
|
|
110
|
+
type: 'choice',
|
|
111
|
+
choices: ['critical', 'high', 'medium', 'low'],
|
|
112
|
+
default: 'medium',
|
|
113
|
+
required: true,
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
id: 'scope',
|
|
117
|
+
prompt: 'What is the scope of this change?',
|
|
118
|
+
type: 'text',
|
|
119
|
+
required: false,
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
id: 'stakeholders',
|
|
123
|
+
prompt: 'Who are the stakeholders? (comma-separated)',
|
|
124
|
+
type: 'text',
|
|
125
|
+
required: false,
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
id: 'requirements',
|
|
129
|
+
prompt: 'List the detailed requirements (one per line)',
|
|
130
|
+
type: 'text',
|
|
131
|
+
required: true,
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
id: 'has_security',
|
|
135
|
+
prompt: 'Does this have security implications?',
|
|
136
|
+
type: 'confirm',
|
|
137
|
+
default: false,
|
|
138
|
+
required: true,
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
id: 'security_considerations',
|
|
142
|
+
prompt: 'What are the security considerations?',
|
|
143
|
+
type: 'text',
|
|
144
|
+
required: true,
|
|
145
|
+
condition: (answers) => answers.has_security === true,
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
id: 'testing_strategy',
|
|
149
|
+
prompt: 'Describe the testing strategy',
|
|
150
|
+
type: 'text',
|
|
151
|
+
required: true,
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
id: 'has_performance',
|
|
155
|
+
prompt: 'Are there specific performance requirements?',
|
|
156
|
+
type: 'confirm',
|
|
157
|
+
default: false,
|
|
158
|
+
required: true,
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
id: 'performance_requirements',
|
|
162
|
+
prompt: 'What are the performance requirements?',
|
|
163
|
+
type: 'text',
|
|
164
|
+
required: true,
|
|
165
|
+
condition: (answers) => answers.has_performance === true,
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
id: 'dependencies',
|
|
169
|
+
prompt: 'List any dependencies (systems, APIs, libraries)',
|
|
170
|
+
type: 'text',
|
|
171
|
+
required: false,
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
id: 'timeline',
|
|
175
|
+
prompt: 'What is the estimated timeline?',
|
|
176
|
+
type: 'text',
|
|
177
|
+
required: false,
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
id: 'risks',
|
|
181
|
+
prompt: 'What are the potential risks?',
|
|
182
|
+
type: 'text',
|
|
183
|
+
required: false,
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
id: 'acceptance_criteria',
|
|
187
|
+
prompt: 'What are the acceptance criteria?',
|
|
188
|
+
type: 'text',
|
|
189
|
+
required: true,
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
id: 'notes',
|
|
193
|
+
prompt: 'Any additional notes or context?',
|
|
194
|
+
type: 'text',
|
|
195
|
+
required: false,
|
|
196
|
+
},
|
|
197
|
+
],
|
|
198
|
+
};
|
|
199
|
+
/**
|
|
200
|
+
* EARS flow: EARS-focused requirement elicitation
|
|
201
|
+
*/
|
|
202
|
+
export const earsFlow = {
|
|
203
|
+
id: 'ears',
|
|
204
|
+
name: 'EARS Spec',
|
|
205
|
+
description: 'EARS-formatted specification with structured requirements',
|
|
206
|
+
steps: [
|
|
207
|
+
{
|
|
208
|
+
id: 'name',
|
|
209
|
+
prompt: 'What is the name of this feature?',
|
|
210
|
+
type: 'text',
|
|
211
|
+
required: true,
|
|
212
|
+
validate: (value) => {
|
|
213
|
+
if (typeof value !== 'string' || value.trim().length === 0) {
|
|
214
|
+
return 'Name is required';
|
|
215
|
+
}
|
|
216
|
+
return true;
|
|
217
|
+
},
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
id: 'description',
|
|
221
|
+
prompt: 'Provide a description',
|
|
222
|
+
type: 'text',
|
|
223
|
+
required: true,
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
id: 'req_count',
|
|
227
|
+
prompt: 'How many requirements do you want to define?',
|
|
228
|
+
type: 'text',
|
|
229
|
+
required: true,
|
|
230
|
+
default: '3',
|
|
231
|
+
validate: (value) => {
|
|
232
|
+
const num = parseInt(value, 10);
|
|
233
|
+
if (isNaN(num) || num < 1 || num > 20) {
|
|
234
|
+
return 'Please enter a number between 1 and 20';
|
|
235
|
+
}
|
|
236
|
+
return true;
|
|
237
|
+
},
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
id: 'req_1_type',
|
|
241
|
+
prompt: 'Requirement 1 - Type',
|
|
242
|
+
type: 'choice',
|
|
243
|
+
choices: ['ubiquitous', 'event', 'state', 'optional', 'unwanted'],
|
|
244
|
+
default: 'ubiquitous',
|
|
245
|
+
required: true,
|
|
246
|
+
condition: (answers) => parseInt(answers.req_count, 10) >= 1,
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
id: 'req_1_trigger',
|
|
250
|
+
prompt: 'Requirement 1 - What is the trigger/event?',
|
|
251
|
+
type: 'text',
|
|
252
|
+
required: true,
|
|
253
|
+
condition: (answers) => answers.req_1_type === 'event',
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
id: 'req_1_precondition',
|
|
257
|
+
prompt: 'Requirement 1 - What is the precondition/state?',
|
|
258
|
+
type: 'text',
|
|
259
|
+
required: true,
|
|
260
|
+
condition: (answers) => answers.req_1_type === 'state' || answers.req_1_type === 'optional',
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
id: 'req_1_response',
|
|
264
|
+
prompt: 'Requirement 1 - What should the system do?',
|
|
265
|
+
type: 'text',
|
|
266
|
+
required: true,
|
|
267
|
+
condition: (answers) => parseInt(answers.req_count, 10) >= 1,
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
id: 'req_2_type',
|
|
271
|
+
prompt: 'Requirement 2 - Type',
|
|
272
|
+
type: 'choice',
|
|
273
|
+
choices: ['ubiquitous', 'event', 'state', 'optional', 'unwanted'],
|
|
274
|
+
default: 'ubiquitous',
|
|
275
|
+
required: true,
|
|
276
|
+
condition: (answers) => parseInt(answers.req_count, 10) >= 2,
|
|
277
|
+
},
|
|
278
|
+
{
|
|
279
|
+
id: 'req_2_trigger',
|
|
280
|
+
prompt: 'Requirement 2 - What is the trigger/event?',
|
|
281
|
+
type: 'text',
|
|
282
|
+
required: true,
|
|
283
|
+
condition: (answers) => answers.req_2_type === 'event' && parseInt(answers.req_count, 10) >= 2,
|
|
284
|
+
},
|
|
285
|
+
{
|
|
286
|
+
id: 'req_2_precondition',
|
|
287
|
+
prompt: 'Requirement 2 - What is the precondition/state?',
|
|
288
|
+
type: 'text',
|
|
289
|
+
required: true,
|
|
290
|
+
condition: (answers) => (answers.req_2_type === 'state' || answers.req_2_type === 'optional') && parseInt(answers.req_count, 10) >= 2,
|
|
291
|
+
},
|
|
292
|
+
{
|
|
293
|
+
id: 'req_2_response',
|
|
294
|
+
prompt: 'Requirement 2 - What should the system do?',
|
|
295
|
+
type: 'text',
|
|
296
|
+
required: true,
|
|
297
|
+
condition: (answers) => parseInt(answers.req_count, 10) >= 2,
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
id: 'req_3_type',
|
|
301
|
+
prompt: 'Requirement 3 - Type',
|
|
302
|
+
type: 'choice',
|
|
303
|
+
choices: ['ubiquitous', 'event', 'state', 'optional', 'unwanted'],
|
|
304
|
+
default: 'ubiquitous',
|
|
305
|
+
required: true,
|
|
306
|
+
condition: (answers) => parseInt(answers.req_count, 10) >= 3,
|
|
307
|
+
},
|
|
308
|
+
{
|
|
309
|
+
id: 'req_3_trigger',
|
|
310
|
+
prompt: 'Requirement 3 - What is the trigger/event?',
|
|
311
|
+
type: 'text',
|
|
312
|
+
required: true,
|
|
313
|
+
condition: (answers) => answers.req_3_type === 'event' && parseInt(answers.req_count, 10) >= 3,
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
id: 'req_3_precondition',
|
|
317
|
+
prompt: 'Requirement 3 - What is the precondition/state?',
|
|
318
|
+
type: 'text',
|
|
319
|
+
required: true,
|
|
320
|
+
condition: (answers) => (answers.req_3_type === 'state' || answers.req_3_type === 'optional') && parseInt(answers.req_count, 10) >= 3,
|
|
321
|
+
},
|
|
322
|
+
{
|
|
323
|
+
id: 'req_3_response',
|
|
324
|
+
prompt: 'Requirement 3 - What should the system do?',
|
|
325
|
+
type: 'text',
|
|
326
|
+
required: true,
|
|
327
|
+
condition: (answers) => parseInt(answers.req_count, 10) >= 3,
|
|
328
|
+
},
|
|
329
|
+
],
|
|
330
|
+
};
|
|
331
|
+
//# sourceMappingURL=flows.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flows.js","sourceRoot":"","sources":["../../src/elicitation/flows.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Specification Generator
|
|
3
|
+
* Converts elicitation results into SpecSafe-formatted markdown specs
|
|
4
|
+
*/
|
|
5
|
+
import type { ElicitationResult } from './types.js';
|
|
6
|
+
/**
|
|
7
|
+
* Generate a SpecSafe-formatted specification from elicitation results
|
|
8
|
+
*
|
|
9
|
+
* @param result The completed elicitation result
|
|
10
|
+
* @returns Markdown-formatted specification
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* const result = engine.getResult();
|
|
15
|
+
* const spec = generateSpec(result);
|
|
16
|
+
* await writeFile('specs/SPEC-001.md', spec);
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export declare function generateSpec(result: ElicitationResult): string;
|
|
20
|
+
//# sourceMappingURL=generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/elicitation/generator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEpD;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAa9D"}
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Specification Generator
|
|
3
|
+
* Converts elicitation results into SpecSafe-formatted markdown specs
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Generate a SpecSafe-formatted specification from elicitation results
|
|
7
|
+
*
|
|
8
|
+
* @param result The completed elicitation result
|
|
9
|
+
* @returns Markdown-formatted specification
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* const result = engine.getResult();
|
|
14
|
+
* const spec = generateSpec(result);
|
|
15
|
+
* await writeFile('specs/SPEC-001.md', spec);
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export function generateSpec(result) {
|
|
19
|
+
const { flowId, answers } = result;
|
|
20
|
+
switch (flowId) {
|
|
21
|
+
case 'quick':
|
|
22
|
+
return generateQuickSpec(answers);
|
|
23
|
+
case 'full':
|
|
24
|
+
return generateFullSpec(answers);
|
|
25
|
+
case 'ears':
|
|
26
|
+
return generateEARSSpec(answers);
|
|
27
|
+
default:
|
|
28
|
+
throw new Error(`Unknown flow ID: ${flowId}`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Generate spec from quick flow
|
|
33
|
+
*/
|
|
34
|
+
function generateQuickSpec(answers) {
|
|
35
|
+
const specId = generateSpecId();
|
|
36
|
+
const date = new Date().toISOString().split('T')[0];
|
|
37
|
+
const requirementsValue = answers.requirements;
|
|
38
|
+
if (typeof requirementsValue !== 'string') {
|
|
39
|
+
throw new Error('Missing required field: requirements');
|
|
40
|
+
}
|
|
41
|
+
const requirements = requirementsValue
|
|
42
|
+
.split('\n')
|
|
43
|
+
.filter(line => line.trim().length > 0)
|
|
44
|
+
.map(req => `- ${req.trim()}`)
|
|
45
|
+
.join('\n');
|
|
46
|
+
return `# ${answers.name}
|
|
47
|
+
|
|
48
|
+
## Metadata
|
|
49
|
+
- **Spec ID**: ${specId}
|
|
50
|
+
- **Created**: ${date}
|
|
51
|
+
- **Type**: ${answers.type}
|
|
52
|
+
- **Priority**: ${answers.priority}
|
|
53
|
+
- **Status**: draft
|
|
54
|
+
|
|
55
|
+
## Description
|
|
56
|
+
|
|
57
|
+
${answers.description}
|
|
58
|
+
|
|
59
|
+
## Requirements
|
|
60
|
+
|
|
61
|
+
${requirements}
|
|
62
|
+
|
|
63
|
+
## Testing Strategy
|
|
64
|
+
|
|
65
|
+
- [ ] Unit tests for core functionality
|
|
66
|
+
- [ ] Integration tests for workflows
|
|
67
|
+
- [ ] End-to-end tests for user scenarios
|
|
68
|
+
|
|
69
|
+
## Acceptance Criteria
|
|
70
|
+
|
|
71
|
+
- All requirements implemented
|
|
72
|
+
- All tests passing
|
|
73
|
+
- Code reviewed and approved
|
|
74
|
+
|
|
75
|
+
## Notes
|
|
76
|
+
|
|
77
|
+
Created via SpecSafe quick flow elicitation.
|
|
78
|
+
`;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Generate spec from full flow
|
|
82
|
+
*/
|
|
83
|
+
function generateFullSpec(answers) {
|
|
84
|
+
const specId = generateSpecId();
|
|
85
|
+
const date = new Date().toISOString().split('T')[0];
|
|
86
|
+
const requirementsValue = answers.requirements;
|
|
87
|
+
if (typeof requirementsValue !== 'string') {
|
|
88
|
+
throw new Error('Missing required field: requirements');
|
|
89
|
+
}
|
|
90
|
+
const requirements = requirementsValue
|
|
91
|
+
.split('\n')
|
|
92
|
+
.filter(line => line.trim().length > 0)
|
|
93
|
+
.map(req => `- ${req.trim()}`)
|
|
94
|
+
.join('\n');
|
|
95
|
+
let spec = `# ${answers.name}
|
|
96
|
+
|
|
97
|
+
## Metadata
|
|
98
|
+
- **Spec ID**: ${specId}
|
|
99
|
+
- **Created**: ${date}
|
|
100
|
+
- **Type**: ${answers.type}
|
|
101
|
+
- **Priority**: ${answers.priority}
|
|
102
|
+
- **Status**: draft
|
|
103
|
+
|
|
104
|
+
## Description
|
|
105
|
+
|
|
106
|
+
${answers.description}
|
|
107
|
+
`;
|
|
108
|
+
if (answers.scope) {
|
|
109
|
+
spec += `\n## Scope\n\n${answers.scope}\n`;
|
|
110
|
+
}
|
|
111
|
+
if (answers.stakeholders) {
|
|
112
|
+
const stakeholdersValue = answers.stakeholders;
|
|
113
|
+
if (typeof stakeholdersValue === 'string') {
|
|
114
|
+
const stakeholderList = stakeholdersValue
|
|
115
|
+
.split(',')
|
|
116
|
+
.map(s => `- ${s.trim()}`)
|
|
117
|
+
.join('\n');
|
|
118
|
+
spec += `\n## Stakeholders\n\n${stakeholderList}\n`;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
spec += `\n## Requirements\n\n${requirements}\n`;
|
|
122
|
+
if (answers.has_security && answers.security_considerations) {
|
|
123
|
+
spec += `\n## Security Considerations\n\n${answers.security_considerations}\n`;
|
|
124
|
+
}
|
|
125
|
+
spec += `\n## Testing Strategy\n\n${answers.testing_strategy}\n`;
|
|
126
|
+
if (answers.has_performance && answers.performance_requirements) {
|
|
127
|
+
spec += `\n## Performance Requirements\n\n${answers.performance_requirements}\n`;
|
|
128
|
+
}
|
|
129
|
+
if (answers.dependencies) {
|
|
130
|
+
const dependenciesValue = answers.dependencies;
|
|
131
|
+
if (typeof dependenciesValue === 'string') {
|
|
132
|
+
const depList = dependenciesValue
|
|
133
|
+
.split('\n')
|
|
134
|
+
.filter(line => line.trim().length > 0)
|
|
135
|
+
.map(dep => `- ${dep.trim()}`)
|
|
136
|
+
.join('\n');
|
|
137
|
+
spec += `\n## Dependencies\n\n${depList}\n`;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
if (answers.timeline) {
|
|
141
|
+
spec += `\n## Timeline\n\n${answers.timeline}\n`;
|
|
142
|
+
}
|
|
143
|
+
if (answers.risks) {
|
|
144
|
+
const risksValue = answers.risks;
|
|
145
|
+
if (typeof risksValue === 'string') {
|
|
146
|
+
const riskList = risksValue
|
|
147
|
+
.split('\n')
|
|
148
|
+
.filter(line => line.trim().length > 0)
|
|
149
|
+
.map(risk => `- ${risk.trim()}`)
|
|
150
|
+
.join('\n');
|
|
151
|
+
spec += `\n## Risks\n\n${riskList}\n`;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
spec += `\n## Acceptance Criteria\n\n${answers.acceptance_criteria}\n`;
|
|
155
|
+
if (answers.notes) {
|
|
156
|
+
spec += `\n## Notes\n\n${answers.notes}\n`;
|
|
157
|
+
}
|
|
158
|
+
spec += `\n---\n\nCreated via SpecSafe full flow elicitation.\n`;
|
|
159
|
+
return spec;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Generate spec from EARS flow
|
|
163
|
+
*/
|
|
164
|
+
function generateEARSSpec(answers) {
|
|
165
|
+
const specId = generateSpecId();
|
|
166
|
+
const date = new Date().toISOString().split('T')[0];
|
|
167
|
+
const reqCountValue = answers.req_count;
|
|
168
|
+
if (typeof reqCountValue !== 'string') {
|
|
169
|
+
throw new Error('Missing required field: req_count');
|
|
170
|
+
}
|
|
171
|
+
const reqCount = parseInt(reqCountValue, 10);
|
|
172
|
+
if (isNaN(reqCount) || reqCount < 1) {
|
|
173
|
+
throw new Error('Invalid req_count value');
|
|
174
|
+
}
|
|
175
|
+
let spec = `# ${answers.name}
|
|
176
|
+
|
|
177
|
+
## Metadata
|
|
178
|
+
- **Spec ID**: ${specId}
|
|
179
|
+
- **Created**: ${date}
|
|
180
|
+
- **Type**: feature
|
|
181
|
+
- **Format**: EARS
|
|
182
|
+
- **Status**: draft
|
|
183
|
+
|
|
184
|
+
## Description
|
|
185
|
+
|
|
186
|
+
${answers.description}
|
|
187
|
+
|
|
188
|
+
## Requirements (EARS Format)
|
|
189
|
+
|
|
190
|
+
`;
|
|
191
|
+
for (let i = 1; i <= reqCount; i++) {
|
|
192
|
+
const typeKey = `req_${i}_type`;
|
|
193
|
+
const triggerKey = `req_${i}_trigger`;
|
|
194
|
+
const preconditionKey = `req_${i}_precondition`;
|
|
195
|
+
const responseKey = `req_${i}_response`;
|
|
196
|
+
const type = answers[typeKey];
|
|
197
|
+
const response = answers[responseKey];
|
|
198
|
+
if (!response || typeof response !== 'string')
|
|
199
|
+
continue;
|
|
200
|
+
spec += `### REQ-${i.toString().padStart(3, '0')}\n\n`;
|
|
201
|
+
switch (type) {
|
|
202
|
+
case 'ubiquitous':
|
|
203
|
+
spec += `**Type**: Ubiquitous\n\n`;
|
|
204
|
+
spec += `The system shall ${response}\n\n`;
|
|
205
|
+
break;
|
|
206
|
+
case 'event': {
|
|
207
|
+
const trigger = answers[triggerKey];
|
|
208
|
+
spec += `**Type**: Event-driven\n\n`;
|
|
209
|
+
spec += `WHEN ${trigger}, the system shall ${response}\n\n`;
|
|
210
|
+
break;
|
|
211
|
+
}
|
|
212
|
+
case 'state': {
|
|
213
|
+
const statePrecondition = answers[preconditionKey];
|
|
214
|
+
spec += `**Type**: State-driven\n\n`;
|
|
215
|
+
spec += `WHILE ${statePrecondition}, the system shall ${response}\n\n`;
|
|
216
|
+
break;
|
|
217
|
+
}
|
|
218
|
+
case 'optional': {
|
|
219
|
+
const optionalPrecondition = answers[preconditionKey];
|
|
220
|
+
spec += `**Type**: Optional\n\n`;
|
|
221
|
+
spec += `WHERE ${optionalPrecondition}, the system shall ${response}\n\n`;
|
|
222
|
+
break;
|
|
223
|
+
}
|
|
224
|
+
case 'unwanted':
|
|
225
|
+
spec += `**Type**: Unwanted behavior\n\n`;
|
|
226
|
+
spec += `IF [unwanted condition], then the system shall ${response}\n\n`;
|
|
227
|
+
break;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
spec += `## Testing Strategy
|
|
231
|
+
|
|
232
|
+
- [ ] Validate each EARS requirement with specific test cases
|
|
233
|
+
- [ ] Test trigger conditions for event-driven requirements
|
|
234
|
+
- [ ] Test state conditions for state-driven requirements
|
|
235
|
+
- [ ] Verify optional requirements under specified conditions
|
|
236
|
+
|
|
237
|
+
## Acceptance Criteria
|
|
238
|
+
|
|
239
|
+
- All EARS requirements implemented and tested
|
|
240
|
+
- Requirements follow EARS syntax properly
|
|
241
|
+
- All tests passing with >80% coverage
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
Created via SpecSafe EARS flow elicitation.
|
|
246
|
+
`;
|
|
247
|
+
return spec;
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Generate a unique spec ID
|
|
251
|
+
*/
|
|
252
|
+
function generateSpecId() {
|
|
253
|
+
const date = new Date();
|
|
254
|
+
const year = date.getFullYear();
|
|
255
|
+
const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
256
|
+
const day = String(date.getDate()).padStart(2, '0');
|
|
257
|
+
const random = Math.floor(Math.random() * 1000).toString().padStart(3, '0');
|
|
258
|
+
return `SPEC-${year}${month}${day}-${random}`;
|
|
259
|
+
}
|
|
260
|
+
//# sourceMappingURL=generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generator.js","sourceRoot":"","sources":["../../src/elicitation/generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Elicitation System
|
|
3
|
+
*
|
|
4
|
+
* Interactive specification elicitation workflows for SpecSafe.
|
|
5
|
+
* Guides users through structured question flows to create well-formed specs.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { ElicitationEngine, quickFlow, generateSpec } from '@specsafe/core';
|
|
10
|
+
*
|
|
11
|
+
* const engine = new ElicitationEngine(quickFlow);
|
|
12
|
+
* let step = engine.start();
|
|
13
|
+
*
|
|
14
|
+
* while (step) {
|
|
15
|
+
* const answer = await promptUser(step);
|
|
16
|
+
* step = engine.answer(step.id, answer);
|
|
17
|
+
* }
|
|
18
|
+
*
|
|
19
|
+
* const result = engine.getResult();
|
|
20
|
+
* const spec = generateSpec(result);
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export type { StepType, ValidateFn, ConditionFn, ElicitationStep, ElicitationFlow, ElicitationResult, } from './types.js';
|
|
24
|
+
export { ElicitationEngine } from './engine.js';
|
|
25
|
+
export { quickFlow, fullFlow, earsFlow } from './flows.js';
|
|
26
|
+
export { generateSpec } from './generator.js';
|
|
27
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/elicitation/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAGH,YAAY,EACV,QAAQ,EACR,UAAU,EACV,WAAW,EACX,eAAe,EACf,eAAe,EACf,iBAAiB,GAClB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAGhD,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAG3D,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC"}
|