@specsafe/core 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Agentic Engineering
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,282 @@
1
+ # @specsafe/core
2
+
3
+ <p align="center">
4
+ <img src="https://img.shields.io/npm/v/@specsafe/core.svg" alt="npm version">
5
+ <img src="https://img.shields.io/npm/l/@specsafe/core.svg" alt="license">
6
+ </p>
7
+
8
+ Core workflow engine, types, and utilities for the SpecSafe spec-driven development framework.
9
+
10
+ ## Installation
11
+
12
+ ```bash
13
+ npm install @specsafe/core
14
+ ```
15
+
16
+ ## What It Provides
17
+
18
+ - **Workflow Engine** - Manage spec lifecycle from creation to archive
19
+ - **ProjectTracker** - Track project state and spec metadata
20
+ - **TypeScript Types** - Full type definitions for specs, requirements, and reports
21
+ - **Validation Utilities** - Schema validation and ID validation
22
+
23
+ ## API Reference
24
+
25
+ ### Workflow Class
26
+
27
+ The main class for managing spec workflows.
28
+
29
+ ```typescript
30
+ import { Workflow } from '@specsafe/core';
31
+
32
+ const workflow = new Workflow({
33
+ specsDir: './specs',
34
+ projectName: 'My Project'
35
+ });
36
+ ```
37
+
38
+ #### `createSpec(specId: string, content: string): Promise<Spec>`
39
+
40
+ Create a new specification.
41
+
42
+ ```typescript
43
+ const spec = await workflow.createSpec('user-auth', `# User Authentication
44
+
45
+ ## Requirements
46
+
47
+ ### REQ-001: Login
48
+ **Given** a registered user
49
+ **When** they enter valid credentials
50
+ **Then** they should be logged in
51
+ `);
52
+ ```
53
+
54
+ #### `moveToTest(specId: string): Promise<Spec>`
55
+
56
+ Move a spec to the "test" phase.
57
+
58
+ ```typescript
59
+ const spec = await workflow.moveToTest('user-auth');
60
+ ```
61
+
62
+ #### `moveToCode(specId: string): Promise<Spec>`
63
+
64
+ Move a spec to the "code" phase.
65
+
66
+ ```typescript
67
+ const spec = await workflow.moveToCode('user-auth');
68
+ ```
69
+
70
+ #### `moveToQA(specId: string, report?: QAReport): Promise<Spec>`
71
+
72
+ Transition a spec into QA review or mark QA as complete. Optionally accepts a QAReport to record results.
73
+
74
+ ```typescript
75
+ const spec = await workflow.moveToQA('user-auth', {
76
+ passed: true,
77
+ notes: 'All tests passing'
78
+ });
79
+ ```
80
+
81
+ #### `complete(specId: string): Promise<Spec>`
82
+
83
+ Mark a spec as complete.
84
+
85
+ ```typescript
86
+ const spec = await workflow.complete('user-auth');
87
+ ```
88
+
89
+ #### `archive(specId: string): Promise<Spec>`
90
+
91
+ Archive a completed spec.
92
+
93
+ ```typescript
94
+ const spec = await workflow.archive('user-auth');
95
+ ```
96
+
97
+ #### `getSpec(specId: string): Promise<Spec | null>`
98
+
99
+ Get a spec by ID.
100
+
101
+ ```typescript
102
+ const spec = await workflow.getSpec('user-auth');
103
+ ```
104
+
105
+ #### `listSpecs(phase?: Phase): Promise<Spec[]>`
106
+
107
+ List all specs or filter by phase.
108
+
109
+ ```typescript
110
+ // All specs
111
+ const allSpecs = await workflow.listSpecs();
112
+
113
+ // Only active specs
114
+ const activeSpecs = await workflow.listSpecs('active');
115
+ ```
116
+
117
+ ---
118
+
119
+ ### ProjectTracker Class
120
+
121
+ Track project-level state and metadata.
122
+
123
+ ```typescript
124
+ import { ProjectTracker } from '@specsafe/core';
125
+
126
+ const tracker = new ProjectTracker('./specs');
127
+ ```
128
+
129
+ #### `getProjectState(): Promise<ProjectState>`
130
+
131
+ Get the current project state.
132
+
133
+ ```typescript
134
+ const state = await tracker.getProjectState();
135
+ console.log(state.activeSpecs.length);
136
+ console.log(state.completedSpecs.length);
137
+ ```
138
+
139
+ #### `updateSpecStatus(specId: string, status: SpecStatus): Promise<void>`
140
+
141
+ Update the status of a spec.
142
+
143
+ ```typescript
144
+ await tracker.updateSpecStatus('user-auth', 'in-progress');
145
+ ```
146
+
147
+ ---
148
+
149
+ ### Validation Utilities
150
+
151
+ #### `validateSpecId(specId: string): boolean`
152
+
153
+ Validate a spec ID format.
154
+
155
+ ```typescript
156
+ import { validateSpecId } from '@specsafe/core';
157
+
158
+ validateSpecId('user-auth'); // true
159
+ validateSpecId('user_auth'); // false (underscores not allowed)
160
+ validateSpecId('user-auth-123'); // true
161
+ ```
162
+
163
+ ---
164
+
165
+ ## TypeScript Types
166
+
167
+ ### Spec
168
+
169
+ ```typescript
170
+ interface Spec {
171
+ id: string;
172
+ title: string;
173
+ description: string;
174
+ phase: Phase;
175
+ status: SpecStatus;
176
+ requirements: Requirement[];
177
+ acceptanceCriteria: string[];
178
+ technicalNotes?: string;
179
+ createdAt: Date;
180
+ updatedAt: Date;
181
+ completedAt?: Date;
182
+ qaReport?: QAReport;
183
+ }
184
+ ```
185
+
186
+ ### Requirement
187
+
188
+ ```typescript
189
+ interface Requirement {
190
+ id: string;
191
+ title: string;
192
+ given: string;
193
+ when: string;
194
+ then: string;
195
+ }
196
+ ```
197
+
198
+ ### QAReport
199
+
200
+ ```typescript
201
+ interface QAReport {
202
+ passed: boolean;
203
+ notes?: string;
204
+ testedAt: Date;
205
+ testedBy?: string;
206
+ }
207
+ ```
208
+
209
+ ### Phase
210
+
211
+ ```typescript
212
+ type Phase = 'draft' | 'active' | 'test' | 'code' | 'qa' | 'completed' | 'archived';
213
+ ```
214
+
215
+ ### SpecStatus
216
+
217
+ ```typescript
218
+ type SpecStatus = 'pending' | 'in-progress' | 'blocked' | 'completed';
219
+ ```
220
+
221
+ ---
222
+
223
+ ## Usage Examples
224
+
225
+ ### Basic Workflow
226
+
227
+ ```typescript
228
+ import { Workflow } from '@specsafe/core';
229
+
230
+ async function main() {
231
+ const workflow = new Workflow({
232
+ specsDir: './specs',
233
+ projectName: 'My App'
234
+ });
235
+
236
+ // Create a spec
237
+ await workflow.createSpec('email-validation', `
238
+ # Email Validation
239
+
240
+ ## Requirements
241
+
242
+ ### REQ-001: Valid Email Format
243
+ **Given** an email input field
244
+ **When** the user enters "user@example.com"
245
+ **Then** the email should be marked as valid
246
+
247
+ ### REQ-002: Invalid Email Format
248
+ **Given** an email input field
249
+ **When** the user enters "invalid-email"
250
+ **Then** an error message should be shown
251
+ `);
252
+
253
+ // Move through phases
254
+ await workflow.moveToTest('email-validation');
255
+ await workflow.moveToCode('email-validation');
256
+ await workflow.moveToQA('email-validation', { passed: true });
257
+ await workflow.complete('email-validation');
258
+ }
259
+
260
+ main();
261
+ ```
262
+
263
+ ### Project Statistics
264
+
265
+ ```typescript
266
+ import { ProjectTracker } from '@specsafe/core';
267
+
268
+ async function printStats() {
269
+ const tracker = new ProjectTracker('./specs');
270
+ const state = await tracker.getProjectState();
271
+
272
+ console.log(`Active specs: ${state.activeSpecs.length}`);
273
+ console.log(`Completed: ${state.completedSpecs.length}`);
274
+ console.log(`Archived: ${state.archivedSpecs.length}`);
275
+ }
276
+ ```
277
+
278
+ ---
279
+
280
+ ## License
281
+
282
+ MIT © Agentic Engineering
@@ -0,0 +1,26 @@
1
+ /**
2
+ * SpecSafe Core - Workflow Engine and Types
3
+ *
4
+ * This package provides the core types and workflow engine for the SpecSafe
5
+ * Test-Driven Development framework.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { Workflow, ProjectTracker } from '@specsafe/core';
10
+ *
11
+ * const workflow = new Workflow();
12
+ * const spec = workflow.createSpec('auth-001', 'User Authentication', '...', 'dev', 'myapp');
13
+ *
14
+ * workflow.moveToTest(spec.id);
15
+ * workflow.moveToCode(spec.id);
16
+ * workflow.moveToQA(spec.id);
17
+ *
18
+ * // After QA passes
19
+ * workflow.moveToComplete(spec.id, qaReport);
20
+ * ```
21
+ */
22
+ export type { Spec, SpecStage, Requirement, Scenario, QAReport, TestResult, CoverageReport, Issue, ProjectState, SpecSummary, ProjectMetrics } from './types.js';
23
+ export { Workflow } from './workflow.js';
24
+ export { ProjectTracker } from './tracker.js';
25
+ export { validateSpecId } from './validation.js';
26
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +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"}
package/dist/index.js ADDED
@@ -0,0 +1,28 @@
1
+ /**
2
+ * SpecSafe Core - Workflow Engine and Types
3
+ *
4
+ * This package provides the core types and workflow engine for the SpecSafe
5
+ * Test-Driven Development framework.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { Workflow, ProjectTracker } from '@specsafe/core';
10
+ *
11
+ * const workflow = new Workflow();
12
+ * const spec = workflow.createSpec('auth-001', 'User Authentication', '...', 'dev', 'myapp');
13
+ *
14
+ * workflow.moveToTest(spec.id);
15
+ * workflow.moveToCode(spec.id);
16
+ * workflow.moveToQA(spec.id);
17
+ *
18
+ * // After QA passes
19
+ * workflow.moveToComplete(spec.id, qaReport);
20
+ * ```
21
+ */
22
+ // Workflow engine
23
+ export { Workflow } from './workflow.js';
24
+ // Project tracker
25
+ export { ProjectTracker } from './tracker.js';
26
+ // Validation utilities
27
+ export { validateSpecId } from './validation.js';
28
+ //# sourceMappingURL=index.js.map
@@ -0,0 +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"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * SpecSafe Project State Tracker
3
+ * Manages PROJECT_STATE.md for tracking all specs
4
+ */
5
+ import type { Spec, ProjectState } from './types.js';
6
+ import type { Workflow } from './workflow.js';
7
+ export declare class ProjectTracker {
8
+ private projectPath;
9
+ private stateFile;
10
+ constructor(projectPath: string);
11
+ /**
12
+ * Initialize a new PROJECT_STATE.md
13
+ */
14
+ initialize(projectName: string): Promise<void>;
15
+ /**
16
+ * Read current project state
17
+ */
18
+ readState(): Promise<ProjectState | null>;
19
+ /**
20
+ * Update PROJECT_STATE.md with new spec
21
+ */
22
+ addSpec(spec: Spec): Promise<void>;
23
+ /**
24
+ * Write state to PROJECT_STATE.md
25
+ */
26
+ private writeState;
27
+ /**
28
+ * Generate markdown content
29
+ */
30
+ private generateMarkdown;
31
+ private generateSpecsTable;
32
+ private getPercentage;
33
+ private calculateProgress;
34
+ private calculateMetrics;
35
+ private parseMarkdown;
36
+ /**
37
+ * Load all specs from PROJECT_STATE.md into a Workflow instance
38
+ */
39
+ loadSpecsIntoWorkflow(workflow: Workflow): Promise<void>;
40
+ private createDefaultState;
41
+ }
42
+ //# sourceMappingURL=tracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracker.d.ts","sourceRoot":"","sources":["../src/tracker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAE,IAAI,EAAE,YAAY,EAA0C,MAAM,YAAY,CAAC;AAC7F,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,qBAAa,cAAc;IACzB,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,SAAS,CAAS;gBAEd,WAAW,EAAE,MAAM;IAK/B;;OAEG;IACG,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAwBpD;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAiB/C;;OAEG;IACG,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IA+BxC;;OAEG;YACW,UAAU;IAKxB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAyCxB,OAAO,CAAC,kBAAkB;IAa1B,OAAO,CAAC,aAAa;IAKrB,OAAO,CAAC,iBAAiB;IAYzB,OAAO,CAAC,gBAAgB;IAsCxB,OAAO,CAAC,aAAa;IAuCrB;;OAEG;IACG,qBAAqB,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;YAwChD,kBAAkB;CAcjC"}
@@ -0,0 +1,287 @@
1
+ /**
2
+ * SpecSafe Project State Tracker
3
+ * Manages PROJECT_STATE.md for tracking all specs
4
+ */
5
+ import { writeFile, readFile, access } from 'fs/promises';
6
+ import { join } from 'path';
7
+ export class ProjectTracker {
8
+ projectPath;
9
+ stateFile;
10
+ constructor(projectPath) {
11
+ this.projectPath = projectPath;
12
+ this.stateFile = join(projectPath, 'PROJECT_STATE.md');
13
+ }
14
+ /**
15
+ * Initialize a new PROJECT_STATE.md
16
+ */
17
+ async initialize(projectName) {
18
+ const state = {
19
+ projectName,
20
+ version: '1.0.0',
21
+ lastUpdated: new Date(),
22
+ specs: [],
23
+ metrics: {
24
+ totalSpecs: 0,
25
+ byStage: {
26
+ spec: 0,
27
+ test: 0,
28
+ code: 0,
29
+ qa: 0,
30
+ complete: 0,
31
+ archived: 0
32
+ },
33
+ completionRate: 0,
34
+ averageCycleTime: 0
35
+ }
36
+ };
37
+ await this.writeState(state);
38
+ }
39
+ /**
40
+ * Read current project state
41
+ */
42
+ async readState() {
43
+ try {
44
+ await access(this.stateFile);
45
+ const content = await readFile(this.stateFile, 'utf-8');
46
+ const parsed = this.parseMarkdown(content);
47
+ if (parsed === null && content.length > 0) {
48
+ throw new Error('Failed to parse PROJECT_STATE.md - file exists but is malformed');
49
+ }
50
+ return parsed;
51
+ }
52
+ catch (error) {
53
+ if (error.code === 'ENOENT') {
54
+ return null;
55
+ }
56
+ throw error;
57
+ }
58
+ }
59
+ /**
60
+ * Update PROJECT_STATE.md with new spec
61
+ */
62
+ async addSpec(spec) {
63
+ const state = await this.readState() || await this.createDefaultState();
64
+ const summary = {
65
+ id: spec.id,
66
+ name: spec.name,
67
+ stage: spec.stage,
68
+ progress: this.calculateProgress(spec),
69
+ lastUpdated: spec.updatedAt,
70
+ createdAt: spec.createdAt,
71
+ completedAt: spec.completedAt
72
+ };
73
+ // Update or add spec
74
+ const existingIndex = state.specs.findIndex(s => s.id === spec.id);
75
+ if (existingIndex >= 0) {
76
+ // Preserve createdAt from existing summary if not set
77
+ if (!summary.createdAt && state.specs[existingIndex].createdAt) {
78
+ summary.createdAt = state.specs[existingIndex].createdAt;
79
+ }
80
+ state.specs[existingIndex] = summary;
81
+ }
82
+ else {
83
+ state.specs.push(summary);
84
+ }
85
+ state.lastUpdated = new Date();
86
+ state.metrics = this.calculateMetrics(state.specs);
87
+ await this.writeState(state);
88
+ }
89
+ /**
90
+ * Write state to PROJECT_STATE.md
91
+ */
92
+ async writeState(state) {
93
+ const markdown = this.generateMarkdown(state);
94
+ await writeFile(this.stateFile, markdown, 'utf-8');
95
+ }
96
+ /**
97
+ * Generate markdown content
98
+ */
99
+ generateMarkdown(state) {
100
+ const date = state.lastUpdated.toISOString().split('T')[0];
101
+ return `# ${state.projectName} - Project State
102
+
103
+ **Version:** ${state.version}
104
+ **Last Updated:** ${date}
105
+
106
+ ---
107
+
108
+ ## 📊 Metrics
109
+
110
+ | Metric | Value |
111
+ |--------|-------|
112
+ | Total Specs | ${state.metrics.totalSpecs} |
113
+ | Completion Rate | ${(state.metrics.completionRate * 100).toFixed(1)}% |
114
+ | Avg Cycle Time | ${state.metrics.averageCycleTime.toFixed(1)} days |
115
+
116
+ ### By Stage
117
+
118
+ | Stage | Count | Percentage |
119
+ |-------|-------|------------|
120
+ | SPEC | ${state.metrics.byStage.spec} | ${this.getPercentage(state.metrics.byStage.spec, state.metrics.totalSpecs)}% |
121
+ | TEST | ${state.metrics.byStage.test} | ${this.getPercentage(state.metrics.byStage.test, state.metrics.totalSpecs)}% |
122
+ | CODE | ${state.metrics.byStage.code} | ${this.getPercentage(state.metrics.byStage.code, state.metrics.totalSpecs)}% |
123
+ | QA | ${state.metrics.byStage.qa} | ${this.getPercentage(state.metrics.byStage.qa, state.metrics.totalSpecs)}% |
124
+ | COMPLETE | ${state.metrics.byStage.complete} | ${this.getPercentage(state.metrics.byStage.complete, state.metrics.totalSpecs)}% |
125
+ | ARCHIVED | ${state.metrics.byStage.archived} | ${this.getPercentage(state.metrics.byStage.archived, state.metrics.totalSpecs)}% |
126
+
127
+ ---
128
+
129
+ ## 📋 Active Specs
130
+
131
+ ${this.generateSpecsTable(state.specs)}
132
+
133
+ ---
134
+
135
+ *This file is auto-generated by SpecSafe*
136
+ `;
137
+ }
138
+ generateSpecsTable(specs) {
139
+ if (specs.length === 0)
140
+ return 'No specs yet.';
141
+ const rows = specs
142
+ .sort((a, b) => b.lastUpdated.getTime() - a.lastUpdated.getTime())
143
+ .map(s => `| ${s.id} | ${s.name} | ${s.stage.toUpperCase()} | ${s.progress}% | ${s.lastUpdated.toISOString().split('T')[0]} |`)
144
+ .join('\n');
145
+ return `| ID | Name | Stage | Progress | Last Updated |
146
+ |----|------|-------|----------|--------------|
147
+ ${rows}`;
148
+ }
149
+ getPercentage(count, total) {
150
+ if (total === 0)
151
+ return '0.0';
152
+ return ((count / total) * 100).toFixed(1);
153
+ }
154
+ calculateProgress(spec) {
155
+ const stageWeights = {
156
+ spec: 20,
157
+ test: 40,
158
+ code: 60,
159
+ qa: 80,
160
+ complete: 100,
161
+ archived: 100
162
+ };
163
+ return stageWeights[spec.stage] || 0;
164
+ }
165
+ calculateMetrics(specs) {
166
+ const total = specs.length;
167
+ const byStage = {
168
+ spec: specs.filter(s => s.stage === 'spec').length,
169
+ test: specs.filter(s => s.stage === 'test').length,
170
+ code: specs.filter(s => s.stage === 'code').length,
171
+ qa: specs.filter(s => s.stage === 'qa').length,
172
+ complete: specs.filter(s => s.stage === 'complete').length,
173
+ archived: specs.filter(s => s.stage === 'archived').length
174
+ };
175
+ const completionRate = total > 0 ? byStage.complete / total : 0;
176
+ // Calculate average cycle time for completed specs (in days)
177
+ let totalCycleTime = 0;
178
+ let completedCount = 0;
179
+ for (const spec of specs) {
180
+ const isCompleted = spec.stage === 'complete' || spec.stage === 'archived';
181
+ if (isCompleted && spec.completedAt && spec.createdAt) {
182
+ const cycleTime = spec.completedAt.getTime() - spec.createdAt.getTime();
183
+ totalCycleTime += cycleTime;
184
+ completedCount++;
185
+ }
186
+ }
187
+ const averageCycleTime = completedCount > 0
188
+ ? totalCycleTime / completedCount / (1000 * 60 * 60 * 24)
189
+ : 0;
190
+ return {
191
+ totalSpecs: total,
192
+ byStage,
193
+ completionRate,
194
+ averageCycleTime
195
+ };
196
+ }
197
+ parseMarkdown(content) {
198
+ try {
199
+ // Extract project name from header
200
+ const nameMatch = content.match(/^#\s+(.+?)\s+-\s+Project\s+State/m);
201
+ const projectName = nameMatch ? nameMatch[1] : 'Untitled Project';
202
+ // Extract version
203
+ const versionMatch = content.match(/\*\*Version:\*\*\s*(.+)/m);
204
+ const version = versionMatch ? versionMatch[1].trim() : '1.0.0';
205
+ // Extract specs from table
206
+ const specs = [];
207
+ const tableRegex = /\|\s*(SPEC-\d+-\d+)\s*\|\s*([^|]+)\|\s*(SPEC|TEST|CODE|QA|COMPLETE|ARCHIVED)\s*\|\s*(\d+)%?\s*\|\s*(\d{4}-\d{2}-\d{2})\s*\|/gi;
208
+ let match;
209
+ while ((match = tableRegex.exec(content)) !== null) {
210
+ specs.push({
211
+ id: match[1].trim(),
212
+ name: match[2].trim(),
213
+ stage: match[3].toLowerCase(),
214
+ progress: parseInt(match[4], 10),
215
+ lastUpdated: new Date(match[5])
216
+ });
217
+ }
218
+ // Calculate metrics
219
+ const metrics = this.calculateMetrics(specs);
220
+ return {
221
+ projectName,
222
+ version,
223
+ lastUpdated: new Date(),
224
+ specs,
225
+ metrics
226
+ };
227
+ }
228
+ catch {
229
+ return null;
230
+ }
231
+ }
232
+ /**
233
+ * Load all specs from PROJECT_STATE.md into a Workflow instance
234
+ */
235
+ async loadSpecsIntoWorkflow(workflow) {
236
+ const state = await this.readState();
237
+ if (!state)
238
+ return;
239
+ for (const summary of state.specs) {
240
+ // Try to read the actual spec file for full details
241
+ const dir = summary.stage === 'complete' || summary.stage === 'archived' ? 'completed' : 'active';
242
+ const specPath = join(this.projectPath, 'specs', dir, `${summary.id}.md`);
243
+ // Create spec object from summary data
244
+ const spec = {
245
+ id: summary.id,
246
+ name: summary.name,
247
+ description: '',
248
+ stage: summary.stage,
249
+ createdAt: summary.createdAt || summary.lastUpdated,
250
+ updatedAt: summary.lastUpdated,
251
+ completedAt: summary.completedAt,
252
+ requirements: [],
253
+ testFiles: [],
254
+ implementationFiles: [],
255
+ metadata: {
256
+ author: '',
257
+ project: '',
258
+ tags: []
259
+ }
260
+ };
261
+ // Try to read actual spec file for richer data
262
+ try {
263
+ await access(specPath);
264
+ // File exists — we could parse more details here in the future
265
+ }
266
+ catch {
267
+ // Spec file not found, still load the summary-based spec
268
+ }
269
+ workflow.loadSpec(spec);
270
+ }
271
+ }
272
+ async createDefaultState() {
273
+ return {
274
+ projectName: 'Untitled Project',
275
+ version: '1.0.0',
276
+ lastUpdated: new Date(),
277
+ specs: [],
278
+ metrics: {
279
+ totalSpecs: 0,
280
+ byStage: { spec: 0, test: 0, code: 0, qa: 0, complete: 0, archived: 0 },
281
+ completionRate: 0,
282
+ averageCycleTime: 0
283
+ }
284
+ };
285
+ }
286
+ }
287
+ //# sourceMappingURL=tracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracker.js","sourceRoot":"","sources":["../src/tracker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * SpecSafe Core Types
3
+ * Defines the data structures for the SPEC → TEST → CODE → QA → COMPLETE workflow
4
+ */
5
+ export type SpecStage = 'spec' | 'test' | 'code' | 'qa' | 'complete' | 'archived';
6
+ export interface Requirement {
7
+ id: string;
8
+ text: string;
9
+ priority: 'P0' | 'P1' | 'P2';
10
+ scenarios: Scenario[];
11
+ }
12
+ export interface Scenario {
13
+ id: string;
14
+ given: string;
15
+ when: string;
16
+ then: string;
17
+ }
18
+ export interface Spec {
19
+ id: string;
20
+ name: string;
21
+ description: string;
22
+ stage: SpecStage;
23
+ createdAt: Date;
24
+ updatedAt: Date;
25
+ completedAt?: Date;
26
+ requirements: Requirement[];
27
+ testFiles: string[];
28
+ implementationFiles: string[];
29
+ qaReport?: QAReport;
30
+ metadata: {
31
+ author: string;
32
+ project: string;
33
+ tags: string[];
34
+ };
35
+ }
36
+ export interface QAReport {
37
+ id: string;
38
+ specId: string;
39
+ timestamp: Date;
40
+ testResults: TestResult[];
41
+ coverage: CoverageReport;
42
+ recommendation: 'GO' | 'NO-GO';
43
+ issues: Issue[];
44
+ notes: string;
45
+ }
46
+ export interface TestResult {
47
+ file: string;
48
+ passed: number;
49
+ failed: number;
50
+ skipped: number;
51
+ duration: number;
52
+ }
53
+ export interface CoverageReport {
54
+ statements: number;
55
+ branches: number;
56
+ functions: number;
57
+ lines: number;
58
+ }
59
+ export interface Issue {
60
+ severity: 'critical' | 'high' | 'medium' | 'low';
61
+ description: string;
62
+ file?: string;
63
+ line?: number;
64
+ }
65
+ export interface ProjectState {
66
+ projectName: string;
67
+ version: string;
68
+ lastUpdated: Date;
69
+ specs: SpecSummary[];
70
+ metrics: ProjectMetrics;
71
+ }
72
+ export interface SpecSummary {
73
+ id: string;
74
+ name: string;
75
+ stage: SpecStage;
76
+ progress: number;
77
+ lastUpdated: Date;
78
+ createdAt?: Date;
79
+ completedAt?: Date;
80
+ }
81
+ export interface ProjectMetrics {
82
+ totalSpecs: number;
83
+ byStage: Record<SpecStage, number>;
84
+ completionRate: number;
85
+ averageCycleTime: number;
86
+ }
87
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,6 @@
1
+ /**
2
+ * SpecSafe Core Types
3
+ * Defines the data structures for the SPEC → TEST → CODE → QA → COMPLETE workflow
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Validation utilities for SpecSafe
3
+ */
4
+ /**
5
+ * Validates that a spec ID matches the required format: SPEC-YYYYMMDD-NNN
6
+ * @param id - The spec ID to validate
7
+ * @throws Error if the ID is invalid
8
+ */
9
+ export declare function validateSpecId(id: string): void;
10
+ //# sourceMappingURL=validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAiB/C"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Validation utilities for SpecSafe
3
+ */
4
+ const SPEC_ID_REGEX = /^SPEC-\d{8}-\d{3}$/;
5
+ /**
6
+ * Validates that a spec ID matches the required format: SPEC-YYYYMMDD-NNN
7
+ * @param id - The spec ID to validate
8
+ * @throws Error if the ID is invalid
9
+ */
10
+ export function validateSpecId(id) {
11
+ if (!id || typeof id !== 'string') {
12
+ throw new Error('Spec ID is required and must be a string');
13
+ }
14
+ if (!SPEC_ID_REGEX.test(id)) {
15
+ throw new Error(`Invalid spec ID format: "${id}". Expected format: SPEC-YYYYMMDD-NNN (e.g., SPEC-20250211-001)`);
16
+ }
17
+ // Validate the date portion is a real date
18
+ const dateStr = id.substring(5, 13); // YYYYMMDD
19
+ const year = parseInt(dateStr.substring(0, 4), 10);
20
+ const month = parseInt(dateStr.substring(4, 6), 10);
21
+ const day = parseInt(dateStr.substring(6, 8), 10);
22
+ const date = new Date(year, month - 1, day);
23
+ if (date.getFullYear() !== year || date.getMonth() !== month - 1 || date.getDate() !== day) {
24
+ throw new Error(`Invalid spec ID "${id}": contains invalid date ${dateStr}. Expected format: SPEC-YYYYMMDD-NNN`);
25
+ }
26
+ }
27
+ //# sourceMappingURL=validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.js","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,aAAa,GAAG,oBAAoB,CAAC;AAE3C;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,EAAU;IACvC,IAAI,CAAC,EAAE,IAAI,OAAO,EAAE,KAAK,QAAQ,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IAC9D,CAAC;IACD,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,4BAA4B,EAAE,iEAAiE,CAAC,CAAC;IACnH,CAAC;IAED,2CAA2C;IAC3C,MAAM,OAAO,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW;IAChD,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACnD,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACpD,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAClD,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;IAC5C,IAAI,IAAI,CAAC,WAAW,EAAE,KAAK,IAAI,IAAI,IAAI,CAAC,QAAQ,EAAE,KAAK,KAAK,GAAG,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,KAAK,GAAG,EAAE,CAAC;QAC3F,MAAM,IAAI,KAAK,CAAC,oBAAoB,EAAE,4BAA4B,OAAO,sCAAsC,CAAC,CAAC;IACnH,CAAC;AACH,CAAC"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * SpecSafe Workflow Engine
3
+ * Manages the 5-stage development cycle: SPEC → TEST → CODE → QA → COMPLETE
4
+ */
5
+ import type { Spec, SpecStage, QAReport } from './types.js';
6
+ export declare class Workflow {
7
+ private specs;
8
+ /**
9
+ * Create a new spec in the SPEC stage
10
+ */
11
+ createSpec(id: string, name: string, description: string, author: string, project: string): Spec;
12
+ /**
13
+ * Get a spec by ID
14
+ */
15
+ getSpec(id: string): Spec | undefined;
16
+ /**
17
+ * Load an existing spec into the workflow (for hydration from disk)
18
+ */
19
+ loadSpec(spec: Spec): void;
20
+ /**
21
+ * Get all specs
22
+ */
23
+ getAllSpecs(): Spec[];
24
+ /**
25
+ * Get specs by stage
26
+ */
27
+ getSpecsByStage(stage: SpecStage): Spec[];
28
+ /**
29
+ * Transition spec to TEST stage
30
+ * Requirements must be defined
31
+ */
32
+ moveToTest(specId: string): Spec;
33
+ /**
34
+ * Transition spec to CODE stage
35
+ * Tests must be generated
36
+ */
37
+ moveToCode(specId: string): Spec;
38
+ /**
39
+ * Transition spec to QA stage
40
+ * Implementation must be complete
41
+ */
42
+ moveToQA(specId: string): Spec;
43
+ /**
44
+ * Transition spec to COMPLETE stage
45
+ * QA report must be provided with GO recommendation
46
+ */
47
+ moveToComplete(specId: string, qaReport: QAReport): Spec;
48
+ /**
49
+ * Archive a completed spec
50
+ */
51
+ archiveSpec(specId: string): Spec;
52
+ /**
53
+ * Get workflow status summary
54
+ */
55
+ getStatus(): {
56
+ stage: SpecStage;
57
+ count: number;
58
+ }[];
59
+ /**
60
+ * Validate stage transition
61
+ */
62
+ canTransition(specId: string, toStage: SpecStage): {
63
+ valid: boolean;
64
+ reason?: string;
65
+ };
66
+ }
67
+ //# sourceMappingURL=workflow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workflow.d.ts","sourceRoot":"","sources":["../src/workflow.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE5D,qBAAa,QAAQ;IACnB,OAAO,CAAC,KAAK,CAAgC;IAE7C;;OAEG;IACH,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IA0BhG;;OAEG;IACH,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS;IAIrC;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IAI1B;;OAEG;IACH,WAAW,IAAI,IAAI,EAAE;IAIrB;;OAEG;IACH,eAAe,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,EAAE;IAIzC;;;OAGG;IACH,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAehC;;;OAGG;IACH,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAehC;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAe9B;;;OAGG;IACH,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAqBxD;;OAEG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAYjC;;OAEG;IACH,SAAS,IAAI;QAAE,KAAK,EAAE,SAAS,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE;IAQlD;;OAEG;IACH,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,GAAG;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE;CAgCvF"}
@@ -0,0 +1,193 @@
1
+ /**
2
+ * SpecSafe Workflow Engine
3
+ * Manages the 5-stage development cycle: SPEC → TEST → CODE → QA → COMPLETE
4
+ */
5
+ export class Workflow {
6
+ specs = new Map();
7
+ /**
8
+ * Create a new spec in the SPEC stage
9
+ */
10
+ createSpec(id, name, description, author, project) {
11
+ // Check if spec already exists to prevent overwriting
12
+ if (this.specs.has(id)) {
13
+ throw new Error(`Spec with ID ${id} already exists. Use a different name or delete the existing spec first.`);
14
+ }
15
+ const spec = {
16
+ id,
17
+ name,
18
+ description,
19
+ stage: 'spec',
20
+ createdAt: new Date(),
21
+ updatedAt: new Date(),
22
+ requirements: [],
23
+ testFiles: [],
24
+ implementationFiles: [],
25
+ metadata: {
26
+ author,
27
+ project,
28
+ tags: []
29
+ }
30
+ };
31
+ this.specs.set(id, spec);
32
+ return spec;
33
+ }
34
+ /**
35
+ * Get a spec by ID
36
+ */
37
+ getSpec(id) {
38
+ return this.specs.get(id);
39
+ }
40
+ /**
41
+ * Load an existing spec into the workflow (for hydration from disk)
42
+ */
43
+ loadSpec(spec) {
44
+ this.specs.set(spec.id, spec);
45
+ }
46
+ /**
47
+ * Get all specs
48
+ */
49
+ getAllSpecs() {
50
+ return Array.from(this.specs.values());
51
+ }
52
+ /**
53
+ * Get specs by stage
54
+ */
55
+ getSpecsByStage(stage) {
56
+ return this.getAllSpecs().filter(s => s.stage === stage);
57
+ }
58
+ /**
59
+ * Transition spec to TEST stage
60
+ * Requirements must be defined
61
+ */
62
+ moveToTest(specId) {
63
+ const spec = this.getSpec(specId);
64
+ if (!spec)
65
+ throw new Error(`Spec ${specId} not found`);
66
+ if (spec.stage !== 'spec') {
67
+ throw new Error(`Cannot move to TEST from ${spec.stage}. Must be in SPEC stage.`);
68
+ }
69
+ if (spec.requirements.length === 0) {
70
+ throw new Error('Cannot move to TEST: No requirements defined');
71
+ }
72
+ spec.stage = 'test';
73
+ spec.updatedAt = new Date();
74
+ return spec;
75
+ }
76
+ /**
77
+ * Transition spec to CODE stage
78
+ * Tests must be generated
79
+ */
80
+ moveToCode(specId) {
81
+ const spec = this.getSpec(specId);
82
+ if (!spec)
83
+ throw new Error(`Spec ${specId} not found`);
84
+ if (spec.stage !== 'test') {
85
+ throw new Error(`Cannot move to CODE from ${spec.stage}. Must be in TEST stage.`);
86
+ }
87
+ if (spec.testFiles.length === 0) {
88
+ throw new Error('Cannot move to CODE: No test files generated');
89
+ }
90
+ spec.stage = 'code';
91
+ spec.updatedAt = new Date();
92
+ return spec;
93
+ }
94
+ /**
95
+ * Transition spec to QA stage
96
+ * Implementation must be complete
97
+ */
98
+ moveToQA(specId) {
99
+ const spec = this.getSpec(specId);
100
+ if (!spec)
101
+ throw new Error(`Spec ${specId} not found`);
102
+ if (spec.stage !== 'code') {
103
+ throw new Error(`Cannot move to QA from ${spec.stage}. Must be in CODE stage.`);
104
+ }
105
+ if (spec.implementationFiles.length === 0) {
106
+ throw new Error('Cannot move to QA: No implementation files');
107
+ }
108
+ spec.stage = 'qa';
109
+ spec.updatedAt = new Date();
110
+ return spec;
111
+ }
112
+ /**
113
+ * Transition spec to COMPLETE stage
114
+ * QA report must be provided with GO recommendation
115
+ */
116
+ moveToComplete(specId, qaReport) {
117
+ const spec = this.getSpec(specId);
118
+ if (!spec)
119
+ throw new Error(`Spec ${specId} not found`);
120
+ if (spec.stage !== 'qa') {
121
+ throw new Error(`Cannot move to COMPLETE from ${spec.stage}. Must be in QA stage.`);
122
+ }
123
+ // Validate QA report belongs to target spec
124
+ if (qaReport.specId !== specId) {
125
+ throw new Error(`QA report spec ID (${qaReport.specId}) does not match target spec (${specId})`);
126
+ }
127
+ if (qaReport.recommendation !== 'GO') {
128
+ throw new Error('Cannot complete: QA report recommends NO-GO. Address issues first.');
129
+ }
130
+ spec.stage = 'complete';
131
+ spec.qaReport = qaReport;
132
+ spec.completedAt = new Date();
133
+ spec.updatedAt = new Date();
134
+ return spec;
135
+ }
136
+ /**
137
+ * Archive a completed spec
138
+ */
139
+ archiveSpec(specId) {
140
+ const spec = this.getSpec(specId);
141
+ if (!spec)
142
+ throw new Error(`Spec ${specId} not found`);
143
+ if (spec.stage !== 'complete') {
144
+ throw new Error(`Cannot archive spec in ${spec.stage} stage. Must be COMPLETE.`);
145
+ }
146
+ spec.stage = 'archived';
147
+ spec.updatedAt = new Date();
148
+ return spec;
149
+ }
150
+ /**
151
+ * Get workflow status summary
152
+ */
153
+ getStatus() {
154
+ const stages = ['spec', 'test', 'code', 'qa', 'complete', 'archived'];
155
+ return stages.map(stage => ({
156
+ stage,
157
+ count: this.getSpecsByStage(stage).length
158
+ }));
159
+ }
160
+ /**
161
+ * Validate stage transition
162
+ */
163
+ canTransition(specId, toStage) {
164
+ const spec = this.getSpec(specId);
165
+ if (!spec)
166
+ return { valid: false, reason: 'Spec not found' };
167
+ const transitions = {
168
+ spec: ['test'],
169
+ test: ['code'],
170
+ code: ['qa'],
171
+ qa: ['complete'],
172
+ complete: ['archived'],
173
+ archived: []
174
+ };
175
+ if (!transitions[spec.stage].includes(toStage)) {
176
+ return { valid: false, reason: `Cannot transition from ${spec.stage} to ${toStage}` };
177
+ }
178
+ // Validate prerequisites based on target stage
179
+ if (toStage === 'test' && spec.requirements.length === 0) {
180
+ return { valid: false, reason: 'Cannot move to TEST: No requirements defined' };
181
+ }
182
+ if (toStage === 'code' && spec.testFiles.length === 0) {
183
+ return { valid: false, reason: 'Cannot move to CODE: No test files generated' };
184
+ }
185
+ if (toStage === 'qa' && spec.implementationFiles.length === 0) {
186
+ return { valid: false, reason: 'Cannot move to QA: No implementation files' };
187
+ }
188
+ // Note: 'complete' transition requires a QA report, but that's validated in moveToComplete()
189
+ // since canTransition() doesn't have access to the QAReport parameter
190
+ return { valid: true };
191
+ }
192
+ }
193
+ //# sourceMappingURL=workflow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workflow.js","sourceRoot":"","sources":["../src/workflow.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "@specsafe/core",
3
+ "version": "0.1.0",
4
+ "description": "Core types and workflow engine for SpecSafe",
5
+ "type": "module",
6
+ "engines": {
7
+ "node": ">=18"
8
+ },
9
+ "main": "./dist/index.js",
10
+ "types": "./dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "import": "./dist/index.js"
15
+ }
16
+ },
17
+ "files": [
18
+ "dist/",
19
+ "README.md",
20
+ "LICENSE"
21
+ ],
22
+ "publishConfig": {
23
+ "access": "public"
24
+ },
25
+ "devDependencies": {
26
+ "@types/node": "^20.0.0",
27
+ "typescript": "^5.3.0",
28
+ "vitest": "^1.0.0"
29
+ },
30
+ "scripts": {
31
+ "build": "tsc",
32
+ "dev": "tsc --watch",
33
+ "test": "vitest --passWithNoTests",
34
+ "typecheck": "tsc --noEmit"
35
+ }
36
+ }