@mocoto/mahoraga 0.14.1 → 0.14.3

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 (306) hide show
  1. package/README.md +0 -34
  2. package/dist/analysts/architects/analyst-structure.js +20 -20
  3. package/dist/analysts/architects/archetypes-custom.js +16 -19
  4. package/dist/analysts/architects/detector-archetypes.js +43 -36
  5. package/dist/analysts/architects/orchestrator-archetypes.js +3 -3
  6. package/dist/analysts/architects/signals-project-advanced.js +26 -28
  7. package/dist/analysts/architects/signals-project.js +2 -2
  8. package/dist/analysts/architects/strategist-structure.js +47 -66
  9. package/dist/analysts/azure-pipelines/analysts/analyst-azure.js +41 -35
  10. package/dist/analysts/azure-pipelines/corrections/correction-azure.js +22 -19
  11. package/dist/analysts/azure-pipelines/detectors/detector-azure-performance.js +21 -18
  12. package/dist/analysts/azure-pipelines/detectors/detector-azure-security.js +25 -20
  13. package/dist/analysts/azure-pipelines/detectors/detector-azure-structure.js +39 -40
  14. package/dist/analysts/azure-pipelines/scorers/scorer-azure.js +10 -7
  15. package/dist/analysts/circleci/analysts/analyst-circleci.js +33 -27
  16. package/dist/analysts/circleci/corrections/correction-circleci.js +22 -20
  17. package/dist/analysts/circleci/detectors/detector-circleci-performance.js +23 -19
  18. package/dist/analysts/circleci/detectors/detector-circleci-security.js +78 -82
  19. package/dist/analysts/circleci/detectors/detector-circleci-structure.js +22 -22
  20. package/dist/analysts/converters/convert-registry.js +1 -1
  21. package/dist/analysts/converters/engines/converter-gha-to-gitlab.js +17 -15
  22. package/dist/analysts/converters/index.js +1 -1
  23. package/dist/analysts/corrections/analyst-quick-fixes.js +25 -28
  24. package/dist/analysts/corrections/analyst-scoring.js +24 -21
  25. package/dist/analysts/corrections/auto-fix-engine.js +1 -1
  26. package/dist/analysts/corrections/corrector-structure.js +43 -42
  27. package/dist/analysts/corrections/fix-alias-imports.js +10 -6
  28. package/dist/analysts/corrections/fix-md-fences.js +23 -23
  29. package/dist/analysts/corrections/map-reversion.js +56 -53
  30. package/dist/analysts/corrections/pruning.js +19 -16
  31. package/dist/analysts/corrections/quick-fixes/fix-any-to-proper-type.js +57 -61
  32. package/dist/analysts/corrections/quick-fixes/fix-unknown-to-specific-type.js +30 -30
  33. package/dist/analysts/corrections/reorganize-barrels.js +13 -13
  34. package/dist/analysts/corrections/rewrite-testes-aliases.js +23 -22
  35. package/dist/analysts/corrections/scoring-shared.js +19 -18
  36. package/dist/analysts/corrections/type-safety/context-analyzer.js +15 -10
  37. package/dist/analysts/corrections/type-safety/type-analyzer.js +3 -3
  38. package/dist/analysts/corrections/type-safety/type-validator.js +4 -3
  39. package/dist/analysts/corrections/type-safety/usage-analyzer.js +39 -42
  40. package/dist/analysts/css/analysts/analyst-css.js +42 -42
  41. package/dist/analysts/css/corrections/correction-css.js +19 -11
  42. package/dist/analysts/css/detectors/detector-css-best-practices.js +129 -118
  43. package/dist/analysts/css/scorers/scorer-css.js +23 -18
  44. package/dist/analysts/css-in-js/analysts/analyst-css-in-js.js +24 -17
  45. package/dist/analysts/css-in-js/corrections/correction-css-in-js.js +31 -16
  46. package/dist/analysts/css-in-js/detectors/detector-css-in-js-best-practices.js +28 -30
  47. package/dist/analysts/css-in-js/scorers/scorer-css-in-js.js +79 -54
  48. package/dist/analysts/css-in-js/shared.js +7 -0
  49. package/dist/analysts/detectors/detector-architecture.js +91 -85
  50. package/dist/analysts/detectors/detector-bugs-ml.js +29 -27
  51. package/dist/analysts/detectors/detector-code-fragile.js +41 -36
  52. package/dist/analysts/detectors/detector-dependencies.js +5 -5
  53. package/dist/analysts/detectors/detector-duplications.js +26 -26
  54. package/dist/analysts/detectors/detector-monorepo.js +51 -45
  55. package/dist/analysts/detectors/detector-performance.js +24 -17
  56. package/dist/analysts/detectors/detector-recommendation-architecture.js +40 -36
  57. package/dist/analysts/detectors/detector-security.js +43 -42
  58. package/dist/analysts/detectors/detector-structure.js +31 -28
  59. package/dist/analysts/github-actions/analysts/analyst-github-actions.js +5 -8
  60. package/dist/analysts/github-actions/detectors/detector-workflow-accessibility.js +1 -9
  61. package/dist/analysts/github-actions/detectors/detector-workflow-structure.js +1 -4
  62. package/dist/analysts/github-actions/detectors/detector-workflow-trigger-unsafe.js +6 -5
  63. package/dist/analysts/gitlab-ci/analysts/analyst-gitlab-ci.js +2 -2
  64. package/dist/analysts/gitlab-ci/detectors/detector-gitlab-ci-structure.js +0 -3
  65. package/dist/analysts/go/analysts/analyst-best-practices.js +2 -2
  66. package/dist/analysts/go/analysts/analyst-concurrency.js +1 -1
  67. package/dist/analysts/go/analysts/analyst-security.js +1 -1
  68. package/dist/analysts/go/detectors/detector-conventions.js +1 -1
  69. package/dist/analysts/html/analysts/analyst-html.js +10 -12
  70. package/dist/analysts/html/detectors/detector-html.js +3 -3
  71. package/dist/analysts/js-ts/analysts/analyst-commands-cli.js +22 -22
  72. package/dist/analysts/js-ts/analysts/analyst-functions-long.js +5 -5
  73. package/dist/analysts/js-ts/analysts/analyst-patterns-usage.js +6 -2
  74. package/dist/analysts/js-ts/detectors/detector-anti-patterns-async.js +84 -9
  75. package/dist/analysts/js-ts/detectors/detector-constructions-syntactic.js +33 -10
  76. package/dist/analysts/js-ts/detectors/detector-context-smart.js +6 -6
  77. package/dist/analysts/js-ts/detectors/detector-leaks-memory.js +1 -1
  78. package/dist/analysts/js-ts/detectors/detector-types-unsafe.js +33 -2
  79. package/dist/analysts/php/analysts/analyst-php.js +3 -3
  80. package/dist/analysts/php/detectors/detector-php-best-practices.js +5 -5
  81. package/dist/analysts/php/detectors/detector-php-security.js +5 -5
  82. package/dist/analysts/php/scorers/scorer-php.js +2 -2
  83. package/dist/analysts/plugins/detector-documentation.js +6 -6
  84. package/dist/analysts/plugins/detector-markdown.js +7 -7
  85. package/dist/analysts/python/analysts/analyst-python.js +2 -5
  86. package/dist/analysts/react/analysts/analyst-react-hooks.js +66 -9
  87. package/dist/analysts/react/analysts/analyst-react.js +46 -2
  88. package/dist/analysts/react/corrections/correction-react.js +41 -1
  89. package/dist/analysts/react/detectors/detector-react-best-practices.js +5 -5
  90. package/dist/analysts/react/scorers/scorer-react.js +36 -1
  91. package/dist/analysts/registry/autodiscovery.js +2 -2
  92. package/dist/analysts/rust/analysts/analyst-best-practices.js +42 -3
  93. package/dist/analysts/rust/analysts/analyst-memory.js +2 -2
  94. package/dist/analysts/rust/analysts/analyst-rust.js +52 -5
  95. package/dist/analysts/rust/analysts/analyst-security.js +29 -1
  96. package/dist/analysts/scorers/scorer.js +5 -5
  97. package/dist/analysts/shell/analysts/analyst-shell.js +81 -5
  98. package/dist/analysts/shell/corrections/correction-shell.js +34 -1
  99. package/dist/analysts/shell/detectors/detector-shell-security.js +88 -0
  100. package/dist/analysts/shell/scorers/scorer-shell.js +58 -1
  101. package/dist/analysts/strategists/operator-structure.js +5 -7
  102. package/dist/analysts/strategists/suggestions-contextuais.js +5 -2
  103. package/dist/analysts/svg/analysts/analyst-svg.js +1 -0
  104. package/dist/analysts/tailwind/analysts/analyst-tailwind.js +79 -55
  105. package/dist/analysts/tailwind/corrections/correction-tailwind.js +108 -9
  106. package/dist/analysts/tailwind/detectors/detector-tailwind-best-practices.js +122 -7
  107. package/dist/analysts/tailwind/scorers/scorer-tailwind.js +62 -11
  108. package/dist/analysts/xml/analysts/analyst-xml.js +2 -2
  109. package/dist/app/index.js +1 -0
  110. package/dist/bin/cli-bootstrap.js +6 -4
  111. package/dist/bin/index.js +6 -4
  112. package/dist/caretakers/scoring.js +1 -0
  113. package/dist/cli/commands/command-analysts.js +4 -3
  114. package/dist/cli/commands/command-azure.js +1 -1
  115. package/dist/cli/commands/command-circleci.js +1 -1
  116. package/dist/cli/commands/command-compliance.js +1 -1
  117. package/dist/cli/commands/command-diagnose.js +10 -13
  118. package/dist/cli/commands/command-fix-types.js +9 -32
  119. package/dist/cli/commands/command-formatters.js +2 -2
  120. package/dist/cli/commands/command-github-actions.js +1 -1
  121. package/dist/cli/commands/command-gitlab-ci.js +1 -1
  122. package/dist/cli/commands/command-guardian.js +1 -1
  123. package/dist/cli/commands/command-imports.js +6 -6
  124. package/dist/cli/commands/command-jenkins.js +1 -1
  125. package/dist/cli/commands/command-licenses.js +1 -1
  126. package/dist/cli/commands/command-marketplace.js +7 -7
  127. package/dist/cli/commands/command-names.js +3 -8
  128. package/dist/cli/commands/command-perf.js +7 -9
  129. package/dist/cli/commands/command-plugins.js +4 -4
  130. package/dist/cli/diagnostic/auto-fix.js +2 -2
  131. package/dist/cli/diagnostic/exporters/json-exporter.js +1 -1
  132. package/dist/cli/diagnostic/exporters/sharded-exporter.js +0 -3
  133. package/dist/cli/diagnostic/exporters/svg-optimization-exporter.js +1 -1
  134. package/dist/cli/diagnostic/filters.js +9 -9
  135. package/dist/cli/diagnostic/handlers/archetype-handler.js +3 -6
  136. package/dist/cli/diagnostic/handlers/auto-fix-handler.js +4 -4
  137. package/dist/cli/diagnostic/handlers/guardian-handler.js +1 -1
  138. package/dist/cli/diagnostic/processing-diagnostic.js +31 -35
  139. package/dist/cli/diagnostic/processing-helpers.js +2 -2
  140. package/dist/cli/handlers/fix-types-exporter.js +1 -4
  141. package/dist/cli/helpers/display-frame.js +5 -5
  142. package/dist/core/config/auto/auto-fix-config.js +0 -6
  143. package/dist/core/config/chalk-safe.js +6 -6
  144. package/dist/core/config/config.js +11 -13
  145. package/dist/core/config/conventions.js +1 -1
  146. package/dist/core/config/security.js +2 -2
  147. package/dist/core/execution/analysis-cache.js +5 -8
  148. package/dist/core/execution/ast-cache.js +1 -3
  149. package/dist/core/execution/executor.js +8 -21
  150. package/dist/core/execution/inquisitor.js +24 -21
  151. package/dist/core/execution/results.js +1 -0
  152. package/dist/core/execution/scanner.js +4 -4
  153. package/dist/core/messages/en/analysts/analyst-github-actions-messages.js +1 -1
  154. package/dist/core/messages/en/analysts/analyst-patterns-usage-messages.js +1 -0
  155. package/dist/core/messages/en/analysts/analyst-shell-messages.js +15 -0
  156. package/dist/core/messages/en/analysts/detector-constructions-syntactic-messages.js +6 -0
  157. package/dist/core/messages/en/analysts/detector-js-ts-messages.js +27 -0
  158. package/dist/core/messages/en/analysts/detector-react-messages.js +8 -0
  159. package/dist/core/messages/en/analysts/detector-shell-messages.js +17 -0
  160. package/dist/core/messages/en/analysts/detector-tailwind-messages.js +3 -3
  161. package/dist/core/messages/en/analysts/report-circleci-messages.js +7 -7
  162. package/dist/core/messages/en/caretakers/caretaker-messages.js +1 -7
  163. package/dist/core/messages/en/core/plugin-messages.js +31 -3
  164. package/dist/core/messages/en/log/log.js +4 -4
  165. package/dist/core/messages/en/ui/filter-config.js +1 -5
  166. package/dist/core/messages/i18n-system.js +3 -3
  167. package/dist/core/messages/index.js +3 -3
  168. package/dist/core/messages/ja/analysts/analyst-github-actions-messages.js +1 -1
  169. package/dist/core/messages/ja/analysts/analyst-patterns-usage-messages.js +1 -0
  170. package/dist/core/messages/ja/analysts/analyst-shell-messages.js +15 -0
  171. package/dist/core/messages/ja/analysts/detector-constructions-syntactic-messages.js +6 -0
  172. package/dist/core/messages/ja/analysts/detector-js-ts-messages.js +27 -0
  173. package/dist/core/messages/ja/analysts/detector-react-messages.js +8 -0
  174. package/dist/core/messages/ja/analysts/detector-shell-messages.js +17 -0
  175. package/dist/core/messages/ja/analysts/detector-tailwind-messages.js +3 -3
  176. package/dist/core/messages/ja/analysts/report-circleci-messages.js +7 -7
  177. package/dist/core/messages/ja/caretakers/caretaker-messages.js +1 -7
  178. package/dist/core/messages/ja/core/plugin-messages.js +31 -3
  179. package/dist/core/messages/ja/log/log.js +4 -4
  180. package/dist/core/messages/ja/ui/filter-config.js +1 -1
  181. package/dist/core/messages/pt/analysts/analyst-github-actions-messages.js +1 -1
  182. package/dist/core/messages/pt/analysts/analyst-patterns-usage-messages.js +1 -0
  183. package/dist/core/messages/pt/analysts/analyst-shell-messages.js +15 -0
  184. package/dist/core/messages/pt/analysts/detector-constructions-syntactic-messages.js +6 -0
  185. package/dist/core/messages/pt/analysts/detector-js-ts-messages.js +27 -0
  186. package/dist/core/messages/pt/analysts/detector-react-messages.js +8 -0
  187. package/dist/core/messages/pt/analysts/detector-shell-messages.js +17 -0
  188. package/dist/core/messages/pt/analysts/detector-tailwind-messages.js +3 -3
  189. package/dist/core/messages/pt/analysts/report-circleci-messages.js +7 -7
  190. package/dist/core/messages/pt/caretakers/caretaker-messages.js +1 -7
  191. package/dist/core/messages/pt/core/plugin-messages.js +31 -3
  192. package/dist/core/messages/pt/log/log-engine.js +6 -6
  193. package/dist/core/messages/pt/log/log.js +3 -3
  194. package/dist/core/messages/pt/ui/filter-config.js +1 -1
  195. package/dist/core/messages/shared/icons.js +3 -3
  196. package/dist/core/messages/zh/analysts/analyst-github-actions-messages.js +1 -1
  197. package/dist/core/messages/zh/analysts/analyst-patterns-usage-messages.js +1 -0
  198. package/dist/core/messages/zh/analysts/analyst-shell-messages.js +15 -0
  199. package/dist/core/messages/zh/analysts/detector-constructions-syntactic-messages.js +6 -0
  200. package/dist/core/messages/zh/analysts/detector-js-ts-messages.js +27 -0
  201. package/dist/core/messages/zh/analysts/detector-react-messages.js +8 -0
  202. package/dist/core/messages/zh/analysts/detector-shell-messages.js +17 -0
  203. package/dist/core/messages/zh/analysts/detector-tailwind-messages.js +3 -3
  204. package/dist/core/messages/zh/analysts/report-circleci-messages.js +7 -7
  205. package/dist/core/messages/zh/caretakers/caretaker-messages.js +1 -7
  206. package/dist/core/messages/zh/core/plugin-messages.js +31 -3
  207. package/dist/core/messages/zh/log/log.js +3 -3
  208. package/dist/core/messages/zh/ui/filter-config.js +1 -5
  209. package/dist/core/parsing/filters.js +3 -3
  210. package/dist/core/parsing/langs/json.js +1 -1
  211. package/dist/core/parsing/langs/python.js +1 -1
  212. package/dist/core/parsing/langs/typescript.js +1 -1
  213. package/dist/core/parsing/parser.js +3 -4
  214. package/dist/core/parsing/utils.js +1 -0
  215. package/dist/core/registry/file-registry.js +3 -2
  216. package/dist/core/registry/paths.js +3 -3
  217. package/dist/core/reporting/default-reporter.js +2 -2
  218. package/dist/core/schema/version.js +6 -6
  219. package/dist/core/workers/worker-executor.js +3 -3
  220. package/dist/core/workers/worker-pool.js +0 -0
  221. package/dist/guardian/baseline.js +1 -1
  222. package/dist/guardian/gpg.js +3 -1
  223. package/dist/guardian/integrity.js +2 -7
  224. package/dist/guardian/records.js +7 -1
  225. package/dist/guardian/result.js +1 -1
  226. package/dist/guardian/sentinel.js +7 -1
  227. package/dist/guardian/watcher-hidden.js +6 -1
  228. package/dist/licenses/fs-utils.js +5 -1
  229. package/dist/licenses/generate-notices.js +1 -1
  230. package/dist/licenses/index.js +1 -0
  231. package/dist/licenses/normalizer.js +10 -9
  232. package/dist/node.loader.js +224 -4
  233. package/dist/reports/analise-async-patterns.js +1 -1
  234. package/dist/reports/filter-smart.js +2 -5
  235. package/dist/reports/generator-report.js +7 -7
  236. package/dist/reports/report-archetypes.js +10 -10
  237. package/dist/reports/report-caretaker-health.js +2 -1
  238. package/dist/reports/report-patterns-usage.js +1 -1
  239. package/dist/sdk/analyzer.js +1 -1
  240. package/dist/shared/data-processing/fragment-report.js +11 -11
  241. package/dist/shared/data-processing/json.js +1 -1
  242. package/dist/shared/data-processing/occurrences.js +3 -2
  243. package/dist/shared/formatters/code-min-formatter.js +1 -1
  244. package/dist/shared/formatters/engines/prettier.js +1 -1
  245. package/dist/shared/formatters/engines/stylelint.js +43 -40
  246. package/dist/shared/formatters/formatter.js +8 -8
  247. package/dist/shared/formatters/formatters/code.js +3 -3
  248. package/dist/shared/formatters/formatters/css.js +2 -10
  249. package/dist/shared/formatters/formatters/dotfiles.js +1 -1
  250. package/dist/shared/formatters/formatters/html.js +1 -5
  251. package/dist/shared/formatters/formatters/json.js +0 -3
  252. package/dist/shared/formatters/formatters/markdown.js +19 -24
  253. package/dist/shared/formatters/formatters/properties.js +2 -2
  254. package/dist/shared/formatters/formatters/shell.js +1 -4
  255. package/dist/shared/formatters/formatters/sql.js +0 -3
  256. package/dist/shared/formatters/formatters/xml.js +5 -7
  257. package/dist/shared/formatters/formatters/yaml.js +2 -7
  258. package/dist/shared/formatters/index.js +1 -1
  259. package/dist/shared/helpers/framework-detector.js +6 -2
  260. package/dist/shared/helpers/json.js +1 -1
  261. package/dist/shared/helpers/magic-constants-whitelist.js +1 -1
  262. package/dist/shared/helpers/masking.js +17 -17
  263. package/dist/shared/helpers/reader-report.js +0 -12
  264. package/dist/shared/helpers/structural-hash.js +3 -2
  265. package/dist/shared/helpers/structure.js +1 -1
  266. package/dist/shared/marketplace/registry.js +1 -1
  267. package/dist/shared/marketplace/remote.js +4 -4
  268. package/dist/shared/persistence/persistence.js +13 -6
  269. package/dist/shared/plugins/core-plugin.js +5 -1
  270. package/dist/shared/plugins/registry.js +3 -2
  271. package/dist/types/analysts/tailwind-correction.js +2 -0
  272. package/dist/types/caretakers/imports-barrel.js +1 -0
  273. package/dist/types/caretakers/index.js +4 -0
  274. package/dist/types/caretakers/map-reversion.js +1 -0
  275. package/dist/types/caretakers/pruning.js +1 -0
  276. package/dist/types/caretakers/scoring.js +1 -0
  277. package/dist/types/common/analysts.js +1 -1
  278. package/dist/types/core/config/filters.js +1 -0
  279. package/dist/types/core/config/index.js +2 -0
  280. package/dist/types/core/execution/ambiente.js +1 -0
  281. package/dist/types/core/execution/linguagens.js +1 -0
  282. package/dist/types/core/execution/parse-errors.js +1 -0
  283. package/dist/types/core/execution/results.js +1 -0
  284. package/dist/types/core/execution/structure-json.js +1 -0
  285. package/dist/types/core/index.js +1 -0
  286. package/dist/types/core/messages/index.js +1 -0
  287. package/dist/types/core/messages/log.js +1 -0
  288. package/dist/types/core/parsing/babel-narrow.js +1 -0
  289. package/dist/types/core/parsing/index.js +1 -0
  290. package/dist/types/core/runtime.js +1 -0
  291. package/dist/types/guardian/index.js +2 -0
  292. package/dist/types/guardian/integrity.js +7 -0
  293. package/dist/types/guardian/snapshot.js +1 -0
  294. package/dist/types/index.js +4 -4
  295. package/dist/types/licenses/index.js +2 -0
  296. package/dist/types/processing/display.js +16 -13
  297. package/dist/types/processing/filters.js +8 -11
  298. package/dist/types/reports/compliance.js +1 -0
  299. package/dist/types/reports/streaming.js +1 -0
  300. package/dist/types/scripts/index.js +1 -0
  301. package/dist/types/scripts/migrar-aliases.js +1 -0
  302. package/dist/types/sdk/index.js +1 -0
  303. package/dist/types/shared/index.js +2 -0
  304. package/dist/types/vulnerabilities/index.js +2 -0
  305. package/dist/vulnerabilities/scanner.js +3 -2
  306. package/package.json +14 -20
@@ -45,7 +45,7 @@ const visitorFragil = {
45
45
  const fragilidades = visitorState.resultados.get('codigo-fragil') ?? [];
46
46
  let depth = 0;
47
47
  let current = path;
48
- while (current) {
48
+ while (current.node.type !== 'Program') {
49
49
  if (current.isIfStatement()) {
50
50
  depth++;
51
51
  }
@@ -65,9 +65,9 @@ const visitorFragil = {
65
65
  FunctionDeclaration(path, state) {
66
66
  const visitorState = state;
67
67
  const fragilidades = visitorState.resultados.get('codigo-fragil') ?? [];
68
- const maxLinhas = config.ANALISE_LIMITES.CODIGO_FRAGIL.MAX_LINHAS_FUNCAO ?? LIMITES.LINHAS_FUNCAO;
68
+ const maxLinhas = config.ANALISE_LIMITES.CODIGO_FRAGIL.MAX_LINHAS_FUNCAO;
69
69
  const node = path.node;
70
- if (node.body.type === 'BlockStatement') {
70
+ {
71
71
  const inicio = node.loc?.start.line ?? 0;
72
72
  const fim = node.loc?.end.line ?? 0;
73
73
  const numLinhas = fim - inicio;
@@ -90,7 +90,7 @@ const visitorFragil = {
90
90
  if (isInVariableDeclarator(path) || isInArrayIndex(path)) {
91
91
  return;
92
92
  }
93
- frameworksDetectados ??= detectarFrameworks(process.cwd()).map(arquivo => arquivo.name);
93
+ frameworksDetectados = detectarFrameworks(process.cwd()).map(arquivo => arquivo.name);
94
94
  if (isWhitelistedConstant(value, frameworksDetectados)) {
95
95
  return;
96
96
  }
@@ -104,14 +104,43 @@ const visitorFragil = {
104
104
  visitorState.resultados.set('codigo-fragil', fragilidades);
105
105
  }
106
106
  };
107
+ function converterFragilidadesParaOcorrencias(fragilidades, relPath) {
108
+ const ocorrencias = [];
109
+ const porSeveridade = agruparPor(fragilidades, arquivo => arquivo.severidade ?? 'media');
110
+ for (const [severidade, items] of Object.entries(porSeveridade)) {
111
+ if (items.length === 0) {
112
+ continue;
113
+ }
114
+ const nivel = severidade === 'critica' || severidade === 'alta' ? 'erro' : severidade === 'media' ? 'aviso' : 'info';
115
+ const tipos = {};
116
+ for (const it of items) {
117
+ tipos[it.tipo] = (tipos[it.tipo] || 0) + 1;
118
+ }
119
+ const resumo = items.slice(0, 3).map(caminho => caminho.tipo).join(', ');
120
+ const amostra = items.slice(0, 5).map(it => `${it.tipo} (L${it.linha})`);
121
+ ocorrencias.push(criarOcorrencia({
122
+ tipo: 'codigo-fragil',
123
+ nivel,
124
+ mensagem: messages.DetectorCodigoFragilMensagens.fragilidadesResumo(severidade, resumo, {
125
+ severidade,
126
+ total: items.length,
127
+ tipos,
128
+ amostra
129
+ }),
130
+ relPath,
131
+ linha: items[0].linha
132
+ }));
133
+ }
134
+ return ocorrencias;
135
+ }
107
136
  export const analistaCodigoFragil = {
108
137
  nome: 'codigo-fragil',
109
138
  categoria: 'qualidade',
110
139
  descricao: 'Detecta padrões de código que podem levar a problemas futuros',
111
140
  limites: {
112
- maxLinhasFuncao: config.ANALISE_LIMITES.CODIGO_FRAGIL.MAX_LINHAS_FUNCAO ?? LIMITES.LINHAS_FUNCAO,
113
- maxParametros: config.ANALISE_LIMITES.CODIGO_FRAGIL.MAX_PARAMETROS ?? LIMITES.PARAMETROS_FUNCAO,
114
- maxNestedCallbacks: config.ANALISE_LIMITES.CODIGO_FRAGIL.MAX_NESTED_CALLBACKS ?? LIMITES.CALLBACKS_ANINHADOS
141
+ maxLinhasFuncao: config.ANALISE_LIMITES.CODIGO_FRAGIL.MAX_LINHAS_FUNCAO,
142
+ maxParametros: config.ANALISE_LIMITES.CODIGO_FRAGIL.MAX_PARAMETROS,
143
+ maxNestedCallbacks: config.ANALISE_LIMITES.CODIGO_FRAGIL.MAX_NESTED_CALLBACKS
115
144
  },
116
145
  visitor: visitorFragil,
117
146
  test: (relPath) => {
@@ -156,11 +185,12 @@ export const analistaCodigoFragil = {
156
185
  });
157
186
  }
158
187
  // Processamento AST: Otimizado (preColetado) ou Fallback
159
- if (ast.preColetado) {
160
- fragilidades.push(...ast.preColetado);
188
+ const astMeta = ast;
189
+ if (astMeta?.preColetado) {
190
+ fragilidades.push(...astMeta.preColetado);
161
191
  }
162
192
  else {
163
- const nodeToTraverse = ast.node ?? ast;
193
+ const nodeToTraverse = astMeta?.node ?? ast;
164
194
  const stateMock = {
165
195
  resultados: new Map([['codigo-fragil', []]])
166
196
  };
@@ -169,32 +199,7 @@ export const analistaCodigoFragil = {
169
199
  }
170
200
  // Detecções de texto complementares (Heurísticas)
171
201
  detectarProblemasAvancados(src, fragilidades);
172
- // Converter para ocorrências Mahoraga
173
- const ocorrencias = [];
174
- const porSeveridade = agruparPor(fragilidades, arquivo => arquivo.severidade ?? 'media');
175
- for (const [severidade, items] of Object.entries(porSeveridade)) {
176
- if (items.length > 0) {
177
- const nivel = severidade === 'critica' || severidade === 'alta' ? 'erro' : severidade === 'media' ? 'aviso' : 'info';
178
- const resumo = items.slice(0, 3).map(caminho => caminho.tipo).join(', ');
179
- const tipos = {};
180
- for (const it of items) {
181
- tipos[it.tipo] = (tipos[it.tipo] || 0) + 1;
182
- }
183
- const amostra = items.slice(0, 5).map(it => `${it.tipo} (L${it.linha})`);
184
- ocorrencias.push(criarOcorrencia({
185
- tipo: 'codigo-fragil',
186
- nivel,
187
- mensagem: messages.DetectorCodigoFragilMensagens.fragilidadesResumo(severidade, resumo, {
188
- severidade,
189
- total: items.length,
190
- tipos,
191
- amostra
192
- }),
193
- relPath,
194
- linha: items[0].linha
195
- }));
196
- }
197
- }
202
+ const ocorrencias = converterFragilidadesParaOcorrencias(fragilidades, relPath);
198
203
  return filtrarOcorrenciasSuprimidas(ocorrencias, 'codigo-fragil', src);
199
204
  }
200
205
  };
@@ -14,7 +14,7 @@ function ehImportSomenteTipo(node) {
14
14
  if (node.importKind === 'type') {
15
15
  return true;
16
16
  }
17
- const specifiers = node.specifiers || [];
17
+ const specifiers = node.specifiers;
18
18
  if (specifiers.length === 0) {
19
19
  return false;
20
20
  }
@@ -185,12 +185,12 @@ function processarImportDeclaration(caminho, state) {
185
185
  }
186
186
  const val = caminho.node.source.value;
187
187
  if (somenteTipo) {
188
- const specifiers = caminho.node.specifiers || [];
188
+ const specifiers = caminho.node.specifiers;
189
189
  for (const s of specifiers) {
190
190
  if (s.type === 'ImportDefaultSpecifier' || s.type === 'ImportSpecifier') {
191
191
  state.importsDeclarados.add(s.local.name);
192
192
  }
193
- else if (s.type === 'ImportNamespaceSpecifier') {
193
+ else {
194
194
  state.importsDeclarados.add(s.local.name);
195
195
  }
196
196
  }
@@ -240,12 +240,12 @@ function processarImportDeclaration(caminho, state) {
240
240
  });
241
241
  }
242
242
  }
243
- const specifiers = caminho.node.specifiers || [];
243
+ const specifiers = caminho.node.specifiers;
244
244
  for (const s of specifiers) {
245
245
  if (s.type === 'ImportDefaultSpecifier' || s.type === 'ImportSpecifier') {
246
246
  state.importsDeclarados.add(s.local.name);
247
247
  }
248
- else if (s.type === 'ImportNamespaceSpecifier') {
248
+ else {
249
249
  state.importsDeclarados.add(s.local.name);
250
250
  }
251
251
  }
@@ -13,7 +13,7 @@ export const analistaDuplicacoes = {
13
13
  test: (relPath) => {
14
14
  return /\.(js|jsx|ts|tsx|mjs|cjs)$/.test(relPath);
15
15
  },
16
- aplicar: async (src, relPath, ast, fullCaminho, contexto) => {
16
+ aplicar: (src, relPath, ast, fullCaminho, contexto) => {
17
17
  if (!ast || !src || !contexto) {
18
18
  return [];
19
19
  }
@@ -40,24 +40,7 @@ export const analistaDuplicacoes = {
40
40
  if (duplicacoes.length === 0) {
41
41
  return [];
42
42
  }
43
- // Agrupar por tipo de similaridade
44
- const porTipo = agruparPorTipoSimilaridade(duplicacoes);
45
- const ocorrencias = [];
46
- for (const [tipo, dups] of Object.entries(porTipo)) {
47
- if (dups.length > 0) {
48
- const nivel = tipo === 'identica' ? 'aviso' : 'info';
49
- const primeiraFunc = dups[0]?.funcaoA;
50
- const resumo = dups.map(diretorio => `${diretorio.funcaoA?.nome ?? 'unknown'} ≈ ${diretorio.funcaoB?.nome ?? 'unknown'} (${diretorio.similaridade.toFixed(0)}%)`).slice(0, 3).join(', ');
51
- ocorrencias.push(criarOcorrencia({
52
- tipo: 'codigo_duplicado',
53
- nivel,
54
- mensagem: messages.DetectorAgregadosMensagens.duplicacoesResumo(tipo, resumo, dups.length),
55
- relPath,
56
- linha: primeiraFunc?.inicio ?? 1
57
- }));
58
- }
59
- }
60
- return ocorrencias;
43
+ return agruparEConverterDuplicacoes(duplicacoes, relPath);
61
44
  }
62
45
  catch (erro) {
63
46
  return [criarOcorrencia({
@@ -70,6 +53,26 @@ export const analistaDuplicacoes = {
70
53
  }
71
54
  }
72
55
  };
56
+ function agruparEConverterDuplicacoes(duplicacoes, relPath) {
57
+ const porTipo = agruparPorTipoSimilaridade(duplicacoes);
58
+ const ocorrencias = [];
59
+ for (const [tipo, dups] of Object.entries(porTipo)) {
60
+ if (dups.length === 0) {
61
+ continue;
62
+ }
63
+ const nivel = tipo === 'identica' ? 'aviso' : 'info';
64
+ const primeiraFunc = dups[0]?.funcaoA;
65
+ const resumo = dups.map(diretorio => `${diretorio.funcaoA?.nome ?? 'unknown'} ≈ ${diretorio.funcaoB?.nome ?? 'unknown'} (${diretorio.similaridade.toFixed(0)}%)`).slice(0, 3).join(', ');
66
+ ocorrencias.push(criarOcorrencia({
67
+ tipo: 'codigo_duplicado',
68
+ nivel,
69
+ mensagem: messages.DetectorAgregadosMensagens.duplicacoesResumo(tipo, resumo, dups.length),
70
+ relPath,
71
+ linha: primeiraFunc?.inicio ?? 1
72
+ }));
73
+ }
74
+ return ocorrencias;
75
+ }
73
76
  function extrairFuncoes(ast, caminho, src) {
74
77
  const funcoes = [];
75
78
  const linhas = src.split('\n');
@@ -125,12 +128,12 @@ function extrairInfoFuncao(path, caminho, tipoFuncao, linhas) {
125
128
  if ('id' in node && node.id && 'name' in node.id) {
126
129
  nome = node.id.name;
127
130
  }
128
- else if ('key' in node && node.key && 'name' in node.key) {
131
+ else if ('key' in node && 'name' in node.key) {
129
132
  nome = node.key.name;
130
133
  }
131
134
  else if (path.parentPath.isVariableDeclarator()) {
132
135
  const parent = path.parentPath.node;
133
- nome = 'id' in parent && parent.id && 'name' in parent.id ? parent.id.name : 'assigned';
136
+ nome = 'id' in parent && 'name' in parent.id ? parent.id.name : 'assigned';
134
137
  }
135
138
  // Extrair parâmetros
136
139
  const parametros = ('params' in node && Array.isArray(node.params) ? node.params : []).map((param) => {
@@ -138,7 +141,7 @@ function extrairInfoFuncao(path, caminho, tipoFuncao, linhas) {
138
141
  if (param.type === 'Identifier' && 'name' in param) {
139
142
  return param.name;
140
143
  } // Identifier node
141
- if (param.type === 'RestElement' && 'argument' in param && param.argument && 'name' in param.argument) {
144
+ if (param.type === 'RestElement' && 'argument' in param && 'name' in param.argument) {
142
145
  return `...${param.argument.name}`; // RestElement node
143
146
  }
144
147
  return param.type;
@@ -257,10 +260,7 @@ function agruparPorTipoSimilaridade(duplicacoes) {
257
260
  return duplicacoes.reduce((acc, dup) => {
258
261
  const tipo = dup.tipoSimilaridade;
259
262
  if (tipo) {
260
- if (!acc[tipo]) {
261
- acc[tipo] = [];
262
- }
263
- acc[tipo].push(dup);
263
+ (acc[tipo] ??= []).push(dup);
264
264
  }
265
265
  return acc;
266
266
  }, {});
@@ -14,7 +14,7 @@ export function detectarMonorepo(baseDir) {
14
14
  return info;
15
15
  }
16
16
  // Detect package manager
17
- const pm = rootPkg.packageManager || '';
17
+ const pm = rootPkg.packageManager ?? '';
18
18
  if (pm) {
19
19
  info.packageManager = pm;
20
20
  }
@@ -51,11 +51,12 @@ export function detectarMonorepo(baseDir) {
51
51
  info.type = 'nx';
52
52
  try {
53
53
  const nx = JSON.parse(fs.readFileSync(nxPath, 'utf-8'));
54
- if (nx.workspaceLayout?.appsDir) {
55
- workspaceGlobs.push(nx.workspaceLayout.appsDir);
54
+ const nxLayout = nx.workspaceLayout;
55
+ if (nxLayout?.appsDir) {
56
+ workspaceGlobs.push(nxLayout.appsDir);
56
57
  }
57
- if (nx.workspaceLayout?.libsDir) {
58
- workspaceGlobs.push(nx.workspaceLayout.libsDir);
58
+ if (nxLayout?.libsDir) {
59
+ workspaceGlobs.push(nxLayout.libsDir);
59
60
  }
60
61
  }
61
62
  catch { }
@@ -82,7 +83,7 @@ export function detectarMonorepo(baseDir) {
82
83
  if (Array.isArray(rootPkg.workspaces)) {
83
84
  workspaceGlobs = rootPkg.workspaces;
84
85
  }
85
- else if (typeof rootPkg.workspaces === 'object' && rootPkg.workspaces !== null) {
86
+ else if (typeof rootPkg.workspaces === 'object') {
86
87
  const ws = rootPkg.workspaces;
87
88
  if (Array.isArray(ws.packages)) {
88
89
  workspaceGlobs = ws.packages;
@@ -132,9 +133,9 @@ function resolverWorkspaces(rootDir, globs) {
132
133
  name: pkg.name || entry.name,
133
134
  dir: resolved,
134
135
  packageJson: pkg,
135
- dependencies: pkg.dependencies || {},
136
- devDependencies: pkg.devDependencies || {},
137
- peerDependencies: pkg.peerDependencies || {},
136
+ dependencies: pkg.dependencies,
137
+ devDependencies: pkg.devDependencies,
138
+ peerDependencies: pkg.peerDependencies,
138
139
  });
139
140
  }
140
141
  }
@@ -173,7 +174,7 @@ export const detectorMonorepo = {
173
174
  // Check for missing root scripts
174
175
  const rootPkg = lerPackageJson(baseDir);
175
176
  if (rootPkg) {
176
- const scripts = rootPkg.scripts || {};
177
+ const scripts = rootPkg.scripts;
177
178
  const expectedScripts = ['build', 'test', 'lint'];
178
179
  for (const script of expectedScripts) {
179
180
  if (!scripts[script]) {
@@ -236,47 +237,52 @@ export const detectorMonorepo = {
236
237
  versionMap.set(dep, verMap);
237
238
  }
238
239
  }
239
- for (const [dep, versions] of versionMap) {
240
- if (versions.size > 1) {
241
- const uniqueVersions = new Set(versions.values());
242
- if (uniqueVersions.size > 1) {
243
- ocorrencias.push({
244
- tipo: 'monorepo-versao-mismatch',
245
- nivel: 'aviso',
246
- mensagem: `Dependência ${dep} com versões diferentes entre workspaces: ${Array.from(versions.entries()).map(([w, v]) => `${w}@${v}`).join(', ')}`,
247
- origem: 'detector-monorepo',
248
- relPath: '[monorepo]',
249
- linha: 0,
250
- });
251
- }
240
+ detectarVersionMismatch(versionMap, ocorrencias);
241
+ detectarDependenciasInternasFaltando(info, ocorrencias);
242
+ return ocorrencias;
243
+ },
244
+ };
245
+ function detectarVersionMismatch(versionMap, ocorrencias) {
246
+ for (const [dep, versions] of versionMap) {
247
+ if (versions.size > 1) {
248
+ const uniqueVersions = new Set(versions.values());
249
+ if (uniqueVersions.size > 1) {
250
+ ocorrencias.push({
251
+ tipo: 'monorepo-versao-mismatch',
252
+ nivel: 'aviso',
253
+ mensagem: `Dependência ${dep} com versões diferentes entre workspaces: ${Array.from(versions.entries()).map(([w, v]) => `${w}@${v}`).join(', ')}`,
254
+ origem: 'detector-monorepo',
255
+ relPath: '[monorepo]',
256
+ linha: 0,
257
+ });
252
258
  }
253
259
  }
254
- // Detect missing internal dependencies (workspace A uses workspace B but B isn't in A's deps)
255
- const workspaceNames = new Set(info.workspaces.map(w => w.name));
256
- for (const ws of info.workspaces) {
257
- const imports = coletarImports(ws.dir);
258
- for (const imp of imports) {
259
- for (const wsName of workspaceNames) {
260
- if (imp.includes(wsName) && wsName !== ws.name) {
261
- const isDep = ws.dependencies[wsName] || ws.devDependencies[wsName] || ws.peerDependencies[wsName];
262
- if (!isDep) {
263
- ocorrencias.push({
264
- tipo: 'monorepo-dependencia-interna-faltando',
265
- nivel: 'aviso',
266
- mensagem: `${ws.name} importa ${wsName} mas não o declara como dependência`,
267
- origem: 'detector-monorepo',
268
- relPath: `[${ws.name}]`,
269
- linha: 0,
270
- });
271
- }
272
- break;
260
+ }
261
+ }
262
+ function detectarDependenciasInternasFaltando(info, ocorrencias) {
263
+ const workspaceNames = new Set(info.workspaces.map(w => w.name));
264
+ for (const ws of info.workspaces) {
265
+ const imports = coletarImports(ws.dir);
266
+ for (const imp of imports) {
267
+ for (const wsName of workspaceNames) {
268
+ if (imp.includes(wsName) && wsName !== ws.name) {
269
+ const isDep = ws.dependencies[wsName] || ws.devDependencies[wsName] || ws.peerDependencies[wsName];
270
+ if (!isDep) {
271
+ ocorrencias.push({
272
+ tipo: 'monorepo-dependencia-interna-faltando',
273
+ nivel: 'aviso',
274
+ mensagem: `${ws.name} importa ${wsName} mas não o declara como dependência`,
275
+ origem: 'detector-monorepo',
276
+ relPath: `[${ws.name}]`,
277
+ linha: 0,
278
+ });
273
279
  }
280
+ break;
274
281
  }
275
282
  }
276
283
  }
277
- return ocorrencias;
278
- },
279
- };
284
+ }
285
+ }
280
286
  function coletarImports(dir) {
281
287
  const imports = [];
282
288
  try {
@@ -169,12 +169,33 @@ function detectarPadroesPerformance(src, problemas, relPath) {
169
169
  }
170
170
  });
171
171
  }
172
+ function detectarTimerSemCleanup(path, ast, problemas, relPath) {
173
+ if (path.node.callee.type !== 'Identifier') {
174
+ return;
175
+ }
176
+ if (path.node.callee.name !== 'setTimeout' && path.node.callee.name !== 'setInterval') {
177
+ return;
178
+ }
179
+ const parentFunction = path.getFunctionParent();
180
+ const context = parentFunction ? parentFunction.toString() : ast.toString();
181
+ if (context.includes('clear') || relPath.includes('test')) {
182
+ return;
183
+ }
184
+ problemas.push({
185
+ tipo: 'memory-leak',
186
+ descricao: `${path.node.callee.name} sem cleanup pode causar vazamento`,
187
+ impacto: 'medio',
188
+ linha: path.node.loc?.start.line ?? 0,
189
+ coluna: path.node.loc?.start.column ?? 0,
190
+ sugestao: `Use clear${path.node.callee.name.replace('set', '')} para limpar`
191
+ });
192
+ }
172
193
  function detectarProblemasPerformanceAST(ast, problemas, relPath) {
173
194
  try {
174
195
  const isLoop = (type) => ['ForStatement', 'WhileStatement', 'DoWhileStatement', 'ForInStatement', 'ForOfStatement'].includes(type);
175
196
  const checkNesting = (path) => {
176
197
  let parent = path.parentPath;
177
- while (parent) {
198
+ while ((parent.node).type !== 'Program') {
178
199
  if (isLoop(parent.type)) {
179
200
  problemas.push({
180
201
  tipo: 'inefficient-loop',
@@ -195,23 +216,8 @@ function detectarProblemasPerformanceAST(ast, problemas, relPath) {
195
216
  DoWhileStatement: checkNesting,
196
217
  ForInStatement: checkNesting,
197
218
  ForOfStatement: checkNesting,
198
- // Detectar função setTimeout/setInterval sem cleanup
199
219
  CallExpression(path) {
200
- if (path.node.callee.type === 'Identifier' && (path.node.callee.name === 'setTimeout' || path.node.callee.name === 'setInterval')) {
201
- // Heurística simples: se não há clear* na mesma função/arquivo
202
- const parentFunction = path.getFunctionParent();
203
- const context = parentFunction ? parentFunction.toString() : ast.toString();
204
- if (!context.includes('clear') && !relPath.includes('test')) {
205
- problemas.push({
206
- tipo: 'memory-leak',
207
- descricao: `${path.node.callee.name} sem cleanup pode causar vazamento`,
208
- impacto: 'medio',
209
- linha: path.node.loc?.start.line ?? 0,
210
- coluna: path.node.loc?.start.column ?? 0,
211
- sugestao: `Use clear${path.node.callee.name.replace('set', '')} para limpar`
212
- });
213
- }
214
- }
220
+ detectarTimerSemCleanup(path, ast, problemas, relPath);
215
221
  }
216
222
  });
217
223
  }
@@ -226,6 +232,7 @@ function mapearImpactoParaNivel(impacto) {
226
232
  case 'medio':
227
233
  return 'aviso';
228
234
  case 'baixo':
235
+ return 'info';
229
236
  case undefined: {
230
237
  throw new Error('Not implemented yet: undefined case');
231
238
  }
@@ -3,6 +3,43 @@ import { criarOcorrencia } from '../../types/index.js';
3
3
  * Analista global que analisa o projeto completo e recomenda
4
4
  * a melhor arquitetura (Clean Architecture, Microsserviços, MVC, etc.)
5
5
  */
6
+ const CONFIANCA_SIMPLES = 60;
7
+ function adicionarOcorrenciasRecomendacao(ocorrencias, _relPath, sinaisCleanArch, sinaisDistributed, recomendacoes, arquiteturaRecomendada, confianca) {
8
+ ocorrencias.push(criarOcorrencia({
9
+ tipo: 'recomendacao-arquitetura',
10
+ nivel: 'info',
11
+ relPath: _relPath,
12
+ linha: 1,
13
+ mensagem: `[TARGET] Arquitetura recomendada: ${arquiteturaRecomendada} (${confianca}% confiança)`
14
+ }));
15
+ if (sinaisCleanArch.length > 0) {
16
+ ocorrencias.push(criarOcorrencia({
17
+ tipo: 'sinais-clean-arch',
18
+ nivel: 'info',
19
+ relPath: _relPath,
20
+ linha: 1,
21
+ mensagem: `Sinais de Clean Architecture: ${sinaisCleanArch.join(', ')}`
22
+ }));
23
+ }
24
+ if (sinaisDistributed.length > 0) {
25
+ ocorrencias.push(criarOcorrencia({
26
+ tipo: 'sinais-distributed-arch',
27
+ nivel: 'info',
28
+ relPath: _relPath,
29
+ linha: 1,
30
+ mensagem: `Sinais de Arquitetura Distribuída: ${sinaisDistributed.join(', ')}`
31
+ }));
32
+ }
33
+ for (const rec of recomendacoes.slice(0, 5)) {
34
+ ocorrencias.push(criarOcorrencia({
35
+ tipo: 'recomendacao-arquitetura-item',
36
+ nivel: 'info',
37
+ relPath: _relPath,
38
+ linha: 1,
39
+ mensagem: `[IDEA] ${rec}`
40
+ }));
41
+ }
42
+ }
6
43
  export const analistaRecomendacaoArquitetura = {
7
44
  nome: 'recomendacao-arquitetura',
8
45
  categoria: 'arquitetura',
@@ -210,7 +247,7 @@ export const analistaRecomendacaoArquitetura = {
210
247
  }
211
248
  // MVC para projetos web tradicionais
212
249
  if (temFrontend && temControllers && !temEntities) {
213
- const scoreMvc = (temControllers ? 15 : 0) + (temFrontend ? 15 : 0);
250
+ const scoreMvc = 30;
214
251
  if (scoreMvc > melhorScore && !complexidadeBaixa) {
215
252
  arquiteturaRecomendada = 'MVC (Model-View-Controller)';
216
253
  melhorScore = scoreMvc;
@@ -221,7 +258,7 @@ export const analistaRecomendacaoArquitetura = {
221
258
  if (melhorScore === 0) {
222
259
  if (complexidadeBaixa) {
223
260
  arquiteturaRecomendada = 'Arquitetura Simples / Monolítica';
224
- confianca = 60;
261
+ confianca = CONFIANCA_SIMPLES;
225
262
  recomendacoes.push('Projeto de baixa complexidade - comece com uma estrutura simples');
226
263
  recomendacoes.push('Considere evoluir para Clean Architecture conforme o projeto crescer');
227
264
  }
@@ -243,40 +280,7 @@ export const analistaRecomendacaoArquitetura = {
243
280
  if (totalArquivos > 100 && servicosSet.size === 0) {
244
281
  recomendacoes.push('Projeto grande e monolítico - considere dividir em serviços menores');
245
282
  }
246
- ocorrencias.push(criarOcorrencia({
247
- tipo: 'recomendacao-arquitetura',
248
- nivel: 'info',
249
- relPath: _relPath,
250
- linha: 1,
251
- mensagem: `[TARGET] Arquitetura recomendada: ${arquiteturaRecomendada} (${confianca}% confiança)`
252
- }));
253
- if (sinaisCleanArch.length > 0) {
254
- ocorrencias.push(criarOcorrencia({
255
- tipo: 'sinais-clean-arch',
256
- nivel: 'info',
257
- relPath: _relPath,
258
- linha: 1,
259
- mensagem: `Sinais de Clean Architecture: ${sinaisCleanArch.join(', ')}`
260
- }));
261
- }
262
- if (sinaisDistributed.length > 0) {
263
- ocorrencias.push(criarOcorrencia({
264
- tipo: 'sinais-distributed-arch',
265
- nivel: 'info',
266
- relPath: _relPath,
267
- linha: 1,
268
- mensagem: `Sinais de Arquitetura Distribuída: ${sinaisDistributed.join(', ')}`
269
- }));
270
- }
271
- for (const rec of recomendacoes.slice(0, 5)) {
272
- ocorrencias.push(criarOcorrencia({
273
- tipo: 'recomendacao-arquitetura-item',
274
- nivel: 'info',
275
- relPath: _relPath,
276
- linha: 1,
277
- mensagem: `[IDEA] ${rec}`
278
- }));
279
- }
283
+ adicionarOcorrenciasRecomendacao(ocorrencias, _relPath, sinaisCleanArch, sinaisDistributed, recomendacoes, arquiteturaRecomendada, confianca);
280
284
  return ocorrencias;
281
285
  }
282
286
  };