@mocoto/mahoraga 0.14.1 → 0.14.2

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 (268) hide show
  1. package/dist/analysts/architects/analyst-structure.js +1 -1
  2. package/dist/analysts/architects/archetypes-custom.js +8 -13
  3. package/dist/analysts/architects/detector-archetypes.js +39 -35
  4. package/dist/analysts/architects/orchestrator-archetypes.js +3 -3
  5. package/dist/analysts/architects/signals-project-advanced.js +2 -2
  6. package/dist/analysts/architects/signals-project.js +1 -1
  7. package/dist/analysts/azure-pipelines/analysts/analyst-azure.js +20 -21
  8. package/dist/analysts/azure-pipelines/detectors/detector-azure-structure.js +0 -3
  9. package/dist/analysts/circleci/analysts/analyst-circleci.js +22 -24
  10. package/dist/analysts/circleci/detectors/detector-circleci-structure.js +4 -7
  11. package/dist/analysts/converters/convert-registry.js +1 -1
  12. package/dist/analysts/converters/index.js +1 -1
  13. package/dist/analysts/corrections/auto-fix-engine.js +1 -1
  14. package/dist/analysts/corrections/corrector-structure.js +8 -7
  15. package/dist/analysts/corrections/map-reversion.js +2 -2
  16. package/dist/analysts/corrections/reorganize-barrels.js +3 -3
  17. package/dist/analysts/corrections/rewrite-testes-aliases.js +23 -22
  18. package/dist/analysts/corrections/type-safety/type-analyzer.js +3 -3
  19. package/dist/analysts/corrections/type-safety/type-validator.js +2 -2
  20. package/dist/analysts/corrections/type-safety/usage-analyzer.js +3 -3
  21. package/dist/analysts/css/analysts/analyst-css.js +27 -28
  22. package/dist/analysts/css-in-js/detectors/detector-css-in-js-best-practices.js +8 -15
  23. package/dist/analysts/detectors/detector-architecture.js +2 -2
  24. package/dist/analysts/detectors/detector-bugs-ml.js +8 -8
  25. package/dist/analysts/detectors/detector-code-fragile.js +11 -10
  26. package/dist/analysts/detectors/detector-dependencies.js +5 -5
  27. package/dist/analysts/detectors/detector-duplications.js +5 -8
  28. package/dist/analysts/detectors/detector-monorepo.js +10 -9
  29. package/dist/analysts/detectors/detector-performance.js +2 -1
  30. package/dist/analysts/detectors/detector-recommendation-architecture.js +1 -1
  31. package/dist/analysts/detectors/detector-security.js +1 -1
  32. package/dist/analysts/detectors/detector-structure.js +3 -3
  33. package/dist/analysts/github-actions/analysts/analyst-github-actions.js +5 -8
  34. package/dist/analysts/github-actions/detectors/detector-workflow-accessibility.js +1 -9
  35. package/dist/analysts/github-actions/detectors/detector-workflow-structure.js +1 -4
  36. package/dist/analysts/github-actions/detectors/detector-workflow-trigger-unsafe.js +6 -5
  37. package/dist/analysts/gitlab-ci/analysts/analyst-gitlab-ci.js +2 -2
  38. package/dist/analysts/gitlab-ci/detectors/detector-gitlab-ci-structure.js +0 -3
  39. package/dist/analysts/go/analysts/analyst-best-practices.js +2 -2
  40. package/dist/analysts/go/analysts/analyst-concurrency.js +1 -1
  41. package/dist/analysts/go/analysts/analyst-security.js +1 -1
  42. package/dist/analysts/go/detectors/detector-conventions.js +1 -1
  43. package/dist/analysts/html/analysts/analyst-html.js +10 -12
  44. package/dist/analysts/html/detectors/detector-html.js +3 -3
  45. package/dist/analysts/js-ts/analysts/analyst-commands-cli.js +22 -22
  46. package/dist/analysts/js-ts/analysts/analyst-functions-long.js +5 -5
  47. package/dist/analysts/js-ts/analysts/analyst-patterns-usage.js +6 -2
  48. package/dist/analysts/js-ts/detectors/detector-anti-patterns-async.js +81 -9
  49. package/dist/analysts/js-ts/detectors/detector-constructions-syntactic.js +35 -6
  50. package/dist/analysts/js-ts/detectors/detector-context-smart.js +6 -6
  51. package/dist/analysts/js-ts/detectors/detector-leaks-memory.js +1 -1
  52. package/dist/analysts/js-ts/detectors/detector-types-unsafe.js +33 -2
  53. package/dist/analysts/php/analysts/analyst-php.js +3 -3
  54. package/dist/analysts/php/detectors/detector-php-best-practices.js +5 -5
  55. package/dist/analysts/php/detectors/detector-php-security.js +5 -5
  56. package/dist/analysts/php/scorers/scorer-php.js +2 -2
  57. package/dist/analysts/plugins/detector-documentation.js +5 -6
  58. package/dist/analysts/plugins/detector-markdown.js +7 -7
  59. package/dist/analysts/python/analysts/analyst-python.js +2 -5
  60. package/dist/analysts/react/analysts/analyst-react-hooks.js +63 -8
  61. package/dist/analysts/react/analysts/analyst-react.js +45 -1
  62. package/dist/analysts/react/corrections/correction-react.js +40 -0
  63. package/dist/analysts/react/detectors/detector-react-best-practices.js +4 -4
  64. package/dist/analysts/react/scorers/scorer-react.js +36 -1
  65. package/dist/analysts/rust/analysts/analyst-best-practices.js +42 -3
  66. package/dist/analysts/rust/analysts/analyst-memory.js +2 -2
  67. package/dist/analysts/rust/analysts/analyst-rust.js +52 -5
  68. package/dist/analysts/rust/analysts/analyst-security.js +29 -1
  69. package/dist/analysts/scorers/scorer.js +5 -5
  70. package/dist/analysts/shell/analysts/analyst-shell.js +81 -5
  71. package/dist/analysts/shell/corrections/correction-shell.js +34 -1
  72. package/dist/analysts/shell/detectors/detector-shell-security.js +88 -0
  73. package/dist/analysts/shell/scorers/scorer-shell.js +58 -1
  74. package/dist/analysts/strategists/operator-structure.js +5 -7
  75. package/dist/analysts/strategists/suggestions-contextuais.js +5 -2
  76. package/dist/analysts/svg/analysts/analyst-svg.js +1 -0
  77. package/dist/analysts/tailwind/analysts/analyst-tailwind.js +79 -55
  78. package/dist/analysts/tailwind/corrections/correction-tailwind.js +116 -9
  79. package/dist/analysts/tailwind/detectors/detector-tailwind-best-practices.js +122 -7
  80. package/dist/analysts/tailwind/scorers/scorer-tailwind.js +62 -10
  81. package/dist/analysts/xml/analysts/analyst-xml.js +2 -2
  82. package/dist/app/index.js +1 -0
  83. package/dist/bin/cli-bootstrap.js +6 -4
  84. package/dist/bin/index.js +6 -4
  85. package/dist/caretakers/scoring.js +1 -0
  86. package/dist/cli/commands/command-analysts.js +1 -1
  87. package/dist/cli/commands/command-azure.js +1 -1
  88. package/dist/cli/commands/command-circleci.js +1 -1
  89. package/dist/cli/commands/command-compliance.js +1 -1
  90. package/dist/cli/commands/command-diagnose.js +10 -13
  91. package/dist/cli/commands/command-fix-types.js +9 -32
  92. package/dist/cli/commands/command-formatters.js +2 -2
  93. package/dist/cli/commands/command-gitlab-ci.js +1 -1
  94. package/dist/cli/commands/command-guardian.js +1 -1
  95. package/dist/cli/commands/command-imports.js +6 -6
  96. package/dist/cli/commands/command-jenkins.js +1 -1
  97. package/dist/cli/commands/command-licenses.js +1 -1
  98. package/dist/cli/commands/command-marketplace.js +3 -3
  99. package/dist/cli/commands/command-names.js +3 -8
  100. package/dist/cli/commands/command-perf.js +7 -9
  101. package/dist/cli/commands/command-plugins.js +4 -4
  102. package/dist/cli/diagnostic/auto-fix.js +2 -2
  103. package/dist/cli/diagnostic/exporters/json-exporter.js +1 -1
  104. package/dist/cli/diagnostic/exporters/sharded-exporter.js +0 -3
  105. package/dist/cli/diagnostic/exporters/svg-optimization-exporter.js +1 -1
  106. package/dist/cli/diagnostic/handlers/archetype-handler.js +3 -6
  107. package/dist/cli/diagnostic/handlers/auto-fix-handler.js +4 -4
  108. package/dist/cli/diagnostic/handlers/guardian-handler.js +1 -1
  109. package/dist/cli/diagnostic/processing-diagnostic.js +31 -35
  110. package/dist/cli/diagnostic/processing-helpers.js +2 -2
  111. package/dist/cli/handlers/fix-types-exporter.js +1 -4
  112. package/dist/cli/helpers/display-frame.js +5 -5
  113. package/dist/core/config/auto/auto-fix-config.js +0 -6
  114. package/dist/core/config/chalk-safe.js +2 -2
  115. package/dist/core/config/config.js +6 -8
  116. package/dist/core/config/conventions.js +1 -1
  117. package/dist/core/config/security.js +2 -2
  118. package/dist/core/execution/analysis-cache.js +5 -8
  119. package/dist/core/execution/executor.js +8 -19
  120. package/dist/core/execution/inquisitor.js +24 -21
  121. package/dist/core/execution/results.js +1 -0
  122. package/dist/core/execution/scanner.js +3 -3
  123. package/dist/core/messages/en/analysts/analyst-github-actions-messages.js +1 -1
  124. package/dist/core/messages/en/analysts/analyst-patterns-usage-messages.js +1 -0
  125. package/dist/core/messages/en/analysts/analyst-shell-messages.js +15 -0
  126. package/dist/core/messages/en/analysts/detector-constructions-syntactic-messages.js +6 -0
  127. package/dist/core/messages/en/analysts/detector-js-ts-messages.js +27 -0
  128. package/dist/core/messages/en/analysts/detector-react-messages.js +8 -0
  129. package/dist/core/messages/en/analysts/detector-shell-messages.js +17 -0
  130. package/dist/core/messages/en/analysts/detector-tailwind-messages.js +3 -3
  131. package/dist/core/messages/en/core/plugin-messages.js +31 -3
  132. package/dist/core/messages/en/log/log.js +4 -4
  133. package/dist/core/messages/en/ui/filter-config.js +1 -5
  134. package/dist/core/messages/i18n-system.js +3 -3
  135. package/dist/core/messages/index.js +3 -3
  136. package/dist/core/messages/ja/analysts/analyst-github-actions-messages.js +1 -1
  137. package/dist/core/messages/ja/analysts/analyst-patterns-usage-messages.js +1 -0
  138. package/dist/core/messages/ja/analysts/analyst-shell-messages.js +15 -0
  139. package/dist/core/messages/ja/analysts/detector-constructions-syntactic-messages.js +6 -0
  140. package/dist/core/messages/ja/analysts/detector-js-ts-messages.js +27 -0
  141. package/dist/core/messages/ja/analysts/detector-react-messages.js +8 -0
  142. package/dist/core/messages/ja/analysts/detector-shell-messages.js +17 -0
  143. package/dist/core/messages/ja/analysts/detector-tailwind-messages.js +3 -3
  144. package/dist/core/messages/ja/core/plugin-messages.js +31 -3
  145. package/dist/core/messages/ja/log/log.js +4 -4
  146. package/dist/core/messages/ja/ui/filter-config.js +1 -1
  147. package/dist/core/messages/pt/analysts/analyst-github-actions-messages.js +1 -1
  148. package/dist/core/messages/pt/analysts/analyst-patterns-usage-messages.js +1 -0
  149. package/dist/core/messages/pt/analysts/analyst-shell-messages.js +15 -0
  150. package/dist/core/messages/pt/analysts/detector-constructions-syntactic-messages.js +6 -0
  151. package/dist/core/messages/pt/analysts/detector-js-ts-messages.js +27 -0
  152. package/dist/core/messages/pt/analysts/detector-react-messages.js +8 -0
  153. package/dist/core/messages/pt/analysts/detector-shell-messages.js +17 -0
  154. package/dist/core/messages/pt/analysts/detector-tailwind-messages.js +3 -3
  155. package/dist/core/messages/pt/core/plugin-messages.js +31 -3
  156. package/dist/core/messages/pt/log/log-engine.js +6 -6
  157. package/dist/core/messages/pt/log/log.js +3 -3
  158. package/dist/core/messages/pt/ui/filter-config.js +1 -1
  159. package/dist/core/messages/shared/icons.js +3 -3
  160. package/dist/core/messages/zh/analysts/analyst-github-actions-messages.js +1 -1
  161. package/dist/core/messages/zh/analysts/analyst-patterns-usage-messages.js +1 -0
  162. package/dist/core/messages/zh/analysts/analyst-shell-messages.js +15 -0
  163. package/dist/core/messages/zh/analysts/detector-constructions-syntactic-messages.js +6 -0
  164. package/dist/core/messages/zh/analysts/detector-js-ts-messages.js +27 -0
  165. package/dist/core/messages/zh/analysts/detector-react-messages.js +8 -0
  166. package/dist/core/messages/zh/analysts/detector-shell-messages.js +17 -0
  167. package/dist/core/messages/zh/analysts/detector-tailwind-messages.js +3 -3
  168. package/dist/core/messages/zh/core/plugin-messages.js +31 -3
  169. package/dist/core/messages/zh/log/log.js +3 -3
  170. package/dist/core/messages/zh/ui/filter-config.js +1 -5
  171. package/dist/core/parsing/filters.js +3 -3
  172. package/dist/core/parsing/langs/json.js +1 -1
  173. package/dist/core/parsing/langs/python.js +1 -1
  174. package/dist/core/parsing/langs/typescript.js +1 -1
  175. package/dist/core/parsing/parser.js +2 -2
  176. package/dist/core/registry/file-registry.js +3 -2
  177. package/dist/core/registry/paths.js +3 -3
  178. package/dist/core/reporting/default-reporter.js +2 -2
  179. package/dist/core/schema/version.js +6 -6
  180. package/dist/core/workers/worker-executor.js +3 -3
  181. package/dist/core/workers/worker-pool.js +0 -0
  182. package/dist/guardian/baseline.js +1 -1
  183. package/dist/guardian/gpg.js +3 -1
  184. package/dist/guardian/integrity.js +2 -7
  185. package/dist/guardian/records.js +6 -1
  186. package/dist/guardian/result.js +1 -1
  187. package/dist/guardian/sentinel.js +6 -1
  188. package/dist/guardian/watcher-hidden.js +5 -1
  189. package/dist/licenses/fs-utils.js +4 -1
  190. package/dist/licenses/generate-notices.js +1 -1
  191. package/dist/licenses/header-options.js +0 -1
  192. package/dist/licenses/index.js +1 -0
  193. package/dist/licenses/normalizer.js +10 -9
  194. package/dist/node.loader.js +224 -4
  195. package/dist/reports/analise-async-patterns.js +1 -1
  196. package/dist/reports/filter-smart.js +2 -5
  197. package/dist/reports/generator-report.js +4 -4
  198. package/dist/reports/report-archetypes.js +10 -10
  199. package/dist/reports/report-caretaker-health.js +2 -1
  200. package/dist/sdk/analyzer.js +1 -1
  201. package/dist/shared/data-processing/fragment-report.js +10 -10
  202. package/dist/shared/data-processing/json.js +1 -1
  203. package/dist/shared/data-processing/occurrences.js +3 -2
  204. package/dist/shared/formatters/code-min-formatter.js +1 -1
  205. package/dist/shared/formatters/engines/prettier.js +1 -1
  206. package/dist/shared/formatters/engines/stylelint.js +6 -9
  207. package/dist/shared/formatters/formatter.js +8 -8
  208. package/dist/shared/formatters/formatters/code.js +3 -3
  209. package/dist/shared/formatters/formatters/css.js +2 -10
  210. package/dist/shared/formatters/formatters/dotfiles.js +1 -1
  211. package/dist/shared/formatters/formatters/html.js +1 -5
  212. package/dist/shared/formatters/formatters/json.js +0 -3
  213. package/dist/shared/formatters/formatters/markdown.js +18 -23
  214. package/dist/shared/formatters/formatters/properties.js +2 -2
  215. package/dist/shared/formatters/formatters/shell.js +1 -4
  216. package/dist/shared/formatters/formatters/sql.js +0 -3
  217. package/dist/shared/formatters/formatters/xml.js +5 -7
  218. package/dist/shared/formatters/formatters/yaml.js +2 -7
  219. package/dist/shared/formatters/index.js +1 -1
  220. package/dist/shared/helpers/framework-detector.js +1 -1
  221. package/dist/shared/helpers/json.js +1 -1
  222. package/dist/shared/helpers/magic-constants-whitelist.js +1 -1
  223. package/dist/shared/helpers/masking.js +17 -17
  224. package/dist/shared/helpers/reader-report.js +0 -12
  225. package/dist/shared/helpers/structural-hash.js +3 -2
  226. package/dist/shared/helpers/structure.js +1 -1
  227. package/dist/shared/marketplace/registry.js +1 -1
  228. package/dist/shared/marketplace/remote.js +4 -4
  229. package/dist/shared/persistence/persistence.js +0 -1
  230. package/dist/shared/plugins/core-plugin.js +3 -1
  231. package/dist/shared/plugins/registry.js +3 -2
  232. package/dist/types/caretakers/imports-barrel.js +1 -0
  233. package/dist/types/caretakers/index.js +4 -0
  234. package/dist/types/caretakers/map-reversion.js +1 -0
  235. package/dist/types/caretakers/pruning.js +1 -0
  236. package/dist/types/caretakers/scoring.js +1 -0
  237. package/dist/types/common/analysts.js +1 -1
  238. package/dist/types/core/config/filters.js +1 -0
  239. package/dist/types/core/config/index.js +2 -0
  240. package/dist/types/core/execution/ambiente.js +1 -0
  241. package/dist/types/core/execution/linguagens.js +1 -0
  242. package/dist/types/core/execution/parse-errors.js +1 -0
  243. package/dist/types/core/execution/results.js +1 -0
  244. package/dist/types/core/execution/structure-json.js +1 -0
  245. package/dist/types/core/index.js +1 -0
  246. package/dist/types/core/messages/index.js +1 -0
  247. package/dist/types/core/messages/log.js +1 -0
  248. package/dist/types/core/parsing/babel-narrow.js +1 -0
  249. package/dist/types/core/parsing/index.js +1 -0
  250. package/dist/types/core/runtime.js +1 -0
  251. package/dist/types/guardian/index.js +2 -0
  252. package/dist/types/guardian/integrity.js +7 -0
  253. package/dist/types/guardian/snapshot.js +1 -0
  254. package/dist/types/index.js +4 -4
  255. package/dist/types/licenses/index.js +2 -0
  256. package/dist/types/processing/display.js +16 -13
  257. package/dist/types/processing/filters.js +3 -7
  258. package/dist/types/reports/compliance.js +1 -0
  259. package/dist/types/reports/streaming.js +1 -0
  260. package/dist/types/scripts/index.js +1 -0
  261. package/dist/types/scripts/migrar-aliases.js +1 -0
  262. package/dist/types/sdk/index.js +1 -0
  263. package/dist/types/shared/index.js +2 -0
  264. package/dist/types/vulnerabilities/index.js +2 -0
  265. package/dist/vulnerabilities/npm-audit.js +0 -1
  266. package/dist/vulnerabilities/scanner.js +2 -1
  267. package/dist/vulnerabilities/vulnerabilities.js +0 -1
  268. package/package.json +11 -12
@@ -3,7 +3,7 @@ import path from 'node:path';
3
3
  import pLimit from 'p-limit';
4
4
  import { config } from '../../core/config/index.js';
5
5
  // Constantes para análise estrutural
6
- export const CONCORRENCIA = (config.STRUCTURE_CONCURRENCY ?? 5);
6
+ export const CONCORRENCIA = config.STRUCTURE_CONCURRENCY;
7
7
  export const CAMADAS = {
8
8
  ts: 'src',
9
9
  js: 'src',
@@ -105,8 +105,8 @@ export async function existeArquetipoPersonalizado(baseDir = process.cwd()) {
105
105
  * Obtém o arquétipo oficial base para um arquétipo personalizado
106
106
  */
107
107
  export function obterArquetipoOficial(arquetipoPersonalizado) {
108
- const nomeOficial = arquetipoPersonalizado.arquetipoOficial ?? '';
109
- const encontrado = ARQUETIPOS.find((arq) => arq.nome === nomeOficial);
108
+ const nomeOficial = arquetipoPersonalizado.arquetipoOficial;
109
+ const encontrado = ARQUETIPOS?.find((arq) => arq.nome === nomeOficial);
110
110
  return encontrado ?? null;
111
111
  }
112
112
  /**
@@ -209,21 +209,16 @@ export function validarArquetipoPersonalizado(arquetipo) {
209
209
  }
210
210
  else {
211
211
  // Verifica se o arquétipo oficial existe
212
- const arquetipoOficial = ARQUETIPOS.find((arq) => arq.nome === arquetipo.arquetipoOficial);
212
+ const arquetipoOficial = ARQUETIPOS?.find((arq) => arq.nome === arquetipo.arquetipoOficial);
213
213
  if (!arquetipoOficial) {
214
- erros.push(ArquetiposExtraMensagens.validacao.arquetipoNaoEncontrado.replace('{arquetipo}', arquetipo.arquetipoOficial).replace('{disponiveis}', (ARQUETIPOS ?? []).map(arquivo => (arquivo).nome).join(', ')));
214
+ erros.push(ArquetiposExtraMensagens.validacao.arquetipoNaoEncontrado.replace('{arquetipo}', arquetipo.arquetipoOficial).replace('{disponiveis}', ARQUETIPOS.map(arquivo => (arquivo).nome).join(', ')));
215
215
  }
216
216
  }
217
- if (!arquetipo.estruturaPersonalizada) {
218
- erros.push(ArquetiposExtraMensagens.validacao.estruturaObrigatoria);
217
+ if (!Array.isArray(arquetipo.estruturaPersonalizada.diretorios)) {
218
+ erros.push(ArquetiposExtraMensagens.validacao.diretoriosArray);
219
219
  }
220
- else {
221
- if (!Array.isArray(arquetipo.estruturaPersonalizada.diretorios)) {
222
- erros.push(ArquetiposExtraMensagens.validacao.diretoriosArray);
223
- }
224
- if (!Array.isArray(arquetipo.estruturaPersonalizada.arquivosChave)) {
225
- erros.push(ArquetiposExtraMensagens.validacao.arquivosChaveArray);
226
- }
220
+ if (!Array.isArray(arquetipo.estruturaPersonalizada.arquivosChave)) {
221
+ erros.push(ArquetiposExtraMensagens.validacao.arquivosChaveArray);
227
222
  }
228
223
  return {
229
224
  valido: erros.length === 0,
@@ -91,7 +91,7 @@ export async function detectarArquetipos(contexto, baseDir, options) {
91
91
  const melhorDeteccao = resultadosContextuais.reduce((melhor, atual) => atual.confiancaTotal > melhor.confiancaTotal ? atual : melhor, {
92
92
  confiancaTotal: 0
93
93
  });
94
- if (melhorDeteccao && melhorDeteccao.confiancaTotal > 0.6) {
94
+ if (melhorDeteccao.confiancaTotal > 0.6) {
95
95
  // Escala 0-1, não 0-100
96
96
  // Mapear tecnologias detectadas para arquétipos conhecidos
97
97
  const mapeamentoTecnologia = {
@@ -106,40 +106,44 @@ export async function detectarArquetipos(contexto, baseDir, options) {
106
106
  'react-spa': ['react-spa', 'react', 'spa']
107
107
  };
108
108
  const tecnologiaDetectada = melhorDeteccao.tecnologia ?? 'desconhecido';
109
- const arquetiposCandidatos = mapeamentoTecnologia[tecnologiaDetectada] || [];
110
- // Aplicar boost de confiança para arquétipos relacionados
111
- let boostAplicado = false;
112
- candidatos = candidatos.map((candidato) => {
113
- if (arquetiposCandidatos.some((arq) => candidato.nome.includes(arq) || arq.includes(candidato.nome))) {
114
- const boostConfianca = Math.min(melhorDeteccao.confiancaTotal * 100 * 0.8, 60); // Boost agressivo até 60%
115
- boostAplicado = true;
116
- return {
117
- ...candidato,
118
- confidence: Math.max(candidato.confidence + boostConfianca, 70),
119
- // Mínimo 70% se detectado
120
- explicacaoSimilaridade: `[Boost contextual: ${melhorDeteccao.tecnologia} detectado com ${(melhorDeteccao.confiancaTotal * 100).toFixed(0)}% confiança] ${candidato.explicacaoSimilaridade ?? ''}`
109
+ const arquetiposCandidatos = mapeamentoTecnologia[tecnologiaDetectada];
110
+ if (!arquetiposCandidatos) {
111
+ if (!options?.quiet && config.VERBOSE) {
112
+ console.log(`[AVISO] Tecnologia detectada "${tecnologiaDetectada}" não mapeada para nenhum arquétipo.`);
113
+ }
114
+ }
115
+ else {
116
+ // Aplicar boost de confiança para arquétipos relacionados
117
+ const boostAplicado = candidatos.some((candidato) => arquetiposCandidatos.some((arq) => candidato.nome.includes(arq) || arq.includes(candidato.nome)));
118
+ candidatos = candidatos.map((candidato) => {
119
+ if (arquetiposCandidatos.some((arq) => candidato.nome.includes(arq) || arq.includes(candidato.nome))) {
120
+ const boostConfianca = Math.min(melhorDeteccao.confiancaTotal * 100 * 0.8, 60);
121
+ return {
122
+ ...candidato,
123
+ confidence: Math.max(candidato.confidence + boostConfianca, 70),
124
+ explicacaoSimilaridade: `[Boost contextual: ${melhorDeteccao.tecnologia} detectado com ${(melhorDeteccao.confiancaTotal * 100).toFixed(0)}% confiança] ${candidato.explicacaoSimilaridade ?? ''}`
125
+ };
126
+ }
127
+ return candidato;
128
+ });
129
+ if (!boostAplicado) {
130
+ const arquetipoVirtual = {
131
+ nome: tecnologiaDetectada,
132
+ score: Math.round(melhorDeteccao.confiancaTotal * 100),
133
+ confidence: Math.round(melhorDeteccao.confiancaTotal * 100),
134
+ matchedRequired: [],
135
+ missingRequired: [],
136
+ matchedOptional: [],
137
+ dependencyMatches: (melhorDeteccao.evidencias ?? []).filter(erro => erro.tipo === 'dependencia').map(erro => erro.valor),
138
+ filePadraoMatches: (melhorDeteccao.evidencias ?? []).filter(erro => erro.tipo === 'estrutura').map(erro => erro.valor),
139
+ forbiddenPresent: [],
140
+ anomalias: [],
141
+ sugestaoPadronizacao: (melhorDeteccao.sugestoesMelhoria ?? []).join('; '),
142
+ explicacaoSimilaridade: `Detectado via sistema inteligente contextual com ${(melhorDeteccao.confiancaTotal * 100).toFixed(0)}% confiança`,
143
+ descricao: `Projeto ${melhorDeteccao.tecnologia} identificado por análise contextual`
121
144
  };
145
+ candidatos.unshift(arquetipoVirtual);
122
146
  }
123
- return candidato;
124
- });
125
- // Se não encontrou arquétipo compatível, criar um virtual baseado na detecção
126
- if (!boostAplicado) {
127
- const arquetipoVirtual = {
128
- nome: tecnologiaDetectada,
129
- score: Math.round(melhorDeteccao.confiancaTotal * 100),
130
- confidence: Math.round(melhorDeteccao.confiancaTotal * 100),
131
- matchedRequired: [],
132
- missingRequired: [],
133
- matchedOptional: [],
134
- dependencyMatches: (melhorDeteccao.evidencias ?? []).filter(erro => erro.tipo === 'dependencia').map(erro => erro.valor),
135
- filePadraoMatches: (melhorDeteccao.evidencias ?? []).filter(erro => erro.tipo === 'estrutura').map(erro => erro.valor),
136
- forbiddenPresent: [],
137
- anomalias: [],
138
- sugestaoPadronizacao: (melhorDeteccao.sugestoesMelhoria ?? []).join('; '),
139
- explicacaoSimilaridade: `Detectado via sistema inteligente contextual com ${(melhorDeteccao.confiancaTotal * 100).toFixed(0)}% confiança`,
140
- descricao: `Projeto ${melhorDeteccao.tecnologia} identificado por análise contextual`
141
- };
142
- candidatos.unshift(arquetipoVirtual); // Adiciona no início
143
147
  }
144
148
  }
145
149
  }
@@ -211,7 +215,7 @@ export async function detectarArquetipos(contexto, baseDir, options) {
211
215
  const baselineCaminho = path.join(baseDir, '.mahoraga', 'baseline-estrutura.json');
212
216
  let baseline;
213
217
  const existente = await lerEstado(baselineCaminho);
214
- if (existente && !Array.isArray(existente) && typeof existente === 'object' && 'arquetipo' in existente) {
218
+ if (!Array.isArray(existente) && typeof existente === 'object' && 'arquetipo' in existente) {
215
219
  baseline = existente;
216
220
  }
217
221
  if (!baseline && candidatos[0]) {
@@ -227,7 +231,7 @@ export async function detectarArquetipos(contexto, baseDir, options) {
227
231
  // Prioriza baseline apenas se o candidato principal for 'desconhecido' ou confiança baixa
228
232
  if (baseline && baseline.arquetipo !== 'desconhecido') {
229
233
  const arquivosRaizAtuais = arquivos.filter(caminho => !caminho.includes('/'));
230
- const setBase = new Set(baseline.arquivosRaiz || []);
234
+ const setBase = new Set(baseline.arquivosRaiz);
231
235
  const temIntersecao = arquivosRaizAtuais.some(arquivo => setBase.has(arquivo));
232
236
  const candidatoTop = candidatos[0];
233
237
  if (temIntersecao && (candidatoTop.nome === 'desconhecido' || candidatoTop.confidence < 50)) {
@@ -94,7 +94,7 @@ export function detectarArquetipo(arquivos) {
94
94
  const filtrados = apenasPenalidades.filter(elem => {
95
95
  // Regra específica: se o candidato for 'monorepo-packages' e o único forbidden detectado for 'src', descartamos
96
96
  if (elem.nome === 'monorepo-packages') {
97
- const forb = elem.forbiddenPresent || [];
97
+ const forb = elem.forbiddenPresent;
98
98
  if (forb.length === 1 && forb[0] === 'src') {
99
99
  return false;
100
100
  }
@@ -110,8 +110,8 @@ export function detectarArquetipo(arquivos) {
110
110
  const forbA = arquivo.forbiddenPresent.length || 0;
111
111
  const forbB = base.forbiddenPresent.length || 0;
112
112
  // Usa somente o total de diretórios proibidos definidos no alvo para o ratio
113
- const defA = ARQUETIPOS.find((diretorio) => diretorio.nome === arquivo.nome);
114
- const defB = ARQUETIPOS.find((diretorio) => diretorio.nome === base.nome);
113
+ const defA = ARQUETIPOS?.find((diretorio) => diretorio.nome === arquivo.nome);
114
+ const defB = ARQUETIPOS?.find((diretorio) => diretorio.nome === base.nome);
115
115
  const totA = defA?.forbiddenDirs?.length ?? 0;
116
116
  const totB = defB?.forbiddenDirs?.length ?? 0;
117
117
  const ratioA = totA > 0 ? forbA / totA : 0;
@@ -5,7 +5,7 @@ _sinaisAvancados // prefixo _ para ignorar warning de unused
5
5
  // Implementação fictícia para evitar erro de compilação
6
6
  return {
7
7
  nome: def.nome,
8
- descricao: def.descricao ?? '',
8
+ descricao: def.descricao,
9
9
  score: 0,
10
10
  confidence: 0,
11
11
  matchedRequired: [],
@@ -45,7 +45,7 @@ export function extrairSinaisAvancados(fileEntries, packageJson, _p0, _baseDir,
45
45
  const tecnologias = new Map();
46
46
  for (const fe of fileEntries) {
47
47
  let body = [];
48
- if (fe.ast && 'node' in fe.ast && fe.ast.node && fe.ast.node.type === 'Program' && Array.isArray(fe.ast.node.body)) {
48
+ if (fe.ast && 'node' in fe.ast && Array.isArray(fe.ast.node.body)) {
49
49
  body = fe.ast.node.body;
50
50
  }
51
51
  // Análise inteligente de padrões
@@ -22,7 +22,7 @@ export function extrairSinaisProjeto(fileEntries, packageJson) {
22
22
  };
23
23
  for (const fe of fileEntries) {
24
24
  let body = [];
25
- if (fe.ast && 'node' in fe.ast && fe.ast.node && fe.ast.node.type === 'Program' && Array.isArray(fe.ast.node.body)) {
25
+ if (fe.ast && 'node' in fe.ast && Array.isArray(fe.ast.node.body)) {
26
26
  body = fe.ast.node.body;
27
27
  }
28
28
  // Funções
@@ -27,32 +27,31 @@ export const analistaAzurePipelines = {
27
27
  // 2. Análise Estrutural básica
28
28
  const doc = parseDocument(conteudo);
29
29
  const configData = doc.toJS();
30
- if (configData) {
31
- // Verificar versão antiga (v0.x)
32
- if (configData.version && parseFloat(String(configData.version)) < 1.0) {
30
+ // Verificar versão antiga (v0.x)
31
+ const version = configData.version;
32
+ if ((typeof version === 'string' || typeof version === 'number') && parseFloat(String(version)) < 1.0) {
33
+ ocorrencias.push({
34
+ tipo: 'AZURE_OBSOLETE_VERSION',
35
+ mensagem: 'Versão do schema do Azure Pipelines está obsoleta',
36
+ relPath,
37
+ linha: 1,
38
+ nivel: 'aviso',
39
+ sugestao: 'Remova o campo "version" para usar o schema YAML moderno',
40
+ });
41
+ }
42
+ // Detectar excesso de variáveis globais
43
+ if (configData.variables && typeof configData.variables === 'object') {
44
+ const varCount = Object.keys(configData.variables).length;
45
+ if (varCount > 20) {
33
46
  ocorrencias.push({
34
- tipo: 'AZURE_OBSOLETE_VERSION',
35
- mensagem: 'Versão do schema do Azure Pipelines está obsoleta',
47
+ tipo: 'AZURE_TOO_MANY_VARIABLES',
48
+ mensagem: messages.RelatorioAzureMensagens.tooManyVariables,
36
49
  relPath,
37
50
  linha: 1,
38
- nivel: 'aviso',
39
- sugestao: 'Remova o campo "version" para usar o schema YAML moderno',
51
+ nivel: 'info',
52
+ sugestao: messages.RelatorioAzureMensagens.tooManyVariablesSugestao,
40
53
  });
41
54
  }
42
- // Detectar excesso de variáveis globais
43
- if (configData.variables && typeof configData.variables === 'object') {
44
- const varCount = Object.keys(configData.variables).length;
45
- if (varCount > 20) {
46
- ocorrencias.push({
47
- tipo: 'AZURE_TOO_MANY_VARIABLES',
48
- mensagem: messages.RelatorioAzureMensagens.tooManyVariables,
49
- relPath,
50
- linha: 1,
51
- nivel: 'info',
52
- sugestao: messages.RelatorioAzureMensagens.tooManyVariablesSugestao,
53
- });
54
- }
55
- }
56
55
  }
57
56
  // 3. Plugins registrados
58
57
  const caminhos = contexto?.arquivos.map(arquivo => arquivo.relPath) ?? [];
@@ -15,9 +15,6 @@ export const detectorAzureEstrutura = {
15
15
  try {
16
16
  const doc = parseDocument(src);
17
17
  const pipeline = doc.toJS();
18
- if (!pipeline) {
19
- return ocorrencias;
20
- }
21
18
  const jobs = pipeline.jobs;
22
19
  if (jobs && Array.isArray(jobs)) {
23
20
  const jobNames = jobs.map(j => j.job ?? '').filter(Boolean);
@@ -32,30 +32,28 @@ export const analistaCircleCI = {
32
32
  }
33
33
  const doc = parseDocument(conteudo);
34
34
  const config = doc.toJS();
35
- if (config) {
36
- const configData = config;
37
- if (configData.version && parseFloat(String(configData.version)) < 2.1) {
38
- ocorrencias.push({
39
- tipo: 'CIRCLECI_OBSOLETE_VERSION',
40
- mensagem: `Versão do CircleCI (${configData.version}) está obsoleta`,
41
- relPath,
42
- linha: 1,
43
- nivel: 'aviso',
44
- sugestao: 'Atualize para a versão 2.1 para usar Orbs, Commands e outras melhorias modernas'
45
- });
46
- }
47
- if (configData.jobs) {
48
- for (const [jobName, job] of Object.entries(configData.jobs)) {
49
- if (job.steps && job.steps.length > 20) {
50
- ocorrencias.push({
51
- tipo: 'CIRCLECI_JOB_TOO_MANY_STEPS',
52
- mensagem: `Job '${jobName}' possui muitos steps (${job.steps.length})`,
53
- relPath,
54
- linha: 1,
55
- nivel: 'info',
56
- sugestao: 'Agrupe steps repetitivos em "commands" para maior legibilidade'
57
- });
58
- }
35
+ const configData = config;
36
+ if (configData.version && parseFloat(String(configData.version)) < 2.1) {
37
+ ocorrencias.push({
38
+ tipo: 'CIRCLECI_OBSOLETE_VERSION',
39
+ mensagem: `Versão do CircleCI (${configData.version}) está obsoleta`,
40
+ relPath,
41
+ linha: 1,
42
+ nivel: 'aviso',
43
+ sugestao: 'Atualize para a versão 2.1 para usar Orbs, Commands e outras melhorias modernas'
44
+ });
45
+ }
46
+ if (configData.jobs) {
47
+ for (const [jobName, job] of Object.entries(configData.jobs)) {
48
+ if (job.steps && job.steps.length > 20) {
49
+ ocorrencias.push({
50
+ tipo: 'CIRCLECI_JOB_TOO_MANY_STEPS',
51
+ mensagem: `Job '${jobName}' possui muitos steps (${job.steps.length})`,
52
+ relPath,
53
+ linha: 1,
54
+ nivel: 'info',
55
+ sugestao: 'Agrupe steps repetitivos em "commands" para maior legibilidade'
56
+ });
59
57
  }
60
58
  }
61
59
  }
@@ -16,9 +16,6 @@ export const detectorCircleCIEstrutura = {
16
16
  try {
17
17
  const doc = parseDocument(src);
18
18
  const config = doc.toJS();
19
- if (!config) {
20
- return ocorrencias;
21
- }
22
19
  const jobs = config;
23
20
  if (jobs.jobs) {
24
21
  for (const [jobName, job] of Object.entries(jobs.jobs)) {
@@ -91,7 +88,7 @@ export const detectorCircleCIEstrutura = {
91
88
  const commands = config.commands;
92
89
  if (commands) {
93
90
  for (const [_cmdName, cmdDef] of Object.entries(commands)) {
94
- if (cmdDef && !('parameters' in cmdDef)) {
91
+ if (!('parameters' in cmdDef)) {
95
92
  ocorrencias.push(criarOcorrencia({
96
93
  tipo: 'circleci-command-no-parameters',
97
94
  nivel: 'info',
@@ -133,14 +130,14 @@ export const detectorCircleCIEstrutura = {
133
130
  const wfValues = Object.values(workflows);
134
131
  const usedJobs = new Set();
135
132
  for (const wf of wfValues) {
136
- if (wf && typeof wf === 'object') {
133
+ if (typeof wf === 'object') {
137
134
  const wfJobs = wf.jobs;
138
135
  if (Array.isArray(wfJobs)) {
139
136
  for (const wfJob of wfJobs) {
140
137
  if (typeof wfJob === 'string') {
141
138
  usedJobs.add(wfJob);
142
139
  }
143
- else if (wfJob && typeof wfJob === 'object') {
140
+ else if (typeof wfJob === 'object') {
144
141
  Object.keys(wfJob).forEach(k => usedJobs.add(k));
145
142
  }
146
143
  }
@@ -162,7 +159,7 @@ export const detectorCircleCIEstrutura = {
162
159
  // Resource class pricing consideration
163
160
  if (jobs.jobs) {
164
161
  for (const [, job] of Object.entries(jobs.jobs)) {
165
- if (job && !('resource_class' in job) && job.steps && job.steps.length > 5) {
162
+ if (!('resource_class' in job) && job.steps && job.steps.length > 5) {
166
163
  ocorrencias.push(criarOcorrencia({
167
164
  tipo: 'circleci-resource-class-pricing',
168
165
  nivel: 'info',
@@ -1,5 +1,5 @@
1
1
  import { ConversorGhaToGitlab } from './engines/converter-gha-to-gitlab.js';
2
2
  export const registroConversores = [new ConversorGhaToGitlab()];
3
3
  export function obterConversor(de, para) {
4
- return registroConversores.find(elem => elem.de.toLowerCase() === de.toLowerCase() && elem.para.toLowerCase() === para.toLowerCase());
4
+ return registroConversores?.find(elem => elem.de.toLowerCase() === de.toLowerCase() && elem.para.toLowerCase() === para.toLowerCase());
5
5
  }
@@ -10,5 +10,5 @@ export const registroConversores = [new ConversorGhaToGitlab()];
10
10
  * Busca um conversor compatível com as plataformas de origem e destino.
11
11
  */
12
12
  export function obterConversor(de, para) {
13
- return registroConversores.find(elem => elem.de.toLowerCase() === de.toLowerCase() && elem.para.toLowerCase() === para.toLowerCase());
13
+ return registroConversores?.find(elem => elem.de.toLowerCase() === de.toLowerCase() && elem.para.toLowerCase() === para.toLowerCase());
14
14
  }
@@ -83,7 +83,7 @@ export function aplicarCorrecaoArquivo(arquivo, ocorrencias, config) {
83
83
  /**
84
84
  * Aplica correções em múltiplos arquivos
85
85
  */
86
- export async function aplicarCorrecoesEmLote(porArquivo, config) {
86
+ export function aplicarCorrecoesEmLote(porArquivo, config) {
87
87
  const resultados = [];
88
88
  let sucesso = 0;
89
89
  let falhas = 0;
@@ -12,9 +12,10 @@ import { mapaReversao } from './map-reversion.js';
12
12
  const { log, logAuto, CorretorEstruturaExtraMensagens } = getMessages();
13
13
  export async function corrigirEstrutura(mapa, fileEntries, baseDir = process.cwd()) {
14
14
  // Captura dinâmica das configs (evita congelar valores em tempo de import)
15
- const CONCORRENCIA = (config.STRUCTURE_CONCURRENCY ?? 5);
15
+ const CONCORRENCIA = config.STRUCTURE_CONCURRENCY;
16
16
  const AUTO_CORRECAO = config.STRUCTURE_AUTO_FIX;
17
- const PLUGINS = config.STRUCTURE_PLUGINS ?? [];
17
+ const rawPlugins = config.STRUCTURE_PLUGINS ?? [];
18
+ const PLUGINS = Array.isArray(rawPlugins) ? rawPlugins.filter((p) => typeof p === 'string') : [];
18
19
  const ESTRUTURA_CAMADAS = config.ESTRUTURA_CAMADAS;
19
20
  const limit = pLimit(CONCORRENCIA);
20
21
  await Promise.all(mapa.map(entry => limit(async () => {
@@ -68,17 +69,17 @@ export async function corrigirEstrutura(mapa, fileEntries, baseDir = process.cwd
68
69
  })));
69
70
  for (const pluginRel of PLUGINS) {
70
71
  try {
71
- const resolvido = resolverPluginSeguro(baseDir, String(pluginRel));
72
+ const resolvido = resolverPluginSeguro(baseDir, pluginRel);
72
73
  if (resolvido.erro) {
73
- logAuto.pluginIgnorado(String(pluginRel), resolvido.erro);
74
+ logAuto.pluginIgnorado(pluginRel, resolvido.erro);
74
75
  continue;
75
76
  }
76
77
  const caminhoPlugin = resolvido.caminho;
77
78
  if (!caminhoPlugin) {
78
- logAuto.caminhoNaoResolvido(String(pluginRel));
79
+ logAuto.caminhoNaoResolvido(pluginRel);
79
80
  continue;
80
81
  }
81
- const pluginModule = await importarModuloSeguro(baseDir, String(pluginRel));
82
+ const pluginModule = await importarModuloSeguro(baseDir, pluginRel);
82
83
  let pluginFn;
83
84
  if (pluginModule && typeof pluginModule === 'object' && 'default' in pluginModule && typeof pluginModule.default === 'function') {
84
85
  pluginFn = pluginModule.default;
@@ -103,7 +104,7 @@ export async function corrigirEstrutura(mapa, fileEntries, baseDir = process.cwd
103
104
  else if (typeof err === 'string') {
104
105
  msg = err;
105
106
  }
106
- logAuto.pluginFalhou(String(pluginRel), msg);
107
+ logAuto.pluginFalhou(pluginRel, msg);
107
108
  }
108
109
  }
109
110
  }
@@ -41,7 +41,7 @@ export class GerenciadorMapaReversao {
41
41
  }
42
42
  };
43
43
  // Validação básica
44
- if (!this.mapa.moves || !Array.isArray(this.mapa.moves)) {
44
+ if (!Array.isArray(this.mapa.moves)) {
45
45
  throw new Error(messages.ExcecoesMensagens.mapaReversaoCorrompido);
46
46
  }
47
47
  logAuto.mapaReversaoCarregado(this.mapa.moves.length);
@@ -89,7 +89,7 @@ export class GerenciadorMapaReversao {
89
89
  // quando true, evita persistir o mapa no disco imediatamente (útil para chamadas em massa/tests)
90
90
  skipSalvar) {
91
91
  try {
92
- const id = `move_${Date.now()}_${Math.random().toString(CONSTANTES_MAPA.RADIX_36).substr(CONSTANTES_MAPA.ID_OFFSET, CONSTANTES_MAPA.ID_LENGTH)}`;
92
+ const id = `move_${Date.now()}_${Math.random().toString(CONSTANTES_MAPA.RADIX_36).slice(CONSTANTES_MAPA.ID_OFFSET, CONSTANTES_MAPA.ID_OFFSET + CONSTANTES_MAPA.ID_LENGTH)}`;
93
93
  const move = {
94
94
  id,
95
95
  timestamp: new Date().toISOString(),
@@ -301,9 +301,9 @@ async function extrairNomesExportados(srcDir, relPath, visitados = new Set(), pr
301
301
  nomes.add(exportDecl[1]);
302
302
  }
303
303
  // export { name1, name2 as alias, ... }
304
- const exportList = trimmed.match(/^export\s+type\s*\{([^}]+)\}|^export\s*\{([^}]+)\}/);
304
+ const exportList = trimmed.match(/^export\s+(?:type\s+)?\s*\{([^}]+)\}/);
305
305
  if (exportList) {
306
- const body = exportList[1] ?? exportList[2];
306
+ const body = exportList[1];
307
307
  if (body) {
308
308
  body.split(',').forEach(part => {
309
309
  const m = part.trim().match(/^(\w+)(?:\s+as\s+\w+)?$/);
@@ -469,7 +469,7 @@ async function repararImportsBarrelPerdidos(srcDir, barrelsPerdidos, _movimentos
469
469
  if (!match) {
470
470
  return null;
471
471
  }
472
- return { imported: match[1], local: match[2] ?? match[1] };
472
+ return { imported: match[1], local: match[2] || match[1] };
473
473
  }).filter((n) => n !== null);
474
474
  const nomesQueFicam = [];
475
475
  const nomesQueMoveram = [];
@@ -19,7 +19,7 @@ function exists(caminho) {
19
19
  function pathFromAlias(aliasSpec, srcRoot) {
20
20
  const spec = aliasSpec.replace(/^@/, '');
21
21
  const parts = spec.split('/');
22
- const top = parts.shift();
22
+ const top = parts?.shift();
23
23
  return path.join(srcRoot, top ?? '', parts.join('/'));
24
24
  }
25
25
  export function pickExtForAlias(aliasBase, srcRoot) {
@@ -67,40 +67,41 @@ export function rewriteToAlias(spec, ctx) {
67
67
  export function transformCodeForTests(code, ctx) {
68
68
  let changed = false;
69
69
  const rewrite = (spec) => rewriteToAlias(spec, ctx);
70
- code = code.replace(/(import\s+[^'"\n]+?from\s+)(["'])([^"']+?)\2/g, (metrica, p1, delimitadorString, spec) => {
71
- const result = rewrite(spec);
72
- if (!result.changed) {
73
- return metrica;
70
+ let result = code;
71
+ result = result.replace(/(import\s+[^'"\n]+?from\s+)(["'])([^"']+?)\2/g, (substring, p1, delimitadorString, spec) => {
72
+ const res = rewrite(spec);
73
+ if (!res.changed) {
74
+ return substring;
74
75
  }
75
76
  changed = true;
76
- return `${p1}${delimitadorString}${result.value}${delimitadorString}`;
77
+ return `${p1}${delimitadorString}${res.value}${delimitadorString}`;
77
78
  });
78
- code = code.replace(/(import\s*)(["'])([^"']+?)\2/g, (metrica, p1, delimitadorString, spec) => {
79
- const result = rewrite(spec);
80
- if (!result.changed) {
81
- return metrica;
79
+ result = result.replace(/(import\s*)(["'])([^"']+?)\2/g, (substring, p1, delimitadorString, spec) => {
80
+ const res = rewrite(spec);
81
+ if (!res.changed) {
82
+ return substring;
82
83
  }
83
84
  changed = true;
84
- return `${p1}${delimitadorString}${result.value}${delimitadorString}`;
85
+ return `${p1}${delimitadorString}${res.value}${delimitadorString}`;
85
86
  });
86
- code = code.replace(/(import\s*\()(\s*["'])([^"']+?)(["']\s*\))/g, (metrica, p1, q1, spec, q2) => {
87
- const result = rewrite(spec);
88
- if (!result.changed) {
89
- return metrica;
87
+ result = result.replace(/(import\s*\()(\s*["'])([^"']+?)(["']\s*\))/g, (substring, p1, q1, spec, q2) => {
88
+ const res = rewrite(spec);
89
+ if (!res.changed) {
90
+ return substring;
90
91
  }
91
92
  changed = true;
92
- return `${p1}${q1}${result.value}${q2}`;
93
+ return `${p1}${q1}${res.value}${q2}`;
93
94
  });
94
- code = code.replace(/(vi\.(?:do)?mock\s*\()(\s*["'])([^"']+?)(["'])(\s*,?)/g, (metrica, p1, q1, spec, q2, comma = '') => {
95
- const result = rewrite(spec);
96
- if (!result.changed) {
97
- return metrica;
95
+ result = result.replace(/(vi\.(?:do)?mock\s*\()(\s*["'])([^"']+?)(["'])(\s*,?)/g, (substring, p1, q1, spec, q2, comma = '') => {
96
+ const res = rewrite(spec);
97
+ if (!res.changed) {
98
+ return substring;
98
99
  }
99
100
  changed = true;
100
- return `${p1}${q1}${result.value}${q2}${comma}`;
101
+ return `${p1}${q1}${res.value}${q2}${comma}`;
101
102
  });
102
103
  return {
103
- code,
104
+ code: result,
104
105
  changed
105
106
  };
106
107
  }
@@ -62,14 +62,14 @@ export function analyzeTypeUsage(match, fullCode, fileCaminho, ast) {
62
62
  /**
63
63
  * Analisa uso de unknown com foco em type guards
64
64
  */
65
- export async function analyzeUnknownUsage(match, fullCode, fileCaminho, ast) {
65
+ export function analyzeUnknownUsage(match, fullCode, fileCaminho, ast) {
66
66
  // Mesma lógica de analyzeTypeUsage, mas mais conservador
67
67
  const analysis = analyzeTypeUsage(match, fullCode, fileCaminho, ast);
68
68
  // Penalizar confiança em 10% para unknown (mais conservador)
69
69
  analysis.confidence = Math.max(0, analysis.confidence - 10);
70
70
  // Se confiança ainda é baixa, sugerir manter unknown
71
71
  if (analysis.confidence < 70) {
72
- analysis.suggestion = 'Confiança baixa para substituir unknown. ' + `Considere adicionar type guards ou criar tipo dedicado em ${getTypesDirectoryDisplay()}`;
72
+ analysis.suggestion = `Confiança baixa para substituir unknown. Considere adicionar type guards ou criar tipo dedicado em ${getTypesDirectoryDisplay()}`;
73
73
  }
74
- return analysis;
74
+ return Promise.resolve(analysis);
75
75
  }
@@ -18,13 +18,13 @@ export async function validateTypeReplacement(originalCode, fixedCodigo, typeAna
18
18
  if (typeAnalise.createdNewType) {
19
19
  const existingTipo = await findExistingType(typeAnalise.typeName);
20
20
  if (existingTipo && !isSameType(existingTipo, typeAnalise.typeDefinition)) {
21
- result.warnings.push(`Tipo ${typeAnalise.typeName} já existe com definição diferente. ` + `Verifique conflito em ${existingTipo.path}`);
21
+ result.warnings.push(`Tipo ${typeAnalise.typeName} já existe com definição diferente. Verifique conflito em ${existingTipo.path}`);
22
22
  }
23
23
  }
24
24
  // 2. Verificar se tipo inferido é compatível com uso
25
25
  const usageValidation = validateTypeUsageCompatibility(fixedCodigo, typeAnalise);
26
26
  if (!usageValidation.isCompatible) {
27
- result.errors.push(`Tipo inferido ${typeAnalise.inferredTipo} incompatível com uso detectado. ` + `Esperado: ${usageValidation.expectedType}`);
27
+ result.errors.push(`Tipo inferido ${typeAnalise.inferredTipo} incompatível com uso detectado. Esperado: ${usageValidation.expectedType}`);
28
28
  result.isCompatible = false;
29
29
  }
30
30
  // 3. Verificar se import foi adicionado corretamente
@@ -214,7 +214,7 @@ function extractUsageFromNode(node, varNome) {
214
214
  * Extrai informações de MemberExpression
215
215
  */
216
216
  function extractMemberExpressionUsage(node, varNome) {
217
- const property = node.property?.name ?? node.property.value;
217
+ const property = node.property?.name ?? String(node.property.value);
218
218
  return {
219
219
  name: varNome,
220
220
  nodeType: 'MemberExpression',
@@ -222,7 +222,7 @@ function extractMemberExpressionUsage(node, varNome) {
222
222
  column: node.loc?.start?.column ?? 0,
223
223
  context: extractNodeContext(node),
224
224
  operation: 'access',
225
- property: property ? String(property) : undefined
225
+ property: property || undefined
226
226
  };
227
227
  }
228
228
  /**
@@ -250,7 +250,7 @@ function extractNodeContext(node) {
250
250
  }
251
251
  if (node.type === 'MemberExpression') {
252
252
  const obj = node.object?.name ?? extractNodeContext(node.object);
253
- const prop = node.property?.name ?? node.property.value;
253
+ const prop = node.property?.name ?? String(node.property.value);
254
254
  return `${obj}.${prop}`;
255
255
  }
256
256
  if (node.type === 'CallExpression') {