@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,402 @@
1
+ import { AnalysisReport } from '@girardelli/architect-core/src/core/types/core.js';
2
+
3
+ /**
4
+ * All JavaScript for D3.js visualizations, animated counters, and radar chart
5
+ */
6
+ export function getScripts(report: AnalysisReport): string {
7
+ const breakdown = report.score.breakdown;
8
+ return `<script>
9
+ // ── Animated Counters ──
10
+ document.addEventListener('DOMContentLoaded', () => {
11
+ const counters = document.querySelectorAll('.score-counter, .stat-counter');
12
+ const observer = new IntersectionObserver((entries) => {
13
+ entries.forEach(entry => {
14
+ if (entry.isIntersecting) {
15
+ const el = entry.target;
16
+ const target = parseInt(el.dataset.target || '0');
17
+ animateCounter(el, target);
18
+ observer.unobserve(el);
19
+ }
20
+ });
21
+ }, { threshold: 0.5 });
22
+
23
+ counters.forEach(c => observer.observe(c));
24
+
25
+ // ── Sidebar Active Section Tracking ──
26
+ const sectionIds = ['score', 'layers', 'anti-patterns', 'suggestions', 'refactoring', 'agents'];
27
+ const sectionObserver = new IntersectionObserver((entries) => {
28
+ entries.forEach(entry => {
29
+ if (entry.isIntersecting) {
30
+ document.querySelectorAll('.sidebar-link').forEach(l => l.classList.remove('active'));
31
+ const link = document.querySelector('.sidebar-link[data-section="' + entry.target.id + '"]');
32
+ if (link) link.classList.add('active');
33
+ }
34
+ });
35
+ }, { threshold: 0.15, rootMargin: '-80px 0px -60% 0px' });
36
+
37
+ sectionIds.forEach(id => {
38
+ const el = document.getElementById(id);
39
+ if (el) sectionObserver.observe(el);
40
+ });
41
+ });
42
+
43
+ function animateCounter(el, target) {
44
+ const duration = 1500;
45
+ const start = performance.now();
46
+ const update = (now) => {
47
+ const elapsed = now - start;
48
+ const progress = Math.min(elapsed / duration, 1);
49
+ const ease = 1 - Math.pow(1 - progress, 3);
50
+ el.textContent = Math.round(target * ease).toLocaleString();
51
+ if (progress < 1) requestAnimationFrame(update);
52
+ };
53
+ requestAnimationFrame(update);
54
+ }
55
+
56
+ // ── Radar Chart ──
57
+ (function() {
58
+ const data = [
59
+ { axis: 'Modularity', value: ${breakdown.modularity} },
60
+ { axis: 'Coupling', value: ${breakdown.coupling} },
61
+ { axis: 'Cohesion', value: ${breakdown.cohesion} },
62
+ { axis: 'Layering', value: ${breakdown.layering} },
63
+ ];
64
+
65
+ const svg = d3.select('#radar-chart');
66
+ const w = 350, h = 350, cx = w/2, cy = h/2, maxR = 120;
67
+ const levels = 5;
68
+ const total = data.length;
69
+ const angleSlice = (Math.PI * 2) / total;
70
+
71
+ // Grid circles
72
+ for (let i = 1; i <= levels; i++) {
73
+ const r = (maxR / levels) * i;
74
+ svg.append('circle')
75
+ .attr('cx', cx).attr('cy', cy).attr('r', r)
76
+ .attr('fill', 'none').attr('stroke', '#334155').attr('stroke-width', 0.5)
77
+ .attr('stroke-dasharray', '4,4');
78
+
79
+ svg.append('text')
80
+ .attr('x', cx + 4).attr('y', cy - r + 4)
81
+ .text(Math.round(100 / levels * i))
82
+ .attr('fill', '#475569').attr('font-size', '10px');
83
+ }
84
+
85
+ // Axis lines
86
+ data.forEach((d, i) => {
87
+ const angle = angleSlice * i - Math.PI/2;
88
+ const x = cx + Math.cos(angle) * (maxR + 20);
89
+ const y = cy + Math.sin(angle) * (maxR + 20);
90
+
91
+ svg.append('line')
92
+ .attr('x1', cx).attr('y1', cy).attr('x2', cx + Math.cos(angle) * maxR).attr('y2', cy + Math.sin(angle) * maxR)
93
+ .attr('stroke', '#334155').attr('stroke-width', 1);
94
+
95
+ svg.append('text')
96
+ .attr('x', x).attr('y', y)
97
+ .attr('text-anchor', 'middle').attr('dominant-baseline', 'middle')
98
+ .attr('fill', '#94a3b8').attr('font-size', '12px').attr('font-weight', '600')
99
+ .text(d.axis);
100
+ });
101
+
102
+ // Data polygon
103
+ const points = data.map((d, i) => {
104
+ const angle = angleSlice * i - Math.PI/2;
105
+ const r = (d.value / 100) * maxR;
106
+ return [cx + Math.cos(angle) * r, cy + Math.sin(angle) * r];
107
+ });
108
+
109
+ const pointsStr = points.map(p => p.join(',')).join(' ');
110
+
111
+ svg.append('polygon')
112
+ .attr('points', pointsStr)
113
+ .attr('fill', 'rgba(129, 140, 248, 0.15)')
114
+ .attr('stroke', '#818cf8').attr('stroke-width', 2);
115
+
116
+ // Data dots
117
+ points.forEach((p, i) => {
118
+ const color = data[i].value >= 70 ? '#22c55e' : data[i].value >= 50 ? '#f59e0b' : '#ef4444';
119
+ svg.append('circle')
120
+ .attr('cx', p[0]).attr('cy', p[1]).attr('r', 5)
121
+ .attr('fill', color).attr('stroke', '#0f172a').attr('stroke-width', 2);
122
+
123
+ svg.append('text')
124
+ .attr('x', p[0]).attr('y', p[1] - 12)
125
+ .attr('text-anchor', 'middle')
126
+ .attr('fill', color).attr('font-size', '12px').attr('font-weight', '700')
127
+ .text(data[i].value);
128
+ });
129
+ })();
130
+
131
+ // ── D3 Force Dependency Graph ──
132
+ (function() {
133
+ const nodesEl = document.getElementById('graph-nodes');
134
+ const linksEl = document.getElementById('graph-links');
135
+ if (!nodesEl || !linksEl) return;
136
+
137
+ const nodes = JSON.parse(nodesEl.textContent || '[]');
138
+ const links = JSON.parse(linksEl.textContent || '[]');
139
+ if (nodes.length === 0) return;
140
+
141
+ const container = document.getElementById('dep-graph');
142
+ const width = container.clientWidth || 800;
143
+ const height = 500;
144
+ container.style.height = height + 'px';
145
+
146
+ // Dynamic color map — loaded from JSON (supports both layer and module coloring)
147
+ const colorsEl = document.getElementById('graph-colors');
148
+ const layerColors = colorsEl ? JSON.parse(colorsEl.textContent || '{}') : {
149
+ API: '#ec4899', Service: '#3b82f6', Data: '#10b981',
150
+ UI: '#f59e0b', Infrastructure: '#8b5cf6', Other: '#64748b',
151
+ };
152
+
153
+ const svg = d3.select('#dep-graph').append('svg')
154
+ .attr('width', width).attr('height', height)
155
+ .attr('viewBox', [0, 0, width, height]);
156
+
157
+ // Zoom container
158
+ const g = svg.append('g');
159
+
160
+ // Zoom behavior
161
+ const zoom = d3.zoom()
162
+ .scaleExtent([0.2, 5])
163
+ .on('zoom', (event) => { g.attr('transform', event.transform); });
164
+ svg.call(zoom);
165
+
166
+ // Double-click to reset zoom
167
+ svg.on('dblclick.zoom', () => {
168
+ svg.transition().duration(500).call(zoom.transform, d3.zoomIdentity);
169
+ });
170
+
171
+ // Arrow marker
172
+ g.append('defs').append('marker')
173
+ .attr('id', 'arrowhead').attr('viewBox', '-0 -5 10 10')
174
+ .attr('refX', 20).attr('refY', 0).attr('orient', 'auto')
175
+ .attr('markerWidth', 6).attr('markerHeight', 6)
176
+ .append('path').attr('d', 'M 0,-5 L 10,0 L 0,5')
177
+ .attr('fill', '#475569');
178
+
179
+ // Tuned simulation for better spread
180
+ const simulation = d3.forceSimulation(nodes)
181
+ .force('link', d3.forceLink(links).id(d => d.id).distance(80))
182
+ .force('charge', d3.forceManyBody().strength(-250))
183
+ .force('center', d3.forceCenter(width / 2, height / 2))
184
+ .force('x', d3.forceX(width / 2).strength(0.05))
185
+ .force('y', d3.forceY(height / 2).strength(0.05))
186
+ .force('collision', d3.forceCollide().radius(d => Math.max(d.connections * 2 + 16, 20)));
187
+
188
+ const link = g.append('g')
189
+ .selectAll('line').data(links).join('line')
190
+ .attr('stroke', '#334155').attr('stroke-width', 1)
191
+ .attr('stroke-opacity', 0.4).attr('marker-end', 'url(#arrowhead)');
192
+
193
+ const node = g.append('g')
194
+ .selectAll('g').data(nodes).join('g')
195
+ .call(d3.drag()
196
+ .on('start', (e, d) => { if (!e.active) simulation.alphaTarget(0.3).restart(); d.fx = d.x; d.fy = d.y; })
197
+ .on('drag', (e, d) => { d.fx = e.x; d.fy = e.y; })
198
+ .on('end', (e, d) => { if (!e.active) simulation.alphaTarget(0); d.fx = null; d.fy = null; })
199
+ );
200
+
201
+ // Node circles — color by layer
202
+ node.append('circle')
203
+ .attr('r', d => Math.max(d.connections * 2.5 + 5, 6))
204
+ .attr('fill', d => layerColors[d.layer] || '#64748b')
205
+ .attr('stroke', '#0f172a').attr('stroke-width', 1.5)
206
+ .attr('opacity', 0.9);
207
+
208
+ // Node labels — only show for nodes with enough connections
209
+ node.filter(d => d.connections >= 2).append('text')
210
+ .text(d => d.name.replace(/\\.[^.]+$/, ''))
211
+ .attr('x', 0).attr('y', d => -(Math.max(d.connections * 2.5 + 5, 6) + 4))
212
+ .attr('text-anchor', 'middle')
213
+ .attr('fill', '#e2e8f0').attr('font-size', '9px').attr('font-weight', '500');
214
+
215
+ // Tooltip
216
+ node.append('title')
217
+ .text(d => d.id + '\\nConnections: ' + d.connections + '\\nLayer: ' + d.layer);
218
+
219
+ simulation.on('tick', () => {
220
+ link
221
+ .attr('x1', d => d.source.x).attr('y1', d => d.source.y)
222
+ .attr('x2', d => d.target.x).attr('y2', d => d.target.y);
223
+ node.attr('transform', d => 'translate(' + d.x + ',' + d.y + ')');
224
+ });
225
+
226
+ // Expose search and filter functions
227
+ window.filterGraphNodes = function(query) {
228
+ if (!query) {
229
+ node.attr('opacity', 1);
230
+ link.attr('opacity', 0.4);
231
+ return;
232
+ }
233
+ query = query.toLowerCase();
234
+ node.attr('opacity', d => d.id.toLowerCase().includes(query) || d.name.toLowerCase().includes(query) ? 1 : 0.1);
235
+ link.attr('opacity', d => {
236
+ const srcMatch = d.source.id.toLowerCase().includes(query);
237
+ const tgtMatch = d.target.id.toLowerCase().includes(query);
238
+ return (srcMatch || tgtMatch) ? 0.6 : 0.05;
239
+ });
240
+ };
241
+
242
+ window.toggleGraphLayer = function(layer, visible) {
243
+ node.filter(d => d.layer === layer)
244
+ .transition().duration(300)
245
+ .attr('opacity', visible ? 1 : 0.05);
246
+ link.filter(d => d.source.layer === layer || d.target.layer === layer)
247
+ .transition().duration(300)
248
+ .attr('opacity', visible ? 0.4 : 0.02);
249
+ };
250
+ })();
251
+
252
+ // ── Bubble Chart ──
253
+ (function() {
254
+ const dataEl = document.getElementById('bubble-data');
255
+ if (!dataEl) return;
256
+
257
+ const bubbles = JSON.parse(dataEl.textContent || '[]');
258
+ if (bubbles.length === 0) return;
259
+
260
+ const container = document.getElementById('bubble-chart');
261
+ const width = container.clientWidth || 600;
262
+ const height = 300;
263
+
264
+ const svg = d3.select('#bubble-chart').append('svg')
265
+ .attr('width', width).attr('height', height)
266
+ .attr('viewBox', [0, 0, width, height]);
267
+
268
+ const simulation = d3.forceSimulation(bubbles)
269
+ .force('charge', d3.forceManyBody().strength(5))
270
+ .force('center', d3.forceCenter(width / 2, height / 2))
271
+ .force('collision', d3.forceCollide().radius(d => d.radius + 4))
272
+ .stop();
273
+
274
+ for (let i = 0; i < 120; i++) simulation.tick();
275
+
276
+ const g = svg.selectAll('g').data(bubbles).join('g')
277
+ .attr('transform', d => 'translate(' + d.x + ',' + d.y + ')');
278
+
279
+ // Glow effect
280
+ g.append('circle')
281
+ .attr('r', d => d.radius)
282
+ .attr('fill', d => d.color + '20')
283
+ .attr('stroke', d => d.color).attr('stroke-width', 2)
284
+ .attr('opacity', 0)
285
+ .transition().duration(800).delay((d, i) => i * 200)
286
+ .attr('opacity', 1);
287
+
288
+ // Inner circle
289
+ g.append('circle')
290
+ .attr('r', d => d.radius * 0.7)
291
+ .attr('fill', d => d.color + '30')
292
+ .attr('opacity', 0)
293
+ .transition().duration(800).delay((d, i) => i * 200)
294
+ .attr('opacity', 1);
295
+
296
+ // Name
297
+ g.append('text')
298
+ .text(d => d.name)
299
+ .attr('text-anchor', 'middle').attr('dy', '-0.3em')
300
+ .attr('fill', '#e2e8f0').attr('font-size', d => Math.max(d.radius / 4, 10) + 'px')
301
+ .attr('font-weight', '700');
302
+
303
+ // Count badge
304
+ g.append('text')
305
+ .text(d => '×' + d.count)
306
+ .attr('text-anchor', 'middle').attr('dy', '1.2em')
307
+ .attr('fill', d => d.color).attr('font-size', d => Math.max(d.radius / 5, 9) + 'px')
308
+ .attr('font-weight', '600');
309
+
310
+ // Severity label
311
+ g.append('text')
312
+ .text(d => d.severity)
313
+ .attr('text-anchor', 'middle').attr('dy', '2.5em')
314
+ .attr('fill', '#64748b').attr('font-size', '9px').attr('text-transform', 'uppercase');
315
+ })();
316
+ // ── AI Prompt Downloader ──
317
+
318
+ window.toggleAllPrompts = function(checked) {
319
+ const checkboxes = document.querySelectorAll('.prompt-export-cb');
320
+ checkboxes.forEach(cb => cb.checked = checked);
321
+ window.updatePromptSelection();
322
+ };
323
+
324
+ window.updatePromptSelection = function() {
325
+ const checkboxes = document.querySelectorAll('.prompt-export-cb:checked');
326
+ const totalCheckboxes = document.querySelectorAll('.prompt-export-cb');
327
+ const selectAllCb = document.getElementById('select-all-prompts');
328
+ const btn = document.getElementById('download-selected-prompts-btn');
329
+ const badge = document.getElementById('prompt-count-badge');
330
+
331
+ if (selectAllCb && totalCheckboxes.length > 0) {
332
+ selectAllCb.checked = (checkboxes.length === totalCheckboxes.length);
333
+ }
334
+
335
+ if (btn) {
336
+ if (checkboxes.length > 0) {
337
+ btn.style.display = 'flex';
338
+ if (badge) badge.innerText = checkboxes.length;
339
+ } else {
340
+ btn.style.display = 'none';
341
+ }
342
+ }
343
+ };
344
+
345
+ window.downloadSelectedPrompts = function() {
346
+ const checkboxes = document.querySelectorAll('.prompt-export-cb:checked');
347
+ if (checkboxes.length === 0) return;
348
+
349
+ const btn = document.getElementById('download-selected-prompts-btn');
350
+ const originalHtml = btn.innerHTML;
351
+ btn.innerHTML = '✅ Criando...';
352
+
353
+ checkboxes.forEach((cb, i) => {
354
+ setTimeout(() => {
355
+ const box = cb.closest('.ai-prompt-box');
356
+ const codeEl = box.querySelector('code');
357
+ if (!codeEl) return;
358
+ const text = codeEl.innerText;
359
+ const filename = cb.dataset.filename || ('step-prompt-' + i + '.md');
360
+
361
+ const a = document.createElement('a');
362
+ a.setAttribute('href', 'data:text/markdown;charset=utf-8,' + encodeURIComponent(text));
363
+ a.setAttribute('download', filename);
364
+ a.style.display = 'none';
365
+ document.body.appendChild(a);
366
+ a.click();
367
+ document.body.removeChild(a);
368
+ }, i * 400); // 400ms delay per file to prevent browser spam-block
369
+ });
370
+
371
+ setTimeout(() => {
372
+ btn.innerHTML = originalHtml;
373
+ }, checkboxes.length * 400 + 1000);
374
+ };
375
+
376
+ window.downloadAIPrompt = function(element, filename) {
377
+ const container = element.closest('.ai-prompt-box');
378
+ const codeEl = container.querySelector('code');
379
+ if (!codeEl) return;
380
+ const text = codeEl.innerText;
381
+
382
+ const a = document.createElement('a');
383
+ a.setAttribute('href', 'data:text/markdown;charset=utf-8,' + encodeURIComponent(text));
384
+ a.setAttribute('download', filename);
385
+ a.style.display = 'none';
386
+ document.body.appendChild(a);
387
+ a.click();
388
+ document.body.removeChild(a);
389
+
390
+ const originalHtml = element.innerHTML;
391
+ element.innerHTML = '✅ Executing Download...';
392
+ element.style.background = '#059669';
393
+ element.style.color = '#fff';
394
+ setTimeout(() => {
395
+ element.innerHTML = originalHtml;
396
+ element.style.background = '';
397
+ element.style.color = '';
398
+ }, 2000);
399
+ };
400
+ <\/script>`;
401
+ }
402
+
@@ -0,0 +1,267 @@
1
+ import { AgentSuggestion } from '@girardelli/architect-agents/src/core/agent-generator/index.js';
2
+
3
+ // import { escapeHtml } from "../utils_sections.js";
4
+
5
+ export function renderAgentSuggestions(s: AgentSuggestion): string {
6
+ const roleIcon = (name: string): string => {
7
+ if (name.includes('ORCHESTRATOR')) return '\u{1F3AD}';
8
+ if (name.includes('BACKEND') || name.includes('FRONTEND') || name.includes('DATABASE') || name.includes('FLUTTER')) return '\u{1F4BB}';
9
+ if (name.includes('SECURITY')) return '\u{1F6E1}\uFE0F';
10
+ if (name.includes('QA')) return '\u{1F9EA}';
11
+ if (name.includes('TECH-DEBT')) return '\u{1F4CA}';
12
+ return '\u{1F916}';
13
+ };
14
+
15
+ const roleLabel = (name: string): string => {
16
+ if (name.includes('ORCHESTRATOR')) return 'coordination';
17
+ if (name.includes('SECURITY')) return 'protection';
18
+ if (name.includes('QA')) return 'quality';
19
+ if (name.includes('TECH-DEBT')) return 'governance';
20
+ return 'development';
21
+ };
22
+
23
+ const roleColor = (name: string): string => {
24
+ if (name.includes('ORCHESTRATOR')) return '#c084fc';
25
+ if (name.includes('SECURITY')) return '#f87171';
26
+ if (name.includes('QA')) return '#34d399';
27
+ if (name.includes('TECH-DEBT')) return '#fbbf24';
28
+ return '#60a5fa';
29
+ };
30
+
31
+ // Status helpers
32
+ const statusBadge = (status: string): string => {
33
+ const map: Record<string, { icon: string; label: string; color: string }> = {
34
+ 'KEEP': { icon: '✅', label: 'KEEP', color: '#22c55e' },
35
+ 'MODIFY': { icon: '🔵', label: 'MODIFY', color: '#3b82f6' },
36
+ 'CREATE': { icon: '🟡', label: 'NEW', color: '#f59e0b' },
37
+ 'DELETE': { icon: '🔴', label: 'REMOVE', color: '#ef4444' },
38
+ };
39
+ const s = map[status] || map['CREATE'];
40
+ return `<span class="agent-status-badge" style="background:${s.color}20;color:${s.color};border:1px solid ${s.color}40">${s.icon} ${s.label}</span>`;
41
+ };
42
+
43
+ const statusBorder = (status: string): string => {
44
+ const map: Record<string, string> = {
45
+ 'KEEP': '#22c55e', 'MODIFY': '#3b82f6', 'CREATE': '#f59e0b', 'DELETE': '#ef4444',
46
+ };
47
+ return map[status] || '#334155';
48
+ };
49
+
50
+ const agentCards = s.suggestedAgents.map((a: any) =>
51
+ `<label class="agent-toggle-card" data-category="agents" data-name="${a.name}">
52
+ <input type="checkbox" class="agent-check" ${a.status !== 'DELETE' ? 'checked' : ''} data-type="agents" data-item="${a.name}">
53
+ <div class="agent-toggle-inner" style="border-color:${statusBorder(a.status)}">
54
+ <div class="agent-toggle-icon">${roleIcon(a.name)}</div>
55
+ <div class="agent-toggle-info">
56
+ <span class="agent-toggle-name">${a.name}</span>
57
+ <span class="agent-toggle-role" style="color:${roleColor(a.name)}">${roleLabel(a.name)}</span>
58
+ ${a.description ? `<span class="agent-toggle-desc">${a.description}</span>` : ''}
59
+ </div>
60
+ ${statusBadge(a.status)}
61
+ <div class="agent-toggle-check">\u2713</div>
62
+ </div>
63
+ </label>`
64
+ ).join('\n');
65
+
66
+ const miniCard = (item: { name: string; status: string; description?: string }, icon: string, type: string): string =>
67
+ `<label class="agent-toggle-card mini" data-category="${type}">
68
+ <input type="checkbox" class="agent-check" ${item.status !== 'DELETE' ? 'checked' : ''} data-type="${type}" data-item="${item.name}">
69
+ <div class="agent-toggle-inner" style="border-color:${statusBorder(item.status)}">
70
+ <span class="agent-toggle-icon">${icon}</span>
71
+ <div class="agent-toggle-info">
72
+ <span class="agent-toggle-name">${item.name}.md</span>
73
+ ${item.description ? `<span class="agent-toggle-desc">${item.description}</span>` : ''}
74
+ </div>
75
+ ${statusBadge(item.status)}
76
+ <div class="agent-toggle-check">\u2713</div>
77
+ </div>
78
+ </label>`;
79
+
80
+ const ruleCards = s.suggestedRules.map((r: any) => miniCard(r, '\u{1F4CF}', 'rules')).join('\n');
81
+ const guardCards = s.suggestedGuards.map((g: any) => miniCard(g, '\u{1F6E1}\uFE0F', 'guards')).join('\n');
82
+ const workflowCards = s.suggestedWorkflows.map((w: any) => miniCard(w, '\u26A1', 'workflows')).join('\n');
83
+
84
+ const skillCards = s.suggestedSkills.map((sk: any) =>
85
+ `<label class="agent-toggle-card" data-category="skills">
86
+ <input type="checkbox" class="agent-check" checked data-type="skills" data-item="${sk.source}">
87
+ <div class="agent-toggle-inner" style="border-color:${statusBorder(sk.status)}">
88
+ <span class="agent-toggle-icon">\u{1F9E0}</span>
89
+ <div class="agent-toggle-info">
90
+ <span class="agent-toggle-name">${sk.name}</span>
91
+ <span class="agent-toggle-role" style="color:#34d399">${sk.description}</span>
92
+ </div>
93
+ ${statusBadge(sk.status)}
94
+ <div class="agent-toggle-check">\u2713</div>
95
+ </div>
96
+ </label>`
97
+ ).join('\n');
98
+
99
+ const auditSection = s.audit.filter((f: any) => f.type !== 'OK').length > 0 ? `
100
+ <div class="agent-audit-section">
101
+ <h3 class="agent-section-subtitle">\u{1F50D} Audit Findings</h3>
102
+ <div class="agent-audit-grid">
103
+ ${s.audit.filter((f: any) => f.type !== 'OK').map((f: any) => {
104
+ const icon = f.type === 'MISSING' ? '\u274C' : f.type === 'IMPROVEMENT' ? '\u{1F4A1}' : '\u26A0\uFE0F';
105
+ const cls = f.type === 'MISSING' ? 'audit-missing' : 'audit-improvement';
106
+ return `<div class="agent-audit-item ${cls}">
107
+ <span class="audit-icon">${icon}</span>
108
+ <div class="audit-content">
109
+ <span class="audit-desc">${f.description}</span>
110
+ ${f.suggestion ? `<span class="audit-suggestion">\u2192 ${f.suggestion}</span>` : ''}
111
+ </div>
112
+ </div>`;
113
+ }).join('\n')}
114
+ </div>
115
+ </div>` : '';
116
+
117
+ const stackPills = [
118
+ `\u{1F527} ${s.stack.primary}`,
119
+ `\u{1F4E6} ${s.stack.frameworks.length > 0 ? s.stack.frameworks.join(', ') : 'No framework'}`,
120
+ s.hasExistingAgents ? '\u{1F4C1} Existing .agent/' : '\u{1F4C1} New .agent/',
121
+ ...(s.stack.hasBackend ? ['\u{1F519} Backend'] : []),
122
+ ...(s.stack.hasFrontend ? ['\u{1F5A5}\uFE0F Frontend'] : []),
123
+ ...(s.stack.hasMobile ? ['\u{1F4F1} Mobile'] : []),
124
+ ...(s.stack.hasDatabase ? ['\u{1F5C4}\uFE0F Database'] : []),
125
+ ];
126
+
127
+ const totalItems = s.suggestedAgents.length + s.suggestedRules.length + s.suggestedGuards.length + s.suggestedWorkflows.length + s.suggestedSkills.length;
128
+
129
+ // Status summary counts
130
+ const allItems = [...s.suggestedAgents, ...s.suggestedRules, ...s.suggestedGuards, ...s.suggestedWorkflows];
131
+ const keepCount = allItems.filter(i => i.status === 'KEEP').length;
132
+ const modifyCount = allItems.filter(i => i.status === 'MODIFY').length;
133
+ const createCount = allItems.filter(i => i.status === 'CREATE').length;
134
+
135
+ return `
136
+ <h2 class="section-title">\u{1F916} Agent System</h2>
137
+
138
+ <div class="card agent-system-card">
139
+ <div class="agent-stack-banner">
140
+ ${stackPills.map(p => `<div class="stack-pill">${p}</div>`).join('\n ')}
141
+ </div>
142
+
143
+ <div class="agent-status-legend">
144
+ <span class="status-legend-item"><span class="legend-dot" style="background:#22c55e"></span> KEEP (${keepCount})</span>
145
+ <span class="status-legend-item"><span class="legend-dot" style="background:#3b82f6"></span> MODIFY (${modifyCount})</span>
146
+ <span class="status-legend-item"><span class="legend-dot" style="background:#f59e0b"></span> NEW (${createCount})</span>
147
+ </div>
148
+
149
+ <div class="agent-controls">
150
+ <button class="agent-ctrl-btn" onclick="toggleAll(true)">\u2705 Select All</button>
151
+ <button class="agent-ctrl-btn" onclick="toggleAll(false)">\u2B1C Select None</button>
152
+ <span class="agent-count-label"><span id="agentSelectedCount">${totalItems}</span> selected</span>
153
+ </div>
154
+
155
+ <h3 class="agent-section-subtitle">\u{1F916} Agents</h3>
156
+ <div class="agent-toggle-grid">
157
+ ${agentCards}
158
+ </div>
159
+
160
+ <div class="agent-extras-grid">
161
+ <div>
162
+ <h3 class="agent-section-subtitle">\u{1F4CF} Rules</h3>
163
+ <div class="agent-toggle-list">${ruleCards}</div>
164
+ </div>
165
+ <div>
166
+ <h3 class="agent-section-subtitle">\u{1F6E1}\uFE0F Guards</h3>
167
+ <div class="agent-toggle-list">${guardCards}</div>
168
+ </div>
169
+ <div>
170
+ <h3 class="agent-section-subtitle">\u26A1 Workflows</h3>
171
+ <div class="agent-toggle-list">${workflowCards}</div>
172
+ </div>
173
+ </div>
174
+
175
+ <h3 class="agent-section-subtitle">\u{1F9E0} Skills <span style="font-size:0.7rem;color:#94a3b8;font-weight:400">from skills.sh</span></h3>
176
+ <div class="agent-toggle-grid">
177
+ ${skillCards}
178
+ </div>
179
+
180
+ ${auditSection}
181
+
182
+ <div class="agent-command-box">
183
+ <div class="agent-command-header">
184
+ <span>\u{1F4A1} Command to generate selected items:</span>
185
+ <button class="agent-copy-btn" onclick="copyAgentCommand()">
186
+ <span id="copyIcon">\u{1F4CB}</span> Copy
187
+ </button>
188
+ </div>
189
+ <code id="agentCommandOutput" class="agent-command-code">${s.command}</code>
190
+ </div>
191
+ </div>
192
+
193
+ <style>
194
+ .agent-system-card { padding: 1.5rem; }
195
+ .agent-stack-banner { display: flex; gap: 0.5rem; flex-wrap: wrap; margin-bottom: 1.5rem; }
196
+ .stack-pill { background: #1e293b; border: 1px solid #334155; border-radius: 99px; padding: 0.4rem 1rem; font-size: 0.8rem; color: #94a3b8; white-space: nowrap; }
197
+ .agent-status-legend { display: flex; gap: 1.5rem; margin-bottom: 1rem; padding: 0.5rem 0; border-bottom: 1px solid #1e293b; }
198
+ .status-legend-item { display: flex; align-items: center; gap: 0.4rem; font-size: 0.8rem; color: #94a3b8; }
199
+ .agent-status-badge { display: inline-flex; align-items: center; gap: 0.25rem; padding: 0.15rem 0.5rem; border-radius: 99px; font-size: 0.65rem; font-weight: 700; flex-shrink: 0; letter-spacing: 0.03em; }
200
+ .agent-toggle-desc { display: block; font-size: 0.65rem; color: #64748b; margin-top: 0.15rem; line-height: 1.3; }
201
+ .agent-controls { display: flex; align-items: center; gap: 0.75rem; margin-bottom: 1.5rem; }
202
+ .agent-ctrl-btn { background: #1e293b; border: 1px solid #334155; color: #e2e8f0; padding: 0.4rem 1rem; border-radius: 8px; font-size: 0.8rem; cursor: pointer; transition: all 0.2s; }
203
+ .agent-ctrl-btn:hover { background: #334155; }
204
+ .agent-count-label { color: #94a3b8; font-size: 0.85rem; margin-left: auto; }
205
+ #agentSelectedCount { color: #c084fc; font-weight: 700; }
206
+ .agent-section-subtitle { color: #e2e8f0; font-size: 1.05rem; font-weight: 700; margin: 1.25rem 0 0.75rem; }
207
+ .agent-toggle-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 0.75rem; }
208
+ .agent-toggle-card { cursor: pointer; transition: all 0.3s; }
209
+ .agent-toggle-card input { display: none; }
210
+ .agent-toggle-inner { display: flex; align-items: center; gap: 0.75rem; background: #1e293b; border: 2px solid #334155; border-radius: 12px; padding: 0.75rem 1rem; transition: all 0.3s; }
211
+ .agent-toggle-card input:checked + .agent-toggle-inner { background: #1e1b4b; }
212
+ .agent-toggle-icon { font-size: 1.3rem; flex-shrink: 0; }
213
+ .agent-toggle-info { flex: 1; min-width: 0; }
214
+ .agent-toggle-name { display: block; color: #e2e8f0; font-weight: 600; font-size: 0.85rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
215
+ .agent-toggle-role { display: block; font-size: 0.7rem; margin-top: 0.15rem; }
216
+ .agent-toggle-check { color: #334155; font-size: 1rem; flex-shrink: 0; transition: color 0.3s; }
217
+ .agent-toggle-card input:checked + .agent-toggle-inner .agent-toggle-check { color: #818cf8; }
218
+ .agent-toggle-card.mini .agent-toggle-inner { padding: 0.5rem 0.75rem; border-radius: 8px; }
219
+ .agent-extras-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; margin-top: 0.5rem; }
220
+ @media (max-width: 768px) { .agent-extras-grid { grid-template-columns: 1fr; } }
221
+ .agent-toggle-list { display: flex; flex-direction: column; gap: 0.5rem; }
222
+ .agent-audit-section { margin-top: 1.5rem; }
223
+ .agent-audit-grid { display: flex; flex-direction: column; gap: 0.5rem; }
224
+ .agent-audit-item { display: flex; gap: 0.75rem; align-items: flex-start; background: #1e293b; padding: 0.75rem 1rem; border-radius: 8px; }
225
+ .agent-audit-item.audit-missing { border-left: 3px solid #ef4444; }
226
+ .agent-audit-item.audit-improvement { border-left: 3px solid #fbbf24; }
227
+ .audit-icon { font-size: 1rem; flex-shrink: 0; margin-top: 2px; }
228
+ .audit-content { display: flex; flex-direction: column; gap: 0.25rem; }
229
+ .audit-desc { color: #e2e8f0; font-size: 0.85rem; }
230
+ .audit-suggestion { color: #94a3b8; font-size: 0.8rem; font-style: italic; }
231
+ .agent-command-box { margin-top: 1.5rem; background: #0f172a; border-radius: 12px; border: 1px solid #334155; overflow: hidden; }
232
+ .agent-command-header { display: flex; justify-content: space-between; align-items: center; padding: 0.75rem 1rem; background: #1e293b; font-size: 0.8rem; color: #94a3b8; }
233
+ .agent-copy-btn { background: #c084fc; color: #0f172a; border: none; border-radius: 6px; padding: 0.4rem 0.8rem; cursor: pointer; font-size: 0.75rem; font-weight: 600; transition: all 0.2s; }
234
+ .agent-copy-btn:hover { background: #a855f7; transform: scale(1.05); }
235
+ .agent-command-code { display: block; padding: 1rem; color: #c084fc; font-size: 0.85rem; word-break: break-all; font-family: 'Fira Code', monospace; }
236
+ </style>
237
+
238
+ <script>
239
+ (function() {
240
+ var basePath = ${JSON.stringify(s.command.replace('architect agents ', ''))};
241
+ var totalItems = ${totalItems};
242
+ function updateCommand() {
243
+ var checks = document.querySelectorAll('.agent-check');
244
+ var selected = { agents: [], rules: [], guards: [], workflows: [], skills: [] };
245
+ var count = 0;
246
+ checks.forEach(function(cb) { if (cb.checked) { selected[cb.dataset.type].push(cb.dataset.item); count++; } });
247
+ document.getElementById('agentSelectedCount').textContent = count;
248
+ var cmd;
249
+ if (count === totalItems) { cmd = 'architect agents ' + basePath; }
250
+ else if (count === 0) { cmd = '# No items selected'; }
251
+ else {
252
+ var parts = ['architect agents ' + basePath];
253
+ if (selected.agents.length > 0) parts.push('--agents ' + selected.agents.join(','));
254
+ if (selected.rules.length > 0) parts.push('--rules ' + selected.rules.join(','));
255
+ if (selected.guards.length > 0) parts.push('--guards ' + selected.guards.join(','));
256
+ if (selected.workflows.length > 0) parts.push('--workflows ' + selected.workflows.join(','));
257
+ if (selected.skills.length > 0) parts.push('&& ' + selected.skills.map(function(sk){ return 'npx skills add ' + sk; }).join(' && '));
258
+ cmd = parts.join(' ');
259
+ }
260
+ document.getElementById('agentCommandOutput').textContent = cmd;
261
+ }
262
+ document.querySelectorAll('.agent-check').forEach(function(cb) { cb.addEventListener('change', updateCommand); });
263
+ window.toggleAll = function(state) { document.querySelectorAll('.agent-check').forEach(function(cb) { cb.checked = state; }); updateCommand(); };
264
+ window.copyAgentCommand = function() { var cmd = document.getElementById('agentCommandOutput').textContent; navigator.clipboard.writeText(cmd).then(function() { var btn = document.getElementById('copyIcon'); btn.textContent = '\u2705'; setTimeout(function() { btn.textContent = '\ud83d\udccb'; }, 2000); }); };
265
+ })();
266
+ <\/script>`;
267
+ }