(text)
| 51 | } |
| 52 | |
| 53 | function parseProjectSpec(text) { |
| 54 | const spec = createProjectSpecSkeleton(); |
| 55 | const normalized = text.replace(/\r\n/g, '\n'); |
| 56 | |
| 57 | const versionMatch = normalized.match(/^Version:\s*(.+)$/mi); |
| 58 | if (versionMatch) spec.version = versionMatch[1].trim(); |
| 59 | |
| 60 | const projectSection = extractSection(normalized, 'Project'); |
| 61 | const projectMeta = parseKeyValueLines(projectSection.split('\n')); |
| 62 | spec.project.name = projectMeta.name || ''; |
| 63 | spec.project.summary = projectMeta.summary || ''; |
| 64 | |
| 65 | spec.conventions = parseBulletLines(extractSection(normalized, 'Conventions').split('\n')); |
| 66 | spec.workflows = parseBulletLines(extractSection(normalized, 'Workflows').split('\n')); |
| 67 | spec.constraints = parseBulletLines(extractSection(normalized, 'Constraints').split('\n')); |
| 68 | |
| 69 | return spec; |
| 70 | } |
| 71 | |
| 72 | function validateProjectSpec(spec) { |
| 73 | const errors = []; |
no test coverage detected