@specsafe/core 0.4.0 → 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.
Files changed (81) hide show
  1. package/dist/agents/adapters/base.d.ts +44 -0
  2. package/dist/agents/adapters/base.d.ts.map +1 -0
  3. package/dist/agents/adapters/base.js +164 -0
  4. package/dist/agents/adapters/base.js.map +1 -0
  5. package/dist/agents/adapters/claude-code.d.ts +14 -0
  6. package/dist/agents/adapters/claude-code.d.ts.map +1 -0
  7. package/dist/agents/adapters/claude-code.js +120 -0
  8. package/dist/agents/adapters/claude-code.js.map +1 -0
  9. package/dist/agents/adapters/copilot.d.ts +13 -0
  10. package/dist/agents/adapters/copilot.d.ts.map +1 -0
  11. package/dist/agents/adapters/copilot.js +115 -0
  12. package/dist/agents/adapters/copilot.js.map +1 -0
  13. package/dist/agents/adapters/cursor.d.ts +13 -0
  14. package/dist/agents/adapters/cursor.d.ts.map +1 -0
  15. package/dist/agents/adapters/cursor.js +105 -0
  16. package/dist/agents/adapters/cursor.js.map +1 -0
  17. package/dist/agents/adapters/gemini-cli.d.ts +13 -0
  18. package/dist/agents/adapters/gemini-cli.d.ts.map +1 -0
  19. package/dist/agents/adapters/gemini-cli.js +79 -0
  20. package/dist/agents/adapters/gemini-cli.js.map +1 -0
  21. package/dist/agents/adapters/index.d.ts +16 -0
  22. package/dist/agents/adapters/index.d.ts.map +1 -0
  23. package/dist/agents/adapters/index.js +47 -0
  24. package/dist/agents/adapters/index.js.map +1 -0
  25. package/dist/agents/adapters/opencode.d.ts +13 -0
  26. package/dist/agents/adapters/opencode.d.ts.map +1 -0
  27. package/dist/agents/adapters/opencode.js +67 -0
  28. package/dist/agents/adapters/opencode.js.map +1 -0
  29. package/dist/agents/index.d.ts +8 -0
  30. package/dist/agents/index.d.ts.map +1 -0
  31. package/dist/agents/index.js +9 -0
  32. package/dist/agents/index.js.map +1 -0
  33. package/dist/agents/registry.d.ts +70 -0
  34. package/dist/agents/registry.d.ts.map +1 -0
  35. package/dist/agents/registry.js +194 -0
  36. package/dist/agents/registry.js.map +1 -0
  37. package/dist/agents/types.d.ts +71 -0
  38. package/dist/agents/types.d.ts.map +1 -0
  39. package/dist/agents/types.js +6 -0
  40. package/dist/agents/types.js.map +1 -0
  41. package/dist/delta/merger.d.ts +36 -0
  42. package/dist/delta/merger.d.ts.map +1 -0
  43. package/dist/delta/merger.js +264 -0
  44. package/dist/delta/merger.js.map +1 -0
  45. package/dist/delta/parser.d.ts +27 -0
  46. package/dist/delta/parser.d.ts.map +1 -0
  47. package/dist/delta/parser.js +196 -0
  48. package/dist/delta/parser.js.map +1 -0
  49. package/dist/delta/types.d.ts +39 -0
  50. package/dist/delta/types.d.ts.map +1 -0
  51. package/dist/delta/types.js +6 -0
  52. package/dist/delta/types.js.map +1 -0
  53. package/dist/ears/index.d.ts +11 -0
  54. package/dist/ears/index.d.ts.map +1 -0
  55. package/dist/ears/index.js +11 -0
  56. package/dist/ears/index.js.map +1 -0
  57. package/dist/ears/parser.d.ts +22 -0
  58. package/dist/ears/parser.d.ts.map +1 -0
  59. package/dist/ears/parser.js +273 -0
  60. package/dist/ears/parser.js.map +1 -0
  61. package/dist/ears/template.d.ts +20 -0
  62. package/dist/ears/template.d.ts.map +1 -0
  63. package/dist/ears/template.js +364 -0
  64. package/dist/ears/template.js.map +1 -0
  65. package/dist/ears/types.d.ts +58 -0
  66. package/dist/ears/types.d.ts.map +1 -0
  67. package/dist/ears/types.js +6 -0
  68. package/dist/ears/types.js.map +1 -0
  69. package/dist/ears/validator.d.ts +37 -0
  70. package/dist/ears/validator.d.ts.map +1 -0
  71. package/dist/ears/validator.js +234 -0
  72. package/dist/ears/validator.js.map +1 -0
  73. package/dist/index.d.ts +8 -0
  74. package/dist/index.d.ts.map +1 -1
  75. package/dist/index.js +6 -0
  76. package/dist/index.js.map +1 -1
  77. package/dist/templates/delta-template.d.ts +18 -0
  78. package/dist/templates/delta-template.d.ts.map +1 -0
  79. package/dist/templates/delta-template.js +191 -0
  80. package/dist/templates/delta-template.js.map +1 -0
  81. package/package.json +1 -1
@@ -0,0 +1,234 @@
1
+ /**
2
+ * EARS Validator
3
+ * Validates requirements against EARS patterns and suggests improvements
4
+ */
5
+ import { parseEARSRequirement } from './parser.js';
6
+ /**
7
+ * Validate all requirements in a spec for EARS compliance
8
+ */
9
+ export function validateRequirements(spec) {
10
+ const validations = [];
11
+ for (const requirement of spec.requirements) {
12
+ const validation = validateRequirement(requirement.text);
13
+ validations.push(validation);
14
+ }
15
+ // Calculate summary
16
+ const compliantCount = validations.filter(v => v.isCompliant).length;
17
+ const score = spec.requirements.length > 0
18
+ ? Math.round((compliantCount / spec.requirements.length) * 100)
19
+ : 0;
20
+ // Group by EARS type
21
+ const typeCounts = new Map();
22
+ for (const validation of validations) {
23
+ if (validation.earsRequirement) {
24
+ const type = validation.earsRequirement.type;
25
+ typeCounts.set(type, (typeCounts.get(type) || 0) + 1);
26
+ }
27
+ }
28
+ const summary = Array.from(typeCounts.entries()).map(([type, count]) => ({
29
+ type,
30
+ count
31
+ }));
32
+ // Generate recommendation
33
+ let recommendation = '';
34
+ if (score >= 90) {
35
+ recommendation = '✅ Excellent EARS compliance! Requirements are well-structured and testable.';
36
+ }
37
+ else if (score >= 70) {
38
+ recommendation = '⚠️ Good EARS compliance, but some requirements could be improved for better testability.';
39
+ }
40
+ else if (score >= 50) {
41
+ recommendation = '⚠️ Moderate EARS compliance. Consider rewriting requirements using EARS patterns.';
42
+ }
43
+ else {
44
+ recommendation = '❌ Low EARS compliance. Requirements should be rewritten using EARS patterns for testability.';
45
+ }
46
+ return {
47
+ score,
48
+ totalRequirements: spec.requirements.length,
49
+ compliantCount,
50
+ requirements: validations,
51
+ summary,
52
+ recommendation
53
+ };
54
+ }
55
+ /**
56
+ * Validate a single requirement text
57
+ *
58
+ * Note: A requirement is considered compliant (isCompliant = true) ONLY if it both:
59
+ * 1. Matches an EARS pattern with sufficient confidence, AND
60
+ * 2. Has zero quality issues (no ambiguous words, vague terms, etc.)
61
+ *
62
+ * @param text - The requirement text to validate
63
+ * @returns Validation result with compliance status, issues, and suggestions
64
+ */
65
+ export function validateRequirement(text) {
66
+ const earsRequirement = parseEARSRequirement(text);
67
+ const issues = [];
68
+ let isCompliant = false;
69
+ let suggestion;
70
+ // Check if it matches an EARS pattern
71
+ if (earsRequirement.type === 'unknown') {
72
+ issues.push('Does not follow any EARS pattern');
73
+ suggestion = generateEARSSuggestion(text);
74
+ }
75
+ else if (earsRequirement.confidence < 0.7) {
76
+ issues.push('Weak EARS pattern match');
77
+ suggestion = generateEARSSuggestion(text);
78
+ }
79
+ else {
80
+ isCompliant = true;
81
+ }
82
+ // Additional quality checks
83
+ if (!text.match(/\b(shall|must|will)\b/i)) {
84
+ issues.push('Missing modal verb (shall/must/will)');
85
+ }
86
+ if (text.split(' ').length < 5) {
87
+ issues.push('Requirement is too short - may lack necessary detail');
88
+ }
89
+ if (text.split(' ').length > 40) {
90
+ issues.push('Requirement is too long - consider splitting into multiple requirements');
91
+ }
92
+ // Check for ambiguous words
93
+ const ambiguousWords = ['should', 'may', 'might', 'could', 'possibly', 'probably', 'usually', 'maybe', 'perhaps'];
94
+ for (const word of ambiguousWords) {
95
+ if (new RegExp(`\\b${word}\\b`, 'i').test(text)) {
96
+ issues.push(`Contains ambiguous word: "${word}"`);
97
+ }
98
+ }
99
+ // Check for vague terms (precompiled with word boundaries to avoid false positives)
100
+ const vagueTerms = ['appropriate', 'adequate', 'reasonable', 'efficient', 'user-friendly', 'as needed'];
101
+ const vagueTermPatterns = vagueTerms.map(term => new RegExp(`\\b${term}\\b`, 'i'));
102
+ for (let i = 0; i < vagueTerms.length; i++) {
103
+ if (vagueTermPatterns[i].test(text)) {
104
+ issues.push(`Contains vague term: "${vagueTerms[i]}" - specify measurable criteria`);
105
+ }
106
+ }
107
+ return {
108
+ text,
109
+ isCompliant: isCompliant && issues.length === 0,
110
+ earsRequirement: earsRequirement.type !== 'unknown' ? earsRequirement : undefined,
111
+ issues,
112
+ suggestion
113
+ };
114
+ }
115
+ /**
116
+ * Generate an EARS-formatted suggestion for a non-compliant requirement
117
+ */
118
+ function generateEARSSuggestion(text) {
119
+ // Try to detect implicit patterns and suggest EARS format
120
+ // If it mentions a trigger condition, suggest event-driven
121
+ if (/\b(after|once|following|receives|detects|triggers)\b/i.test(text)) {
122
+ return `Consider event-driven EARS: "When [event occurs], the system shall [action]"\nExample: "When user submits the form, the system shall validate all fields"`;
123
+ }
124
+ // If it mentions a state, suggest state-driven
125
+ if (/\b(during|active|running|enabled|in\s+\w+\s+mode)\b/i.test(text)) {
126
+ return `Consider state-driven EARS: "While [state exists], the system shall [action]"\nExample: "While user is logged in, the system shall display the dashboard"`;
127
+ }
128
+ // If it mentions a condition, suggest optional
129
+ if (/\b(if|when|in case|for|with)\b/i.test(text) && !/then/i.test(text)) {
130
+ return `Consider optional EARS: "Where [condition], the system shall [action]"\nExample: "Where user has admin privileges, the system shall allow access to settings"`;
131
+ }
132
+ // If it mentions error handling, suggest unwanted
133
+ if (/\b(error|fail|invalid|incorrect|wrong|exception)\b/i.test(text)) {
134
+ return `Consider unwanted behavior EARS: "If [unwanted condition], then the system shall [action]"\nExample: "If user enters invalid credentials, then the system shall display an error message"`;
135
+ }
136
+ // Default to ubiquitous
137
+ return `Consider ubiquitous EARS: "The system shall [action]"\nExample: "The system shall encrypt all sensitive data at rest"`;
138
+ }
139
+ /**
140
+ * Get EARS compliance score for a spec (0-100)
141
+ */
142
+ export function getEARSScore(spec) {
143
+ const result = validateRequirements(spec);
144
+ return result.score;
145
+ }
146
+ /**
147
+ * Check if a spec meets minimum EARS compliance threshold
148
+ * @param spec - The spec to check
149
+ * @param threshold - Minimum score (0-100)
150
+ * @param precomputedScore - Optional pre-computed score to avoid re-validation
151
+ */
152
+ export function meetsEARSThreshold(spec, threshold = 80, precomputedScore) {
153
+ const score = precomputedScore !== undefined ? precomputedScore : getEARSScore(spec);
154
+ return score >= threshold;
155
+ }
156
+ /**
157
+ * Generate a detailed EARS compliance report as markdown
158
+ */
159
+ export function generateEARSReport(spec) {
160
+ const result = validateRequirements(spec);
161
+ let report = `# EARS Compliance Report\n\n`;
162
+ report += `**Spec ID:** ${spec.id}\n`;
163
+ report += `**Spec Name:** ${spec.name}\n`;
164
+ report += `**Date:** ${new Date().toISOString().split('T')[0]}\n\n`;
165
+ report += `## Overall Score: ${result.score}/100\n\n`;
166
+ report += `${result.recommendation}\n\n`;
167
+ report += `### Summary\n`;
168
+ report += `- **Total Requirements:** ${result.totalRequirements}\n`;
169
+ report += `- **Compliant:** ${result.compliantCount}\n`;
170
+ report += `- **Non-Compliant:** ${result.totalRequirements - result.compliantCount}\n\n`;
171
+ if (result.summary.length > 0) {
172
+ report += `### Requirements by EARS Type\n\n`;
173
+ for (const { type, count } of result.summary) {
174
+ const emoji = getEARSTypeEmoji(type);
175
+ report += `- ${emoji} **${type}:** ${count}\n`;
176
+ }
177
+ report += `\n`;
178
+ }
179
+ report += `## Detailed Analysis\n\n`;
180
+ for (let i = 0; i < result.requirements.length; i++) {
181
+ const validation = result.requirements[i];
182
+ const status = validation.isCompliant ? '✅' : '❌';
183
+ report += `### ${status} Requirement ${i + 1}\n\n`;
184
+ report += `**Text:** "${validation.text}"\n\n`;
185
+ if (validation.earsRequirement && validation.earsRequirement.type !== 'unknown') {
186
+ const ears = validation.earsRequirement;
187
+ report += `**EARS Type:** ${ears.type}\n`;
188
+ report += `**Confidence:** ${Math.round(ears.confidence * 100)}%\n\n`;
189
+ if (ears.event)
190
+ report += `- **Event:** ${ears.event}\n`;
191
+ if (ears.state)
192
+ report += `- **State:** ${ears.state}\n`;
193
+ if (ears.condition)
194
+ report += `- **Condition:** ${ears.condition}\n`;
195
+ if (ears.unwantedCondition)
196
+ report += `- **Unwanted Condition:** ${ears.unwantedCondition}\n`;
197
+ if (ears.conditions) {
198
+ report += `- **Conditions:**\n`;
199
+ for (const cond of ears.conditions) {
200
+ report += ` - ${cond.type}: ${cond.value}\n`;
201
+ }
202
+ }
203
+ report += `- **Action:** ${ears.action}\n\n`;
204
+ }
205
+ if (validation.issues.length > 0) {
206
+ report += `**Issues:**\n`;
207
+ for (const issue of validation.issues) {
208
+ report += `- ⚠️ ${issue}\n`;
209
+ }
210
+ report += `\n`;
211
+ }
212
+ if (validation.suggestion) {
213
+ report += `**Suggestion:**\n${validation.suggestion}\n\n`;
214
+ }
215
+ report += `---\n\n`;
216
+ }
217
+ return report;
218
+ }
219
+ /**
220
+ * Get emoji for EARS type
221
+ */
222
+ function getEARSTypeEmoji(type) {
223
+ const emojis = {
224
+ ubiquitous: '🌐',
225
+ event: '⚡',
226
+ state: '🔄',
227
+ optional: '🔀',
228
+ unwanted: '🚫',
229
+ complex: '🔗',
230
+ unknown: '❓'
231
+ };
232
+ return emojis[type] || '❓';
233
+ }
234
+ //# sourceMappingURL=validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validator.js","sourceRoot":"","sources":["../../src/ears/validator.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -20,7 +20,15 @@
20
20
  * ```
21
21
  */
22
22
  export type { Spec, SpecStage, Requirement, Scenario, QAReport, TestResult, CoverageReport, Issue, ProjectState, SpecSummary, ProjectMetrics } from './types.js';
23
+ export type { DeltaSpec, DeltaRequirement, MergeResult, MergeConflict, MergeStats } from './delta/types.js';
23
24
  export { Workflow } from './workflow.js';
24
25
  export { ProjectTracker } from './tracker.js';
25
26
  export { validateSpecId } from './validation.js';
27
+ export { DeltaParser } from './delta/parser.js';
28
+ export { SemanticMerger } from './delta/merger.js';
29
+ export { generateDeltaTemplate, generateDeltaReadme } from './templates/delta-template.js';
30
+ export type { AgentDefinition, AgentAdapter, AgentRegistryEntry, GenerateOptions, GeneratedFile, } from './agents/index.js';
31
+ export { getAgent, listAgents, getSupportedAgents, isValidAgent, getAgentDefinition, AGENT_DEFINITIONS, } from './agents/index.js';
32
+ export type { EARSType, EARSRequirement, EARSValidationResult, RequirementValidation, } from './ears/index.js';
33
+ export { parseEARSRequirement, hasEARSKeywords, extractRequirements, validateRequirements, validateRequirement, getEARSScore, meetsEARSThreshold, generateEARSReport, generateEARSTemplate, generateEARSExamples, } from './ears/index.js';
26
34
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAGH,YAAY,EACV,IAAI,EACJ,SAAS,EACT,WAAW,EACX,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,cAAc,EACd,KAAK,EACL,YAAY,EACZ,WAAW,EACX,cAAc,EACf,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGzC,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAG9C,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAGH,YAAY,EACV,IAAI,EACJ,SAAS,EACT,WAAW,EACX,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,cAAc,EACd,KAAK,EACL,YAAY,EACZ,WAAW,EACX,cAAc,EACf,MAAM,YAAY,CAAC;AAGpB,YAAY,EACV,SAAS,EACT,gBAAgB,EAChB,WAAW,EACX,aAAa,EACb,UAAU,EACX,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGzC,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAG9C,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGjD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAG3F,YAAY,EACV,eAAe,EACf,YAAY,EACZ,kBAAkB,EAClB,eAAe,EACf,aAAa,GACd,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,QAAQ,EACR,UAAU,EACV,kBAAkB,EAClB,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAG3B,YAAY,EACV,QAAQ,EACR,eAAe,EACf,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,oBAAoB,EACpB,eAAe,EACf,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACnB,YAAY,EACZ,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,iBAAiB,CAAC"}
package/dist/index.js CHANGED
@@ -25,4 +25,10 @@ export { Workflow } from './workflow.js';
25
25
  export { ProjectTracker } from './tracker.js';
26
26
  // Validation utilities
27
27
  export { validateSpecId } from './validation.js';
28
+ // Delta system
29
+ export { DeltaParser } from './delta/parser.js';
30
+ export { SemanticMerger } from './delta/merger.js';
31
+ export { generateDeltaTemplate, generateDeltaReadme } from './templates/delta-template.js';
32
+ export { getAgent, listAgents, getSupportedAgents, isValidAgent, getAgentDefinition, AGENT_DEFINITIONS, } from './agents/index.js';
33
+ export { parseEARSRequirement, hasEARSKeywords, extractRequirements, validateRequirements, validateRequirement, getEARSScore, meetsEARSThreshold, generateEARSReport, generateEARSTemplate, generateEARSExamples, } from './ears/index.js';
28
34
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAiBH,kBAAkB;AAClB,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,kBAAkB;AAClB,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,uBAAuB;AACvB,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AA0BH,kBAAkB;AAClB,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,kBAAkB;AAClB,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,uBAAuB;AACvB,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEjD,eAAe;AACf,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAW3F,OAAO,EACL,QAAQ,EACR,UAAU,EACV,kBAAkB,EAClB,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAU3B,OAAO,EACL,oBAAoB,EACpB,eAAe,EACf,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACnB,YAAY,EACZ,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Delta Spec Template
3
+ * Template for creating delta specs (brownfield changes)
4
+ */
5
+ /**
6
+ * Generate a delta spec template
7
+ * @param deltaId - Delta spec identifier
8
+ * @param baseSpecId - Base spec this delta applies to
9
+ * @param author - Author name
10
+ * @param date - Optional date for testability (defaults to today)
11
+ */
12
+ export declare function generateDeltaTemplate(deltaId: string, baseSpecId: string, author: string, date?: string): string;
13
+ /**
14
+ * Generate a README file explaining the delta spec format
15
+ * @returns Markdown content for delta spec documentation
16
+ */
17
+ export declare function generateDeltaReadme(): string;
18
+ //# sourceMappingURL=delta-template.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delta-template.d.ts","sourceRoot":"","sources":["../../src/templates/delta-template.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,IAAI,CAAC,EAAE,MAAM,GACZ,MAAM,CAgGR;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CA8E5C"}
@@ -0,0 +1,191 @@
1
+ /**
2
+ * Delta Spec Template
3
+ * Template for creating delta specs (brownfield changes)
4
+ */
5
+ /**
6
+ * Generate a delta spec template
7
+ * @param deltaId - Delta spec identifier
8
+ * @param baseSpecId - Base spec this delta applies to
9
+ * @param author - Author name
10
+ * @param date - Optional date for testability (defaults to today)
11
+ */
12
+ export function generateDeltaTemplate(deltaId, baseSpecId, author, date) {
13
+ const createdDate = date || new Date().toISOString().split('T')[0];
14
+ return `# Delta Spec: ${deltaId}
15
+
16
+ **Base Spec:** ${baseSpecId}
17
+ **Created:** ${createdDate}
18
+ **Author:** ${author}
19
+ **Description:** Brief description of changes
20
+
21
+ ---
22
+
23
+ ## Change Summary
24
+
25
+ What is changing and why?
26
+
27
+ ---
28
+
29
+ ## ADDED Requirements
30
+
31
+ New requirements being added to the spec.
32
+
33
+ ### FR-NEW-1
34
+ **Priority:** P1
35
+
36
+ [Requirement text here]
37
+
38
+ **Scenarios:**
39
+ - Given [context]
40
+ - When [action]
41
+ - Then [outcome]
42
+
43
+ ---
44
+
45
+ ## MODIFIED Requirements
46
+
47
+ Existing requirements being changed.
48
+
49
+ ### FR-EXISTING-1
50
+ **Priority:** P0
51
+
52
+ [New requirement text] ← (was [old requirement text])
53
+
54
+ **Scenarios:**
55
+ - [Updated scenarios]
56
+
57
+ ---
58
+
59
+ ## REMOVED Requirements
60
+
61
+ Requirements being removed (just list IDs).
62
+
63
+ - FR-OLD-1
64
+ - FR-OLD-2
65
+
66
+ ---
67
+
68
+ ## Impact Analysis
69
+
70
+ ### Affected Components
71
+ - Component 1
72
+ - Component 2
73
+
74
+ ### Breaking Changes
75
+ - [ ] Yes
76
+ - [x] No
77
+
78
+ ### Migration Required
79
+ - [ ] Yes
80
+ - [x] No
81
+
82
+ If yes, describe migration path:
83
+
84
+ ---
85
+
86
+ ## Testing Strategy
87
+
88
+ ### Tests to Add
89
+ -
90
+
91
+ ### Tests to Update
92
+ -
93
+
94
+ ### Tests to Remove
95
+ -
96
+
97
+ ---
98
+
99
+ ## Notes
100
+
101
+ Additional context, links, or references.
102
+
103
+ ---
104
+
105
+ *Generated by SpecSafe Delta System*
106
+ `;
107
+ }
108
+ /**
109
+ * Generate a README file explaining the delta spec format
110
+ * @returns Markdown content for delta spec documentation
111
+ */
112
+ export function generateDeltaReadme() {
113
+ return `# Delta Specs
114
+
115
+ Delta specs describe **incremental changes** to existing specs (brownfield projects).
116
+
117
+ ## Format
118
+
119
+ Delta specs use three sections:
120
+
121
+ ### ADDED Requirements
122
+ New requirements being added. Each requirement includes:
123
+ - **ID**: Unique requirement ID (e.g., FR-NEW-1)
124
+ - **Priority**: P0, P1, or P2
125
+ - **Text**: Requirement description
126
+ - **Scenarios**: Given/When/Then scenarios
127
+
128
+ ### MODIFIED Requirements
129
+ Existing requirements being changed. Use the notation:
130
+ \`\`\`
131
+ [New text] ← (was [old text])
132
+ \`\`\`
133
+
134
+ ### REMOVED Requirements
135
+ Requirements being removed. Just list the IDs:
136
+ \`\`\`
137
+ - FR-OLD-1
138
+ - FR-OLD-2
139
+ \`\`\`
140
+
141
+ ## Workflow
142
+
143
+ 1. **Create Delta**: \`specsafe delta <spec-id>\`
144
+ - Opens a template for the delta spec
145
+ - Edit to describe changes
146
+
147
+ 2. **Preview Changes**: \`specsafe diff <spec-id>\`
148
+ - Shows what would change
149
+ - Identifies conflicts
150
+
151
+ 3. **Apply Delta**: \`specsafe apply <spec-id>\`
152
+ - Merges changes into base spec
153
+ - Creates backup before applying
154
+
155
+ ## Best Practices
156
+
157
+ - Keep deltas focused (one feature/fix at a time)
158
+ - Include clear change justification
159
+ - Document breaking changes
160
+ - Update tests alongside requirements
161
+ - Review conflicts before applying
162
+
163
+ ## Example
164
+
165
+ \`\`\`markdown
166
+ ## ADDED Requirements
167
+
168
+ ### FR-AUTH-3
169
+ **Priority:** P0
170
+
171
+ Users must be able to reset their password via email verification.
172
+
173
+ **Scenarios:**
174
+ - Given user is on login page
175
+ - When user clicks "Forgot Password"
176
+ - Then system sends reset link to registered email
177
+
178
+ ## MODIFIED Requirements
179
+
180
+ ### FR-AUTH-1
181
+ **Priority:** P0
182
+
183
+ Users must authenticate using email and password with 2FA enabled ← (was Users must authenticate using email and password)
184
+
185
+ ## REMOVED Requirements
186
+
187
+ - FR-AUTH-OLD-1
188
+ \`\`\`
189
+ `;
190
+ }
191
+ //# sourceMappingURL=delta-template.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delta-template.js","sourceRoot":"","sources":["../../src/templates/delta-template.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CACnC,OAAe,EACf,UAAkB,EAClB,MAAc,EACd,IAAa;IAEb,MAAM,WAAW,GAAG,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAEnE,OAAO,iBAAiB,OAAO;;iBAEhB,UAAU;eACZ,WAAW;cACZ,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwFnB,CAAC;AACF,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB;IACjC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4ER,CAAC;AACF,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@specsafe/core",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Core types and workflow engine for SpecSafe",
5
5
  "type": "module",
6
6
  "engines": {