@semacode/cli 2.3.0 → 3.0.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 (267) hide show
  1. package/LICENSE +39 -39
  2. package/README.md +112 -41
  3. package/dist/agentContextPack.js +14 -10
  4. package/dist/agentEntryPoints.d.ts +5 -0
  5. package/dist/agentEntryPoints.js +102 -91
  6. package/dist/angular-consumer-standalone.d.ts +3 -1
  7. package/dist/angular-consumer-standalone.js +12 -8
  8. package/dist/bin.d.ts +6 -0
  9. package/dist/bin.js +130 -0
  10. package/dist/cliArgs.js +4 -4
  11. package/dist/cliControlError.d.ts +12 -0
  12. package/dist/cliControlError.js +47 -0
  13. package/dist/cliGrammar.d.ts +11 -0
  14. package/dist/cliGrammar.js +551 -0
  15. package/dist/cliHelp.d.ts +13 -0
  16. package/dist/cliHelp.js +19 -0
  17. package/dist/cliHelpTexto.d.ts +3 -0
  18. package/dist/cliHelpTexto.js +168 -0
  19. package/dist/cliRuntime.d.ts +2 -0
  20. package/dist/cliRuntime.js +31 -0
  21. package/dist/comandos.js +9 -22
  22. package/dist/contexto.js +5 -5
  23. package/dist/dev/index.d.ts +1 -0
  24. package/dist/dev/index.js +51 -9
  25. package/dist/discovery/catalog.js +3 -3
  26. package/dist/distribuicao/filesystemGlobal.d.ts +63 -0
  27. package/dist/distribuicao/filesystemGlobal.js +701 -0
  28. package/dist/distribuicao/index.d.ts +7 -0
  29. package/dist/distribuicao/index.js +227 -0
  30. package/dist/distribuicao/launcherGlobal.d.ts +53 -0
  31. package/dist/distribuicao/launcherGlobal.js +643 -0
  32. package/dist/distribuicao/launcherWindows.d.ts +28 -0
  33. package/dist/distribuicao/launcherWindows.js +326 -0
  34. package/dist/distribuicao/lockContextGlobal.d.ts +10 -0
  35. package/dist/distribuicao/lockContextGlobal.js +17 -0
  36. package/dist/distribuicao/lockGlobal.d.ts +6 -0
  37. package/dist/distribuicao/lockGlobal.js +520 -0
  38. package/dist/distribuicao/skillGlobal.d.ts +48 -0
  39. package/dist/distribuicao/skillGlobal.js +652 -0
  40. package/dist/distribuicao/skillIntentPolicy.d.ts +21 -0
  41. package/dist/distribuicao/skillIntentPolicy.js +115 -0
  42. package/dist/distribuicao/tipos.d.ts +50 -0
  43. package/dist/distribuicao/tipos.js +10 -0
  44. package/dist/distribuicao/versaoSemantica.d.ts +3 -0
  45. package/dist/distribuicao/versaoSemantica.js +62 -0
  46. package/dist/drift.part01.d.ts +34 -2
  47. package/dist/drift.part01.js +3 -0
  48. package/dist/drift.part04.d.ts +12 -2
  49. package/dist/drift.part04.js +89 -15
  50. package/dist/drift.part05.d.ts +2 -1
  51. package/dist/drift.part05.js +9 -6
  52. package/dist/drift.part06.d.ts +2 -1
  53. package/dist/drift.part06.js +115 -24
  54. package/dist/drift.part07.d.ts +11 -10
  55. package/dist/drift.part07.js +261 -255
  56. package/dist/drift.part08.d.ts +2 -1
  57. package/dist/drift.part08.js +35 -25
  58. package/dist/drift.part11.js +279 -32
  59. package/dist/drift.part12.d.ts +1 -1
  60. package/dist/drift.part12.js +196 -11
  61. package/dist/drift.part13.d.ts +18 -2
  62. package/dist/drift.part13.js +654 -76
  63. package/dist/drift.part14.js +21 -7
  64. package/dist/driftCacheCas.d.ts +43 -0
  65. package/dist/driftCacheCas.js +351 -0
  66. package/dist/driftCacheFilesystem.d.ts +64 -0
  67. package/dist/driftCacheFilesystem.js +313 -0
  68. package/dist/driftCacheModes.d.ts +38 -0
  69. package/dist/driftCacheModes.js +147 -0
  70. package/dist/driftCacheStore.d.ts +80 -0
  71. package/dist/driftCacheStore.js +603 -0
  72. package/dist/driftCatalogo.d.ts +65 -0
  73. package/dist/driftCatalogo.js +516 -0
  74. package/dist/driftEscopo.d.ts +21 -0
  75. package/dist/driftEscopo.js +647 -0
  76. package/dist/driftEscopoReferencias.d.ts +8 -0
  77. package/dist/driftEscopoReferencias.js +612 -0
  78. package/dist/driftOrcamento.d.ts +6 -0
  79. package/dist/driftOrcamento.js +20 -3
  80. package/dist/geracaoCore.js +4 -6
  81. package/dist/iaPrompts.d.ts +3 -3
  82. package/dist/iaPrompts.js +13 -14
  83. package/dist/index.d.ts +4 -1
  84. package/dist/index.js +6 -25
  85. package/dist/index.part01.d.ts +21 -14
  86. package/dist/index.part01.js +20 -165
  87. package/dist/index.part02.js +57 -43
  88. package/dist/index.part03.d.ts +23 -1
  89. package/dist/index.part03.js +83 -8
  90. package/dist/index.part04.d.ts +10 -2
  91. package/dist/index.part04.js +48 -14
  92. package/dist/index.part05.d.ts +1 -1
  93. package/dist/index.part05.js +109 -30
  94. package/dist/index.part06.js +34 -16
  95. package/dist/index.part07.js +31 -27
  96. package/dist/index.part08.d.ts +1 -1
  97. package/dist/index.part08.js +23 -28
  98. package/dist/init/templates.part01.js +393 -393
  99. package/dist/init/templates.part02.js +189 -189
  100. package/dist/initCommand.js +5 -1
  101. package/dist/initTemplatesBackend.js +73 -73
  102. package/dist/initTemplatesBase.js +7 -5
  103. package/dist/initTemplatesFlutter.js +137 -137
  104. package/dist/initTemplatesRuntime.js +350 -350
  105. package/dist/initTemplatesWeb.js +309 -309
  106. package/dist/pipelineConteudo/command.d.ts +1 -0
  107. package/dist/pipelineConteudo/command.js +4 -32
  108. package/dist/pipelineConteudo/help.d.ts +2 -0
  109. package/dist/pipelineConteudo/help.js +33 -0
  110. package/dist/profileAuthorCommand.js +3 -7
  111. package/dist/profileCommand.js +3 -7
  112. package/dist/projeto.d.ts +1 -1
  113. package/dist/projetoCarregar.d.ts +2 -2
  114. package/dist/projetoCarregar.js +69 -28
  115. package/dist/projetoCatalogo.d.ts +8 -0
  116. package/dist/projetoCatalogo.js +164 -0
  117. package/dist/projetoOrigens.d.ts +2 -0
  118. package/dist/projetoOrigens.js +65 -9
  119. package/dist/projetoTipos.d.ts +15 -5
  120. package/dist/resultadoCli.d.ts +20 -0
  121. package/dist/resultadoCli.js +57 -0
  122. package/dist/saidaCli.d.ts +35 -0
  123. package/dist/saidaCli.js +118 -0
  124. package/dist/sistemasInterativos/acceptanceEvidence.d.ts +22 -0
  125. package/dist/sistemasInterativos/acceptanceEvidence.js +345 -0
  126. package/dist/sistemasInterativos/engineObservation.d.ts +12 -0
  127. package/dist/sistemasInterativos/engineObservation.js +438 -0
  128. package/dist/sistemasInterativos/jobOrchestration.d.ts +2 -0
  129. package/dist/sistemasInterativos/jobOrchestration.js +204 -0
  130. package/dist/sistemasInterativos/operationPrimitives.d.ts +21 -0
  131. package/dist/sistemasInterativos/operationPrimitives.js +194 -0
  132. package/dist/sistemasInterativos/operations.d.ts +4 -39
  133. package/dist/sistemasInterativos/operations.js +5 -1164
  134. package/dist/skillCommand.d.ts +5 -0
  135. package/dist/skillCommand.js +88 -0
  136. package/dist/sync/index.js +35 -35
  137. package/docs/README.md +11 -7
  138. package/docs/ai-integration.md +18 -11
  139. package/docs/ai-onboarding.md +81 -62
  140. package/docs/ai-workflow.md +10 -4
  141. package/docs/auth.md +26 -26
  142. package/docs/cli.md +197 -79
  143. package/docs/commands.md +30 -6
  144. package/docs/database.md +15 -15
  145. package/docs/deploy.md +54 -41
  146. package/docs/documentation.md +11 -10
  147. package/docs/drift-cache.md +108 -0
  148. package/docs/env.md +16 -16
  149. package/docs/frontend.md +41 -41
  150. package/docs/getting-started.md +82 -57
  151. package/docs/i18n.md +15 -15
  152. package/docs/repositories.md +60 -43
  153. package/docs/rollback.md +38 -31
  154. package/docs/security.md +54 -32
  155. package/docs/sistemas-interativos.md +27 -27
  156. package/docs/support.md +8 -8
  157. package/docs/testing.md +123 -17
  158. package/docs/vocabulary.md +29 -29
  159. package/exemplos/agendamento.sema +1 -1
  160. package/exemplos/assinatura.sema +1 -1
  161. package/exemplos/auditoria.sema +1 -1
  162. package/exemplos/autenticacao.sema +1 -1
  163. package/exemplos/author_obra_comum.sema +1 -1
  164. package/exemplos/author_tema_sensivel.sema +1 -1
  165. package/exemplos/automacao.sema +1 -1
  166. package/exemplos/cadastro_usuario.sema +1 -1
  167. package/exemplos/calculadora.sema +1 -1
  168. package/exemplos/crud_simples.sema +1 -1
  169. package/exemplos/estoque.sema +1 -1
  170. package/exemplos/exportacao.sema +1 -1
  171. package/exemplos/fila.sema +1 -1
  172. package/exemplos/integracao_externa.sema +1 -1
  173. package/exemplos/multi_tenant.sema +1 -1
  174. package/exemplos/notificacao.sema +1 -1
  175. package/exemplos/operacao_estrategia.sema +132 -132
  176. package/exemplos/operacao_estrategia_discovery.sema +220 -220
  177. package/exemplos/operacao_estrategia_fluxo.sema +114 -114
  178. package/exemplos/operacao_estrategia_gates.sema +106 -106
  179. package/exemplos/operacao_estrategia_quarentena.sema +133 -133
  180. package/exemplos/operacao_estrategia_rollout.sema +124 -124
  181. package/exemplos/pagamento.sema +1 -1
  182. package/exemplos/pagamento_dominio.sema +1 -1
  183. package/exemplos/pedido.sema +1 -1
  184. package/exemplos/permissao.sema +1 -1
  185. package/exemplos/persistencia_vendor_first.sema +1 -1
  186. package/exemplos/profile_conversas.sema +165 -165
  187. package/exemplos/profile_game.sema +1 -1
  188. package/exemplos/profile_legal.sema +1 -1
  189. package/exemplos/profile_ops.sema +1 -1
  190. package/exemplos/profile_research.sema +1 -1
  191. package/exemplos/profile_software.sema +1 -1
  192. package/exemplos/profile_workflow_n8n.sema +1 -1
  193. package/exemplos/relatorio.sema +1 -1
  194. package/exemplos/replica_analitica_erp.sema +1 -1
  195. package/exemplos/testes_embutidos.sema +1 -1
  196. package/exemplos/tratamento_erro.sema +1 -1
  197. package/exemplos/upload_arquivo.sema +1 -1
  198. package/exemplos/webhook.sema +1 -1
  199. package/node_modules/@sema/gerador-cpp/dist/index.js +176 -176
  200. package/node_modules/@sema/gerador-css/dist/index.part01.js +10 -10
  201. package/node_modules/@sema/gerador-css/dist/index.part02.js +460 -460
  202. package/node_modules/@sema/gerador-dotnet/dist/index.js +169 -169
  203. package/node_modules/@sema/gerador-html/dist/index.js +17 -17
  204. package/node_modules/@sema/gerador-python/dist/index.part02.js +3 -3
  205. package/node_modules/@sema/gerador-typescript/dist/index.part02.js +11 -11
  206. package/node_modules/@sema/nucleo/dist/diagnosticos/melhorador.js +42 -42
  207. package/node_modules/@sema/nucleo/dist/semantico/analisador.d.ts +1 -0
  208. package/node_modules/@sema/nucleo/dist/semantico/analisador.js +1 -0
  209. package/package.json +7 -2
  210. package/scripts/postinstall.mjs +148 -0
  211. package/skills/sema/SKILL.md +199 -0
  212. package/skills/sema/agents/openai.yaml +4 -0
  213. package/node_modules/@sema/gerador-cpp/dist/index.js.map +0 -1
  214. package/node_modules/@sema/gerador-css/dist/index.js.map +0 -1
  215. package/node_modules/@sema/gerador-css/dist/index.part01.js.map +0 -1
  216. package/node_modules/@sema/gerador-css/dist/index.part02.js.map +0 -1
  217. package/node_modules/@sema/gerador-dart/dist/index.js.map +0 -1
  218. package/node_modules/@sema/gerador-dotnet/dist/index.js.map +0 -1
  219. package/node_modules/@sema/gerador-html/dist/index.js.map +0 -1
  220. package/node_modules/@sema/gerador-javascript/dist/index.js.map +0 -1
  221. package/node_modules/@sema/gerador-lua/dist/index.js.map +0 -1
  222. package/node_modules/@sema/gerador-php/dist/index.js.map +0 -1
  223. package/node_modules/@sema/gerador-python/dist/index.js.map +0 -1
  224. package/node_modules/@sema/gerador-python/dist/index.part01.js.map +0 -1
  225. package/node_modules/@sema/gerador-python/dist/index.part02.js.map +0 -1
  226. package/node_modules/@sema/gerador-typescript/dist/index.js.map +0 -1
  227. package/node_modules/@sema/gerador-typescript/dist/index.part01.js.map +0 -1
  228. package/node_modules/@sema/gerador-typescript/dist/index.part02.js.map +0 -1
  229. package/node_modules/@sema/gerador-typescript/dist/index.part03.js.map +0 -1
  230. package/node_modules/@sema/nucleo/dist/ast/tipos.js.map +0 -1
  231. package/node_modules/@sema/nucleo/dist/diagnosticos/index.js.map +0 -1
  232. package/node_modules/@sema/nucleo/dist/diagnosticos/melhorador.js.map +0 -1
  233. package/node_modules/@sema/nucleo/dist/diagnosticos/snippets.js.map +0 -1
  234. package/node_modules/@sema/nucleo/dist/formatador/index.js.map +0 -1
  235. package/node_modules/@sema/nucleo/dist/formatador/index.part01.js.map +0 -1
  236. package/node_modules/@sema/nucleo/dist/formatador/index.part02.js.map +0 -1
  237. package/node_modules/@sema/nucleo/dist/index.js.map +0 -1
  238. package/node_modules/@sema/nucleo/dist/ir/conversor.js.map +0 -1
  239. package/node_modules/@sema/nucleo/dist/ir/conversor.part01.js.map +0 -1
  240. package/node_modules/@sema/nucleo/dist/ir/conversor.part02.js.map +0 -1
  241. package/node_modules/@sema/nucleo/dist/ir/conversor.part03.js.map +0 -1
  242. package/node_modules/@sema/nucleo/dist/ir/modelos.js.map +0 -1
  243. package/node_modules/@sema/nucleo/dist/lexer/lexer.js.map +0 -1
  244. package/node_modules/@sema/nucleo/dist/lexer/tokens.js.map +0 -1
  245. package/node_modules/@sema/nucleo/dist/parser/parser.declaracoes.js.map +0 -1
  246. package/node_modules/@sema/nucleo/dist/parser/parser.js.map +0 -1
  247. package/node_modules/@sema/nucleo/dist/parser/parser.modulo.js.map +0 -1
  248. package/node_modules/@sema/nucleo/dist/parser/parser.part01.js.map +0 -1
  249. package/node_modules/@sema/nucleo/dist/parser/parser.part02.js.map +0 -1
  250. package/node_modules/@sema/nucleo/dist/parser/parser.part03.js.map +0 -1
  251. package/node_modules/@sema/nucleo/dist/persistencia/contratos.js.map +0 -1
  252. package/node_modules/@sema/nucleo/dist/semantico/analisador.js.map +0 -1
  253. package/node_modules/@sema/nucleo/dist/semantico/analisador.part01.js.map +0 -1
  254. package/node_modules/@sema/nucleo/dist/semantico/analisador.part02.js.map +0 -1
  255. package/node_modules/@sema/nucleo/dist/semantico/analisador.part03.js.map +0 -1
  256. package/node_modules/@sema/nucleo/dist/semantico/analisador.part04.js.map +0 -1
  257. package/node_modules/@sema/nucleo/dist/semantico/analisador.part05.js.map +0 -1
  258. package/node_modules/@sema/nucleo/dist/semantico/analisador.part06.js.map +0 -1
  259. package/node_modules/@sema/nucleo/dist/semantico/analisador.part07.js.map +0 -1
  260. package/node_modules/@sema/nucleo/dist/semantico/analisador.part08.js.map +0 -1
  261. package/node_modules/@sema/nucleo/dist/semantico/estruturas.js.map +0 -1
  262. package/node_modules/@sema/nucleo/dist/semantico/estruturas.part01.js.map +0 -1
  263. package/node_modules/@sema/nucleo/dist/semantico/estruturas.part02.js.map +0 -1
  264. package/node_modules/@sema/nucleo/dist/semantico/orcamentoSemantico.js.map +0 -1
  265. package/node_modules/@sema/nucleo/dist/semantico/seguranca.js.map +0 -1
  266. package/node_modules/@sema/nucleo/dist/util/arquivos.js.map +0 -1
  267. package/node_modules/@sema/padroes/dist/index.js.map +0 -1
@@ -0,0 +1,516 @@
1
+ // SEMA-GOVERNED: sema.produto.governanca_ia.drift, sema.produto.governanca_ia.drift.cache.store
2
+ // Descrição: cataloga somente o plano físico do drift e compartilha uma leitura estável por arquivo.
3
+ import { createHash } from "node:crypto";
4
+ import { lstat, open, readdir, realpath } from "node:fs/promises";
5
+ import path from "node:path";
6
+ const CONCORRENCIA_PADRAO = 8;
7
+ const CONCORRENCIA_MAXIMA = 64;
8
+ function emitirEvento(observador, evento) {
9
+ try {
10
+ observador?.(evento);
11
+ }
12
+ catch {
13
+ // Observabilidade nunca altera o resultado funcional do drift.
14
+ }
15
+ }
16
+ function normalizarConcorrencia(valor) {
17
+ if (!Number.isFinite(valor)) {
18
+ return CONCORRENCIA_PADRAO;
19
+ }
20
+ return Math.max(1, Math.min(CONCORRENCIA_MAXIMA, Math.trunc(valor)));
21
+ }
22
+ function normalizarExtensao(extensao) {
23
+ const limpa = extensao.trim().toLowerCase();
24
+ if (!limpa) {
25
+ return limpa;
26
+ }
27
+ return limpa.startsWith(".") ? limpa : `.${limpa}`;
28
+ }
29
+ function ehFiltroCatalogoDrift(valor) {
30
+ return !Array.isArray(valor);
31
+ }
32
+ function chaveCaminho(caminho) {
33
+ const normalizado = path.normalize(path.resolve(caminho));
34
+ return process.platform === "win32" ? normalizado.toLowerCase() : normalizado;
35
+ }
36
+ function caminhoEstaDentro(raiz, alvo) {
37
+ const relativo = path.relative(path.resolve(raiz), path.resolve(alvo));
38
+ return relativo === "" || (relativo !== ".."
39
+ && !relativo.startsWith(`..${path.sep}`)
40
+ && !path.isAbsolute(relativo));
41
+ }
42
+ function erroEhAusencia(erro) {
43
+ return ["ENOENT", "ENOTDIR"].includes(erro.code ?? "");
44
+ }
45
+ function assinaturaDiretorio(info) {
46
+ return {
47
+ mtimeNs: info.mtimeNs,
48
+ ctimeNs: info.ctimeNs,
49
+ dev: info.dev,
50
+ ino: info.ino,
51
+ };
52
+ }
53
+ function assinaturasDiretorioIguais(a, b) {
54
+ return a.mtimeNs === b.mtimeNs
55
+ && a.ctimeNs === b.ctimeNs
56
+ && a.dev === b.dev
57
+ && a.ino === b.ino;
58
+ }
59
+ function identidadeArquivoEstavel(a, b) {
60
+ return a.isFile()
61
+ && b.isFile()
62
+ && !a.isSymbolicLink()
63
+ && !b.isSymbolicLink()
64
+ && a.nlink === 1n
65
+ && b.nlink === 1n
66
+ && a.dev === b.dev
67
+ && a.ino === b.ino
68
+ && a.size === b.size
69
+ && a.mtimeNs === b.mtimeNs
70
+ && a.ctimeNs === b.ctimeNs;
71
+ }
72
+ function criarIdentidadeArquivoCatalogado(caminhoReal, informacao) {
73
+ return {
74
+ caminhoReal: path.resolve(caminhoReal),
75
+ dev: informacao.dev,
76
+ ino: informacao.ino,
77
+ nlink: informacao.nlink,
78
+ size: informacao.size,
79
+ mtimeNs: informacao.mtimeNs,
80
+ ctimeNs: informacao.ctimeNs,
81
+ };
82
+ }
83
+ function identidadeCatalogadaCorresponde(identidade, caminhoReal, informacao) {
84
+ return chaveCaminho(identidade.caminhoReal) === chaveCaminho(caminhoReal)
85
+ && informacao.isFile()
86
+ && !informacao.isSymbolicLink()
87
+ && identidade.nlink === 1n
88
+ && informacao.nlink === 1n
89
+ && identidade.dev === informacao.dev
90
+ && identidade.ino === informacao.ino
91
+ && identidade.size === informacao.size
92
+ && identidade.mtimeNs === informacao.mtimeNs
93
+ && identidade.ctimeNs === informacao.ctimeNs;
94
+ }
95
+ function chavesFisicasArquivo(identidade) {
96
+ const chaves = [`real:${chaveCaminho(identidade.caminhoReal)}`];
97
+ if (identidade.dev !== 0n || identidade.ino !== 0n) {
98
+ chaves.push(`id:${identidade.dev.toString()}:${identidade.ino.toString()}`);
99
+ }
100
+ return chaves;
101
+ }
102
+ function mesmoObjetoFisico(a, b) {
103
+ const possuiIdentidadeInode = (a.dev !== 0n || a.ino !== 0n) && (b.dev !== 0n || b.ino !== 0n);
104
+ return possuiIdentidadeInode
105
+ ? a.dev === b.dev && a.ino === b.ino
106
+ : chaveCaminho(a.caminhoReal) === chaveCaminho(b.caminhoReal);
107
+ }
108
+ async function mapearComLimite(itens, limite, executar) {
109
+ if (itens.length === 0) {
110
+ return [];
111
+ }
112
+ const resultados = new Array(itens.length);
113
+ let proximoIndice = 0;
114
+ const trabalhador = async () => {
115
+ for (;;) {
116
+ const indice = proximoIndice;
117
+ proximoIndice += 1;
118
+ if (indice >= itens.length) {
119
+ return;
120
+ }
121
+ resultados[indice] = await executar(itens[indice]);
122
+ }
123
+ };
124
+ await Promise.all(Array.from({ length: Math.min(limite, itens.length) }, () => trabalhador()));
125
+ return resultados;
126
+ }
127
+ class CatalogoDriftImplementacao {
128
+ baseDiretorio;
129
+ raizes;
130
+ registros = new Map();
131
+ registrosFisicos = new Map();
132
+ conteudos = new Map();
133
+ extensoesPermitidas;
134
+ concorrencia;
135
+ observador;
136
+ baseDiretorioReal;
137
+ contadores = {
138
+ diretoriosVisitados: 0,
139
+ arquivosCatalogados: 0,
140
+ leiturasConteudo: 0,
141
+ bytesLidos: 0,
142
+ acertosMemoriaConteudo: 0,
143
+ origem: "plano_explicito",
144
+ };
145
+ constructor(opcoes) {
146
+ this.baseDiretorio = path.resolve(opcoes.baseDiretorio ?? process.cwd());
147
+ this.baseDiretorioReal = realpath(this.baseDiretorio);
148
+ this.raizes = [...new Map((opcoes.raizes ?? [])
149
+ .map((raiz) => path.resolve(this.baseDiretorio, raiz))
150
+ .filter((raiz) => caminhoEstaDentro(this.baseDiretorio, raiz))
151
+ .map((raiz) => [chaveCaminho(raiz), raiz])).values()].sort((a, b) => a.localeCompare(b, "pt-BR"));
152
+ const extensoes = opcoes.extensoes
153
+ ?.map(normalizarExtensao)
154
+ .filter(Boolean);
155
+ this.extensoesPermitidas = extensoes?.length
156
+ ? new Set(extensoes)
157
+ : undefined;
158
+ this.concorrencia = normalizarConcorrencia(opcoes.concorrencia);
159
+ this.observador = opcoes.observador;
160
+ }
161
+ async construir(arquivosExplicitos, diretoriosIgnorados) {
162
+ await this.baseDiretorioReal;
163
+ if (this.raizes.length > 0) {
164
+ this.contadores.origem = "caminhada";
165
+ await this.caminharRaizes(diretoriosIgnorados);
166
+ }
167
+ await this.incluir(arquivosExplicitos);
168
+ }
169
+ async incluir(arquivosExplicitos) {
170
+ const explicitos = [...new Map(arquivosExplicitos
171
+ .map((arquivo) => path.resolve(this.baseDiretorio, arquivo))
172
+ .map((arquivo) => [chaveCaminho(arquivo), arquivo])).values()].sort((a, b) => a.localeCompare(b, "pt-BR"));
173
+ const sondagens = await mapearComLimite(explicitos, this.concorrencia, async (arquivo) => this.sondarArquivoSeguro(arquivo));
174
+ for (const sondagem of sondagens
175
+ .filter((item) => Boolean(item))
176
+ .sort((a, b) => a.caminho.localeCompare(b.caminho, "pt-BR"))) {
177
+ this.adicionarArquivo(sondagem, true);
178
+ }
179
+ }
180
+ listar(extensoesOuFiltro = [], raizes) {
181
+ if (ehFiltroCatalogoDrift(extensoesOuFiltro)) {
182
+ return this.listarEntradas(extensoesOuFiltro).map((arquivo) => arquivo.caminho);
183
+ }
184
+ const extensoes = extensoesOuFiltro.length ? extensoesOuFiltro : undefined;
185
+ if (!raizes?.length) {
186
+ return this.listarEntradas({ extensoes }).map((arquivo) => arquivo.caminho);
187
+ }
188
+ const raizesAbsolutas = raizes.map((raiz) => path.resolve(this.baseDiretorio, raiz));
189
+ return [...new Map(raizesAbsolutas.flatMap((raiz) => this.listarEntradas({ extensoes, raiz }).map((arquivo) => [chaveCaminho(arquivo.caminho), arquivo.caminho]))).values()].sort((a, b) => a.localeCompare(b, "pt-BR"));
190
+ }
191
+ listarEntradas(filtro = {}) {
192
+ const extensoes = filtro.extensoes
193
+ ? new Set(filtro.extensoes.map(normalizarExtensao).filter(Boolean))
194
+ : undefined;
195
+ const raiz = filtro.raiz
196
+ ? path.resolve(this.baseDiretorio, filtro.raiz)
197
+ : undefined;
198
+ return [...new Set(this.registros.values())]
199
+ .filter((registro) => !extensoes || extensoes.has(registro.extensao))
200
+ .filter((registro) => !raiz || [...registro.aliases].some((alias) => caminhoEstaDentro(raiz, alias)))
201
+ .map((registro) => ({
202
+ caminho: registro.caminho,
203
+ extensao: registro.extensao,
204
+ explicito: registro.explicito,
205
+ raizes: [...registro.raizes].sort((a, b) => a.localeCompare(b, "pt-BR")),
206
+ }))
207
+ .sort((a, b) => a.caminho.localeCompare(b.caminho, "pt-BR"));
208
+ }
209
+ listarPorExtensoes(extensoes, raiz) {
210
+ return raiz ? this.listar(extensoes, [raiz]) : this.listar(extensoes);
211
+ }
212
+ listarPorRaiz(raiz, extensoes) {
213
+ return this.listar(extensoes, [raiz]);
214
+ }
215
+ arquivosCatalogados() {
216
+ return this.listar();
217
+ }
218
+ contem(caminho) {
219
+ return this.registros.has(chaveCaminho(path.resolve(this.baseDiretorio, caminho)));
220
+ }
221
+ ler(caminho) {
222
+ const absoluto = path.resolve(this.baseDiretorio, caminho);
223
+ const chave = chaveCaminho(absoluto);
224
+ const registro = this.registros.get(chave);
225
+ if (!registro) {
226
+ const descricao = caminhoEstaDentro(this.baseDiretorio, absoluto)
227
+ ? absoluto
228
+ : `[fora_do_workspace]/${path.basename(absoluto)}`;
229
+ return Promise.reject(new Error(`Arquivo fora do plano explicito do drift: ${descricao}`));
230
+ }
231
+ const existente = this.conteudos.get(registro);
232
+ if (existente) {
233
+ this.contadores.acertosMemoriaConteudo += 1;
234
+ return existente;
235
+ }
236
+ const leitura = this.lerFisicamente(registro);
237
+ this.conteudos.set(registro, leitura);
238
+ void leitura.catch(() => {
239
+ if (this.conteudos.get(registro) === leitura) {
240
+ this.conteudos.delete(registro);
241
+ }
242
+ });
243
+ return leitura;
244
+ }
245
+ async lerTexto(caminho) {
246
+ return (await this.ler(caminho)).texto;
247
+ }
248
+ async digest(caminho) {
249
+ return (await this.ler(caminho)).digest;
250
+ }
251
+ emitir(tipo, arquivo) {
252
+ emitirEvento(this.observador, {
253
+ tipo,
254
+ caminho: arquivo ? path.resolve(this.baseDiretorio, arquivo) : undefined,
255
+ });
256
+ }
257
+ metricas() {
258
+ return { ...this.contadores };
259
+ }
260
+ async caminharRaizes(diretoriosIgnorados) {
261
+ let nivel = [...this.raizes];
262
+ const visitados = new Set();
263
+ while (nivel.length > 0) {
264
+ const nivelUnico = [...new Map(nivel.map((diretorio) => [chaveCaminho(diretorio), diretorio])).values()]
265
+ .filter((diretorio) => {
266
+ const chave = chaveCaminho(diretorio);
267
+ if (visitados.has(chave)) {
268
+ return false;
269
+ }
270
+ visitados.add(chave);
271
+ return true;
272
+ })
273
+ .sort((a, b) => a.localeCompare(b, "pt-BR"));
274
+ const proximos = await mapearComLimite(nivelUnico, this.concorrencia, async (diretorio) => this.visitarDiretorio(diretorio, diretoriosIgnorados));
275
+ nivel = proximos.flat();
276
+ }
277
+ }
278
+ async visitarDiretorio(diretorio, diretoriosIgnorados) {
279
+ if (!await this.caminhoPermaneceNoWorkspace(diretorio)) {
280
+ return [];
281
+ }
282
+ let informacao;
283
+ try {
284
+ informacao = await lstat(diretorio, { bigint: true });
285
+ }
286
+ catch (erro) {
287
+ if (erroEhAusencia(erro)) {
288
+ return [];
289
+ }
290
+ throw erro;
291
+ }
292
+ if (informacao.isSymbolicLink()) {
293
+ return [];
294
+ }
295
+ if (informacao.isFile()) {
296
+ const sondagem = await this.sondarArquivoSeguro(diretorio);
297
+ if (sondagem) {
298
+ this.adicionarArquivo(sondagem, false);
299
+ }
300
+ return [];
301
+ }
302
+ if (!informacao.isDirectory()) {
303
+ return [];
304
+ }
305
+ const entradas = await readdir(diretorio, { withFileTypes: true });
306
+ const informacaoDepois = await lstat(diretorio, { bigint: true });
307
+ if (!informacaoDepois.isDirectory()
308
+ || informacaoDepois.isSymbolicLink()
309
+ || !assinaturasDiretorioIguais(assinaturaDiretorio(informacao), assinaturaDiretorio(informacaoDepois))) {
310
+ throw new Error(`catalogo_diretorio_instavel:${diretorio}`);
311
+ }
312
+ this.contadores.diretoriosVisitados += 1;
313
+ emitirEvento(this.observador, {
314
+ tipo: "catalog.visit",
315
+ caminho: diretorio,
316
+ categoria: "diretorio",
317
+ });
318
+ const proximos = [];
319
+ const arquivos = [];
320
+ for (const entrada of entradas.sort((a, b) => a.name.localeCompare(b.name, "pt-BR"))) {
321
+ if (entrada.isSymbolicLink()) {
322
+ continue;
323
+ }
324
+ const caminhoAtual = path.join(diretorio, entrada.name);
325
+ if (entrada.isDirectory()) {
326
+ if (!diretoriosIgnorados.has(entrada.name.toLowerCase())) {
327
+ proximos.push(caminhoAtual);
328
+ }
329
+ }
330
+ else if (entrada.isFile()) {
331
+ arquivos.push(caminhoAtual);
332
+ }
333
+ }
334
+ const sondagens = await mapearComLimite(arquivos, this.concorrencia, async (arquivo) => this.sondarArquivoSeguro(arquivo));
335
+ for (const sondagem of sondagens
336
+ .filter((item) => Boolean(item))
337
+ .sort((a, b) => a.caminho.localeCompare(b.caminho, "pt-BR"))) {
338
+ this.adicionarArquivo(sondagem, false);
339
+ }
340
+ return proximos;
341
+ }
342
+ adicionarArquivo(sondagem, explicito) {
343
+ const absoluto = path.resolve(sondagem.caminho);
344
+ const extensao = path.extname(absoluto).toLowerCase();
345
+ if (!explicito && this.extensoesPermitidas && !this.extensoesPermitidas.has(extensao)) {
346
+ return;
347
+ }
348
+ const chave = chaveCaminho(absoluto);
349
+ const chavesFisicas = chavesFisicasArquivo(sondagem.identidade);
350
+ const existentePorCaminho = this.registros.get(chave);
351
+ if (existentePorCaminho && !mesmoObjetoFisico(existentePorCaminho.identidade, sondagem.identidade)) {
352
+ throw new Error(`Arquivo catalogado mudou de identidade fisica: ${absoluto}`);
353
+ }
354
+ const existente = existentePorCaminho
355
+ ?? chavesFisicas.map((chaveFisica) => this.registrosFisicos.get(chaveFisica)).find(Boolean);
356
+ const raizes = this.raizes.filter((raiz) => caminhoEstaDentro(raiz, absoluto));
357
+ if (existente) {
358
+ existente.explicito = existente.explicito || explicito;
359
+ existente.aliases.add(absoluto);
360
+ this.registros.set(chave, existente);
361
+ for (const raiz of raizes) {
362
+ existente.raizes.add(raiz);
363
+ }
364
+ for (const chaveFisica of chavesFisicas) {
365
+ this.registrosFisicos.set(chaveFisica, existente);
366
+ }
367
+ if (absoluto.localeCompare(existente.caminho, "pt-BR") < 0) {
368
+ existente.caminho = absoluto;
369
+ existente.extensao = extensao;
370
+ existente.identidade = sondagem.identidade;
371
+ }
372
+ return;
373
+ }
374
+ const registro = {
375
+ caminho: absoluto,
376
+ extensao,
377
+ explicito,
378
+ raizes: new Set(raizes),
379
+ aliases: new Set([absoluto]),
380
+ identidade: sondagem.identidade,
381
+ };
382
+ this.registros.set(chave, registro);
383
+ for (const chaveFisica of chavesFisicas) {
384
+ this.registrosFisicos.set(chaveFisica, registro);
385
+ }
386
+ this.contadores.arquivosCatalogados += 1;
387
+ emitirEvento(this.observador, {
388
+ tipo: "catalog.visit",
389
+ caminho: absoluto,
390
+ categoria: "arquivo",
391
+ });
392
+ }
393
+ async sondarArquivoSeguro(caminho) {
394
+ const absoluto = path.resolve(caminho);
395
+ if (!caminhoEstaDentro(this.baseDiretorio, absoluto)) {
396
+ return undefined;
397
+ }
398
+ try {
399
+ const informacaoAntes = await lstat(absoluto, { bigint: true });
400
+ if (!informacaoAntes.isFile() || informacaoAntes.isSymbolicLink() || informacaoAntes.nlink !== 1n) {
401
+ return undefined;
402
+ }
403
+ const [baseReal, caminhoReal] = await Promise.all([
404
+ this.baseDiretorioReal,
405
+ realpath(absoluto),
406
+ ]);
407
+ const informacaoDepois = await lstat(absoluto, { bigint: true });
408
+ if (!caminhoEstaDentro(baseReal, caminhoReal)
409
+ || !identidadeArquivoEstavel(informacaoAntes, informacaoDepois)) {
410
+ return undefined;
411
+ }
412
+ return {
413
+ caminho: absoluto,
414
+ identidade: criarIdentidadeArquivoCatalogado(caminhoReal, informacaoDepois),
415
+ };
416
+ }
417
+ catch (erro) {
418
+ if (erroEhAusencia(erro)) {
419
+ return undefined;
420
+ }
421
+ throw erro;
422
+ }
423
+ }
424
+ async lerFisicamente(registro) {
425
+ const caminho = registro.caminho;
426
+ const informacaoAntes = await lstat(caminho, { bigint: true });
427
+ const [baseReal, caminhoRealAntes] = await Promise.all([
428
+ this.baseDiretorioReal,
429
+ realpath(caminho),
430
+ ]);
431
+ if (!caminhoEstaDentro(baseReal, caminhoRealAntes)
432
+ || !identidadeCatalogadaCorresponde(registro.identidade, caminhoRealAntes, informacaoAntes)) {
433
+ throw new Error(`Arquivo catalogado mudou entre catalogacao e primeira leitura: ${caminho}`);
434
+ }
435
+ const handle = await open(caminho, "r");
436
+ let bytes;
437
+ try {
438
+ const informacaoHandleAntes = await handle.stat({ bigint: true });
439
+ emitirEvento(this.observador, {
440
+ tipo: "content.open",
441
+ caminho,
442
+ categoria: "arquivo",
443
+ });
444
+ const [informacaoCaminhoAberto, caminhoRealAberto] = await Promise.all([
445
+ lstat(caminho, { bigint: true }),
446
+ realpath(caminho),
447
+ ]);
448
+ if (!caminhoEstaDentro(baseReal, caminhoRealAberto)
449
+ || !identidadeCatalogadaCorresponde(registro.identidade, caminhoRealAberto, informacaoCaminhoAberto)
450
+ || !identidadeArquivoEstavel(informacaoAntes, informacaoHandleAntes)
451
+ || !identidadeArquivoEstavel(informacaoHandleAntes, informacaoCaminhoAberto)) {
452
+ throw new Error(`Arquivo catalogado mudou durante abertura segura: ${caminho}`);
453
+ }
454
+ bytes = await handle.readFile();
455
+ const [informacaoHandleDepois, informacaoCaminhoDepois, caminhoRealDepois] = await Promise.all([
456
+ handle.stat({ bigint: true }),
457
+ lstat(caminho, { bigint: true }),
458
+ realpath(caminho),
459
+ ]);
460
+ if (!caminhoEstaDentro(baseReal, caminhoRealDepois)
461
+ || !identidadeCatalogadaCorresponde(registro.identidade, caminhoRealDepois, informacaoCaminhoDepois)
462
+ || !identidadeArquivoEstavel(informacaoHandleAntes, informacaoHandleDepois)
463
+ || !identidadeArquivoEstavel(informacaoHandleDepois, informacaoCaminhoDepois)) {
464
+ throw new Error(`Arquivo catalogado mudou durante leitura segura: ${caminho}`);
465
+ }
466
+ }
467
+ finally {
468
+ await handle.close().catch(() => undefined);
469
+ }
470
+ const digest = `sha256:${createHash("sha256").update(bytes).digest("hex")}`;
471
+ this.contadores.leiturasConteudo += 1;
472
+ this.contadores.bytesLidos += bytes.byteLength;
473
+ emitirEvento(this.observador, {
474
+ tipo: "content.read",
475
+ caminho,
476
+ categoria: "arquivo",
477
+ bytes: bytes.byteLength,
478
+ digest,
479
+ });
480
+ return {
481
+ caminho,
482
+ bytes,
483
+ texto: bytes.toString("utf8"),
484
+ digest,
485
+ };
486
+ }
487
+ async caminhoPermaneceNoWorkspace(caminho) {
488
+ const absoluto = path.resolve(caminho);
489
+ if (!caminhoEstaDentro(this.baseDiretorio, absoluto)) {
490
+ return false;
491
+ }
492
+ try {
493
+ const [baseReal, caminhoReal] = await Promise.all([
494
+ this.baseDiretorioReal,
495
+ realpath(absoluto),
496
+ ]);
497
+ return caminhoEstaDentro(baseReal, caminhoReal);
498
+ }
499
+ catch (erro) {
500
+ if (erroEhAusencia(erro)) {
501
+ return false;
502
+ }
503
+ throw erro;
504
+ }
505
+ }
506
+ }
507
+ export async function criarCatalogoDrift(opcoes) {
508
+ const ignoradosOrigem = opcoes.diretoriosIgnorados ?? [];
509
+ const ignorados = new Set([...ignoradosOrigem]
510
+ .map((diretorio) => diretorio.trim().toLowerCase())
511
+ .filter(Boolean));
512
+ const catalogo = new CatalogoDriftImplementacao(opcoes);
513
+ await catalogo.construir(opcoes.arquivos ?? [], ignorados);
514
+ return catalogo;
515
+ }
516
+ //# sourceMappingURL=driftCatalogo.js.map
@@ -0,0 +1,21 @@
1
+ import type { ContextoProjetoCarregado } from "./projeto.js";
2
+ import type { ConfiguracaoEscopoDriftAplicada, EscopoDriftReal } from "./drift.part01.js";
3
+ import type { CatalogoDrift } from "./driftCatalogo.js";
4
+ export { extrairReferenciasLocaisDrift } from "./driftEscopoReferencias.js";
5
+ export type EstrategiaEscopoDrift = "arquivos_vinculados" | "projeto";
6
+ export type CoberturaEscopoDrift = "completa" | "parcial";
7
+ export interface PlanoEscopoDrift {
8
+ escopo: EscopoDriftReal;
9
+ estrategia: EstrategiaEscopoDrift;
10
+ arquivos: string[];
11
+ arquivosDeclarados: string[];
12
+ arquivosInferidos: string[];
13
+ arquivosAusentes: string[];
14
+ diretorios: string[];
15
+ modulos: string[];
16
+ cobertura: CoberturaEscopoDrift;
17
+ bloqueios: string[];
18
+ dependencias: Record<string, string[]>;
19
+ }
20
+ export declare function planejarEscopoDrift(contexto: ContextoProjetoCarregado, configuracao: ConfiguracaoEscopoDriftAplicada): Promise<PlanoEscopoDrift>;
21
+ export declare function expandirDependenciasPlanoDrift(contexto: ContextoProjetoCarregado, plano: PlanoEscopoDrift, catalogo: CatalogoDrift): Promise<PlanoEscopoDrift>;