@planu/cli 0.37.0 → 0.39.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 (108) hide show
  1. package/dist/config/license-plans.json +2 -1
  2. package/dist/engine/reverse-engineer/api-detector.d.ts +3 -0
  3. package/dist/engine/reverse-engineer/api-detector.d.ts.map +1 -0
  4. package/dist/engine/reverse-engineer/api-detector.js +170 -0
  5. package/dist/engine/reverse-engineer/api-detector.js.map +1 -0
  6. package/dist/engine/reverse-engineer/complexity-analyzer.d.ts +3 -0
  7. package/dist/engine/reverse-engineer/complexity-analyzer.d.ts.map +1 -0
  8. package/dist/engine/reverse-engineer/complexity-analyzer.js +230 -0
  9. package/dist/engine/reverse-engineer/complexity-analyzer.js.map +1 -0
  10. package/dist/engine/reverse-engineer/config-analyzer.d.ts +3 -0
  11. package/dist/engine/reverse-engineer/config-analyzer.d.ts.map +1 -0
  12. package/dist/engine/reverse-engineer/config-analyzer.js +247 -0
  13. package/dist/engine/reverse-engineer/config-analyzer.js.map +1 -0
  14. package/dist/engine/reverse-engineer/dependency-graph.d.ts +3 -0
  15. package/dist/engine/reverse-engineer/dependency-graph.d.ts.map +1 -0
  16. package/dist/engine/reverse-engineer/dependency-graph.js +197 -0
  17. package/dist/engine/reverse-engineer/dependency-graph.js.map +1 -0
  18. package/dist/engine/reverse-engineer/index.d.ts +7 -0
  19. package/dist/engine/reverse-engineer/index.d.ts.map +1 -0
  20. package/dist/engine/reverse-engineer/index.js +7 -0
  21. package/dist/engine/reverse-engineer/index.js.map +1 -0
  22. package/dist/engine/reverse-engineer/orchestrator.d.ts +5 -0
  23. package/dist/engine/reverse-engineer/orchestrator.d.ts.map +1 -0
  24. package/dist/engine/reverse-engineer/orchestrator.js +200 -0
  25. package/dist/engine/reverse-engineer/orchestrator.js.map +1 -0
  26. package/dist/engine/reverse-engineer/test-analyzer.d.ts +4 -0
  27. package/dist/engine/reverse-engineer/test-analyzer.d.ts.map +1 -0
  28. package/dist/engine/reverse-engineer/test-analyzer.js +130 -0
  29. package/dist/engine/reverse-engineer/test-analyzer.js.map +1 -0
  30. package/dist/engine/spec-kit-exporter.d.ts +6 -0
  31. package/dist/engine/spec-kit-exporter.d.ts.map +1 -0
  32. package/dist/engine/spec-kit-exporter.js +227 -0
  33. package/dist/engine/spec-kit-exporter.js.map +1 -0
  34. package/dist/engine/spec-migrator.d.ts +9 -0
  35. package/dist/engine/spec-migrator.d.ts.map +1 -1
  36. package/dist/engine/spec-migrator.js +70 -0
  37. package/dist/engine/spec-migrator.js.map +1 -1
  38. package/dist/index.js +4 -3
  39. package/dist/index.js.map +1 -1
  40. package/dist/tools/create-spec/spec-builder.js +1 -1
  41. package/dist/tools/create-spec/spec-builder.js.map +1 -1
  42. package/dist/tools/create-spec.d.ts.map +1 -1
  43. package/dist/tools/create-spec.js +28 -0
  44. package/dist/tools/create-spec.js.map +1 -1
  45. package/dist/tools/export-spec.d.ts +3 -0
  46. package/dist/tools/export-spec.d.ts.map +1 -0
  47. package/dist/tools/export-spec.js +110 -0
  48. package/dist/tools/export-spec.js.map +1 -0
  49. package/dist/tools/init-project/handler.d.ts.map +1 -1
  50. package/dist/tools/init-project/handler.js +11 -1
  51. package/dist/tools/init-project/handler.js.map +1 -1
  52. package/dist/tools/init-project/result-builder.d.ts.map +1 -1
  53. package/dist/tools/init-project/result-builder.js +1 -0
  54. package/dist/tools/init-project/result-builder.js.map +1 -1
  55. package/dist/tools/register-export-tools.d.ts +3 -0
  56. package/dist/tools/register-export-tools.d.ts.map +1 -0
  57. package/dist/tools/register-export-tools.js +21 -0
  58. package/dist/tools/register-export-tools.js.map +1 -0
  59. package/dist/tools/register-spec-tools/core-spec-tools.d.ts.map +1 -1
  60. package/dist/tools/register-spec-tools/core-spec-tools.js +4 -1
  61. package/dist/tools/register-spec-tools/core-spec-tools.js.map +1 -1
  62. package/dist/tools/reverse-engineer/handler.d.ts.map +1 -1
  63. package/dist/tools/reverse-engineer/handler.js +156 -128
  64. package/dist/tools/reverse-engineer/handler.js.map +1 -1
  65. package/dist/tools/update-status-actions.d.ts +14 -0
  66. package/dist/tools/update-status-actions.d.ts.map +1 -0
  67. package/dist/tools/update-status-actions.js +91 -0
  68. package/dist/tools/update-status-actions.js.map +1 -0
  69. package/dist/tools/update-status.d.ts.map +1 -1
  70. package/dist/tools/update-status.js +36 -89
  71. package/dist/tools/update-status.js.map +1 -1
  72. package/dist/tools/validate.d.ts.map +1 -1
  73. package/dist/tools/validate.js +34 -1
  74. package/dist/tools/validate.js.map +1 -1
  75. package/dist/transports/http-transport.d.ts +7 -0
  76. package/dist/transports/http-transport.d.ts.map +1 -0
  77. package/dist/transports/http-transport.js +170 -0
  78. package/dist/transports/http-transport.js.map +1 -0
  79. package/dist/transports/index.d.ts +4 -0
  80. package/dist/transports/index.d.ts.map +1 -0
  81. package/dist/transports/index.js +4 -0
  82. package/dist/transports/index.js.map +1 -0
  83. package/dist/transports/transport-factory.d.ts +5 -0
  84. package/dist/transports/transport-factory.d.ts.map +1 -0
  85. package/dist/transports/transport-factory.js +48 -0
  86. package/dist/transports/transport-factory.js.map +1 -0
  87. package/dist/types/estimation.d.ts +1 -1
  88. package/dist/types/estimation.d.ts.map +1 -1
  89. package/dist/types/export.d.ts +24 -0
  90. package/dist/types/export.d.ts.map +1 -0
  91. package/dist/types/export.js +3 -0
  92. package/dist/types/export.js.map +1 -0
  93. package/dist/types/index.d.ts +3 -0
  94. package/dist/types/index.d.ts.map +1 -1
  95. package/dist/types/index.js +3 -0
  96. package/dist/types/index.js.map +1 -1
  97. package/dist/types/project/planu-config.d.ts +4 -0
  98. package/dist/types/project/planu-config.d.ts.map +1 -1
  99. package/dist/types/reverse-engineer.d.ts +90 -0
  100. package/dist/types/reverse-engineer.d.ts.map +1 -0
  101. package/dist/types/reverse-engineer.js +3 -0
  102. package/dist/types/reverse-engineer.js.map +1 -0
  103. package/dist/types/transport.d.ts +14 -0
  104. package/dist/types/transport.d.ts.map +1 -0
  105. package/dist/types/transport.js +2 -0
  106. package/dist/types/transport.js.map +1 -0
  107. package/package.json +11 -2
  108. package/src/config/license-plans.json +2 -1
@@ -0,0 +1,200 @@
1
+ // engine/reverse-engineer/orchestrator.ts — AC-7: Parallel analyzer orchestration
2
+ // AC-9: Spec enrichment from analysis results
3
+ // AC-10: Human-readable output summary
4
+ import { analyzeTestCoverage } from './test-analyzer.js';
5
+ import { buildDependencyGraph } from './dependency-graph.js';
6
+ import { detectApiRoutes } from './api-detector.js';
7
+ import { analyzeComplexity } from './complexity-analyzer.js';
8
+ import { analyzeConfig } from './config-analyzer.js';
9
+ const DEFAULT_OPTIONS = {
10
+ enableTest: true,
11
+ enableDeps: true,
12
+ enableApi: true,
13
+ enableComplexity: true,
14
+ enableConfig: true,
15
+ };
16
+ export async function runDeepAnalysis(projectPath, options) {
17
+ const opts = { ...DEFAULT_OPTIONS, ...options };
18
+ const start = Date.now();
19
+ // All analyzers are independent — run in parallel
20
+ const [testCoverage, dependencyGraph, apiRoutes, complexityMetrics, configAnalysis] = await Promise.all([
21
+ opts.enableTest
22
+ ? Promise.resolve(analyzeTestCoverage(projectPath))
23
+ : Promise.resolve(emptyTestCoverage()),
24
+ opts.enableDeps
25
+ ? Promise.resolve(buildDependencyGraph(projectPath))
26
+ : Promise.resolve(emptyDependencyGraph()),
27
+ opts.enableApi ? Promise.resolve(detectApiRoutes(projectPath)) : Promise.resolve([]),
28
+ opts.enableComplexity ? Promise.resolve(analyzeComplexity(projectPath)) : Promise.resolve([]),
29
+ opts.enableConfig
30
+ ? Promise.resolve(analyzeConfig(projectPath))
31
+ : Promise.resolve(emptyConfigReport()),
32
+ ]);
33
+ return {
34
+ testCoverage,
35
+ dependencyGraph,
36
+ apiRoutes,
37
+ complexityMetrics,
38
+ configAnalysis,
39
+ analysisTimeMs: Date.now() - start,
40
+ };
41
+ }
42
+ // --- AC-9: Spec enrichment helpers ---
43
+ function detectTags(result) {
44
+ const tags = [];
45
+ const tagMap = {
46
+ jest: 'vitest/jest',
47
+ vitest: 'vitest/jest',
48
+ 'next.config': 'nextjs',
49
+ 'vite.config': 'vite',
50
+ tsconfig: 'typescript',
51
+ docker: 'docker',
52
+ Docker: 'docker',
53
+ };
54
+ for (const cfg of result.configAnalysis.configFiles) {
55
+ for (const [key, tag] of Object.entries(tagMap)) {
56
+ if (cfg.includes(key)) {
57
+ tags.push(tag);
58
+ }
59
+ }
60
+ }
61
+ if (result.apiRoutes.length > 0) {
62
+ const methods = new Set(result.apiRoutes.map((r) => r.method));
63
+ if (methods.has('GET') && methods.has('POST')) {
64
+ tags.push('rest-api');
65
+ }
66
+ }
67
+ if (result.testCoverage.testedModules.length > 0) {
68
+ tags.push('has-tests');
69
+ }
70
+ return [...new Set(tags)];
71
+ }
72
+ function detectTechDebt(result) {
73
+ const items = [];
74
+ if (result.testCoverage.untestedModules.length > 0) {
75
+ items.push({
76
+ file: 'multiple files',
77
+ type: 'missing-tests',
78
+ description: `${result.testCoverage.untestedModules.length} modules without tests`,
79
+ severity: result.testCoverage.untestedModules.length > 10 ? 'high' : 'medium',
80
+ effort: 'large',
81
+ suggestion: 'Add tests for untested modules to improve coverage',
82
+ });
83
+ }
84
+ if (result.dependencyGraph.cycles.length > 0) {
85
+ items.push({
86
+ file: 'dependency graph',
87
+ type: 'anti-pattern',
88
+ description: `${result.dependencyGraph.cycles.length} circular dependency cycle(s) detected`,
89
+ severity: 'high',
90
+ effort: 'medium',
91
+ suggestion: 'Break circular dependencies by extracting shared interfaces',
92
+ });
93
+ }
94
+ const hotspots = result.complexityMetrics
95
+ .flatMap((m) => m.hotspots.map((h) => ({ ...h, file: m.file })))
96
+ .sort((a, b) => b.complexity - a.complexity)
97
+ .slice(0, 5);
98
+ if (hotspots.length > 0) {
99
+ items.push({
100
+ file: hotspots[0]?.file ?? 'unknown',
101
+ type: 'code-smell',
102
+ description: `${hotspots.length} high-complexity functions (top: ${hotspots[0]?.name} at ${hotspots[0]?.complexity})`,
103
+ severity: 'medium',
104
+ effort: 'medium',
105
+ suggestion: 'Refactor complex functions into smaller, focused units',
106
+ });
107
+ }
108
+ return items;
109
+ }
110
+ export function enrichSpecFromAnalysis(result) {
111
+ const affectedFiles = result.dependencyGraph.nodes
112
+ .slice()
113
+ .sort((a, b) => b.fanIn - a.fanIn)
114
+ .slice(0, 50)
115
+ .map((n) => n.file);
116
+ return { affectedFiles, tags: detectTags(result), techDebt: detectTechDebt(result) };
117
+ }
118
+ // --- AC-10: Output summary ---
119
+ function buildHealthLines(result) {
120
+ const lines = ['', '## Health Indicators'];
121
+ const { testCoverage } = result;
122
+ const total = testCoverage.testedModules.length + testCoverage.untestedModules.length;
123
+ const coveragePct = total > 0 ? Math.round((testCoverage.testedModules.length / total) * 100) : 0;
124
+ lines.push(`- Test coverage: ${coveragePct}% (${testCoverage.testedModules.length}/${total} modules)`);
125
+ lines.push(`- Circular dependencies: ${result.dependencyGraph.cycles.length}`);
126
+ if (result.complexityMetrics.length > 0) {
127
+ const avg = result.complexityMetrics.reduce((s, m) => s + m.avgComplexity, 0) /
128
+ result.complexityMetrics.length;
129
+ lines.push(`- Average complexity: ${avg.toFixed(1)}`);
130
+ }
131
+ lines.push(`- Config files: ${result.configAnalysis.configFiles.length}`);
132
+ lines.push(`- Environment variables: ${result.configAnalysis.envVars.length}`);
133
+ return lines;
134
+ }
135
+ export function generateAnalysisSummary(result) {
136
+ const lines = ['## Architecture Overview'];
137
+ const { nodes, hubs: hubList, orphans: orphanList } = result.dependencyGraph;
138
+ lines.push(`- ${nodes.length} modules analyzed, ${hubList.length} hub(s), ${orphanList.length} orphan(s)`);
139
+ if (result.apiRoutes.length > 0) {
140
+ const resources = [...new Set(result.apiRoutes.map((r) => r.resource))];
141
+ lines.push(`- ${result.apiRoutes.length} API routes across ${resources.length} resource(s): ${resources.slice(0, 5).join(', ')}`);
142
+ }
143
+ if (result.configAnalysis.infrastructure.length > 0) {
144
+ lines.push(`- Infrastructure: ${result.configAnalysis.infrastructure.join(', ')}`);
145
+ }
146
+ lines.push(...buildHealthLines(result));
147
+ // Top 5 risk areas
148
+ lines.push('');
149
+ lines.push('## Top 5 Risk Areas');
150
+ const riskAreas = result.complexityMetrics
151
+ .map((m) => ({
152
+ file: m.file,
153
+ complexity: m.avgComplexity,
154
+ maxFnLen: m.maxFunctionLength,
155
+ hasCoverage: result.testCoverage.testedModules.some((t) => m.file.includes(t) || t.includes(m.file)),
156
+ }))
157
+ .sort((a, b) => {
158
+ const scoreA = a.complexity * (a.hasCoverage ? 1 : 2);
159
+ const scoreB = b.complexity * (b.hasCoverage ? 1 : 2);
160
+ return scoreB - scoreA;
161
+ })
162
+ .slice(0, 5);
163
+ if (riskAreas.length === 0) {
164
+ lines.push('- No significant risk areas detected');
165
+ }
166
+ else {
167
+ for (const area of riskAreas) {
168
+ const coverageLabel = area.hasCoverage ? 'tested' : 'UNTESTED';
169
+ lines.push(`- **${area.file}**: complexity ${area.complexity.toFixed(1)}, max fn ${area.maxFnLen}L [${coverageLabel}]`);
170
+ }
171
+ }
172
+ // Suggested decomposition
173
+ lines.push('');
174
+ lines.push('## Suggested Spec Decomposition');
175
+ const hubs = result.dependencyGraph.hubs;
176
+ if (hubs.length > 0) {
177
+ lines.push(`- Hub modules (high fan-in) suggest natural spec boundaries: ${hubs.slice(0, 5).join(', ')}`);
178
+ }
179
+ if (result.apiRoutes.length > 0) {
180
+ const resources = [...new Set(result.apiRoutes.map((r) => r.resource))];
181
+ lines.push(`- API resources can be separate specs: ${resources.slice(0, 5).join(', ')}`);
182
+ }
183
+ if (result.dependencyGraph.orphans.length > 0) {
184
+ lines.push(`- Orphan modules (no dependents) are safe to refactor independently: ${result.dependencyGraph.orphans.slice(0, 5).join(', ')}`);
185
+ }
186
+ lines.push('');
187
+ lines.push(`*Analysis completed in ${result.analysisTimeMs}ms*`);
188
+ return lines.join('\n');
189
+ }
190
+ // --- Empty defaults ---
191
+ function emptyTestCoverage() {
192
+ return { testedModules: [], untestedModules: [], testToSourceRatio: 0 };
193
+ }
194
+ function emptyDependencyGraph() {
195
+ return { nodes: [], cycles: [], hubs: [], orphans: [] };
196
+ }
197
+ function emptyConfigReport() {
198
+ return { configFiles: [], envVars: [], featureFlags: [], infrastructure: [] };
199
+ }
200
+ //# sourceMappingURL=orchestrator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../../../src/engine/reverse-engineer/orchestrator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { TestCoverageReport } from '../../types/reverse-engineer.js';
2
+ export declare function isTestFile(filePath: string): boolean;
3
+ export declare function analyzeTestCoverage(rootDir: string): TestCoverageReport;
4
+ //# sourceMappingURL=test-analyzer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-analyzer.d.ts","sourceRoot":"","sources":["../../../src/engine/reverse-engineer/test-analyzer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AA2C1E,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAOpD;AAiED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,kBAAkB,CAgCvE"}
@@ -0,0 +1,130 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ const TEST_PATTERNS = [
4
+ /\.test\.\w+$/,
5
+ /\.spec\.\w+$/,
6
+ /_test\.\w+$/, // Go convention
7
+ /Test\.java$/, // JUnit convention
8
+ ];
9
+ const TEST_DIRS = new Set(['__tests__', 'test', 'tests', 'spec', 'specs']);
10
+ const SOURCE_EXTENSIONS = new Set([
11
+ '.ts',
12
+ '.tsx',
13
+ '.js',
14
+ '.jsx',
15
+ '.mjs',
16
+ '.cjs',
17
+ '.py',
18
+ '.go',
19
+ '.java',
20
+ '.kt',
21
+ '.rs',
22
+ '.rb',
23
+ '.cs',
24
+ '.cpp',
25
+ '.c',
26
+ '.swift',
27
+ ]);
28
+ const IGNORE_DIRS = new Set([
29
+ 'node_modules',
30
+ '.git',
31
+ 'dist',
32
+ 'build',
33
+ 'out',
34
+ '.next',
35
+ '.nuxt',
36
+ 'coverage',
37
+ 'vendor',
38
+ '__pycache__',
39
+ ]);
40
+ export function isTestFile(filePath) {
41
+ const basename = path.basename(filePath);
42
+ if (TEST_PATTERNS.some((p) => p.test(basename))) {
43
+ return true;
44
+ }
45
+ const parts = filePath.split(path.sep);
46
+ return parts.some((p) => TEST_DIRS.has(p));
47
+ }
48
+ function collectFiles(dir) {
49
+ const results = [];
50
+ const queue = [dir];
51
+ while (queue.length > 0) {
52
+ const current = queue.pop();
53
+ if (!current) {
54
+ continue;
55
+ }
56
+ let entries;
57
+ try {
58
+ entries = fs.readdirSync(current, { withFileTypes: true });
59
+ }
60
+ catch {
61
+ continue;
62
+ }
63
+ for (const entry of entries) {
64
+ if (IGNORE_DIRS.has(entry.name)) {
65
+ continue;
66
+ }
67
+ const full = path.join(current, entry.name);
68
+ if (entry.isDirectory()) {
69
+ queue.push(full);
70
+ }
71
+ else if (entry.isFile() && SOURCE_EXTENSIONS.has(path.extname(entry.name))) {
72
+ results.push(full);
73
+ }
74
+ }
75
+ }
76
+ return results;
77
+ }
78
+ function mapTestToSource(testFile, sourceFiles, rootDir) {
79
+ const relative = path.relative(rootDir, testFile);
80
+ // Strip test dir prefix (tests/, test/, __tests__/)
81
+ const stripped = relative
82
+ .replace(/^(?:tests?|__tests__|specs?)[/\\]/, '')
83
+ .replace(/\.(?:test|spec)\./, '.')
84
+ .replace(/_test\./, '.')
85
+ .replace(/Test\.java$/, '.java');
86
+ // Try exact match
87
+ for (const src of sourceFiles) {
88
+ const srcRel = path.relative(rootDir, src);
89
+ if (srcRel === stripped) {
90
+ return srcRel;
91
+ }
92
+ }
93
+ // Try basename match
94
+ const targetBase = path.basename(stripped, path.extname(stripped));
95
+ for (const src of sourceFiles) {
96
+ const srcBase = path.basename(src, path.extname(src));
97
+ if (srcBase === targetBase) {
98
+ return path.relative(rootDir, src);
99
+ }
100
+ }
101
+ return undefined;
102
+ }
103
+ export function analyzeTestCoverage(rootDir) {
104
+ const allFiles = collectFiles(rootDir);
105
+ const testFiles = [];
106
+ const sourceFiles = [];
107
+ for (const f of allFiles) {
108
+ if (isTestFile(f)) {
109
+ testFiles.push(f);
110
+ }
111
+ else {
112
+ sourceFiles.push(f);
113
+ }
114
+ }
115
+ const testedSet = new Set();
116
+ for (const tf of testFiles) {
117
+ const mapped = mapTestToSource(tf, sourceFiles, rootDir);
118
+ if (mapped) {
119
+ testedSet.add(mapped);
120
+ }
121
+ }
122
+ const testedModules = [...testedSet].sort();
123
+ const untestedModules = sourceFiles
124
+ .map((f) => path.relative(rootDir, f))
125
+ .filter((f) => !testedSet.has(f))
126
+ .sort();
127
+ const testToSourceRatio = sourceFiles.length > 0 ? Math.round((testFiles.length / sourceFiles.length) * 100) / 100 : 0;
128
+ return { testedModules, untestedModules, testToSourceRatio };
129
+ }
130
+ //# sourceMappingURL=test-analyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-analyzer.js","sourceRoot":"","sources":["../../../src/engine/reverse-engineer/test-analyzer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { Spec, SpecKitExportOptions, SpecKitExportResult } from '../types/index.js';
2
+ export declare function generateSpecKitSpec(spec: Spec, specContent: string, _constitution?: string): string;
3
+ export declare function generateSpecKitPlan(spec: Spec, technicalContent?: string, constitution?: string, filePlan?: string[]): string;
4
+ export declare function generateSpecKitTasks(spec: Spec, specContent: string): string;
5
+ export declare function exportToSpecKit(spec: Spec, specContent: string, options?: SpecKitExportOptions): SpecKitExportResult;
6
+ //# sourceMappingURL=spec-kit-exporter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spec-kit-exporter.d.ts","sourceRoot":"","sources":["../../src/engine/spec-kit-exporter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,oBAAoB,EAAE,mBAAmB,EAAa,MAAM,mBAAmB,CAAC;AA+CpG,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,IAAI,EACV,WAAW,EAAE,MAAM,EACnB,aAAa,CAAC,EAAE,MAAM,GACrB,MAAM,CAqDR;AAED,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,IAAI,EACV,gBAAgB,CAAC,EAAE,MAAM,EACzB,YAAY,CAAC,EAAE,MAAM,EACrB,QAAQ,CAAC,EAAE,MAAM,EAAE,GAClB,MAAM,CAgER;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CA8B5E;AAED,wBAAgB,eAAe,CAC7B,IAAI,EAAE,IAAI,EACV,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,oBAAyB,GACjC,mBAAmB,CAWrB"}
@@ -0,0 +1,227 @@
1
+ // --- Helpers ---
2
+ function extractAcceptanceCriteria(specContent) {
3
+ const criteria = [];
4
+ const lines = specContent.split('\n');
5
+ let acIndex = 0;
6
+ for (const line of lines) {
7
+ const match = /^-\s*\[[ x]\]\s*(.+)$/i.exec(line);
8
+ if (match?.[1]) {
9
+ acIndex++;
10
+ criteria.push({ id: `AC-${String(acIndex)}`, text: match[1].trim() });
11
+ }
12
+ }
13
+ return criteria;
14
+ }
15
+ function acToGivenWhenThen(text) {
16
+ // Best-effort heuristic: if AC is behavioral, map to Given/When/Then
17
+ const lower = text.toLowerCase();
18
+ if (lower.includes(' when ') || lower.includes(' if ')) {
19
+ return `- Given the system is ready\n - When ${text}\n - Then the expected outcome occurs`;
20
+ }
21
+ return `- Given the system is ready\n - When the user triggers: ${text}\n - Then the feature works as specified`;
22
+ }
23
+ function generateYamlFrontmatter(spec) {
24
+ const lines = ['---'];
25
+ lines.push(`title: "${spec.title}"`);
26
+ lines.push(`planu_id: "${spec.id}"`);
27
+ lines.push(`type: ${spec.type}`);
28
+ lines.push(`scope: ${spec.scope}`);
29
+ lines.push(`status: ${spec.status}`);
30
+ lines.push(`risk: ${spec.risk}`);
31
+ lines.push(`difficulty: ${String(spec.difficulty)}`);
32
+ if (spec.tags.length > 0) {
33
+ lines.push(`tags: [${spec.tags.map((t) => `"${t}"`).join(', ')}]`);
34
+ }
35
+ lines.push(`estimated_hours: ${String(spec.estimation.devHours + spec.estimation.reviewHours)}`);
36
+ lines.push('---');
37
+ return lines.join('\n');
38
+ }
39
+ // --- Public API ---
40
+ export function generateSpecKitSpec(spec, specContent, _constitution) {
41
+ const lines = [];
42
+ const frontmatter = generateYamlFrontmatter(spec);
43
+ lines.push(frontmatter);
44
+ lines.push('');
45
+ lines.push(`# ${spec.title}`);
46
+ lines.push('');
47
+ // User Scenarios
48
+ lines.push('## User Scenarios');
49
+ lines.push('');
50
+ const sections = extractSections(specContent);
51
+ const description = sections.summary ?? sections.description ?? spec.title;
52
+ lines.push(description);
53
+ lines.push('');
54
+ // Acceptance Scenarios (Given/When/Then)
55
+ const criteria = extractAcceptanceCriteria(specContent);
56
+ if (criteria.length > 0) {
57
+ lines.push('## Acceptance Scenarios');
58
+ lines.push('');
59
+ for (const ac of criteria) {
60
+ lines.push(`### ${ac.id}`);
61
+ lines.push(acToGivenWhenThen(ac.text));
62
+ lines.push('');
63
+ }
64
+ }
65
+ // Functional Requirements
66
+ if (criteria.length > 0) {
67
+ lines.push('## Functional Requirements');
68
+ lines.push('');
69
+ for (const ac of criteria) {
70
+ const frId = ac.id.replace('AC-', 'FR-');
71
+ lines.push(`- **${frId}**: ${ac.text}`);
72
+ }
73
+ lines.push('');
74
+ }
75
+ // Success Criteria
76
+ lines.push('## Success Criteria');
77
+ lines.push('');
78
+ if (criteria.length > 0) {
79
+ lines.push(`- All ${String(criteria.length)} acceptance criteria pass`);
80
+ }
81
+ lines.push('- No regressions introduced');
82
+ lines.push('- Code passes type checking and linting');
83
+ lines.push('');
84
+ // Planu marker for round-trip
85
+ lines.push(`<!-- planu:${spec.id} -->`);
86
+ return lines.join('\n');
87
+ }
88
+ export function generateSpecKitPlan(spec, technicalContent, constitution, filePlan) {
89
+ const lines = [];
90
+ lines.push(`# Plan: ${spec.title}`);
91
+ lines.push('');
92
+ // Technical Context
93
+ if (technicalContent) {
94
+ lines.push('## Technical Context');
95
+ lines.push('');
96
+ const techSections = extractSections(technicalContent);
97
+ if (techSections.architecture) {
98
+ lines.push('### Architecture');
99
+ lines.push(techSections.architecture);
100
+ lines.push('');
101
+ }
102
+ if (techSections['key decisions']) {
103
+ lines.push('### Key Decisions');
104
+ lines.push(techSections['key decisions']);
105
+ lines.push('');
106
+ }
107
+ // Fallback: if no recognized sections, include full content
108
+ if (!techSections.architecture && !techSections['key decisions']) {
109
+ lines.push(technicalContent.replace(/^#\s+.+\n/, '').trim());
110
+ lines.push('');
111
+ }
112
+ }
113
+ // Language/Version, Dependencies, Storage, Testing
114
+ lines.push('## Implementation Details');
115
+ lines.push('');
116
+ lines.push(`- **Type**: ${spec.type}`);
117
+ lines.push(`- **Scope**: ${spec.scope}`);
118
+ lines.push(`- **Target**: ${spec.target}`);
119
+ lines.push(`- **Estimated Hours**: ${String(spec.estimation.devHours + spec.estimation.reviewHours)}`);
120
+ lines.push('');
121
+ // Project Structure from file plan
122
+ if (filePlan && filePlan.length > 0) {
123
+ lines.push('## Project Structure');
124
+ lines.push('');
125
+ lines.push('```');
126
+ for (const file of filePlan) {
127
+ lines.push(file);
128
+ }
129
+ lines.push('```');
130
+ lines.push('');
131
+ }
132
+ // Constitution Check
133
+ if (constitution) {
134
+ lines.push('## Constitution Check');
135
+ lines.push('');
136
+ lines.push(constitution);
137
+ lines.push('');
138
+ }
139
+ lines.push(`<!-- planu:${spec.id} -->`);
140
+ return lines.join('\n');
141
+ }
142
+ export function generateSpecKitTasks(spec, specContent) {
143
+ const lines = [];
144
+ lines.push(`# Tasks: ${spec.title}`);
145
+ lines.push('');
146
+ const criteria = extractAcceptanceCriteria(specContent);
147
+ if (criteria.length === 0) {
148
+ lines.push('No tasks derived — no acceptance criteria found.');
149
+ lines.push('');
150
+ lines.push(`<!-- planu:${spec.id} -->`);
151
+ return lines.join('\n');
152
+ }
153
+ // Phase organization
154
+ const phases = categorizeTasks(criteria);
155
+ for (const phase of phases) {
156
+ lines.push(`## ${phase.name}`);
157
+ lines.push('');
158
+ for (const task of phase.tasks) {
159
+ const parallel = phase.name !== 'Setup' ? ' [P]' : '';
160
+ lines.push(`- [ ] ${task.text} [${task.id}]${parallel}`);
161
+ }
162
+ lines.push('');
163
+ }
164
+ lines.push(`<!-- planu:${spec.id} -->`);
165
+ return lines.join('\n');
166
+ }
167
+ export function exportToSpecKit(spec, specContent, options = {}) {
168
+ return {
169
+ specMd: generateSpecKitSpec(spec, specContent, options.constitution),
170
+ planMd: generateSpecKitPlan(spec, options.technicalContent, options.constitution, options.filePlan),
171
+ tasksMd: generateSpecKitTasks(spec, specContent),
172
+ };
173
+ }
174
+ // --- Internal helpers ---
175
+ function extractSections(content) {
176
+ const sections = {};
177
+ const lines = content.split('\n');
178
+ let currentHeading = '';
179
+ let currentContent = [];
180
+ for (const line of lines) {
181
+ const headingMatch = /^#{1,3}\s+(.+)/.exec(line);
182
+ if (headingMatch?.[1]) {
183
+ if (currentHeading && currentContent.length > 0) {
184
+ sections[currentHeading] = currentContent.join('\n').trim();
185
+ }
186
+ currentHeading = headingMatch[1].toLowerCase();
187
+ currentContent = [];
188
+ }
189
+ else {
190
+ currentContent.push(line);
191
+ }
192
+ }
193
+ if (currentHeading && currentContent.length > 0) {
194
+ sections[currentHeading] = currentContent.join('\n').trim();
195
+ }
196
+ return sections;
197
+ }
198
+ function categorizeTasks(criteria) {
199
+ const setup = { name: 'Setup', tasks: [] };
200
+ const core = { name: 'Core', tasks: [] };
201
+ const integration = { name: 'Integration', tasks: [] };
202
+ const polish = { name: 'Polish', tasks: [] };
203
+ for (const ac of criteria) {
204
+ const lower = ac.text.toLowerCase();
205
+ if (lower.includes('register') ||
206
+ lower.includes('create') ||
207
+ lower.includes('setup') ||
208
+ lower.includes('schema')) {
209
+ setup.tasks.push(ac);
210
+ }
211
+ else if (lower.includes('test') || lower.includes('document') || lower.includes('clean')) {
212
+ polish.tasks.push(ac);
213
+ }
214
+ else if (lower.includes('output') ||
215
+ lower.includes('write') ||
216
+ lower.includes('return') ||
217
+ lower.includes('directory')) {
218
+ integration.tasks.push(ac);
219
+ }
220
+ else {
221
+ core.tasks.push(ac);
222
+ }
223
+ }
224
+ // Filter out empty phases
225
+ return [setup, core, integration, polish].filter((p) => p.tasks.length > 0);
226
+ }
227
+ //# sourceMappingURL=spec-kit-exporter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spec-kit-exporter.js","sourceRoot":"","sources":["../../src/engine/spec-kit-exporter.ts"],"names":[],"mappings":"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"}
@@ -10,6 +10,15 @@ export declare function filterLegacySpecs(specs: Spec[]): Spec[];
10
10
  * Also rewrites planu.json.
11
11
  */
12
12
  export declare function migrateSpecs(projectPath: string, legacySpecs: Spec[], deps: SpecMigrationDeps): Promise<SpecMigrationResult>;
13
+ /**
14
+ * Detect specs whose folder name lacks the SPEC-XXX- prefix.
15
+ * E.g., folder is `planu/specs/auth/login-form/` but should be `planu/specs/auth/SPEC-012-login-form/`.
16
+ */
17
+ export declare function filterUnprefixedSpecs(specs: Spec[]): Spec[];
18
+ /**
19
+ * Rename spec folders on disk and update storage paths to include the SPEC-XXX- prefix.
20
+ */
21
+ export declare function migrateSpecFolderNames(projectPath: string, specs: Spec[], deps: SpecMigrationDeps): Promise<SpecMigrationResult>;
13
22
  /**
14
23
  * Check if a project path has a planu.json with legacy specLocation.
15
24
  */
@@ -1 +1 @@
1
- {"version":3,"file":"spec-migrator.d.ts","sourceRoot":"","sources":["../../src/engine/spec-migrator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAetF;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,CAEvD;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAChC,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,IAAI,EAAE,EACnB,IAAI,EAAE,iBAAiB,GACtB,OAAO,CAAC,mBAAmB,CAAC,CAoB9B;AA8ED;;GAEG;AACH,wBAAsB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAS3E"}
1
+ {"version":3,"file":"spec-migrator.d.ts","sourceRoot":"","sources":["../../src/engine/spec-migrator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAetF;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,CAEvD;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAChC,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,IAAI,EAAE,EACnB,IAAI,EAAE,iBAAiB,GACtB,OAAO,CAAC,mBAAmB,CAAC,CAoB9B;AAkFD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,CAU3D;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAC1C,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,IAAI,EAAE,EACb,IAAI,EAAE,iBAAiB,GACtB,OAAO,CAAC,mBAAmB,CAAC,CAsD9B;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAS3E"}