@girardelli/architect 5.0.0 → 8.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 (335) hide show
  1. package/dist/{cli.d.ts → src/adapters/cli.d.ts} +1 -2
  2. package/dist/{cli.js → src/adapters/cli.js} +191 -213
  3. package/dist/src/adapters/cli.js.map +1 -0
  4. package/dist/src/adapters/github-action.d.ts +9 -0
  5. package/dist/src/adapters/github-action.js +94 -0
  6. package/dist/src/adapters/github-action.js.map +1 -0
  7. package/dist/src/adapters/html-reporter/scripts.d.ts +5 -0
  8. package/dist/src/adapters/html-reporter/scripts.js +400 -0
  9. package/dist/src/adapters/html-reporter/scripts.js.map +1 -0
  10. package/dist/src/adapters/html-reporter/sections/agents.d.ts +2 -0
  11. package/dist/src/adapters/html-reporter/sections/agents.js +260 -0
  12. package/dist/src/adapters/html-reporter/sections/agents.js.map +1 -0
  13. package/dist/src/adapters/html-reporter/sections/anti-patterns.d.ts +13 -0
  14. package/dist/src/adapters/html-reporter/sections/anti-patterns.js +64 -0
  15. package/dist/src/adapters/html-reporter/sections/anti-patterns.js.map +1 -0
  16. package/dist/src/adapters/html-reporter/sections/header.d.ts +3 -0
  17. package/dist/src/adapters/html-reporter/sections/header.js +30 -0
  18. package/dist/src/adapters/html-reporter/sections/header.js.map +1 -0
  19. package/dist/src/adapters/html-reporter/sections/layers.d.ts +9 -0
  20. package/dist/src/adapters/html-reporter/sections/layers.js +143 -0
  21. package/dist/src/adapters/html-reporter/sections/layers.js.map +1 -0
  22. package/dist/src/adapters/html-reporter/sections/overview.d.ts +2 -0
  23. package/dist/src/adapters/html-reporter/sections/overview.js +58 -0
  24. package/dist/src/adapters/html-reporter/sections/overview.js.map +1 -0
  25. package/dist/src/adapters/html-reporter/sections/refactoring-plan.d.ts +3 -0
  26. package/dist/src/adapters/html-reporter/sections/refactoring-plan.js +151 -0
  27. package/dist/src/adapters/html-reporter/sections/refactoring-plan.js.map +1 -0
  28. package/dist/src/adapters/html-reporter/sections/score.d.ts +7 -0
  29. package/dist/src/adapters/html-reporter/sections/score.js +70 -0
  30. package/dist/src/adapters/html-reporter/sections/score.js.map +1 -0
  31. package/dist/src/adapters/html-reporter/sections/suggestions.d.ts +7 -0
  32. package/dist/src/adapters/html-reporter/sections/suggestions.js +34 -0
  33. package/dist/src/adapters/html-reporter/sections/suggestions.js.map +1 -0
  34. package/dist/src/adapters/html-reporter/styles.d.ts +1 -0
  35. package/dist/src/adapters/html-reporter/styles.js +526 -0
  36. package/dist/src/adapters/html-reporter/styles.js.map +1 -0
  37. package/dist/src/adapters/html-reporter/utils_adapters.d.ts +20 -0
  38. package/dist/src/adapters/html-reporter/utils_adapters.js +32 -0
  39. package/dist/src/adapters/html-reporter/utils_adapters.js.map +1 -0
  40. package/dist/src/adapters/html-reporter/utils_sections.d.ts +7 -0
  41. package/dist/src/adapters/html-reporter/utils_sections.js +58 -0
  42. package/dist/src/adapters/html-reporter/utils_sections.js.map +1 -0
  43. package/dist/src/adapters/html-reporter.d.ts +10 -0
  44. package/dist/src/adapters/html-reporter.js +97 -0
  45. package/dist/src/adapters/html-reporter.js.map +1 -0
  46. package/dist/src/adapters/progress-logger.d.ts +55 -0
  47. package/dist/src/adapters/progress-logger.js +200 -0
  48. package/dist/src/adapters/progress-logger.js.map +1 -0
  49. package/dist/{refactor-reporter.d.ts → src/adapters/refactor-reporter.d.ts} +1 -2
  50. package/dist/{refactor-reporter.js → src/adapters/refactor-reporter.js} +1 -1
  51. package/dist/src/adapters/refactor-reporter.js.map +1 -0
  52. package/dist/{reporter.d.ts → src/adapters/reporter.d.ts} +1 -2
  53. package/dist/src/adapters/reporter.js.map +1 -0
  54. package/dist/src/core/GenesisTerminal.d.ts +8 -0
  55. package/dist/src/core/GenesisTerminal.js +105 -0
  56. package/dist/src/core/GenesisTerminal.js.map +1 -0
  57. package/dist/{index.d.ts → src/core/architect.d.ts} +4 -18
  58. package/dist/{index.js → src/core/architect.js} +22 -21
  59. package/dist/src/core/architect.js.map +1 -0
  60. package/dist/tests/architect-adapter-enrichment.test.d.ts +1 -0
  61. package/dist/tests/architect-adapter-enrichment.test.js +11 -0
  62. package/dist/tests/architect-adapter-enrichment.test.js.map +1 -0
  63. package/dist/tests/github-action.test.d.ts +1 -0
  64. package/dist/tests/github-action.test.js +92 -0
  65. package/dist/tests/github-action.test.js.map +1 -0
  66. package/package.json +15 -65
  67. package/src/adapters/cli.ts +492 -0
  68. package/src/adapters/github-action.ts +109 -0
  69. package/src/adapters/html-reporter/scripts.ts +402 -0
  70. package/src/adapters/html-reporter/sections/agents.ts +267 -0
  71. package/src/adapters/html-reporter/sections/anti-patterns.ts +81 -0
  72. package/src/adapters/html-reporter/sections/header.ts +35 -0
  73. package/src/adapters/html-reporter/sections/layers.ts +165 -0
  74. package/src/adapters/html-reporter/sections/overview.ts +64 -0
  75. package/src/adapters/html-reporter/sections/refactoring-plan.ts +166 -0
  76. package/src/adapters/html-reporter/sections/score.ts +80 -0
  77. package/src/adapters/html-reporter/sections/suggestions.ts +39 -0
  78. package/src/adapters/html-reporter/styles.ts +525 -0
  79. package/src/adapters/html-reporter/utils_adapters.ts +39 -0
  80. package/src/adapters/html-reporter/utils_sections.ts +55 -0
  81. package/src/adapters/html-reporter.ts +102 -0
  82. package/src/adapters/progress-logger.ts +236 -0
  83. package/src/{refactor-reporter.ts → adapters/refactor-reporter.ts} +2 -2
  84. package/src/{reporter.ts → adapters/reporter.ts} +1 -1
  85. package/src/core/GenesisTerminal.ts +127 -0
  86. package/src/{index.ts → core/architect.ts} +27 -45
  87. package/tests/github-action.test.ts +109 -0
  88. package/tsconfig.json +12 -19
  89. package/CONTRIBUTING.md +0 -140
  90. package/LICENSE +0 -21
  91. package/PROJECT_STRUCTURE.txt +0 -168
  92. package/README.md +0 -257
  93. package/architect-run.sh +0 -431
  94. package/assets/banner-v3.html +0 -561
  95. package/dist/agent-generator/context-enricher.d.ts +0 -58
  96. package/dist/agent-generator/context-enricher.d.ts.map +0 -1
  97. package/dist/agent-generator/context-enricher.js +0 -613
  98. package/dist/agent-generator/context-enricher.js.map +0 -1
  99. package/dist/agent-generator/domain-inferrer.d.ts +0 -52
  100. package/dist/agent-generator/domain-inferrer.d.ts.map +0 -1
  101. package/dist/agent-generator/domain-inferrer.js +0 -585
  102. package/dist/agent-generator/domain-inferrer.js.map +0 -1
  103. package/dist/agent-generator/framework-detector.d.ts +0 -40
  104. package/dist/agent-generator/framework-detector.d.ts.map +0 -1
  105. package/dist/agent-generator/framework-detector.js +0 -611
  106. package/dist/agent-generator/framework-detector.js.map +0 -1
  107. package/dist/agent-generator/index.d.ts +0 -47
  108. package/dist/agent-generator/index.d.ts.map +0 -1
  109. package/dist/agent-generator/index.js +0 -545
  110. package/dist/agent-generator/index.js.map +0 -1
  111. package/dist/agent-generator/stack-detector.d.ts +0 -14
  112. package/dist/agent-generator/stack-detector.d.ts.map +0 -1
  113. package/dist/agent-generator/stack-detector.js +0 -124
  114. package/dist/agent-generator/stack-detector.js.map +0 -1
  115. package/dist/agent-generator/templates/core/agents.d.ts +0 -17
  116. package/dist/agent-generator/templates/core/agents.d.ts.map +0 -1
  117. package/dist/agent-generator/templates/core/agents.js +0 -1256
  118. package/dist/agent-generator/templates/core/agents.js.map +0 -1
  119. package/dist/agent-generator/templates/core/architecture-rules.d.ts +0 -7
  120. package/dist/agent-generator/templates/core/architecture-rules.d.ts.map +0 -1
  121. package/dist/agent-generator/templates/core/architecture-rules.js +0 -274
  122. package/dist/agent-generator/templates/core/architecture-rules.js.map +0 -1
  123. package/dist/agent-generator/templates/core/general-rules.d.ts +0 -8
  124. package/dist/agent-generator/templates/core/general-rules.d.ts.map +0 -1
  125. package/dist/agent-generator/templates/core/general-rules.js +0 -301
  126. package/dist/agent-generator/templates/core/general-rules.js.map +0 -1
  127. package/dist/agent-generator/templates/core/hooks-generator.d.ts +0 -21
  128. package/dist/agent-generator/templates/core/hooks-generator.d.ts.map +0 -1
  129. package/dist/agent-generator/templates/core/hooks-generator.js +0 -233
  130. package/dist/agent-generator/templates/core/hooks-generator.js.map +0 -1
  131. package/dist/agent-generator/templates/core/index-md.d.ts +0 -7
  132. package/dist/agent-generator/templates/core/index-md.d.ts.map +0 -1
  133. package/dist/agent-generator/templates/core/index-md.js +0 -246
  134. package/dist/agent-generator/templates/core/index-md.js.map +0 -1
  135. package/dist/agent-generator/templates/core/orchestrator.d.ts +0 -8
  136. package/dist/agent-generator/templates/core/orchestrator.d.ts.map +0 -1
  137. package/dist/agent-generator/templates/core/orchestrator.js +0 -422
  138. package/dist/agent-generator/templates/core/orchestrator.js.map +0 -1
  139. package/dist/agent-generator/templates/core/preflight.d.ts +0 -8
  140. package/dist/agent-generator/templates/core/preflight.d.ts.map +0 -1
  141. package/dist/agent-generator/templates/core/preflight.js +0 -213
  142. package/dist/agent-generator/templates/core/preflight.js.map +0 -1
  143. package/dist/agent-generator/templates/core/quality-gates.d.ts +0 -11
  144. package/dist/agent-generator/templates/core/quality-gates.d.ts.map +0 -1
  145. package/dist/agent-generator/templates/core/quality-gates.js +0 -254
  146. package/dist/agent-generator/templates/core/quality-gates.js.map +0 -1
  147. package/dist/agent-generator/templates/core/security-rules.d.ts +0 -7
  148. package/dist/agent-generator/templates/core/security-rules.d.ts.map +0 -1
  149. package/dist/agent-generator/templates/core/security-rules.js +0 -528
  150. package/dist/agent-generator/templates/core/security-rules.js.map +0 -1
  151. package/dist/agent-generator/templates/core/skills-generator.d.ts +0 -19
  152. package/dist/agent-generator/templates/core/skills-generator.d.ts.map +0 -1
  153. package/dist/agent-generator/templates/core/skills-generator.js +0 -546
  154. package/dist/agent-generator/templates/core/skills-generator.js.map +0 -1
  155. package/dist/agent-generator/templates/core/workflow-fix-bug.d.ts +0 -7
  156. package/dist/agent-generator/templates/core/workflow-fix-bug.d.ts.map +0 -1
  157. package/dist/agent-generator/templates/core/workflow-fix-bug.js +0 -237
  158. package/dist/agent-generator/templates/core/workflow-fix-bug.js.map +0 -1
  159. package/dist/agent-generator/templates/core/workflow-new-feature.d.ts +0 -8
  160. package/dist/agent-generator/templates/core/workflow-new-feature.d.ts.map +0 -1
  161. package/dist/agent-generator/templates/core/workflow-new-feature.js +0 -321
  162. package/dist/agent-generator/templates/core/workflow-new-feature.js.map +0 -1
  163. package/dist/agent-generator/templates/core/workflow-review.d.ts +0 -7
  164. package/dist/agent-generator/templates/core/workflow-review.d.ts.map +0 -1
  165. package/dist/agent-generator/templates/core/workflow-review.js +0 -104
  166. package/dist/agent-generator/templates/core/workflow-review.js.map +0 -1
  167. package/dist/agent-generator/templates/domain/index.d.ts +0 -22
  168. package/dist/agent-generator/templates/domain/index.d.ts.map +0 -1
  169. package/dist/agent-generator/templates/domain/index.js +0 -1176
  170. package/dist/agent-generator/templates/domain/index.js.map +0 -1
  171. package/dist/agent-generator/templates/stack/index.d.ts +0 -8
  172. package/dist/agent-generator/templates/stack/index.d.ts.map +0 -1
  173. package/dist/agent-generator/templates/stack/index.js +0 -695
  174. package/dist/agent-generator/templates/stack/index.js.map +0 -1
  175. package/dist/agent-generator/templates/template-helpers.d.ts +0 -75
  176. package/dist/agent-generator/templates/template-helpers.d.ts.map +0 -1
  177. package/dist/agent-generator/templates/template-helpers.js +0 -726
  178. package/dist/agent-generator/templates/template-helpers.js.map +0 -1
  179. package/dist/agent-generator/types.d.ts +0 -196
  180. package/dist/agent-generator/types.d.ts.map +0 -1
  181. package/dist/agent-generator/types.js +0 -27
  182. package/dist/agent-generator/types.js.map +0 -1
  183. package/dist/analyzer.d.ts +0 -38
  184. package/dist/analyzer.d.ts.map +0 -1
  185. package/dist/analyzer.js +0 -383
  186. package/dist/analyzer.js.map +0 -1
  187. package/dist/analyzers/forecast.d.ts +0 -85
  188. package/dist/analyzers/forecast.d.ts.map +0 -1
  189. package/dist/analyzers/forecast.js +0 -337
  190. package/dist/analyzers/forecast.js.map +0 -1
  191. package/dist/analyzers/git-cache.d.ts +0 -7
  192. package/dist/analyzers/git-cache.d.ts.map +0 -1
  193. package/dist/analyzers/git-cache.js +0 -41
  194. package/dist/analyzers/git-cache.js.map +0 -1
  195. package/dist/analyzers/git-history.d.ts +0 -113
  196. package/dist/analyzers/git-history.d.ts.map +0 -1
  197. package/dist/analyzers/git-history.js +0 -333
  198. package/dist/analyzers/git-history.js.map +0 -1
  199. package/dist/analyzers/index.d.ts +0 -10
  200. package/dist/analyzers/index.d.ts.map +0 -1
  201. package/dist/analyzers/index.js +0 -7
  202. package/dist/analyzers/index.js.map +0 -1
  203. package/dist/analyzers/temporal-scorer.d.ts +0 -72
  204. package/dist/analyzers/temporal-scorer.d.ts.map +0 -1
  205. package/dist/analyzers/temporal-scorer.js +0 -140
  206. package/dist/analyzers/temporal-scorer.js.map +0 -1
  207. package/dist/anti-patterns.d.ts +0 -24
  208. package/dist/anti-patterns.d.ts.map +0 -1
  209. package/dist/anti-patterns.js +0 -230
  210. package/dist/anti-patterns.js.map +0 -1
  211. package/dist/cli.d.ts.map +0 -1
  212. package/dist/cli.js.map +0 -1
  213. package/dist/config.d.ts +0 -12
  214. package/dist/config.d.ts.map +0 -1
  215. package/dist/config.js +0 -110
  216. package/dist/config.js.map +0 -1
  217. package/dist/diagram.d.ts +0 -9
  218. package/dist/diagram.d.ts.map +0 -1
  219. package/dist/diagram.js +0 -116
  220. package/dist/diagram.js.map +0 -1
  221. package/dist/html-reporter.d.ts +0 -47
  222. package/dist/html-reporter.d.ts.map +0 -1
  223. package/dist/html-reporter.js +0 -1747
  224. package/dist/html-reporter.js.map +0 -1
  225. package/dist/index.d.ts.map +0 -1
  226. package/dist/index.js.map +0 -1
  227. package/dist/project-summarizer.d.ts +0 -38
  228. package/dist/project-summarizer.d.ts.map +0 -1
  229. package/dist/project-summarizer.js +0 -463
  230. package/dist/project-summarizer.js.map +0 -1
  231. package/dist/refactor-engine.d.ts +0 -18
  232. package/dist/refactor-engine.d.ts.map +0 -1
  233. package/dist/refactor-engine.js +0 -86
  234. package/dist/refactor-engine.js.map +0 -1
  235. package/dist/refactor-reporter.d.ts.map +0 -1
  236. package/dist/refactor-reporter.js.map +0 -1
  237. package/dist/reporter.d.ts.map +0 -1
  238. package/dist/reporter.js.map +0 -1
  239. package/dist/rules/barrel-optimizer.d.ts +0 -13
  240. package/dist/rules/barrel-optimizer.d.ts.map +0 -1
  241. package/dist/rules/barrel-optimizer.js +0 -77
  242. package/dist/rules/barrel-optimizer.js.map +0 -1
  243. package/dist/rules/dead-code-detector.d.ts +0 -21
  244. package/dist/rules/dead-code-detector.d.ts.map +0 -1
  245. package/dist/rules/dead-code-detector.js +0 -117
  246. package/dist/rules/dead-code-detector.js.map +0 -1
  247. package/dist/rules/hub-splitter.d.ts +0 -13
  248. package/dist/rules/hub-splitter.d.ts.map +0 -1
  249. package/dist/rules/hub-splitter.js +0 -110
  250. package/dist/rules/hub-splitter.js.map +0 -1
  251. package/dist/rules/import-organizer.d.ts +0 -13
  252. package/dist/rules/import-organizer.d.ts.map +0 -1
  253. package/dist/rules/import-organizer.js +0 -85
  254. package/dist/rules/import-organizer.js.map +0 -1
  255. package/dist/rules/module-grouper.d.ts +0 -13
  256. package/dist/rules/module-grouper.d.ts.map +0 -1
  257. package/dist/rules/module-grouper.js +0 -110
  258. package/dist/rules/module-grouper.js.map +0 -1
  259. package/dist/scanner.d.ts +0 -31
  260. package/dist/scanner.d.ts.map +0 -1
  261. package/dist/scanner.js +0 -328
  262. package/dist/scanner.js.map +0 -1
  263. package/dist/scorer.d.ts +0 -27
  264. package/dist/scorer.d.ts.map +0 -1
  265. package/dist/scorer.js +0 -229
  266. package/dist/scorer.js.map +0 -1
  267. package/dist/types.d.ts +0 -186
  268. package/dist/types.d.ts.map +0 -1
  269. package/dist/types.js +0 -2
  270. package/dist/types.js.map +0 -1
  271. package/examples/sample-report.md +0 -207
  272. package/jest.config.js +0 -18
  273. package/src/agent-generator/context-enricher.ts +0 -672
  274. package/src/agent-generator/domain-inferrer.ts +0 -635
  275. package/src/agent-generator/framework-detector.ts +0 -669
  276. package/src/agent-generator/index.ts +0 -634
  277. package/src/agent-generator/stack-detector.ts +0 -115
  278. package/src/agent-generator/templates/core/agents.ts +0 -1296
  279. package/src/agent-generator/templates/core/architecture-rules.ts +0 -287
  280. package/src/agent-generator/templates/core/general-rules.ts +0 -306
  281. package/src/agent-generator/templates/core/hooks-generator.ts +0 -242
  282. package/src/agent-generator/templates/core/index-md.ts +0 -260
  283. package/src/agent-generator/templates/core/orchestrator.ts +0 -459
  284. package/src/agent-generator/templates/core/preflight.ts +0 -215
  285. package/src/agent-generator/templates/core/quality-gates.ts +0 -256
  286. package/src/agent-generator/templates/core/security-rules.ts +0 -543
  287. package/src/agent-generator/templates/core/skills-generator.ts +0 -585
  288. package/src/agent-generator/templates/core/workflow-fix-bug.ts +0 -239
  289. package/src/agent-generator/templates/core/workflow-new-feature.ts +0 -323
  290. package/src/agent-generator/templates/core/workflow-review.ts +0 -106
  291. package/src/agent-generator/templates/domain/index.ts +0 -1201
  292. package/src/agent-generator/templates/stack/index.ts +0 -705
  293. package/src/agent-generator/templates/template-helpers.ts +0 -776
  294. package/src/agent-generator/types.ts +0 -232
  295. package/src/analyzer.ts +0 -447
  296. package/src/analyzers/forecast.ts +0 -496
  297. package/src/analyzers/git-cache.ts +0 -52
  298. package/src/analyzers/git-history.ts +0 -488
  299. package/src/analyzers/index.ts +0 -33
  300. package/src/analyzers/temporal-scorer.ts +0 -227
  301. package/src/anti-patterns.ts +0 -287
  302. package/src/cli.ts +0 -517
  303. package/src/config.ts +0 -123
  304. package/src/diagram.ts +0 -144
  305. package/src/html-reporter.ts +0 -1830
  306. package/src/project-summarizer.ts +0 -521
  307. package/src/refactor-engine.ts +0 -117
  308. package/src/rules/barrel-optimizer.ts +0 -97
  309. package/src/rules/dead-code-detector.ts +0 -132
  310. package/src/rules/hub-splitter.ts +0 -123
  311. package/src/rules/import-organizer.ts +0 -98
  312. package/src/rules/module-grouper.ts +0 -124
  313. package/src/scanner.ts +0 -344
  314. package/src/scorer.ts +0 -254
  315. package/src/types.ts +0 -193
  316. package/tests/agent-generator.test.ts +0 -427
  317. package/tests/analyzers-integration.test.ts +0 -174
  318. package/tests/anti-patterns.test.ts +0 -94
  319. package/tests/context-enricher.test.ts +0 -971
  320. package/tests/fixtures/monorepo/package.json +0 -6
  321. package/tests/fixtures/monorepo/packages/app/package.json +0 -12
  322. package/tests/fixtures/monorepo/packages/app/src/index.ts +0 -6
  323. package/tests/fixtures/monorepo/packages/core/package.json +0 -7
  324. package/tests/fixtures/monorepo/packages/core/src/index.ts +0 -7
  325. package/tests/forecast.test.ts +0 -509
  326. package/tests/framework-detector.test.ts +0 -1172
  327. package/tests/git-history.test.ts +0 -254
  328. package/tests/monorepo-scan.test.ts +0 -170
  329. package/tests/scanner.test.ts +0 -54
  330. package/tests/scorer.test.ts +0 -674
  331. package/tests/stack-detector.test.ts +0 -241
  332. package/tests/template-generation.test.ts +0 -706
  333. package/tests/template-helpers.test.ts +0 -1152
  334. package/tests/temporal-scorer.test.ts +0 -307
  335. /package/dist/{reporter.js → src/adapters/reporter.js} +0 -0
@@ -0,0 +1,81 @@
1
+ import { AnalysisReport} from '@girardelli/architect-core/src/core/types/core.js';
2
+
3
+ import { escapeHtml } from "../utils_sections.js";
4
+
5
+ export function renderAntiPatternBubbles(
6
+ report: AnalysisReport,
7
+ grouped: Record<string, { count: number; severity: string; locations: string[]; suggestion: string }>
8
+ ): string {
9
+ if (report.antiPatterns.length === 0) {
10
+ return `
11
+ <h2 class="section-title">✅ Anti-Patterns</h2>
12
+ <div class="card success-card">
13
+ <p>No significant anti-patterns detected. Excellent architecture!</p>
14
+ </div>`;
15
+ }
16
+
17
+ const severityWeight: Record<string, number> = {
18
+ CRITICAL: 80, HIGH: 60, MEDIUM: 40, LOW: 25,
19
+ };
20
+
21
+ const severityColor: Record<string, string> = {
22
+ CRITICAL: '#ef4444', HIGH: '#f59e0b', MEDIUM: '#60a5fa', LOW: '#22c55e',
23
+ };
24
+
25
+ const bubbles = Object.entries(grouped).map(([name, data]) => ({
26
+ name,
27
+ count: data.count,
28
+ severity: data.severity,
29
+ radius: (severityWeight[data.severity] || 30) + data.count * 8,
30
+ color: severityColor[data.severity] || '#64748b',
31
+ }));
32
+
33
+ return `
34
+ <h2 class="section-title">🫧 Anti-Pattern Impact Map</h2>
35
+ <div class="card" style="display:flex; justify-content:center;">
36
+ <div id="bubble-chart" style="width:100%; min-height:300px;"></div>
37
+ </div>
38
+ <script type="application/json" id="bubble-data">${JSON.stringify(bubbles)}<\/script>`;
39
+ }
40
+
41
+
42
+ export function renderAntiPatterns(
43
+ report: AnalysisReport,
44
+ grouped: Record<string, { count: number; severity: string; locations: string[]; suggestion: string }>
45
+ ): string {
46
+ if (report.antiPatterns.length === 0) return '';
47
+
48
+ const rows = Object.entries(grouped)
49
+ .sort((a, b) => b[1].count - a[1].count)
50
+ .map(
51
+ ([name, data]) => `
52
+ <tr>
53
+ <td><strong>${escapeHtml(name)}</strong></td>
54
+ <td class="count-cell">${data.count}</td>
55
+ <td><span class="severity-badge severity-${data.severity}">${data.severity}</span></td>
56
+ <td><small class="suggestion">${escapeHtml(data.suggestion)}</small></td>
57
+ <td><div class="locations">${data.locations
58
+ .slice(0, 5)
59
+ .map((l) => `<code>${escapeHtml(l)}</code>`)
60
+ .join(' ')}${data.locations.length > 5 ? ` <em>+${data.count - 5} more</em>` : ''}</div></td>
61
+ </tr>`
62
+ )
63
+ .join('');
64
+
65
+ return `
66
+ <h2 class="section-title">⚠️ Anti-Pattern Details (${report.antiPatterns.length})</h2>
67
+ <div class="card">
68
+ <table>
69
+ <thead>
70
+ <tr>
71
+ <th>Pattern</th>
72
+ <th>Count</th>
73
+ <th>Severity</th>
74
+ <th>Suggestion</th>
75
+ <th>Locations</th>
76
+ </tr>
77
+ </thead>
78
+ <tbody>${rows}</tbody>
79
+ </table>
80
+ </div>`;
81
+ }
@@ -0,0 +1,35 @@
1
+ import { AnalysisReport } from '@girardelli/architect-core/src/core/types/core.js';
2
+
3
+ import { escapeHtml } from "../utils_sections.js";
4
+
5
+ export function renderHeader(report: AnalysisReport): string {
6
+ const date = new Date(report.timestamp).toLocaleDateString('en-US', {
7
+ year: 'numeric',
8
+ month: 'long',
9
+ day: 'numeric',
10
+ });
11
+ return `
12
+ <div class="header">
13
+ <h1>🏗️ Architect</h1>
14
+ <p class="subtitle">Architecture Analysis Report</p>
15
+ <div class="meta">
16
+ <span>📂 <strong>${escapeHtml(report.projectInfo.name)}</strong></span>
17
+ <span>📁 <strong>${report.projectInfo.totalFiles}</strong> files</span>
18
+ <span>📝 <strong>${report.projectInfo.totalLines.toLocaleString()}</strong> lines</span>
19
+ <span>💻 <strong>${report.projectInfo.primaryLanguages.join(', ')}</strong></span>
20
+ ${report.projectInfo.frameworks.length > 0 ? `<span>🔧 <strong>${report.projectInfo.frameworks.join(', ')}</strong></span>` : ''}
21
+ <span>📅 <strong>${date}</strong></span>
22
+ </div>
23
+ </div>`;
24
+ }
25
+
26
+
27
+ export function renderFooter(): string {
28
+ return `
29
+ <div class="footer">
30
+ <p>Generated by <a href="https://github.com/camilooscargbaptista/architect">⚡ Architect v8.1</a> — Enterprise Architecture Intelligence</p>
31
+ <p>By <strong>Camilo Girardelli</strong> · <a href="https://www.girardellitecnologia.com">Girardelli Tecnologia</a></p>
32
+ </div>`;
33
+ }
34
+
35
+ // ── Refactoring Plan Section ──
@@ -0,0 +1,165 @@
1
+ import { AnalysisReport } from '@girardelli/architect-core/src/core/types/core.js';
2
+
3
+ import { escapeHtml } from "../utils_sections.js";
4
+
5
+ export function renderLayers(report: AnalysisReport): string {
6
+ if (report.layers.length === 0) return '';
7
+
8
+ const layerColors: Record<string, string> = {
9
+ API: '#ec4899',
10
+ Service: '#3b82f6',
11
+ Data: '#10b981',
12
+ UI: '#f59e0b',
13
+ Infrastructure: '#8b5cf6',
14
+ };
15
+
16
+ const cards = report.layers
17
+ .map((l) => {
18
+ const color = layerColors[l.name] || '#64748b';
19
+ return `
20
+ <div class="layer-card" style="--layer-color: ${color}">
21
+ <div class="count" style="color: ${color}">${l.files.length}</div>
22
+ <div class="name">${l.name}</div>
23
+ <div class="desc">${escapeHtml(l.description)}</div>
24
+ </div>`;
25
+ })
26
+ .join('');
27
+
28
+ return `
29
+ <h2 class="section-title">📐 Architectural Layers</h2>
30
+ <div class="layers-grid">${cards}</div>`;
31
+ }
32
+
33
+ /**
34
+ * Interactive D3.js force-directed dependency graph
35
+ */
36
+
37
+ export function renderDependencyGraph(report: AnalysisReport): string {
38
+ if (report.dependencyGraph.edges.length === 0) return '';
39
+
40
+ // Build real file set — only files that appear as SOURCE in edges (these are real scanned files)
41
+ const realFiles = new Set(report.dependencyGraph.edges.map(e => e.from));
42
+
43
+ // Count connections only for real files
44
+ const connectionCount: Record<string, number> = {};
45
+ for (const edge of report.dependencyGraph.edges) {
46
+ if (realFiles.has(edge.from)) {
47
+ connectionCount[edge.from] = (connectionCount[edge.from] || 0) + 1;
48
+ }
49
+ if (realFiles.has(edge.to)) {
50
+ connectionCount[edge.to] = (connectionCount[edge.to] || 0) + 1;
51
+ }
52
+ }
53
+
54
+ // Build layer map from report layers
55
+ const layerMap: Record<string, string> = {};
56
+ for (const layer of report.layers) {
57
+ for (const file of layer.files) {
58
+ layerMap[file] = layer.name;
59
+ }
60
+ }
61
+
62
+ // Create nodes only from real files
63
+ const allNodes = [...realFiles].map(n => ({
64
+ id: n,
65
+ name: n.split('/').pop() || n,
66
+ connections: connectionCount[n] || 0,
67
+ layer: layerMap[n] || 'Other',
68
+ }));
69
+
70
+ // ── Fallback: color by module/directory when layer detection is weak ──
71
+ const otherCount = allNodes.filter(n => n.layer === 'Other').length;
72
+ const useModuleColoring = allNodes.length > 0 && (otherCount / allNodes.length) > 0.7;
73
+
74
+ // Palette for module-based coloring (10 distinct, vibrant colors)
75
+ const modulePalette = [
76
+ '#3b82f6', '#ec4899', '#10b981', '#f59e0b', '#8b5cf6',
77
+ '#06b6d4', '#ef4444', '#84cc16', '#f97316', '#6366f1',
78
+ ];
79
+
80
+ let moduleColorMap: Record<string, string> = {};
81
+ if (useModuleColoring) {
82
+ // Extract module (first meaningful directory) from each node path
83
+ const getModule = (filePath: string): string => {
84
+ const parts = filePath.split('/');
85
+ if (parts.length < 2) return 'root';
86
+ const first = parts[0];
87
+ // If first dir is common source dir, use second level
88
+ if (['src', 'lib', 'app', 'packages', 'modules', 'features', 'apps'].includes(first)) {
89
+ return parts.length > 2 ? parts[1] : first;
90
+ }
91
+ return first;
92
+ };
93
+
94
+ // Assign colors to modules
95
+ const moduleNames = [...new Set(allNodes.map(n => getModule(n.id)))];
96
+ moduleNames.forEach((mod, i) => {
97
+ moduleColorMap[mod] = modulePalette[i % modulePalette.length];
98
+ });
99
+
100
+ // Reassign layer field to module name for coloring
101
+ for (const node of allNodes) {
102
+ node.layer = getModule(node.id);
103
+ }
104
+ }
105
+
106
+ // Build links only between real files
107
+ const allLinks = report.dependencyGraph.edges
108
+ .filter(e => realFiles.has(e.from) && realFiles.has(e.to))
109
+ .map(e => ({ source: e.from, target: e.to }));
110
+
111
+ // Limit to top N most-connected nodes for large projects
112
+ const maxNodes = 60;
113
+ const sortedNodes = [...allNodes].sort((a, b) => b.connections - a.connections);
114
+ const limitedNodes = sortedNodes.slice(0, maxNodes);
115
+ const limitedNodeIds = new Set(limitedNodes.map(n => n.id));
116
+ const limitedLinks = allLinks.filter(l => limitedNodeIds.has(l.source) && limitedNodeIds.has(l.target));
117
+ const isLimited = allNodes.length > maxNodes;
118
+
119
+ // Collect unique layers/modules from limited nodes
120
+ const uniqueLayers = [...new Set(limitedNodes.map(n => n.layer))];
121
+
122
+ // Build dynamic color map for legend and D3
123
+ const colorMap: Record<string, string> = useModuleColoring
124
+ ? moduleColorMap
125
+ : { API: '#ec4899', Service: '#3b82f6', Data: '#10b981', UI: '#f59e0b', Infrastructure: '#8b5cf6', Other: '#64748b' };
126
+
127
+ const legendLabel = useModuleColoring ? 'Colored by module' : 'Colored by layer';
128
+
129
+ const legendHtml = uniqueLayers.map(l => {
130
+ const color = colorMap[l] || '#64748b';
131
+ return `<span class="legend-item"><span class="legend-dot" style="background: ${color}"></span> ${l}</span>`;
132
+ }).join('');
133
+
134
+ const filterHtml = uniqueLayers.map(l => {
135
+ const color = colorMap[l] || '#64748b';
136
+ return `<label class="graph-filter-check"><input type="checkbox" checked data-layer="${l}" onchange="toggleGraphLayer('${l}', checked)"><span class="legend-dot" style="background: ${color}"></span> ${l}</label>`;
137
+ }).join('');
138
+
139
+ return `
140
+ <h2 class="section-title">🔗 Dependency Graph</h2>
141
+ <div class="card graph-card">
142
+ <div class="graph-controls">
143
+ <div class="graph-legend">
144
+ <span class="legend-label" style="color:#94a3b8;font-size:11px;margin-right:8px;">${legendLabel}:</span>
145
+ ${legendHtml}
146
+ </div>
147
+ <div class="graph-filters">
148
+ <input type="text" id="graphSearch" class="graph-search" placeholder="🔍 Search node..." oninput="filterGraphNodes(value)">
149
+ <div class="graph-layer-filters">
150
+ ${filterHtml}
151
+ </div>
152
+ </div>
153
+ ${isLimited ? `<div class="graph-limit-notice">Showing top ${maxNodes} of ${allNodes.length} source files (most connected) · ${limitedLinks.length} links</div>` : ''}
154
+ </div>
155
+ <div id="dep-graph" style="width:100%; min-height:500px;"></div>
156
+ <div class="graph-hint">🖱️ Drag nodes • Scroll to zoom • Double-click to reset • Node size = connections</div>
157
+ </div>
158
+ <script type="application/json" id="graph-nodes">${JSON.stringify(limitedNodes)}${'</'+'script>'}
159
+ <script type="application/json" id="graph-links">${JSON.stringify(limitedLinks)}${'</'+'script>'}
160
+ <script type="application/json" id="graph-colors">${JSON.stringify(colorMap)}${'</'+'script>'}`;
161
+ }
162
+
163
+ /**
164
+ * Bubble chart for anti-patterns — bigger = more severe
165
+ */
@@ -0,0 +1,64 @@
1
+ import { AnalysisReport } from '@girardelli/architect-core/src/core/types/core.js';
2
+
3
+ import { esc } from "../utils_sections.js";
4
+
5
+ export function renderProjectOverview(report: AnalysisReport): string {
6
+ const summary = report.projectSummary;
7
+ if (!summary) return '';
8
+
9
+ const modulesHtml = summary.modules.length > 0
10
+ ? summary.modules.map(m => `
11
+ <div class="overview-module">
12
+ <div class="overview-module-name">${esc(m.name)}</div>
13
+ <div class="overview-module-desc">${esc(m.description)}</div>
14
+ <div class="overview-module-files">${m.files} file${m.files > 1 ? 's' : ''}</div>
15
+ </div>`).join('')
16
+ : '<div class="overview-empty">Nenhum módulo detectado</div>';
17
+
18
+ const techHtml = summary.techStack
19
+ .map(t => `<span class="overview-tag tech-tag">${esc(t)}</span>`)
20
+ .join('');
21
+
22
+ const keywordsHtml = summary.keywords
23
+ .map(k => `<span class="overview-tag keyword-tag">${esc(k)}</span>`)
24
+ .join('');
25
+
26
+ const entryHtml = summary.entryPoints.length > 0
27
+ ? summary.entryPoints.map(e => `<code class="overview-entry">${esc(e)}</code>`).join(' ')
28
+ : '<span class="overview-empty">—</span>';
29
+
30
+ return `
31
+ <details class="section-accordion" id="overview" open>
32
+ <summary class="section-accordion-header">📋 Project Overview</summary>
33
+ <div class="section-accordion-body">
34
+ <div class="overview-grid">
35
+ <div class="overview-card overview-main">
36
+ <div class="overview-label">O que é</div>
37
+ <div class="overview-description">${esc(summary.description)}</div>
38
+ <div class="overview-purpose-row">
39
+ <span class="overview-purpose-label">Tipo:</span>
40
+ <span class="overview-purpose-value">${esc(summary.purpose)}</span>
41
+ </div>
42
+ </div>
43
+ <div class="overview-card">
44
+ <div class="overview-label">Tech Stack</div>
45
+ <div class="overview-tags">${techHtml || '<span class="overview-empty">—</span>'}</div>
46
+ </div>
47
+ <div class="overview-card">
48
+ <div class="overview-label">Keywords</div>
49
+ <div class="overview-tags">${keywordsHtml || '<span class="overview-empty">—</span>'}</div>
50
+ </div>
51
+ <div class="overview-card">
52
+ <div class="overview-label">Entry Points</div>
53
+ <div class="overview-entries">${entryHtml}</div>
54
+ </div>
55
+ </div>
56
+ <div class="overview-modules-section">
57
+ <div class="overview-label">Módulos Detectados (${summary.modules.length})</div>
58
+ <div class="overview-modules-grid">
59
+ ${modulesHtml}
60
+ </div>
61
+ </div>
62
+ </div>
63
+ </details>`;
64
+ }
@@ -0,0 +1,166 @@
1
+ import { RefactoringPlan, RefactorStep } from '@girardelli/architect-core/src/core/types/rules.js';
2
+
3
+ import { scoreColor, opColor, opIcon, escapeHtml } from "../utils_sections.js";
4
+
5
+ export function renderRefactoringPlan(plan: RefactoringPlan): string {
6
+ if (plan.steps.length === 0) {
7
+ return `
8
+ <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 1.5rem;">
9
+ <h2 class="section-title" style="margin-bottom: 0;">✅ Refactoring Plan</h2>
10
+ </div>
11
+ <div class="card success-card">
12
+ <p>No refactoring needed! Your architecture is already in great shape.</p>
13
+ </div>`;
14
+ }
15
+
16
+ const improvement = plan.estimatedScoreAfter.overall - plan.currentScore.overall;
17
+
18
+ const metrics = Object.keys(plan.currentScore.breakdown) as Array<keyof typeof plan.currentScore.breakdown>;
19
+ const bars = metrics.map(metric => {
20
+ const before = plan.currentScore.breakdown[metric];
21
+ const after = plan.estimatedScoreAfter.breakdown[metric] ?? before;
22
+ const diff = after - before;
23
+ return `
24
+ <div class="comparison-row">
25
+ <div class="refactor-metric-name">${metric}</div>
26
+ <div class="refactor-metric-bars">
27
+ <div class="rbar-before" style="width: ${before}%; background: ${scoreColor(before)}40"><span>${before}</span></div>
28
+ <div class="rbar-after" style="width: ${after}%; background: ${scoreColor(after)}"><span>${after}</span></div>
29
+ </div>
30
+ <div class="refactor-metric-diff" style="color: ${diff > 0 ? '#22c55e' : '#64748b'}">
31
+ ${diff > 0 ? `+${diff}` : diff === 0 ? '—' : String(diff)}
32
+ </div>
33
+ </div>`;
34
+ }).join('');
35
+
36
+ const stepsHtml = plan.steps.map(step => renderRefactorStep(step)).join('');
37
+
38
+ const criticalCount = plan.steps.filter(s => s.priority === 'CRITICAL').length;
39
+ const highCount = plan.steps.filter(s => s.priority === 'HIGH').length;
40
+ const mediumCount = plan.steps.filter(s => s.priority === 'MEDIUM').length;
41
+ const lowCount = plan.steps.filter(s => s.priority === 'LOW').length;
42
+
43
+ return `
44
+ <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 1.5rem; flex-wrap: wrap; gap: 1rem;">
45
+ <h2 class="section-title" style="margin-bottom: 0;">🔧 Refactoring Plan</h2>
46
+ <label style="display: flex; align-items: center; gap: 0.5rem; cursor: pointer; color: #10b981; font-weight: 600; font-size: 0.9rem; background: #10b98115; padding: 0.4rem 0.8rem; border-radius: 6px; border: 1px solid #10b98140;">
47
+ <input type="checkbox" id="select-all-prompts" style="width: 1.1rem; height: 1.1rem; accent-color: #10b981; cursor: pointer;" onchange="window.toggleAllPrompts(this.checked)">
48
+ Selecionar Todos
49
+ </label>
50
+ </div>
51
+ <button id="download-selected-prompts-btn" onclick="window.downloadSelectedPrompts()" style="display: none; position: fixed; bottom: 30px; right: 30px; background: #10b981; color: white; border: none; padding: 1rem 2rem; border-radius: 50px; font-weight: bold; font-size: 1rem; cursor: pointer; box-shadow: 0 10px 25px rgba(16,185,129,0.4); z-index: 9999; transition: all 0.3s; align-items: center; gap: 0.5rem;">
52
+ 📥 Criar <span id="prompt-count-badge" style="background: white; color: #10b981; padding: 0.1rem 0.5rem; border-radius: 10px; font-size: 0.9rem;">0</span> Prompts p/ IA
53
+ </button>
54
+ <p>Below are action-items ordered by impact and safety. Implementing these gives an estimated score of <strong>${plan.estimatedScoreAfter.overall}/100</strong> (+${improvement}).</p>
55
+
56
+ <div class="card refactor-score">
57
+ <div class="refactor-score-pair">
58
+ <div class="rscore-box">
59
+ <div class="rscore-num" style="color: ${scoreColor(plan.currentScore.overall)}">${plan.currentScore.overall}</div>
60
+ <div class="rscore-label">Current</div>
61
+ </div>
62
+ <div class="rscore-arrow">
63
+ <svg width="60" height="30" viewBox="0 0 60 30">
64
+ <path d="M5 15 L45 15 M40 8 L48 15 L40 22" stroke="#818cf8" stroke-width="2.5" fill="none"/>
65
+ </svg>
66
+ </div>
67
+ <div class="rscore-box">
68
+ <div class="rscore-num" style="color: ${scoreColor(plan.estimatedScoreAfter.overall)}">${plan.estimatedScoreAfter.overall}</div>
69
+ <div class="rscore-label">Estimated</div>
70
+ </div>
71
+ <div class="rscore-improvement" style="color: #22c55e">+${improvement} pts</div>
72
+ </div>
73
+ <div class="refactor-bars-section">
74
+ <div class="refactor-legend">
75
+ <span class="rlegend-tag rbefore">Before</span>
76
+ <span class="rlegend-tag rafter">After</span>
77
+ </div>
78
+ ${bars}
79
+ </div>
80
+ </div>
81
+
82
+ <div class="refactor-stats-row">
83
+ <div class="rstat">${plan.steps.length} steps</div>
84
+ <div class="rstat">${plan.totalOperations} operations</div>
85
+ <div class="rstat">Tier 1: ${plan.tier1Steps}</div>
86
+ <div class="rstat">Tier 2: ${plan.tier2Steps}</div>
87
+ </div>
88
+
89
+ <div class="priority-bar">
90
+ ${criticalCount ? `<div class="prio-seg prio-critical" style="flex: ${criticalCount}">🔴 ${criticalCount}</div>` : ''}
91
+ ${highCount ? `<div class="prio-seg prio-high" style="flex: ${highCount}">🟠 ${highCount}</div>` : ''}
92
+ ${mediumCount ? `<div class="prio-seg prio-medium" style="flex: ${mediumCount}">🔵 ${mediumCount}</div>` : ''}
93
+ ${lowCount ? `<div class="prio-seg prio-low" style="flex: ${lowCount}">🟢 ${lowCount}</div>` : ''}
94
+ </div>
95
+
96
+ <div class="refactor-roadmap">
97
+ ${stepsHtml}
98
+ </div>`;
99
+ }
100
+
101
+
102
+ export function renderRefactorStep(step: RefactorStep): string {
103
+ const operationsHtml = step.operations.map(op => `
104
+ <div class="rop">
105
+ <span class="rop-icon">${opIcon(op.type)}</span>
106
+ <span class="rop-badge" style="background: ${opColor(op.type)}20; color: ${opColor(op.type)}; border: 1px solid ${opColor(op.type)}40">${op.type}</span>
107
+ <code class="rop-path">${escapeHtml(op.path)}</code>
108
+ ${op.newPath ? `<span class="rop-arrow">→</span> <code class="rop-path">${escapeHtml(op.newPath)}</code>` : ''}
109
+ <div class="rop-desc">${escapeHtml(op.description)}</div>
110
+ </div>
111
+ `).join('');
112
+
113
+ const impactHtml = step.scoreImpact.map(i =>
114
+ `<span class="rimpact-tag">${i.metric}: ${i.before}→${i.after} <strong>+${i.after - i.before}</strong></span>`
115
+ ).join('');
116
+
117
+ const promptHtml = step.aiPrompt ? `
118
+ <div class="ai-prompt-box">
119
+ <div class="ai-prompt-header">
120
+ <label style="display: flex; align-items: center; gap: 0.5rem; cursor: pointer;">
121
+ <input type="checkbox" class="prompt-export-cb" data-filename="step-${step.id}-${step.rule.replace(/[^a-zA-Z0-9-]/g, '-')}.md" onchange="window.updatePromptSelection()">
122
+ <div>
123
+ <h4>🤖 Auto-Execute in AI</h4>
124
+ <p class="ai-prompt-desc">Select to batch-download this prompt for your IDE.</p>
125
+ </div>
126
+ </label>
127
+ <button class="ai-prompt-btn" onclick="window.downloadAIPrompt(this, 'step-${step.id}-refactor.md')">
128
+ 📥 Download Single
129
+ </button>
130
+ </div>
131
+ <div class="ai-prompt-pre">
132
+ <pre><code>${escapeHtml(step.aiPrompt)}</code></pre>
133
+ </div>
134
+ </div>` : '';
135
+
136
+ return `
137
+ <div class="rstep-card">
138
+ <div class="rstep-header">
139
+ <div class="rstep-number">${step.id}</div>
140
+ <div class="rstep-info">
141
+ <div class="rstep-title-row">
142
+ <h3>${escapeHtml(step.title)}</h3>
143
+ <span class="severity-badge severity-${step.priority}">${step.priority}</span>
144
+ <span class="tier-badge">Tier ${step.tier}</span>
145
+ </div>
146
+ <p class="rstep-desc">${escapeHtml(step.description)}</p>
147
+ <details class="rstep-details">
148
+ <summary>📖 Why?</summary>
149
+ <p class="rstep-rationale">${escapeHtml(step.rationale)}</p>
150
+ </details>
151
+ </div>
152
+ </div>
153
+ <details class="rstep-ops-accordion">
154
+ <summary class="rstep-ops-toggle">📋 Operations (${step.operations.length})</summary>
155
+ <div class="rstep-ops">
156
+ ${operationsHtml}
157
+ </div>
158
+ </details>
159
+ <div class="rstep-impact">
160
+ <h4>📈 Score Impact</h4>
161
+ <div class="rimpact-tags">${impactHtml}</div>
162
+ </div>
163
+ ${promptHtml}
164
+ </div>`;
165
+ }
166
+
@@ -0,0 +1,80 @@
1
+ import { AnalysisReport } from '@girardelli/architect-core/src/core/types/core.js';
2
+
3
+ import { scoreColor, scoreEmoji, scoreLabel } from "../utils_sections.js";
4
+
5
+ export function renderScoreHero(report: AnalysisReport): string {
6
+ const overall = report.score.overall;
7
+ const circumference = 2 * Math.PI * 85;
8
+ const offset = circumference * (1 - overall / 100);
9
+
10
+ const breakdownItems = Object.entries(report.score.breakdown)
11
+ .map(
12
+ ([name, score]) => `
13
+ <div class="score-item">
14
+ <div class="name">${name}</div>
15
+ <div class="val" style="color: ${scoreColor(score)}">${score} ${scoreEmoji(score)}</div>
16
+ <div class="bar-container">
17
+ <div class="bar" style="width: ${score}%; background: ${scoreColor(score)}"></div>
18
+ </div>
19
+ </div>`
20
+ )
21
+ .join('');
22
+
23
+ return `
24
+ <div class="score-hero">
25
+ <div class="score-circle">
26
+ <svg viewBox="0 0 200 200" width="180" height="180">
27
+ <circle class="bg" cx="100" cy="100" r="85" />
28
+ <circle class="fg" cx="100" cy="100" r="85"
29
+ stroke="${scoreColor(overall)}"
30
+ stroke-dasharray="${circumference}"
31
+ stroke-dashoffset="${offset}" />
32
+ </svg>
33
+ <div class="score-value">
34
+ <div class="number score-counter" data-target="${overall}" style="color: ${scoreColor(overall)}">0</div>
35
+ <div class="label">/ 100</div>
36
+ <div class="grade">${scoreLabel(overall)}</div>
37
+ </div>
38
+ </div>
39
+ <div class="score-breakdown">
40
+ ${breakdownItems}
41
+ </div>
42
+ </div>`;
43
+ }
44
+
45
+ /**
46
+ * Radar chart for the 4 score components
47
+ */
48
+
49
+ export function renderRadarChart(report: AnalysisReport): string {
50
+ // @ts-ignore - Audit cleanup unused variable
51
+ const entries = Object.entries(report.score.breakdown);
52
+ return `
53
+ <h2 class="section-title">🎯 Health Radar</h2>
54
+ <div class="card" style="display: flex; justify-content: center;">
55
+ <svg id="radar-chart" width="350" height="350" viewBox="0 0 350 350"></svg>
56
+ </div>`;
57
+ }
58
+
59
+
60
+ export function renderStats(report: AnalysisReport): string {
61
+ return `
62
+ <div class="stats-grid">
63
+ <div class="stat-card">
64
+ <div class="value stat-counter" data-target="${report.projectInfo.totalFiles}">0</div>
65
+ <div class="label">Files Scanned</div>
66
+ </div>
67
+ <div class="stat-card">
68
+ <div class="value stat-counter" data-target="${report.projectInfo.totalLines}">0</div>
69
+ <div class="label">Lines of Code</div>
70
+ </div>
71
+ <div class="stat-card">
72
+ <div class="value stat-counter" data-target="${report.antiPatterns.length}">0</div>
73
+ <div class="label">Anti-Patterns</div>
74
+ </div>
75
+ <div class="stat-card">
76
+ <div class="value stat-counter" data-target="${report.dependencyGraph.edges.length}">0</div>
77
+ <div class="label">Dependencies</div>
78
+ </div>
79
+ </div>`;
80
+ }
@@ -0,0 +1,39 @@
1
+ import { escapeHtml } from "../utils_sections.js";
2
+
3
+ export function renderSuggestions(
4
+ suggestions: Array<{ priority: string; title: string; description: string; impact: string; count: number }>
5
+ ): string {
6
+ if (suggestions.length === 0) return '';
7
+
8
+ const rows = suggestions
9
+ .map(
10
+ (s, i) => `
11
+ <tr>
12
+ <td>${i + 1}</td>
13
+ <td><span class="severity-badge severity-${s.priority}">${s.priority}</span></td>
14
+ <td>
15
+ <strong>${escapeHtml(s.title)}</strong>
16
+ ${s.count > 1 ? `<span class="count-badge">×${s.count}</span>` : ''}
17
+ <br/><small class="suggestion">${escapeHtml(s.description)}</small>
18
+ </td>
19
+ <td class="impact">${escapeHtml(s.impact)}</td>
20
+ </tr>`
21
+ )
22
+ .join('');
23
+
24
+ return `
25
+ <h2 class="section-title">💡 Refactoring Suggestions</h2>
26
+ <div class="card">
27
+ <table>
28
+ <thead>
29
+ <tr>
30
+ <th>#</th>
31
+ <th>Priority</th>
32
+ <th>Suggestion</th>
33
+ <th>Impact</th>
34
+ </tr>
35
+ </thead>
36
+ <tbody>${rows}</tbody>
37
+ </table>
38
+ </div>`;
39
+ }