@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,364 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EARS Template Generator
|
|
3
|
+
* Creates spec templates with EARS requirement format
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Generate an EARS-formatted spec template
|
|
7
|
+
*/
|
|
8
|
+
export function generateEARSTemplate(id, name, author, priority = 'P1') {
|
|
9
|
+
const today = new Date().toISOString().split('T')[0];
|
|
10
|
+
return `# ${name} Specification (EARS Format)
|
|
11
|
+
|
|
12
|
+
**ID:** ${id}
|
|
13
|
+
**Status:** SPEC
|
|
14
|
+
**Created:** ${today}
|
|
15
|
+
**Author:** ${author}
|
|
16
|
+
**Priority:** ${priority}
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## EARS Guide
|
|
21
|
+
|
|
22
|
+
This spec uses **EARS (Easy Approach to Requirements Syntax)** for testable requirements.
|
|
23
|
+
|
|
24
|
+
### EARS Patterns
|
|
25
|
+
|
|
26
|
+
#### 🌐 Ubiquitous (Always Active)
|
|
27
|
+
**Pattern:** "The system shall [action]"
|
|
28
|
+
**Use when:** Requirement applies at all times, no conditions
|
|
29
|
+
|
|
30
|
+
**Example:**
|
|
31
|
+
- The system shall encrypt all data at rest using AES-256
|
|
32
|
+
- The system shall log all authentication attempts
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
#### ⚡ Event-Driven (Triggered by Events)
|
|
37
|
+
**Pattern:** "When [event], the system shall [action]"
|
|
38
|
+
**Use when:** Requirement is triggered by a specific event
|
|
39
|
+
|
|
40
|
+
**Example:**
|
|
41
|
+
- When user clicks "Submit", the system shall validate all form fields
|
|
42
|
+
- When payment is received, the system shall send a confirmation email
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
#### 🔄 State-Driven (Active During State)
|
|
47
|
+
**Pattern:** "While [state], the system shall [action]"
|
|
48
|
+
**Use when:** Requirement applies during a specific state
|
|
49
|
+
|
|
50
|
+
**Example:**
|
|
51
|
+
- While user session is active, the system shall refresh the authentication token every 30 minutes
|
|
52
|
+
- While processing a transaction, the system shall prevent duplicate submissions
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
#### 🔀 Optional (Feature Available)
|
|
57
|
+
**Pattern:** "Where [condition], the system shall [action]"
|
|
58
|
+
**Use when:** Requirement applies when optional feature/condition is present
|
|
59
|
+
|
|
60
|
+
**Example:**
|
|
61
|
+
- Where user has admin privileges, the system shall display the settings menu
|
|
62
|
+
- Where GPS is enabled, the system shall track location history
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
#### 🚫 Unwanted Behavior (Error Handling)
|
|
67
|
+
**Pattern:** "If [unwanted condition], then the system shall [action]"
|
|
68
|
+
**Use when:** Requirement handles errors or unwanted states
|
|
69
|
+
|
|
70
|
+
**Example:**
|
|
71
|
+
- If network connection is lost, then the system shall queue requests for retry
|
|
72
|
+
- If user enters invalid credentials 3 times, then the system shall lock the account
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
#### 🔗 Complex (Multiple Conditions)
|
|
77
|
+
**Pattern:** "When [event], while [state], the system shall [action]"
|
|
78
|
+
**Use when:** Multiple conditions must be met
|
|
79
|
+
|
|
80
|
+
**Example:**
|
|
81
|
+
- When user uploads a file, while file size exceeds 10MB, the system shall compress the file
|
|
82
|
+
- Where user has premium subscription, when downloading content, the system shall allow offline access
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## PRD (Product Requirements Document)
|
|
87
|
+
|
|
88
|
+
### Problem Statement
|
|
89
|
+
<!-- Describe the problem this feature solves -->
|
|
90
|
+
|
|
91
|
+
### User Stories
|
|
92
|
+
\`\`\`
|
|
93
|
+
As a [type of user]
|
|
94
|
+
I want [some goal]
|
|
95
|
+
So that [some reason]
|
|
96
|
+
\`\`\`
|
|
97
|
+
|
|
98
|
+
### Success Criteria
|
|
99
|
+
- [ ] All requirements follow EARS patterns
|
|
100
|
+
- [ ] All requirements are testable
|
|
101
|
+
- [ ] All tests pass
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Requirements (EARS Format)
|
|
106
|
+
|
|
107
|
+
### Functional Requirements
|
|
108
|
+
|
|
109
|
+
| ID | EARS Pattern | Requirement | Priority |
|
|
110
|
+
|----|--------------|-------------|----------|
|
|
111
|
+
| FR-1 | Ubiquitous | The system shall [action] | P0 |
|
|
112
|
+
| FR-2 | Event | When [event], the system shall [action] | P0 |
|
|
113
|
+
| FR-3 | State | While [state], the system shall [action] | P1 |
|
|
114
|
+
| FR-4 | Optional | Where [condition], the system shall [action] | P1 |
|
|
115
|
+
| FR-5 | Unwanted | If [error], then the system shall [action] | P2 |
|
|
116
|
+
|
|
117
|
+
**Example Requirements:**
|
|
118
|
+
- **Ubiquitous:** The system shall store all user data in encrypted format
|
|
119
|
+
- **Event-driven:** When user completes checkout, the system shall generate an order confirmation
|
|
120
|
+
- **State-driven:** While user is in offline mode, the system shall cache all changes locally
|
|
121
|
+
- **Optional:** Where user enables notifications, the system shall send real-time alerts
|
|
122
|
+
- **Unwanted:** If API request fails, then the system shall retry with exponential backoff
|
|
123
|
+
|
|
124
|
+
### Non-Functional Requirements
|
|
125
|
+
|
|
126
|
+
| ID | EARS Pattern | Requirement | Metric |
|
|
127
|
+
|----|--------------|-------------|--------|
|
|
128
|
+
| NFR-1 | Ubiquitous | The system shall respond to requests | < 200ms (p95) |
|
|
129
|
+
| NFR-2 | State | While under peak load, the system shall maintain availability | > 99.9% |
|
|
130
|
+
|
|
131
|
+
**Example Requirements:**
|
|
132
|
+
- The system shall handle up to 10,000 concurrent users
|
|
133
|
+
- While processing batch jobs, the system shall maintain CPU usage below 80%
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## Scenarios (Given/When/Then)
|
|
138
|
+
|
|
139
|
+
EARS requirements naturally map to test scenarios:
|
|
140
|
+
|
|
141
|
+
### Scenario 1: [EARS Pattern Type]
|
|
142
|
+
**Requirement:** [Copy EARS requirement here]
|
|
143
|
+
|
|
144
|
+
- **Given** [initial state/context]
|
|
145
|
+
- **When** [action/event occurs]
|
|
146
|
+
- **Then** [expected outcome matching the EARS action]
|
|
147
|
+
|
|
148
|
+
**Example:**
|
|
149
|
+
**Requirement:** When user submits payment form, the system shall validate credit card number
|
|
150
|
+
|
|
151
|
+
- **Given** user has entered payment information
|
|
152
|
+
- **When** user clicks "Pay Now" button
|
|
153
|
+
- **Then** system validates card number format
|
|
154
|
+
- **And** system displays validation errors if invalid
|
|
155
|
+
- **And** system processes payment if valid
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
### Scenario 2: [Another Pattern]
|
|
160
|
+
**Requirement:** [Another EARS requirement]
|
|
161
|
+
|
|
162
|
+
- **Given** [context]
|
|
163
|
+
- **When** [trigger]
|
|
164
|
+
- **Then** [outcome]
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## Technical Approach
|
|
169
|
+
|
|
170
|
+
### Implementation Checklist
|
|
171
|
+
For each EARS requirement:
|
|
172
|
+
- [ ] Write unit test matching the EARS action
|
|
173
|
+
- [ ] Implement the action handler
|
|
174
|
+
- [ ] Add integration test for the complete flow
|
|
175
|
+
- [ ] Verify error handling (for "unwanted" patterns)
|
|
176
|
+
|
|
177
|
+
### Testing Strategy
|
|
178
|
+
|
|
179
|
+
**Event-driven requirements:**
|
|
180
|
+
- Test the event trigger
|
|
181
|
+
- Test the action execution
|
|
182
|
+
- Test edge cases (event occurs multiple times, etc.)
|
|
183
|
+
|
|
184
|
+
**State-driven requirements:**
|
|
185
|
+
- Test state entry/exit
|
|
186
|
+
- Test action during state
|
|
187
|
+
- Test behavior outside the state
|
|
188
|
+
|
|
189
|
+
**Unwanted behavior requirements:**
|
|
190
|
+
- Test the error condition
|
|
191
|
+
- Test the recovery action
|
|
192
|
+
- Test system state after recovery
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## EARS Quality Checklist
|
|
197
|
+
|
|
198
|
+
Before moving to TEST stage, verify:
|
|
199
|
+
|
|
200
|
+
- [ ] All requirements use EARS patterns (ubiquitous, event, state, optional, unwanted, or complex)
|
|
201
|
+
- [ ] Each requirement has exactly one "shall" statement
|
|
202
|
+
- [ ] Each requirement is testable (can write pass/fail test)
|
|
203
|
+
- [ ] No ambiguous words (should, may, might, could)
|
|
204
|
+
- [ ] No vague terms (appropriate, reasonable, user-friendly)
|
|
205
|
+
- [ ] Modal verbs are consistent (shall/must/will, not mixed)
|
|
206
|
+
- [ ] Requirements are atomic (one requirement = one capability)
|
|
207
|
+
- [ ] Complex requirements are justified (can't be split)
|
|
208
|
+
|
|
209
|
+
Run: \`specsafe qa ${id} --ears\` to validate EARS compliance
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## Notes
|
|
214
|
+
|
|
215
|
+
### EARS Benefits
|
|
216
|
+
1. **Testability:** Each pattern directly maps to test scenarios
|
|
217
|
+
2. **Clarity:** Explicit triggers and conditions
|
|
218
|
+
3. **Completeness:** Forces you to think about edge cases (unwanted behavior)
|
|
219
|
+
4. **Consistency:** Standardized language across team
|
|
220
|
+
|
|
221
|
+
### Common Mistakes
|
|
222
|
+
- ❌ "The system should validate input" → Use "shall" not "should"
|
|
223
|
+
- ❌ "The system shall be fast" → Specify measurable criteria
|
|
224
|
+
- ❌ "When user clicks button, system processes data" → Add "the system shall"
|
|
225
|
+
- ❌ "The system shall validate and save data" → Split into two requirements
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
*Generated by SpecSafe with EARS format*
|
|
230
|
+
`;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Generate EARS examples for a specific domain
|
|
234
|
+
*/
|
|
235
|
+
export function generateEARSExamples(domain) {
|
|
236
|
+
const examples = {
|
|
237
|
+
web: {
|
|
238
|
+
ubiquitous: [
|
|
239
|
+
'The system shall use HTTPS for all connections',
|
|
240
|
+
'The system shall validate all user inputs before processing',
|
|
241
|
+
'The system shall maintain session state using secure cookies'
|
|
242
|
+
],
|
|
243
|
+
event: [
|
|
244
|
+
'When user submits the form, the system shall validate all required fields',
|
|
245
|
+
'When page load time exceeds 3 seconds, the system shall display a loading indicator',
|
|
246
|
+
'When user clicks logout, the system shall clear all session data'
|
|
247
|
+
],
|
|
248
|
+
state: [
|
|
249
|
+
'While user is authenticated, the system shall display the user dashboard',
|
|
250
|
+
'While form validation is in progress, the system shall disable the submit button',
|
|
251
|
+
'While processing payment, the system shall prevent duplicate submissions'
|
|
252
|
+
],
|
|
253
|
+
optional: [
|
|
254
|
+
'Where user has enabled dark mode, the system shall apply dark color scheme',
|
|
255
|
+
'Where user has admin role, the system shall display administrative controls',
|
|
256
|
+
'Where browser supports service workers, the system shall enable offline mode'
|
|
257
|
+
],
|
|
258
|
+
unwanted: [
|
|
259
|
+
'If session expires, then the system shall redirect to login page',
|
|
260
|
+
'If API request fails, then the system shall display error message to user',
|
|
261
|
+
'If user enters invalid email format, then the system shall show format hint'
|
|
262
|
+
],
|
|
263
|
+
complex: [
|
|
264
|
+
'When user uploads a file, while file size exceeds 5MB, the system shall compress the file before upload',
|
|
265
|
+
'Where user has premium subscription, when downloading content, the system shall allow offline access'
|
|
266
|
+
]
|
|
267
|
+
},
|
|
268
|
+
mobile: {
|
|
269
|
+
ubiquitous: [
|
|
270
|
+
'The system shall support iOS 15.0 and later',
|
|
271
|
+
'The system shall cache user preferences locally',
|
|
272
|
+
'The system shall request user permission before accessing location data'
|
|
273
|
+
],
|
|
274
|
+
event: [
|
|
275
|
+
'When app enters background, the system shall save current state',
|
|
276
|
+
'When user pulls to refresh, the system shall reload content from server',
|
|
277
|
+
'When notification is received, the system shall display badge count'
|
|
278
|
+
],
|
|
279
|
+
state: [
|
|
280
|
+
'While app is in offline mode, the system shall queue all network requests',
|
|
281
|
+
'While device battery is below 20%, the system shall reduce background sync frequency',
|
|
282
|
+
'While user is viewing media, the system shall prevent screen lock'
|
|
283
|
+
],
|
|
284
|
+
optional: [
|
|
285
|
+
'Where device supports biometric authentication, the system shall offer fingerprint login',
|
|
286
|
+
'Where user grants camera permission, the system shall enable photo upload',
|
|
287
|
+
'Where device supports push notifications, the system shall enable real-time alerts'
|
|
288
|
+
],
|
|
289
|
+
unwanted: [
|
|
290
|
+
'If network connection is lost, then the system shall display offline banner',
|
|
291
|
+
'If location permission is denied, then the system shall use default location',
|
|
292
|
+
'If app crashes, then the system shall restore previous state on relaunch'
|
|
293
|
+
],
|
|
294
|
+
complex: [
|
|
295
|
+
'When user takes a photo, while storage is nearly full, the system shall compress image quality',
|
|
296
|
+
'Where user has disabled cellular data, when uploading content, the system shall wait for WiFi connection'
|
|
297
|
+
]
|
|
298
|
+
},
|
|
299
|
+
api: {
|
|
300
|
+
ubiquitous: [
|
|
301
|
+
'The system shall authenticate all API requests using JWT tokens',
|
|
302
|
+
'The system shall rate limit requests to 100 per minute per API key',
|
|
303
|
+
'The system shall log all API requests with timestamp and user ID'
|
|
304
|
+
],
|
|
305
|
+
event: [
|
|
306
|
+
'When API receives POST request, the system shall validate request body schema',
|
|
307
|
+
'When rate limit is exceeded, the system shall return 429 Too Many Requests',
|
|
308
|
+
'When authentication fails, the system shall return 401 Unauthorized'
|
|
309
|
+
],
|
|
310
|
+
state: [
|
|
311
|
+
'While maintenance mode is active, the system shall return 503 Service Unavailable',
|
|
312
|
+
'While processing webhook, the system shall prevent concurrent processing of same event',
|
|
313
|
+
'While database connection is unavailable, the system shall return 503 with retry-after header'
|
|
314
|
+
],
|
|
315
|
+
optional: [
|
|
316
|
+
'Where client provides API version header, the system shall use specified API version',
|
|
317
|
+
'Where request includes pagination parameters, the system shall return paginated results',
|
|
318
|
+
'Where client supports compression, the system shall compress response with gzip'
|
|
319
|
+
],
|
|
320
|
+
unwanted: [
|
|
321
|
+
'If request payload exceeds 10MB, then the system shall return 413 Payload Too Large',
|
|
322
|
+
'If database query times out, then the system shall return 504 Gateway Timeout',
|
|
323
|
+
'If request contains invalid JSON, then the system shall return 400 Bad Request with error details'
|
|
324
|
+
],
|
|
325
|
+
complex: [
|
|
326
|
+
'When API receives file upload, while file type is not allowed, the system shall return 415 Unsupported Media Type',
|
|
327
|
+
'Where request includes webhook callback URL, when processing completes, the system shall POST results to callback'
|
|
328
|
+
]
|
|
329
|
+
},
|
|
330
|
+
embedded: {
|
|
331
|
+
ubiquitous: [
|
|
332
|
+
'The system shall monitor sensor readings every 100ms',
|
|
333
|
+
'The system shall maintain operation within temperature range -40°C to 85°C',
|
|
334
|
+
'The system shall consume less than 500mW in active mode'
|
|
335
|
+
],
|
|
336
|
+
event: [
|
|
337
|
+
'When button is pressed, the system shall debounce input for 50ms',
|
|
338
|
+
'When power supply drops below 3.3V, the system shall trigger low battery warning',
|
|
339
|
+
'When sensor detects motion, the system shall activate recording mode'
|
|
340
|
+
],
|
|
341
|
+
state: [
|
|
342
|
+
'While in sleep mode, the system shall reduce power consumption to < 10μW',
|
|
343
|
+
'While calibrating sensors, the system shall ignore external inputs',
|
|
344
|
+
'While firmware update is in progress, the system shall disable all other operations'
|
|
345
|
+
],
|
|
346
|
+
optional: [
|
|
347
|
+
'Where external RTC is available, the system shall use hardware clock',
|
|
348
|
+
'Where temperature sensor is connected, the system shall log temperature data',
|
|
349
|
+
'Where SD card is inserted, the system shall store logs to external storage'
|
|
350
|
+
],
|
|
351
|
+
unwanted: [
|
|
352
|
+
'If watchdog timer expires, then the system shall perform hardware reset',
|
|
353
|
+
'If sensor reading is out of range, then the system shall use last known good value',
|
|
354
|
+
'If memory allocation fails, then the system shall log error and continue with reduced functionality'
|
|
355
|
+
],
|
|
356
|
+
complex: [
|
|
357
|
+
'When motion is detected, while device is in power-save mode, the system shall wake up and begin recording',
|
|
358
|
+
'Where battery level is below 10%, when sensor reading is requested, the system shall reduce sampling rate to conserve power'
|
|
359
|
+
]
|
|
360
|
+
}
|
|
361
|
+
};
|
|
362
|
+
return examples[domain];
|
|
363
|
+
}
|
|
364
|
+
//# sourceMappingURL=template.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template.js","sourceRoot":"","sources":["../../src/ears/template.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EARS (Easy Approach to Requirements Syntax) Types
|
|
3
|
+
* Defines structured requirement patterns for testability
|
|
4
|
+
*/
|
|
5
|
+
export type EARSType = 'ubiquitous' | 'event' | 'state' | 'optional' | 'unwanted' | 'complex' | 'unknown';
|
|
6
|
+
export interface EARSRequirement {
|
|
7
|
+
/** Original requirement text */
|
|
8
|
+
text: string;
|
|
9
|
+
/** EARS pattern type */
|
|
10
|
+
type: EARSType;
|
|
11
|
+
/** Event trigger (for event-driven requirements) */
|
|
12
|
+
event?: string;
|
|
13
|
+
/** State condition (for state-driven requirements) */
|
|
14
|
+
state?: string;
|
|
15
|
+
/** Optional condition (for optional requirements) */
|
|
16
|
+
condition?: string;
|
|
17
|
+
/** Unwanted condition (for unwanted behavior requirements) */
|
|
18
|
+
unwantedCondition?: string;
|
|
19
|
+
/** The system action/response */
|
|
20
|
+
action: string;
|
|
21
|
+
/** For complex requirements with multiple conditions */
|
|
22
|
+
conditions?: {
|
|
23
|
+
type: 'event' | 'state' | 'optional';
|
|
24
|
+
value: string;
|
|
25
|
+
}[];
|
|
26
|
+
/** Confidence score (0-1) that this matches EARS pattern */
|
|
27
|
+
confidence: number;
|
|
28
|
+
}
|
|
29
|
+
export interface EARSValidationResult {
|
|
30
|
+
/** Overall EARS compliance score (0-100) */
|
|
31
|
+
score: number;
|
|
32
|
+
/** Total requirements analyzed */
|
|
33
|
+
totalRequirements: number;
|
|
34
|
+
/** Number of EARS-compliant requirements */
|
|
35
|
+
compliantCount: number;
|
|
36
|
+
/** Detailed validation for each requirement */
|
|
37
|
+
requirements: RequirementValidation[];
|
|
38
|
+
/** Summary by EARS type */
|
|
39
|
+
summary: {
|
|
40
|
+
type: EARSType;
|
|
41
|
+
count: number;
|
|
42
|
+
}[];
|
|
43
|
+
/** Overall recommendation */
|
|
44
|
+
recommendation: string;
|
|
45
|
+
}
|
|
46
|
+
export interface RequirementValidation {
|
|
47
|
+
/** Original requirement text */
|
|
48
|
+
text: string;
|
|
49
|
+
/** Whether it follows EARS pattern */
|
|
50
|
+
isCompliant: boolean;
|
|
51
|
+
/** Detected EARS pattern (if any) */
|
|
52
|
+
earsRequirement?: EARSRequirement;
|
|
53
|
+
/** Issues found */
|
|
54
|
+
issues: string[];
|
|
55
|
+
/** Suggested EARS rewrite */
|
|
56
|
+
suggestion?: string;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/ears/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,MAAM,QAAQ,GAChB,YAAY,GACZ,OAAO,GACP,OAAO,GACP,UAAU,GACV,UAAU,GACV,SAAS,GACT,SAAS,CAAC;AAEd,MAAM,WAAW,eAAe;IAC9B,gCAAgC;IAChC,IAAI,EAAE,MAAM,CAAC;IAEb,wBAAwB;IACxB,IAAI,EAAE,QAAQ,CAAC;IAEf,oDAAoD;IACpD,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,sDAAsD;IACtD,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,qDAAqD;IACrD,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,8DAA8D;IAC9D,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B,iCAAiC;IACjC,MAAM,EAAE,MAAM,CAAC;IAEf,wDAAwD;IACxD,UAAU,CAAC,EAAE;QACX,IAAI,EAAE,OAAO,GAAG,OAAO,GAAG,UAAU,CAAC;QACrC,KAAK,EAAE,MAAM,CAAC;KACf,EAAE,CAAC;IAEJ,4DAA4D;IAC5D,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,oBAAoB;IACnC,4CAA4C;IAC5C,KAAK,EAAE,MAAM,CAAC;IAEd,kCAAkC;IAClC,iBAAiB,EAAE,MAAM,CAAC;IAE1B,4CAA4C;IAC5C,cAAc,EAAE,MAAM,CAAC;IAEvB,+CAA+C;IAC/C,YAAY,EAAE,qBAAqB,EAAE,CAAC;IAEtC,2BAA2B;IAC3B,OAAO,EAAE;QACP,IAAI,EAAE,QAAQ,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;KACf,EAAE,CAAC;IAEJ,6BAA6B;IAC7B,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,qBAAqB;IACpC,gCAAgC;IAChC,IAAI,EAAE,MAAM,CAAC;IAEb,sCAAsC;IACtC,WAAW,EAAE,OAAO,CAAC;IAErB,qCAAqC;IACrC,eAAe,CAAC,EAAE,eAAe,CAAC;IAElC,mBAAmB;IACnB,MAAM,EAAE,MAAM,EAAE,CAAC;IAEjB,6BAA6B;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/ears/types.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EARS Validator
|
|
3
|
+
* Validates requirements against EARS patterns and suggests improvements
|
|
4
|
+
*/
|
|
5
|
+
import type { Spec } from '../types.js';
|
|
6
|
+
import type { EARSValidationResult, RequirementValidation } from './types.js';
|
|
7
|
+
/**
|
|
8
|
+
* Validate all requirements in a spec for EARS compliance
|
|
9
|
+
*/
|
|
10
|
+
export declare function validateRequirements(spec: Spec): EARSValidationResult;
|
|
11
|
+
/**
|
|
12
|
+
* Validate a single requirement text
|
|
13
|
+
*
|
|
14
|
+
* Note: A requirement is considered compliant (isCompliant = true) ONLY if it both:
|
|
15
|
+
* 1. Matches an EARS pattern with sufficient confidence, AND
|
|
16
|
+
* 2. Has zero quality issues (no ambiguous words, vague terms, etc.)
|
|
17
|
+
*
|
|
18
|
+
* @param text - The requirement text to validate
|
|
19
|
+
* @returns Validation result with compliance status, issues, and suggestions
|
|
20
|
+
*/
|
|
21
|
+
export declare function validateRequirement(text: string): RequirementValidation;
|
|
22
|
+
/**
|
|
23
|
+
* Get EARS compliance score for a spec (0-100)
|
|
24
|
+
*/
|
|
25
|
+
export declare function getEARSScore(spec: Spec): number;
|
|
26
|
+
/**
|
|
27
|
+
* Check if a spec meets minimum EARS compliance threshold
|
|
28
|
+
* @param spec - The spec to check
|
|
29
|
+
* @param threshold - Minimum score (0-100)
|
|
30
|
+
* @param precomputedScore - Optional pre-computed score to avoid re-validation
|
|
31
|
+
*/
|
|
32
|
+
export declare function meetsEARSThreshold(spec: Spec, threshold?: number, precomputedScore?: number): boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Generate a detailed EARS compliance report as markdown
|
|
35
|
+
*/
|
|
36
|
+
export declare function generateEARSReport(spec: Spec): string;
|
|
37
|
+
//# sourceMappingURL=validator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../src/ears/validator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAe,MAAM,aAAa,CAAC;AACrD,OAAO,KAAK,EAAE,oBAAoB,EAAE,qBAAqB,EAAY,MAAM,YAAY,CAAC;AAGxF;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,IAAI,GAAG,oBAAoB,CAgDrE;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,qBAAqB,CAuDvE;AAgCD;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAG/C;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,IAAI,EACV,SAAS,GAAE,MAAW,EACtB,gBAAgB,CAAC,EAAE,MAAM,GACxB,OAAO,CAGT;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAmErD"}
|