@levironexe/architect 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.
Files changed (210) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/CONTRIBUTING.md +55 -0
  3. package/README.md +341 -0
  4. package/dist/analyzers/ast-parser.d.ts +3 -0
  5. package/dist/analyzers/ast-parser.js +305 -0
  6. package/dist/analyzers/ast-parser.js.map +1 -0
  7. package/dist/analyzers/dependency-graph.d.ts +2 -0
  8. package/dist/analyzers/dependency-graph.js +67 -0
  9. package/dist/analyzers/dependency-graph.js.map +1 -0
  10. package/dist/analyzers/duplication.d.ts +2 -0
  11. package/dist/analyzers/duplication.js +56 -0
  12. package/dist/analyzers/duplication.js.map +1 -0
  13. package/dist/analyzers/file-walker.d.ts +3 -0
  14. package/dist/analyzers/file-walker.js +80 -0
  15. package/dist/analyzers/file-walker.js.map +1 -0
  16. package/dist/cli/context-runner.d.ts +1 -0
  17. package/dist/cli/context-runner.js +16 -0
  18. package/dist/cli/context-runner.js.map +1 -0
  19. package/dist/cli/index.d.ts +24 -0
  20. package/dist/cli/index.js +217 -0
  21. package/dist/cli/index.js.map +1 -0
  22. package/dist/cli/init-runner.d.ts +25 -0
  23. package/dist/cli/init-runner.js +152 -0
  24. package/dist/cli/init-runner.js.map +1 -0
  25. package/dist/cli/scan-runner.d.ts +8 -0
  26. package/dist/cli/scan-runner.js +133 -0
  27. package/dist/cli/scan-runner.js.map +1 -0
  28. package/dist/formatters/plan-json.d.ts +2 -0
  29. package/dist/formatters/plan-json.js +4 -0
  30. package/dist/formatters/plan-json.js.map +1 -0
  31. package/dist/formatters/plan-markdown.d.ts +2 -0
  32. package/dist/formatters/plan-markdown.js +42 -0
  33. package/dist/formatters/plan-markdown.js.map +1 -0
  34. package/dist/formatters/plan-prompt.d.ts +4 -0
  35. package/dist/formatters/plan-prompt.js +5 -0
  36. package/dist/formatters/plan-prompt.js.map +1 -0
  37. package/dist/formatters/plan-terminal.d.ts +5 -0
  38. package/dist/formatters/plan-terminal.js +62 -0
  39. package/dist/formatters/plan-terminal.js.map +1 -0
  40. package/dist/generators/blueprint-renderer.d.ts +3 -0
  41. package/dist/generators/blueprint-renderer.js +27 -0
  42. package/dist/generators/blueprint-renderer.js.map +1 -0
  43. package/dist/generators/claudeWriter.d.ts +3 -0
  44. package/dist/generators/claudeWriter.js +9 -0
  45. package/dist/generators/claudeWriter.js.map +1 -0
  46. package/dist/generators/copilotWriter.d.ts +3 -0
  47. package/dist/generators/copilotWriter.js +11 -0
  48. package/dist/generators/copilotWriter.js.map +1 -0
  49. package/dist/generators/cursorWriter.d.ts +3 -0
  50. package/dist/generators/cursorWriter.js +14 -0
  51. package/dist/generators/cursorWriter.js.map +1 -0
  52. package/dist/generators/genericWriter.d.ts +3 -0
  53. package/dist/generators/genericWriter.js +9 -0
  54. package/dist/generators/genericWriter.js.map +1 -0
  55. package/dist/generators/template-context.d.ts +18 -0
  56. package/dist/generators/template-context.js +126 -0
  57. package/dist/generators/template-context.js.map +1 -0
  58. package/dist/generators/templateRenderer.d.ts +2 -0
  59. package/dist/generators/templateRenderer.js +19 -0
  60. package/dist/generators/templateRenderer.js.map +1 -0
  61. package/dist/generators/windsurfWriter.d.ts +3 -0
  62. package/dist/generators/windsurfWriter.js +14 -0
  63. package/dist/generators/windsurfWriter.js.map +1 -0
  64. package/dist/generators/writer-types.d.ts +11 -0
  65. package/dist/generators/writer-types.js +40 -0
  66. package/dist/generators/writer-types.js.map +1 -0
  67. package/dist/llm/claude-provider.d.ts +8 -0
  68. package/dist/llm/claude-provider.js +22 -0
  69. package/dist/llm/claude-provider.js.map +1 -0
  70. package/dist/llm/concern-classifier.d.ts +15 -0
  71. package/dist/llm/concern-classifier.js +61 -0
  72. package/dist/llm/concern-classifier.js.map +1 -0
  73. package/dist/llm/config.d.ts +11 -0
  74. package/dist/llm/config.js +120 -0
  75. package/dist/llm/config.js.map +1 -0
  76. package/dist/llm/ollama-provider.d.ts +8 -0
  77. package/dist/llm/ollama-provider.js +27 -0
  78. package/dist/llm/ollama-provider.js.map +1 -0
  79. package/dist/llm/openai-provider.d.ts +8 -0
  80. package/dist/llm/openai-provider.js +19 -0
  81. package/dist/llm/openai-provider.js.map +1 -0
  82. package/dist/llm/prompt-builder.d.ts +12 -0
  83. package/dist/llm/prompt-builder.js +132 -0
  84. package/dist/llm/prompt-builder.js.map +1 -0
  85. package/dist/llm/provider.d.ts +17 -0
  86. package/dist/llm/provider.js +2 -0
  87. package/dist/llm/provider.js.map +1 -0
  88. package/dist/llm/response-parser.d.ts +6 -0
  89. package/dist/llm/response-parser.js +128 -0
  90. package/dist/llm/response-parser.js.map +1 -0
  91. package/dist/planner/plan-generator.d.ts +7 -0
  92. package/dist/planner/plan-generator.js +275 -0
  93. package/dist/planner/plan-generator.js.map +1 -0
  94. package/dist/planner/plan-prompt-builder.d.ts +9 -0
  95. package/dist/planner/plan-prompt-builder.js +92 -0
  96. package/dist/planner/plan-prompt-builder.js.map +1 -0
  97. package/dist/planner/plan-response-parser.d.ts +7 -0
  98. package/dist/planner/plan-response-parser.js +21 -0
  99. package/dist/planner/plan-response-parser.js.map +1 -0
  100. package/dist/planner/plan-validator.d.ts +3 -0
  101. package/dist/planner/plan-validator.js +49 -0
  102. package/dist/planner/plan-validator.js.map +1 -0
  103. package/dist/reporters/scan-json.d.ts +13 -0
  104. package/dist/reporters/scan-json.js +26 -0
  105. package/dist/reporters/scan-json.js.map +1 -0
  106. package/dist/reporters/terminal.d.ts +6 -0
  107. package/dist/reporters/terminal.js +224 -0
  108. package/dist/reporters/terminal.js.map +1 -0
  109. package/dist/scoring/consistency-score.d.ts +3 -0
  110. package/dist/scoring/consistency-score.js +23 -0
  111. package/dist/scoring/consistency-score.js.map +1 -0
  112. package/dist/scoring/duplication-score.d.ts +3 -0
  113. package/dist/scoring/duplication-score.js +16 -0
  114. package/dist/scoring/duplication-score.js.map +1 -0
  115. package/dist/scoring/health-score.d.ts +4 -0
  116. package/dist/scoring/health-score.js +20 -0
  117. package/dist/scoring/health-score.js.map +1 -0
  118. package/dist/scoring/issue-builder.d.ts +4 -0
  119. package/dist/scoring/issue-builder.js +62 -0
  120. package/dist/scoring/issue-builder.js.map +1 -0
  121. package/dist/scoring/modularity-score.d.ts +3 -0
  122. package/dist/scoring/modularity-score.js +56 -0
  123. package/dist/scoring/modularity-score.js.map +1 -0
  124. package/dist/scoring/pattern-analysis.d.ts +3 -0
  125. package/dist/scoring/pattern-analysis.js +74 -0
  126. package/dist/scoring/pattern-analysis.js.map +1 -0
  127. package/dist/scoring/separation-score.d.ts +3 -0
  128. package/dist/scoring/separation-score.js +35 -0
  129. package/dist/scoring/separation-score.js.map +1 -0
  130. package/dist/skills/detector.d.ts +4 -0
  131. package/dist/skills/detector.js +104 -0
  132. package/dist/skills/detector.js.map +1 -0
  133. package/dist/skills/lister.d.ts +9 -0
  134. package/dist/skills/lister.js +35 -0
  135. package/dist/skills/lister.js.map +1 -0
  136. package/dist/skills/loader.d.ts +6 -0
  137. package/dist/skills/loader.js +76 -0
  138. package/dist/skills/loader.js.map +1 -0
  139. package/dist/skills/structure-check.d.ts +2 -0
  140. package/dist/skills/structure-check.js +37 -0
  141. package/dist/skills/structure-check.js.map +1 -0
  142. package/dist/skills/validator.d.ts +6 -0
  143. package/dist/skills/validator.js +229 -0
  144. package/dist/skills/validator.js.map +1 -0
  145. package/dist/types/analysis.d.ts +130 -0
  146. package/dist/types/analysis.js +41 -0
  147. package/dist/types/analysis.js.map +1 -0
  148. package/dist/types/concern.d.ts +48 -0
  149. package/dist/types/concern.js +16 -0
  150. package/dist/types/concern.js.map +1 -0
  151. package/dist/types/generation.d.ts +32 -0
  152. package/dist/types/generation.js +2 -0
  153. package/dist/types/generation.js.map +1 -0
  154. package/dist/types/issue.d.ts +12 -0
  155. package/dist/types/issue.js +2 -0
  156. package/dist/types/issue.js.map +1 -0
  157. package/dist/types/pattern.d.ts +15 -0
  158. package/dist/types/pattern.js +2 -0
  159. package/dist/types/pattern.js.map +1 -0
  160. package/dist/types/plan.d.ts +56 -0
  161. package/dist/types/plan.js +2 -0
  162. package/dist/types/plan.js.map +1 -0
  163. package/dist/types/scan-output.d.ts +84 -0
  164. package/dist/types/scan-output.js +2 -0
  165. package/dist/types/scan-output.js.map +1 -0
  166. package/dist/types/scoring.d.ts +15 -0
  167. package/dist/types/scoring.js +2 -0
  168. package/dist/types/scoring.js.map +1 -0
  169. package/dist/types/skill.d.ts +97 -0
  170. package/dist/types/skill.js +2 -0
  171. package/dist/types/skill.js.map +1 -0
  172. package/dist/utils/agent-detector.d.ts +2 -0
  173. package/dist/utils/agent-detector.js +22 -0
  174. package/dist/utils/agent-detector.js.map +1 -0
  175. package/dist/utils/interactive.d.ts +6 -0
  176. package/dist/utils/interactive.js +15 -0
  177. package/dist/utils/interactive.js.map +1 -0
  178. package/dist/utils/path.d.ts +5 -0
  179. package/dist/utils/path.js +31 -0
  180. package/dist/utils/path.js.map +1 -0
  181. package/dist/utils/progress.d.ts +17 -0
  182. package/dist/utils/progress.js +48 -0
  183. package/dist/utils/progress.js.map +1 -0
  184. package/dist/utils/thresholds.d.ts +6 -0
  185. package/dist/utils/thresholds.js +48 -0
  186. package/dist/utils/thresholds.js.map +1 -0
  187. package/package.json +63 -0
  188. package/skills/meta/general-js.skill.yaml +131 -0
  189. package/skills/patterns/clerk-auth.skill.yaml +349 -0
  190. package/skills/patterns/docker-deploy.skill.yaml +214 -0
  191. package/skills/patterns/drizzle.skill.yaml +277 -0
  192. package/skills/patterns/mongoose.skill.yaml +290 -0
  193. package/skills/patterns/nextauth.skill.yaml +308 -0
  194. package/skills/patterns/playwright-e2e.skill.yaml +265 -0
  195. package/skills/patterns/prisma.skill.yaml +255 -0
  196. package/skills/patterns/s3-storage.skill.yaml +235 -0
  197. package/skills/patterns/selenium-e2e.skill.yaml +276 -0
  198. package/skills/patterns/supabase-auth.skill.yaml +298 -0
  199. package/skills/patterns/supabase.skill.yaml +304 -0
  200. package/skills/patterns/vercel-deploy.skill.yaml +219 -0
  201. package/skills/patterns/vitest-testing.skill.yaml +262 -0
  202. package/skills/stacks/express-api.skill.yaml +155 -0
  203. package/skills/stacks/fastify-api.skill.yaml +119 -0
  204. package/skills/stacks/hono-api.skill.yaml +130 -0
  205. package/skills/stacks/nestjs.skill.yaml +135 -0
  206. package/skills/stacks/nextjs-app-router.skill.yaml +176 -0
  207. package/skills/stacks/react-spa.skill.yaml +153 -0
  208. package/skills/stacks/vue-nuxt.skill.yaml +115 -0
  209. package/templates/architect-plan.md +139 -0
  210. package/templates/architect-refactor.md +119 -0
@@ -0,0 +1,275 @@
1
+ const HIGH_LOC_THRESHOLD = 500;
2
+ export function generateRefactorPlan(context) {
3
+ const { scan, primarySkill } = context;
4
+ const steps = [];
5
+ addStructureSteps(steps, scan);
6
+ addOversizedFileSteps(steps, scan);
7
+ addDuplicationSteps(steps, scan);
8
+ addDependencySteps(steps, scan);
9
+ addConcernSteps(steps, scan);
10
+ if (steps.length === 0) {
11
+ steps.push(createStep(steps, {
12
+ action: 'consolidate',
13
+ sourceFile: scan.files[0]?.relativePath ?? null,
14
+ targetFile: scan.files[0]?.relativePath ?? 'project root',
15
+ what: 'Keep the current structure and document the conventions that are already working.',
16
+ why: 'No critical structural issues were found, so a lightweight maintenance roadmap is safer than broad refactoring.',
17
+ importsToUpdate: [],
18
+ dependencyNotes: 'None; maintenance step does not require import changes.',
19
+ risk: 'low',
20
+ confidence: 'high'
21
+ }));
22
+ }
23
+ const phases = buildPhases(steps);
24
+ const issueCount = scan.issues?.length ?? 0;
25
+ return {
26
+ summary: buildSummary(scan, primarySkill, steps.length),
27
+ estimatedComplexity: estimateComplexity(scan, steps.length),
28
+ estimatedRisk: estimateRisk(scan),
29
+ phases,
30
+ validationFindings: [],
31
+ assumptions: buildAssumptions(scan, primarySkill),
32
+ source: {
33
+ targetDir: scan.summary.targetDir,
34
+ primarySkillId: primarySkill?.skill.id ?? null,
35
+ healthLabel: scan.health?.label ?? 'unavailable',
36
+ issueCount
37
+ }
38
+ };
39
+ }
40
+ function addStructureSteps(steps, scan) {
41
+ const missingEntries = scan.structureComparison?.entries.filter((entry) => entry.status === 'missing') ?? [];
42
+ for (const entry of missingEntries.slice(0, 4)) {
43
+ steps.push(createStep(steps, {
44
+ action: 'create_dir',
45
+ sourceFile: null,
46
+ targetFile: entry.path,
47
+ what: `Create ${entry.required ? 'required' : 'recommended'} architecture directory for ${trimTrailingPeriod(entry.purpose)}.`,
48
+ why: 'The detected architecture skill expects this structure and the scan found it missing.',
49
+ importsToUpdate: [],
50
+ dependencyNotes: 'None until code is moved into the new directory.',
51
+ risk: 'low',
52
+ confidence: 'high'
53
+ }));
54
+ }
55
+ }
56
+ function addOversizedFileSteps(steps, scan) {
57
+ const oversizedFiles = [...scan.files]
58
+ .filter((file) => file.isOversized || file.hasCriticalComplexity || file.loc >= HIGH_LOC_THRESHOLD)
59
+ .sort((a, b) => b.loc - a.loc);
60
+ for (const file of oversizedFiles.slice(0, 4)) {
61
+ const criticalFunction = file.functions.find((fn) => fn.isFlagged);
62
+ steps.push(createStep(steps, {
63
+ action: 'extract',
64
+ sourceFile: file.relativePath,
65
+ targetFile: suggestTargetForFile(scan, file.relativePath),
66
+ what: criticalFunction
67
+ ? `Extract ${criticalFunction.name} and related logic from ${file.relativePath}.`
68
+ : `Split high-volume responsibilities out of ${file.relativePath}.`,
69
+ why: `${file.relativePath} is a structural hotspot with ${file.loc} LOC${criticalFunction ? ` and critical function complexity ${criticalFunction.complexity}` : ''}.`,
70
+ lineRange: criticalFunction ? `${criticalFunction.startLine}-${criticalFunction.endLine}` : null,
71
+ importsToUpdate: dependentFiles(scan, file.relativePath),
72
+ dependencyNotes: dependencyNoteFor(scan, file.relativePath),
73
+ risk: file.loc >= HIGH_LOC_THRESHOLD ? 'high' : 'medium',
74
+ confidence: 'high'
75
+ }));
76
+ }
77
+ }
78
+ function addDuplicationSteps(steps, scan) {
79
+ for (const finding of scan.duplication.findings.slice(0, 3)) {
80
+ const first = finding.occurrences[0];
81
+ if (!first)
82
+ continue;
83
+ steps.push(createStep(steps, {
84
+ action: 'consolidate',
85
+ sourceFile: first.relativePath,
86
+ targetFile: 'src/shared',
87
+ what: `Consolidate duplicate block shared by ${finding.occurrences.map((item) => item.relativePath).join(', ')}.`,
88
+ why: `The scan found ${finding.duplicatedLines} duplicated lines that should move behind one reusable abstraction.`,
89
+ lineRange: `${first.startLine}-${first.endLine}`,
90
+ importsToUpdate: unique(finding.occurrences.map((item) => item.relativePath)),
91
+ dependencyNotes: 'Update each duplicate occurrence to import the shared abstraction after consolidation.',
92
+ risk: finding.occurrences.length > 2 ? 'medium' : 'low',
93
+ confidence: 'medium'
94
+ }));
95
+ }
96
+ }
97
+ function addDependencySteps(steps, scan) {
98
+ for (const hotspot of scan.dependencyGraph.hotspots.slice(0, 3)) {
99
+ steps.push(createStep(steps, {
100
+ action: 'extract',
101
+ sourceFile: hotspot.relativePath,
102
+ targetFile: suggestTargetForFile(scan, hotspot.relativePath),
103
+ what: `Extract stable contracts from dependency hotspot ${hotspot.relativePath}.`,
104
+ why: `${hotspot.relativePath} is imported by ${hotspot.dependentCount} files, so changes there have broad blast radius.`,
105
+ importsToUpdate: dependentFiles(scan, hotspot.relativePath),
106
+ dependencyNotes: dependencyNoteFor(scan, hotspot.relativePath),
107
+ risk: 'high',
108
+ confidence: 'high'
109
+ }));
110
+ }
111
+ for (const cycle of scan.dependencyGraph.circularDependencies.slice(0, 2)) {
112
+ const first = cycle.files[0] ?? null;
113
+ steps.push(createStep(steps, {
114
+ action: 'move',
115
+ sourceFile: first,
116
+ targetFile: 'src/shared',
117
+ what: `Break circular dependency ${cycle.files.join(' -> ')} by moving shared logic behind a lower-level module.`,
118
+ why: 'Circular dependencies make refactors fragile and can produce runtime initialization bugs.',
119
+ importsToUpdate: unique(cycle.files),
120
+ dependencyNotes: 'Update both sides of the cycle so higher-level modules depend on the extracted shared module.',
121
+ risk: 'high',
122
+ confidence: 'medium'
123
+ }));
124
+ }
125
+ }
126
+ function addConcernSteps(steps, scan) {
127
+ const misplaced = (scan.classifications ?? [])
128
+ .flatMap((classification) => classification.functions
129
+ .filter((fn) => fn.isMisplaced)
130
+ .map((fn) => ({
131
+ file: classification.file,
132
+ name: fn.name,
133
+ concern: fn.concern,
134
+ reason: fn.reason
135
+ })))
136
+ .slice(0, 4);
137
+ for (const item of misplaced) {
138
+ steps.push(createStep(steps, {
139
+ action: 'move',
140
+ sourceFile: item.file,
141
+ targetFile: concernTarget(item.concern),
142
+ what: `Move ${item.name} ${item.reason ? `(${item.reason})` : `to the ${item.concern} layer`}.`,
143
+ why: 'Concern classification flagged this function as misplaced relative to the detected architecture rules.',
144
+ importsToUpdate: dependentFiles(scan, item.file),
145
+ dependencyNotes: dependencyNoteFor(scan, item.file),
146
+ risk: 'medium',
147
+ confidence: 'medium'
148
+ }));
149
+ }
150
+ }
151
+ function createStep(steps, input) {
152
+ return {
153
+ stepNumber: steps.length + 1,
154
+ action: input.action,
155
+ sourceFile: input.sourceFile,
156
+ targetFile: input.targetFile,
157
+ what: input.what,
158
+ why: input.why,
159
+ lineRange: input.lineRange ?? null,
160
+ importsToUpdate: unique(input.importsToUpdate),
161
+ dependencyNotes: input.dependencyNotes,
162
+ risk: input.risk,
163
+ confidence: input.confidence ?? 'medium'
164
+ };
165
+ }
166
+ function buildPhases(steps) {
167
+ const foundation = steps.filter((step) => step.action === 'create_dir');
168
+ const foundationIds = new Set(foundation.map((step) => step.stepNumber));
169
+ const extraction = steps.filter((step) => !foundationIds.has(step.stepNumber) && (step.action === 'extract' || step.action === 'consolidate'));
170
+ const extractionIds = new Set(extraction.map((step) => step.stepNumber));
171
+ const dependency = steps.filter((step) => !foundationIds.has(step.stepNumber) && !extractionIds.has(step.stepNumber) && (step.action === 'move' || step.risk === 'high'));
172
+ const used = new Set([...foundation, ...extraction, ...dependency].map((step) => step.stepNumber));
173
+ const remaining = steps.filter((step) => !used.has(step.stepNumber));
174
+ const phases = [];
175
+ if (foundation.length > 0) {
176
+ phases.push({ name: 'Prepare target structure', description: 'Create missing architectural destinations before moving code.', steps: foundation });
177
+ }
178
+ if (extraction.length > 0) {
179
+ phases.push({ name: 'Reduce structural hotspots', description: 'Extract and consolidate the highest-impact files first.', steps: extraction });
180
+ }
181
+ if (dependency.length > 0) {
182
+ phases.push({ name: 'Stabilize dependencies', description: 'Handle dependency hotspots and cycles with explicit import updates.', steps: dependency });
183
+ }
184
+ if (remaining.length > 0 || phases.length === 0) {
185
+ phases.push({ name: 'Maintain architecture', description: 'Keep the project healthy with low-risk follow-up work.', steps: remaining.length > 0 ? remaining : steps });
186
+ }
187
+ return phases.map((phase) => ({
188
+ ...phase,
189
+ steps: uniqueByStepNumber(phase.steps).sort((a, b) => a.stepNumber - b.stepNumber)
190
+ })).filter((phase) => phase.steps.length > 0);
191
+ }
192
+ function buildSummary(scan, primarySkill, stepCount) {
193
+ const skillText = primarySkill ? ` toward ${primarySkill.skill.name}` : '';
194
+ return `Refactor ${scan.summary.totalFiles} analyzed file(s)${skillText} through ${stepCount} ordered step(s).`;
195
+ }
196
+ function buildAssumptions(scan, primarySkill) {
197
+ const assumptions = ['Plan is generated from the current scan result and does not modify source files.'];
198
+ if (primarySkill) {
199
+ assumptions.push(`Primary architecture skill is ${primarySkill.skill.name} with ${primarySkill.confidence} confidence.`);
200
+ }
201
+ else {
202
+ assumptions.push('No confident primary architecture skill was detected; stack-specific rules are not invented.');
203
+ }
204
+ if (scan.parseErrors.length > 0) {
205
+ assumptions.push(`${scan.parseErrors.length} file(s) could not be parsed, so dependency and duplication guidance may be partial.`);
206
+ }
207
+ return assumptions;
208
+ }
209
+ function estimateComplexity(scan, stepCount) {
210
+ if (stepCount >= 8 || scan.summary.flaggedFiles >= 3 || scan.summary.duplicateFindings >= 3)
211
+ return 'high';
212
+ if (stepCount >= 4 || scan.summary.flaggedFiles > 0 || scan.summary.duplicateFindings > 0)
213
+ return 'medium';
214
+ return 'low';
215
+ }
216
+ function estimateRisk(scan) {
217
+ if (scan.summary.circularDependencies > 0 || scan.summary.dependencyHotspots >= 2)
218
+ return 'high';
219
+ if (scan.summary.dependencyHotspots > 0 || scan.parseErrors.length > 0)
220
+ return 'medium';
221
+ return 'low';
222
+ }
223
+ function suggestTargetForFile(scan, relativePath) {
224
+ const required = scan.structureComparison?.entries.find((entry) => entry.status === 'missing' && entry.required);
225
+ if (required)
226
+ return required.path;
227
+ if (relativePath.includes('/'))
228
+ return relativePath.split('/').slice(0, -1).join('/');
229
+ return 'src';
230
+ }
231
+ function concernTarget(concern) {
232
+ const targets = {
233
+ routing: 'src/routes',
234
+ business_logic: 'src/services',
235
+ data_access: 'src/repositories',
236
+ validation: 'src/validation',
237
+ middleware: 'src/middleware',
238
+ ui_component: 'src/components',
239
+ utility: 'src/utils',
240
+ configuration: 'src/config'
241
+ };
242
+ return targets[concern] ?? 'src/shared';
243
+ }
244
+ function dependentFiles(scan, relativePath) {
245
+ return scan.dependencyGraph.nodes.find((node) => node.relativePath === relativePath)?.importedBy ?? [];
246
+ }
247
+ function dependencyNoteFor(scan, relativePath) {
248
+ const dependents = dependentFiles(scan, relativePath);
249
+ if (dependents.length === 0)
250
+ return 'No known import updates from the dependency graph.';
251
+ return `Update imports in ${dependents.join(', ')}.`;
252
+ }
253
+ function unique(values) {
254
+ return [...new Set(values.filter(Boolean))];
255
+ }
256
+ function uniqueByStepNumber(steps) {
257
+ const seen = new Set();
258
+ return steps.filter((step) => {
259
+ if (seen.has(step.stepNumber))
260
+ return false;
261
+ seen.add(step.stepNumber);
262
+ return true;
263
+ });
264
+ }
265
+ function trimTrailingPeriod(value) {
266
+ return value.replace(/\.+$/, '');
267
+ }
268
+ export function primarySkillFrom(scan) {
269
+ return scan.matchedSkills?.find((match) => match.primary) ?? null;
270
+ }
271
+ export function issuesBySeverity(scan) {
272
+ const rank = { critical: 0, warning: 1, info: 2 };
273
+ return [...(scan.issues ?? [])].sort((a, b) => rank[a.severity] - rank[b.severity]);
274
+ }
275
+ //# sourceMappingURL=plan-generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan-generator.js","sourceRoot":"","sources":["../../src/planner/plan-generator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { ScanResult } from '../types/analysis.js';
2
+ import type { AIAgentPrompt, RefactorPlan } from '../types/plan.js';
3
+ import type { SkillMatch } from '../types/skill.js';
4
+ export interface BuildPromptOptions {
5
+ budget?: number;
6
+ }
7
+ export declare function buildAIAgentPrompt(plan: RefactorPlan, scan: ScanResult, primarySkill: SkillMatch | null, options?: BuildPromptOptions): AIAgentPrompt;
8
+ export declare function serializePrompt(prompt: AIAgentPrompt): string;
9
+ export declare function estimateTokens(text: string): number;
@@ -0,0 +1,92 @@
1
+ const DEFAULT_BUDGET = 4000;
2
+ export function buildAIAgentPrompt(plan, scan, primarySkill, options = {}) {
3
+ const constraints = [
4
+ 'Preserve existing behavior unless a step explicitly says otherwise.',
5
+ 'Preserve and update tests with each refactor.',
6
+ 'Update imports after moving or extracting code.',
7
+ 'Avoid introducing new circular dependencies.',
8
+ 'Do not delete source code until replacement behavior is covered.'
9
+ ];
10
+ const projectContext = [
11
+ `Target: ${scan.summary.targetDir}`,
12
+ `Files analyzed: ${scan.summary.totalFiles}`,
13
+ `Health: ${plan.source.healthLabel}`,
14
+ `Complexity: ${plan.estimatedComplexity}`,
15
+ `Risk: ${plan.estimatedRisk}`,
16
+ `Top issues: ${(scan.issues ?? []).slice(0, 5).map((issue) => `${issue.severity} ${issue.category}: ${issue.message}`).join('; ') || 'none'}`
17
+ ].join('\n');
18
+ const skillBlueprint = primarySkill ? renderSkillBlueprint(primarySkill) : 'No confident primary architecture skill was detected. Use the generic plan and do not invent stack-specific rules.';
19
+ const renderedPlan = plan.phases
20
+ .map((phase) => [
21
+ `## ${phase.name}`,
22
+ phase.description,
23
+ ...phase.steps.map((step) => `${step.stepNumber}. ${step.what} Target: ${step.targetFile}. Dependencies: ${step.dependencyNotes}`)
24
+ ].join('\n'))
25
+ .join('\n\n');
26
+ const prompt = {
27
+ projectContext,
28
+ skillBlueprint,
29
+ plan: renderedPlan,
30
+ constraints,
31
+ budgetStatus: 'within_budget'
32
+ };
33
+ return trimPrompt(prompt, options.budget ?? DEFAULT_BUDGET);
34
+ }
35
+ function renderSkillBlueprint(match) {
36
+ const { skill } = match;
37
+ const required = skill.structure.requiredDirs.map((entry) => `- ${entry.path}: ${entry.purpose}`).join('\n') || '- none';
38
+ const recommended = skill.structure.recommendedDirs.map((entry) => `- ${entry.path}: ${entry.purpose}`).join('\n') || '- none';
39
+ const separation = skill.separation.rules.map((rule) => `- ${rule.concern} belongs in ${rule.belongsIn}`).join('\n') || '- none';
40
+ const naming = Object.entries(skill.patterns.naming ?? {}).map(([key, value]) => `- ${key}: ${value}`).join('\n') || '- none';
41
+ const dataFlow = skill.patterns.dataFlow ? [`Direction: ${skill.patterns.dataFlow.direction}`, ...skill.patterns.dataFlow.rules.map((rule) => `- ${rule}`)].join('\n') : 'none';
42
+ const antiPatterns = skill.antiPatterns.map((item) => `- ${item.severity}: ${item.description}`).join('\n') || '- none';
43
+ return [
44
+ `Matched skill: ${skill.name} (${skill.id}) at ${match.confidence} confidence`,
45
+ 'Target structure:',
46
+ required,
47
+ 'Recommended structure:',
48
+ recommended,
49
+ 'Separation rules:',
50
+ separation,
51
+ 'Naming conventions:',
52
+ naming,
53
+ 'Pattern expectations:',
54
+ dataFlow,
55
+ 'Anti-patterns:',
56
+ antiPatterns
57
+ ].join('\n');
58
+ }
59
+ function trimPrompt(prompt, budget) {
60
+ const serialized = serializePrompt(prompt);
61
+ if (estimateTokens(serialized) <= budget)
62
+ return prompt;
63
+ const trimmedPlan = prompt.plan.split('\n').slice(0, 80).join('\n');
64
+ return {
65
+ ...prompt,
66
+ plan: `${trimmedPlan}\n\n[Trimmed to fit prompt budget; keep highest-priority steps above.]`,
67
+ budgetStatus: 'trimmed'
68
+ };
69
+ }
70
+ export function serializePrompt(prompt) {
71
+ return [
72
+ 'You are implementing a refactoring plan generated by architect.',
73
+ '',
74
+ 'PROJECT CONTEXT',
75
+ prompt.projectContext,
76
+ '',
77
+ 'ARCHITECTURE BLUEPRINT',
78
+ prompt.skillBlueprint,
79
+ '',
80
+ 'ORDERED PLAN',
81
+ prompt.plan,
82
+ '',
83
+ 'SAFETY CONSTRAINTS',
84
+ ...prompt.constraints.map((constraint) => `- ${constraint}`),
85
+ '',
86
+ `Budget status: ${prompt.budgetStatus}`
87
+ ].join('\n');
88
+ }
89
+ export function estimateTokens(text) {
90
+ return Math.ceil(text.length / 4);
91
+ }
92
+ //# sourceMappingURL=plan-prompt-builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan-prompt-builder.js","sourceRoot":"","sources":["../../src/planner/plan-prompt-builder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { RefactorPlan } from '../types/plan.js';
2
+ export interface PlanParseResult {
3
+ ok: boolean;
4
+ plan: RefactorPlan | null;
5
+ error: string | null;
6
+ }
7
+ export declare function parseRefactorPlanResponse(response: string): PlanParseResult;
@@ -0,0 +1,21 @@
1
+ export function parseRefactorPlanResponse(response) {
2
+ try {
3
+ const parsed = JSON.parse(extractJson(response));
4
+ if (!parsed || !Array.isArray(parsed.phases) || typeof parsed.summary !== 'string') {
5
+ return { ok: false, plan: null, error: 'Response did not contain a valid RefactorPlan shape.' };
6
+ }
7
+ return { ok: true, plan: parsed, error: null };
8
+ }
9
+ catch (error) {
10
+ return {
11
+ ok: false,
12
+ plan: null,
13
+ error: error instanceof Error ? error.message : 'Failed to parse plan response.'
14
+ };
15
+ }
16
+ }
17
+ function extractJson(response) {
18
+ const fenced = response.match(/```(?:json)?\s*([\s\S]*?)```/);
19
+ return fenced?.[1]?.trim() ?? response.trim();
20
+ }
21
+ //# sourceMappingURL=plan-response-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan-response-parser.js","sourceRoot":"","sources":["../../src/planner/plan-response-parser.ts"],"names":[],"mappings":"AAQA,MAAM,UAAU,yBAAyB,CAAC,QAAgB;IACxD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAiB,CAAC;QACjE,IAAI,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;YACnF,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,sDAAsD,EAAE,CAAC;QAClG,CAAC;QAED,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IACjD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,EAAE,EAAE,KAAK;YACT,IAAI,EAAE,IAAI;YACV,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,gCAAgC;SACjF,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,QAAgB;IACnC,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC;IAC9D,OAAO,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;AAChD,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { RefactorPlan, PlanValidationFinding } from '../types/plan.js';
2
+ export declare function validateRefactorPlan(plan: RefactorPlan): RefactorPlan;
3
+ export declare function collectValidationFindings(plan: RefactorPlan): PlanValidationFinding[];
@@ -0,0 +1,49 @@
1
+ const SUPPORTED_ACTIONS = ['create_dir', 'extract', 'move', 'consolidate', 'delete', 'update_imports'];
2
+ const SOURCE_REQUIRED_ACTIONS = ['extract', 'move', 'consolidate', 'delete'];
3
+ export function validateRefactorPlan(plan) {
4
+ return {
5
+ ...plan,
6
+ validationFindings: [...plan.validationFindings, ...collectValidationFindings(plan)]
7
+ };
8
+ }
9
+ export function collectValidationFindings(plan) {
10
+ const findings = [];
11
+ const steps = plan.phases.flatMap((phase) => phase.steps);
12
+ if (plan.phases.length === 0) {
13
+ findings.push(error(null, 'Plan has no phases.', 'Generate at least one phase before rendering the plan.'));
14
+ }
15
+ if (steps.length === 0) {
16
+ findings.push(error(null, 'Plan has no actionable steps.', 'Generate at least one maintenance or refactoring step.'));
17
+ }
18
+ steps.forEach((step, index) => {
19
+ if (step.stepNumber !== index + 1) {
20
+ findings.push(error(step.stepNumber, `Expected step number ${index + 1} but found ${step.stepNumber}.`, 'Renumber plan steps sequentially across all phases.'));
21
+ }
22
+ if (!SUPPORTED_ACTIONS.includes(step.action)) {
23
+ findings.push(error(step.stepNumber, `Unsupported action: ${step.action}.`, `Use one of: ${SUPPORTED_ACTIONS.join(', ')}.`));
24
+ }
25
+ if (!step.targetFile.trim()) {
26
+ findings.push(error(step.stepNumber, 'Step is missing a target location.', 'Add the file or directory the step should create or change.'));
27
+ }
28
+ if (!step.what.trim() || !step.why.trim()) {
29
+ findings.push(error(step.stepNumber, 'Step is missing action detail or explanation.', 'Add both what to change and why it matters.'));
30
+ }
31
+ if (!Array.isArray(step.importsToUpdate)) {
32
+ findings.push(error(step.stepNumber, 'Step importsToUpdate must be a list.', 'Use an empty list when no imports are known.'));
33
+ }
34
+ if (SOURCE_REQUIRED_ACTIONS.includes(step.action) && !step.sourceFile) {
35
+ findings.push(warning(step.stepNumber, `Step ${step.action} has no source location.`, 'Add a source file or explain the source in the step text before execution.'));
36
+ }
37
+ if (step.risk === 'high' && step.importsToUpdate.length === 0 && step.dependencyNotes.toLowerCase().includes('no known') === false) {
38
+ findings.push(warning(step.stepNumber, 'High-risk step does not list imports to update.', 'Review dependency graph before executing this step.'));
39
+ }
40
+ });
41
+ return findings;
42
+ }
43
+ function error(stepNumber, message, suggestion) {
44
+ return { severity: 'error', stepNumber, message, suggestion };
45
+ }
46
+ function warning(stepNumber, message, suggestion) {
47
+ return { severity: 'warning', stepNumber, message, suggestion };
48
+ }
49
+ //# sourceMappingURL=plan-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan-validator.js","sourceRoot":"","sources":["../../src/planner/plan-validator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { ScanResult } from '../types/analysis.js';
2
+ import type { MachineReadableScanOutput, ScanDiagnostic, ScanWarning } from '../types/scan-output.js';
3
+ export interface RenderScanJsonInput {
4
+ result: ScanResult | null;
5
+ targetDir: string;
6
+ verbose: boolean;
7
+ durationMs: number;
8
+ warnings: ScanWarning[];
9
+ diagnostics: ScanDiagnostic[];
10
+ status?: MachineReadableScanOutput['run']['status'];
11
+ error?: MachineReadableScanOutput['error'];
12
+ }
13
+ export declare function renderScanJson(input: RenderScanJsonInput): string;
@@ -0,0 +1,26 @@
1
+ export function renderScanJson(input) {
2
+ const output = {
3
+ schemaVersion: '1.0',
4
+ command: {
5
+ name: 'scan',
6
+ targetDir: input.targetDir,
7
+ verbose: input.verbose
8
+ },
9
+ run: {
10
+ status: input.status ?? statusFor(input.result, input.warnings),
11
+ durationMs: input.durationMs,
12
+ outputMode: 'json'
13
+ },
14
+ result: input.result,
15
+ warnings: input.warnings,
16
+ diagnostics: input.diagnostics,
17
+ ...(input.error ? { error: input.error } : {})
18
+ };
19
+ return `${JSON.stringify(output, null, 2)}\n`;
20
+ }
21
+ function statusFor(result, warnings) {
22
+ if (!result)
23
+ return 'failed';
24
+ return warnings.some((warning) => warning.code === 'parse_error' || warning.code === 'partial_analysis') ? 'partial' : 'success';
25
+ }
26
+ //# sourceMappingURL=scan-json.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan-json.js","sourceRoot":"","sources":["../../src/reporters/scan-json.ts"],"names":[],"mappings":"AAcA,MAAM,UAAU,cAAc,CAAC,KAA0B;IACvD,MAAM,MAAM,GAA8B;QACxC,aAAa,EAAE,KAAK;QACpB,OAAO,EAAE;YACP,IAAI,EAAE,MAAM;YACZ,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,OAAO,EAAE,KAAK,CAAC,OAAO;SACvB;QACD,GAAG,EAAE;YACH,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,SAAS,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC;YAC/D,UAAU,EAAE,KAAK,CAAC,UAAU;YAC5B,UAAU,EAAE,MAAM;SACnB;QACD,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC/C,CAAC;IAEF,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC;AAChD,CAAC;AAED,SAAS,SAAS,CAAC,MAAyB,EAAE,QAAuB;IACnE,IAAI,CAAC,MAAM;QAAE,OAAO,QAAQ,CAAC;IAC7B,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,KAAK,aAAa,IAAI,OAAO,CAAC,IAAI,KAAK,kBAAkB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;AACnI,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { type ScanResult } from '../types/analysis.js';
2
+ export declare function renderDiscoveryReport(targetDirectory: string, files: string[]): void;
3
+ export declare function renderScanReport(result: ScanResult, options?: {
4
+ color?: boolean;
5
+ verbose?: boolean;
6
+ }): void;