@sudocode-ai/integration-openspec 0.1.14

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 (41) hide show
  1. package/dist/id-generator.d.ts +114 -0
  2. package/dist/id-generator.d.ts.map +1 -0
  3. package/dist/id-generator.js +165 -0
  4. package/dist/id-generator.js.map +1 -0
  5. package/dist/index.d.ts +29 -0
  6. package/dist/index.d.ts.map +1 -0
  7. package/dist/index.js +692 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/parser/change-parser.d.ts +164 -0
  10. package/dist/parser/change-parser.d.ts.map +1 -0
  11. package/dist/parser/change-parser.js +339 -0
  12. package/dist/parser/change-parser.js.map +1 -0
  13. package/dist/parser/markdown-utils.d.ts +138 -0
  14. package/dist/parser/markdown-utils.d.ts.map +1 -0
  15. package/dist/parser/markdown-utils.js +283 -0
  16. package/dist/parser/markdown-utils.js.map +1 -0
  17. package/dist/parser/spec-parser.d.ts +116 -0
  18. package/dist/parser/spec-parser.d.ts.map +1 -0
  19. package/dist/parser/spec-parser.js +204 -0
  20. package/dist/parser/spec-parser.js.map +1 -0
  21. package/dist/parser/tasks-parser.d.ts +120 -0
  22. package/dist/parser/tasks-parser.d.ts.map +1 -0
  23. package/dist/parser/tasks-parser.js +176 -0
  24. package/dist/parser/tasks-parser.js.map +1 -0
  25. package/dist/watcher.d.ts +160 -0
  26. package/dist/watcher.d.ts.map +1 -0
  27. package/dist/watcher.js +614 -0
  28. package/dist/watcher.js.map +1 -0
  29. package/dist/writer/index.d.ts +9 -0
  30. package/dist/writer/index.d.ts.map +1 -0
  31. package/dist/writer/index.js +9 -0
  32. package/dist/writer/index.js.map +1 -0
  33. package/dist/writer/spec-writer.d.ts +24 -0
  34. package/dist/writer/spec-writer.d.ts.map +1 -0
  35. package/dist/writer/spec-writer.js +75 -0
  36. package/dist/writer/spec-writer.js.map +1 -0
  37. package/dist/writer/tasks-writer.d.ts +33 -0
  38. package/dist/writer/tasks-writer.d.ts.map +1 -0
  39. package/dist/writer/tasks-writer.js +144 -0
  40. package/dist/writer/tasks-writer.js.map +1 -0
  41. package/package.json +43 -0
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Shared Markdown Utilities for OpenSpec Parsing
3
+ *
4
+ * Common regex patterns and helper functions for extracting
5
+ * metadata from OpenSpec markdown files.
6
+ */
7
+ /**
8
+ * Regex patterns for common markdown elements in OpenSpec files
9
+ */
10
+ export declare const PATTERNS: {
11
+ /** Match H1 title: # Title */
12
+ TITLE: RegExp;
13
+ /** Match title with prefix: # Feature Specification: Title */
14
+ TITLE_WITH_PREFIX: RegExp;
15
+ /** Match metadata line: **Key**: Value */
16
+ METADATA: RegExp;
17
+ /** Match status metadata: **Status**: Value */
18
+ STATUS: RegExp;
19
+ /** Match feature branch metadata: **Feature Branch**: Value */
20
+ FEATURE_BRANCH: RegExp;
21
+ /** Match branch metadata: **Branch**: Value */
22
+ BRANCH: RegExp;
23
+ /** Match created date metadata: **Created**: Value */
24
+ CREATED: RegExp;
25
+ /** Match spec link metadata: **Spec**: [[link]] or **Spec**: link */
26
+ SPEC_LINK: RegExp;
27
+ /** Match cross-reference: [[id]] or [[id|display]] */
28
+ CROSS_REFERENCE: RegExp;
29
+ /** Match task line: - [ ] T001 [P] [US1] Description or - [x] T001: Description */
30
+ TASK_LINE: RegExp;
31
+ /** Match parallelizable marker: [P] */
32
+ PARALLELIZABLE: RegExp;
33
+ /** Match user story marker: [US1], [US2], etc. */
34
+ USER_STORY: RegExp;
35
+ /** Match phase header: ## Phase N: Name or ### Phase N */
36
+ PHASE_HEADER: RegExp;
37
+ /** Match section header: ## Section Name */
38
+ SECTION_HEADER: RegExp;
39
+ /** Match date format: YYYY-MM-DD */
40
+ DATE: RegExp;
41
+ /** Match ISO date with time */
42
+ ISO_DATE: RegExp;
43
+ };
44
+ /**
45
+ * Extract all metadata from a markdown file's lines
46
+ *
47
+ * @param lines - Array of file lines
48
+ * @returns Map of metadata key-value pairs
49
+ *
50
+ * @example
51
+ * const lines = [
52
+ * "# Title",
53
+ * "",
54
+ * "**Status**: Draft",
55
+ * "**Created**: 2024-01-01",
56
+ * ];
57
+ * extractMetadata(lines);
58
+ * // Map { "Status" => "Draft", "Created" => "2024-01-01" }
59
+ */
60
+ export declare function extractMetadata(lines: string[]): Map<string, string>;
61
+ /**
62
+ * Extract the title from markdown content
63
+ *
64
+ * @param lines - Array of file lines
65
+ * @returns The title text or null if not found
66
+ */
67
+ export declare function extractTitle(lines: string[]): string | null;
68
+ /**
69
+ * Extract title with optional prefix removal
70
+ *
71
+ * @param lines - Array of file lines
72
+ * @param prefixes - Optional prefixes to remove (e.g., ["Feature Specification:", "Implementation Plan:"])
73
+ * @returns The clean title text or null
74
+ */
75
+ export declare function extractTitleWithPrefixRemoval(lines: string[], prefixes?: string[]): string | null;
76
+ /**
77
+ * Extract a specific metadata value by key (case-insensitive)
78
+ *
79
+ * @param lines - Array of file lines
80
+ * @param key - The metadata key to find
81
+ * @returns The value or null if not found
82
+ */
83
+ export declare function extractMetadataValue(lines: string[], key: string): string | null;
84
+ /**
85
+ * Extract all cross-references from markdown content
86
+ *
87
+ * @param content - The full markdown content as a string
88
+ * @returns Array of cross-reference objects
89
+ */
90
+ export declare function extractCrossReferences(content: string): Array<{
91
+ id: string;
92
+ displayText?: string;
93
+ }>;
94
+ /**
95
+ * Find the line index where the main content starts (after metadata)
96
+ *
97
+ * @param lines - Array of file lines
98
+ * @returns Index of the first content line
99
+ */
100
+ export declare function findContentStartIndex(lines: string[]): number;
101
+ /**
102
+ * Extract section content by header
103
+ *
104
+ * @param lines - Array of file lines
105
+ * @param sectionName - Name of the section to extract
106
+ * @param headerLevel - Header level (2-6, default 2 for ##)
107
+ * @returns Section content as array of lines, or null if not found
108
+ */
109
+ export declare function extractSection(lines: string[], sectionName: string, headerLevel?: number): string[] | null;
110
+ /**
111
+ * Parse a date string from various formats
112
+ *
113
+ * @param dateStr - Date string to parse
114
+ * @returns Date object or null if invalid
115
+ */
116
+ export declare function parseDate(dateStr: string): Date | null;
117
+ /**
118
+ * Escape special regex characters in a string
119
+ *
120
+ * @param str - String to escape
121
+ * @returns Escaped string safe for use in regex
122
+ */
123
+ export declare function escapeRegex(str: string): string;
124
+ /**
125
+ * Clean task description by removing markers
126
+ *
127
+ * @param description - Raw task description
128
+ * @returns Cleaned description
129
+ */
130
+ export declare function cleanTaskDescription(description: string): string;
131
+ /**
132
+ * Normalize status string to a consistent format
133
+ *
134
+ * @param status - Raw status string
135
+ * @returns Normalized status
136
+ */
137
+ export declare function normalizeStatus(status: string): string;
138
+ //# sourceMappingURL=markdown-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown-utils.d.ts","sourceRoot":"","sources":["../../src/parser/markdown-utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;GAEG;AACH,eAAO,MAAM,QAAQ;IACnB,8BAA8B;;IAG9B,8DAA8D;;IAG9D,0CAA0C;;IAG1C,+CAA+C;;IAG/C,+DAA+D;;IAG/D,+CAA+C;;IAG/C,sDAAsD;;IAGtD,qEAAqE;;IAGrE,sDAAsD;;IAGtD,mFAAmF;;IAGnF,uCAAuC;;IAGvC,kDAAkD;;IAGlD,0DAA0D;;IAG1D,4CAA4C;;IAG5C,oCAAoC;;IAGpC,+BAA+B;;CAEhC,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAYpE;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAQ3D;AAED;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAC3C,KAAK,EAAE,MAAM,EAAE,EACf,QAAQ,GAAE,MAAM,EAAO,GACtB,MAAM,GAAG,IAAI,CAef;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,MAAM,EAAE,EACf,GAAG,EAAE,MAAM,GACV,MAAM,GAAG,IAAI,CAWf;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,GACd,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAa7C;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAgC7D;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,EAAE,EACf,WAAW,EAAE,MAAM,EACnB,WAAW,GAAE,MAAU,GACtB,MAAM,EAAE,GAAG,IAAI,CAiCjB;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAoBtD;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAOhE;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAmBtD"}
@@ -0,0 +1,283 @@
1
+ /**
2
+ * Shared Markdown Utilities for OpenSpec Parsing
3
+ *
4
+ * Common regex patterns and helper functions for extracting
5
+ * metadata from OpenSpec markdown files.
6
+ */
7
+ /**
8
+ * Regex patterns for common markdown elements in OpenSpec files
9
+ */
10
+ export const PATTERNS = {
11
+ /** Match H1 title: # Title */
12
+ TITLE: /^#\s+(.+)$/,
13
+ /** Match title with prefix: # Feature Specification: Title */
14
+ TITLE_WITH_PREFIX: /^#\s+(?:Feature Specification|Implementation Plan):\s*(.+)$/i,
15
+ /** Match metadata line: **Key**: Value */
16
+ METADATA: /^\*\*([^*]+)\*\*:\s*(.*)$/,
17
+ /** Match status metadata: **Status**: Value */
18
+ STATUS: /^\*\*Status\*\*:\s*(.*)$/i,
19
+ /** Match feature branch metadata: **Feature Branch**: Value */
20
+ FEATURE_BRANCH: /^\*\*Feature Branch\*\*:\s*(.*)$/i,
21
+ /** Match branch metadata: **Branch**: Value */
22
+ BRANCH: /^\*\*Branch\*\*:\s*(.*)$/i,
23
+ /** Match created date metadata: **Created**: Value */
24
+ CREATED: /^\*\*Created\*\*:\s*(.*)$/i,
25
+ /** Match spec link metadata: **Spec**: [[link]] or **Spec**: link */
26
+ SPEC_LINK: /^\*\*Spec\*\*:\s*(?:\[\[)?([^\]]+)(?:\]\])?$/i,
27
+ /** Match cross-reference: [[id]] or [[id|display]] */
28
+ CROSS_REFERENCE: /\[\[([^\]|]+)(?:\|([^\]]+))?\]\]/g,
29
+ /** Match task line: - [ ] T001 [P] [US1] Description or - [x] T001: Description */
30
+ TASK_LINE: /^(\s*)-\s*\[([ xX])\]\s*(T\d+)(.*)$/,
31
+ /** Match parallelizable marker: [P] */
32
+ PARALLELIZABLE: /\[P\]/i,
33
+ /** Match user story marker: [US1], [US2], etc. */
34
+ USER_STORY: /\[US(\d+)\]/i,
35
+ /** Match phase header: ## Phase N: Name or ### Phase N */
36
+ PHASE_HEADER: /^#{2,3}\s+Phase\s+(\d+)(?::\s*(.+))?$/i,
37
+ /** Match section header: ## Section Name */
38
+ SECTION_HEADER: /^(#{2,6})\s+(.+)$/,
39
+ /** Match date format: YYYY-MM-DD */
40
+ DATE: /^\d{4}-\d{2}-\d{2}$/,
41
+ /** Match ISO date with time */
42
+ ISO_DATE: /^\d{4}-\d{2}-\d{2}(?:T\d{2}:\d{2}:\d{2})?/,
43
+ };
44
+ /**
45
+ * Extract all metadata from a markdown file's lines
46
+ *
47
+ * @param lines - Array of file lines
48
+ * @returns Map of metadata key-value pairs
49
+ *
50
+ * @example
51
+ * const lines = [
52
+ * "# Title",
53
+ * "",
54
+ * "**Status**: Draft",
55
+ * "**Created**: 2024-01-01",
56
+ * ];
57
+ * extractMetadata(lines);
58
+ * // Map { "Status" => "Draft", "Created" => "2024-01-01" }
59
+ */
60
+ export function extractMetadata(lines) {
61
+ const metadata = new Map();
62
+ for (const line of lines) {
63
+ const match = line.match(PATTERNS.METADATA);
64
+ if (match) {
65
+ const [, key, value] = match;
66
+ metadata.set(key.trim(), value.trim());
67
+ }
68
+ }
69
+ return metadata;
70
+ }
71
+ /**
72
+ * Extract the title from markdown content
73
+ *
74
+ * @param lines - Array of file lines
75
+ * @returns The title text or null if not found
76
+ */
77
+ export function extractTitle(lines) {
78
+ for (const line of lines) {
79
+ const match = line.match(PATTERNS.TITLE);
80
+ if (match) {
81
+ return match[1].trim();
82
+ }
83
+ }
84
+ return null;
85
+ }
86
+ /**
87
+ * Extract title with optional prefix removal
88
+ *
89
+ * @param lines - Array of file lines
90
+ * @param prefixes - Optional prefixes to remove (e.g., ["Feature Specification:", "Implementation Plan:"])
91
+ * @returns The clean title text or null
92
+ */
93
+ export function extractTitleWithPrefixRemoval(lines, prefixes = []) {
94
+ const rawTitle = extractTitle(lines);
95
+ if (!rawTitle)
96
+ return null;
97
+ // Try to match and remove known prefixes
98
+ for (const prefix of prefixes) {
99
+ const prefixLower = prefix.toLowerCase();
100
+ if (rawTitle.toLowerCase().startsWith(prefixLower)) {
101
+ const remainder = rawTitle.slice(prefix.length).trim();
102
+ // Remove leading colon if present
103
+ return remainder.startsWith(":") ? remainder.slice(1).trim() : remainder;
104
+ }
105
+ }
106
+ return rawTitle;
107
+ }
108
+ /**
109
+ * Extract a specific metadata value by key (case-insensitive)
110
+ *
111
+ * @param lines - Array of file lines
112
+ * @param key - The metadata key to find
113
+ * @returns The value or null if not found
114
+ */
115
+ export function extractMetadataValue(lines, key) {
116
+ const keyLower = key.toLowerCase();
117
+ for (const line of lines) {
118
+ const match = line.match(PATTERNS.METADATA);
119
+ if (match && match[1].trim().toLowerCase() === keyLower) {
120
+ return match[2].trim();
121
+ }
122
+ }
123
+ return null;
124
+ }
125
+ /**
126
+ * Extract all cross-references from markdown content
127
+ *
128
+ * @param content - The full markdown content as a string
129
+ * @returns Array of cross-reference objects
130
+ */
131
+ export function extractCrossReferences(content) {
132
+ const references = [];
133
+ const regex = new RegExp(PATTERNS.CROSS_REFERENCE.source, "g");
134
+ let match;
135
+ while ((match = regex.exec(content)) !== null) {
136
+ references.push({
137
+ id: match[1].trim(),
138
+ displayText: match[2]?.trim(),
139
+ });
140
+ }
141
+ return references;
142
+ }
143
+ /**
144
+ * Find the line index where the main content starts (after metadata)
145
+ *
146
+ * @param lines - Array of file lines
147
+ * @returns Index of the first content line
148
+ */
149
+ export function findContentStartIndex(lines) {
150
+ let titleFound = false;
151
+ let lastMetadataIndex = -1;
152
+ for (let i = 0; i < lines.length; i++) {
153
+ const line = lines[i];
154
+ // Track title
155
+ if (!titleFound && PATTERNS.TITLE.test(line)) {
156
+ titleFound = true;
157
+ continue;
158
+ }
159
+ // Track metadata lines
160
+ if (PATTERNS.METADATA.test(line)) {
161
+ lastMetadataIndex = i;
162
+ continue;
163
+ }
164
+ // Skip blank lines after metadata
165
+ if (line.trim() === "") {
166
+ continue;
167
+ }
168
+ // If we're past the title and metadata, this is content start
169
+ if (titleFound && i > lastMetadataIndex) {
170
+ return i;
171
+ }
172
+ }
173
+ // Return end of file if no content found
174
+ return lines.length;
175
+ }
176
+ /**
177
+ * Extract section content by header
178
+ *
179
+ * @param lines - Array of file lines
180
+ * @param sectionName - Name of the section to extract
181
+ * @param headerLevel - Header level (2-6, default 2 for ##)
182
+ * @returns Section content as array of lines, or null if not found
183
+ */
184
+ export function extractSection(lines, sectionName, headerLevel = 2) {
185
+ const headerPrefix = "#".repeat(headerLevel);
186
+ const sectionRegex = new RegExp(`^${headerPrefix}\\s+${escapeRegex(sectionName)}\\s*$`, "i");
187
+ const nextHeaderRegex = new RegExp(`^#{1,${headerLevel}}\\s+`);
188
+ let sectionStart = -1;
189
+ let sectionEnd = lines.length;
190
+ for (let i = 0; i < lines.length; i++) {
191
+ const line = lines[i];
192
+ if (sectionStart === -1) {
193
+ // Looking for section start
194
+ if (sectionRegex.test(line)) {
195
+ sectionStart = i + 1; // Start after header
196
+ }
197
+ }
198
+ else {
199
+ // Looking for section end (next header at same or higher level)
200
+ if (nextHeaderRegex.test(line)) {
201
+ sectionEnd = i;
202
+ break;
203
+ }
204
+ }
205
+ }
206
+ if (sectionStart === -1) {
207
+ return null;
208
+ }
209
+ return lines.slice(sectionStart, sectionEnd);
210
+ }
211
+ /**
212
+ * Parse a date string from various formats
213
+ *
214
+ * @param dateStr - Date string to parse
215
+ * @returns Date object or null if invalid
216
+ */
217
+ export function parseDate(dateStr) {
218
+ if (!dateStr)
219
+ return null;
220
+ // Try ISO format first
221
+ if (PATTERNS.ISO_DATE.test(dateStr)) {
222
+ const date = new Date(dateStr);
223
+ if (!isNaN(date.getTime())) {
224
+ return date;
225
+ }
226
+ }
227
+ // Try simple date format
228
+ if (PATTERNS.DATE.test(dateStr)) {
229
+ const date = new Date(dateStr + "T00:00:00");
230
+ if (!isNaN(date.getTime())) {
231
+ return date;
232
+ }
233
+ }
234
+ return null;
235
+ }
236
+ /**
237
+ * Escape special regex characters in a string
238
+ *
239
+ * @param str - String to escape
240
+ * @returns Escaped string safe for use in regex
241
+ */
242
+ export function escapeRegex(str) {
243
+ return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
244
+ }
245
+ /**
246
+ * Clean task description by removing markers
247
+ *
248
+ * @param description - Raw task description
249
+ * @returns Cleaned description
250
+ */
251
+ export function cleanTaskDescription(description) {
252
+ return description
253
+ .replace(PATTERNS.PARALLELIZABLE, "")
254
+ .replace(PATTERNS.USER_STORY, "")
255
+ .replace(/^\s*:\s*/, "") // Remove leading colon with surrounding whitespace
256
+ .replace(/\s+/g, " ") // Normalize whitespace
257
+ .trim();
258
+ }
259
+ /**
260
+ * Normalize status string to a consistent format
261
+ *
262
+ * @param status - Raw status string
263
+ * @returns Normalized status
264
+ */
265
+ export function normalizeStatus(status) {
266
+ const statusLower = status.toLowerCase().trim();
267
+ const statusMap = {
268
+ draft: "Draft",
269
+ "in progress": "In Progress",
270
+ "in-progress": "In Progress",
271
+ inprogress: "In Progress",
272
+ blocked: "Blocked",
273
+ complete: "Complete",
274
+ completed: "Complete",
275
+ done: "Complete",
276
+ review: "Review",
277
+ "needs review": "Needs Review",
278
+ "needs-review": "Needs Review",
279
+ approved: "Approved",
280
+ };
281
+ return statusMap[statusLower] || status;
282
+ }
283
+ //# sourceMappingURL=markdown-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown-utils.js","sourceRoot":"","sources":["../../src/parser/markdown-utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,116 @@
1
+ /**
2
+ * OpenSpec Spec Parser
3
+ *
4
+ * Parses OpenSpec specification files from `openspec/specs/[capability]/spec.md`.
5
+ *
6
+ * OpenSpec spec format:
7
+ * - Title from H1 heading: `# Title`
8
+ * - Purpose section: `## Purpose`
9
+ * - Requirements: `### Requirement: Name`
10
+ * - Scenarios: `#### Scenario: Description` with GIVEN/WHEN/THEN steps
11
+ */
12
+ /**
13
+ * A parsed scenario from an OpenSpec requirement
14
+ */
15
+ export interface ParsedScenario {
16
+ /** Scenario description from `#### Scenario: Description` */
17
+ description: string;
18
+ /** GIVEN steps (preconditions) */
19
+ given?: string[];
20
+ /** WHEN steps (actions) */
21
+ when?: string[];
22
+ /** THEN steps (expected outcomes) */
23
+ then?: string[];
24
+ }
25
+ /**
26
+ * A parsed requirement from an OpenSpec spec
27
+ */
28
+ export interface ParsedRequirement {
29
+ /** Requirement name from `### Requirement: Name` */
30
+ name: string;
31
+ /** Full content of the requirement section */
32
+ content: string;
33
+ /** Scenarios within this requirement */
34
+ scenarios: ParsedScenario[];
35
+ }
36
+ /**
37
+ * A fully parsed OpenSpec specification
38
+ */
39
+ export interface ParsedOpenSpecSpec {
40
+ /** Directory name (e.g., "cli-init") */
41
+ capability: string;
42
+ /** Title from H1 heading */
43
+ title: string;
44
+ /** Content from ## Purpose section */
45
+ purpose?: string;
46
+ /** Parsed requirements */
47
+ requirements: ParsedRequirement[];
48
+ /** Full markdown content of the file */
49
+ rawContent: string;
50
+ /** Absolute path to the spec file */
51
+ filePath: string;
52
+ }
53
+ /**
54
+ * OpenSpec-specific patterns for parsing spec files
55
+ */
56
+ export declare const SPEC_PATTERNS: {
57
+ /** Match requirement header: ### Requirement: Name */
58
+ REQUIREMENT: RegExp;
59
+ /** Match scenario header: #### Scenario: Description */
60
+ SCENARIO: RegExp;
61
+ /** Match GIVEN step: - **GIVEN** content or **GIVEN**: content */
62
+ GIVEN: RegExp;
63
+ /** Match WHEN step: - **WHEN** content or **WHEN**: content */
64
+ WHEN: RegExp;
65
+ /** Match THEN step: - **THEN** content or **THEN**: content */
66
+ THEN: RegExp;
67
+ };
68
+ /**
69
+ * Parse an OpenSpec spec file
70
+ *
71
+ * @param filePath - Absolute path to the spec.md file
72
+ * @returns Parsed spec object
73
+ * @throws Error if file cannot be read
74
+ *
75
+ * @example
76
+ * const spec = parseSpecFile("/path/to/openspec/specs/cli-init/spec.md");
77
+ * console.log(spec.title); // "CLI Init Specification"
78
+ * console.log(spec.capability); // "cli-init"
79
+ * console.log(spec.requirements); // Array of parsed requirements
80
+ */
81
+ export declare function parseSpecFile(filePath: string): ParsedOpenSpecSpec;
82
+ /**
83
+ * Extract the capability name from the file path
84
+ *
85
+ * Assumes path structure: .../specs/[capability]/spec.md
86
+ *
87
+ * @param filePath - Path to the spec file
88
+ * @returns Capability directory name
89
+ */
90
+ export declare function extractCapability(filePath: string): string;
91
+ /**
92
+ * Parse all requirements from spec content
93
+ *
94
+ * @param content - Full markdown content
95
+ * @returns Array of parsed requirements
96
+ */
97
+ export declare function parseRequirements(content: string): ParsedRequirement[];
98
+ /**
99
+ * Parse scenarios from requirement content
100
+ *
101
+ * @param content - Requirement section content
102
+ * @returns Array of parsed scenarios
103
+ */
104
+ export declare function parseScenarios(content: string): ParsedScenario[];
105
+ /**
106
+ * Parse GIVEN/WHEN/THEN steps from scenario lines
107
+ *
108
+ * @param lines - Lines within a scenario section
109
+ * @returns Object with given, when, then arrays
110
+ */
111
+ export declare function parseGivenWhenThen(lines: string[]): {
112
+ given: string[];
113
+ when: string[];
114
+ then: string[];
115
+ };
116
+ //# sourceMappingURL=spec-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spec-parser.d.ts","sourceRoot":"","sources":["../../src/parser/spec-parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAUH;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,6DAA6D;IAC7D,WAAW,EAAE,MAAM,CAAC;IACpB,kCAAkC;IAClC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,2BAA2B;IAC3B,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,qCAAqC;IACrC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,8CAA8C;IAC9C,OAAO,EAAE,MAAM,CAAC;IAChB,wCAAwC;IACxC,SAAS,EAAE,cAAc,EAAE,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,wCAAwC;IACxC,UAAU,EAAE,MAAM,CAAC;IACnB,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,sCAAsC;IACtC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,0BAA0B;IAC1B,YAAY,EAAE,iBAAiB,EAAE,CAAC;IAClC,wCAAwC;IACxC,UAAU,EAAE,MAAM,CAAC;IACnB,qCAAqC;IACrC,QAAQ,EAAE,MAAM,CAAC;CAClB;AAMD;;GAEG;AACH,eAAO,MAAM,aAAa;IACxB,sDAAsD;;IAGtD,wDAAwD;;IAGxD,kEAAkE;;IAGlE,+DAA+D;;IAG/D,+DAA+D;;CAEhE,CAAC;AAMF;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,kBAAkB,CAyBlE;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAU1D;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,iBAAiB,EAAE,CA2CtE;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,EAAE,CA4ChE;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,MAAM,EAAE,GACd;IAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAgCrD"}