@semacode/cli 1.3.5 → 1.3.6
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.
- package/dist/cpp-symbols.d.ts +10 -0
- package/dist/cpp-symbols.js.map +1 -0
- package/dist/dotnet-http.d.ts +23 -0
- package/dist/dotnet-http.js.map +1 -0
- package/dist/drift.d.ts +118 -0
- package/dist/drift.js.map +1 -0
- package/dist/go-http.d.ts +23 -0
- package/dist/go-http.js.map +1 -0
- package/dist/importador.d.ts +29 -0
- package/dist/importador.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js.map +1 -0
- package/dist/java-http.d.ts +23 -0
- package/dist/java-http.js.map +1 -0
- package/dist/lua-symbols.d.ts +8 -0
- package/dist/lua-symbols.js.map +1 -0
- package/dist/projeto.d.ts +48 -0
- package/dist/projeto.js.map +1 -0
- package/dist/python-http.d.ts +23 -0
- package/dist/python-http.js.map +1 -0
- package/dist/rust-http.d.ts +23 -0
- package/dist/rust-http.js.map +1 -0
- package/dist/tipos.d.ts +3 -0
- package/dist/tipos.js.map +1 -0
- package/dist/typescript-http.d.ts +35 -0
- package/dist/typescript-http.js.map +1 -0
- package/node_modules/@sema/gerador-css/dist/index.d.ts +3 -0
- package/node_modules/@sema/gerador-css/dist/index.js +592 -0
- package/node_modules/@sema/gerador-css/dist/index.js.map +1 -0
- package/node_modules/@sema/gerador-css/package.json +14 -0
- package/node_modules/@sema/gerador-css/src/index.ts +605 -0
- package/node_modules/@sema/gerador-css/tsconfig.json +13 -0
- package/node_modules/@sema/gerador-css/tsconfig.tsbuildinfo +1 -0
- package/node_modules/@sema/gerador-dart/dist/index.d.ts +3 -0
- package/node_modules/@sema/gerador-dart/dist/index.js +44 -0
- package/node_modules/@sema/gerador-dart/dist/index.js.map +1 -0
- package/node_modules/@sema/gerador-dart/package.json +14 -0
- package/node_modules/@sema/gerador-dart/src/index.ts +52 -0
- package/node_modules/@sema/gerador-dart/tsconfig.json +13 -0
- package/node_modules/@sema/gerador-dart/tsconfig.tsbuildinfo +1 -0
- package/node_modules/@sema/gerador-html/dist/index.d.ts +3 -0
- package/node_modules/@sema/gerador-html/dist/index.js +163 -0
- package/node_modules/@sema/gerador-html/dist/index.js.map +1 -0
- package/node_modules/@sema/gerador-html/package.json +14 -0
- package/node_modules/@sema/gerador-html/src/index.ts +185 -0
- package/node_modules/@sema/gerador-html/tsconfig.json +13 -0
- package/node_modules/@sema/gerador-html/tsconfig.tsbuildinfo +1 -0
- package/node_modules/@sema/gerador-javascript/dist/index.d.ts +3 -0
- package/node_modules/@sema/gerador-javascript/dist/index.js +421 -0
- package/node_modules/@sema/gerador-javascript/dist/index.js.map +1 -0
- package/node_modules/@sema/gerador-javascript/package.json +14 -0
- package/node_modules/@sema/gerador-javascript/src/index.ts +461 -0
- package/node_modules/@sema/gerador-javascript/tsconfig.json +13 -0
- package/node_modules/@sema/gerador-javascript/tsconfig.tsbuildinfo +1 -0
- package/node_modules/@sema/gerador-lua/dist/index.d.ts +3 -0
- package/node_modules/@sema/gerador-lua/dist/index.js +328 -0
- package/node_modules/@sema/gerador-lua/dist/index.js.map +1 -0
- package/node_modules/@sema/gerador-lua/package.json +14 -0
- package/node_modules/@sema/gerador-lua/src/index.d.ts +3 -0
- package/node_modules/@sema/gerador-lua/src/index.js.map +1 -0
- package/node_modules/@sema/gerador-lua/src/index.ts +359 -0
- package/node_modules/@sema/gerador-lua/tsconfig.json +13 -0
- package/node_modules/@sema/gerador-lua/tsconfig.tsbuildinfo +1 -0
- package/node_modules/@sema/gerador-python/dist/index.d.ts +6 -0
- package/node_modules/@sema/gerador-python/dist/index.js +628 -0
- package/node_modules/@sema/gerador-python/dist/index.js.map +1 -0
- package/node_modules/@sema/gerador-python/package.json +14 -0
- package/node_modules/@sema/gerador-python/src/index.ts +706 -0
- package/node_modules/@sema/gerador-python/tsconfig.json +13 -0
- package/node_modules/@sema/gerador-python/tsconfig.tsbuildinfo +1 -0
- package/node_modules/@sema/gerador-typescript/dist/index.d.ts +6 -0
- package/node_modules/@sema/gerador-typescript/dist/index.js +656 -0
- package/node_modules/@sema/gerador-typescript/dist/index.js.map +1 -0
- package/node_modules/@sema/gerador-typescript/package.json +14 -0
- package/node_modules/@sema/gerador-typescript/src/index.ts +728 -0
- package/node_modules/@sema/gerador-typescript/tsconfig.json +13 -0
- package/node_modules/@sema/gerador-typescript/tsconfig.tsbuildinfo +1 -0
- package/node_modules/@sema/nucleo/dist/ast/tipos.d.ts +122 -0
- package/node_modules/@sema/nucleo/dist/ast/tipos.js +2 -0
- package/node_modules/@sema/nucleo/dist/ast/tipos.js.map +1 -0
- package/node_modules/@sema/nucleo/dist/diagnosticos/index.d.ts +21 -0
- package/node_modules/@sema/nucleo/dist/diagnosticos/index.js +12 -0
- package/node_modules/@sema/nucleo/dist/diagnosticos/index.js.map +1 -0
- package/node_modules/@sema/nucleo/dist/formatador/index.d.ts +9 -0
- package/node_modules/@sema/nucleo/dist/formatador/index.js +445 -0
- package/node_modules/@sema/nucleo/dist/formatador/index.js.map +1 -0
- package/node_modules/@sema/nucleo/dist/index.d.ts +34 -0
- package/node_modules/@sema/nucleo/dist/index.js +95 -0
- package/node_modules/@sema/nucleo/dist/index.js.map +1 -0
- package/node_modules/@sema/nucleo/dist/ir/conversor.d.ts +5 -0
- package/node_modules/@sema/nucleo/dist/ir/conversor.js +781 -0
- package/node_modules/@sema/nucleo/dist/ir/conversor.js.map +1 -0
- package/node_modules/@sema/nucleo/dist/ir/modelos.d.ts +285 -0
- package/node_modules/@sema/nucleo/dist/ir/modelos.js +2 -0
- package/node_modules/@sema/nucleo/dist/ir/modelos.js.map +1 -0
- package/node_modules/@sema/nucleo/dist/lexer/lexer.d.ts +7 -0
- package/node_modules/@sema/nucleo/dist/lexer/lexer.js +122 -0
- package/node_modules/@sema/nucleo/dist/lexer/lexer.js.map +1 -0
- package/node_modules/@sema/nucleo/dist/lexer/tokens.d.ts +8 -0
- package/node_modules/@sema/nucleo/dist/lexer/tokens.js +46 -0
- package/node_modules/@sema/nucleo/dist/lexer/tokens.js.map +1 -0
- package/node_modules/@sema/nucleo/dist/parser/parser.d.ts +9 -0
- package/node_modules/@sema/nucleo/dist/parser/parser.js +656 -0
- package/node_modules/@sema/nucleo/dist/parser/parser.js.map +1 -0
- package/node_modules/@sema/nucleo/dist/semantico/analisador.d.ts +57 -0
- package/node_modules/@sema/nucleo/dist/semantico/analisador.js +1497 -0
- package/node_modules/@sema/nucleo/dist/semantico/analisador.js.map +1 -0
- package/node_modules/@sema/nucleo/dist/semantico/estruturas.d.ts +104 -0
- package/node_modules/@sema/nucleo/dist/semantico/estruturas.js +445 -0
- package/node_modules/@sema/nucleo/dist/semantico/estruturas.js.map +1 -0
- package/node_modules/@sema/nucleo/dist/semantico/seguranca.d.ts +91 -0
- package/node_modules/@sema/nucleo/dist/semantico/seguranca.js +258 -0
- package/node_modules/@sema/nucleo/dist/semantico/seguranca.js.map +1 -0
- package/node_modules/@sema/nucleo/dist/util/arquivos.d.ts +2 -0
- package/node_modules/@sema/nucleo/dist/util/arquivos.js +25 -0
- package/node_modules/@sema/nucleo/dist/util/arquivos.js.map +1 -0
- package/node_modules/@sema/nucleo/package.json +10 -0
- package/node_modules/@sema/nucleo/src/ast/tipos.ts +191 -0
- package/node_modules/@sema/nucleo/src/diagnosticos/index.ts +43 -0
- package/node_modules/@sema/nucleo/src/formatador/index.ts +507 -0
- package/node_modules/@sema/nucleo/src/index.ts +133 -0
- package/node_modules/@sema/nucleo/src/ir/conversor.ts +912 -0
- package/node_modules/@sema/nucleo/src/ir/modelos.ts +331 -0
- package/node_modules/@sema/nucleo/src/lexer/lexer.ts +166 -0
- package/node_modules/@sema/nucleo/src/lexer/tokens.ts +64 -0
- package/node_modules/@sema/nucleo/src/parser/gramatica.ebnf +39 -0
- package/node_modules/@sema/nucleo/src/parser/parser.ts +790 -0
- package/node_modules/@sema/nucleo/src/semantico/analisador.ts +2692 -0
- package/node_modules/@sema/nucleo/src/semantico/estruturas.ts +632 -0
- package/node_modules/@sema/nucleo/src/semantico/seguranca.ts +362 -0
- package/node_modules/@sema/nucleo/src/util/arquivos.ts +28 -0
- package/node_modules/@sema/nucleo/tsconfig.json +9 -0
- package/node_modules/@sema/nucleo/tsconfig.tsbuildinfo +1 -0
- package/node_modules/@sema/padroes/dist/index.d.ts +23 -0
- package/node_modules/@sema/padroes/dist/index.js +210 -0
- package/node_modules/@sema/padroes/dist/index.js.map +1 -0
- package/node_modules/@sema/padroes/package.json +10 -0
- package/node_modules/@sema/padroes/src/index.ts +251 -0
- package/node_modules/@sema/padroes/tsconfig.json +9 -0
- package/node_modules/@sema/padroes/tsconfig.tsbuildinfo +1 -0
- package/package.json +1 -1
- package/README.md +0 -73
- package/logo.png +0 -0
- package/semacode-cli-1.3.1.tgz +0 -0
- package/src/cpp-symbols.ts +0 -82
- package/src/dotnet-http.ts +0 -355
- package/src/drift.ts +0 -2455
- package/src/go-http.ts +0 -118
- package/src/importador.ts +0 -3448
- package/src/index.ts +0 -4476
- package/src/java-http.ts +0 -247
- package/src/projeto.ts +0 -810
- package/src/python-http.ts +0 -258
- package/src/rust-http.ts +0 -125
- package/src/tipos.ts +0 -22
- package/src/typescript-http.ts +0 -1076
- package/tsconfig.json +0 -20
package/src/index.ts
DELETED
|
@@ -1,4476 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { mkdir, readFile, stat, writeFile } from "node:fs/promises";
|
|
3
|
-
import path from "node:path";
|
|
4
|
-
import { spawnSync } from "node:child_process";
|
|
5
|
-
import { fileURLToPath } from "node:url";
|
|
6
|
-
import pacoteCli from "../package.json" with { type: "json" };
|
|
7
|
-
import {
|
|
8
|
-
compilarCodigo,
|
|
9
|
-
formatarCodigo,
|
|
10
|
-
formatarDiagnosticos,
|
|
11
|
-
lerArquivoTexto,
|
|
12
|
-
temErros,
|
|
13
|
-
type IrModulo,
|
|
14
|
-
} from "@sema/nucleo";
|
|
15
|
-
import { descreverEstruturaModulo, type AlvoGeracao, type FrameworkGeracao } from "@sema/padroes";
|
|
16
|
-
import { gerarDart } from "@sema/gerador-dart";
|
|
17
|
-
import { gerarLua } from "@sema/gerador-lua";
|
|
18
|
-
import { gerarPython } from "@sema/gerador-python";
|
|
19
|
-
import { gerarTypeScript } from "@sema/gerador-typescript";
|
|
20
|
-
import { gerarJavaScript } from "@sema/gerador-javascript";
|
|
21
|
-
import { gerarHtml } from "@sema/gerador-html";
|
|
22
|
-
import { gerarCss } from "@sema/gerador-css";
|
|
23
|
-
import {
|
|
24
|
-
carregarConfiguracaoProjeto,
|
|
25
|
-
carregarProjeto,
|
|
26
|
-
resolverAlvoPadrao,
|
|
27
|
-
resolverAlvosVerificacao,
|
|
28
|
-
resolverEstruturaSaidaPadrao,
|
|
29
|
-
resolverFrameworkPadrao,
|
|
30
|
-
resolverSaidaPadrao,
|
|
31
|
-
type ContextoProjetoCarregado,
|
|
32
|
-
} from "./projeto.js";
|
|
33
|
-
import type { EstruturaSaida } from "./tipos.js";
|
|
34
|
-
import { importarProjetoLegado, resumoImportacao, type FonteImportacao } from "./importador.js";
|
|
35
|
-
import { analisarDriftLegado } from "./drift.js";
|
|
36
|
-
|
|
37
|
-
type Comando =
|
|
38
|
-
| "iniciar"
|
|
39
|
-
| "validar"
|
|
40
|
-
| "ast"
|
|
41
|
-
| "ir"
|
|
42
|
-
| "compilar"
|
|
43
|
-
| "gerar"
|
|
44
|
-
| "testar"
|
|
45
|
-
| "diagnosticos"
|
|
46
|
-
| "verificar"
|
|
47
|
-
| "inspecionar"
|
|
48
|
-
| "drift"
|
|
49
|
-
| "importar"
|
|
50
|
-
| "doctor"
|
|
51
|
-
| "formatar"
|
|
52
|
-
| "ajuda-ia"
|
|
53
|
-
| "starter-ia"
|
|
54
|
-
| "sync-ai-entrypoints"
|
|
55
|
-
| "resumo"
|
|
56
|
-
| "prompt-curto"
|
|
57
|
-
| "prompt-ia"
|
|
58
|
-
| "prompt-ia-ui"
|
|
59
|
-
| "prompt-ia-react"
|
|
60
|
-
| "prompt-ia-sema-primeiro"
|
|
61
|
-
| "exemplos-prompt-ia"
|
|
62
|
-
| "contexto-ia";
|
|
63
|
-
|
|
64
|
-
type TemplateIniciar =
|
|
65
|
-
| FrameworkGeracao
|
|
66
|
-
| "nextjs-api"
|
|
67
|
-
| "nextjs-consumer"
|
|
68
|
-
| "react-vite-consumer"
|
|
69
|
-
| "angular-consumer"
|
|
70
|
-
| "flutter-consumer"
|
|
71
|
-
| "node-firebase-worker"
|
|
72
|
-
| "aspnet-api"
|
|
73
|
-
| "springboot-api"
|
|
74
|
-
| "go-http-api"
|
|
75
|
-
| "rust-axum-api"
|
|
76
|
-
| "cpp-service-bridge";
|
|
77
|
-
|
|
78
|
-
interface ResultadoExecucaoTestes {
|
|
79
|
-
codigoSaida: number;
|
|
80
|
-
quantidadeTestes: number;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
interface ResumoAlvoVerificacao {
|
|
84
|
-
alvo: AlvoGeracao;
|
|
85
|
-
arquivosGerados: number;
|
|
86
|
-
quantidadeTestes: number;
|
|
87
|
-
pastaSaida: string;
|
|
88
|
-
sucesso: boolean;
|
|
89
|
-
framework: FrameworkGeracao;
|
|
90
|
-
estrutura: EstruturaSaida;
|
|
91
|
-
testesExecutados: boolean;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
interface ResumoModuloVerificacao {
|
|
95
|
-
modulo: string;
|
|
96
|
-
arquivoFonte: string;
|
|
97
|
-
alvos: ResumoAlvoVerificacao[];
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
interface SaidaTesteCapturada {
|
|
101
|
-
codigoSaida: number;
|
|
102
|
-
quantidadeTestes: number;
|
|
103
|
-
saidaPadrao: string;
|
|
104
|
-
saidaErro: string;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
interface ResultadoFormatacaoArquivo {
|
|
108
|
-
caminho: string;
|
|
109
|
-
alterado: boolean;
|
|
110
|
-
sucesso: boolean;
|
|
111
|
-
diagnosticos: ReturnType<typeof compilarCodigo>["diagnosticos"];
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
interface ContextoIaGerado {
|
|
115
|
-
sucesso: boolean;
|
|
116
|
-
arquivo: string;
|
|
117
|
-
modulo: string;
|
|
118
|
-
pastaSaida: string;
|
|
119
|
-
artefatos: string[];
|
|
120
|
-
artefatosCompactos: string[];
|
|
121
|
-
geradoEm: string;
|
|
122
|
-
guiaPorCapacidade: Record<CapacidadeIa, GuiaCapacidadeIa>;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
interface DescobertaDocsIa {
|
|
126
|
-
origemInstalacao: string;
|
|
127
|
-
baseDetectada: string | null;
|
|
128
|
-
documentos: Array<{ nome: string; caminho: string }>;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
type TamanhoResumoIa = "micro" | "curto" | "medio";
|
|
132
|
-
type ModoResumoIa = "resumo" | "onboarding" | "review" | "mudanca" | "bug" | "arquitetura";
|
|
133
|
-
type CapacidadeIa = "pequena" | "media" | "grande";
|
|
134
|
-
type ResultadoDriftIa = Awaited<ReturnType<typeof analisarDriftLegado>>;
|
|
135
|
-
type ResumoModuloDrift = ReturnType<typeof resumirDriftPorModulo>;
|
|
136
|
-
|
|
137
|
-
interface GuiaCapacidadeIa {
|
|
138
|
-
descricao: string;
|
|
139
|
-
artefatos: string[];
|
|
140
|
-
ordemLeitura: string[];
|
|
141
|
-
evitar: string[];
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
interface PacoteContextoModuloIa {
|
|
145
|
-
arquivo: string;
|
|
146
|
-
modulo: string;
|
|
147
|
-
sucesso: boolean;
|
|
148
|
-
geradoEm: string;
|
|
149
|
-
diagnosticos: ReturnType<typeof compilarCodigo>["diagnosticos"];
|
|
150
|
-
ir: IrModulo | null;
|
|
151
|
-
validar: {
|
|
152
|
-
comando: "validar";
|
|
153
|
-
sucesso: boolean;
|
|
154
|
-
resultados: Array<{
|
|
155
|
-
caminho: string;
|
|
156
|
-
modulo: string | null;
|
|
157
|
-
sucesso: boolean;
|
|
158
|
-
diagnosticos: ReturnType<typeof compilarCodigo>["diagnosticos"];
|
|
159
|
-
}>;
|
|
160
|
-
};
|
|
161
|
-
diagnosticosJson: {
|
|
162
|
-
comando: "diagnosticos";
|
|
163
|
-
caminho: string;
|
|
164
|
-
modulo: string | null;
|
|
165
|
-
diagnosticos: ReturnType<typeof compilarCodigo>["diagnosticos"];
|
|
166
|
-
};
|
|
167
|
-
ast: {
|
|
168
|
-
comando: "ast";
|
|
169
|
-
caminho: string;
|
|
170
|
-
modulo: string | null;
|
|
171
|
-
sucesso: boolean;
|
|
172
|
-
diagnosticos: ReturnType<typeof compilarCodigo>["diagnosticos"];
|
|
173
|
-
ast: unknown;
|
|
174
|
-
};
|
|
175
|
-
irJson: {
|
|
176
|
-
comando: "ir";
|
|
177
|
-
caminho: string;
|
|
178
|
-
modulo: string | null;
|
|
179
|
-
sucesso: boolean;
|
|
180
|
-
diagnosticos: ReturnType<typeof compilarCodigo>["diagnosticos"];
|
|
181
|
-
ir: IrModulo | null;
|
|
182
|
-
};
|
|
183
|
-
drift: {
|
|
184
|
-
comando: "drift";
|
|
185
|
-
caminho: string;
|
|
186
|
-
modulo: string | null;
|
|
187
|
-
sucesso: boolean;
|
|
188
|
-
resumo: ResumoModuloDrift;
|
|
189
|
-
drift: ResultadoDriftIa;
|
|
190
|
-
};
|
|
191
|
-
briefing: ReturnType<typeof criarBriefingAgente>;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
interface ResumoSemanticoModuloIa {
|
|
195
|
-
geradoEm: string;
|
|
196
|
-
arquivo: string;
|
|
197
|
-
modulo: string;
|
|
198
|
-
perfilCompatibilidade: string;
|
|
199
|
-
scoreSemantico: number;
|
|
200
|
-
confiancaGeral: string;
|
|
201
|
-
riscoOperacional: string;
|
|
202
|
-
faz: string;
|
|
203
|
-
tarefasPrincipais: string[];
|
|
204
|
-
entradasChave: string[];
|
|
205
|
-
saidasChave: string[];
|
|
206
|
-
superficiesPublicas: string[];
|
|
207
|
-
regrasCriticas: string[];
|
|
208
|
-
efeitos: string[];
|
|
209
|
-
erros: string[];
|
|
210
|
-
entidadesAfetadas: string[];
|
|
211
|
-
arquivosProvaveis: string[];
|
|
212
|
-
simbolosRelacionados: string[];
|
|
213
|
-
riscosPrincipais: string[];
|
|
214
|
-
lacunas: string[];
|
|
215
|
-
inferido: string[];
|
|
216
|
-
checksSugeridos: string[];
|
|
217
|
-
testesMinimos: string[];
|
|
218
|
-
consumerFramework: string | null;
|
|
219
|
-
appRoutes: string[];
|
|
220
|
-
consumerSurfaces: string[];
|
|
221
|
-
consumerBridges: string[];
|
|
222
|
-
arquivosProvaveisEditar: string[];
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
const STARTER_IA = `Voce esta trabalhando com Sema, um Protocolo de Governanca de Intencao para IA sobre software vivo em backend e front consumer.
|
|
226
|
-
|
|
227
|
-
Importante:
|
|
228
|
-
- a Sema se apresenta publicamente como protocolo e funciona tecnicamente como linguagem de intencao
|
|
229
|
-
- a Sema e protocolo de governanca semantica desenhado para IA, nao para ergonomia humana
|
|
230
|
-
- leitura humana e bonus toleravel, nao objetivo de produto
|
|
231
|
-
- a Sema nao e gerador magico que deveria fazer tudo
|
|
232
|
-
- a Sema modela contratos, estados, fluxos, erros, efeitos, garantias, vinculos e execucao
|
|
233
|
-
- a Sema gera codigo e scaffolding real para TypeScript, Python e Dart
|
|
234
|
-
- a Sema usa \`importar\` para bootstrap revisavel, nao para contrato final automatico
|
|
235
|
-
- a Sema usa \`impl\` para ligar task a simbolo real do runtime
|
|
236
|
-
- a Sema usa \`vinculos\` para ligar contrato a arquivo, simbolo, recurso e superficie real
|
|
237
|
-
- a Sema usa \`execucao\` para explicitar timeout, retry, compensacao e criticidade
|
|
238
|
-
- a Sema usa \`drift\` para medir diferenca entre contrato e codigo vivo com score, confianca e lacunas
|
|
239
|
-
- a Sema usa \`resumo\` e \`prompt-curto\` para IA pequena ou gratuita
|
|
240
|
-
- a Sema usa \`contexto-ia\` para gerar \`ast.json\`, \`ir.json\`, \`drift.json\`, \`briefing.json\` e artefatos compactos antes da edicao
|
|
241
|
-
- a Sema pode servir de base para interfaces graficas elegantes e coerentes
|
|
242
|
-
- a Sema nao gera uma interface completa sozinha no estado atual
|
|
243
|
-
- trate a Sema como cerebro semantico da aplicacao, nao como gerador magico de front-end pronto
|
|
244
|
-
- se a tarefa envolver UI, prefira pedir Sema + React + TypeScript ou Sema + arquitetura de front-end
|
|
245
|
-
- evite pedir HTML unico solto quando a intencao for testar a Sema de verdade
|
|
246
|
-
|
|
247
|
-
Regras:
|
|
248
|
-
- nao invente sintaxe fora da gramatica e dos exemplos oficiais
|
|
249
|
-
- se a IA for pequena, nao tente abrir tudo de uma vez
|
|
250
|
-
- use \`sema resumo\` e \`briefing.min.json\` antes de subir para o pacote completo
|
|
251
|
-
- trate \`ir --json\` como fonte de verdade semantica
|
|
252
|
-
- trate \`briefing.json\` como plano de intervencao antes de editar projeto vivo
|
|
253
|
-
- trate \`diagnosticos --json\` como fonte de correcao
|
|
254
|
-
- use \`sema formatar\` como fonte unica de estilo
|
|
255
|
-
- preserve a intencao do contrato
|
|
256
|
-
- nao cobre da Sema adivinhacao de negocio que nao esta no contrato nem no codigo
|
|
257
|
-
|
|
258
|
-
Comandos essenciais:
|
|
259
|
-
- resumo compacto por capacidade: \`sema resumo <arquivo-ou-pasta> [--micro|--curto|--medio] [--para <resumo|onboarding|review|mudanca|bug|arquitetura>]\`
|
|
260
|
-
- prompt curto para IA pequena: \`sema prompt-curto <arquivo-ou-pasta> [--micro|--curto|--medio] [--para <resumo|onboarding|review|mudanca|bug|arquitetura>]\`
|
|
261
|
-
- descoberta do projeto: \`sema inspecionar [arquivo-ou-pasta] --json\`
|
|
262
|
-
- auditoria do contrato vivo: \`sema drift <arquivo-ou-pasta> [--json]\`
|
|
263
|
-
- contexto completo do modulo: \`sema contexto-ia <arquivo.sema>\`
|
|
264
|
-
- estrutura sintatica: \`sema ast <arquivo.sema> --json\`
|
|
265
|
-
- estrutura semantica: \`sema ir <arquivo.sema> --json\`
|
|
266
|
-
- validacao: \`sema validar <arquivo.sema> --json\`
|
|
267
|
-
- diagnosticos: \`sema diagnosticos <arquivo.sema> --json\`
|
|
268
|
-
- formatacao: \`sema formatar <arquivo.sema>\`
|
|
269
|
-
- importacao assistida de legado: \`sema importar <nestjs|fastapi|flask|nextjs|nextjs-consumer|react-vite-consumer|angular-consumer|flutter-consumer|firebase|dotnet|java|go|rust|cpp|typescript|python|dart> <diretorio> --saida <diretorio>\`
|
|
270
|
-
- geracao de codigo: \`sema compilar <arquivo-ou-pasta> --alvo <typescript|python|dart|lua> --saida <diretorio>\`
|
|
271
|
-
- verificacao final: \`sema verificar <arquivo-ou-pasta> [--json]\`
|
|
272
|
-
|
|
273
|
-
Antes de editar:
|
|
274
|
-
1. leia README, docs de IA e um exemplo oficial parecido
|
|
275
|
-
2. se a IA for pequena, rode \`sema resumo <arquivo> --micro\` e leia \`briefing.min.json\`
|
|
276
|
-
3. se a IA aguentar mais, rode \`sema drift\` para medir impls, vinculos, rotas, score e lacunas
|
|
277
|
-
4. se a tarefa for pesada, rode \`sema contexto-ia\` e leia \`briefing.json\`
|
|
278
|
-
5. consulte AST e IR do modulo alvo so quando a capacidade realmente aguentar
|
|
279
|
-
|
|
280
|
-
Depois de editar:
|
|
281
|
-
1. rode \`sema formatar\`
|
|
282
|
-
2. rode \`sema validar --json\`
|
|
283
|
-
3. se houver falha, use \`diagnosticos --json\`
|
|
284
|
-
4. rode \`sema drift\` de novo quando mexer em codigo vivo
|
|
285
|
-
5. se a tarefa pedir codigo derivado, rode \`sema compilar\`
|
|
286
|
-
6. feche com \`sema verificar <arquivo-ou-pasta> --json\`
|
|
287
|
-
|
|
288
|
-
Priorize sempre:
|
|
289
|
-
- exemplos oficiais
|
|
290
|
-
- JSON da CLI
|
|
291
|
-
- o menor artefato que resolva a tarefa da IA atual
|
|
292
|
-
- score, confianca e lacunas do \`drift\`
|
|
293
|
-
- \`briefing.json\` como guia de mudanca
|
|
294
|
-
- consistencia semantica
|
|
295
|
-
|
|
296
|
-
Superficies que a IA deve enxergar como first-class:
|
|
297
|
-
- \`route\`
|
|
298
|
-
- \`worker\`
|
|
299
|
-
- \`evento\`
|
|
300
|
-
- \`fila\`
|
|
301
|
-
- \`cron\`
|
|
302
|
-
- \`webhook\`
|
|
303
|
-
- \`cache\`
|
|
304
|
-
- \`storage\`
|
|
305
|
-
- \`policy\`
|
|
306
|
-
|
|
307
|
-
Nao improvise quando faltar contexto.
|
|
308
|
-
`;
|
|
309
|
-
|
|
310
|
-
const PROMPT_BASE_IA = `Voce esta trabalhando com Sema, um Protocolo de Governanca de Intencao orientado a contrato, desenhado para operacao por IA.
|
|
311
|
-
|
|
312
|
-
Trate a Sema como camada semantica e linguagem de especificacao executavel feita para IA, nao para leitura humana confortavel. Nao invente sintaxe, palavras-chave ou blocos fora da gramatica e dos exemplos oficiais.
|
|
313
|
-
|
|
314
|
-
Fontes de verdade, em ordem:
|
|
315
|
-
1. se o projeto expuser \`SEMA_CONTEXT.md\`, comece por ele
|
|
316
|
-
2. \`SEMA_BRIEF.md\`
|
|
317
|
-
3. \`SEMA_INDEX.json\`
|
|
318
|
-
4. README do projeto
|
|
319
|
-
5. gramatica e documentacao de sintaxe da Sema
|
|
320
|
-
6. especificacao semantica da linguagem
|
|
321
|
-
7. exemplos oficiais, com prioridade para o vertical de pagamento
|
|
322
|
-
8. \`sema resumo\` e \`briefing.min.json\` quando a IA for pequena
|
|
323
|
-
9. AST, IR e diagnosticos exportados pela CLI em JSON quando a capacidade aguentar
|
|
324
|
-
|
|
325
|
-
Regras de operacao:
|
|
326
|
-
- preserve o significado semantico
|
|
327
|
-
- use o formatador oficial da Sema como fonte unica de estilo
|
|
328
|
-
- use diagnosticos estruturados como contrato de correcao
|
|
329
|
-
- use a IR como fonte de verdade semantica quando houver duvida
|
|
330
|
-
- nao conclua uma alteracao sem validar e verificar o modulo
|
|
331
|
-
- comece pelo menor artefato semantico que resolva a tarefa
|
|
332
|
-
|
|
333
|
-
Antes de editar \`.sema\`, entenda:
|
|
334
|
-
- o module alvo
|
|
335
|
-
- os contratos de task, route, error, effects, guarantees, state e flow
|
|
336
|
-
- os exemplos oficiais relacionados
|
|
337
|
-
|
|
338
|
-
Depois de editar \`.sema\`, execute este fluxo:
|
|
339
|
-
1. formatar
|
|
340
|
-
2. validar
|
|
341
|
-
3. diagnosticar, se houver falha
|
|
342
|
-
4. verificar
|
|
343
|
-
|
|
344
|
-
Se houver conflito entre texto livre e IR/diagnosticos, priorize a IR e os diagnosticos da CLI.
|
|
345
|
-
|
|
346
|
-
Se algo nao estiver claro, siga a forma ja usada nos exemplos oficiais. Nao improvise sem base.
|
|
347
|
-
`;
|
|
348
|
-
|
|
349
|
-
const PROMPT_IA_UI = `Atue como Engenheiro de Software Senior e UX/UI Designer de elite.
|
|
350
|
-
|
|
351
|
-
Quero que voce trabalhe com Sema como fonte de verdade semantica do sistema e com React + TypeScript como camada de interface.
|
|
352
|
-
|
|
353
|
-
Entregue obrigatoriamente duas partes integradas:
|
|
354
|
-
1. os arquivos \`.sema\` do dominio
|
|
355
|
-
2. a proposta ou implementacao da interface em React + TypeScript
|
|
356
|
-
|
|
357
|
-
Regras:
|
|
358
|
-
- nao entregue apenas HTML solto em arquivo unico
|
|
359
|
-
- nao trate a Sema como enfeite conceitual
|
|
360
|
-
- a interface deve nascer do contrato semantico definido em Sema
|
|
361
|
-
- use os exemplos oficiais da Sema como referencia de estilo e semantica
|
|
362
|
-
- nao invente sintaxe fora da gramatica suportada
|
|
363
|
-
|
|
364
|
-
A Sema deve modelar, quando fizer sentido:
|
|
365
|
-
- \`module\`
|
|
366
|
-
- \`use\`
|
|
367
|
-
- \`entity\`
|
|
368
|
-
- \`enum\`
|
|
369
|
-
- \`state\`
|
|
370
|
-
- \`task\`
|
|
371
|
-
- \`flow\`
|
|
372
|
-
- \`route\`
|
|
373
|
-
- \`effects\`
|
|
374
|
-
- \`error\`
|
|
375
|
-
- \`guarantees\`
|
|
376
|
-
- \`tests\`
|
|
377
|
-
- \`docs\`
|
|
378
|
-
|
|
379
|
-
A interface deve refletir visualmente:
|
|
380
|
-
- \`state\` como status e progresso observavel
|
|
381
|
-
- \`flow\` como etapas ou orquestracao visivel
|
|
382
|
-
- \`error\` como falhas tratadas com clareza
|
|
383
|
-
- \`effects\` como operacoes relevantes para usuario ou operacao
|
|
384
|
-
- \`guarantees\` como confianca, confirmacao ou consistencia final
|
|
385
|
-
|
|
386
|
-
Estruture a entrega assim:
|
|
387
|
-
1. visao do produto
|
|
388
|
-
2. dominio modelado em Sema
|
|
389
|
-
3. arquitetura de pastas em React + TypeScript
|
|
390
|
-
4. componentes principais
|
|
391
|
-
5. estrategia visual
|
|
392
|
-
6. codigo principal da interface
|
|
393
|
-
7. explicacao curta de como a UI conversa com a semantica da Sema
|
|
394
|
-
|
|
395
|
-
Se a tarefa envolver app visual, a Sema governa o significado e o React renderiza a experiencia. Nao atropele essa separacao.
|
|
396
|
-
`;
|
|
397
|
-
|
|
398
|
-
const PROMPT_IA_REACT = `Crie uma solucao com Sema + React + TypeScript.
|
|
399
|
-
|
|
400
|
-
Regras principais:
|
|
401
|
-
- a Sema deve ser a fonte de verdade semantica do dominio
|
|
402
|
-
- React + TypeScript deve ser a camada de interface e experiencia
|
|
403
|
-
- nao entregue HTML unico solto
|
|
404
|
-
- nao trate a Sema como enfeite
|
|
405
|
-
|
|
406
|
-
Entregue obrigatoriamente:
|
|
407
|
-
1. arquivos \`.sema\` do dominio
|
|
408
|
-
2. arquitetura de pastas do frontend
|
|
409
|
-
3. componentes React principais
|
|
410
|
-
4. contratos e tipos derivados da semantica
|
|
411
|
-
5. interface elegante e implementavel
|
|
412
|
-
|
|
413
|
-
A modelagem Sema deve cobrir, quando fizer sentido:
|
|
414
|
-
- \`entity\`
|
|
415
|
-
- \`enum\`
|
|
416
|
-
- \`state\`
|
|
417
|
-
- \`task\`
|
|
418
|
-
- \`flow\`
|
|
419
|
-
- \`route\`
|
|
420
|
-
- \`effects\`
|
|
421
|
-
- \`error\`
|
|
422
|
-
- \`guarantees\`
|
|
423
|
-
- \`tests\`
|
|
424
|
-
|
|
425
|
-
A interface React deve tornar visiveis:
|
|
426
|
-
- estado atual e transicoes relevantes
|
|
427
|
-
- fluxo operacional
|
|
428
|
-
- erros publicos
|
|
429
|
-
- efeitos operacionais importantes
|
|
430
|
-
- garantias ou confirmacoes finais
|
|
431
|
-
|
|
432
|
-
Estruture a entrega assim:
|
|
433
|
-
1. visao do produto
|
|
434
|
-
2. arquivos \`.sema\`
|
|
435
|
-
3. arquitetura React + TypeScript
|
|
436
|
-
4. componentes e telas
|
|
437
|
-
5. codigo principal
|
|
438
|
-
6. explicacao de como a UI deriva da semantica da Sema
|
|
439
|
-
|
|
440
|
-
Se houver duvida, siga os exemplos oficiais e mantenha a separacao:
|
|
441
|
-
- Sema governa o significado
|
|
442
|
-
- React governa a apresentacao
|
|
443
|
-
`;
|
|
444
|
-
|
|
445
|
-
const PROMPT_IA_SEMA_PRIMEIRO = `Quero que voce trabalhe no modo "Sema primeiro".
|
|
446
|
-
|
|
447
|
-
Regra principal:
|
|
448
|
-
- modele primeiro o dominio em arquivos \`.sema\`
|
|
449
|
-
- so depois proponha ou gere codigo de aplicacao derivado disso
|
|
450
|
-
|
|
451
|
-
Fluxo obrigatorio:
|
|
452
|
-
1. entender o dominio pedido
|
|
453
|
-
2. modelar o contrato em Sema
|
|
454
|
-
3. validar coerencia entre \`task\`, \`route\`, \`state\`, \`flow\`, \`error\`, \`effects\` e \`guarantees\`
|
|
455
|
-
4. so depois gerar TypeScript, Python, React ou outra camada de implementacao
|
|
456
|
-
|
|
457
|
-
Nao entregue apenas codigo de interface ou codigo imperativo direto sem antes entregar a camada semantica.
|
|
458
|
-
|
|
459
|
-
A modelagem em Sema deve:
|
|
460
|
-
- preservar a intencao do dominio
|
|
461
|
-
- explicitar entradas, saidas, erros, efeitos e garantias
|
|
462
|
-
- usar apenas blocos e sintaxe oficiais
|
|
463
|
-
- incluir testes embutidos quando fizer sentido
|
|
464
|
-
|
|
465
|
-
Se houver interface grafica:
|
|
466
|
-
- entregue a modelagem Sema primeiro
|
|
467
|
-
- depois explique como a interface deve refletir a semantica
|
|
468
|
-
- se gerar UI, use React + TypeScript em vez de HTML unico solto
|
|
469
|
-
|
|
470
|
-
Se houver backend:
|
|
471
|
-
- entregue a modelagem Sema primeiro
|
|
472
|
-
- depois gere a borda publica e a implementacao derivada
|
|
473
|
-
|
|
474
|
-
Nao pule a etapa semantica. A camada \`.sema\` e a ancora principal da solucao.
|
|
475
|
-
`;
|
|
476
|
-
|
|
477
|
-
const EXEMPLOS_PROMPT_IA = `Exemplos de prompt oficial para trabalhar com Sema
|
|
478
|
-
|
|
479
|
-
1. Sema primeiro
|
|
480
|
-
|
|
481
|
-
Crie uma solucao seguindo a estrategia "Sema primeiro".
|
|
482
|
-
Entregue primeiro os arquivos \`.sema\` do dominio e so depois a implementacao derivada.
|
|
483
|
-
Nao entregue apenas codigo imperativo.
|
|
484
|
-
Use Sema como fonte de verdade para contratos, estados, erros, efeitos e garantias.
|
|
485
|
-
|
|
486
|
-
2. Sema + React + TypeScript
|
|
487
|
-
|
|
488
|
-
Crie um projeto com Sema + React + TypeScript.
|
|
489
|
-
Entregue:
|
|
490
|
-
- os arquivos \`.sema\` do dominio
|
|
491
|
-
- a arquitetura de pastas do frontend
|
|
492
|
-
- componentes React que reflitam \`state\`, \`flow\`, \`error\`, \`effects\` e \`guarantees\`
|
|
493
|
-
- uma interface elegante e implementavel
|
|
494
|
-
- nao entregue HTML solto em arquivo unico
|
|
495
|
-
|
|
496
|
-
3. Revisar ou corrigir um modulo Sema
|
|
497
|
-
|
|
498
|
-
Revise e corrija um modulo \`.sema\`.
|
|
499
|
-
Antes de editar:
|
|
500
|
-
- leia os exemplos oficiais parecidos
|
|
501
|
-
- consulte AST e IR
|
|
502
|
-
Depois de editar:
|
|
503
|
-
- rode \`sema formatar\`
|
|
504
|
-
- rode \`sema validar --json\`
|
|
505
|
-
- use \`diagnosticos --json\` se houver falha
|
|
506
|
-
- feche com \`sema verificar\`
|
|
507
|
-
|
|
508
|
-
4. Caso de UI sem perder a semantica
|
|
509
|
-
|
|
510
|
-
Quero uma interface premium para este dominio, mas a solucao deve continuar ancorada em Sema.
|
|
511
|
-
Modele primeiro o dominio em \`.sema\`.
|
|
512
|
-
Depois proponha uma interface em React + TypeScript que torne visiveis:
|
|
513
|
-
- estado
|
|
514
|
-
- fluxo
|
|
515
|
-
- erros
|
|
516
|
-
- efeitos
|
|
517
|
-
- garantias
|
|
518
|
-
Nao transforme isso em um \`index.html\` solto.
|
|
519
|
-
|
|
520
|
-
Comandos uteis da CLI para esse fluxo:
|
|
521
|
-
- \`sema starter-ia\`
|
|
522
|
-
- \`sema ajuda-ia\`
|
|
523
|
-
- \`sema resumo <arquivo-ou-pasta>\`
|
|
524
|
-
- \`sema prompt-curto <arquivo-ou-pasta>\`
|
|
525
|
-
- \`sema prompt-ia\`
|
|
526
|
-
- \`sema prompt-ia-ui\`
|
|
527
|
-
- \`sema prompt-ia-react\`
|
|
528
|
-
- \`sema prompt-ia-sema-primeiro\`
|
|
529
|
-
- \`sema contexto-ia <arquivo.sema>\`
|
|
530
|
-
`;
|
|
531
|
-
|
|
532
|
-
const DIRETORIO_CLI_ATUAL = path.dirname(fileURLToPath(import.meta.url));
|
|
533
|
-
const VERSAO_CLI = pacoteCli.version;
|
|
534
|
-
const ARQUIVOS_CANONICOS_IA_RAIZ = [
|
|
535
|
-
"llms.txt",
|
|
536
|
-
"SEMA_BRIEF.md",
|
|
537
|
-
"SEMA_INDEX.json",
|
|
538
|
-
"AGENTS.md",
|
|
539
|
-
"README.md",
|
|
540
|
-
"llms-full.txt",
|
|
541
|
-
] as const;
|
|
542
|
-
const DOCUMENTOS_SUPORTE_IA = [
|
|
543
|
-
"docs/AGENT_STARTER.md",
|
|
544
|
-
"docs/integracao-com-ia.md",
|
|
545
|
-
"docs/fluxo-pratico-ia-sema.md",
|
|
546
|
-
"docs/como-ensinar-a-sema-para-ia.md",
|
|
547
|
-
"docs/sintaxe.md",
|
|
548
|
-
"docs/cli.md",
|
|
549
|
-
] as const;
|
|
550
|
-
|
|
551
|
-
function obterArgumentos(): { comando?: Comando; resto: string[] } {
|
|
552
|
-
const [, , comando, ...resto] = process.argv;
|
|
553
|
-
return { comando: comando as Comando | undefined, resto };
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
function renderizarCaixaAscii(linhas: string[]): string {
|
|
557
|
-
const largura = Math.max(...linhas.map((linha) => linha.length), 12);
|
|
558
|
-
const borda = `+${"-".repeat(largura + 2)}+`;
|
|
559
|
-
return [
|
|
560
|
-
borda,
|
|
561
|
-
...linhas.map((linha) => `| ${linha.padEnd(largura, " ")} |`),
|
|
562
|
-
borda,
|
|
563
|
-
].join("\n");
|
|
564
|
-
}
|
|
565
|
-
|
|
566
|
-
function renderizarSecaoAscii(titulo: string, linhas: string[]): string {
|
|
567
|
-
return [
|
|
568
|
-
titulo,
|
|
569
|
-
...linhas.map((linha) => ` ${linha}`),
|
|
570
|
-
].join("\n");
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
function ajuda(): string {
|
|
574
|
-
return [
|
|
575
|
-
renderizarCaixaAscii([
|
|
576
|
-
`Sema CLI v${VERSAO_CLI}`,
|
|
577
|
-
"IA-first para contrato, geracao e adocao incremental",
|
|
578
|
-
"novo projeto, edicao guiada e legado sem contrato inicial",
|
|
579
|
-
]),
|
|
580
|
-
"",
|
|
581
|
-
renderizarSecaoAscii("Fluxos rapidos", [
|
|
582
|
-
"[1] Projeto novo / producao inicial",
|
|
583
|
-
"sema iniciar --template <base|nestjs|fastapi|nextjs-api|nextjs-consumer|react-vite-consumer|angular-consumer|flutter-consumer>",
|
|
584
|
-
"sema validar contratos/<modulo>.sema --json",
|
|
585
|
-
"sema compilar <arquivo-ou-pasta> --alvo <typescript|python|dart|lua> --saida <diretorio>",
|
|
586
|
-
"sema verificar <arquivo-ou-pasta> --json",
|
|
587
|
-
"",
|
|
588
|
-
"[2] Editar projeto que ja usa Sema",
|
|
589
|
-
"sema inspecionar . --json",
|
|
590
|
-
"sema resumo <arquivo-ou-pasta> --micro --para mudanca",
|
|
591
|
-
"sema drift <arquivo-ou-pasta> --json",
|
|
592
|
-
"sema contexto-ia <arquivo.sema> --saida ./.tmp/contexto --json",
|
|
593
|
-
"",
|
|
594
|
-
"[3] Adotar Sema em projeto que ainda nao usa",
|
|
595
|
-
"sema importar <fonte> <diretorio> --saida <diretorio> --json",
|
|
596
|
-
"sema formatar <arquivo-ou-pasta>",
|
|
597
|
-
"sema validar <arquivo-ou-pasta> --json",
|
|
598
|
-
"sema drift <arquivo-ou-pasta> --json",
|
|
599
|
-
]),
|
|
600
|
-
"",
|
|
601
|
-
renderizarSecaoAscii("IA por capacidade", [
|
|
602
|
-
"pequena: sema resumo --micro + briefing.min.json + prompt-curto.txt",
|
|
603
|
-
"media: sema resumo --curto + drift.json + briefing.min.json",
|
|
604
|
-
"grande: sema contexto-ia + briefing.json + ir.json + ast.json",
|
|
605
|
-
]),
|
|
606
|
-
"",
|
|
607
|
-
renderizarSecaoAscii("Comandos principais", [
|
|
608
|
-
"descoberta: sema inspecionar [arquivo-ou-pasta] [--json]",
|
|
609
|
-
"auditoria: sema drift <arquivo-ou-pasta> [--json]",
|
|
610
|
-
"importacao: sema importar <nestjs|fastapi|flask|nextjs|nextjs-consumer|react-vite-consumer|angular-consumer|flutter-consumer|firebase|dotnet|java|go|rust|cpp|typescript|python|dart> <diretorio> [--saida <diretorio>] [--namespace <base>] [--json]",
|
|
611
|
-
"validacao: sema validar <arquivo-ou-pasta> [--json]",
|
|
612
|
-
"diagnostico: sema diagnosticos <arquivo.sema> [--json]",
|
|
613
|
-
"geracao: sema compilar <arquivo-ou-pasta> --alvo <python|typescript|dart|lua> --saida <diretorio> [--estrutura <flat|modulos|backend>] [--framework <base|nestjs|fastapi>]",
|
|
614
|
-
"teste local: sema testar <arquivo.sema> --alvo <python|typescript|dart|lua> --saida <diretorio-temporario> [--estrutura <flat|modulos|backend>] [--framework <base|nestjs|fastapi>]",
|
|
615
|
-
"verificacao final: sema verificar <arquivo-ou-pasta> [--saida <diretorio-base>] [--json]",
|
|
616
|
-
"formatacao: sema formatar <arquivo-ou-pasta> [--check] [--json]",
|
|
617
|
-
]),
|
|
618
|
-
"",
|
|
619
|
-
renderizarSecaoAscii("Ajuda IA-first", [
|
|
620
|
-
"sema ajuda-ia",
|
|
621
|
-
"sema starter-ia",
|
|
622
|
-
"sema resumo <arquivo-ou-pasta> [--micro|--curto|--medio] [--para <resumo|onboarding|review|mudanca|bug|arquitetura>] [--saida <diretorio>] [--raiz] [--json]",
|
|
623
|
-
"sema prompt-curto <arquivo-ou-pasta> [--micro|--curto|--medio] [--para <resumo|onboarding|review|mudanca|bug|arquitetura>] [--json]",
|
|
624
|
-
"sema prompt-ia",
|
|
625
|
-
"sema prompt-ia-ui",
|
|
626
|
-
"sema prompt-ia-react",
|
|
627
|
-
"sema prompt-ia-sema-primeiro",
|
|
628
|
-
"sema exemplos-prompt-ia",
|
|
629
|
-
"sema contexto-ia <arquivo.sema> [--saida <diretorio>] [--json]",
|
|
630
|
-
"sema sync-ai-entrypoints [--json]",
|
|
631
|
-
]),
|
|
632
|
-
"",
|
|
633
|
-
renderizarSecaoAscii("Operacional", [
|
|
634
|
-
"sema doctor",
|
|
635
|
-
"sema --versao | --version | -v",
|
|
636
|
-
]),
|
|
637
|
-
].join("\n");
|
|
638
|
-
}
|
|
639
|
-
|
|
640
|
-
async function carregarModulos(entrada: string | undefined, cwd = process.cwd()): Promise<ContextoProjetoCarregado["modulosSelecionados"]> {
|
|
641
|
-
return (await carregarProjeto(entrada, cwd)).modulosSelecionados;
|
|
642
|
-
}
|
|
643
|
-
|
|
644
|
-
async function escreverArquivos(base: string, arquivos: Array<{ caminhoRelativo: string; conteudo: string }>): Promise<void> {
|
|
645
|
-
await mkdir(base, { recursive: true });
|
|
646
|
-
for (const arquivo of arquivos) {
|
|
647
|
-
const destino = path.join(base, arquivo.caminhoRelativo);
|
|
648
|
-
await mkdir(path.dirname(destino), { recursive: true });
|
|
649
|
-
await writeFile(destino, arquivo.conteudo, "utf8");
|
|
650
|
-
}
|
|
651
|
-
}
|
|
652
|
-
|
|
653
|
-
function obterOpcao(args: string[], nome: string, padrao?: string): string | undefined {
|
|
654
|
-
const nomes = [nome, ...Object.entries(ALIAS_OPCOES).filter(([, v]) => v === nome).map(([k]) => k)];
|
|
655
|
-
for (const n of nomes) {
|
|
656
|
-
const indice = args.findIndex((arg) => arg === n);
|
|
657
|
-
if (indice !== -1) return args[indice + 1] ?? padrao;
|
|
658
|
-
}
|
|
659
|
-
return padrao;
|
|
660
|
-
}
|
|
661
|
-
|
|
662
|
-
function possuiFlag(args: string[], nome: string): boolean {
|
|
663
|
-
return args.includes(nome);
|
|
664
|
-
}
|
|
665
|
-
|
|
666
|
-
const OPCOES_COM_VALOR = new Set([
|
|
667
|
-
"--template",
|
|
668
|
-
"--alvo", "-a",
|
|
669
|
-
"--saida", "-s",
|
|
670
|
-
"--estrutura",
|
|
671
|
-
"--framework",
|
|
672
|
-
"--namespace",
|
|
673
|
-
"--para",
|
|
674
|
-
]);
|
|
675
|
-
|
|
676
|
-
const ALIAS_OPCOES: Record<string, string> = {
|
|
677
|
-
"-a": "--alvo",
|
|
678
|
-
"-s": "--saida",
|
|
679
|
-
};
|
|
680
|
-
|
|
681
|
-
function obterPosicionais(args: string[]): string[] {
|
|
682
|
-
const posicionais: string[] = [];
|
|
683
|
-
for (let indice = 0; indice < args.length; indice += 1) {
|
|
684
|
-
const atual = args[indice]!;
|
|
685
|
-
if (atual.startsWith("-")) {
|
|
686
|
-
if (OPCOES_COM_VALOR.has(atual)) {
|
|
687
|
-
indice += 1;
|
|
688
|
-
}
|
|
689
|
-
continue;
|
|
690
|
-
}
|
|
691
|
-
posicionais.push(atual);
|
|
692
|
-
}
|
|
693
|
-
return posicionais;
|
|
694
|
-
}
|
|
695
|
-
|
|
696
|
-
function normalizarTamanhoResumo(args: string[]): TamanhoResumoIa {
|
|
697
|
-
const escolhas = [
|
|
698
|
-
possuiFlag(args, "--micro") ? "micro" : null,
|
|
699
|
-
possuiFlag(args, "--curto") ? "curto" : null,
|
|
700
|
-
possuiFlag(args, "--medio") ? "medio" : null,
|
|
701
|
-
].filter((item): item is TamanhoResumoIa => item !== null);
|
|
702
|
-
|
|
703
|
-
if (escolhas.length > 1) {
|
|
704
|
-
throw new Error("Use apenas uma entre as flags --micro, --curto ou --medio.");
|
|
705
|
-
}
|
|
706
|
-
|
|
707
|
-
return escolhas[0] ?? "curto";
|
|
708
|
-
}
|
|
709
|
-
|
|
710
|
-
function normalizarModoResumo(valor?: string): ModoResumoIa {
|
|
711
|
-
if (
|
|
712
|
-
valor === "resumo"
|
|
713
|
-
|| valor === "onboarding"
|
|
714
|
-
|| valor === "review"
|
|
715
|
-
|| valor === "mudanca"
|
|
716
|
-
|| valor === "bug"
|
|
717
|
-
|| valor === "arquitetura"
|
|
718
|
-
) {
|
|
719
|
-
return valor;
|
|
720
|
-
}
|
|
721
|
-
return "resumo";
|
|
722
|
-
}
|
|
723
|
-
|
|
724
|
-
function comandoDisponivel(comando: string, argumentos: string[] = ["--version"]): boolean {
|
|
725
|
-
const execucao = spawnSync(comando, argumentos, { stdio: "ignore", shell: process.platform === "win32" });
|
|
726
|
-
return (execucao.status ?? 1) === 0;
|
|
727
|
-
}
|
|
728
|
-
|
|
729
|
-
async function comandoDoctor(): Promise<number> {
|
|
730
|
-
const checks = [
|
|
731
|
-
{ nome: "node", ok: comandoDisponivel("node") },
|
|
732
|
-
{ nome: "npm", ok: comandoDisponivel("npm") },
|
|
733
|
-
{ nome: "python", ok: comandoDisponivel("python") || comandoDisponivel("py") },
|
|
734
|
-
{ nome: "dotnet", ok: comandoDisponivel("dotnet") },
|
|
735
|
-
{ nome: "go", ok: comandoDisponivel("go") },
|
|
736
|
-
{ nome: "cargo", ok: comandoDisponivel("cargo") },
|
|
737
|
-
{ nome: "java", ok: comandoDisponivel("java") },
|
|
738
|
-
{ nome: "code", ok: comandoDisponivel("code", ["--version"]) },
|
|
739
|
-
];
|
|
740
|
-
|
|
741
|
-
console.log(renderizarCaixaAscii([
|
|
742
|
-
"Sema doctor",
|
|
743
|
-
"checa a toolchain minima para validar, gerar e operar a CLI",
|
|
744
|
-
]));
|
|
745
|
-
for (const check of checks) {
|
|
746
|
-
console.log(`- ${check.nome}: ${check.ok ? "ok" : "ausente"}`);
|
|
747
|
-
}
|
|
748
|
-
|
|
749
|
-
const obrigatorios = checks.filter((check) => ["node", "npm"].includes(check.nome));
|
|
750
|
-
return obrigatorios.every((check) => check.ok) ? 0 : 1;
|
|
751
|
-
}
|
|
752
|
-
|
|
753
|
-
function validarCompatibilidadeFramework(alvo: AlvoGeracao, framework: FrameworkGeracao): string | undefined {
|
|
754
|
-
if (framework === "base") {
|
|
755
|
-
return undefined;
|
|
756
|
-
}
|
|
757
|
-
if (framework === "nestjs" && alvo !== "typescript") {
|
|
758
|
-
return `Framework "${framework}" so pode ser usado com o alvo typescript.`;
|
|
759
|
-
}
|
|
760
|
-
if (framework === "fastapi" && alvo !== "python") {
|
|
761
|
-
return `Framework "${framework}" so pode ser usado com o alvo python.`;
|
|
762
|
-
}
|
|
763
|
-
if (alvo === "dart" || alvo === "lua" || alvo === "javascript" || alvo === "html" || alvo === "css") {
|
|
764
|
-
return `Framework "${framework}" nao e suportado para o alvo ${alvo}.`;
|
|
765
|
-
}
|
|
766
|
-
return undefined;
|
|
767
|
-
}
|
|
768
|
-
|
|
769
|
-
function normalizarFonteImportacao(valor: string | undefined): FonteImportacao | undefined {
|
|
770
|
-
if (!valor) {
|
|
771
|
-
return undefined;
|
|
772
|
-
}
|
|
773
|
-
if (valor === "ts") {
|
|
774
|
-
return "typescript";
|
|
775
|
-
}
|
|
776
|
-
if (valor === "py") {
|
|
777
|
-
return "python";
|
|
778
|
-
}
|
|
779
|
-
if (valor === "nest") {
|
|
780
|
-
return "nestjs";
|
|
781
|
-
}
|
|
782
|
-
if (valor === "api") {
|
|
783
|
-
return "fastapi";
|
|
784
|
-
}
|
|
785
|
-
if (valor === "next") {
|
|
786
|
-
return "nextjs";
|
|
787
|
-
}
|
|
788
|
-
if (valor === "next-consumer" || valor === "nextjs-consumer") {
|
|
789
|
-
return "nextjs-consumer";
|
|
790
|
-
}
|
|
791
|
-
if (valor === "react-vite" || valor === "react-vite-consumer" || valor === "react-consumer") {
|
|
792
|
-
return "react-vite-consumer";
|
|
793
|
-
}
|
|
794
|
-
if (valor === "angular" || valor === "angular-consumer") {
|
|
795
|
-
return "angular-consumer";
|
|
796
|
-
}
|
|
797
|
-
if (valor === "flutter" || valor === "flutter-consumer") {
|
|
798
|
-
return "flutter-consumer";
|
|
799
|
-
}
|
|
800
|
-
if (valor === "fb") {
|
|
801
|
-
return "firebase";
|
|
802
|
-
}
|
|
803
|
-
if (valor === "csharp" || valor === "cs" || valor === "dotnet") {
|
|
804
|
-
return "dotnet";
|
|
805
|
-
}
|
|
806
|
-
if (valor === "java") {
|
|
807
|
-
return "java";
|
|
808
|
-
}
|
|
809
|
-
if (valor === "go" || valor === "golang") {
|
|
810
|
-
return "go";
|
|
811
|
-
}
|
|
812
|
-
if (valor === "rust" || valor === "rs") {
|
|
813
|
-
return "rust";
|
|
814
|
-
}
|
|
815
|
-
if (valor === "cpp" || valor === "cxx" || valor === "cc" || valor === "c++") {
|
|
816
|
-
return "cpp";
|
|
817
|
-
}
|
|
818
|
-
if (
|
|
819
|
-
valor === "nestjs"
|
|
820
|
-
|| valor === "fastapi"
|
|
821
|
-
|| valor === "flask"
|
|
822
|
-
|| valor === "nextjs"
|
|
823
|
-
|| valor === "nextjs-consumer"
|
|
824
|
-
|| valor === "react-vite-consumer"
|
|
825
|
-
|| valor === "angular-consumer"
|
|
826
|
-
|| valor === "flutter-consumer"
|
|
827
|
-
|| valor === "firebase"
|
|
828
|
-
|| valor === "dotnet"
|
|
829
|
-
|| valor === "java"
|
|
830
|
-
|| valor === "go"
|
|
831
|
-
|| valor === "rust"
|
|
832
|
-
|| valor === "cpp"
|
|
833
|
-
|| valor === "typescript"
|
|
834
|
-
|| valor === "python"
|
|
835
|
-
|| valor === "dart"
|
|
836
|
-
) {
|
|
837
|
-
return valor;
|
|
838
|
-
}
|
|
839
|
-
return undefined;
|
|
840
|
-
}
|
|
841
|
-
|
|
842
|
-
function normalizarTemplateIniciar(valor?: string): TemplateIniciar {
|
|
843
|
-
if (
|
|
844
|
-
valor === "nestjs"
|
|
845
|
-
|| valor === "fastapi"
|
|
846
|
-
|| valor === "nextjs-api"
|
|
847
|
-
|| valor === "nextjs-consumer"
|
|
848
|
-
|| valor === "react-vite-consumer"
|
|
849
|
-
|| valor === "angular-consumer"
|
|
850
|
-
|| valor === "flutter-consumer"
|
|
851
|
-
|| valor === "node-firebase-worker"
|
|
852
|
-
|| valor === "aspnet-api"
|
|
853
|
-
|| valor === "springboot-api"
|
|
854
|
-
|| valor === "go-http-api"
|
|
855
|
-
|| valor === "rust-axum-api"
|
|
856
|
-
|| valor === "cpp-service-bridge"
|
|
857
|
-
) {
|
|
858
|
-
return valor;
|
|
859
|
-
}
|
|
860
|
-
return "base";
|
|
861
|
-
}
|
|
862
|
-
|
|
863
|
-
function garantirIr(resultado: ReturnType<typeof compilarCodigo>, caminho: string): IrModulo {
|
|
864
|
-
if (!resultado.ir) {
|
|
865
|
-
throw new Error(`Nao foi possivel gerar IR para ${caminho}.\n${formatarDiagnosticos(resultado.diagnosticos)}`);
|
|
866
|
-
}
|
|
867
|
-
return resultado.ir;
|
|
868
|
-
}
|
|
869
|
-
|
|
870
|
-
function gerarArquivosPorAlvo(ir: IrModulo, alvo: AlvoGeracao, framework: FrameworkGeracao) {
|
|
871
|
-
if (alvo === "python") {
|
|
872
|
-
return gerarPython(ir, { framework });
|
|
873
|
-
}
|
|
874
|
-
if (alvo === "dart") {
|
|
875
|
-
return gerarDart(ir);
|
|
876
|
-
}
|
|
877
|
-
if (alvo === "lua") {
|
|
878
|
-
return gerarLua(ir);
|
|
879
|
-
}
|
|
880
|
-
if (alvo === "javascript") {
|
|
881
|
-
return gerarJavaScript(ir);
|
|
882
|
-
}
|
|
883
|
-
if (alvo === "html") {
|
|
884
|
-
return gerarHtml(ir);
|
|
885
|
-
}
|
|
886
|
-
if (alvo === "css") {
|
|
887
|
-
return gerarCss(ir);
|
|
888
|
-
}
|
|
889
|
-
return gerarTypeScript(ir, { framework });
|
|
890
|
-
}
|
|
891
|
-
|
|
892
|
-
function aplicarEstruturaSaida(
|
|
893
|
-
arquivos: Array<{ caminhoRelativo: string; conteudo: string }>,
|
|
894
|
-
ir: IrModulo,
|
|
895
|
-
estrutura: EstruturaSaida,
|
|
896
|
-
): Array<{ caminhoRelativo: string; conteudo: string }> {
|
|
897
|
-
if (estrutura === "flat" || estrutura === "backend") {
|
|
898
|
-
return arquivos;
|
|
899
|
-
}
|
|
900
|
-
|
|
901
|
-
const estruturaModulo = descreverEstruturaModulo(ir.nome);
|
|
902
|
-
const pastaModulo = estruturaModulo.contextoSegmentos.join(path.sep);
|
|
903
|
-
const nomeArquivo = estruturaModulo.nomeArquivo;
|
|
904
|
-
const nomeBaseAntigo = estruturaModulo.nomeBase;
|
|
905
|
-
|
|
906
|
-
return arquivos.map((arquivo) => {
|
|
907
|
-
const basename = path.basename(arquivo.caminhoRelativo);
|
|
908
|
-
let novoBasename = basename;
|
|
909
|
-
let conteudo = arquivo.conteudo;
|
|
910
|
-
|
|
911
|
-
if (basename === `${nomeBaseAntigo}.ts`) {
|
|
912
|
-
novoBasename = `${nomeArquivo}.ts`;
|
|
913
|
-
} else if (basename === `${nomeBaseAntigo}.test.ts`) {
|
|
914
|
-
novoBasename = `${nomeArquivo}.test.ts`;
|
|
915
|
-
conteudo = conteudo.replace(`./${nomeBaseAntigo}.ts`, `./${nomeArquivo}.ts`);
|
|
916
|
-
} else if (basename === `${nomeBaseAntigo}.py`) {
|
|
917
|
-
novoBasename = `${nomeArquivo}.py`;
|
|
918
|
-
} else if (basename === `test_${nomeBaseAntigo}.py`) {
|
|
919
|
-
novoBasename = `test_${nomeArquivo}.py`;
|
|
920
|
-
conteudo = conteudo.replace(`from ${nomeBaseAntigo} import *`, `from ${nomeArquivo} import *`);
|
|
921
|
-
} else if (basename === `${nomeBaseAntigo}.dart`) {
|
|
922
|
-
novoBasename = `${nomeArquivo}.dart`;
|
|
923
|
-
} else if (basename === `${nomeBaseAntigo}.lua`) {
|
|
924
|
-
novoBasename = `${nomeArquivo}.lua`;
|
|
925
|
-
} else if (basename === `test_${nomeBaseAntigo}.lua`) {
|
|
926
|
-
novoBasename = `test_${nomeArquivo}.lua`;
|
|
927
|
-
conteudo = conteudo.replace(`${nomeBaseAntigo}.lua`, `${nomeArquivo}.lua`);
|
|
928
|
-
} else if (basename === `${nomeBaseAntigo}.js`) {
|
|
929
|
-
novoBasename = `${nomeArquivo}.js`;
|
|
930
|
-
} else if (basename === `${nomeBaseAntigo}.test.js`) {
|
|
931
|
-
novoBasename = `${nomeArquivo}.test.js`;
|
|
932
|
-
conteudo = conteudo.replace(`./${nomeBaseAntigo}.js`, `./${nomeArquivo}.js`);
|
|
933
|
-
} else if (basename === `${nomeBaseAntigo}.html`) {
|
|
934
|
-
novoBasename = `${nomeArquivo}.html`;
|
|
935
|
-
} else if (basename === `${nomeBaseAntigo}.css`) {
|
|
936
|
-
novoBasename = `${nomeArquivo}.css`;
|
|
937
|
-
}
|
|
938
|
-
|
|
939
|
-
return {
|
|
940
|
-
caminhoRelativo: pastaModulo ? path.join(pastaModulo, novoBasename) : novoBasename,
|
|
941
|
-
conteudo,
|
|
942
|
-
};
|
|
943
|
-
});
|
|
944
|
-
}
|
|
945
|
-
|
|
946
|
-
function contarCasosDeTesteGerados(alvo: AlvoGeracao, arquivos: Array<{ caminhoRelativo: string; conteudo: string }>): number {
|
|
947
|
-
if (alvo === "dart" || alvo === "html" || alvo === "css") {
|
|
948
|
-
return 0;
|
|
949
|
-
}
|
|
950
|
-
if (alvo === "lua") {
|
|
951
|
-
const arquivoTeste = arquivos.find((item) => path.basename(item.caminhoRelativo).startsWith("test_") && item.caminhoRelativo.endsWith(".lua"));
|
|
952
|
-
if (!arquivoTeste) {
|
|
953
|
-
return 0;
|
|
954
|
-
}
|
|
955
|
-
return (arquivoTeste.conteudo.match(/\blocal function test_/g) ?? []).length;
|
|
956
|
-
}
|
|
957
|
-
|
|
958
|
-
if (alvo === "typescript") {
|
|
959
|
-
const arquivoTeste = arquivos.find((item) => item.caminhoRelativo.endsWith(".test.ts"));
|
|
960
|
-
if (!arquivoTeste) {
|
|
961
|
-
return 0;
|
|
962
|
-
}
|
|
963
|
-
return (arquivoTeste.conteudo.match(/\btest\(/g) ?? []).length;
|
|
964
|
-
}
|
|
965
|
-
|
|
966
|
-
if (alvo === "javascript") {
|
|
967
|
-
const arquivoTeste = arquivos.find((item) => item.caminhoRelativo.endsWith(".test.js"));
|
|
968
|
-
if (!arquivoTeste) {
|
|
969
|
-
return 0;
|
|
970
|
-
}
|
|
971
|
-
return (arquivoTeste.conteudo.match(/\btest\(/g) ?? []).length;
|
|
972
|
-
}
|
|
973
|
-
|
|
974
|
-
const arquivoTeste = arquivos.find((item) => path.basename(item.caminhoRelativo).startsWith("test_"));
|
|
975
|
-
if (!arquivoTeste) {
|
|
976
|
-
return 0;
|
|
977
|
-
}
|
|
978
|
-
return (arquivoTeste.conteudo.match(/\bdef test_/g) ?? []).length;
|
|
979
|
-
}
|
|
980
|
-
|
|
981
|
-
function executarTestesGerados(
|
|
982
|
-
alvo: AlvoGeracao,
|
|
983
|
-
baseSaida: string,
|
|
984
|
-
arquivos: Array<{ caminhoRelativo: string; conteudo: string }>,
|
|
985
|
-
silencioso = false,
|
|
986
|
-
): SaidaTesteCapturada {
|
|
987
|
-
const quantidadeTestes = contarCasosDeTesteGerados(alvo, arquivos);
|
|
988
|
-
if (quantidadeTestes === 0) {
|
|
989
|
-
if (!silencioso) {
|
|
990
|
-
const nomesAlvo: Record<AlvoGeracao, string> = { typescript: "TypeScript", python: "Python", lua: "Lua", dart: "Dart", javascript: "JavaScript", html: "HTML", css: "CSS" };
|
|
991
|
-
console.log(`Nenhum teste ${nomesAlvo[alvo] ?? alvo} foi gerado.`);
|
|
992
|
-
}
|
|
993
|
-
return { codigoSaida: 0, quantidadeTestes, saidaPadrao: "", saidaErro: "" };
|
|
994
|
-
}
|
|
995
|
-
|
|
996
|
-
if (alvo === "html" || alvo === "css") {
|
|
997
|
-
return { codigoSaida: 0, quantidadeTestes: 0, saidaPadrao: "", saidaErro: "" };
|
|
998
|
-
}
|
|
999
|
-
|
|
1000
|
-
if (alvo === "typescript") {
|
|
1001
|
-
const arquivoTeste = arquivos.find((item) => item.caminhoRelativo.endsWith(".test.ts"))?.caminhoRelativo;
|
|
1002
|
-
if (!arquivoTeste) {
|
|
1003
|
-
if (!silencioso) {
|
|
1004
|
-
console.log("Nenhum teste TypeScript foi gerado.");
|
|
1005
|
-
}
|
|
1006
|
-
return { codigoSaida: 0, quantidadeTestes, saidaPadrao: "", saidaErro: "" };
|
|
1007
|
-
}
|
|
1008
|
-
const execucao = spawnSync("node", ["--import", "tsx", path.join(baseSaida, arquivoTeste)], {
|
|
1009
|
-
stdio: silencioso ? "pipe" : "inherit",
|
|
1010
|
-
encoding: silencioso ? "utf8" : undefined,
|
|
1011
|
-
});
|
|
1012
|
-
return {
|
|
1013
|
-
codigoSaida: execucao.status ?? 1,
|
|
1014
|
-
quantidadeTestes,
|
|
1015
|
-
saidaPadrao: typeof execucao.stdout === "string" ? execucao.stdout : "",
|
|
1016
|
-
saidaErro: typeof execucao.stderr === "string" ? execucao.stderr : "",
|
|
1017
|
-
};
|
|
1018
|
-
}
|
|
1019
|
-
|
|
1020
|
-
if (alvo === "javascript") {
|
|
1021
|
-
const arquivoTeste = arquivos.find((item) => item.caminhoRelativo.endsWith(".test.js"))?.caminhoRelativo;
|
|
1022
|
-
if (!arquivoTeste) {
|
|
1023
|
-
if (!silencioso) {
|
|
1024
|
-
console.log("Nenhum teste JavaScript foi gerado.");
|
|
1025
|
-
}
|
|
1026
|
-
return { codigoSaida: 0, quantidadeTestes, saidaPadrao: "", saidaErro: "" };
|
|
1027
|
-
}
|
|
1028
|
-
const execucao = spawnSync("node", ["--test", path.join(baseSaida, arquivoTeste)], {
|
|
1029
|
-
stdio: silencioso ? "pipe" : "inherit",
|
|
1030
|
-
encoding: silencioso ? "utf8" : undefined,
|
|
1031
|
-
});
|
|
1032
|
-
return {
|
|
1033
|
-
codigoSaida: execucao.status ?? 1,
|
|
1034
|
-
quantidadeTestes,
|
|
1035
|
-
saidaPadrao: typeof execucao.stdout === "string" ? execucao.stdout : "",
|
|
1036
|
-
saidaErro: typeof execucao.stderr === "string" ? execucao.stderr : "",
|
|
1037
|
-
};
|
|
1038
|
-
}
|
|
1039
|
-
|
|
1040
|
-
if (alvo === "lua") {
|
|
1041
|
-
const arquivoTeste = arquivos.find((item) => path.basename(item.caminhoRelativo).startsWith("test_") && item.caminhoRelativo.endsWith(".lua"))?.caminhoRelativo;
|
|
1042
|
-
if (!arquivoTeste) {
|
|
1043
|
-
if (!silencioso) {
|
|
1044
|
-
console.log("Nenhum teste Lua foi gerado.");
|
|
1045
|
-
}
|
|
1046
|
-
return { codigoSaida: 0, quantidadeTestes, saidaPadrao: "", saidaErro: "" };
|
|
1047
|
-
}
|
|
1048
|
-
const execucao = spawnSync("lua", [arquivoTeste], {
|
|
1049
|
-
stdio: silencioso ? "pipe" : "inherit",
|
|
1050
|
-
cwd: baseSaida,
|
|
1051
|
-
encoding: silencioso ? "utf8" : undefined,
|
|
1052
|
-
shell: process.platform === "win32",
|
|
1053
|
-
});
|
|
1054
|
-
return {
|
|
1055
|
-
codigoSaida: execucao.status ?? 1,
|
|
1056
|
-
quantidadeTestes,
|
|
1057
|
-
saidaPadrao: typeof execucao.stdout === "string" ? execucao.stdout : "",
|
|
1058
|
-
saidaErro: typeof execucao.stderr === "string" ? execucao.stderr : "",
|
|
1059
|
-
};
|
|
1060
|
-
}
|
|
1061
|
-
|
|
1062
|
-
const arquivoTeste = arquivos.find((item) => path.basename(item.caminhoRelativo).startsWith("test_"))?.caminhoRelativo;
|
|
1063
|
-
if (!arquivoTeste) {
|
|
1064
|
-
if (!silencioso) {
|
|
1065
|
-
console.log("Nenhum teste Python foi gerado.");
|
|
1066
|
-
}
|
|
1067
|
-
return { codigoSaida: 0, quantidadeTestes, saidaPadrao: "", saidaErro: "" };
|
|
1068
|
-
}
|
|
1069
|
-
const execucao = spawnSync("pytest", [arquivoTeste], {
|
|
1070
|
-
stdio: silencioso ? "pipe" : "inherit",
|
|
1071
|
-
cwd: baseSaida,
|
|
1072
|
-
encoding: silencioso ? "utf8" : undefined,
|
|
1073
|
-
});
|
|
1074
|
-
return {
|
|
1075
|
-
codigoSaida: execucao.status ?? 1,
|
|
1076
|
-
quantidadeTestes,
|
|
1077
|
-
saidaPadrao: typeof execucao.stdout === "string" ? execucao.stdout : "",
|
|
1078
|
-
saidaErro: typeof execucao.stderr === "string" ? execucao.stderr : "",
|
|
1079
|
-
};
|
|
1080
|
-
}
|
|
1081
|
-
|
|
1082
|
-
function resolverConfiguracaoVerificacaoPorAlvo(
|
|
1083
|
-
alvo: AlvoGeracao,
|
|
1084
|
-
configCarregada?: Awaited<ReturnType<typeof carregarConfiguracaoProjeto>>,
|
|
1085
|
-
): {
|
|
1086
|
-
framework: FrameworkGeracao;
|
|
1087
|
-
estrutura: EstruturaSaida;
|
|
1088
|
-
incompatibilidade?: string;
|
|
1089
|
-
} {
|
|
1090
|
-
const framework = resolverFrameworkPadrao(undefined, configCarregada);
|
|
1091
|
-
const incompatibilidade = validarCompatibilidadeFramework(alvo, framework);
|
|
1092
|
-
const estrutura = resolverEstruturaSaidaPadrao(undefined, framework, configCarregada);
|
|
1093
|
-
|
|
1094
|
-
return {
|
|
1095
|
-
framework,
|
|
1096
|
-
estrutura,
|
|
1097
|
-
incompatibilidade,
|
|
1098
|
-
};
|
|
1099
|
-
}
|
|
1100
|
-
|
|
1101
|
-
function executarTestesParaVerificacao(
|
|
1102
|
-
alvo: AlvoGeracao,
|
|
1103
|
-
baseSaida: string,
|
|
1104
|
-
arquivos: Array<{ caminhoRelativo: string; conteudo: string }>,
|
|
1105
|
-
framework: FrameworkGeracao,
|
|
1106
|
-
silencioso = false,
|
|
1107
|
-
): {
|
|
1108
|
-
execucao: SaidaTesteCapturada;
|
|
1109
|
-
testesExecutados: boolean;
|
|
1110
|
-
} {
|
|
1111
|
-
if (framework !== "base") {
|
|
1112
|
-
return {
|
|
1113
|
-
execucao: {
|
|
1114
|
-
codigoSaida: 0,
|
|
1115
|
-
quantidadeTestes: 0,
|
|
1116
|
-
saidaPadrao: "",
|
|
1117
|
-
saidaErro: "",
|
|
1118
|
-
},
|
|
1119
|
-
testesExecutados: false,
|
|
1120
|
-
};
|
|
1121
|
-
}
|
|
1122
|
-
|
|
1123
|
-
return {
|
|
1124
|
-
execucao: executarTestesGerados(alvo, baseSaida, arquivos, silencioso),
|
|
1125
|
-
testesExecutados: true,
|
|
1126
|
-
};
|
|
1127
|
-
}
|
|
1128
|
-
|
|
1129
|
-
function nomeSubpastaModulo(caminhoArquivo: string): string {
|
|
1130
|
-
return path.basename(caminhoArquivo, ".sema");
|
|
1131
|
-
}
|
|
1132
|
-
|
|
1133
|
-
async function caminhoExiste(caminhoAlvo: string): Promise<boolean> {
|
|
1134
|
-
try {
|
|
1135
|
-
await stat(caminhoAlvo);
|
|
1136
|
-
return true;
|
|
1137
|
-
} catch {
|
|
1138
|
-
return false;
|
|
1139
|
-
}
|
|
1140
|
-
}
|
|
1141
|
-
|
|
1142
|
-
async function descobrirDocsIa(): Promise<DescobertaDocsIa> {
|
|
1143
|
-
const candidatosBase = [];
|
|
1144
|
-
let atual = DIRETORIO_CLI_ATUAL;
|
|
1145
|
-
|
|
1146
|
-
for (let tentativas = 0; tentativas < 8; tentativas += 1) {
|
|
1147
|
-
candidatosBase.push(atual);
|
|
1148
|
-
const proximo = path.dirname(atual);
|
|
1149
|
-
if (proximo === atual) {
|
|
1150
|
-
break;
|
|
1151
|
-
}
|
|
1152
|
-
atual = proximo;
|
|
1153
|
-
}
|
|
1154
|
-
|
|
1155
|
-
const nomesDocs = [
|
|
1156
|
-
"AGENT_STARTER.md",
|
|
1157
|
-
"como-ensinar-a-sema-para-ia.md",
|
|
1158
|
-
"prompt-base-ia-sema.md",
|
|
1159
|
-
"fluxo-pratico-ia-sema.md",
|
|
1160
|
-
];
|
|
1161
|
-
|
|
1162
|
-
for (const base of candidatosBase) {
|
|
1163
|
-
const documentos = [];
|
|
1164
|
-
let encontrouTodos = true;
|
|
1165
|
-
|
|
1166
|
-
for (const nome of nomesDocs) {
|
|
1167
|
-
const caminhoDoc = path.join(base, "docs", nome);
|
|
1168
|
-
if (!(await caminhoExiste(caminhoDoc))) {
|
|
1169
|
-
encontrouTodos = false;
|
|
1170
|
-
break;
|
|
1171
|
-
}
|
|
1172
|
-
documentos.push({ nome, caminho: caminhoDoc });
|
|
1173
|
-
}
|
|
1174
|
-
|
|
1175
|
-
if (encontrouTodos) {
|
|
1176
|
-
return {
|
|
1177
|
-
origemInstalacao: DIRETORIO_CLI_ATUAL,
|
|
1178
|
-
baseDetectada: base,
|
|
1179
|
-
documentos,
|
|
1180
|
-
};
|
|
1181
|
-
}
|
|
1182
|
-
}
|
|
1183
|
-
|
|
1184
|
-
return {
|
|
1185
|
-
origemInstalacao: DIRETORIO_CLI_ATUAL,
|
|
1186
|
-
baseDetectada: null,
|
|
1187
|
-
documentos: [],
|
|
1188
|
-
};
|
|
1189
|
-
}
|
|
1190
|
-
|
|
1191
|
-
function renderizarCabecalhoDocsIa(descoberta: DescobertaDocsIa): string {
|
|
1192
|
-
const documentos = descoberta.documentos.map((documento) => `\`${documento.nome}\``);
|
|
1193
|
-
const linhas = [
|
|
1194
|
-
"Modo IA-first da instalacao atual",
|
|
1195
|
-
"- Use `sema` como interface publica principal.",
|
|
1196
|
-
"- A Sema entra em projeto novo, projeto ja semantizado e adocao incremental em legado sem contrato inicial.",
|
|
1197
|
-
"- Nao assuma monorepo, `node pacotes/cli/dist/index.js`, `npm run project:check` ou uma pasta `exemplos` externa ao projeto atual.",
|
|
1198
|
-
"- Se a IA tiver contexto curto, comece por `sema resumo` e `sema prompt-curto`.",
|
|
1199
|
-
"- Se a IA aguentar mais contexto, suba para `sema drift --json` e `sema contexto-ia`.",
|
|
1200
|
-
"- So leia `ast.json` e `ir.json` completos quando a capacidade da IA realmente aguentar esse volume.",
|
|
1201
|
-
];
|
|
1202
|
-
|
|
1203
|
-
if (documentos.length > 0) {
|
|
1204
|
-
linhas.push(`- Documentos locais empacotados: ${documentos.join(", ")}.`);
|
|
1205
|
-
} else {
|
|
1206
|
-
linhas.push("- Documentos locais empacotados: nenhum extra detectado. Siga a CLI, o contrato atual e os artefatos JSON.");
|
|
1207
|
-
}
|
|
1208
|
-
|
|
1209
|
-
return linhas.join("\n");
|
|
1210
|
-
}
|
|
1211
|
-
|
|
1212
|
-
function unicos<T>(itens: T[]): T[] {
|
|
1213
|
-
return [...new Set(itens)];
|
|
1214
|
-
}
|
|
1215
|
-
|
|
1216
|
-
function unicosOrdenados(itens: string[]): string[] {
|
|
1217
|
-
return unicos(itens).sort((a, b) => a.localeCompare(b, "pt-BR"));
|
|
1218
|
-
}
|
|
1219
|
-
|
|
1220
|
-
function limitarLista(itens: string[], limite: number): string[] {
|
|
1221
|
-
return itens.slice(0, limite);
|
|
1222
|
-
}
|
|
1223
|
-
|
|
1224
|
-
function resumirListaTexto(itens: string[], limite: number, padrao = "nenhum"): string {
|
|
1225
|
-
if (itens.length === 0) {
|
|
1226
|
-
return padrao;
|
|
1227
|
-
}
|
|
1228
|
-
const visiveis = itens.slice(0, limite);
|
|
1229
|
-
const restante = itens.length - visiveis.length;
|
|
1230
|
-
return restante > 0 ? `${visiveis.join(", ")} (+${restante})` : visiveis.join(", ");
|
|
1231
|
-
}
|
|
1232
|
-
|
|
1233
|
-
function normalizarIdentificadorResumo(valor: string): string {
|
|
1234
|
-
return valor.replace(/[._]/g, " ").replace(/\s+/g, " ").trim();
|
|
1235
|
-
}
|
|
1236
|
-
|
|
1237
|
-
function resumirCamposTask(
|
|
1238
|
-
task: { nome: string; input?: Array<{ nome: string }>; output?: Array<{ nome: string }> },
|
|
1239
|
-
campo: "input" | "output",
|
|
1240
|
-
limiteCampos: number,
|
|
1241
|
-
): string {
|
|
1242
|
-
const campos = (task[campo] ?? []).map((item) => item.nome).slice(0, limiteCampos);
|
|
1243
|
-
if (campos.length === 0) {
|
|
1244
|
-
return `${task.nome}(-)`;
|
|
1245
|
-
}
|
|
1246
|
-
return `${task.nome}(${campos.join(", ")})`;
|
|
1247
|
-
}
|
|
1248
|
-
|
|
1249
|
-
function formatarEfeitoSemanticoResumido(
|
|
1250
|
-
efeito: { categoria: string; alvo: string; criticidade?: string; detalhe?: string; textoOriginal?: string },
|
|
1251
|
-
): string {
|
|
1252
|
-
if (efeito.textoOriginal) {
|
|
1253
|
-
return efeito.textoOriginal;
|
|
1254
|
-
}
|
|
1255
|
-
const partes = [`${efeito.categoria} ${efeito.alvo}`];
|
|
1256
|
-
if (efeito.criticidade) {
|
|
1257
|
-
partes.push(`criticidade=${efeito.criticidade}`);
|
|
1258
|
-
}
|
|
1259
|
-
if (efeito.detalhe) {
|
|
1260
|
-
partes.push(efeito.detalhe);
|
|
1261
|
-
}
|
|
1262
|
-
return partes.join(" ");
|
|
1263
|
-
}
|
|
1264
|
-
|
|
1265
|
-
function calcularRiscoOperacionalResumo(resumoDrift: ResumoModuloDrift): string {
|
|
1266
|
-
if (resumoDrift.tasks.some((task) => task.riscoOperacional === "alto")) {
|
|
1267
|
-
return "alto";
|
|
1268
|
-
}
|
|
1269
|
-
if (resumoDrift.tasks.some((task) => task.riscoOperacional === "medio")) {
|
|
1270
|
-
return "medio";
|
|
1271
|
-
}
|
|
1272
|
-
return "baixo";
|
|
1273
|
-
}
|
|
1274
|
-
|
|
1275
|
-
function descreverFazModulo(ir: IrModulo | null, modulo: string): string {
|
|
1276
|
-
if (!ir) {
|
|
1277
|
-
return `governa o modulo ${normalizarIdentificadorResumo(modulo)}`;
|
|
1278
|
-
}
|
|
1279
|
-
|
|
1280
|
-
const partes: string[] = [];
|
|
1281
|
-
if (ir.routes.length > 0) {
|
|
1282
|
-
partes.push(`${ir.routes.length} rota(s)`);
|
|
1283
|
-
}
|
|
1284
|
-
if (ir.superficies.length > 0) {
|
|
1285
|
-
partes.push(`${ir.superficies.length} superficie(s)`);
|
|
1286
|
-
}
|
|
1287
|
-
if (ir.tasks.length > 0) {
|
|
1288
|
-
partes.push(`${ir.tasks.length} task(s)`);
|
|
1289
|
-
}
|
|
1290
|
-
|
|
1291
|
-
const foco = ir.routes[0]?.nome ?? ir.superficies[0]?.nome ?? ir.tasks[0]?.nome ?? modulo;
|
|
1292
|
-
return partes.length > 0
|
|
1293
|
-
? `governa ${partes.join(", ")} com foco em ${normalizarIdentificadorResumo(foco)}`
|
|
1294
|
-
: `governa o modulo ${normalizarIdentificadorResumo(modulo)}`;
|
|
1295
|
-
}
|
|
1296
|
-
|
|
1297
|
-
function criarGuiaCapacidadeIa(): Record<CapacidadeIa, GuiaCapacidadeIa> {
|
|
1298
|
-
return {
|
|
1299
|
-
pequena: {
|
|
1300
|
-
descricao: "IA gratuita ou com contexto curto. Leia so o cartao semantico e o briefing minimo.",
|
|
1301
|
-
artefatos: ["resumo.micro.txt", "briefing.min.json", "prompt-curto.txt"],
|
|
1302
|
-
ordemLeitura: ["resumo.micro.txt", "briefing.min.json", "resumo.curto.txt"],
|
|
1303
|
-
evitar: ["ast.json", "ir.json", "diagnosticos.json"],
|
|
1304
|
-
},
|
|
1305
|
-
media: {
|
|
1306
|
-
descricao: "IA com contexto medio. Aguenta resumo expandido, briefing minimo e drift.",
|
|
1307
|
-
artefatos: ["resumo.curto.txt", "briefing.min.json", "drift.json", "prompt-curto.txt"],
|
|
1308
|
-
ordemLeitura: ["resumo.curto.txt", "briefing.min.json", "drift.json", "resumo.md"],
|
|
1309
|
-
evitar: ["ast.json"],
|
|
1310
|
-
},
|
|
1311
|
-
grande: {
|
|
1312
|
-
descricao: "IA com contexto grande ou tool use. Pode consumir o pacote completo.",
|
|
1313
|
-
artefatos: ["README.md", "resumo.md", "briefing.json", "drift.json", "ir.json", "ast.json"],
|
|
1314
|
-
ordemLeitura: ["README.md", "resumo.md", "briefing.json", "drift.json", "ir.json", "ast.json"],
|
|
1315
|
-
evitar: [],
|
|
1316
|
-
},
|
|
1317
|
-
};
|
|
1318
|
-
}
|
|
1319
|
-
|
|
1320
|
-
function coletarResumoSemanticoModulo(
|
|
1321
|
-
contexto: Pick<PacoteContextoModuloIa, "arquivo" | "modulo" | "geradoEm" | "ir" | "briefing" | "drift">,
|
|
1322
|
-
): ResumoSemanticoModuloIa {
|
|
1323
|
-
const { arquivo, modulo, geradoEm, ir, briefing, drift } = contexto;
|
|
1324
|
-
const tarefas = ir?.tasks ?? [];
|
|
1325
|
-
const rotas = ir?.routes ?? [];
|
|
1326
|
-
const superficies = ir?.superficies ?? [];
|
|
1327
|
-
const regrasCriticas = unicosOrdenados([
|
|
1328
|
-
...tarefas.flatMap((task) => task.rules),
|
|
1329
|
-
...tarefas.flatMap((task) => task.guarantees),
|
|
1330
|
-
]);
|
|
1331
|
-
const efeitos = unicosOrdenados([
|
|
1332
|
-
...tarefas.flatMap((task) => task.effects),
|
|
1333
|
-
...rotas.flatMap((route) => route.efeitosPublicos.map((efeito) => formatarEfeitoSemanticoResumido(efeito))),
|
|
1334
|
-
...superficies.flatMap((superficie) => superficie.effects.map((efeito) => formatarEfeitoSemanticoResumido(efeito))),
|
|
1335
|
-
]);
|
|
1336
|
-
const erros = unicosOrdenados([
|
|
1337
|
-
...tarefas.flatMap((task) => Object.keys(task.errors)),
|
|
1338
|
-
...tarefas.flatMap((task) => task.errosDetalhados.map((erro) => erro.codigo)),
|
|
1339
|
-
...rotas.flatMap((route) => route.errosPublicos.map((erro) => erro.codigo)),
|
|
1340
|
-
]);
|
|
1341
|
-
const entidadesAfetadas = unicosOrdenados([
|
|
1342
|
-
...(ir?.resumoAgente.entidadesAfetadas ?? []),
|
|
1343
|
-
...tarefas.flatMap((task) => task.resumoAgente.entidadesAfetadas),
|
|
1344
|
-
...rotas.flatMap((route) => route.resumoAgente.entidadesAfetadas),
|
|
1345
|
-
...superficies.flatMap((superficie) => superficie.resumoAgente.entidadesAfetadas),
|
|
1346
|
-
]);
|
|
1347
|
-
|
|
1348
|
-
return {
|
|
1349
|
-
geradoEm,
|
|
1350
|
-
arquivo,
|
|
1351
|
-
modulo,
|
|
1352
|
-
perfilCompatibilidade: ir?.perfilCompatibilidade ?? briefing.perfilCompatibilidade,
|
|
1353
|
-
scoreSemantico: briefing.scoreSemantico,
|
|
1354
|
-
confiancaGeral: briefing.confiancaGeral,
|
|
1355
|
-
riscoOperacional: calcularRiscoOperacionalResumo(drift.resumo),
|
|
1356
|
-
faz: descreverFazModulo(ir, modulo),
|
|
1357
|
-
tarefasPrincipais: limitarLista(tarefas.map((task) => task.nome), 6),
|
|
1358
|
-
entradasChave: limitarLista(tarefas.map((task) => resumirCamposTask(task, "input", 4)), 4),
|
|
1359
|
-
saidasChave: limitarLista(tarefas.map((task) => resumirCamposTask(task, "output", 4)), 4),
|
|
1360
|
-
superficiesPublicas: limitarLista(unicosOrdenados([
|
|
1361
|
-
...briefing.superficiesImpactadas,
|
|
1362
|
-
...rotas.map((route) => `${route.metodo ?? "?"} ${route.caminho ?? route.nome}`),
|
|
1363
|
-
]), 8),
|
|
1364
|
-
regrasCriticas: limitarLista(regrasCriticas, 8),
|
|
1365
|
-
efeitos: limitarLista(efeitos, 8),
|
|
1366
|
-
erros: limitarLista(erros, 8),
|
|
1367
|
-
entidadesAfetadas: limitarLista(entidadesAfetadas, 8),
|
|
1368
|
-
arquivosProvaveis: limitarLista(unicosOrdenados(briefing.oQueTocar), 8),
|
|
1369
|
-
simbolosRelacionados: limitarLista(unicosOrdenados(briefing.simbolosRelacionados), 8),
|
|
1370
|
-
riscosPrincipais: limitarLista(unicosOrdenados(briefing.riscosPrincipais), 6),
|
|
1371
|
-
lacunas: limitarLista(unicosOrdenados(briefing.oQueEstaFrouxo), 6),
|
|
1372
|
-
inferido: limitarLista(unicosOrdenados(briefing.oQueFoiInferido), 6),
|
|
1373
|
-
checksSugeridos: limitarLista(unicosOrdenados(briefing.oQueValidar), 6),
|
|
1374
|
-
testesMinimos: limitarLista(unicosOrdenados(briefing.testesMinimos), 6),
|
|
1375
|
-
consumerFramework: briefing.consumerFramework ?? drift.drift.consumerFramework ?? null,
|
|
1376
|
-
appRoutes: limitarLista(unicosOrdenados(briefing.appRoutes ?? drift.drift.appRoutes ?? []), 8),
|
|
1377
|
-
consumerSurfaces: limitarLista(unicosOrdenados(briefing.consumerSurfaces ?? []), 8),
|
|
1378
|
-
consumerBridges: limitarLista(unicosOrdenados(briefing.consumerBridges ?? []), 8),
|
|
1379
|
-
arquivosProvaveisEditar: limitarLista(unicosOrdenados(briefing.arquivosProvaveisEditar ?? briefing.oQueTocar), 8),
|
|
1380
|
-
};
|
|
1381
|
-
}
|
|
1382
|
-
|
|
1383
|
-
function renderizarResumoModuloTexto(
|
|
1384
|
-
resumo: ResumoSemanticoModuloIa,
|
|
1385
|
-
tamanho: TamanhoResumoIa,
|
|
1386
|
-
modo: ModoResumoIa,
|
|
1387
|
-
): string {
|
|
1388
|
-
const limite = tamanho === "micro" ? 2 : tamanho === "curto" ? 4 : 6;
|
|
1389
|
-
const linhas = [
|
|
1390
|
-
`MODO: ${modo}`,
|
|
1391
|
-
`MODULO: ${resumo.modulo}`,
|
|
1392
|
-
`FAZ: ${resumo.faz}`,
|
|
1393
|
-
`PERFIL: ${resumo.perfilCompatibilidade}`,
|
|
1394
|
-
`CONSUMER_FRAMEWORK: ${resumo.consumerFramework ?? "nenhum"}`,
|
|
1395
|
-
`APP_ROUTES: ${resumirListaTexto(resumo.appRoutes, limite)}`,
|
|
1396
|
-
`CONSUMER_SURFACES: ${resumirListaTexto(resumo.consumerSurfaces, limite)}`,
|
|
1397
|
-
`CONSUMER_BRIDGES: ${resumirListaTexto(resumo.consumerBridges, limite)}`,
|
|
1398
|
-
`PUBLICO: ${resumirListaTexto(resumo.superficiesPublicas, limite)}`,
|
|
1399
|
-
`TAREFAS: ${resumirListaTexto(resumo.tarefasPrincipais, limite)}`,
|
|
1400
|
-
`ENTRADAS: ${resumirListaTexto(resumo.entradasChave, limite)}`,
|
|
1401
|
-
`SAIDAS: ${resumirListaTexto(resumo.saidasChave, limite)}`,
|
|
1402
|
-
`REGRAS: ${resumirListaTexto(resumo.regrasCriticas, limite)}`,
|
|
1403
|
-
`EFEITOS: ${resumirListaTexto(resumo.efeitos, limite)}`,
|
|
1404
|
-
`ERROS: ${resumirListaTexto(resumo.erros, limite)}`,
|
|
1405
|
-
`TOCAR: ${resumirListaTexto(resumo.arquivosProvaveis, limite)}`,
|
|
1406
|
-
`VALIDAR: ${resumirListaTexto(resumo.checksSugeridos, limite)}`,
|
|
1407
|
-
`TESTES: ${resumirListaTexto(resumo.testesMinimos, limite)}`,
|
|
1408
|
-
`RISCOS: ${resumirListaTexto(resumo.riscosPrincipais, limite)}`,
|
|
1409
|
-
`LACUNAS: ${resumirListaTexto(resumo.lacunas, limite)}`,
|
|
1410
|
-
`INFERIDO: ${resumirListaTexto(resumo.inferido, limite)}`,
|
|
1411
|
-
`CONFIANCA: ${resumo.confiancaGeral}`,
|
|
1412
|
-
`RISCO_OPERACIONAL: ${resumo.riscoOperacional}`,
|
|
1413
|
-
`SCORE: ${resumo.scoreSemantico}`,
|
|
1414
|
-
`GERADO_EM: ${resumo.geradoEm}`,
|
|
1415
|
-
];
|
|
1416
|
-
|
|
1417
|
-
if (tamanho === "micro") {
|
|
1418
|
-
return `${linhas.slice(0, 12).join("\n")}\n`;
|
|
1419
|
-
}
|
|
1420
|
-
|
|
1421
|
-
return `${linhas.join("\n")}\n`;
|
|
1422
|
-
}
|
|
1423
|
-
|
|
1424
|
-
function renderizarResumoModuloMarkdown(
|
|
1425
|
-
resumo: ResumoSemanticoModuloIa,
|
|
1426
|
-
modo: ModoResumoIa,
|
|
1427
|
-
guiaPorCapacidade: Record<CapacidadeIa, GuiaCapacidadeIa>,
|
|
1428
|
-
): string {
|
|
1429
|
-
const linhas = [
|
|
1430
|
-
`# Resumo Sema para ${resumo.modulo}`,
|
|
1431
|
-
"",
|
|
1432
|
-
`- Modo: \`${modo}\``,
|
|
1433
|
-
`- Gerado em: \`${resumo.geradoEm}\``,
|
|
1434
|
-
`- Arquivo: \`${resumo.arquivo}\``,
|
|
1435
|
-
`- Perfil: \`${resumo.perfilCompatibilidade}\``,
|
|
1436
|
-
`- Score: \`${resumo.scoreSemantico}\``,
|
|
1437
|
-
`- Confianca: \`${resumo.confiancaGeral}\``,
|
|
1438
|
-
`- Risco operacional: \`${resumo.riscoOperacional}\``,
|
|
1439
|
-
"",
|
|
1440
|
-
"## O que este modulo faz",
|
|
1441
|
-
"",
|
|
1442
|
-
`- ${resumo.faz}`,
|
|
1443
|
-
`- Superficies publicas: ${resumirListaTexto(resumo.superficiesPublicas, 8)}`,
|
|
1444
|
-
`- Tarefas principais: ${resumirListaTexto(resumo.tarefasPrincipais, 8)}`,
|
|
1445
|
-
"",
|
|
1446
|
-
"## Contrato util para IA",
|
|
1447
|
-
"",
|
|
1448
|
-
`- Entradas chave: ${resumirListaTexto(resumo.entradasChave, 6)}`,
|
|
1449
|
-
`- Saidas chave: ${resumirListaTexto(resumo.saidasChave, 6)}`,
|
|
1450
|
-
`- Regras criticas: ${resumirListaTexto(resumo.regrasCriticas, 6)}`,
|
|
1451
|
-
`- Efeitos: ${resumirListaTexto(resumo.efeitos, 6)}`,
|
|
1452
|
-
`- Erros: ${resumirListaTexto(resumo.erros, 6)}`,
|
|
1453
|
-
`- Entidades afetadas: ${resumirListaTexto(resumo.entidadesAfetadas, 6)}`,
|
|
1454
|
-
"",
|
|
1455
|
-
...(resumo.consumerFramework
|
|
1456
|
-
? [
|
|
1457
|
-
"## Consumer IA-first",
|
|
1458
|
-
"",
|
|
1459
|
-
`- Framework consumer: ${resumo.consumerFramework}`,
|
|
1460
|
-
`- Rotas de app: ${resumirListaTexto(resumo.appRoutes, 6)}`,
|
|
1461
|
-
`- Superficies consumer: ${resumirListaTexto(resumo.consumerSurfaces, 6)}`,
|
|
1462
|
-
`- Bridges consumer: ${resumirListaTexto(resumo.consumerBridges, 6)}`,
|
|
1463
|
-
"",
|
|
1464
|
-
]
|
|
1465
|
-
: []),
|
|
1466
|
-
"## Intervencao segura",
|
|
1467
|
-
"",
|
|
1468
|
-
`- Arquivos provaveis: ${resumirListaTexto(resumo.arquivosProvaveis, 6)}`,
|
|
1469
|
-
`- Simbolos relacionados: ${resumirListaTexto(resumo.simbolosRelacionados, 6)}`,
|
|
1470
|
-
`- Riscos principais: ${resumirListaTexto(resumo.riscosPrincipais, 6)}`,
|
|
1471
|
-
`- Lacunas: ${resumirListaTexto(resumo.lacunas, 6)}`,
|
|
1472
|
-
`- O que foi inferido: ${resumirListaTexto(resumo.inferido, 6)}`,
|
|
1473
|
-
`- Checks sugeridos: ${resumirListaTexto(resumo.checksSugeridos, 6)}`,
|
|
1474
|
-
`- Testes minimos: ${resumirListaTexto(resumo.testesMinimos, 6)}`,
|
|
1475
|
-
"",
|
|
1476
|
-
"## Guia por capacidade de IA",
|
|
1477
|
-
"",
|
|
1478
|
-
];
|
|
1479
|
-
|
|
1480
|
-
for (const capacidade of ["pequena", "media", "grande"] as const) {
|
|
1481
|
-
const guia = guiaPorCapacidade[capacidade];
|
|
1482
|
-
linhas.push(`### ${capacidade}`);
|
|
1483
|
-
linhas.push("");
|
|
1484
|
-
linhas.push(`- ${guia.descricao}`);
|
|
1485
|
-
linhas.push(`- Artefatos: ${guia.artefatos.map((item) => `\`${item}\``).join(", ")}`);
|
|
1486
|
-
linhas.push(`- Ordem de leitura: ${guia.ordemLeitura.map((item) => `\`${item}\``).join(" -> ")}`);
|
|
1487
|
-
linhas.push(`- Evitar: ${guia.evitar.length > 0 ? guia.evitar.map((item) => `\`${item}\``).join(", ") : "nada obrigatorio"}`);
|
|
1488
|
-
linhas.push("");
|
|
1489
|
-
}
|
|
1490
|
-
|
|
1491
|
-
return `${linhas.join("\n").trim()}\n`;
|
|
1492
|
-
}
|
|
1493
|
-
|
|
1494
|
-
function criarBriefingMinimo(
|
|
1495
|
-
resumo: ResumoSemanticoModuloIa,
|
|
1496
|
-
modo: ModoResumoIa,
|
|
1497
|
-
tamanho: TamanhoResumoIa,
|
|
1498
|
-
): Record<string, unknown> {
|
|
1499
|
-
return {
|
|
1500
|
-
comando: "briefing-minimo",
|
|
1501
|
-
geradoEm: resumo.geradoEm,
|
|
1502
|
-
cliVersao: VERSAO_CLI,
|
|
1503
|
-
modo,
|
|
1504
|
-
tamanho,
|
|
1505
|
-
arquivo: resumo.arquivo,
|
|
1506
|
-
modulo: resumo.modulo,
|
|
1507
|
-
perfilCompatibilidade: resumo.perfilCompatibilidade,
|
|
1508
|
-
scoreSemantico: resumo.scoreSemantico,
|
|
1509
|
-
confiancaGeral: resumo.confiancaGeral,
|
|
1510
|
-
riscoOperacional: resumo.riscoOperacional,
|
|
1511
|
-
faz: resumo.faz,
|
|
1512
|
-
publico: resumo.superficiesPublicas,
|
|
1513
|
-
tarefasPrincipais: resumo.tarefasPrincipais,
|
|
1514
|
-
entradasChave: resumo.entradasChave,
|
|
1515
|
-
saidasChave: resumo.saidasChave,
|
|
1516
|
-
regrasCriticas: resumo.regrasCriticas,
|
|
1517
|
-
efeitos: resumo.efeitos,
|
|
1518
|
-
erros: resumo.erros,
|
|
1519
|
-
arquivosProvaveis: resumo.arquivosProvaveis,
|
|
1520
|
-
arquivosProvaveisEditar: resumo.arquivosProvaveisEditar,
|
|
1521
|
-
simbolosRelacionados: resumo.simbolosRelacionados,
|
|
1522
|
-
riscosPrincipais: resumo.riscosPrincipais,
|
|
1523
|
-
lacunas: resumo.lacunas,
|
|
1524
|
-
inferido: resumo.inferido,
|
|
1525
|
-
checksSugeridos: resumo.checksSugeridos,
|
|
1526
|
-
testesMinimos: resumo.testesMinimos,
|
|
1527
|
-
consumerFramework: resumo.consumerFramework,
|
|
1528
|
-
appRoutes: resumo.appRoutes,
|
|
1529
|
-
consumerSurfaces: resumo.consumerSurfaces,
|
|
1530
|
-
consumerBridges: resumo.consumerBridges,
|
|
1531
|
-
};
|
|
1532
|
-
}
|
|
1533
|
-
|
|
1534
|
-
function criarPromptCurtoModulo(
|
|
1535
|
-
resumo: ResumoSemanticoModuloIa,
|
|
1536
|
-
modo: ModoResumoIa,
|
|
1537
|
-
tamanho: TamanhoResumoIa,
|
|
1538
|
-
capacidade: CapacidadeIa,
|
|
1539
|
-
): string {
|
|
1540
|
-
const resumoTexto = renderizarResumoModuloTexto(resumo, tamanho, modo).trim();
|
|
1541
|
-
return `Voce esta operando Sema em modo IA-first.
|
|
1542
|
-
|
|
1543
|
-
Esta linguagem nao foi desenhada para agradar humano; ela existe para reduzir ambiguidade para IA.
|
|
1544
|
-
|
|
1545
|
-
Capacidade alvo: ${capacidade}
|
|
1546
|
-
Modo da tarefa: ${modo}
|
|
1547
|
-
|
|
1548
|
-
Regras:
|
|
1549
|
-
- nao invente sintaxe nem bloco fora da gramatica oficial
|
|
1550
|
-
- preserve a intencao do contrato
|
|
1551
|
-
- use este resumo como fonte compacta inicial
|
|
1552
|
-
- se a tarefa pedir mais contexto, suba para \`briefing.min.json\`, \`drift.json\` e depois \`ir.json\`
|
|
1553
|
-
- nao saia editando software vivo sem olhar risco, lacuna e checks sugeridos
|
|
1554
|
-
${resumo.consumerFramework ? "- se for tarefa visual consumer, priorize `appRoutes`, `consumerSurfaces` e `consumerBridges` antes de abrir arquivos aleatorios" : ""}
|
|
1555
|
-
|
|
1556
|
-
Contexto compacto:
|
|
1557
|
-
${resumoTexto}
|
|
1558
|
-
`;
|
|
1559
|
-
}
|
|
1560
|
-
|
|
1561
|
-
function renderizarResumoProjetoMarkdown(
|
|
1562
|
-
geradoEm: string,
|
|
1563
|
-
modulos: ResumoSemanticoModuloIa[],
|
|
1564
|
-
guiaPorCapacidade: Record<CapacidadeIa, GuiaCapacidadeIa>,
|
|
1565
|
-
): string {
|
|
1566
|
-
const entradaCanonica = criarEntradaCanonicaProjeto(guiaPorCapacidade);
|
|
1567
|
-
const linhas = [
|
|
1568
|
-
"# SEMA_BRIEF",
|
|
1569
|
-
"",
|
|
1570
|
-
"Sema e IA-first. Este arquivo existe para IA achar o ponto de entrada do projeto sem ter que catar o repo inteiro feito barata tonta.",
|
|
1571
|
-
"",
|
|
1572
|
-
`- Gerado em: \`${geradoEm}\``,
|
|
1573
|
-
`- Modulos: \`${modulos.length}\``,
|
|
1574
|
-
"",
|
|
1575
|
-
"## Entrada canonica para IA",
|
|
1576
|
-
"",
|
|
1577
|
-
`- Ordem minima: ${entradaCanonica.ordemLeitura.join(" -> ")}`,
|
|
1578
|
-
`- IA pequena: ${entradaCanonica.porCapacidade.pequena.join(" -> ")}`,
|
|
1579
|
-
`- IA media: ${entradaCanonica.porCapacidade.media.join(" -> ")}`,
|
|
1580
|
-
`- IA grande: ${entradaCanonica.porCapacidade.grande.join(" -> ")}`,
|
|
1581
|
-
"",
|
|
1582
|
-
"## Guia por capacidade",
|
|
1583
|
-
"",
|
|
1584
|
-
];
|
|
1585
|
-
|
|
1586
|
-
for (const capacidade of ["pequena", "media", "grande"] as const) {
|
|
1587
|
-
const guia = guiaPorCapacidade[capacidade];
|
|
1588
|
-
linhas.push(`- ${capacidade}: ${guia.descricao} Artefatos: ${guia.artefatos.join(", ")}.`);
|
|
1589
|
-
}
|
|
1590
|
-
|
|
1591
|
-
linhas.push("");
|
|
1592
|
-
linhas.push("## Modulos");
|
|
1593
|
-
linhas.push("");
|
|
1594
|
-
|
|
1595
|
-
for (const modulo of modulos) {
|
|
1596
|
-
linhas.push(`### ${modulo.modulo}`);
|
|
1597
|
-
linhas.push(`- Faz: ${modulo.faz}`);
|
|
1598
|
-
linhas.push(`- Publico: ${resumirListaTexto(modulo.superficiesPublicas, 4)}`);
|
|
1599
|
-
linhas.push(`- Tocar: ${resumirListaTexto(modulo.arquivosProvaveis, 4)}`);
|
|
1600
|
-
linhas.push(`- Score: ${modulo.scoreSemantico} | Confianca: ${modulo.confiancaGeral} | Risco: ${modulo.riscoOperacional}`);
|
|
1601
|
-
linhas.push(`- Lacunas: ${resumirListaTexto(modulo.lacunas, 4)}`);
|
|
1602
|
-
linhas.push("");
|
|
1603
|
-
}
|
|
1604
|
-
|
|
1605
|
-
return `${linhas.join("\n").trim()}\n`;
|
|
1606
|
-
}
|
|
1607
|
-
|
|
1608
|
-
function criarEntradaCanonicaProjeto(guiaPorCapacidade: Record<CapacidadeIa, GuiaCapacidadeIa>) {
|
|
1609
|
-
return {
|
|
1610
|
-
descricao: "Entrada canonica do repositorio para IA. O repo nao e human-first; a IA deve começar por esses artefatos antes de abrir codigo cru.",
|
|
1611
|
-
ordemLeitura: [...ARQUIVOS_CANONICOS_IA_RAIZ],
|
|
1612
|
-
porCapacidade: {
|
|
1613
|
-
pequena: ["llms.txt", "SEMA_BRIEF.micro.txt", "SEMA_INDEX.json", "AGENTS.md"],
|
|
1614
|
-
media: ["llms.txt", "SEMA_BRIEF.curto.txt", "SEMA_INDEX.json", "AGENTS.md", "README.md"],
|
|
1615
|
-
grande: ["llms-full.txt", "SEMA_BRIEF.md", "SEMA_INDEX.json", "AGENTS.md", "README.md"],
|
|
1616
|
-
},
|
|
1617
|
-
docsSuporte: [...DOCUMENTOS_SUPORTE_IA],
|
|
1618
|
-
guiaPorCapacidade,
|
|
1619
|
-
};
|
|
1620
|
-
}
|
|
1621
|
-
|
|
1622
|
-
function falharContextoIa(mensagem: string): never {
|
|
1623
|
-
throw new Error(mensagem);
|
|
1624
|
-
}
|
|
1625
|
-
|
|
1626
|
-
function garantirArquivoSema(caminhoArquivo: string): void {
|
|
1627
|
-
if (!caminhoArquivo.toLowerCase().endsWith(".sema")) {
|
|
1628
|
-
falharContextoIa("O caminho informado precisa apontar para um arquivo .sema.");
|
|
1629
|
-
}
|
|
1630
|
-
}
|
|
1631
|
-
|
|
1632
|
-
function resumirDriftPorModulo(
|
|
1633
|
-
modulo: string | null,
|
|
1634
|
-
caminho: string,
|
|
1635
|
-
resultadoDrift: Awaited<ReturnType<typeof analisarDriftLegado>>,
|
|
1636
|
-
) {
|
|
1637
|
-
const tasks = modulo
|
|
1638
|
-
? resultadoDrift.tasks.filter((task) => task.modulo === modulo)
|
|
1639
|
-
: [];
|
|
1640
|
-
const implsValidos = modulo
|
|
1641
|
-
? resultadoDrift.impls_validos.filter((impl) => impl.modulo === modulo)
|
|
1642
|
-
: [];
|
|
1643
|
-
const implsQuebrados = modulo
|
|
1644
|
-
? resultadoDrift.impls_quebrados.filter((impl) => impl.modulo === modulo)
|
|
1645
|
-
: [];
|
|
1646
|
-
const vinculosValidos = modulo
|
|
1647
|
-
? resultadoDrift.vinculos_validos.filter((vinculo) => vinculo.modulo === modulo)
|
|
1648
|
-
: [];
|
|
1649
|
-
const vinculosQuebrados = modulo
|
|
1650
|
-
? resultadoDrift.vinculos_quebrados.filter((vinculo) => vinculo.modulo === modulo)
|
|
1651
|
-
: [];
|
|
1652
|
-
const rotasDivergentes = modulo
|
|
1653
|
-
? resultadoDrift.rotas_divergentes.filter((rota) => rota.modulo === modulo)
|
|
1654
|
-
: [];
|
|
1655
|
-
const recursosValidos = modulo
|
|
1656
|
-
? resultadoDrift.recursos_validos.filter((recurso) => recurso.modulo === modulo)
|
|
1657
|
-
: [];
|
|
1658
|
-
const recursosDivergentes = modulo
|
|
1659
|
-
? resultadoDrift.recursos_divergentes.filter((recurso) => recurso.modulo === modulo)
|
|
1660
|
-
: [];
|
|
1661
|
-
const vinculosModulo = modulo
|
|
1662
|
-
? [
|
|
1663
|
-
...resultadoDrift.vinculos_validos.filter((vinculo) => vinculo.modulo === modulo),
|
|
1664
|
-
...resultadoDrift.vinculos_quebrados.filter((vinculo) => vinculo.modulo === modulo),
|
|
1665
|
-
]
|
|
1666
|
-
: [];
|
|
1667
|
-
const rotasConsumerModulo = new Set(
|
|
1668
|
-
vinculosModulo
|
|
1669
|
-
.filter((vinculo) => vinculo.tipo === "superficie")
|
|
1670
|
-
.map((vinculo) => vinculo.valor),
|
|
1671
|
-
);
|
|
1672
|
-
const arquivosRelacionados = [...new Set([
|
|
1673
|
-
...tasks.flatMap((task) => task.arquivosReferenciados),
|
|
1674
|
-
...tasks.flatMap((task) => task.arquivosProvaveisEditar),
|
|
1675
|
-
...implsValidos.map((impl) => impl.arquivo).filter((item): item is string => Boolean(item)),
|
|
1676
|
-
...implsQuebrados.flatMap((impl) => impl.candidatos?.map((candidato) => candidato.arquivo) ?? []),
|
|
1677
|
-
...vinculosValidos.map((vinculo) => vinculo.arquivo).filter((item): item is string => Boolean(item)),
|
|
1678
|
-
...recursosValidos.map((recurso) => recurso.arquivo).filter(Boolean),
|
|
1679
|
-
...recursosDivergentes.map((recurso) => recurso.arquivo).filter(Boolean),
|
|
1680
|
-
])].sort((a, b) => a.localeCompare(b, "pt-BR"));
|
|
1681
|
-
const consumerSurfaces = resultadoDrift.consumerSurfaces
|
|
1682
|
-
.filter((surface) =>
|
|
1683
|
-
arquivosRelacionados.includes(surface.arquivo)
|
|
1684
|
-
|| rotasConsumerModulo.has(surface.rota))
|
|
1685
|
-
.map((surface) => `${surface.tipoArquivo}:${surface.rota} -> ${surface.arquivo}`)
|
|
1686
|
-
.sort((a, b) => a.localeCompare(b, "pt-BR"));
|
|
1687
|
-
const consumerBridges = resultadoDrift.consumerBridges
|
|
1688
|
-
.filter((bridge) => arquivosRelacionados.includes(bridge.arquivo))
|
|
1689
|
-
.map((bridge) => bridge.caminho)
|
|
1690
|
-
.sort((a, b) => a.localeCompare(b, "pt-BR"));
|
|
1691
|
-
const appRoutes = [...new Set(resultadoDrift.consumerSurfaces
|
|
1692
|
-
.filter((surface) =>
|
|
1693
|
-
arquivosRelacionados.includes(surface.arquivo)
|
|
1694
|
-
|| rotasConsumerModulo.has(surface.rota))
|
|
1695
|
-
.map((surface) => surface.rota))]
|
|
1696
|
-
.sort((a, b) => a.localeCompare(b, "pt-BR"));
|
|
1697
|
-
const consumerFramework = appRoutes.length > 0 || consumerBridges.length > 0
|
|
1698
|
-
? resultadoDrift.consumerFramework
|
|
1699
|
-
: null;
|
|
1700
|
-
|
|
1701
|
-
return {
|
|
1702
|
-
caminho,
|
|
1703
|
-
modulo,
|
|
1704
|
-
implsValidos: implsValidos.length,
|
|
1705
|
-
implsQuebrados: implsQuebrados.length,
|
|
1706
|
-
vinculosValidos: vinculosValidos.length,
|
|
1707
|
-
vinculosQuebrados: vinculosQuebrados.length,
|
|
1708
|
-
recursosValidos: recursosValidos.length,
|
|
1709
|
-
recursosDivergentesCount: recursosDivergentes.length,
|
|
1710
|
-
tasksSemImplementacao: tasks.filter((task) => task.semImplementacao).length,
|
|
1711
|
-
scoreMedio: tasks.length > 0 ? Math.round(tasks.reduce((total, task) => total + task.scoreSemantico, 0) / tasks.length) : 0,
|
|
1712
|
-
confiancaGeral: tasks.some((task) => task.confiancaVinculo === "alta")
|
|
1713
|
-
? "alta"
|
|
1714
|
-
: tasks.some((task) => task.confiancaVinculo === "media")
|
|
1715
|
-
? "media"
|
|
1716
|
-
: "baixa",
|
|
1717
|
-
arquivosRelacionados,
|
|
1718
|
-
arquivosProvaveisEditar: arquivosRelacionados,
|
|
1719
|
-
consumerFramework,
|
|
1720
|
-
appRoutes,
|
|
1721
|
-
consumerSurfaces,
|
|
1722
|
-
consumerBridges,
|
|
1723
|
-
checksSugeridos: [...new Set(tasks.flatMap((task) => task.checksSugeridos))],
|
|
1724
|
-
lacunas: [...new Set(tasks.flatMap((task) => task.lacunas))],
|
|
1725
|
-
tasks,
|
|
1726
|
-
rotasDivergentes,
|
|
1727
|
-
recursosDivergentes,
|
|
1728
|
-
vinculosQuebradosDetalhes: vinculosQuebrados,
|
|
1729
|
-
};
|
|
1730
|
-
}
|
|
1731
|
-
|
|
1732
|
-
function criarBriefingAgente(
|
|
1733
|
-
arquivo: string,
|
|
1734
|
-
modulo: string,
|
|
1735
|
-
ir: IrModulo | null,
|
|
1736
|
-
resumoDrift: ReturnType<typeof resumirDriftPorModulo>,
|
|
1737
|
-
resultadoDrift: Awaited<ReturnType<typeof analisarDriftLegado>>,
|
|
1738
|
-
) {
|
|
1739
|
-
const tarefasModulo = resultadoDrift.tasks.filter((task) => task.modulo === modulo);
|
|
1740
|
-
return {
|
|
1741
|
-
arquivo,
|
|
1742
|
-
modulo,
|
|
1743
|
-
perfilCompatibilidade: ir?.perfilCompatibilidade ?? "interno",
|
|
1744
|
-
scoreSemantico: resumoDrift.scoreMedio,
|
|
1745
|
-
confiancaGeral: resumoDrift.confiancaGeral,
|
|
1746
|
-
riscosPrincipais: [...new Set([
|
|
1747
|
-
...resultadoDrift.resumo_operacional.riscosPrincipais.filter((item) => item.startsWith(`${modulo}:`) || tarefasModulo.some((task) => item.startsWith(`${task.task}:`))),
|
|
1748
|
-
...(ir?.resumoAgente.riscos ?? []),
|
|
1749
|
-
])],
|
|
1750
|
-
oQueTocar: resumoDrift.arquivosRelacionados,
|
|
1751
|
-
arquivosProvaveisEditar: resumoDrift.arquivosProvaveisEditar,
|
|
1752
|
-
oQueValidar: [...new Set([
|
|
1753
|
-
...resumoDrift.checksSugeridos,
|
|
1754
|
-
...resultadoDrift.resumo_operacional.oQueValidar,
|
|
1755
|
-
])],
|
|
1756
|
-
oQueEstaFrouxo: [...new Set([
|
|
1757
|
-
...resumoDrift.lacunas,
|
|
1758
|
-
...resultadoDrift.resumo_operacional.oQueEstaFrouxo,
|
|
1759
|
-
])],
|
|
1760
|
-
oQueFoiInferido: [...new Set([
|
|
1761
|
-
...resultadoDrift.impls_quebrados
|
|
1762
|
-
.filter((impl) => impl.modulo === modulo)
|
|
1763
|
-
.flatMap((impl) => impl.candidatos?.map((candidato) => candidato.caminho) ?? []),
|
|
1764
|
-
...resultadoDrift.vinculos_validos
|
|
1765
|
-
.filter((vinculo) => vinculo.modulo === modulo && vinculo.status === "parcial")
|
|
1766
|
-
.map((vinculo) => `${vinculo.dono}:${vinculo.valor}`),
|
|
1767
|
-
])],
|
|
1768
|
-
simbolosRelacionados: [...new Set([
|
|
1769
|
-
...tarefasModulo.flatMap((task) => task.simbolosReferenciados),
|
|
1770
|
-
...resultadoDrift.vinculos_validos
|
|
1771
|
-
.filter((vinculo) => vinculo.modulo === modulo)
|
|
1772
|
-
.map((vinculo) => vinculo.simbolo)
|
|
1773
|
-
.filter((item): item is string => Boolean(item)),
|
|
1774
|
-
])],
|
|
1775
|
-
superficiesImpactadas: [
|
|
1776
|
-
...(ir?.routes.map((route) => `${route.metodo ?? "?"} ${route.caminho ?? route.nome}`) ?? []),
|
|
1777
|
-
...(ir?.superficies.map((superficie) => `${superficie.tipo}:${superficie.nome}`) ?? []),
|
|
1778
|
-
],
|
|
1779
|
-
consumerFramework: resumoDrift.consumerFramework,
|
|
1780
|
-
appRoutes: resumoDrift.appRoutes,
|
|
1781
|
-
consumerSurfaces: resumoDrift.consumerSurfaces,
|
|
1782
|
-
consumerBridges: resumoDrift.consumerBridges,
|
|
1783
|
-
testesMinimos: [
|
|
1784
|
-
"sema validar <arquivo> --json",
|
|
1785
|
-
"sema drift <arquivo> --json",
|
|
1786
|
-
"sema verificar <arquivo-ou-pasta> --json",
|
|
1787
|
-
],
|
|
1788
|
-
};
|
|
1789
|
-
}
|
|
1790
|
-
|
|
1791
|
-
async function carregarContextoModuloIa(arquivoEntrada: string): Promise<PacoteContextoModuloIa> {
|
|
1792
|
-
const arquivo = path.resolve(arquivoEntrada);
|
|
1793
|
-
garantirArquivoSema(arquivo);
|
|
1794
|
-
const contextoProjeto = await carregarProjeto(arquivo, process.cwd());
|
|
1795
|
-
const resultadoModulo = contextoProjeto.modulosSelecionados.find((item) => path.resolve(item.caminho) === arquivo)?.resultado;
|
|
1796
|
-
|
|
1797
|
-
if (!resultadoModulo) {
|
|
1798
|
-
falharContextoIa(`Nao foi possivel encontrar o modulo correspondente ao arquivo ${arquivo}.`);
|
|
1799
|
-
}
|
|
1800
|
-
|
|
1801
|
-
const sucesso = !temErros(resultadoModulo.diagnosticos);
|
|
1802
|
-
const modulo = resultadoModulo.modulo?.nome ?? path.basename(arquivo, ".sema");
|
|
1803
|
-
const geradoEm = new Date().toISOString();
|
|
1804
|
-
const resultadoDrift = await analisarDriftLegado(contextoProjeto);
|
|
1805
|
-
const drift = {
|
|
1806
|
-
comando: "drift" as const,
|
|
1807
|
-
caminho: arquivo,
|
|
1808
|
-
modulo: resultadoModulo.modulo?.nome ?? null,
|
|
1809
|
-
sucesso: resultadoDrift.sucesso,
|
|
1810
|
-
resumo: resumirDriftPorModulo(resultadoModulo.modulo?.nome ?? null, arquivo, resultadoDrift),
|
|
1811
|
-
drift: resultadoDrift,
|
|
1812
|
-
};
|
|
1813
|
-
|
|
1814
|
-
const validar = {
|
|
1815
|
-
comando: "validar" as const,
|
|
1816
|
-
sucesso,
|
|
1817
|
-
resultados: [
|
|
1818
|
-
{
|
|
1819
|
-
caminho: arquivo,
|
|
1820
|
-
modulo: resultadoModulo.modulo?.nome ?? null,
|
|
1821
|
-
sucesso,
|
|
1822
|
-
diagnosticos: resultadoModulo.diagnosticos,
|
|
1823
|
-
},
|
|
1824
|
-
],
|
|
1825
|
-
};
|
|
1826
|
-
|
|
1827
|
-
const diagnosticos = {
|
|
1828
|
-
comando: "diagnosticos" as const,
|
|
1829
|
-
caminho: arquivo,
|
|
1830
|
-
modulo: resultadoModulo.modulo?.nome ?? null,
|
|
1831
|
-
diagnosticos: resultadoModulo.diagnosticos,
|
|
1832
|
-
};
|
|
1833
|
-
|
|
1834
|
-
const ast = {
|
|
1835
|
-
comando: "ast" as const,
|
|
1836
|
-
caminho: arquivo,
|
|
1837
|
-
modulo: resultadoModulo.modulo?.nome ?? null,
|
|
1838
|
-
sucesso,
|
|
1839
|
-
diagnosticos: resultadoModulo.diagnosticos,
|
|
1840
|
-
ast: resultadoModulo.modulo ?? null,
|
|
1841
|
-
};
|
|
1842
|
-
|
|
1843
|
-
const ir = {
|
|
1844
|
-
comando: "ir" as const,
|
|
1845
|
-
caminho: arquivo,
|
|
1846
|
-
modulo: resultadoModulo.modulo?.nome ?? null,
|
|
1847
|
-
sucesso,
|
|
1848
|
-
diagnosticos: resultadoModulo.diagnosticos,
|
|
1849
|
-
ir: resultadoModulo.ir ?? null,
|
|
1850
|
-
};
|
|
1851
|
-
const briefing = criarBriefingAgente(
|
|
1852
|
-
arquivo,
|
|
1853
|
-
modulo,
|
|
1854
|
-
resultadoModulo.ir ?? null,
|
|
1855
|
-
drift.resumo,
|
|
1856
|
-
resultadoDrift,
|
|
1857
|
-
);
|
|
1858
|
-
|
|
1859
|
-
return {
|
|
1860
|
-
arquivo,
|
|
1861
|
-
modulo,
|
|
1862
|
-
sucesso,
|
|
1863
|
-
geradoEm,
|
|
1864
|
-
diagnosticos: resultadoModulo.diagnosticos,
|
|
1865
|
-
ir: resultadoModulo.ir ?? null,
|
|
1866
|
-
validar,
|
|
1867
|
-
diagnosticosJson: diagnosticos,
|
|
1868
|
-
ast,
|
|
1869
|
-
irJson: ir,
|
|
1870
|
-
drift,
|
|
1871
|
-
briefing,
|
|
1872
|
-
};
|
|
1873
|
-
}
|
|
1874
|
-
|
|
1875
|
-
async function gerarArquivosResumoModuloIa(
|
|
1876
|
-
contexto: PacoteContextoModuloIa,
|
|
1877
|
-
pastaBase: string,
|
|
1878
|
-
): Promise<{
|
|
1879
|
-
artefatosCompactos: string[];
|
|
1880
|
-
guiaPorCapacidade: Record<CapacidadeIa, GuiaCapacidadeIa>;
|
|
1881
|
-
}> {
|
|
1882
|
-
const guiaPorCapacidade = criarGuiaCapacidadeIa();
|
|
1883
|
-
const resumoSemantico = coletarResumoSemanticoModulo(contexto);
|
|
1884
|
-
const resumoMicro = renderizarResumoModuloTexto(resumoSemantico, "micro", "resumo");
|
|
1885
|
-
const resumoCurto = renderizarResumoModuloTexto(resumoSemantico, "curto", "resumo");
|
|
1886
|
-
const resumoMarkdown = renderizarResumoModuloMarkdown(resumoSemantico, "resumo", guiaPorCapacidade);
|
|
1887
|
-
const briefingMinimo = criarBriefingMinimo(resumoSemantico, "resumo", "curto");
|
|
1888
|
-
const promptCurto = criarPromptCurtoModulo(resumoSemantico, "mudanca", "curto", "pequena");
|
|
1889
|
-
|
|
1890
|
-
await writeFile(path.join(pastaBase, "resumo.micro.txt"), resumoMicro, "utf8");
|
|
1891
|
-
await writeFile(path.join(pastaBase, "resumo.curto.txt"), resumoCurto, "utf8");
|
|
1892
|
-
await writeFile(path.join(pastaBase, "resumo.md"), resumoMarkdown, "utf8");
|
|
1893
|
-
await writeFile(path.join(pastaBase, "briefing.min.json"), `${JSON.stringify(briefingMinimo, null, 2)}\n`, "utf8");
|
|
1894
|
-
await writeFile(path.join(pastaBase, "prompt-curto.txt"), promptCurto, "utf8");
|
|
1895
|
-
|
|
1896
|
-
return {
|
|
1897
|
-
artefatosCompactos: ["resumo.micro.txt", "resumo.curto.txt", "resumo.md", "briefing.min.json", "prompt-curto.txt"],
|
|
1898
|
-
guiaPorCapacidade,
|
|
1899
|
-
};
|
|
1900
|
-
}
|
|
1901
|
-
|
|
1902
|
-
async function gerarResumoProjetoIa(
|
|
1903
|
-
entrada: string | undefined,
|
|
1904
|
-
pastaSaidaOpcional?: string,
|
|
1905
|
-
escreverNaRaiz = false,
|
|
1906
|
-
): Promise<{
|
|
1907
|
-
geradoEm: string;
|
|
1908
|
-
baseProjeto: string;
|
|
1909
|
-
pastaSaida: string;
|
|
1910
|
-
artefatos: string[];
|
|
1911
|
-
modulos: ResumoSemanticoModuloIa[];
|
|
1912
|
-
guiaPorCapacidade: Record<CapacidadeIa, GuiaCapacidadeIa>;
|
|
1913
|
-
}> {
|
|
1914
|
-
const contextoProjeto = await carregarProjeto(entrada, process.cwd());
|
|
1915
|
-
const geradoEm = new Date().toISOString();
|
|
1916
|
-
const guiaPorCapacidade = criarGuiaCapacidadeIa();
|
|
1917
|
-
const entradaCanonica = criarEntradaCanonicaProjeto(guiaPorCapacidade);
|
|
1918
|
-
const resultadoDrift = await analisarDriftLegado(contextoProjeto);
|
|
1919
|
-
const modulos = contextoProjeto.modulosSelecionados.map((item) => {
|
|
1920
|
-
const modulo = item.resultado.modulo?.nome ?? path.basename(item.caminho, ".sema");
|
|
1921
|
-
const driftResumo = resumirDriftPorModulo(modulo, item.caminho, resultadoDrift);
|
|
1922
|
-
const briefing = criarBriefingAgente(item.caminho, modulo, item.resultado.ir ?? null, driftResumo, resultadoDrift);
|
|
1923
|
-
return coletarResumoSemanticoModulo({
|
|
1924
|
-
arquivo: item.caminho,
|
|
1925
|
-
modulo,
|
|
1926
|
-
geradoEm,
|
|
1927
|
-
ir: item.resultado.ir ?? null,
|
|
1928
|
-
briefing,
|
|
1929
|
-
drift: {
|
|
1930
|
-
comando: "drift",
|
|
1931
|
-
caminho: item.caminho,
|
|
1932
|
-
modulo,
|
|
1933
|
-
sucesso: resultadoDrift.sucesso,
|
|
1934
|
-
resumo: driftResumo,
|
|
1935
|
-
drift: resultadoDrift,
|
|
1936
|
-
},
|
|
1937
|
-
});
|
|
1938
|
-
});
|
|
1939
|
-
|
|
1940
|
-
const baseProjeto = contextoProjeto.baseProjeto;
|
|
1941
|
-
const pastaSaida = escreverNaRaiz
|
|
1942
|
-
? baseProjeto
|
|
1943
|
-
: pastaSaidaOpcional
|
|
1944
|
-
? path.resolve(pastaSaidaOpcional)
|
|
1945
|
-
: path.resolve(baseProjeto, ".tmp", "sema-resumo");
|
|
1946
|
-
|
|
1947
|
-
await mkdir(pastaSaida, { recursive: true });
|
|
1948
|
-
|
|
1949
|
-
const semaBrief = renderizarResumoProjetoMarkdown(geradoEm, modulos, guiaPorCapacidade);
|
|
1950
|
-
const indexJson = {
|
|
1951
|
-
comando: "resumo-projeto",
|
|
1952
|
-
geradoEm,
|
|
1953
|
-
cliVersao: VERSAO_CLI,
|
|
1954
|
-
baseProjeto,
|
|
1955
|
-
totalModulos: modulos.length,
|
|
1956
|
-
entradaCanonica,
|
|
1957
|
-
guiaPorCapacidade,
|
|
1958
|
-
modulos,
|
|
1959
|
-
};
|
|
1960
|
-
const micro = [
|
|
1961
|
-
`PROJETO: ${path.basename(baseProjeto)}`,
|
|
1962
|
-
`MODULOS: ${modulos.length}`,
|
|
1963
|
-
`ENTRADA_IA: ${entradaCanonica.porCapacidade.pequena.join(" -> ")}`,
|
|
1964
|
-
`TOP_MODULOS: ${resumirListaTexto(modulos.map((modulo) => modulo.modulo), 3)}`,
|
|
1965
|
-
`TOP_RISCOS: ${resumirListaTexto(unicosOrdenados(modulos.flatMap((modulo) => modulo.riscosPrincipais)), 3)}`,
|
|
1966
|
-
`TOP_LACUNAS: ${resumirListaTexto(unicosOrdenados(modulos.flatMap((modulo) => modulo.lacunas)), 3)}`,
|
|
1967
|
-
`GERADO_EM: ${geradoEm}`,
|
|
1968
|
-
"",
|
|
1969
|
-
].join("\n");
|
|
1970
|
-
const curto = [
|
|
1971
|
-
`PROJETO: ${path.basename(baseProjeto)}`,
|
|
1972
|
-
`BASE: ${baseProjeto}`,
|
|
1973
|
-
`MODULOS: ${modulos.length}`,
|
|
1974
|
-
`ENTRADA_IA: ${entradaCanonica.porCapacidade.media.join(" -> ")}`,
|
|
1975
|
-
`TOP_MODULOS: ${resumirListaTexto(modulos.map((modulo) => modulo.modulo), 6)}`,
|
|
1976
|
-
`TOP_RISCOS: ${resumirListaTexto(unicosOrdenados(modulos.flatMap((modulo) => modulo.riscosPrincipais)), 6)}`,
|
|
1977
|
-
`TOP_LACUNAS: ${resumirListaTexto(unicosOrdenados(modulos.flatMap((modulo) => modulo.lacunas)), 6)}`,
|
|
1978
|
-
`TOP_ARQUIVOS: ${resumirListaTexto(unicosOrdenados(modulos.flatMap((modulo) => modulo.arquivosProvaveis)), 6)}`,
|
|
1979
|
-
`GERADO_EM: ${geradoEm}`,
|
|
1980
|
-
"",
|
|
1981
|
-
].join("\n");
|
|
1982
|
-
|
|
1983
|
-
await writeFile(path.join(pastaSaida, "SEMA_BRIEF.md"), semaBrief, "utf8");
|
|
1984
|
-
await writeFile(path.join(pastaSaida, "SEMA_BRIEF.micro.txt"), micro, "utf8");
|
|
1985
|
-
await writeFile(path.join(pastaSaida, "SEMA_BRIEF.curto.txt"), curto, "utf8");
|
|
1986
|
-
await writeFile(path.join(pastaSaida, "SEMA_INDEX.json"), `${JSON.stringify(indexJson, null, 2)}\n`, "utf8");
|
|
1987
|
-
|
|
1988
|
-
return {
|
|
1989
|
-
geradoEm,
|
|
1990
|
-
baseProjeto,
|
|
1991
|
-
pastaSaida,
|
|
1992
|
-
artefatos: ["SEMA_BRIEF.md", "SEMA_BRIEF.micro.txt", "SEMA_BRIEF.curto.txt", "SEMA_INDEX.json"],
|
|
1993
|
-
modulos,
|
|
1994
|
-
guiaPorCapacidade,
|
|
1995
|
-
};
|
|
1996
|
-
}
|
|
1997
|
-
|
|
1998
|
-
async function gerarContextoIa(arquivoEntrada: string, pastaSaidaOpcional?: string): Promise<ContextoIaGerado> {
|
|
1999
|
-
const contexto = await carregarContextoModuloIa(arquivoEntrada);
|
|
2000
|
-
const pastaBase = pastaSaidaOpcional
|
|
2001
|
-
? path.resolve(pastaSaidaOpcional)
|
|
2002
|
-
: path.resolve(process.cwd(), ".tmp", "contexto-ia", path.basename(contexto.arquivo, ".sema"));
|
|
2003
|
-
|
|
2004
|
-
await mkdir(pastaBase, { recursive: true });
|
|
2005
|
-
|
|
2006
|
-
await writeFile(path.join(pastaBase, "validar.json"), `${JSON.stringify(contexto.validar, null, 2)}\n`, "utf8");
|
|
2007
|
-
await writeFile(path.join(pastaBase, "diagnosticos.json"), `${JSON.stringify(contexto.diagnosticosJson, null, 2)}\n`, "utf8");
|
|
2008
|
-
await writeFile(path.join(pastaBase, "ast.json"), `${JSON.stringify(contexto.ast, null, 2)}\n`, "utf8");
|
|
2009
|
-
await writeFile(path.join(pastaBase, "ir.json"), `${JSON.stringify(contexto.irJson, null, 2)}\n`, "utf8");
|
|
2010
|
-
await writeFile(path.join(pastaBase, "drift.json"), `${JSON.stringify(contexto.drift, null, 2)}\n`, "utf8");
|
|
2011
|
-
await writeFile(path.join(pastaBase, "briefing.json"), `${JSON.stringify(contexto.briefing, null, 2)}\n`, "utf8");
|
|
2012
|
-
const resumoGerado = await gerarArquivosResumoModuloIa(contexto, pastaBase);
|
|
2013
|
-
|
|
2014
|
-
const resumo = `# Contexto de IA para ${contexto.modulo}
|
|
2015
|
-
|
|
2016
|
-
- Arquivo alvo: \`${contexto.arquivo}\`
|
|
2017
|
-
- Modulo: \`${contexto.modulo}\`
|
|
2018
|
-
- Sucesso em validar: \`${contexto.sucesso}\`
|
|
2019
|
-
- Quantidade de diagnosticos: \`${contexto.diagnosticos.length}\`
|
|
2020
|
-
- Gerado em: \`${contexto.geradoEm}\`
|
|
2021
|
-
|
|
2022
|
-
## Arquivos gerados neste pacote
|
|
2023
|
-
|
|
2024
|
-
- \`resumo.micro.txt\`
|
|
2025
|
-
- \`resumo.curto.txt\`
|
|
2026
|
-
- \`resumo.md\`
|
|
2027
|
-
- \`briefing.min.json\`
|
|
2028
|
-
- \`prompt-curto.txt\`
|
|
2029
|
-
- \`validar.json\`
|
|
2030
|
-
- \`diagnosticos.json\`
|
|
2031
|
-
- \`ast.json\`
|
|
2032
|
-
- \`ir.json\`
|
|
2033
|
-
- \`drift.json\`
|
|
2034
|
-
- \`briefing.json\`
|
|
2035
|
-
|
|
2036
|
-
## Fluxo recomendado para o agente
|
|
2037
|
-
|
|
2038
|
-
### IA pequena ou gratuita
|
|
2039
|
-
|
|
2040
|
-
1. Ler \`resumo.micro.txt\`.
|
|
2041
|
-
2. Ler \`briefing.min.json\`.
|
|
2042
|
-
3. Se ainda couber contexto, ler \`resumo.curto.txt\`.
|
|
2043
|
-
|
|
2044
|
-
### IA media
|
|
2045
|
-
|
|
2046
|
-
1. Ler \`resumo.curto.txt\`.
|
|
2047
|
-
2. Ler \`briefing.min.json\`.
|
|
2048
|
-
3. Ler \`drift.json\`.
|
|
2049
|
-
4. Se precisar, subir para \`resumo.md\`.
|
|
2050
|
-
|
|
2051
|
-
### IA grande ou com tool use
|
|
2052
|
-
|
|
2053
|
-
1. Ler \`README.md\`.
|
|
2054
|
-
2. Ler \`resumo.md\`.
|
|
2055
|
-
3. Ler \`briefing.json\`.
|
|
2056
|
-
4. Ler \`drift.json\`.
|
|
2057
|
-
5. So depois abrir \`ir.json\` e \`ast.json\`.
|
|
2058
|
-
|
|
2059
|
-
## Fechamento
|
|
2060
|
-
|
|
2061
|
-
1. Editar o arquivo \`.sema\`.
|
|
2062
|
-
2. Rodar \`sema formatar "${contexto.arquivo}"\`.
|
|
2063
|
-
3. Rodar \`sema validar "${contexto.arquivo}" --json\`.
|
|
2064
|
-
4. Rodar \`sema drift "${contexto.arquivo}" --json\`.
|
|
2065
|
-
5. Fechar com \`sema verificar <arquivo-ou-pasta> --json --saida ./.tmp/verificacao-ia\`.
|
|
2066
|
-
|
|
2067
|
-
## Textos base para onboarding do agente
|
|
2068
|
-
|
|
2069
|
-
- \`sema starter-ia\`
|
|
2070
|
-
- \`sema resumo "${contexto.arquivo}" --micro --para onboarding\`
|
|
2071
|
-
- \`sema prompt-curto "${contexto.arquivo}" --para mudanca\`
|
|
2072
|
-
- \`sema prompt-ia\`
|
|
2073
|
-
`;
|
|
2074
|
-
|
|
2075
|
-
await writeFile(path.join(pastaBase, "README.md"), resumo, "utf8");
|
|
2076
|
-
|
|
2077
|
-
return {
|
|
2078
|
-
sucesso: contexto.sucesso,
|
|
2079
|
-
arquivo: contexto.arquivo,
|
|
2080
|
-
modulo: contexto.modulo,
|
|
2081
|
-
pastaSaida: pastaBase,
|
|
2082
|
-
artefatos: [
|
|
2083
|
-
"validar.json",
|
|
2084
|
-
"diagnosticos.json",
|
|
2085
|
-
"ast.json",
|
|
2086
|
-
"ir.json",
|
|
2087
|
-
"drift.json",
|
|
2088
|
-
"briefing.json",
|
|
2089
|
-
"README.md",
|
|
2090
|
-
...resumoGerado.artefatosCompactos,
|
|
2091
|
-
],
|
|
2092
|
-
artefatosCompactos: resumoGerado.artefatosCompactos,
|
|
2093
|
-
geradoEm: contexto.geradoEm,
|
|
2094
|
-
guiaPorCapacidade: resumoGerado.guiaPorCapacidade,
|
|
2095
|
-
};
|
|
2096
|
-
}
|
|
2097
|
-
|
|
2098
|
-
async function comandoIniciar(cwd: string, template: TemplateIniciar): Promise<number> {
|
|
2099
|
-
const arquivosBase = [
|
|
2100
|
-
{
|
|
2101
|
-
caminhoRelativo: "contratos/pedidos.sema",
|
|
2102
|
-
conteudo: `module app.pedidos {
|
|
2103
|
-
entity Pedido {
|
|
2104
|
-
fields {
|
|
2105
|
-
id: Id
|
|
2106
|
-
status: Texto
|
|
2107
|
-
total: Decimal
|
|
2108
|
-
}
|
|
2109
|
-
}
|
|
2110
|
-
|
|
2111
|
-
task criar_pedido {
|
|
2112
|
-
input {
|
|
2113
|
-
cliente_id: Id required
|
|
2114
|
-
total: Decimal required
|
|
2115
|
-
}
|
|
2116
|
-
output {
|
|
2117
|
-
pedido_id: Id
|
|
2118
|
-
status: Texto
|
|
2119
|
-
}
|
|
2120
|
-
rules {
|
|
2121
|
-
total > 0
|
|
2122
|
-
}
|
|
2123
|
-
effects {
|
|
2124
|
-
persistencia Pedido criticidade=alta
|
|
2125
|
-
auditoria pedidos
|
|
2126
|
-
}
|
|
2127
|
-
guarantees {
|
|
2128
|
-
pedido_id existe
|
|
2129
|
-
status existe
|
|
2130
|
-
}
|
|
2131
|
-
tests {
|
|
2132
|
-
caso "pedido valido" {
|
|
2133
|
-
given {
|
|
2134
|
-
cliente_id: "cli-1"
|
|
2135
|
-
total: 10
|
|
2136
|
-
}
|
|
2137
|
-
expect {
|
|
2138
|
-
sucesso: verdadeiro
|
|
2139
|
-
}
|
|
2140
|
-
}
|
|
2141
|
-
}
|
|
2142
|
-
}
|
|
2143
|
-
|
|
2144
|
-
route criar_pedido_publico {
|
|
2145
|
-
metodo: POST
|
|
2146
|
-
caminho: /pedidos
|
|
2147
|
-
task: criar_pedido
|
|
2148
|
-
}
|
|
2149
|
-
}
|
|
2150
|
-
`,
|
|
2151
|
-
},
|
|
2152
|
-
];
|
|
2153
|
-
|
|
2154
|
-
let arquivos = arquivosBase;
|
|
2155
|
-
if (template === "nestjs") {
|
|
2156
|
-
arquivos = [
|
|
2157
|
-
{
|
|
2158
|
-
caminhoRelativo: "sema.config.json",
|
|
2159
|
-
conteudo: `{
|
|
2160
|
-
"origens": ["./contratos"],
|
|
2161
|
-
"saida": "./generated/nestjs",
|
|
2162
|
-
"alvos": ["typescript"],
|
|
2163
|
-
"alvoPadrao": "typescript",
|
|
2164
|
-
"estruturaSaida": "backend",
|
|
2165
|
-
"framework": "nestjs",
|
|
2166
|
-
"modoEstrito": true,
|
|
2167
|
-
"diretoriosSaidaPorAlvo": {
|
|
2168
|
-
"typescript": "./generated/nestjs"
|
|
2169
|
-
},
|
|
2170
|
-
"convencoesGeracaoPorProjeto": "backend"
|
|
2171
|
-
}
|
|
2172
|
-
`,
|
|
2173
|
-
},
|
|
2174
|
-
{ caminhoRelativo: "src/.gitkeep", conteudo: "" },
|
|
2175
|
-
{ caminhoRelativo: "test/.gitkeep", conteudo: "" },
|
|
2176
|
-
...arquivosBase,
|
|
2177
|
-
];
|
|
2178
|
-
} else if (template === "fastapi") {
|
|
2179
|
-
arquivos = [
|
|
2180
|
-
{
|
|
2181
|
-
caminhoRelativo: "sema.config.json",
|
|
2182
|
-
conteudo: `{
|
|
2183
|
-
"origens": ["./contratos"],
|
|
2184
|
-
"saida": "./generated/fastapi",
|
|
2185
|
-
"alvos": ["python"],
|
|
2186
|
-
"alvoPadrao": "python",
|
|
2187
|
-
"estruturaSaida": "backend",
|
|
2188
|
-
"framework": "fastapi",
|
|
2189
|
-
"modoEstrito": true,
|
|
2190
|
-
"diretoriosSaidaPorAlvo": {
|
|
2191
|
-
"python": "./generated/fastapi"
|
|
2192
|
-
},
|
|
2193
|
-
"convencoesGeracaoPorProjeto": "backend"
|
|
2194
|
-
}
|
|
2195
|
-
`,
|
|
2196
|
-
},
|
|
2197
|
-
{ caminhoRelativo: "app/.gitkeep", conteudo: "" },
|
|
2198
|
-
{ caminhoRelativo: "tests/.gitkeep", conteudo: "" },
|
|
2199
|
-
...arquivosBase,
|
|
2200
|
-
];
|
|
2201
|
-
} else if (template === "nextjs-api") {
|
|
2202
|
-
arquivos = [
|
|
2203
|
-
{
|
|
2204
|
-
caminhoRelativo: "sema.config.json",
|
|
2205
|
-
conteudo: `{
|
|
2206
|
-
"origens": ["./contratos"],
|
|
2207
|
-
"saida": "./generated",
|
|
2208
|
-
"alvos": ["typescript"],
|
|
2209
|
-
"alvoPadrao": "typescript",
|
|
2210
|
-
"estruturaSaida": "modulos",
|
|
2211
|
-
"framework": "base",
|
|
2212
|
-
"modoEstrito": true,
|
|
2213
|
-
"diretoriosCodigo": ["./src"],
|
|
2214
|
-
"fontesLegado": ["nextjs", "typescript"],
|
|
2215
|
-
"diretoriosSaidaPorAlvo": {
|
|
2216
|
-
"typescript": "./generated/typescript"
|
|
2217
|
-
},
|
|
2218
|
-
"convencoesGeracaoPorProjeto": "base"
|
|
2219
|
-
}
|
|
2220
|
-
`,
|
|
2221
|
-
},
|
|
2222
|
-
{
|
|
2223
|
-
caminhoRelativo: "contratos/health.sema",
|
|
2224
|
-
conteudo: `module app.health {
|
|
2225
|
-
task get_api_health {
|
|
2226
|
-
output {
|
|
2227
|
-
status: Texto
|
|
2228
|
-
runtime: Texto
|
|
2229
|
-
}
|
|
2230
|
-
impl {
|
|
2231
|
-
ts: src.app.api.health.route.GET
|
|
2232
|
-
}
|
|
2233
|
-
guarantees {
|
|
2234
|
-
status existe
|
|
2235
|
-
runtime existe
|
|
2236
|
-
}
|
|
2237
|
-
}
|
|
2238
|
-
|
|
2239
|
-
route get_api_health_publico {
|
|
2240
|
-
metodo: GET
|
|
2241
|
-
caminho: /api/health
|
|
2242
|
-
task: get_api_health
|
|
2243
|
-
}
|
|
2244
|
-
}
|
|
2245
|
-
`,
|
|
2246
|
-
},
|
|
2247
|
-
{
|
|
2248
|
-
caminhoRelativo: "src/app/api/health/route.ts",
|
|
2249
|
-
conteudo: `export async function GET() {
|
|
2250
|
-
return Response.json({
|
|
2251
|
-
status: "ok",
|
|
2252
|
-
runtime: "nextjs",
|
|
2253
|
-
});
|
|
2254
|
-
}
|
|
2255
|
-
`,
|
|
2256
|
-
},
|
|
2257
|
-
{
|
|
2258
|
-
caminhoRelativo: "README.md",
|
|
2259
|
-
conteudo: `# Starter Next.js API + Sema
|
|
2260
|
-
|
|
2261
|
-
- Contratos em \`contratos/\`
|
|
2262
|
-
- Handlers App Router em \`src/app/api/\`
|
|
2263
|
-
- Rota de exemplo validada por \`drift\`
|
|
2264
|
-
`,
|
|
2265
|
-
},
|
|
2266
|
-
];
|
|
2267
|
-
} else if (template === "nextjs-consumer") {
|
|
2268
|
-
arquivos = [
|
|
2269
|
-
{
|
|
2270
|
-
caminhoRelativo: "sema.config.json",
|
|
2271
|
-
conteudo: `{
|
|
2272
|
-
"origens": ["./contratos"],
|
|
2273
|
-
"saida": "./generated",
|
|
2274
|
-
"alvos": ["typescript"],
|
|
2275
|
-
"alvoPadrao": "typescript",
|
|
2276
|
-
"estruturaSaida": "modulos",
|
|
2277
|
-
"framework": "base",
|
|
2278
|
-
"modoEstrito": true,
|
|
2279
|
-
"diretoriosCodigo": ["./src"],
|
|
2280
|
-
"fontesLegado": ["nextjs-consumer", "typescript"],
|
|
2281
|
-
"diretoriosSaidaPorAlvo": {
|
|
2282
|
-
"typescript": "./generated/typescript"
|
|
2283
|
-
},
|
|
2284
|
-
"convencoesGeracaoPorProjeto": "base"
|
|
2285
|
-
}
|
|
2286
|
-
`,
|
|
2287
|
-
},
|
|
2288
|
-
{
|
|
2289
|
-
caminhoRelativo: "contratos/showroom_consumer.sema",
|
|
2290
|
-
conteudo: `module showroom.consumer {
|
|
2291
|
-
task fetch_showroom_ranking {
|
|
2292
|
-
input {
|
|
2293
|
-
}
|
|
2294
|
-
output {
|
|
2295
|
-
ranking: Json
|
|
2296
|
-
}
|
|
2297
|
-
impl {
|
|
2298
|
-
ts: src.lib.sema_consumer_bridge.semaFetchShowroomRanking
|
|
2299
|
-
}
|
|
2300
|
-
vinculos {
|
|
2301
|
-
arquivo: "src/lib/sema_consumer_bridge.ts"
|
|
2302
|
-
simbolo: src.lib.sema_consumer_bridge.semaFetchShowroomRanking
|
|
2303
|
-
superficie: "/ranking"
|
|
2304
|
-
arquivo: "src/app/ranking/page.tsx"
|
|
2305
|
-
arquivo: "src/app/ranking/loading.tsx"
|
|
2306
|
-
arquivo: "src/app/ranking/error.tsx"
|
|
2307
|
-
}
|
|
2308
|
-
guarantees {
|
|
2309
|
-
ranking existe
|
|
2310
|
-
}
|
|
2311
|
-
}
|
|
2312
|
-
}
|
|
2313
|
-
`,
|
|
2314
|
-
},
|
|
2315
|
-
{
|
|
2316
|
-
caminhoRelativo: "src/lib/sema_consumer_bridge.ts",
|
|
2317
|
-
conteudo: `export async function semaFetchShowroomRanking() {
|
|
2318
|
-
return {
|
|
2319
|
-
ranking: [
|
|
2320
|
-
{ clube: "Tigres do Norte", pontos: 33 },
|
|
2321
|
-
{ clube: "Porto Azul", pontos: 31 },
|
|
2322
|
-
{ clube: "Galo de Ouro", pontos: 28 },
|
|
2323
|
-
],
|
|
2324
|
-
};
|
|
2325
|
-
}
|
|
2326
|
-
`,
|
|
2327
|
-
},
|
|
2328
|
-
{
|
|
2329
|
-
caminhoRelativo: "src/app/ranking/page.tsx",
|
|
2330
|
-
conteudo: `import { semaFetchShowroomRanking } from "../../lib/sema_consumer_bridge";
|
|
2331
|
-
|
|
2332
|
-
export default async function RankingPage() {
|
|
2333
|
-
const { ranking } = await semaFetchShowroomRanking();
|
|
2334
|
-
|
|
2335
|
-
return (
|
|
2336
|
-
<main>
|
|
2337
|
-
<h1>Ranking showroom</h1>
|
|
2338
|
-
<ul>
|
|
2339
|
-
{ranking.map((item) => (
|
|
2340
|
-
<li key={item.clube}>
|
|
2341
|
-
{item.clube} - {item.pontos} pts
|
|
2342
|
-
</li>
|
|
2343
|
-
))}
|
|
2344
|
-
</ul>
|
|
2345
|
-
</main>
|
|
2346
|
-
);
|
|
2347
|
-
}
|
|
2348
|
-
`,
|
|
2349
|
-
},
|
|
2350
|
-
{
|
|
2351
|
-
caminhoRelativo: "src/app/ranking/loading.tsx",
|
|
2352
|
-
conteudo: `export default function Loading() {
|
|
2353
|
-
return <p>Carregando ranking...</p>;
|
|
2354
|
-
}
|
|
2355
|
-
`,
|
|
2356
|
-
},
|
|
2357
|
-
{
|
|
2358
|
-
caminhoRelativo: "src/app/ranking/error.tsx",
|
|
2359
|
-
conteudo: `"use client";
|
|
2360
|
-
|
|
2361
|
-
export default function Error({
|
|
2362
|
-
error,
|
|
2363
|
-
reset,
|
|
2364
|
-
}: {
|
|
2365
|
-
error: Error;
|
|
2366
|
-
reset: () => void;
|
|
2367
|
-
}) {
|
|
2368
|
-
return (
|
|
2369
|
-
<main>
|
|
2370
|
-
<h1>Falha ao carregar ranking</h1>
|
|
2371
|
-
<p>{error.message}</p>
|
|
2372
|
-
<button type="button" onClick={reset}>Tentar novamente</button>
|
|
2373
|
-
</main>
|
|
2374
|
-
);
|
|
2375
|
-
}
|
|
2376
|
-
`,
|
|
2377
|
-
},
|
|
2378
|
-
{
|
|
2379
|
-
caminhoRelativo: "README.md",
|
|
2380
|
-
conteudo: `# Starter Next.js Consumer + Sema
|
|
2381
|
-
|
|
2382
|
-
- Contratos em \`contratos/\`
|
|
2383
|
-
- Bridge consumer canonico em \`src/lib/sema_consumer_bridge.ts\`
|
|
2384
|
-
- Superficies App Router em \`src/app/\`
|
|
2385
|
-
- O slice oficial desta fase e \`consumer bridge + App Router surfaces\`
|
|
2386
|
-
- \`drift\` valida \`impl\`, \`vinculos\`, bridge e superficies, sem prometer visual drift
|
|
2387
|
-
`,
|
|
2388
|
-
},
|
|
2389
|
-
];
|
|
2390
|
-
} else if (template === "react-vite-consumer") {
|
|
2391
|
-
arquivos = [
|
|
2392
|
-
{
|
|
2393
|
-
caminhoRelativo: "sema.config.json",
|
|
2394
|
-
conteudo: `{
|
|
2395
|
-
"origens": ["./contratos"],
|
|
2396
|
-
"saida": "./generated",
|
|
2397
|
-
"alvos": ["typescript"],
|
|
2398
|
-
"alvoPadrao": "typescript",
|
|
2399
|
-
"estruturaSaida": "modulos",
|
|
2400
|
-
"framework": "base",
|
|
2401
|
-
"modoEstrito": true,
|
|
2402
|
-
"diretoriosCodigo": ["./src"],
|
|
2403
|
-
"fontesLegado": ["react-vite-consumer", "typescript"],
|
|
2404
|
-
"diretoriosSaidaPorAlvo": {
|
|
2405
|
-
"typescript": "./generated/typescript"
|
|
2406
|
-
},
|
|
2407
|
-
"convencoesGeracaoPorProjeto": "base"
|
|
2408
|
-
}
|
|
2409
|
-
`,
|
|
2410
|
-
},
|
|
2411
|
-
{
|
|
2412
|
-
caminhoRelativo: "contratos/showroom_consumer.sema",
|
|
2413
|
-
conteudo: `module showroom.consumer {
|
|
2414
|
-
task fetch_showroom_ranking {
|
|
2415
|
-
input {
|
|
2416
|
-
}
|
|
2417
|
-
output {
|
|
2418
|
-
ranking: Json
|
|
2419
|
-
}
|
|
2420
|
-
impl {
|
|
2421
|
-
ts: src.lib.sema_consumer_bridge.semaFetchShowroomRanking
|
|
2422
|
-
}
|
|
2423
|
-
vinculos {
|
|
2424
|
-
arquivo: "src/lib/sema_consumer_bridge.ts"
|
|
2425
|
-
simbolo: src.lib.sema_consumer_bridge.semaFetchShowroomRanking
|
|
2426
|
-
superficie: "/ranking"
|
|
2427
|
-
arquivo: "src/router.tsx"
|
|
2428
|
-
arquivo: "src/pages/ranking.tsx"
|
|
2429
|
-
}
|
|
2430
|
-
guarantees {
|
|
2431
|
-
ranking existe
|
|
2432
|
-
}
|
|
2433
|
-
}
|
|
2434
|
-
}
|
|
2435
|
-
`,
|
|
2436
|
-
},
|
|
2437
|
-
{
|
|
2438
|
-
caminhoRelativo: "src/lib/sema_consumer_bridge.ts",
|
|
2439
|
-
conteudo: `export async function semaFetchShowroomRanking() {
|
|
2440
|
-
return {
|
|
2441
|
-
ranking: [
|
|
2442
|
-
{ clube: "Tigres do Norte", pontos: 33 },
|
|
2443
|
-
{ clube: "Porto Azul", pontos: 31 },
|
|
2444
|
-
{ clube: "Galo de Ouro", pontos: 28 },
|
|
2445
|
-
],
|
|
2446
|
-
};
|
|
2447
|
-
}
|
|
2448
|
-
`,
|
|
2449
|
-
},
|
|
2450
|
-
{
|
|
2451
|
-
caminhoRelativo: "src/pages/ranking.tsx",
|
|
2452
|
-
conteudo: `import { useEffect, useState } from "react";
|
|
2453
|
-
import { semaFetchShowroomRanking } from "../lib/sema_consumer_bridge";
|
|
2454
|
-
|
|
2455
|
-
export function RankingPage() {
|
|
2456
|
-
const [ranking, setRanking] = useState<Array<{ clube: string; pontos: number }>>([]);
|
|
2457
|
-
|
|
2458
|
-
useEffect(() => {
|
|
2459
|
-
void semaFetchShowroomRanking().then((payload) => setRanking(payload.ranking ?? []));
|
|
2460
|
-
}, []);
|
|
2461
|
-
|
|
2462
|
-
return (
|
|
2463
|
-
<main>
|
|
2464
|
-
<h1>Ranking showroom</h1>
|
|
2465
|
-
<ul>
|
|
2466
|
-
{ranking.map((item) => (
|
|
2467
|
-
<li key={item.clube}>
|
|
2468
|
-
{item.clube} - {item.pontos} pts
|
|
2469
|
-
</li>
|
|
2470
|
-
))}
|
|
2471
|
-
</ul>
|
|
2472
|
-
</main>
|
|
2473
|
-
);
|
|
2474
|
-
}
|
|
2475
|
-
`,
|
|
2476
|
-
},
|
|
2477
|
-
{
|
|
2478
|
-
caminhoRelativo: "src/router.tsx",
|
|
2479
|
-
conteudo: `import { createBrowserRouter } from "react-router-dom";
|
|
2480
|
-
import { RankingPage } from "./pages/ranking";
|
|
2481
|
-
|
|
2482
|
-
export const appRouter = createBrowserRouter([
|
|
2483
|
-
{
|
|
2484
|
-
path: "/ranking",
|
|
2485
|
-
Component: RankingPage,
|
|
2486
|
-
},
|
|
2487
|
-
]);
|
|
2488
|
-
`,
|
|
2489
|
-
},
|
|
2490
|
-
{
|
|
2491
|
-
caminhoRelativo: "src/App.tsx",
|
|
2492
|
-
conteudo: `import { RouterProvider } from "react-router-dom";
|
|
2493
|
-
import { appRouter } from "./router";
|
|
2494
|
-
|
|
2495
|
-
export default function App() {
|
|
2496
|
-
return <RouterProvider router={appRouter} />;
|
|
2497
|
-
}
|
|
2498
|
-
`,
|
|
2499
|
-
},
|
|
2500
|
-
{
|
|
2501
|
-
caminhoRelativo: "src/main.tsx",
|
|
2502
|
-
conteudo: `import React from "react";
|
|
2503
|
-
import ReactDOM from "react-dom/client";
|
|
2504
|
-
import App from "./App";
|
|
2505
|
-
|
|
2506
|
-
ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
|
|
2507
|
-
<React.StrictMode>
|
|
2508
|
-
<App />
|
|
2509
|
-
</React.StrictMode>,
|
|
2510
|
-
);
|
|
2511
|
-
`,
|
|
2512
|
-
},
|
|
2513
|
-
{
|
|
2514
|
-
caminhoRelativo: "README.md",
|
|
2515
|
-
conteudo: `# Starter React Vite Consumer + Sema
|
|
2516
|
-
|
|
2517
|
-
- Contratos em \`contratos/\`
|
|
2518
|
-
- Bridge consumer canonico em \`src/lib/sema_consumer_bridge.ts\`
|
|
2519
|
-
- Rotas explicitas em \`src/router.tsx\`
|
|
2520
|
-
- Superficies consumer em \`src/pages/\`
|
|
2521
|
-
- O slice oficial desta fase e \`consumer bridge + react-router surfaces\`
|
|
2522
|
-
- \`drift\` valida \`impl\`, \`vinculos\`, bridge e superficies, sem prometer visual drift
|
|
2523
|
-
`,
|
|
2524
|
-
},
|
|
2525
|
-
];
|
|
2526
|
-
} else if (template === "angular-consumer") {
|
|
2527
|
-
arquivos = [
|
|
2528
|
-
{
|
|
2529
|
-
caminhoRelativo: "sema.config.json",
|
|
2530
|
-
conteudo: `{
|
|
2531
|
-
"origens": ["./contratos"],
|
|
2532
|
-
"saida": "./generated",
|
|
2533
|
-
"alvos": ["typescript"],
|
|
2534
|
-
"alvoPadrao": "typescript",
|
|
2535
|
-
"estruturaSaida": "modulos",
|
|
2536
|
-
"framework": "base",
|
|
2537
|
-
"modoEstrito": true,
|
|
2538
|
-
"diretoriosCodigo": ["./src"],
|
|
2539
|
-
"fontesLegado": ["angular-consumer", "typescript"],
|
|
2540
|
-
"diretoriosSaidaPorAlvo": {
|
|
2541
|
-
"typescript": "./generated/typescript"
|
|
2542
|
-
},
|
|
2543
|
-
"convencoesGeracaoPorProjeto": "base"
|
|
2544
|
-
}
|
|
2545
|
-
`,
|
|
2546
|
-
},
|
|
2547
|
-
{
|
|
2548
|
-
caminhoRelativo: "contratos/showroom_consumer.sema",
|
|
2549
|
-
conteudo: `module showroom.consumer {
|
|
2550
|
-
task fetch_showroom_ranking {
|
|
2551
|
-
input {
|
|
2552
|
-
}
|
|
2553
|
-
output {
|
|
2554
|
-
ranking: Json
|
|
2555
|
-
}
|
|
2556
|
-
impl {
|
|
2557
|
-
ts: src.app.sema_consumer_bridge.semaFetchShowroomRanking
|
|
2558
|
-
}
|
|
2559
|
-
vinculos {
|
|
2560
|
-
arquivo: "src/app/sema_consumer_bridge.ts"
|
|
2561
|
-
simbolo: src.app.sema_consumer_bridge.semaFetchShowroomRanking
|
|
2562
|
-
superficie: "/ranking"
|
|
2563
|
-
arquivo: "src/app/app.routes.ts"
|
|
2564
|
-
arquivo: "src/app/features/ranking/ranking.routes.ts"
|
|
2565
|
-
arquivo: "src/app/features/ranking/ranking-page.component.ts"
|
|
2566
|
-
}
|
|
2567
|
-
guarantees {
|
|
2568
|
-
ranking existe
|
|
2569
|
-
}
|
|
2570
|
-
}
|
|
2571
|
-
}
|
|
2572
|
-
`,
|
|
2573
|
-
},
|
|
2574
|
-
{
|
|
2575
|
-
caminhoRelativo: "src/app/sema_consumer_bridge.ts",
|
|
2576
|
-
conteudo: `export async function semaFetchShowroomRanking() {
|
|
2577
|
-
return {
|
|
2578
|
-
ranking: [
|
|
2579
|
-
{ clube: "Tigres do Norte", pontos: 33 },
|
|
2580
|
-
{ clube: "Porto Azul", pontos: 31 },
|
|
2581
|
-
{ clube: "Galo de Ouro", pontos: 28 },
|
|
2582
|
-
],
|
|
2583
|
-
};
|
|
2584
|
-
}
|
|
2585
|
-
`,
|
|
2586
|
-
},
|
|
2587
|
-
{
|
|
2588
|
-
caminhoRelativo: "src/app/app.routes.ts",
|
|
2589
|
-
conteudo: `import { Routes } from "@angular/router";
|
|
2590
|
-
|
|
2591
|
-
export const routes: Routes = [
|
|
2592
|
-
{
|
|
2593
|
-
path: "ranking",
|
|
2594
|
-
loadChildren: () => import("./features/ranking/ranking.routes").then((m) => m.RANKING_ROUTES),
|
|
2595
|
-
},
|
|
2596
|
-
];
|
|
2597
|
-
`,
|
|
2598
|
-
},
|
|
2599
|
-
{
|
|
2600
|
-
caminhoRelativo: "src/app/features/ranking/ranking.routes.ts",
|
|
2601
|
-
conteudo: `import { Routes } from "@angular/router";
|
|
2602
|
-
|
|
2603
|
-
export const RANKING_ROUTES: Routes = [
|
|
2604
|
-
{
|
|
2605
|
-
path: "",
|
|
2606
|
-
loadComponent: () => import("./ranking-page.component").then((m) => m.RankingPageComponent),
|
|
2607
|
-
},
|
|
2608
|
-
];
|
|
2609
|
-
`,
|
|
2610
|
-
},
|
|
2611
|
-
{
|
|
2612
|
-
caminhoRelativo: "src/app/features/ranking/ranking-page.component.ts",
|
|
2613
|
-
conteudo: `import { Component, OnInit } from "@angular/core";
|
|
2614
|
-
import { CommonModule } from "@angular/common";
|
|
2615
|
-
import { semaFetchShowroomRanking } from "../../sema_consumer_bridge";
|
|
2616
|
-
|
|
2617
|
-
@Component({
|
|
2618
|
-
selector: "app-ranking-page",
|
|
2619
|
-
standalone: true,
|
|
2620
|
-
imports: [CommonModule],
|
|
2621
|
-
template: \`
|
|
2622
|
-
<main>
|
|
2623
|
-
<h1>Ranking showroom</h1>
|
|
2624
|
-
<ul>
|
|
2625
|
-
<li *ngFor="let item of ranking">
|
|
2626
|
-
{{ item.clube }} - {{ item.pontos }} pts
|
|
2627
|
-
</li>
|
|
2628
|
-
</ul>
|
|
2629
|
-
</main>
|
|
2630
|
-
\`,
|
|
2631
|
-
})
|
|
2632
|
-
export class RankingPageComponent implements OnInit {
|
|
2633
|
-
ranking: Array<{ clube: string; pontos: number }> = [];
|
|
2634
|
-
|
|
2635
|
-
async ngOnInit() {
|
|
2636
|
-
const payload = await semaFetchShowroomRanking();
|
|
2637
|
-
this.ranking = payload.ranking ?? [];
|
|
2638
|
-
}
|
|
2639
|
-
}
|
|
2640
|
-
`,
|
|
2641
|
-
},
|
|
2642
|
-
{
|
|
2643
|
-
caminhoRelativo: "src/app/app.component.ts",
|
|
2644
|
-
conteudo: `import { Component } from "@angular/core";
|
|
2645
|
-
import { RouterOutlet } from "@angular/router";
|
|
2646
|
-
|
|
2647
|
-
@Component({
|
|
2648
|
-
selector: "app-root",
|
|
2649
|
-
standalone: true,
|
|
2650
|
-
imports: [RouterOutlet],
|
|
2651
|
-
template: "<router-outlet />",
|
|
2652
|
-
})
|
|
2653
|
-
export class AppComponent {}
|
|
2654
|
-
`,
|
|
2655
|
-
},
|
|
2656
|
-
{
|
|
2657
|
-
caminhoRelativo: "src/main.ts",
|
|
2658
|
-
conteudo: `import { bootstrapApplication } from "@angular/platform-browser";
|
|
2659
|
-
import { provideRouter } from "@angular/router";
|
|
2660
|
-
import { AppComponent } from "./app/app.component";
|
|
2661
|
-
import { routes } from "./app/app.routes";
|
|
2662
|
-
|
|
2663
|
-
void bootstrapApplication(AppComponent, {
|
|
2664
|
-
providers: [provideRouter(routes)],
|
|
2665
|
-
});
|
|
2666
|
-
`,
|
|
2667
|
-
},
|
|
2668
|
-
{
|
|
2669
|
-
caminhoRelativo: "README.md",
|
|
2670
|
-
conteudo: `# Starter Angular Consumer + Sema
|
|
2671
|
-
|
|
2672
|
-
- Contratos em \`contratos/\`
|
|
2673
|
-
- Bridge consumer canonico em \`src/app/sema_consumer_bridge.ts\`
|
|
2674
|
-
- Rotas lazy em \`src/app/app.routes.ts\`
|
|
2675
|
-
- Feature folders em \`src/app/features/\`
|
|
2676
|
-
- O slice oficial desta fase e \`consumer bridge + route config surfaces\`
|
|
2677
|
-
- \`drift\` valida \`impl\`, \`vinculos\`, bridge e superficies, sem prometer visual drift
|
|
2678
|
-
`,
|
|
2679
|
-
},
|
|
2680
|
-
];
|
|
2681
|
-
} else if (template === "flutter-consumer") {
|
|
2682
|
-
arquivos = [
|
|
2683
|
-
{
|
|
2684
|
-
caminhoRelativo: "sema.config.json",
|
|
2685
|
-
conteudo: `{
|
|
2686
|
-
"origens": ["./contratos"],
|
|
2687
|
-
"saida": "./generated",
|
|
2688
|
-
"alvos": ["dart"],
|
|
2689
|
-
"alvoPadrao": "dart",
|
|
2690
|
-
"estruturaSaida": "modulos",
|
|
2691
|
-
"framework": "base",
|
|
2692
|
-
"modoEstrito": true,
|
|
2693
|
-
"diretoriosCodigo": ["./lib"],
|
|
2694
|
-
"fontesLegado": ["flutter-consumer", "dart"],
|
|
2695
|
-
"diretoriosSaidaPorAlvo": {
|
|
2696
|
-
"dart": "./generated/dart"
|
|
2697
|
-
},
|
|
2698
|
-
"convencoesGeracaoPorProjeto": "base"
|
|
2699
|
-
}
|
|
2700
|
-
`,
|
|
2701
|
-
},
|
|
2702
|
-
{
|
|
2703
|
-
caminhoRelativo: "pubspec.yaml",
|
|
2704
|
-
conteudo: `name: sema_flutter_consumer
|
|
2705
|
-
description: Starter Flutter consumer IA-first com Sema
|
|
2706
|
-
publish_to: "none"
|
|
2707
|
-
|
|
2708
|
-
environment:
|
|
2709
|
-
sdk: ">=3.3.0 <4.0.0"
|
|
2710
|
-
|
|
2711
|
-
dependencies:
|
|
2712
|
-
flutter:
|
|
2713
|
-
sdk: flutter
|
|
2714
|
-
go_router: ^14.0.0
|
|
2715
|
-
`,
|
|
2716
|
-
},
|
|
2717
|
-
{
|
|
2718
|
-
caminhoRelativo: "contratos/showroom_consumer.sema",
|
|
2719
|
-
conteudo: `module showroom.consumer {
|
|
2720
|
-
task fetch_showroom_ranking {
|
|
2721
|
-
input {
|
|
2722
|
-
}
|
|
2723
|
-
output {
|
|
2724
|
-
resultado: Json
|
|
2725
|
-
}
|
|
2726
|
-
impl {
|
|
2727
|
-
dart: lib.sema_consumer_bridge.semaFetchShowroomRanking
|
|
2728
|
-
}
|
|
2729
|
-
vinculos {
|
|
2730
|
-
arquivo: "lib/sema_consumer_bridge.dart"
|
|
2731
|
-
simbolo: lib.sema_consumer_bridge.semaFetchShowroomRanking
|
|
2732
|
-
superficie: "/ranking"
|
|
2733
|
-
arquivo: "lib/router.dart"
|
|
2734
|
-
arquivo: "lib/screens/ranking_screen.dart"
|
|
2735
|
-
}
|
|
2736
|
-
guarantees {
|
|
2737
|
-
resultado existe
|
|
2738
|
-
}
|
|
2739
|
-
}
|
|
2740
|
-
}
|
|
2741
|
-
`,
|
|
2742
|
-
},
|
|
2743
|
-
{
|
|
2744
|
-
caminhoRelativo: "lib/sema_consumer_bridge.dart",
|
|
2745
|
-
conteudo: `Future<Map<String, dynamic>> semaFetchShowroomRanking() async {
|
|
2746
|
-
return {
|
|
2747
|
-
"ranking": [
|
|
2748
|
-
{"clube": "Tigres do Norte", "pontos": 33},
|
|
2749
|
-
{"clube": "Porto Azul", "pontos": 31},
|
|
2750
|
-
{"clube": "Galo de Ouro", "pontos": 28},
|
|
2751
|
-
],
|
|
2752
|
-
};
|
|
2753
|
-
}
|
|
2754
|
-
`,
|
|
2755
|
-
},
|
|
2756
|
-
{
|
|
2757
|
-
caminhoRelativo: "lib/router.dart",
|
|
2758
|
-
conteudo: `import "package:go_router/go_router.dart";
|
|
2759
|
-
import "package:flutter/widgets.dart";
|
|
2760
|
-
import "screens/ranking_screen.dart";
|
|
2761
|
-
|
|
2762
|
-
final appRouter = GoRouter(
|
|
2763
|
-
routes: [
|
|
2764
|
-
GoRoute(
|
|
2765
|
-
path: "/ranking",
|
|
2766
|
-
builder: (BuildContext context, GoRouterState state) => const RankingScreen(),
|
|
2767
|
-
),
|
|
2768
|
-
],
|
|
2769
|
-
);
|
|
2770
|
-
`,
|
|
2771
|
-
},
|
|
2772
|
-
{
|
|
2773
|
-
caminhoRelativo: "lib/screens/ranking_screen.dart",
|
|
2774
|
-
conteudo: `import "package:flutter/widgets.dart";
|
|
2775
|
-
import "../sema_consumer_bridge.dart";
|
|
2776
|
-
|
|
2777
|
-
class RankingScreen extends StatefulWidget {
|
|
2778
|
-
const RankingScreen({super.key});
|
|
2779
|
-
|
|
2780
|
-
@override
|
|
2781
|
-
State<RankingScreen> createState() => _RankingScreenState();
|
|
2782
|
-
}
|
|
2783
|
-
|
|
2784
|
-
class _RankingScreenState extends State<RankingScreen> {
|
|
2785
|
-
List<Map<String, dynamic>> ranking = const [];
|
|
2786
|
-
|
|
2787
|
-
@override
|
|
2788
|
-
void initState() {
|
|
2789
|
-
super.initState();
|
|
2790
|
-
semaFetchShowroomRanking().then((payload) {
|
|
2791
|
-
final itens = (payload["ranking"] as List<dynamic>? ?? const [])
|
|
2792
|
-
.whereType<Map<String, dynamic>>()
|
|
2793
|
-
.toList();
|
|
2794
|
-
if (!mounted) return;
|
|
2795
|
-
setState(() {
|
|
2796
|
-
ranking = itens;
|
|
2797
|
-
});
|
|
2798
|
-
});
|
|
2799
|
-
}
|
|
2800
|
-
|
|
2801
|
-
@override
|
|
2802
|
-
Widget build(BuildContext context) {
|
|
2803
|
-
return ListView(
|
|
2804
|
-
children: [
|
|
2805
|
-
const Padding(
|
|
2806
|
-
padding: EdgeInsets.all(16),
|
|
2807
|
-
child: Text("Ranking showroom"),
|
|
2808
|
-
),
|
|
2809
|
-
...ranking.map((item) => Padding(
|
|
2810
|
-
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
|
2811
|
-
child: Text("\${item["clube"]} - \${item["pontos"]} pts"),
|
|
2812
|
-
)),
|
|
2813
|
-
],
|
|
2814
|
-
);
|
|
2815
|
-
}
|
|
2816
|
-
}
|
|
2817
|
-
`,
|
|
2818
|
-
},
|
|
2819
|
-
{
|
|
2820
|
-
caminhoRelativo: "lib/main.dart",
|
|
2821
|
-
conteudo: `import "package:flutter/material.dart";
|
|
2822
|
-
import "router.dart";
|
|
2823
|
-
|
|
2824
|
-
void main() {
|
|
2825
|
-
runApp(const ShowroomApp());
|
|
2826
|
-
}
|
|
2827
|
-
|
|
2828
|
-
class ShowroomApp extends StatelessWidget {
|
|
2829
|
-
const ShowroomApp({super.key});
|
|
2830
|
-
|
|
2831
|
-
@override
|
|
2832
|
-
Widget build(BuildContext context) {
|
|
2833
|
-
return MaterialApp.router(
|
|
2834
|
-
routerConfig: appRouter,
|
|
2835
|
-
);
|
|
2836
|
-
}
|
|
2837
|
-
}
|
|
2838
|
-
`,
|
|
2839
|
-
},
|
|
2840
|
-
{
|
|
2841
|
-
caminhoRelativo: "README.md",
|
|
2842
|
-
conteudo: `# Starter Flutter Consumer + Sema
|
|
2843
|
-
|
|
2844
|
-
- Contratos em \`contratos/\`
|
|
2845
|
-
- Bridge consumer canonico em \`lib/sema_consumer_bridge.dart\`
|
|
2846
|
-
- Rotas consumer em \`lib/router.dart\`
|
|
2847
|
-
- Superficies consumer em \`lib/screens/\`
|
|
2848
|
-
- O slice oficial desta fase e \`consumer bridge + router/screen surfaces\`
|
|
2849
|
-
- \`drift\` valida \`impl\`, \`vinculos\`, bridge e superficies, sem prometer visual diff
|
|
2850
|
-
`,
|
|
2851
|
-
},
|
|
2852
|
-
];
|
|
2853
|
-
} else if (template === "node-firebase-worker") {
|
|
2854
|
-
arquivos = [
|
|
2855
|
-
{
|
|
2856
|
-
caminhoRelativo: "sema.config.json",
|
|
2857
|
-
conteudo: `{
|
|
2858
|
-
"origens": ["./contratos"],
|
|
2859
|
-
"saida": "./generated",
|
|
2860
|
-
"alvos": ["typescript"],
|
|
2861
|
-
"alvoPadrao": "typescript",
|
|
2862
|
-
"estruturaSaida": "modulos",
|
|
2863
|
-
"framework": "base",
|
|
2864
|
-
"modoEstrito": true,
|
|
2865
|
-
"diretoriosCodigo": ["./src"],
|
|
2866
|
-
"fontesLegado": ["firebase", "typescript"],
|
|
2867
|
-
"diretoriosSaidaPorAlvo": {
|
|
2868
|
-
"typescript": "./generated/typescript"
|
|
2869
|
-
},
|
|
2870
|
-
"convencoesGeracaoPorProjeto": "base"
|
|
2871
|
-
}
|
|
2872
|
-
`,
|
|
2873
|
-
},
|
|
2874
|
-
{
|
|
2875
|
-
caminhoRelativo: "contratos/worker_runtime.sema",
|
|
2876
|
-
conteudo: `module worker.runtime {
|
|
2877
|
-
task publicar_payload_health {
|
|
2878
|
-
output {
|
|
2879
|
-
status: Texto
|
|
2880
|
-
timestamp: Texto
|
|
2881
|
-
}
|
|
2882
|
-
effects {
|
|
2883
|
-
evento payload_health criticidade = alta
|
|
2884
|
-
}
|
|
2885
|
-
impl {
|
|
2886
|
-
ts: src.sema_contract_bridge.semaWorkerHealthPayload
|
|
2887
|
-
}
|
|
2888
|
-
guarantees {
|
|
2889
|
-
status existe
|
|
2890
|
-
timestamp existe
|
|
2891
|
-
}
|
|
2892
|
-
}
|
|
2893
|
-
|
|
2894
|
-
task inventariar_colecoes {
|
|
2895
|
-
output {
|
|
2896
|
-
collections: Json
|
|
2897
|
-
}
|
|
2898
|
-
effects {
|
|
2899
|
-
consulta runtime criticidade = baixa
|
|
2900
|
-
}
|
|
2901
|
-
impl {
|
|
2902
|
-
ts: src.sema_contract_bridge.semaCollectionNames
|
|
2903
|
-
}
|
|
2904
|
-
guarantees {
|
|
2905
|
-
collections existe
|
|
2906
|
-
}
|
|
2907
|
-
}
|
|
2908
|
-
|
|
2909
|
-
route get_health_worker {
|
|
2910
|
-
metodo: GET
|
|
2911
|
-
caminho: /health
|
|
2912
|
-
task: publicar_payload_health
|
|
2913
|
-
}
|
|
2914
|
-
}
|
|
2915
|
-
`,
|
|
2916
|
-
},
|
|
2917
|
-
{
|
|
2918
|
-
caminhoRelativo: "src/config/collections.ts",
|
|
2919
|
-
conteudo: `export const COLLECTIONS = {
|
|
2920
|
-
worker_status: "worker_status",
|
|
2921
|
-
audit_log: "audit_log",
|
|
2922
|
-
} as const;
|
|
2923
|
-
`,
|
|
2924
|
-
},
|
|
2925
|
-
{
|
|
2926
|
-
caminhoRelativo: "src/services/health-check.ts",
|
|
2927
|
-
conteudo: `import http from "node:http";
|
|
2928
|
-
|
|
2929
|
-
export type HealthStatus = {
|
|
2930
|
-
status: "healthy" | "degraded" | "unhealthy" | "initializing";
|
|
2931
|
-
timestamp: string;
|
|
2932
|
-
};
|
|
2933
|
-
|
|
2934
|
-
export type HealthProvider = () => HealthStatus;
|
|
2935
|
-
|
|
2936
|
-
export function startHealthCheckServer(port: number, provider: HealthProvider) {
|
|
2937
|
-
const server = http.createServer((req, res) => {
|
|
2938
|
-
if (req.url === "/health" && req.method === "GET") {
|
|
2939
|
-
res.writeHead(200, { "Content-Type": "application/json" });
|
|
2940
|
-
res.end(JSON.stringify(provider()));
|
|
2941
|
-
return;
|
|
2942
|
-
}
|
|
2943
|
-
res.writeHead(404);
|
|
2944
|
-
res.end();
|
|
2945
|
-
});
|
|
2946
|
-
|
|
2947
|
-
server.listen(port);
|
|
2948
|
-
return server;
|
|
2949
|
-
}
|
|
2950
|
-
`,
|
|
2951
|
-
},
|
|
2952
|
-
{
|
|
2953
|
-
caminhoRelativo: "src/sema_contract_bridge.ts",
|
|
2954
|
-
conteudo: `import { COLLECTIONS } from "./config/collections";
|
|
2955
|
-
import { startHealthCheckServer, type HealthProvider, type HealthStatus } from "./services/health-check";
|
|
2956
|
-
|
|
2957
|
-
export function semaStartWorkerHealthServer(port: number, provider: HealthProvider) {
|
|
2958
|
-
return startHealthCheckServer(port, provider);
|
|
2959
|
-
}
|
|
2960
|
-
|
|
2961
|
-
export function semaWorkerHealthPayload(payload: HealthStatus): HealthStatus {
|
|
2962
|
-
return payload;
|
|
2963
|
-
}
|
|
2964
|
-
|
|
2965
|
-
export function semaCollectionNames() {
|
|
2966
|
-
return COLLECTIONS;
|
|
2967
|
-
}
|
|
2968
|
-
`,
|
|
2969
|
-
},
|
|
2970
|
-
{
|
|
2971
|
-
caminhoRelativo: "README.md",
|
|
2972
|
-
conteudo: `# Starter Node Firebase Worker + Sema
|
|
2973
|
-
|
|
2974
|
-
- Contratos em \`contratos/\`
|
|
2975
|
-
- Worker e bridges em \`src/\`
|
|
2976
|
-
- \`drift\` valida impl, endpoint de health e recursos Firestore declarados
|
|
2977
|
-
`,
|
|
2978
|
-
},
|
|
2979
|
-
];
|
|
2980
|
-
} else if (template === "aspnet-api") {
|
|
2981
|
-
arquivos = [
|
|
2982
|
-
{
|
|
2983
|
-
caminhoRelativo: "sema.config.json",
|
|
2984
|
-
conteudo: `{
|
|
2985
|
-
"origens": ["./contratos"],
|
|
2986
|
-
"saida": "./generated",
|
|
2987
|
-
"alvos": ["typescript"],
|
|
2988
|
-
"alvoPadrao": "typescript",
|
|
2989
|
-
"estruturaSaida": "modulos",
|
|
2990
|
-
"framework": "base",
|
|
2991
|
-
"modoEstrito": true,
|
|
2992
|
-
"diretoriosCodigo": ["./src"],
|
|
2993
|
-
"fontesLegado": ["dotnet"],
|
|
2994
|
-
"diretoriosSaidaPorAlvo": {
|
|
2995
|
-
"typescript": "./generated/typescript"
|
|
2996
|
-
},
|
|
2997
|
-
"convencoesGeracaoPorProjeto": "base"
|
|
2998
|
-
}
|
|
2999
|
-
`,
|
|
3000
|
-
},
|
|
3001
|
-
{
|
|
3002
|
-
caminhoRelativo: "contratos/health.sema",
|
|
3003
|
-
conteudo: `module app.health {
|
|
3004
|
-
task get_health {
|
|
3005
|
-
output {
|
|
3006
|
-
status: Texto
|
|
3007
|
-
runtime: Texto
|
|
3008
|
-
}
|
|
3009
|
-
impl {
|
|
3010
|
-
cs: src.Controllers.HealthController.Get
|
|
3011
|
-
}
|
|
3012
|
-
guarantees {
|
|
3013
|
-
status existe
|
|
3014
|
-
runtime existe
|
|
3015
|
-
}
|
|
3016
|
-
}
|
|
3017
|
-
|
|
3018
|
-
route get_health_publico {
|
|
3019
|
-
metodo: GET
|
|
3020
|
-
caminho: /api/health
|
|
3021
|
-
task: get_health
|
|
3022
|
-
}
|
|
3023
|
-
}
|
|
3024
|
-
`,
|
|
3025
|
-
},
|
|
3026
|
-
{
|
|
3027
|
-
caminhoRelativo: "src/Controllers/HealthController.cs",
|
|
3028
|
-
conteudo: `using Microsoft.AspNetCore.Mvc;
|
|
3029
|
-
|
|
3030
|
-
[ApiController]
|
|
3031
|
-
[Route("api/health")]
|
|
3032
|
-
public class HealthController : ControllerBase
|
|
3033
|
-
{
|
|
3034
|
-
[HttpGet]
|
|
3035
|
-
public object Get()
|
|
3036
|
-
{
|
|
3037
|
-
return new { status = "ok", runtime = "aspnet" };
|
|
3038
|
-
}
|
|
3039
|
-
}
|
|
3040
|
-
`,
|
|
3041
|
-
},
|
|
3042
|
-
{
|
|
3043
|
-
caminhoRelativo: "README.md",
|
|
3044
|
-
conteudo: `# Starter ASP.NET Core API + Sema
|
|
3045
|
-
|
|
3046
|
-
- Contratos em \`contratos/\`
|
|
3047
|
-
- Controllers/Minimal API em \`src/\`
|
|
3048
|
-
- \`drift\` valida impl e rota publica
|
|
3049
|
-
`,
|
|
3050
|
-
},
|
|
3051
|
-
];
|
|
3052
|
-
} else if (template === "springboot-api") {
|
|
3053
|
-
arquivos = [
|
|
3054
|
-
{
|
|
3055
|
-
caminhoRelativo: "sema.config.json",
|
|
3056
|
-
conteudo: `{
|
|
3057
|
-
"origens": ["./contratos"],
|
|
3058
|
-
"saida": "./generated",
|
|
3059
|
-
"alvos": ["typescript"],
|
|
3060
|
-
"alvoPadrao": "typescript",
|
|
3061
|
-
"estruturaSaida": "modulos",
|
|
3062
|
-
"framework": "base",
|
|
3063
|
-
"modoEstrito": true,
|
|
3064
|
-
"diretoriosCodigo": ["./src"],
|
|
3065
|
-
"fontesLegado": ["java"],
|
|
3066
|
-
"diretoriosSaidaPorAlvo": {
|
|
3067
|
-
"typescript": "./generated/typescript"
|
|
3068
|
-
},
|
|
3069
|
-
"convencoesGeracaoPorProjeto": "base"
|
|
3070
|
-
}
|
|
3071
|
-
`,
|
|
3072
|
-
},
|
|
3073
|
-
{
|
|
3074
|
-
caminhoRelativo: "contratos/health.sema",
|
|
3075
|
-
conteudo: `module app.health {
|
|
3076
|
-
task get_health {
|
|
3077
|
-
output {
|
|
3078
|
-
status: Texto
|
|
3079
|
-
runtime: Texto
|
|
3080
|
-
}
|
|
3081
|
-
impl {
|
|
3082
|
-
java: src.main.java.com.acme.health.HealthController.health
|
|
3083
|
-
}
|
|
3084
|
-
guarantees {
|
|
3085
|
-
status existe
|
|
3086
|
-
runtime existe
|
|
3087
|
-
}
|
|
3088
|
-
}
|
|
3089
|
-
|
|
3090
|
-
route get_health_publico {
|
|
3091
|
-
metodo: GET
|
|
3092
|
-
caminho: /api/health
|
|
3093
|
-
task: get_health
|
|
3094
|
-
}
|
|
3095
|
-
}
|
|
3096
|
-
`,
|
|
3097
|
-
},
|
|
3098
|
-
{
|
|
3099
|
-
caminhoRelativo: "src/main/java/com/acme/health/HealthController.java",
|
|
3100
|
-
conteudo: `package com.acme.health;
|
|
3101
|
-
|
|
3102
|
-
import java.util.Map;
|
|
3103
|
-
import org.springframework.web.bind.annotation.GetMapping;
|
|
3104
|
-
import org.springframework.web.bind.annotation.RequestMapping;
|
|
3105
|
-
import org.springframework.web.bind.annotation.RestController;
|
|
3106
|
-
|
|
3107
|
-
@RestController
|
|
3108
|
-
@RequestMapping("/api/health")
|
|
3109
|
-
public class HealthController {
|
|
3110
|
-
@GetMapping
|
|
3111
|
-
public Map<String, String> health() {
|
|
3112
|
-
return Map.of("status", "ok", "runtime", "spring");
|
|
3113
|
-
}
|
|
3114
|
-
}
|
|
3115
|
-
`,
|
|
3116
|
-
},
|
|
3117
|
-
{
|
|
3118
|
-
caminhoRelativo: "README.md",
|
|
3119
|
-
conteudo: `# Starter Spring Boot API + Sema
|
|
3120
|
-
|
|
3121
|
-
- Contratos em \`contratos/\`
|
|
3122
|
-
- Controllers REST em \`src/main/java/\`
|
|
3123
|
-
- \`drift\` valida impl e rota publica
|
|
3124
|
-
`,
|
|
3125
|
-
},
|
|
3126
|
-
];
|
|
3127
|
-
} else if (template === "go-http-api") {
|
|
3128
|
-
arquivos = [
|
|
3129
|
-
{
|
|
3130
|
-
caminhoRelativo: "sema.config.json",
|
|
3131
|
-
conteudo: `{
|
|
3132
|
-
"origens": ["./contratos"],
|
|
3133
|
-
"saida": "./generated",
|
|
3134
|
-
"alvos": ["typescript"],
|
|
3135
|
-
"alvoPadrao": "typescript",
|
|
3136
|
-
"estruturaSaida": "modulos",
|
|
3137
|
-
"framework": "base",
|
|
3138
|
-
"modoEstrito": true,
|
|
3139
|
-
"diretoriosCodigo": ["./internal"],
|
|
3140
|
-
"fontesLegado": ["go"],
|
|
3141
|
-
"diretoriosSaidaPorAlvo": {
|
|
3142
|
-
"typescript": "./generated/typescript"
|
|
3143
|
-
},
|
|
3144
|
-
"convencoesGeracaoPorProjeto": "base"
|
|
3145
|
-
}
|
|
3146
|
-
`,
|
|
3147
|
-
},
|
|
3148
|
-
{
|
|
3149
|
-
caminhoRelativo: "contratos/health.sema",
|
|
3150
|
-
conteudo: `module app.health {
|
|
3151
|
-
task get_health {
|
|
3152
|
-
output {
|
|
3153
|
-
resultado: Json
|
|
3154
|
-
}
|
|
3155
|
-
impl {
|
|
3156
|
-
go: internal.health.getHealth
|
|
3157
|
-
}
|
|
3158
|
-
guarantees {
|
|
3159
|
-
resultado existe
|
|
3160
|
-
}
|
|
3161
|
-
}
|
|
3162
|
-
|
|
3163
|
-
route get_health_publico {
|
|
3164
|
-
metodo: GET
|
|
3165
|
-
caminho: /health
|
|
3166
|
-
task: get_health
|
|
3167
|
-
}
|
|
3168
|
-
}
|
|
3169
|
-
`,
|
|
3170
|
-
},
|
|
3171
|
-
{
|
|
3172
|
-
caminhoRelativo: "internal/health.go",
|
|
3173
|
-
conteudo: `package internal
|
|
3174
|
-
|
|
3175
|
-
import "github.com/gin-gonic/gin"
|
|
3176
|
-
|
|
3177
|
-
func registerRoutes(router *gin.Engine) {
|
|
3178
|
-
router.GET("/health", getHealth)
|
|
3179
|
-
}
|
|
3180
|
-
|
|
3181
|
-
func getHealth(ctx *gin.Context) {
|
|
3182
|
-
ctx.JSON(200, gin.H{"status": "ok", "runtime": "go"})
|
|
3183
|
-
}
|
|
3184
|
-
`,
|
|
3185
|
-
},
|
|
3186
|
-
{
|
|
3187
|
-
caminhoRelativo: "README.md",
|
|
3188
|
-
conteudo: `# Starter Go HTTP API + Sema
|
|
3189
|
-
|
|
3190
|
-
- Contratos em \`contratos/\`
|
|
3191
|
-
- Handlers em \`internal/\`
|
|
3192
|
-
- \`drift\` valida impl e rota publica
|
|
3193
|
-
`,
|
|
3194
|
-
},
|
|
3195
|
-
];
|
|
3196
|
-
} else if (template === "rust-axum-api") {
|
|
3197
|
-
arquivos = [
|
|
3198
|
-
{
|
|
3199
|
-
caminhoRelativo: "sema.config.json",
|
|
3200
|
-
conteudo: `{
|
|
3201
|
-
"origens": ["./contratos"],
|
|
3202
|
-
"saida": "./generated",
|
|
3203
|
-
"alvos": ["typescript"],
|
|
3204
|
-
"alvoPadrao": "typescript",
|
|
3205
|
-
"estruturaSaida": "modulos",
|
|
3206
|
-
"framework": "base",
|
|
3207
|
-
"modoEstrito": true,
|
|
3208
|
-
"diretoriosCodigo": ["./src"],
|
|
3209
|
-
"fontesLegado": ["rust"],
|
|
3210
|
-
"diretoriosSaidaPorAlvo": {
|
|
3211
|
-
"typescript": "./generated/typescript"
|
|
3212
|
-
},
|
|
3213
|
-
"convencoesGeracaoPorProjeto": "base"
|
|
3214
|
-
}
|
|
3215
|
-
`,
|
|
3216
|
-
},
|
|
3217
|
-
{
|
|
3218
|
-
caminhoRelativo: "contratos/health.sema",
|
|
3219
|
-
conteudo: `module app.health {
|
|
3220
|
-
task get_health {
|
|
3221
|
-
output {
|
|
3222
|
-
resultado: Json
|
|
3223
|
-
}
|
|
3224
|
-
impl {
|
|
3225
|
-
rust: src.handlers.health
|
|
3226
|
-
}
|
|
3227
|
-
guarantees {
|
|
3228
|
-
resultado existe
|
|
3229
|
-
}
|
|
3230
|
-
}
|
|
3231
|
-
|
|
3232
|
-
route get_health_publico {
|
|
3233
|
-
metodo: GET
|
|
3234
|
-
caminho: /health
|
|
3235
|
-
task: get_health
|
|
3236
|
-
}
|
|
3237
|
-
}
|
|
3238
|
-
`,
|
|
3239
|
-
},
|
|
3240
|
-
{
|
|
3241
|
-
caminhoRelativo: "src/main.rs",
|
|
3242
|
-
conteudo: `use axum::{routing::get, Router};
|
|
3243
|
-
|
|
3244
|
-
mod handlers;
|
|
3245
|
-
|
|
3246
|
-
fn app() -> Router {
|
|
3247
|
-
Router::new().route("/health", get(handlers::health))
|
|
3248
|
-
}
|
|
3249
|
-
`,
|
|
3250
|
-
},
|
|
3251
|
-
{
|
|
3252
|
-
caminhoRelativo: "src/handlers.rs",
|
|
3253
|
-
conteudo: `pub async fn health() -> &'static str {
|
|
3254
|
-
"ok"
|
|
3255
|
-
}
|
|
3256
|
-
`,
|
|
3257
|
-
},
|
|
3258
|
-
{
|
|
3259
|
-
caminhoRelativo: "README.md",
|
|
3260
|
-
conteudo: `# Starter Rust Axum API + Sema
|
|
3261
|
-
|
|
3262
|
-
- Contratos em \`contratos/\`
|
|
3263
|
-
- Handlers em \`src/\`
|
|
3264
|
-
- \`drift\` valida impl e rota publica
|
|
3265
|
-
`,
|
|
3266
|
-
},
|
|
3267
|
-
];
|
|
3268
|
-
} else if (template === "cpp-service-bridge") {
|
|
3269
|
-
arquivos = [
|
|
3270
|
-
{
|
|
3271
|
-
caminhoRelativo: "sema.config.json",
|
|
3272
|
-
conteudo: `{
|
|
3273
|
-
"origens": ["./contratos"],
|
|
3274
|
-
"saida": "./generated",
|
|
3275
|
-
"alvos": ["typescript"],
|
|
3276
|
-
"alvoPadrao": "typescript",
|
|
3277
|
-
"estruturaSaida": "modulos",
|
|
3278
|
-
"framework": "base",
|
|
3279
|
-
"modoEstrito": true,
|
|
3280
|
-
"diretoriosCodigo": ["./src"],
|
|
3281
|
-
"fontesLegado": ["cpp"],
|
|
3282
|
-
"diretoriosSaidaPorAlvo": {
|
|
3283
|
-
"typescript": "./generated/typescript"
|
|
3284
|
-
},
|
|
3285
|
-
"convencoesGeracaoPorProjeto": "base"
|
|
3286
|
-
}
|
|
3287
|
-
`,
|
|
3288
|
-
},
|
|
3289
|
-
{
|
|
3290
|
-
caminhoRelativo: "contratos/runtime_bridge.sema",
|
|
3291
|
-
conteudo: `module app.runtime_bridge {
|
|
3292
|
-
task processar_snapshot {
|
|
3293
|
-
input {
|
|
3294
|
-
payload: Json required
|
|
3295
|
-
}
|
|
3296
|
-
output {
|
|
3297
|
-
resultado: Json
|
|
3298
|
-
}
|
|
3299
|
-
impl {
|
|
3300
|
-
cpp: src.runtime.RuntimeBridge.processSnapshot
|
|
3301
|
-
}
|
|
3302
|
-
guarantees {
|
|
3303
|
-
resultado existe
|
|
3304
|
-
}
|
|
3305
|
-
}
|
|
3306
|
-
}
|
|
3307
|
-
`,
|
|
3308
|
-
},
|
|
3309
|
-
{
|
|
3310
|
-
caminhoRelativo: "src/runtime.cpp",
|
|
3311
|
-
conteudo: `class RuntimeBridge {
|
|
3312
|
-
public:
|
|
3313
|
-
int processSnapshot(int payload) {
|
|
3314
|
-
return payload;
|
|
3315
|
-
}
|
|
3316
|
-
};
|
|
3317
|
-
`,
|
|
3318
|
-
},
|
|
3319
|
-
{
|
|
3320
|
-
caminhoRelativo: "README.md",
|
|
3321
|
-
conteudo: `# Starter C++ Service Bridge + Sema
|
|
3322
|
-
|
|
3323
|
-
- Contratos em \`contratos/\`
|
|
3324
|
-
- Symbols e bridges em \`src/\`
|
|
3325
|
-
- \`drift\` valida impl de simbolos, sem prometer rota HTTP
|
|
3326
|
-
`,
|
|
3327
|
-
},
|
|
3328
|
-
];
|
|
3329
|
-
} else {
|
|
3330
|
-
arquivos = [
|
|
3331
|
-
{
|
|
3332
|
-
caminhoRelativo: "sema.config.json",
|
|
3333
|
-
conteudo: `{
|
|
3334
|
-
"origens": ["./contratos"],
|
|
3335
|
-
"saida": "./generated",
|
|
3336
|
-
"alvos": ["typescript", "python", "dart"],
|
|
3337
|
-
"alvoPadrao": "typescript",
|
|
3338
|
-
"estruturaSaida": "modulos",
|
|
3339
|
-
"framework": "base",
|
|
3340
|
-
"modoEstrito": true,
|
|
3341
|
-
"diretoriosSaidaPorAlvo": {
|
|
3342
|
-
"typescript": "./generated/typescript",
|
|
3343
|
-
"python": "./generated/python",
|
|
3344
|
-
"dart": "./generated/dart"
|
|
3345
|
-
},
|
|
3346
|
-
"convencoesGeracaoPorProjeto": "base"
|
|
3347
|
-
}
|
|
3348
|
-
`,
|
|
3349
|
-
},
|
|
3350
|
-
...arquivosBase,
|
|
3351
|
-
];
|
|
3352
|
-
}
|
|
3353
|
-
|
|
3354
|
-
await escreverArquivos(cwd, arquivos);
|
|
3355
|
-
console.log(`Projeto Sema inicializado com template ${template}.`);
|
|
3356
|
-
return 0;
|
|
3357
|
-
}
|
|
3358
|
-
|
|
3359
|
-
async function comandoValidar(entrada?: string): Promise<number> {
|
|
3360
|
-
const modulos = await carregarModulos(entrada);
|
|
3361
|
-
const diagnosticos = modulos.flatMap((item) => item.resultado.diagnosticos);
|
|
3362
|
-
console.log(formatarDiagnosticos(diagnosticos));
|
|
3363
|
-
return temErros(diagnosticos) ? 1 : 0;
|
|
3364
|
-
}
|
|
3365
|
-
|
|
3366
|
-
async function comandoValidarJson(entrada?: string): Promise<number> {
|
|
3367
|
-
const modulos = await carregarModulos(entrada);
|
|
3368
|
-
const resultados = modulos.map((item) => ({
|
|
3369
|
-
caminho: item.caminho,
|
|
3370
|
-
modulo: item.resultado.modulo?.nome ?? null,
|
|
3371
|
-
sucesso: !temErros(item.resultado.diagnosticos),
|
|
3372
|
-
diagnosticos: item.resultado.diagnosticos,
|
|
3373
|
-
}));
|
|
3374
|
-
console.log(JSON.stringify({
|
|
3375
|
-
comando: "validar",
|
|
3376
|
-
sucesso: resultados.every((resultado) => resultado.sucesso),
|
|
3377
|
-
resultados,
|
|
3378
|
-
}, null, 2));
|
|
3379
|
-
return resultados.every((resultado) => resultado.sucesso) ? 0 : 1;
|
|
3380
|
-
}
|
|
3381
|
-
|
|
3382
|
-
async function comandoInspecionar(entrada: string | undefined, emJson: boolean, cwd = process.cwd()): Promise<number> {
|
|
3383
|
-
const contextoProjeto = await carregarProjeto(entrada, cwd);
|
|
3384
|
-
const resultadoDrift = await analisarDriftLegado(contextoProjeto);
|
|
3385
|
-
const framework = resolverFrameworkPadrao(undefined, contextoProjeto.configCarregada);
|
|
3386
|
-
const estruturaSaida = resolverEstruturaSaidaPadrao(undefined, framework, contextoProjeto.configCarregada);
|
|
3387
|
-
const alvos = resolverAlvosVerificacao(contextoProjeto.configCarregada);
|
|
3388
|
-
const saidas = Object.fromEntries(alvos.map((alvo) => [alvo, resolverSaidaPadrao(undefined, alvo, contextoProjeto.configCarregada)]));
|
|
3389
|
-
const payload = {
|
|
3390
|
-
comando: "inspecionar",
|
|
3391
|
-
entrada: contextoProjeto.entradaResolvida,
|
|
3392
|
-
configuracao: {
|
|
3393
|
-
caminho: contextoProjeto.configCarregada?.caminho ?? null,
|
|
3394
|
-
baseProjeto: contextoProjeto.baseProjeto,
|
|
3395
|
-
framework,
|
|
3396
|
-
estruturaSaida,
|
|
3397
|
-
alvos,
|
|
3398
|
-
saidas,
|
|
3399
|
-
origens: contextoProjeto.origensProjeto,
|
|
3400
|
-
diretoriosCodigo: contextoProjeto.diretoriosCodigo,
|
|
3401
|
-
fontesLegado: contextoProjeto.fontesLegado,
|
|
3402
|
-
modoAdocao: contextoProjeto.modoAdocao,
|
|
3403
|
-
scoreDrift: resultadoDrift.resumo_operacional.scoreMedio,
|
|
3404
|
-
confiancaGeral: resultadoDrift.resumo_operacional.confiancaGeral,
|
|
3405
|
-
consumerFramework: resultadoDrift.consumerFramework,
|
|
3406
|
-
appRoutes: resultadoDrift.appRoutes,
|
|
3407
|
-
consumerSurfaces: resultadoDrift.consumerSurfaces,
|
|
3408
|
-
consumerBridges: resultadoDrift.consumerBridges,
|
|
3409
|
-
},
|
|
3410
|
-
projeto: {
|
|
3411
|
-
arquivos: contextoProjeto.arquivosProjeto,
|
|
3412
|
-
modulos: contextoProjeto.modulosSelecionados.map((item) => ({
|
|
3413
|
-
caminho: item.caminho,
|
|
3414
|
-
modulo: item.resultado.modulo?.nome ?? null,
|
|
3415
|
-
sucesso: !temErros(item.resultado.diagnosticos),
|
|
3416
|
-
diagnosticos: item.resultado.diagnosticos.length,
|
|
3417
|
-
superficies: item.resultado.ir?.superficies.map((superficie) => `${superficie.tipo}:${superficie.nome}`) ?? [],
|
|
3418
|
-
implementacao: resumirDriftPorModulo(item.resultado.modulo?.nome ?? null, item.caminho, resultadoDrift),
|
|
3419
|
-
})),
|
|
3420
|
-
},
|
|
3421
|
-
};
|
|
3422
|
-
|
|
3423
|
-
if (emJson) {
|
|
3424
|
-
console.log(JSON.stringify(payload, null, 2));
|
|
3425
|
-
return 0;
|
|
3426
|
-
}
|
|
3427
|
-
|
|
3428
|
-
console.log("Inspecao de projeto Sema");
|
|
3429
|
-
console.log(`- Entrada: ${payload.entrada}`);
|
|
3430
|
-
console.log(`- Configuracao: ${payload.configuracao.caminho ?? "nenhuma"}`);
|
|
3431
|
-
console.log(`- Base do projeto: ${payload.configuracao.baseProjeto}`);
|
|
3432
|
-
console.log(`- Framework: ${payload.configuracao.framework}`);
|
|
3433
|
-
console.log(`- Estrutura de saida: ${payload.configuracao.estruturaSaida}`);
|
|
3434
|
-
console.log(`- Alvos: ${payload.configuracao.alvos.join(", ")}`);
|
|
3435
|
-
console.log(`- Modo de adocao: ${payload.configuracao.modoAdocao}`);
|
|
3436
|
-
console.log(`- Score medio de drift: ${payload.configuracao.scoreDrift}`);
|
|
3437
|
-
console.log(`- Confianca geral: ${payload.configuracao.confiancaGeral}`);
|
|
3438
|
-
console.log("- Saidas por alvo:");
|
|
3439
|
-
for (const [alvo, saida] of Object.entries(payload.configuracao.saidas)) {
|
|
3440
|
-
console.log(` - ${alvo}: ${saida}`);
|
|
3441
|
-
}
|
|
3442
|
-
console.log("- Origens do projeto:");
|
|
3443
|
-
for (const origem of payload.configuracao.origens) {
|
|
3444
|
-
console.log(` - ${origem}`);
|
|
3445
|
-
}
|
|
3446
|
-
console.log("- Diretorios de codigo:");
|
|
3447
|
-
for (const diretorio of payload.configuracao.diretoriosCodigo) {
|
|
3448
|
-
console.log(` - ${diretorio}`);
|
|
3449
|
-
}
|
|
3450
|
-
console.log(`- Fontes de legado detectadas: ${payload.configuracao.fontesLegado.join(", ") || "nenhuma"}`);
|
|
3451
|
-
console.log("- Modulos selecionados:");
|
|
3452
|
-
for (const modulo of payload.projeto.modulos) {
|
|
3453
|
-
console.log(` - ${modulo.modulo ?? "(sem modulo)"} :: ${modulo.caminho} :: diagnosticos=${modulo.diagnosticos}`);
|
|
3454
|
-
console.log(` impls validos=${modulo.implementacao.implsValidos} quebrados=${modulo.implementacao.implsQuebrados} recursos divergentes=${modulo.implementacao.recursosDivergentesCount} sem_impl=${modulo.implementacao.tasksSemImplementacao}`);
|
|
3455
|
-
for (const arquivoRelacionado of modulo.implementacao.arquivosRelacionados.slice(0, 5)) {
|
|
3456
|
-
console.log(` arquivo relacionado: ${arquivoRelacionado}`);
|
|
3457
|
-
}
|
|
3458
|
-
}
|
|
3459
|
-
return 0;
|
|
3460
|
-
}
|
|
3461
|
-
|
|
3462
|
-
async function comandoDrift(entrada: string | undefined, emJson: boolean, cwd = process.cwd()): Promise<number> {
|
|
3463
|
-
const contextoProjeto = await carregarProjeto(entrada, cwd);
|
|
3464
|
-
const resultado = await analisarDriftLegado(contextoProjeto);
|
|
3465
|
-
|
|
3466
|
-
if (emJson) {
|
|
3467
|
-
console.log(JSON.stringify(resultado, null, 2));
|
|
3468
|
-
return resultado.sucesso ? 0 : 1;
|
|
3469
|
-
}
|
|
3470
|
-
|
|
3471
|
-
console.log("Drift entre Sema e codigo legado");
|
|
3472
|
-
console.log(`- Modulos analisados: ${resultado.modulos.length}`);
|
|
3473
|
-
console.log(`- Tasks analisadas: ${resultado.tasks.length}`);
|
|
3474
|
-
console.log(`- Impl validos: ${resultado.impls_validos.length}`);
|
|
3475
|
-
console.log(`- Impl quebrados: ${resultado.impls_quebrados.length}`);
|
|
3476
|
-
console.log(`- Vinculos validos: ${resultado.vinculos_validos.length}`);
|
|
3477
|
-
console.log(`- Vinculos quebrados: ${resultado.vinculos_quebrados.length}`);
|
|
3478
|
-
console.log(`- Rotas divergentes: ${resultado.rotas_divergentes.length}`);
|
|
3479
|
-
console.log(`- Recursos vivos validos: ${resultado.recursos_validos.length}`);
|
|
3480
|
-
console.log(`- Recursos vivos divergentes: ${resultado.recursos_divergentes.length}`);
|
|
3481
|
-
console.log(`- Score medio: ${resultado.resumo_operacional.scoreMedio}`);
|
|
3482
|
-
console.log(`- Confianca geral: ${resultado.resumo_operacional.confiancaGeral}`);
|
|
3483
|
-
|
|
3484
|
-
if (resultado.impls_quebrados.length > 0) {
|
|
3485
|
-
console.log("- Impl quebrados:");
|
|
3486
|
-
for (const impl of resultado.impls_quebrados) {
|
|
3487
|
-
console.log(` - ${impl.modulo}.${impl.task} :: ${impl.origem}:${impl.caminho}`);
|
|
3488
|
-
if (impl.candidatos && impl.candidatos.length > 0) {
|
|
3489
|
-
console.log(" candidatos provaveis:");
|
|
3490
|
-
for (const candidato of impl.candidatos) {
|
|
3491
|
-
console.log(` - [${candidato.confianca}] ${candidato.caminho} :: ${candidato.arquivo} :: ${candidato.simbolo}`);
|
|
3492
|
-
}
|
|
3493
|
-
}
|
|
3494
|
-
}
|
|
3495
|
-
}
|
|
3496
|
-
|
|
3497
|
-
if (resultado.rotas_divergentes.length > 0) {
|
|
3498
|
-
console.log("- Rotas divergentes:");
|
|
3499
|
-
for (const rota of resultado.rotas_divergentes) {
|
|
3500
|
-
console.log(` - ${rota.modulo}.${rota.route} :: ${rota.metodo ?? "?"} ${rota.caminho ?? "?"}`);
|
|
3501
|
-
}
|
|
3502
|
-
}
|
|
3503
|
-
|
|
3504
|
-
if (resultado.recursos_divergentes.length > 0) {
|
|
3505
|
-
console.log("- Recursos divergentes:");
|
|
3506
|
-
for (const recurso of resultado.recursos_divergentes) {
|
|
3507
|
-
console.log(` - ${recurso.modulo}.${recurso.task} :: ${recurso.categoria} ${recurso.alvo}`);
|
|
3508
|
-
}
|
|
3509
|
-
}
|
|
3510
|
-
|
|
3511
|
-
const semImpl = resultado.tasks.filter((task) => task.semImplementacao);
|
|
3512
|
-
if (semImpl.length > 0) {
|
|
3513
|
-
console.log("- Tasks sem implementacao vinculada:");
|
|
3514
|
-
for (const task of semImpl) {
|
|
3515
|
-
console.log(` - ${task.modulo}.${task.task}`);
|
|
3516
|
-
if (task.candidatosImpl.length > 0) {
|
|
3517
|
-
console.log(" candidatos provaveis:");
|
|
3518
|
-
for (const candidato of task.candidatosImpl) {
|
|
3519
|
-
console.log(` - [${candidato.confianca}] ${candidato.caminho} :: ${candidato.arquivo} :: ${candidato.simbolo}`);
|
|
3520
|
-
}
|
|
3521
|
-
}
|
|
3522
|
-
}
|
|
3523
|
-
}
|
|
3524
|
-
|
|
3525
|
-
if (resultado.vinculos_quebrados.length > 0) {
|
|
3526
|
-
console.log("- Vinculos quebrados:");
|
|
3527
|
-
for (const vinculo of resultado.vinculos_quebrados) {
|
|
3528
|
-
console.log(` - ${vinculo.modulo}.${vinculo.dono} :: ${vinculo.tipo}=${vinculo.valor}`);
|
|
3529
|
-
}
|
|
3530
|
-
}
|
|
3531
|
-
|
|
3532
|
-
if (resultado.resumo_operacional.oQueTocar.length > 0) {
|
|
3533
|
-
console.log("- O que tocar primeiro:");
|
|
3534
|
-
for (const alvo of resultado.resumo_operacional.oQueTocar.slice(0, 8)) {
|
|
3535
|
-
console.log(` - ${alvo}`);
|
|
3536
|
-
}
|
|
3537
|
-
}
|
|
3538
|
-
|
|
3539
|
-
if (resultado.resumo_operacional.oQueValidar.length > 0) {
|
|
3540
|
-
console.log("- O que validar:");
|
|
3541
|
-
for (const check of resultado.resumo_operacional.oQueValidar.slice(0, 8)) {
|
|
3542
|
-
console.log(` - ${check}`);
|
|
3543
|
-
}
|
|
3544
|
-
}
|
|
3545
|
-
|
|
3546
|
-
if (resultado.diagnosticos.length === 0) {
|
|
3547
|
-
console.log("Nenhum drift relevante encontrado.");
|
|
3548
|
-
}
|
|
3549
|
-
|
|
3550
|
-
return resultado.sucesso ? 0 : 1;
|
|
3551
|
-
}
|
|
3552
|
-
|
|
3553
|
-
async function comandoImportar(
|
|
3554
|
-
fonte: FonteImportacao,
|
|
3555
|
-
diretorio: string,
|
|
3556
|
-
saida: string,
|
|
3557
|
-
namespaceBase: string | undefined,
|
|
3558
|
-
emJson: boolean,
|
|
3559
|
-
): Promise<number> {
|
|
3560
|
-
const resultado = await importarProjetoLegado(fonte, diretorio, namespaceBase);
|
|
3561
|
-
const resumo = resumoImportacao(resultado);
|
|
3562
|
-
|
|
3563
|
-
if (!resumo.sucesso) {
|
|
3564
|
-
const payloadErro = {
|
|
3565
|
-
comando: "importar",
|
|
3566
|
-
fonte,
|
|
3567
|
-
diretorio: path.resolve(diretorio),
|
|
3568
|
-
namespaceBase: resultado.namespaceBase,
|
|
3569
|
-
resumo,
|
|
3570
|
-
arquivos: resultado.arquivos.map((arquivo) => ({
|
|
3571
|
-
caminho: path.join(path.resolve(saida), arquivo.caminhoRelativo),
|
|
3572
|
-
modulo: arquivo.modulo,
|
|
3573
|
-
tarefas: arquivo.tarefas,
|
|
3574
|
-
rotas: arquivo.rotas,
|
|
3575
|
-
entidades: arquivo.entidades,
|
|
3576
|
-
enums: arquivo.enums,
|
|
3577
|
-
})),
|
|
3578
|
-
diagnosticos: resultado.diagnosticos,
|
|
3579
|
-
};
|
|
3580
|
-
|
|
3581
|
-
if (emJson) {
|
|
3582
|
-
console.log(JSON.stringify(payloadErro, null, 2));
|
|
3583
|
-
} else {
|
|
3584
|
-
console.error("Falha na importacao assistida. O rascunho gerado ainda nao ficou semanticamente valido.");
|
|
3585
|
-
console.error(formatarDiagnosticos(resultado.diagnosticos));
|
|
3586
|
-
}
|
|
3587
|
-
return 1;
|
|
3588
|
-
}
|
|
3589
|
-
|
|
3590
|
-
await escreverArquivos(saida, resultado.arquivos.map((arquivo) => ({
|
|
3591
|
-
caminhoRelativo: arquivo.caminhoRelativo,
|
|
3592
|
-
conteudo: arquivo.conteudo,
|
|
3593
|
-
})));
|
|
3594
|
-
|
|
3595
|
-
const payload = {
|
|
3596
|
-
comando: "importar",
|
|
3597
|
-
fonte,
|
|
3598
|
-
diretorio: path.resolve(diretorio),
|
|
3599
|
-
saida: path.resolve(saida),
|
|
3600
|
-
namespaceBase: resultado.namespaceBase,
|
|
3601
|
-
resumo,
|
|
3602
|
-
arquivos: resultado.arquivos.map((arquivo) => ({
|
|
3603
|
-
caminho: path.join(path.resolve(saida), arquivo.caminhoRelativo),
|
|
3604
|
-
modulo: arquivo.modulo,
|
|
3605
|
-
tarefas: arquivo.tarefas,
|
|
3606
|
-
rotas: arquivo.rotas,
|
|
3607
|
-
entidades: arquivo.entidades,
|
|
3608
|
-
enums: arquivo.enums,
|
|
3609
|
-
})),
|
|
3610
|
-
};
|
|
3611
|
-
|
|
3612
|
-
if (emJson) {
|
|
3613
|
-
console.log(JSON.stringify(payload, null, 2));
|
|
3614
|
-
return 0;
|
|
3615
|
-
}
|
|
3616
|
-
|
|
3617
|
-
console.log("Importacao assistida para Sema concluida.");
|
|
3618
|
-
console.log(`- Fonte: ${fonte}`);
|
|
3619
|
-
console.log(`- Diretorio analisado: ${payload.diretorio}`);
|
|
3620
|
-
console.log(`- Namespace base: ${payload.namespaceBase}`);
|
|
3621
|
-
console.log(`- Saida: ${payload.saida}`);
|
|
3622
|
-
console.log(`- Modulos: ${resumo.modulos}`);
|
|
3623
|
-
console.log(`- Tarefas: ${resumo.tarefas}`);
|
|
3624
|
-
console.log(`- Rotas: ${resumo.rotas}`);
|
|
3625
|
-
console.log(`- Entidades: ${resumo.entidades}`);
|
|
3626
|
-
console.log(`- Enums: ${resumo.enums}`);
|
|
3627
|
-
console.log("- Arquivos gerados:");
|
|
3628
|
-
for (const arquivo of payload.arquivos) {
|
|
3629
|
-
console.log(` - ${arquivo.caminho} :: modulo=${arquivo.modulo} tarefas=${arquivo.tarefas} rotas=${arquivo.rotas}`);
|
|
3630
|
-
}
|
|
3631
|
-
console.log("Ajuste os rascunhos .sema, rode `sema formatar`, `sema validar --json` e depois `sema compilar`.");
|
|
3632
|
-
return 0;
|
|
3633
|
-
}
|
|
3634
|
-
|
|
3635
|
-
async function comandoAst(arquivo: string): Promise<number> {
|
|
3636
|
-
const codigo = await lerArquivoTexto(arquivo);
|
|
3637
|
-
const resultado = compilarCodigo(codigo, arquivo);
|
|
3638
|
-
console.log(JSON.stringify(resultado.modulo ?? null, null, 2));
|
|
3639
|
-
return temErros(resultado.diagnosticos) ? 1 : 0;
|
|
3640
|
-
}
|
|
3641
|
-
|
|
3642
|
-
async function comandoAstJson(arquivo: string): Promise<number> {
|
|
3643
|
-
const codigo = await lerArquivoTexto(arquivo);
|
|
3644
|
-
const resultado = compilarCodigo(codigo, arquivo);
|
|
3645
|
-
console.log(JSON.stringify({
|
|
3646
|
-
comando: "ast",
|
|
3647
|
-
caminho: path.resolve(arquivo),
|
|
3648
|
-
modulo: resultado.modulo?.nome ?? null,
|
|
3649
|
-
sucesso: !temErros(resultado.diagnosticos),
|
|
3650
|
-
diagnosticos: resultado.diagnosticos,
|
|
3651
|
-
ast: resultado.modulo ?? null,
|
|
3652
|
-
}, null, 2));
|
|
3653
|
-
return temErros(resultado.diagnosticos) ? 1 : 0;
|
|
3654
|
-
}
|
|
3655
|
-
|
|
3656
|
-
async function comandoIr(arquivo: string): Promise<number> {
|
|
3657
|
-
const codigo = await lerArquivoTexto(arquivo);
|
|
3658
|
-
const resultado = compilarCodigo(codigo, arquivo);
|
|
3659
|
-
console.log(JSON.stringify(resultado.ir ?? null, null, 2));
|
|
3660
|
-
return temErros(resultado.diagnosticos) ? 1 : 0;
|
|
3661
|
-
}
|
|
3662
|
-
|
|
3663
|
-
async function comandoIrJson(arquivo: string): Promise<number> {
|
|
3664
|
-
const codigo = await lerArquivoTexto(arquivo);
|
|
3665
|
-
const resultado = compilarCodigo(codigo, arquivo);
|
|
3666
|
-
console.log(JSON.stringify({
|
|
3667
|
-
comando: "ir",
|
|
3668
|
-
caminho: path.resolve(arquivo),
|
|
3669
|
-
modulo: resultado.modulo?.nome ?? null,
|
|
3670
|
-
sucesso: !temErros(resultado.diagnosticos),
|
|
3671
|
-
diagnosticos: resultado.diagnosticos,
|
|
3672
|
-
ir: resultado.ir ?? null,
|
|
3673
|
-
}, null, 2));
|
|
3674
|
-
return temErros(resultado.diagnosticos) ? 1 : 0;
|
|
3675
|
-
}
|
|
3676
|
-
|
|
3677
|
-
async function comandoCompilar(
|
|
3678
|
-
entrada: string | undefined,
|
|
3679
|
-
alvo: AlvoGeracao,
|
|
3680
|
-
saida: string,
|
|
3681
|
-
estrutura: EstruturaSaida,
|
|
3682
|
-
framework: FrameworkGeracao,
|
|
3683
|
-
cwd = process.cwd(),
|
|
3684
|
-
): Promise<number> {
|
|
3685
|
-
const incompatibilidade = validarCompatibilidadeFramework(alvo, framework);
|
|
3686
|
-
if (incompatibilidade) {
|
|
3687
|
-
console.error(incompatibilidade);
|
|
3688
|
-
return 1;
|
|
3689
|
-
}
|
|
3690
|
-
|
|
3691
|
-
const modulos = await carregarModulos(entrada, cwd);
|
|
3692
|
-
const diagnosticos = modulos.flatMap((item) => item.resultado.diagnosticos);
|
|
3693
|
-
if (temErros(diagnosticos)) {
|
|
3694
|
-
console.error(formatarDiagnosticos(diagnosticos));
|
|
3695
|
-
return 1;
|
|
3696
|
-
}
|
|
3697
|
-
|
|
3698
|
-
for (const modulo of modulos) {
|
|
3699
|
-
const ir = garantirIr(modulo.resultado, modulo.caminho);
|
|
3700
|
-
const arquivos = aplicarEstruturaSaida(gerarArquivosPorAlvo(ir, alvo, framework), ir, estrutura);
|
|
3701
|
-
await escreverArquivos(saida, arquivos);
|
|
3702
|
-
}
|
|
3703
|
-
console.log(`Compilacao concluida para o alvo ${alvo} com estrutura ${estrutura} e framework ${framework}.`);
|
|
3704
|
-
return 0;
|
|
3705
|
-
}
|
|
3706
|
-
|
|
3707
|
-
async function comandoDiagnosticos(arquivo: string, emJson: boolean): Promise<number> {
|
|
3708
|
-
const codigo = await lerArquivoTexto(arquivo);
|
|
3709
|
-
const resultado = compilarCodigo(codigo, arquivo);
|
|
3710
|
-
if (emJson) {
|
|
3711
|
-
console.log(JSON.stringify(resultado.diagnosticos, null, 2));
|
|
3712
|
-
} else {
|
|
3713
|
-
console.log(formatarDiagnosticos(resultado.diagnosticos));
|
|
3714
|
-
}
|
|
3715
|
-
return temErros(resultado.diagnosticos) ? 1 : 0;
|
|
3716
|
-
}
|
|
3717
|
-
|
|
3718
|
-
async function comandoFormatar(entrada: string | undefined, verificarApenas: boolean, emJson: boolean): Promise<number> {
|
|
3719
|
-
const contextoProjeto = await carregarProjeto(entrada, process.cwd());
|
|
3720
|
-
const entradaResolvida = contextoProjeto.entradaResolvida;
|
|
3721
|
-
const estatisticas = await stat(entradaResolvida);
|
|
3722
|
-
const arquivos = estatisticas.isFile()
|
|
3723
|
-
? [entradaResolvida]
|
|
3724
|
-
: contextoProjeto.arquivosProjeto.filter((arquivo) => arquivo.startsWith(path.resolve(entradaResolvida)));
|
|
3725
|
-
const resultados: ResultadoFormatacaoArquivo[] = [];
|
|
3726
|
-
|
|
3727
|
-
for (const arquivo of arquivos) {
|
|
3728
|
-
const codigo = await lerArquivoTexto(arquivo);
|
|
3729
|
-
const resultado = formatarCodigo(codigo, arquivo);
|
|
3730
|
-
const sucesso = !temErros(resultado.diagnosticos) && Boolean(resultado.codigoFormatado);
|
|
3731
|
-
resultados.push({
|
|
3732
|
-
caminho: arquivo,
|
|
3733
|
-
alterado: resultado.alterado,
|
|
3734
|
-
sucesso,
|
|
3735
|
-
diagnosticos: resultado.diagnosticos,
|
|
3736
|
-
});
|
|
3737
|
-
|
|
3738
|
-
if (sucesso && !verificarApenas && resultado.alterado && resultado.codigoFormatado) {
|
|
3739
|
-
await writeFile(arquivo, resultado.codigoFormatado, "utf8");
|
|
3740
|
-
}
|
|
3741
|
-
}
|
|
3742
|
-
|
|
3743
|
-
const possuiErros = resultados.some((resultado) => !resultado.sucesso);
|
|
3744
|
-
const possuiDiferencas = resultados.some((resultado) => resultado.alterado);
|
|
3745
|
-
const codigoSaida = possuiErros ? 1 : verificarApenas && possuiDiferencas ? 1 : 0;
|
|
3746
|
-
|
|
3747
|
-
if (emJson) {
|
|
3748
|
-
console.log(JSON.stringify({
|
|
3749
|
-
comando: "formatar",
|
|
3750
|
-
sucesso: codigoSaida === 0,
|
|
3751
|
-
modo: verificarApenas ? "check" : "write",
|
|
3752
|
-
arquivos: resultados,
|
|
3753
|
-
totais: {
|
|
3754
|
-
arquivos: resultados.length,
|
|
3755
|
-
alterados: resultados.filter((resultado) => resultado.alterado).length,
|
|
3756
|
-
erros: resultados.filter((resultado) => !resultado.sucesso).length,
|
|
3757
|
-
},
|
|
3758
|
-
}, null, 2));
|
|
3759
|
-
return codigoSaida;
|
|
3760
|
-
}
|
|
3761
|
-
|
|
3762
|
-
if (possuiErros) {
|
|
3763
|
-
console.error(formatarDiagnosticos(resultados.flatMap((resultado) => resultado.diagnosticos)));
|
|
3764
|
-
return 1;
|
|
3765
|
-
}
|
|
3766
|
-
|
|
3767
|
-
if (verificarApenas) {
|
|
3768
|
-
if (possuiDiferencas) {
|
|
3769
|
-
console.error("Arquivos fora do formato canonico:");
|
|
3770
|
-
for (const resultado of resultados.filter((item) => item.alterado)) {
|
|
3771
|
-
console.error(`- ${resultado.caminho}`);
|
|
3772
|
-
}
|
|
3773
|
-
return 1;
|
|
3774
|
-
}
|
|
3775
|
-
console.log("Todos os arquivos ja estao no formato canonico.");
|
|
3776
|
-
return 0;
|
|
3777
|
-
}
|
|
3778
|
-
|
|
3779
|
-
console.log(`Formatacao concluida. Arquivos verificados=${resultados.length} alterados=${resultados.filter((resultado) => resultado.alterado).length}`);
|
|
3780
|
-
return 0;
|
|
3781
|
-
}
|
|
3782
|
-
|
|
3783
|
-
async function comandoStarterIa(): Promise<number> {
|
|
3784
|
-
const descoberta = await descobrirDocsIa();
|
|
3785
|
-
console.log("Starter de IA da Sema");
|
|
3786
|
-
console.log("");
|
|
3787
|
-
console.log(renderizarCabecalhoDocsIa(descoberta));
|
|
3788
|
-
console.log("");
|
|
3789
|
-
console.log(STARTER_IA);
|
|
3790
|
-
return 0;
|
|
3791
|
-
}
|
|
3792
|
-
|
|
3793
|
-
async function comandoSyncAiEntrypoints(emJson: boolean): Promise<number> {
|
|
3794
|
-
const resumoProjeto = await gerarResumoProjetoIa(process.cwd(), undefined, true);
|
|
3795
|
-
const indexJson = JSON.parse(await readFile(path.join(resumoProjeto.pastaSaida, "SEMA_INDEX.json"), "utf8"));
|
|
3796
|
-
const artefatos = [...new Set([
|
|
3797
|
-
...ARQUIVOS_CANONICOS_IA_RAIZ,
|
|
3798
|
-
...resumoProjeto.artefatos,
|
|
3799
|
-
])];
|
|
3800
|
-
|
|
3801
|
-
if (emJson) {
|
|
3802
|
-
console.log(JSON.stringify({
|
|
3803
|
-
comando: "sync-ai-entrypoints",
|
|
3804
|
-
sucesso: true,
|
|
3805
|
-
baseProjeto: resumoProjeto.baseProjeto,
|
|
3806
|
-
pastaSaida: resumoProjeto.pastaSaida,
|
|
3807
|
-
artefatos,
|
|
3808
|
-
entradaCanonica: indexJson.entradaCanonica,
|
|
3809
|
-
}, null, 2));
|
|
3810
|
-
return 0;
|
|
3811
|
-
}
|
|
3812
|
-
|
|
3813
|
-
console.log("Entrypoints IA-first sincronizados");
|
|
3814
|
-
console.log("");
|
|
3815
|
-
console.log(`Base do projeto: ${resumoProjeto.baseProjeto}`);
|
|
3816
|
-
console.log(`Ordem canonica: ${indexJson.entradaCanonica.ordemLeitura.join(" -> ")}`);
|
|
3817
|
-
console.log(`IA pequena: ${indexJson.entradaCanonica.porCapacidade.pequena.join(" -> ")}`);
|
|
3818
|
-
console.log(`IA media: ${indexJson.entradaCanonica.porCapacidade.media.join(" -> ")}`);
|
|
3819
|
-
console.log(`IA grande: ${indexJson.entradaCanonica.porCapacidade.grande.join(" -> ")}`);
|
|
3820
|
-
return 0;
|
|
3821
|
-
}
|
|
3822
|
-
|
|
3823
|
-
async function comandoAjudaIa(): Promise<number> {
|
|
3824
|
-
const descoberta = await descobrirDocsIa();
|
|
3825
|
-
console.log("Ajuda de IA da Sema");
|
|
3826
|
-
console.log("");
|
|
3827
|
-
console.log(renderizarCaixaAscii([
|
|
3828
|
-
"IA-first para greenfield, edicao guiada e legado sem contrato inicial",
|
|
3829
|
-
"use o menor artefato semantico que resolva a tarefa",
|
|
3830
|
-
]));
|
|
3831
|
-
console.log("");
|
|
3832
|
-
console.log(renderizarCabecalhoDocsIa(descoberta));
|
|
3833
|
-
console.log("");
|
|
3834
|
-
console.log(renderizarSecaoAscii("Tres jeitos de usar a Sema", [
|
|
3835
|
-
"[1] Producao inicial: modele, valide, compile e verifique antes de subir codigo derivado.",
|
|
3836
|
-
"[2] Edicao em projeto com Sema: inspecione, leia resumo, rode drift e gere contexto antes de editar codigo vivo.",
|
|
3837
|
-
"[3] Projeto sem Sema ainda: importe, revise o rascunho, formate, valide e use drift como juiz da adocao incremental.",
|
|
3838
|
-
]));
|
|
3839
|
-
console.log("");
|
|
3840
|
-
console.log(renderizarSecaoAscii("Capacidade de IA", [
|
|
3841
|
-
"pequena: `sema resumo --micro`, `briefing.min.json`, `prompt-curto.txt`",
|
|
3842
|
-
"media: `sema resumo --curto`, `drift.json`, `briefing.min.json`",
|
|
3843
|
-
"grande: `sema contexto-ia`, `briefing.json`, `ir.json`, `ast.json`",
|
|
3844
|
-
]));
|
|
3845
|
-
console.log("");
|
|
3846
|
-
console.log(renderizarSecaoAscii("Fluxo recomendado", [
|
|
3847
|
-
"Use `sema starter-ia` para um texto curto de onboarding.",
|
|
3848
|
-
"Use `sema sync-ai-entrypoints` para regenerar `SEMA_BRIEF.*` e `SEMA_INDEX.json` na raiz.",
|
|
3849
|
-
"Use `sema resumo <arquivo> --micro --para onboarding` para IA pequena.",
|
|
3850
|
-
"Use `sema prompt-curto <arquivo> --curto --para mudanca` para colar contexto em modelo gratuito.",
|
|
3851
|
-
"Use `sema prompt-ia`, `sema prompt-ia-ui`, `sema prompt-ia-react` e `sema prompt-ia-sema-primeiro` conforme a tarefa.",
|
|
3852
|
-
"Use `sema exemplos-prompt-ia` para pegar modelos prontos de prompt.",
|
|
3853
|
-
"Use `sema inspecionar` para descobrir base, codigo vivo e fontes legado.",
|
|
3854
|
-
"Use `sema drift` para medir impls, vinculos, rotas, score e lacunas.",
|
|
3855
|
-
"Use `sema contexto-ia <arquivo.sema>` para gerar AST, IR, drift, `briefing.json` e `briefing.min.json`.",
|
|
3856
|
-
"Use `sema compilar <arquivo-ou-pasta> --alvo <typescript|python|dart|lua> --saida <diretorio>` quando a tarefa pedir codigo derivado.",
|
|
3857
|
-
]));
|
|
3858
|
-
console.log("");
|
|
3859
|
-
console.log(renderizarSecaoAscii("Regras praticas", [
|
|
3860
|
-
"Foi feita para IA operar melhor; leitura humana e consequencia, nao centro de produto.",
|
|
3861
|
-
"Governa contrato, intencao, erro, efeito, garantia, fluxo, vinculos e execucao.",
|
|
3862
|
-
"Nao escreve contrato final sozinho nem substitui decisao arquitetural.",
|
|
3863
|
-
"Se voce quer testar a Sema de verdade, nao peca so HTML solto.",
|
|
3864
|
-
"Peca `.sema` + arquitetura + React + TypeScript, ou use o modo `Sema primeiro`.",
|
|
3865
|
-
"Se o projeto ja existe, trate `importar` como rascunho e `drift` como juiz.",
|
|
3866
|
-
"IA pequena comeca no menor artefato que resolve a tarefa; nao enfie `ast.json` inteiro nela de bobeira.",
|
|
3867
|
-
"Antes de editar software vivo, leia `briefing.min.json` ou `briefing.json` em vez de sair cavando arquivo na fe.",
|
|
3868
|
-
"Trate `route`, `worker`, `evento`, `fila`, `cron`, `webhook`, `cache`, `storage` e `policy` como superficies de primeira classe.",
|
|
3869
|
-
]));
|
|
3870
|
-
return 0;
|
|
3871
|
-
}
|
|
3872
|
-
|
|
3873
|
-
async function comandoPromptIa(): Promise<number> {
|
|
3874
|
-
const descoberta = await descobrirDocsIa();
|
|
3875
|
-
console.log("Prompt-base de IA da Sema");
|
|
3876
|
-
console.log("");
|
|
3877
|
-
console.log(renderizarCabecalhoDocsIa(descoberta));
|
|
3878
|
-
console.log("");
|
|
3879
|
-
console.log(PROMPT_BASE_IA);
|
|
3880
|
-
return 0;
|
|
3881
|
-
}
|
|
3882
|
-
|
|
3883
|
-
async function comandoPromptIaUi(): Promise<number> {
|
|
3884
|
-
const descoberta = await descobrirDocsIa();
|
|
3885
|
-
console.log("Prompt de IA da Sema para UI");
|
|
3886
|
-
console.log("");
|
|
3887
|
-
console.log(renderizarCabecalhoDocsIa(descoberta));
|
|
3888
|
-
console.log("");
|
|
3889
|
-
console.log(PROMPT_IA_UI);
|
|
3890
|
-
return 0;
|
|
3891
|
-
}
|
|
3892
|
-
|
|
3893
|
-
async function comandoPromptIaReact(): Promise<number> {
|
|
3894
|
-
const descoberta = await descobrirDocsIa();
|
|
3895
|
-
console.log("Prompt de IA da Sema para React");
|
|
3896
|
-
console.log("");
|
|
3897
|
-
console.log(renderizarCabecalhoDocsIa(descoberta));
|
|
3898
|
-
console.log("");
|
|
3899
|
-
console.log(PROMPT_IA_REACT);
|
|
3900
|
-
return 0;
|
|
3901
|
-
}
|
|
3902
|
-
|
|
3903
|
-
async function comandoPromptIaSemaPrimeiro(): Promise<number> {
|
|
3904
|
-
const descoberta = await descobrirDocsIa();
|
|
3905
|
-
console.log("Prompt de IA da Sema no modo Sema primeiro");
|
|
3906
|
-
console.log("");
|
|
3907
|
-
console.log(renderizarCabecalhoDocsIa(descoberta));
|
|
3908
|
-
console.log("");
|
|
3909
|
-
console.log(PROMPT_IA_SEMA_PRIMEIRO);
|
|
3910
|
-
return 0;
|
|
3911
|
-
}
|
|
3912
|
-
|
|
3913
|
-
async function comandoExemplosPromptIa(): Promise<number> {
|
|
3914
|
-
const descoberta = await descobrirDocsIa();
|
|
3915
|
-
console.log("Exemplos de prompt de IA da Sema");
|
|
3916
|
-
console.log("");
|
|
3917
|
-
console.log(renderizarCabecalhoDocsIa(descoberta));
|
|
3918
|
-
console.log("");
|
|
3919
|
-
console.log(EXEMPLOS_PROMPT_IA);
|
|
3920
|
-
return 0;
|
|
3921
|
-
}
|
|
3922
|
-
|
|
3923
|
-
async function comandoResumo(
|
|
3924
|
-
entrada: string | undefined,
|
|
3925
|
-
args: string[],
|
|
3926
|
-
emJson: boolean,
|
|
3927
|
-
): Promise<number> {
|
|
3928
|
-
const tamanho = normalizarTamanhoResumo(args);
|
|
3929
|
-
const modo = normalizarModoResumo(obterOpcao(args, "--para"));
|
|
3930
|
-
const pastaSaida = obterOpcao(args, "--saida");
|
|
3931
|
-
const escreverNaRaiz = possuiFlag(args, "--raiz");
|
|
3932
|
-
const alvo = entrada ? path.resolve(process.cwd(), entrada) : process.cwd();
|
|
3933
|
-
|
|
3934
|
-
if (entrada && entrada.toLowerCase().endsWith(".sema")) {
|
|
3935
|
-
const contexto = await carregarContextoModuloIa(alvo);
|
|
3936
|
-
const resumoSemantico = coletarResumoSemanticoModulo(contexto);
|
|
3937
|
-
const guiaPorCapacidade = criarGuiaCapacidadeIa();
|
|
3938
|
-
const texto = tamanho === "medio"
|
|
3939
|
-
? renderizarResumoModuloMarkdown(resumoSemantico, modo, guiaPorCapacidade)
|
|
3940
|
-
: renderizarResumoModuloTexto(resumoSemantico, tamanho, modo);
|
|
3941
|
-
|
|
3942
|
-
let pastaResumo: string | undefined;
|
|
3943
|
-
let artefatosCompactos: string[] = [];
|
|
3944
|
-
if (pastaSaida) {
|
|
3945
|
-
pastaResumo = path.resolve(pastaSaida);
|
|
3946
|
-
await mkdir(pastaResumo, { recursive: true });
|
|
3947
|
-
const gerado = await gerarArquivosResumoModuloIa(contexto, pastaResumo);
|
|
3948
|
-
artefatosCompactos = gerado.artefatosCompactos;
|
|
3949
|
-
}
|
|
3950
|
-
|
|
3951
|
-
if (emJson) {
|
|
3952
|
-
console.log(JSON.stringify({
|
|
3953
|
-
comando: "resumo",
|
|
3954
|
-
modo,
|
|
3955
|
-
tamanho,
|
|
3956
|
-
geradoEm: contexto.geradoEm,
|
|
3957
|
-
arquivo: contexto.arquivo,
|
|
3958
|
-
modulo: contexto.modulo,
|
|
3959
|
-
pastaSaida: pastaResumo ?? null,
|
|
3960
|
-
artefatosCompactos,
|
|
3961
|
-
guiaPorCapacidade,
|
|
3962
|
-
resumo: resumoSemantico,
|
|
3963
|
-
texto,
|
|
3964
|
-
}, null, 2));
|
|
3965
|
-
return 0;
|
|
3966
|
-
}
|
|
3967
|
-
|
|
3968
|
-
if (pastaResumo) {
|
|
3969
|
-
console.log(`Resumo IA-first gerado em ${pastaResumo}`);
|
|
3970
|
-
console.log("");
|
|
3971
|
-
}
|
|
3972
|
-
console.log(texto);
|
|
3973
|
-
return 0;
|
|
3974
|
-
}
|
|
3975
|
-
|
|
3976
|
-
const resumoProjeto = await gerarResumoProjetoIa(alvo, pastaSaida, escreverNaRaiz);
|
|
3977
|
-
const arquivoResumo = tamanho === "micro"
|
|
3978
|
-
? "SEMA_BRIEF.micro.txt"
|
|
3979
|
-
: tamanho === "curto"
|
|
3980
|
-
? "SEMA_BRIEF.curto.txt"
|
|
3981
|
-
: "SEMA_BRIEF.md";
|
|
3982
|
-
const texto = await readFile(path.join(resumoProjeto.pastaSaida, arquivoResumo), "utf8");
|
|
3983
|
-
|
|
3984
|
-
if (emJson) {
|
|
3985
|
-
console.log(JSON.stringify({
|
|
3986
|
-
comando: "resumo",
|
|
3987
|
-
modo,
|
|
3988
|
-
tamanho,
|
|
3989
|
-
geradoEm: resumoProjeto.geradoEm,
|
|
3990
|
-
baseProjeto: resumoProjeto.baseProjeto,
|
|
3991
|
-
pastaSaida: resumoProjeto.pastaSaida,
|
|
3992
|
-
artefatos: resumoProjeto.artefatos,
|
|
3993
|
-
guiaPorCapacidade: resumoProjeto.guiaPorCapacidade,
|
|
3994
|
-
modulos: resumoProjeto.modulos,
|
|
3995
|
-
texto,
|
|
3996
|
-
}, null, 2));
|
|
3997
|
-
return 0;
|
|
3998
|
-
}
|
|
3999
|
-
|
|
4000
|
-
console.log(`Resumo IA-first do projeto gerado em ${resumoProjeto.pastaSaida}`);
|
|
4001
|
-
console.log("");
|
|
4002
|
-
console.log(texto);
|
|
4003
|
-
return 0;
|
|
4004
|
-
}
|
|
4005
|
-
|
|
4006
|
-
async function comandoPromptCurto(
|
|
4007
|
-
entrada: string | undefined,
|
|
4008
|
-
args: string[],
|
|
4009
|
-
emJson: boolean,
|
|
4010
|
-
): Promise<number> {
|
|
4011
|
-
const tamanho = normalizarTamanhoResumo(args);
|
|
4012
|
-
const modo = normalizarModoResumo(obterOpcao(args, "--para"));
|
|
4013
|
-
const alvo = entrada ? path.resolve(process.cwd(), entrada) : process.cwd();
|
|
4014
|
-
|
|
4015
|
-
if (entrada && entrada.toLowerCase().endsWith(".sema")) {
|
|
4016
|
-
const contexto = await carregarContextoModuloIa(alvo);
|
|
4017
|
-
const resumoSemantico = coletarResumoSemanticoModulo(contexto);
|
|
4018
|
-
const capacidade: CapacidadeIa = tamanho === "micro" ? "pequena" : tamanho === "curto" ? "media" : "grande";
|
|
4019
|
-
const prompt = criarPromptCurtoModulo(resumoSemantico, modo, tamanho, capacidade);
|
|
4020
|
-
|
|
4021
|
-
if (emJson) {
|
|
4022
|
-
console.log(JSON.stringify({
|
|
4023
|
-
comando: "prompt-curto",
|
|
4024
|
-
modo,
|
|
4025
|
-
tamanho,
|
|
4026
|
-
capacidade,
|
|
4027
|
-
geradoEm: contexto.geradoEm,
|
|
4028
|
-
arquivo: contexto.arquivo,
|
|
4029
|
-
modulo: contexto.modulo,
|
|
4030
|
-
prompt,
|
|
4031
|
-
}, null, 2));
|
|
4032
|
-
return 0;
|
|
4033
|
-
}
|
|
4034
|
-
|
|
4035
|
-
console.log(prompt);
|
|
4036
|
-
return 0;
|
|
4037
|
-
}
|
|
4038
|
-
|
|
4039
|
-
const resumoProjeto = await gerarResumoProjetoIa(alvo);
|
|
4040
|
-
const arquivoResumo = tamanho === "micro"
|
|
4041
|
-
? "SEMA_BRIEF.micro.txt"
|
|
4042
|
-
: tamanho === "curto"
|
|
4043
|
-
? "SEMA_BRIEF.curto.txt"
|
|
4044
|
-
: "SEMA_BRIEF.md";
|
|
4045
|
-
const contextoProjeto = await readFile(path.join(resumoProjeto.pastaSaida, arquivoResumo), "utf8");
|
|
4046
|
-
const capacidade: CapacidadeIa = tamanho === "micro" ? "pequena" : tamanho === "curto" ? "media" : "grande";
|
|
4047
|
-
const prompt = `Voce esta operando Sema em modo IA-first.
|
|
4048
|
-
|
|
4049
|
-
Isto nao e material feito para humano; e contexto comprimido para IA.
|
|
4050
|
-
|
|
4051
|
-
Capacidade alvo: ${capacidade}
|
|
4052
|
-
Modo da tarefa: ${modo}
|
|
4053
|
-
|
|
4054
|
-
Regras:
|
|
4055
|
-
- comece pelo resumo compacto abaixo
|
|
4056
|
-
- se a tarefa pedir mais contexto, abra \`SEMA_INDEX.json\`
|
|
4057
|
-
- nao tente ler o repo inteiro se o resumo ja disser onde tocar
|
|
4058
|
-
- preserve contrato, risco, lacuna e checks sugeridos
|
|
4059
|
-
|
|
4060
|
-
Contexto do projeto:
|
|
4061
|
-
${contextoProjeto.trim()}
|
|
4062
|
-
`;
|
|
4063
|
-
|
|
4064
|
-
if (emJson) {
|
|
4065
|
-
console.log(JSON.stringify({
|
|
4066
|
-
comando: "prompt-curto",
|
|
4067
|
-
modo,
|
|
4068
|
-
tamanho,
|
|
4069
|
-
capacidade,
|
|
4070
|
-
geradoEm: resumoProjeto.geradoEm,
|
|
4071
|
-
baseProjeto: resumoProjeto.baseProjeto,
|
|
4072
|
-
pastaSaida: resumoProjeto.pastaSaida,
|
|
4073
|
-
prompt,
|
|
4074
|
-
}, null, 2));
|
|
4075
|
-
return 0;
|
|
4076
|
-
}
|
|
4077
|
-
|
|
4078
|
-
console.log(prompt);
|
|
4079
|
-
return 0;
|
|
4080
|
-
}
|
|
4081
|
-
|
|
4082
|
-
async function comandoContextoIa(arquivo: string, pastaSaida: string | undefined, emJson: boolean): Promise<number> {
|
|
4083
|
-
const resultado = await gerarContextoIa(arquivo, pastaSaida);
|
|
4084
|
-
|
|
4085
|
-
if (emJson) {
|
|
4086
|
-
console.log(JSON.stringify(resultado, null, 2));
|
|
4087
|
-
return 0;
|
|
4088
|
-
}
|
|
4089
|
-
|
|
4090
|
-
const resumoGerado = await readFile(path.join(resultado.pastaSaida, "README.md"), "utf8");
|
|
4091
|
-
console.log(`Pacote de contexto gerado em ${resultado.pastaSaida}`);
|
|
4092
|
-
console.log("");
|
|
4093
|
-
console.log(resumoGerado);
|
|
4094
|
-
return 0;
|
|
4095
|
-
}
|
|
4096
|
-
|
|
4097
|
-
async function comandoTestar(
|
|
4098
|
-
arquivo: string,
|
|
4099
|
-
alvo: AlvoGeracao,
|
|
4100
|
-
saida: string,
|
|
4101
|
-
estrutura: EstruturaSaida,
|
|
4102
|
-
framework: FrameworkGeracao,
|
|
4103
|
-
): Promise<number> {
|
|
4104
|
-
const incompatibilidade = validarCompatibilidadeFramework(alvo, framework);
|
|
4105
|
-
if (incompatibilidade) {
|
|
4106
|
-
console.error(incompatibilidade);
|
|
4107
|
-
return 1;
|
|
4108
|
-
}
|
|
4109
|
-
const codigo = await lerArquivoTexto(arquivo);
|
|
4110
|
-
const resultado = compilarCodigo(codigo, arquivo);
|
|
4111
|
-
if (temErros(resultado.diagnosticos)) {
|
|
4112
|
-
console.error(formatarDiagnosticos(resultado.diagnosticos));
|
|
4113
|
-
return 1;
|
|
4114
|
-
}
|
|
4115
|
-
const ir = garantirIr(resultado, arquivo);
|
|
4116
|
-
const arquivos = aplicarEstruturaSaida(gerarArquivosPorAlvo(ir, alvo, framework), ir, estrutura);
|
|
4117
|
-
await escreverArquivos(saida, arquivos);
|
|
4118
|
-
if (framework !== "base") {
|
|
4119
|
-
console.log(`Scaffold ${framework} gerado em ${saida}. A execucao automatica de testes continua focada no framework base da Sema.`);
|
|
4120
|
-
return 0;
|
|
4121
|
-
}
|
|
4122
|
-
return executarTestesGerados(alvo, saida, arquivos).codigoSaida;
|
|
4123
|
-
}
|
|
4124
|
-
|
|
4125
|
-
function imprimirResumoVerificacao(resumos: ResumoModuloVerificacao[]): void {
|
|
4126
|
-
console.log("\nResumo da verificacao:");
|
|
4127
|
-
let totalArquivos = 0;
|
|
4128
|
-
let totalTestes = 0;
|
|
4129
|
-
let totalAlvos = 0;
|
|
4130
|
-
|
|
4131
|
-
for (const resumo of resumos) {
|
|
4132
|
-
console.log(`- Modulo ${resumo.modulo} (${resumo.arquivoFonte})`);
|
|
4133
|
-
for (const alvo of resumo.alvos) {
|
|
4134
|
-
totalArquivos += alvo.arquivosGerados;
|
|
4135
|
-
totalTestes += alvo.quantidadeTestes;
|
|
4136
|
-
totalAlvos += 1;
|
|
4137
|
-
console.log(
|
|
4138
|
-
` alvo=${alvo.alvo} framework=${alvo.framework} estrutura=${alvo.estrutura} status=${alvo.sucesso ? "ok" : "falhou"} arquivos=${alvo.arquivosGerados} testes=${alvo.quantidadeTestes}${alvo.testesExecutados ? "" : " (skip)"} saida=${alvo.pastaSaida}`,
|
|
4139
|
-
);
|
|
4140
|
-
}
|
|
4141
|
-
}
|
|
4142
|
-
|
|
4143
|
-
console.log(`Totais: modulos=${resumos.length} alvos=${totalAlvos} arquivos=${totalArquivos} testes=${totalTestes}`);
|
|
4144
|
-
}
|
|
4145
|
-
|
|
4146
|
-
async function comandoVerificar(
|
|
4147
|
-
entrada: string | undefined,
|
|
4148
|
-
baseSaida: string,
|
|
4149
|
-
cwd = process.cwd(),
|
|
4150
|
-
): Promise<number> {
|
|
4151
|
-
const contextoProjeto = await carregarProjeto(entrada, cwd);
|
|
4152
|
-
const modulos = contextoProjeto.modulosSelecionados;
|
|
4153
|
-
const diagnosticos = modulos.flatMap((item) => item.resultado.diagnosticos);
|
|
4154
|
-
if (temErros(diagnosticos)) {
|
|
4155
|
-
console.error(formatarDiagnosticos(diagnosticos));
|
|
4156
|
-
return 1;
|
|
4157
|
-
}
|
|
4158
|
-
|
|
4159
|
-
const alvos = resolverAlvosVerificacao(contextoProjeto.configCarregada);
|
|
4160
|
-
const configuracoesAlvo = alvos.map((alvo) => ({
|
|
4161
|
-
alvo,
|
|
4162
|
-
...resolverConfiguracaoVerificacaoPorAlvo(alvo, contextoProjeto.configCarregada),
|
|
4163
|
-
}));
|
|
4164
|
-
const incompatibilidade = configuracoesAlvo.find((item) => item.incompatibilidade);
|
|
4165
|
-
if (incompatibilidade?.incompatibilidade) {
|
|
4166
|
-
console.error(incompatibilidade.incompatibilidade);
|
|
4167
|
-
return 1;
|
|
4168
|
-
}
|
|
4169
|
-
|
|
4170
|
-
const resumos: ResumoModuloVerificacao[] = [];
|
|
4171
|
-
for (const modulo of modulos) {
|
|
4172
|
-
const ir = garantirIr(modulo.resultado, modulo.caminho);
|
|
4173
|
-
console.log(`Verificando modulo ${modulo.caminho}`);
|
|
4174
|
-
const resumoModulo: ResumoModuloVerificacao = {
|
|
4175
|
-
modulo: ir.nome,
|
|
4176
|
-
arquivoFonte: modulo.caminho,
|
|
4177
|
-
alvos: [],
|
|
4178
|
-
};
|
|
4179
|
-
for (const configuracaoAlvo of configuracoesAlvo) {
|
|
4180
|
-
const { alvo, framework, estrutura } = configuracaoAlvo;
|
|
4181
|
-
const pastaAlvo = path.join(baseSaida, alvo, nomeSubpastaModulo(modulo.caminho));
|
|
4182
|
-
const arquivos = aplicarEstruturaSaida(gerarArquivosPorAlvo(ir, alvo, framework), ir, estrutura);
|
|
4183
|
-
await escreverArquivos(pastaAlvo, arquivos);
|
|
4184
|
-
const { execucao, testesExecutados } = executarTestesParaVerificacao(alvo, pastaAlvo, arquivos, framework);
|
|
4185
|
-
resumoModulo.alvos.push({
|
|
4186
|
-
alvo,
|
|
4187
|
-
arquivosGerados: arquivos.length,
|
|
4188
|
-
quantidadeTestes: execucao.quantidadeTestes,
|
|
4189
|
-
pastaSaida: pastaAlvo,
|
|
4190
|
-
sucesso: execucao.codigoSaida === 0,
|
|
4191
|
-
framework,
|
|
4192
|
-
estrutura,
|
|
4193
|
-
testesExecutados,
|
|
4194
|
-
});
|
|
4195
|
-
if (execucao.codigoSaida !== 0) {
|
|
4196
|
-
imprimirResumoVerificacao([...resumos, resumoModulo]);
|
|
4197
|
-
console.error(`Falha na verificacao do modulo ${modulo.caminho} para o alvo ${alvo}.`);
|
|
4198
|
-
return execucao.codigoSaida;
|
|
4199
|
-
}
|
|
4200
|
-
}
|
|
4201
|
-
resumos.push(resumoModulo);
|
|
4202
|
-
}
|
|
4203
|
-
|
|
4204
|
-
imprimirResumoVerificacao(resumos);
|
|
4205
|
-
console.log("Verificacao completa concluida com sucesso.");
|
|
4206
|
-
return 0;
|
|
4207
|
-
}
|
|
4208
|
-
|
|
4209
|
-
async function comandoVerificarJson(
|
|
4210
|
-
entrada: string | undefined,
|
|
4211
|
-
baseSaida: string,
|
|
4212
|
-
cwd = process.cwd(),
|
|
4213
|
-
): Promise<number> {
|
|
4214
|
-
const contextoProjeto = await carregarProjeto(entrada, cwd);
|
|
4215
|
-
const modulos = contextoProjeto.modulosSelecionados;
|
|
4216
|
-
const diagnosticos = modulos.flatMap((item) => item.resultado.diagnosticos);
|
|
4217
|
-
if (temErros(diagnosticos)) {
|
|
4218
|
-
console.log(JSON.stringify({
|
|
4219
|
-
comando: "verificar",
|
|
4220
|
-
sucesso: false,
|
|
4221
|
-
diagnosticos,
|
|
4222
|
-
modulos: [],
|
|
4223
|
-
totais: { modulos: 0, alvos: 0, arquivos: 0, testes: 0 },
|
|
4224
|
-
}, null, 2));
|
|
4225
|
-
return 1;
|
|
4226
|
-
}
|
|
4227
|
-
|
|
4228
|
-
const alvos = resolverAlvosVerificacao(contextoProjeto.configCarregada);
|
|
4229
|
-
const configuracoesAlvo = alvos.map((alvo) => ({
|
|
4230
|
-
alvo,
|
|
4231
|
-
...resolverConfiguracaoVerificacaoPorAlvo(alvo, contextoProjeto.configCarregada),
|
|
4232
|
-
}));
|
|
4233
|
-
const incompatibilidade = configuracoesAlvo.find((item) => item.incompatibilidade);
|
|
4234
|
-
if (incompatibilidade?.incompatibilidade) {
|
|
4235
|
-
console.log(JSON.stringify({
|
|
4236
|
-
comando: "verificar",
|
|
4237
|
-
sucesso: false,
|
|
4238
|
-
erro: incompatibilidade.incompatibilidade,
|
|
4239
|
-
modulos: [],
|
|
4240
|
-
totais: { modulos: 0, alvos: 0, arquivos: 0, testes: 0 },
|
|
4241
|
-
}, null, 2));
|
|
4242
|
-
return 1;
|
|
4243
|
-
}
|
|
4244
|
-
|
|
4245
|
-
const resumos: Array<ResumoModuloVerificacao & { saidaTestes?: Array<{ alvo: string; stdout: string; stderr: string }> }> = [];
|
|
4246
|
-
let codigoSaida = 0;
|
|
4247
|
-
|
|
4248
|
-
for (const modulo of modulos) {
|
|
4249
|
-
const ir = garantirIr(modulo.resultado, modulo.caminho);
|
|
4250
|
-
const resumoModulo: ResumoModuloVerificacao & { saidaTestes: Array<{ alvo: string; stdout: string; stderr: string }> } = {
|
|
4251
|
-
modulo: ir.nome,
|
|
4252
|
-
arquivoFonte: modulo.caminho,
|
|
4253
|
-
alvos: [],
|
|
4254
|
-
saidaTestes: [],
|
|
4255
|
-
};
|
|
4256
|
-
|
|
4257
|
-
for (const configuracaoAlvo of configuracoesAlvo) {
|
|
4258
|
-
const { alvo, framework, estrutura } = configuracaoAlvo;
|
|
4259
|
-
const pastaAlvo = path.join(baseSaida, alvo, nomeSubpastaModulo(modulo.caminho));
|
|
4260
|
-
const arquivos = aplicarEstruturaSaida(gerarArquivosPorAlvo(ir, alvo, framework), ir, estrutura);
|
|
4261
|
-
await escreverArquivos(pastaAlvo, arquivos);
|
|
4262
|
-
const { execucao, testesExecutados } = executarTestesParaVerificacao(alvo, pastaAlvo, arquivos, framework, true);
|
|
4263
|
-
resumoModulo.alvos.push({
|
|
4264
|
-
alvo,
|
|
4265
|
-
arquivosGerados: arquivos.length,
|
|
4266
|
-
quantidadeTestes: execucao.quantidadeTestes,
|
|
4267
|
-
pastaSaida: pastaAlvo,
|
|
4268
|
-
sucesso: execucao.codigoSaida === 0,
|
|
4269
|
-
framework,
|
|
4270
|
-
estrutura,
|
|
4271
|
-
testesExecutados,
|
|
4272
|
-
});
|
|
4273
|
-
resumoModulo.saidaTestes.push({ alvo, stdout: execucao.saidaPadrao, stderr: execucao.saidaErro });
|
|
4274
|
-
if (execucao.codigoSaida !== 0) {
|
|
4275
|
-
codigoSaida = execucao.codigoSaida;
|
|
4276
|
-
}
|
|
4277
|
-
}
|
|
4278
|
-
|
|
4279
|
-
resumos.push(resumoModulo);
|
|
4280
|
-
}
|
|
4281
|
-
|
|
4282
|
-
const totais = {
|
|
4283
|
-
modulos: resumos.length,
|
|
4284
|
-
alvos: resumos.reduce((total, resumo) => total + resumo.alvos.length, 0),
|
|
4285
|
-
arquivos: resumos.reduce((total, resumo) => total + resumo.alvos.reduce((subTotal, alvo) => subTotal + alvo.arquivosGerados, 0), 0),
|
|
4286
|
-
testes: resumos.reduce((total, resumo) => total + resumo.alvos.reduce((subTotal, alvo) => subTotal + alvo.quantidadeTestes, 0), 0),
|
|
4287
|
-
};
|
|
4288
|
-
|
|
4289
|
-
console.log(JSON.stringify({
|
|
4290
|
-
comando: "verificar",
|
|
4291
|
-
sucesso: codigoSaida === 0,
|
|
4292
|
-
modulos: resumos,
|
|
4293
|
-
totais,
|
|
4294
|
-
}, null, 2));
|
|
4295
|
-
|
|
4296
|
-
return codigoSaida;
|
|
4297
|
-
}
|
|
4298
|
-
|
|
4299
|
-
async function principal(): Promise<void> {
|
|
4300
|
-
const { comando, resto } = obterArgumentos();
|
|
4301
|
-
const comandoCru = process.argv[2];
|
|
4302
|
-
if (comandoCru === "--versao" || comandoCru === "--version" || comandoCru === "-v") {
|
|
4303
|
-
console.log(VERSAO_CLI);
|
|
4304
|
-
process.exit(0);
|
|
4305
|
-
}
|
|
4306
|
-
if (!comando || comandoCru === "--help" || comandoCru === "-h") {
|
|
4307
|
-
console.log(ajuda());
|
|
4308
|
-
process.exit(0);
|
|
4309
|
-
}
|
|
4310
|
-
|
|
4311
|
-
const cwd = process.cwd();
|
|
4312
|
-
const posicionais = obterPosicionais(resto);
|
|
4313
|
-
let codigoSaida = 0;
|
|
4314
|
-
switch (comando) {
|
|
4315
|
-
case "iniciar":
|
|
4316
|
-
codigoSaida = await comandoIniciar(cwd, normalizarTemplateIniciar(obterOpcao(resto, "--template")));
|
|
4317
|
-
break;
|
|
4318
|
-
case "validar":
|
|
4319
|
-
codigoSaida = possuiFlag(resto, "--json")
|
|
4320
|
-
? await comandoValidarJson(posicionais[0])
|
|
4321
|
-
: await comandoValidar(posicionais[0]);
|
|
4322
|
-
break;
|
|
4323
|
-
case "ast":
|
|
4324
|
-
codigoSaida = possuiFlag(resto, "--json")
|
|
4325
|
-
? await comandoAstJson(resto[0] ?? "")
|
|
4326
|
-
: await comandoAst(resto[0] ?? "");
|
|
4327
|
-
break;
|
|
4328
|
-
case "ir":
|
|
4329
|
-
codigoSaida = possuiFlag(resto, "--json")
|
|
4330
|
-
? await comandoIrJson(resto[0] ?? "")
|
|
4331
|
-
: await comandoIr(resto[0] ?? "");
|
|
4332
|
-
break;
|
|
4333
|
-
case "compilar":
|
|
4334
|
-
{
|
|
4335
|
-
const config = await carregarConfiguracaoProjeto(posicionais[0] ? path.resolve(cwd, posicionais[0]) : cwd);
|
|
4336
|
-
const alvo = resolverAlvoPadrao(obterOpcao(resto, "--alvo"), config);
|
|
4337
|
-
const framework = resolverFrameworkPadrao(obterOpcao(resto, "--framework"), config);
|
|
4338
|
-
const estrutura = resolverEstruturaSaidaPadrao(obterOpcao(resto, "--estrutura"), framework, config);
|
|
4339
|
-
const saida = resolverSaidaPadrao(obterOpcao(resto, "--saida"), alvo, config);
|
|
4340
|
-
codigoSaida = await comandoCompilar(posicionais[0], alvo, saida, estrutura, framework, cwd);
|
|
4341
|
-
}
|
|
4342
|
-
break;
|
|
4343
|
-
case "gerar":
|
|
4344
|
-
{
|
|
4345
|
-
const config = await carregarConfiguracaoProjeto(posicionais[1] ? path.resolve(cwd, posicionais[1]) : cwd);
|
|
4346
|
-
const alvo = resolverAlvoPadrao(posicionais[0] ?? obterOpcao(resto, "--alvo"), config);
|
|
4347
|
-
const framework = resolverFrameworkPadrao(obterOpcao(resto, "--framework"), config);
|
|
4348
|
-
const estrutura = resolverEstruturaSaidaPadrao(obterOpcao(resto, "--estrutura"), framework, config);
|
|
4349
|
-
const saida = resolverSaidaPadrao(obterOpcao(resto, "--saida"), alvo, config);
|
|
4350
|
-
codigoSaida = await comandoCompilar(posicionais[1], alvo, saida, estrutura, framework, cwd);
|
|
4351
|
-
}
|
|
4352
|
-
break;
|
|
4353
|
-
case "diagnosticos":
|
|
4354
|
-
codigoSaida = await comandoDiagnosticos(posicionais[0] ?? "", resto.includes("--json"));
|
|
4355
|
-
break;
|
|
4356
|
-
case "testar":
|
|
4357
|
-
{
|
|
4358
|
-
const config = await carregarConfiguracaoProjeto(posicionais[0] ? path.resolve(cwd, posicionais[0]) : cwd);
|
|
4359
|
-
const alvo = resolverAlvoPadrao(obterOpcao(resto, "--alvo"), config);
|
|
4360
|
-
const framework = resolverFrameworkPadrao(obterOpcao(resto, "--framework"), config);
|
|
4361
|
-
const estrutura = resolverEstruturaSaidaPadrao(obterOpcao(resto, "--estrutura"), framework, config);
|
|
4362
|
-
const saida = resolverSaidaPadrao(obterOpcao(resto, "--saida", "./.tmp/sema-testes"), alvo, config);
|
|
4363
|
-
codigoSaida = await comandoTestar(
|
|
4364
|
-
path.resolve(cwd, posicionais[0] ?? ""),
|
|
4365
|
-
alvo,
|
|
4366
|
-
saida,
|
|
4367
|
-
estrutura,
|
|
4368
|
-
framework,
|
|
4369
|
-
);
|
|
4370
|
-
}
|
|
4371
|
-
break;
|
|
4372
|
-
case "verificar":
|
|
4373
|
-
codigoSaida = possuiFlag(resto, "--json")
|
|
4374
|
-
? await comandoVerificarJson(
|
|
4375
|
-
posicionais[0],
|
|
4376
|
-
resolverSaidaPadrao(obterOpcao(resto, "--saida", "./.tmp/sema-verificar"), "typescript", await carregarConfiguracaoProjeto(posicionais[0] ? path.resolve(cwd, posicionais[0]) : cwd)),
|
|
4377
|
-
cwd,
|
|
4378
|
-
)
|
|
4379
|
-
: await comandoVerificar(
|
|
4380
|
-
posicionais[0],
|
|
4381
|
-
resolverSaidaPadrao(obterOpcao(resto, "--saida", "./.tmp/sema-verificar"), "typescript", await carregarConfiguracaoProjeto(posicionais[0] ? path.resolve(cwd, posicionais[0]) : cwd)),
|
|
4382
|
-
cwd,
|
|
4383
|
-
);
|
|
4384
|
-
break;
|
|
4385
|
-
case "inspecionar":
|
|
4386
|
-
codigoSaida = await comandoInspecionar(posicionais[0], possuiFlag(resto, "--json"), cwd);
|
|
4387
|
-
break;
|
|
4388
|
-
case "drift":
|
|
4389
|
-
codigoSaida = await comandoDrift(posicionais[0], possuiFlag(resto, "--json"), cwd);
|
|
4390
|
-
break;
|
|
4391
|
-
case "importar":
|
|
4392
|
-
{
|
|
4393
|
-
const fonte = normalizarFonteImportacao(posicionais[0]);
|
|
4394
|
-
if (!fonte || !posicionais[1]) {
|
|
4395
|
-
console.error("Uso: sema importar <nestjs|fastapi|flask|nextjs|nextjs-consumer|react-vite-consumer|angular-consumer|flutter-consumer|firebase|dotnet|java|go|rust|cpp|typescript|python|dart> <diretorio> [--saida <diretorio>] [--namespace <base>] [--json]");
|
|
4396
|
-
codigoSaida = 1;
|
|
4397
|
-
break;
|
|
4398
|
-
}
|
|
4399
|
-
codigoSaida = await comandoImportar(
|
|
4400
|
-
fonte,
|
|
4401
|
-
path.resolve(cwd, posicionais[1]),
|
|
4402
|
-
path.resolve(cwd, obterOpcao(resto, "--saida", "./sema/importado")!),
|
|
4403
|
-
obterOpcao(resto, "--namespace"),
|
|
4404
|
-
possuiFlag(resto, "--json"),
|
|
4405
|
-
);
|
|
4406
|
-
}
|
|
4407
|
-
break;
|
|
4408
|
-
case "formatar":
|
|
4409
|
-
codigoSaida = await comandoFormatar(
|
|
4410
|
-
posicionais[0],
|
|
4411
|
-
possuiFlag(resto, "--check"),
|
|
4412
|
-
possuiFlag(resto, "--json"),
|
|
4413
|
-
);
|
|
4414
|
-
break;
|
|
4415
|
-
case "doctor":
|
|
4416
|
-
codigoSaida = await comandoDoctor();
|
|
4417
|
-
break;
|
|
4418
|
-
case "ajuda-ia":
|
|
4419
|
-
codigoSaida = await comandoAjudaIa();
|
|
4420
|
-
break;
|
|
4421
|
-
case "starter-ia":
|
|
4422
|
-
codigoSaida = await comandoStarterIa();
|
|
4423
|
-
break;
|
|
4424
|
-
case "sync-ai-entrypoints":
|
|
4425
|
-
codigoSaida = await comandoSyncAiEntrypoints(possuiFlag(resto, "--json"));
|
|
4426
|
-
break;
|
|
4427
|
-
case "resumo":
|
|
4428
|
-
codigoSaida = await comandoResumo(
|
|
4429
|
-
posicionais[0],
|
|
4430
|
-
resto,
|
|
4431
|
-
possuiFlag(resto, "--json"),
|
|
4432
|
-
);
|
|
4433
|
-
break;
|
|
4434
|
-
case "prompt-curto":
|
|
4435
|
-
codigoSaida = await comandoPromptCurto(
|
|
4436
|
-
posicionais[0],
|
|
4437
|
-
resto,
|
|
4438
|
-
possuiFlag(resto, "--json"),
|
|
4439
|
-
);
|
|
4440
|
-
break;
|
|
4441
|
-
case "prompt-ia":
|
|
4442
|
-
codigoSaida = await comandoPromptIa();
|
|
4443
|
-
break;
|
|
4444
|
-
case "prompt-ia-ui":
|
|
4445
|
-
codigoSaida = await comandoPromptIaUi();
|
|
4446
|
-
break;
|
|
4447
|
-
case "prompt-ia-react":
|
|
4448
|
-
codigoSaida = await comandoPromptIaReact();
|
|
4449
|
-
break;
|
|
4450
|
-
case "prompt-ia-sema-primeiro":
|
|
4451
|
-
codigoSaida = await comandoPromptIaSemaPrimeiro();
|
|
4452
|
-
break;
|
|
4453
|
-
case "exemplos-prompt-ia":
|
|
4454
|
-
codigoSaida = await comandoExemplosPromptIa();
|
|
4455
|
-
break;
|
|
4456
|
-
case "contexto-ia":
|
|
4457
|
-
codigoSaida = await comandoContextoIa(
|
|
4458
|
-
posicionais[0] ?? "",
|
|
4459
|
-
obterOpcao(resto, "--saida"),
|
|
4460
|
-
possuiFlag(resto, "--json"),
|
|
4461
|
-
);
|
|
4462
|
-
break;
|
|
4463
|
-
default:
|
|
4464
|
-
console.log(ajuda());
|
|
4465
|
-
codigoSaida = 1;
|
|
4466
|
-
break;
|
|
4467
|
-
}
|
|
4468
|
-
|
|
4469
|
-
process.exit(codigoSaida);
|
|
4470
|
-
}
|
|
4471
|
-
|
|
4472
|
-
principal().catch((erro) => {
|
|
4473
|
-
console.error("Falha ao executar a CLI da Sema.");
|
|
4474
|
-
console.error(erro instanceof Error ? erro.stack ?? erro.message : erro);
|
|
4475
|
-
process.exit(1);
|
|
4476
|
-
});
|