@semacode/cli 1.4.0 → 1.5.1
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/AGENTS.md +2 -2
- package/README.md +1 -1
- package/dist/drift.d.ts +99 -3
- package/dist/drift.js +1672 -548
- package/dist/drift.js.map +1 -1
- package/dist/index.js +326 -26
- package/dist/index.js.map +1 -1
- package/docs/cli.md +1 -1
- package/docs/instalacao-e-primeiro-uso.md +7 -6
- package/docs/integracao-com-ia.md +6 -0
- package/docs/persistencia-vendor-first.md +1 -1
- package/node_modules/@sema/gerador-css/package.json +1 -1
- package/node_modules/@sema/gerador-dart/package.json +1 -1
- package/node_modules/@sema/gerador-html/package.json +1 -1
- package/node_modules/@sema/gerador-javascript/package.json +1 -1
- package/node_modules/@sema/gerador-lua/package.json +1 -1
- package/node_modules/@sema/gerador-python/package.json +1 -1
- package/node_modules/@sema/gerador-typescript/package.json +1 -1
- package/node_modules/@sema/nucleo/package.json +1 -1
- package/node_modules/@sema/padroes/package.json +1 -1
- package/package.json +11 -10
package/dist/index.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { mkdir, readFile, stat, writeFile } from "node:fs/promises";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { spawnSync } from "node:child_process";
|
|
5
|
+
import { createRequire } from "node:module";
|
|
5
6
|
import { fileURLToPath } from "node:url";
|
|
6
7
|
import pacoteCli from "../package.json" with { type: "json" };
|
|
7
8
|
import { compilarCodigo, formatarCodigo, formatarDiagnosticos, lerArquivoTexto, temErros, } from "@sema/nucleo";
|
|
@@ -15,7 +16,7 @@ import { gerarHtml } from "@sema/gerador-html";
|
|
|
15
16
|
import { gerarCss } from "@sema/gerador-css";
|
|
16
17
|
import { carregarConfiguracaoProjeto, carregarProjeto, resolverAlvoPadrao, resolverAlvosVerificacao, resolverEstruturaSaidaPadrao, resolverFrameworkPadrao, resolverSaidaPadrao, } from "./projeto.js";
|
|
17
18
|
import { importarProjetoLegado, resumoImportacao } from "./importador.js";
|
|
18
|
-
import { analisarDriftLegado } from "./drift.js";
|
|
19
|
+
import { analisarDriftLegado, assistirRenomeacaoSemantica, gerarMapaImpactoSemantico, } from "./drift.js";
|
|
19
20
|
const STARTER_IA = `Voce esta trabalhando com Sema, um Protocolo de Governanca de Intencao para IA sobre software vivo em backend e front consumer.
|
|
20
21
|
|
|
21
22
|
Importante:
|
|
@@ -52,8 +53,10 @@ Regras:
|
|
|
52
53
|
Comandos essenciais:
|
|
53
54
|
- resumo compacto por capacidade: \`sema resumo <arquivo-ou-pasta> [--micro|--curto|--medio] [--para <resumo|onboarding|review|mudanca|bug|arquitetura>]\`
|
|
54
55
|
- prompt curto para IA pequena: \`sema prompt-curto <arquivo-ou-pasta> [--micro|--curto|--medio] [--para <resumo|onboarding|review|mudanca|bug|arquitetura>]\`
|
|
55
|
-
- descoberta do projeto: \`sema inspecionar [arquivo-ou-pasta] --json\`
|
|
56
|
-
- auditoria do contrato vivo: \`sema drift <arquivo-ou-pasta> [--json]\`
|
|
56
|
+
- descoberta do projeto: \`sema inspecionar [arquivo-ou-pasta] --json\`
|
|
57
|
+
- auditoria do contrato vivo: \`sema drift <arquivo-ou-pasta> [--escopo <arquivo|modulo|projeto>] [--json]\`
|
|
58
|
+
- mapa de impacto: \`sema impacto <arquivo-ou-pasta> --alvo <token> [--mudanca <descricao>] [--json]\`
|
|
59
|
+
- renomeacao assistida: \`sema renomear-semantico <arquivo-ou-pasta> --de <nome-atual> --para <nome-novo> [--json]\`
|
|
57
60
|
- contexto completo do modulo: \`sema contexto-ia <arquivo.sema>\`
|
|
58
61
|
- estrutura sintatica: \`sema ast <arquivo.sema> --json\`
|
|
59
62
|
- estrutura semantica: \`sema ir <arquivo.sema> --json\`
|
|
@@ -319,6 +322,7 @@ Comandos uteis da CLI para esse fluxo:
|
|
|
319
322
|
`;
|
|
320
323
|
const DIRETORIO_CLI_ATUAL = path.dirname(fileURLToPath(import.meta.url));
|
|
321
324
|
const VERSAO_CLI = pacoteCli.version;
|
|
325
|
+
const requireRuntimeCli = createRequire(import.meta.url);
|
|
322
326
|
const ARQUIVOS_CANONICOS_IA_RAIZ = [
|
|
323
327
|
"llms.txt",
|
|
324
328
|
"SEMA_BRIEF.md",
|
|
@@ -336,6 +340,16 @@ const DOCUMENTOS_SUPORTE_IA = [
|
|
|
336
340
|
"docs/sintaxe.md",
|
|
337
341
|
"docs/cli.md",
|
|
338
342
|
];
|
|
343
|
+
function resolverImportadorNodeOpcional(especificador) {
|
|
344
|
+
try {
|
|
345
|
+
return requireRuntimeCli.resolve(especificador);
|
|
346
|
+
}
|
|
347
|
+
catch {
|
|
348
|
+
return undefined;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
const TSX_IMPORTADOR_CLI = resolverImportadorNodeOpcional("tsx");
|
|
352
|
+
const TSX_EXECUTOR_CLI = resolverImportadorNodeOpcional("tsx/cli");
|
|
339
353
|
function obterArgumentos() {
|
|
340
354
|
const [, , comando, ...resto] = process.argv;
|
|
341
355
|
return { comando: comando, resto };
|
|
@@ -373,14 +387,15 @@ function ajuda() {
|
|
|
373
387
|
"[2] Editar projeto que ja usa Sema",
|
|
374
388
|
"sema inspecionar . --json",
|
|
375
389
|
"sema resumo <arquivo-ou-pasta> --micro --para mudanca",
|
|
376
|
-
"sema drift <arquivo-ou-pasta> --json",
|
|
390
|
+
"sema drift <arquivo-ou-pasta> --escopo modulo --json",
|
|
391
|
+
"sema impacto <arquivo-ou-pasta> --alvo <token> --mudanca <descricao> --json",
|
|
377
392
|
"sema contexto-ia <arquivo.sema> --saida ./.tmp/contexto --json",
|
|
378
393
|
"",
|
|
379
394
|
"[3] Adotar Sema em projeto que ainda nao usa",
|
|
380
395
|
"sema importar <fonte> <diretorio> --saida <diretorio> --json",
|
|
381
396
|
"sema formatar <arquivo-ou-pasta>",
|
|
382
397
|
"sema validar <arquivo-ou-pasta> --json",
|
|
383
|
-
"sema drift <arquivo-ou-pasta> --json",
|
|
398
|
+
"sema drift <arquivo-ou-pasta> --escopo modulo --json",
|
|
384
399
|
]),
|
|
385
400
|
"",
|
|
386
401
|
renderizarSecaoAscii("IA por capacidade", [
|
|
@@ -391,7 +406,9 @@ function ajuda() {
|
|
|
391
406
|
"",
|
|
392
407
|
renderizarSecaoAscii("Comandos principais", [
|
|
393
408
|
"descoberta: sema inspecionar [arquivo-ou-pasta] [--json]",
|
|
394
|
-
"auditoria: sema drift <arquivo-ou-pasta> [--json]",
|
|
409
|
+
"auditoria: sema drift <arquivo-ou-pasta> [--escopo <arquivo|modulo|projeto>] [--incluir-worktrees] [--incluir-consumidores-laterais] [--json]",
|
|
410
|
+
"impacto: sema impacto <arquivo-ou-pasta> --alvo <token> [--mudanca <descricao>] [--escopo <arquivo|modulo|projeto>] [--json]",
|
|
411
|
+
"renomeacao: sema renomear-semantico <arquivo-ou-pasta> --de <nome-atual> --para <nome-novo> [--escopo <arquivo|modulo|projeto>] [--json]",
|
|
395
412
|
"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]",
|
|
396
413
|
"validacao: sema validar <arquivo-ou-pasta> [--json]",
|
|
397
414
|
"diagnostico: sema diagnosticos <arquivo.sema> [--json]",
|
|
@@ -447,10 +464,13 @@ function possuiFlag(args, nome) {
|
|
|
447
464
|
const OPCOES_COM_VALOR = new Set([
|
|
448
465
|
"--template",
|
|
449
466
|
"--alvo", "-a",
|
|
467
|
+
"--escopo",
|
|
450
468
|
"--saida", "-s",
|
|
451
469
|
"--estrutura",
|
|
452
470
|
"--framework",
|
|
453
471
|
"--namespace",
|
|
472
|
+
"--mudanca",
|
|
473
|
+
"--de",
|
|
454
474
|
"--para",
|
|
455
475
|
]);
|
|
456
476
|
const ALIAS_OPCOES = {
|
|
@@ -471,6 +491,14 @@ function obterPosicionais(args) {
|
|
|
471
491
|
}
|
|
472
492
|
return posicionais;
|
|
473
493
|
}
|
|
494
|
+
function resolverOpcoesDriftCli(args) {
|
|
495
|
+
const escopo = obterOpcao(args, "--escopo");
|
|
496
|
+
return {
|
|
497
|
+
escopo: escopo === "arquivo" || escopo === "modulo" || escopo === "projeto" ? escopo : undefined,
|
|
498
|
+
ignorarWorktrees: !possuiFlag(args, "--incluir-worktrees"),
|
|
499
|
+
ignorarConsumidoresLaterais: !possuiFlag(args, "--incluir-consumidores-laterais"),
|
|
500
|
+
};
|
|
501
|
+
}
|
|
474
502
|
function normalizarTamanhoResumo(args) {
|
|
475
503
|
const escolhas = [
|
|
476
504
|
possuiFlag(args, "--micro") ? "micro" : null,
|
|
@@ -497,25 +525,172 @@ function comandoDisponivel(comando, argumentos = ["--version"]) {
|
|
|
497
525
|
const execucao = spawnSync(comando, argumentos, { stdio: "ignore", shell: process.platform === "win32" });
|
|
498
526
|
return (execucao.status ?? 1) === 0;
|
|
499
527
|
}
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
{
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
{
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
528
|
+
function resolverExecucaoPython() {
|
|
529
|
+
if (comandoDisponivel("python")) {
|
|
530
|
+
return { comando: "python", argumentosBase: [], rotulo: "python" };
|
|
531
|
+
}
|
|
532
|
+
if (comandoDisponivel("py")) {
|
|
533
|
+
return { comando: "py", argumentosBase: [], rotulo: "py" };
|
|
534
|
+
}
|
|
535
|
+
return undefined;
|
|
536
|
+
}
|
|
537
|
+
function resolverExecucaoPytest() {
|
|
538
|
+
if (comandoDisponivel("pytest")) {
|
|
539
|
+
return { comando: "pytest", argumentosBase: [], rotulo: "pytest" };
|
|
540
|
+
}
|
|
541
|
+
const python = resolverExecucaoPython();
|
|
542
|
+
if (python && comandoDisponivel(python.comando, [...python.argumentosBase, "-m", "pytest", "--version"])) {
|
|
543
|
+
return {
|
|
544
|
+
comando: python.comando,
|
|
545
|
+
argumentosBase: [...python.argumentosBase, "-m", "pytest"],
|
|
546
|
+
rotulo: `${python.rotulo} -m pytest`,
|
|
547
|
+
};
|
|
548
|
+
}
|
|
549
|
+
return undefined;
|
|
550
|
+
}
|
|
551
|
+
function criarItemDependencia(nome, ok, detalhe, obrigatoria = true) {
|
|
552
|
+
return { nome, ok, detalhe, obrigatoria };
|
|
553
|
+
}
|
|
554
|
+
function coletarDependenciasDoctor() {
|
|
555
|
+
const python = resolverExecucaoPython();
|
|
556
|
+
const pytest = resolverExecucaoPytest();
|
|
557
|
+
return [
|
|
558
|
+
{
|
|
559
|
+
comando: "base",
|
|
560
|
+
itens: [
|
|
561
|
+
criarItemDependencia("node", comandoDisponivel("node"), "runtime principal da CLI"),
|
|
562
|
+
criarItemDependencia("npm", comandoDisponivel("npm"), "instalacao, pack e publish"),
|
|
563
|
+
criarItemDependencia("python", Boolean(python), python?.rotulo ? `resolvido via ${python.rotulo}` : "python ou py"),
|
|
564
|
+
criarItemDependencia("dotnet", comandoDisponivel("dotnet"), "ecosistema ASP.NET", false),
|
|
565
|
+
criarItemDependencia("go", comandoDisponivel("go"), "ecosistema Go", false),
|
|
566
|
+
criarItemDependencia("cargo", comandoDisponivel("cargo"), "ecosistema Rust", false),
|
|
567
|
+
criarItemDependencia("java", comandoDisponivel("java"), "ecosistema Java/Spring", false),
|
|
568
|
+
criarItemDependencia("code", comandoDisponivel("code", ["--version"]), "VS Code / extensao", false),
|
|
569
|
+
],
|
|
570
|
+
},
|
|
571
|
+
{
|
|
572
|
+
comando: "verificar/typescript",
|
|
573
|
+
itens: [
|
|
574
|
+
criarItemDependencia("node", comandoDisponivel("node"), "execucao do runner TypeScript"),
|
|
575
|
+
criarItemDependencia("tsx", Boolean(TSX_EXECUTOR_CLI ?? TSX_IMPORTADOR_CLI), TSX_EXECUTOR_CLI
|
|
576
|
+
? `runner resolvido em ${TSX_EXECUTOR_CLI}`
|
|
577
|
+
: TSX_IMPORTADOR_CLI
|
|
578
|
+
? `importador resolvido em ${TSX_IMPORTADOR_CLI}`
|
|
579
|
+
: "tsx nao foi encontrado junto da CLI"),
|
|
580
|
+
],
|
|
581
|
+
},
|
|
582
|
+
{
|
|
583
|
+
comando: "verificar/javascript",
|
|
584
|
+
itens: [
|
|
585
|
+
criarItemDependencia("node", comandoDisponivel("node"), "node --test"),
|
|
586
|
+
],
|
|
587
|
+
},
|
|
588
|
+
{
|
|
589
|
+
comando: "verificar/python",
|
|
590
|
+
itens: [
|
|
591
|
+
criarItemDependencia("python", Boolean(python), python?.rotulo ? `resolvido via ${python.rotulo}` : "python ou py"),
|
|
592
|
+
criarItemDependencia("pytest", Boolean(pytest), pytest?.rotulo ? `runner resolvido via ${pytest.rotulo}` : "instale pytest ou exponha python -m pytest"),
|
|
593
|
+
],
|
|
594
|
+
},
|
|
595
|
+
{
|
|
596
|
+
comando: "verificar/lua",
|
|
597
|
+
itens: [
|
|
598
|
+
criarItemDependencia("lua", comandoDisponivel("lua", ["-v"]), "runner de testes Lua"),
|
|
599
|
+
],
|
|
600
|
+
},
|
|
510
601
|
];
|
|
602
|
+
}
|
|
603
|
+
function avaliarPreflightVerificacao(configuracoesAlvo) {
|
|
604
|
+
const dependencias = [];
|
|
605
|
+
const faltando = [];
|
|
606
|
+
const registrar = (comando, itens) => {
|
|
607
|
+
dependencias.push({ comando, itens });
|
|
608
|
+
for (const item of itens) {
|
|
609
|
+
if (item.obrigatoria && !item.ok) {
|
|
610
|
+
faltando.push({
|
|
611
|
+
comando,
|
|
612
|
+
nome: item.nome,
|
|
613
|
+
detalhe: item.detalhe,
|
|
614
|
+
});
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
};
|
|
618
|
+
registrar("base", [
|
|
619
|
+
criarItemDependencia("node", comandoDisponivel("node"), "runtime principal da CLI"),
|
|
620
|
+
criarItemDependencia("npm", comandoDisponivel("npm"), "instalacao e empacotamento"),
|
|
621
|
+
]);
|
|
622
|
+
for (const configuracao of configuracoesAlvo) {
|
|
623
|
+
if (configuracao.framework !== "base") {
|
|
624
|
+
continue;
|
|
625
|
+
}
|
|
626
|
+
if (configuracao.alvo === "typescript") {
|
|
627
|
+
registrar("verificar/typescript", [
|
|
628
|
+
criarItemDependencia("node", comandoDisponivel("node"), "execucao do runner TypeScript"),
|
|
629
|
+
criarItemDependencia("tsx", Boolean(TSX_EXECUTOR_CLI ?? TSX_IMPORTADOR_CLI), TSX_EXECUTOR_CLI
|
|
630
|
+
? `runner resolvido em ${TSX_EXECUTOR_CLI}`
|
|
631
|
+
: TSX_IMPORTADOR_CLI
|
|
632
|
+
? `importador resolvido em ${TSX_IMPORTADOR_CLI}`
|
|
633
|
+
: "tsx nao foi encontrado junto da CLI"),
|
|
634
|
+
]);
|
|
635
|
+
continue;
|
|
636
|
+
}
|
|
637
|
+
if (configuracao.alvo === "javascript") {
|
|
638
|
+
registrar("verificar/javascript", [
|
|
639
|
+
criarItemDependencia("node", comandoDisponivel("node"), "node --test"),
|
|
640
|
+
]);
|
|
641
|
+
continue;
|
|
642
|
+
}
|
|
643
|
+
if (configuracao.alvo === "python") {
|
|
644
|
+
const python = resolverExecucaoPython();
|
|
645
|
+
const pytest = resolverExecucaoPytest();
|
|
646
|
+
registrar("verificar/python", [
|
|
647
|
+
criarItemDependencia("python", Boolean(python), python?.rotulo ? `resolvido via ${python.rotulo}` : "python ou py"),
|
|
648
|
+
criarItemDependencia("pytest", Boolean(pytest), pytest?.rotulo ? `runner resolvido via ${pytest.rotulo}` : "instale pytest ou exponha python -m pytest"),
|
|
649
|
+
]);
|
|
650
|
+
continue;
|
|
651
|
+
}
|
|
652
|
+
if (configuracao.alvo === "lua") {
|
|
653
|
+
registrar("verificar/lua", [
|
|
654
|
+
criarItemDependencia("lua", comandoDisponivel("lua", ["-v"]), "runner de testes Lua"),
|
|
655
|
+
]);
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
return {
|
|
659
|
+
ok: faltando.length === 0,
|
|
660
|
+
dependencias,
|
|
661
|
+
faltando,
|
|
662
|
+
};
|
|
663
|
+
}
|
|
664
|
+
function imprimirDependenciasDoctor(dependencias) {
|
|
665
|
+
for (const dependencia of dependencias) {
|
|
666
|
+
console.log(`\n[${dependencia.comando}]`);
|
|
667
|
+
for (const item of dependencia.itens) {
|
|
668
|
+
const sufixo = item.detalhe ? ` (${item.detalhe})` : "";
|
|
669
|
+
console.log(`- ${item.nome}: ${item.ok ? "ok" : item.obrigatoria ? "faltando" : "ausente"}${sufixo}`);
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
function imprimirPreflightVerificacao(preflight) {
|
|
674
|
+
console.error(renderizarCaixaAscii([
|
|
675
|
+
"Preflight de verificacao falhou",
|
|
676
|
+
"a CLI sabe o que falta antes de gerar e testar",
|
|
677
|
+
]));
|
|
678
|
+
for (const item of preflight.faltando) {
|
|
679
|
+
const detalhe = item.detalhe ? ` (${item.detalhe})` : "";
|
|
680
|
+
console.error(`- ${item.comando}: ${item.nome} faltando${detalhe}`);
|
|
681
|
+
}
|
|
682
|
+
console.error("Rode `sema doctor` para ver as dependencias por comando.");
|
|
683
|
+
}
|
|
684
|
+
async function comandoDoctor() {
|
|
685
|
+
const dependencias = coletarDependenciasDoctor();
|
|
511
686
|
console.log(renderizarCaixaAscii([
|
|
512
687
|
"Sema doctor",
|
|
513
|
-
"checa a toolchain minima
|
|
688
|
+
"checa a toolchain minima e as dependencias reais por comando",
|
|
514
689
|
]));
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
690
|
+
imprimirDependenciasDoctor(dependencias);
|
|
691
|
+
const obrigatorios = dependencias
|
|
692
|
+
.find((dependencia) => dependencia.comando === "base")
|
|
693
|
+
?.itens.filter((item) => item.obrigatoria) ?? [];
|
|
519
694
|
return obrigatorios.every((check) => check.ok) ? 0 : 1;
|
|
520
695
|
}
|
|
521
696
|
function validarCompatibilidadeFramework(alvo, framework) {
|
|
@@ -754,8 +929,17 @@ function executarTestesGerados(alvo, baseSaida, arquivos, silencioso = false) {
|
|
|
754
929
|
}
|
|
755
930
|
return { codigoSaida: 0, quantidadeTestes, saidaPadrao: "", saidaErro: "" };
|
|
756
931
|
}
|
|
757
|
-
|
|
932
|
+
if (!TSX_EXECUTOR_CLI) {
|
|
933
|
+
return {
|
|
934
|
+
codigoSaida: 1,
|
|
935
|
+
quantidadeTestes,
|
|
936
|
+
saidaPadrao: "",
|
|
937
|
+
saidaErro: "Nao foi possivel localizar o runner tsx junto da CLI para executar testes TypeScript.",
|
|
938
|
+
};
|
|
939
|
+
}
|
|
940
|
+
const execucao = spawnSync("node", [TSX_EXECUTOR_CLI, arquivoTeste], {
|
|
758
941
|
stdio: silencioso ? "pipe" : "inherit",
|
|
942
|
+
cwd: baseSaida,
|
|
759
943
|
encoding: silencioso ? "utf8" : undefined,
|
|
760
944
|
});
|
|
761
945
|
return {
|
|
@@ -792,6 +976,14 @@ function executarTestesGerados(alvo, baseSaida, arquivos, silencioso = false) {
|
|
|
792
976
|
}
|
|
793
977
|
return { codigoSaida: 0, quantidadeTestes, saidaPadrao: "", saidaErro: "" };
|
|
794
978
|
}
|
|
979
|
+
if (!comandoDisponivel("lua", ["-v"])) {
|
|
980
|
+
return {
|
|
981
|
+
codigoSaida: 1,
|
|
982
|
+
quantidadeTestes,
|
|
983
|
+
saidaPadrao: "",
|
|
984
|
+
saidaErro: "Nao foi possivel localizar o runner lua para executar os testes gerados.",
|
|
985
|
+
};
|
|
986
|
+
}
|
|
795
987
|
const execucao = spawnSync("lua", [arquivoTeste], {
|
|
796
988
|
stdio: silencioso ? "pipe" : "inherit",
|
|
797
989
|
cwd: baseSaida,
|
|
@@ -812,10 +1004,20 @@ function executarTestesGerados(alvo, baseSaida, arquivos, silencioso = false) {
|
|
|
812
1004
|
}
|
|
813
1005
|
return { codigoSaida: 0, quantidadeTestes, saidaPadrao: "", saidaErro: "" };
|
|
814
1006
|
}
|
|
815
|
-
const
|
|
1007
|
+
const pytest = resolverExecucaoPytest();
|
|
1008
|
+
if (!pytest) {
|
|
1009
|
+
return {
|
|
1010
|
+
codigoSaida: 1,
|
|
1011
|
+
quantidadeTestes,
|
|
1012
|
+
saidaPadrao: "",
|
|
1013
|
+
saidaErro: "Nao foi possivel localizar pytest. Instale pytest ou exponha python -m pytest.",
|
|
1014
|
+
};
|
|
1015
|
+
}
|
|
1016
|
+
const execucao = spawnSync(pytest.comando, [...pytest.argumentosBase, arquivoTeste], {
|
|
816
1017
|
stdio: silencioso ? "pipe" : "inherit",
|
|
817
1018
|
cwd: baseSaida,
|
|
818
1019
|
encoding: silencioso ? "utf8" : undefined,
|
|
1020
|
+
shell: process.platform === "win32" && pytest.comando === "pytest",
|
|
819
1021
|
});
|
|
820
1022
|
return {
|
|
821
1023
|
codigoSaida: execucao.status ?? 1,
|
|
@@ -3058,14 +3260,17 @@ async function comandoInspecionar(entrada, emJson, cwd = process.cwd()) {
|
|
|
3058
3260
|
}
|
|
3059
3261
|
return 0;
|
|
3060
3262
|
}
|
|
3061
|
-
async function comandoDrift(entrada, emJson, cwd = process.cwd()) {
|
|
3263
|
+
async function comandoDrift(entrada, args, emJson, cwd = process.cwd()) {
|
|
3062
3264
|
const contextoProjeto = await carregarProjeto(entrada, cwd);
|
|
3063
|
-
const resultado = await analisarDriftLegado(contextoProjeto);
|
|
3265
|
+
const resultado = await analisarDriftLegado(contextoProjeto, resolverOpcoesDriftCli(args));
|
|
3064
3266
|
if (emJson) {
|
|
3065
3267
|
console.log(JSON.stringify(resultado, null, 2));
|
|
3066
3268
|
return resultado.sucesso ? 0 : 1;
|
|
3067
3269
|
}
|
|
3068
3270
|
console.log("Drift entre Sema e codigo legado");
|
|
3271
|
+
console.log(`- Escopo aplicado: ${resultado.escopo_aplicado.escopo}`);
|
|
3272
|
+
console.log(`- Ignorar worktrees: ${resultado.escopo_aplicado.ignorarWorktrees ? "sim" : "nao"}`);
|
|
3273
|
+
console.log(`- Ignorar consumidores laterais: ${resultado.escopo_aplicado.ignorarConsumidoresLaterais ? "sim" : "nao"}`);
|
|
3069
3274
|
console.log(`- Modulos analisados: ${resultado.modulos.length}`);
|
|
3070
3275
|
console.log(`- Tasks analisadas: ${resultado.tasks.length}`);
|
|
3071
3276
|
console.log(`- Impl validos: ${resultado.impls_validos.length}`);
|
|
@@ -3075,6 +3280,7 @@ async function comandoDrift(entrada, emJson, cwd = process.cwd()) {
|
|
|
3075
3280
|
console.log(`- Rotas divergentes: ${resultado.rotas_divergentes.length}`);
|
|
3076
3281
|
console.log(`- Recursos vivos validos: ${resultado.recursos_validos.length}`);
|
|
3077
3282
|
console.log(`- Recursos vivos divergentes: ${resultado.recursos_divergentes.length}`);
|
|
3283
|
+
console.log(`- Persistencia real mapeada: ${resultado.persistencia_real.length}`);
|
|
3078
3284
|
console.log(`- Score medio: ${resultado.resumo_operacional.scoreMedio}`);
|
|
3079
3285
|
console.log(`- Confianca geral: ${resultado.resumo_operacional.confiancaGeral}`);
|
|
3080
3286
|
if (resultado.impls_quebrados.length > 0) {
|
|
@@ -3101,6 +3307,13 @@ async function comandoDrift(entrada, emJson, cwd = process.cwd()) {
|
|
|
3101
3307
|
console.log(` - ${recurso.modulo}.${recurso.task} :: ${recurso.categoria} ${recurso.alvo}`);
|
|
3102
3308
|
}
|
|
3103
3309
|
}
|
|
3310
|
+
const persistenciaDivergente = resultado.persistencia_real.filter((item) => item.status !== "materializado");
|
|
3311
|
+
if (persistenciaDivergente.length > 0) {
|
|
3312
|
+
console.log("- Persistencia que pede revisao:");
|
|
3313
|
+
for (const item of persistenciaDivergente.slice(0, 8)) {
|
|
3314
|
+
console.log(` - ${item.modulo}.${item.task} :: ${item.alvo} :: ${item.status} :: categoria=${item.categoriaPersistencia} :: compat=${item.compatibilidade}`);
|
|
3315
|
+
}
|
|
3316
|
+
}
|
|
3104
3317
|
const semImpl = resultado.tasks.filter((task) => task.semImplementacao);
|
|
3105
3318
|
if (semImpl.length > 0) {
|
|
3106
3319
|
console.log("- Tasks sem implementacao vinculada:");
|
|
@@ -3137,6 +3350,70 @@ async function comandoDrift(entrada, emJson, cwd = process.cwd()) {
|
|
|
3137
3350
|
}
|
|
3138
3351
|
return resultado.sucesso ? 0 : 1;
|
|
3139
3352
|
}
|
|
3353
|
+
async function comandoImpacto(entrada, args, emJson, cwd = process.cwd()) {
|
|
3354
|
+
const alvoSemantico = obterOpcao(args, "--alvo");
|
|
3355
|
+
if (!alvoSemantico) {
|
|
3356
|
+
console.error("Uso: sema impacto <arquivo-ou-pasta> --alvo <token-semântico> [--mudanca <descricao>] [--escopo <arquivo|modulo|projeto>] [--incluir-worktrees] [--incluir-consumidores-laterais] [--json]");
|
|
3357
|
+
return 1;
|
|
3358
|
+
}
|
|
3359
|
+
const contextoProjeto = await carregarProjeto(entrada, cwd);
|
|
3360
|
+
const resultado = await gerarMapaImpactoSemantico(contextoProjeto, alvoSemantico, obterOpcao(args, "--mudanca", `avaliar impacto de ${alvoSemantico}`), resolverOpcoesDriftCli(args));
|
|
3361
|
+
if (emJson) {
|
|
3362
|
+
console.log(JSON.stringify(resultado, null, 2));
|
|
3363
|
+
return resultado.sucesso ? 0 : 1;
|
|
3364
|
+
}
|
|
3365
|
+
console.log("Impact map semantico");
|
|
3366
|
+
console.log(`- Escopo: ${resultado.escopo}`);
|
|
3367
|
+
console.log(`- Alvo: ${resultado.alvoSemantico}`);
|
|
3368
|
+
console.log(`- Mudanca: ${resultado.mudancaProposta}`);
|
|
3369
|
+
console.log(`- Arquivos impactados: ${resultado.arquivos.length}`);
|
|
3370
|
+
console.log(`- Tasks afetadas: ${resultado.tasksAfetadas.length}`);
|
|
3371
|
+
console.log(`- Rotas afetadas: ${resultado.routesAfetadas.length}`);
|
|
3372
|
+
console.log(`- Superficies afetadas: ${resultado.superficiesAfetadas.length}`);
|
|
3373
|
+
console.log(`- Persistencia afetada: ${resultado.persistenciaAfetada.length}`);
|
|
3374
|
+
if (resultado.arquivos.length > 0) {
|
|
3375
|
+
console.log("- Arquivos prioritarios:");
|
|
3376
|
+
for (const arquivo of resultado.arquivos.slice(0, 10)) {
|
|
3377
|
+
console.log(` - [${arquivo.prioridade}] ${arquivo.tipo} :: ${arquivo.arquivo}`);
|
|
3378
|
+
}
|
|
3379
|
+
}
|
|
3380
|
+
console.log("- Ordem operacional:");
|
|
3381
|
+
for (const passo of resultado.ordemOperacional) {
|
|
3382
|
+
console.log(` - ${passo}`);
|
|
3383
|
+
}
|
|
3384
|
+
return resultado.sucesso ? 0 : 1;
|
|
3385
|
+
}
|
|
3386
|
+
async function comandoRenomearSemantico(entrada, args, emJson, cwd = process.cwd()) {
|
|
3387
|
+
const nomeAtual = obterOpcao(args, "--de");
|
|
3388
|
+
const nomeNovo = obterOpcao(args, "--para");
|
|
3389
|
+
if (!nomeAtual || !nomeNovo) {
|
|
3390
|
+
console.error("Uso: sema renomear-semantico <arquivo-ou-pasta> --de <nome-atual> --para <nome-novo> [--escopo <arquivo|modulo|projeto>] [--incluir-worktrees] [--incluir-consumidores-laterais] [--json]");
|
|
3391
|
+
return 1;
|
|
3392
|
+
}
|
|
3393
|
+
const contextoProjeto = await carregarProjeto(entrada, cwd);
|
|
3394
|
+
const resultado = await assistirRenomeacaoSemantica(contextoProjeto, nomeAtual, nomeNovo, resolverOpcoesDriftCli(args));
|
|
3395
|
+
if (emJson) {
|
|
3396
|
+
console.log(JSON.stringify(resultado, null, 2));
|
|
3397
|
+
return resultado.sucesso ? 0 : 1;
|
|
3398
|
+
}
|
|
3399
|
+
console.log("Renomeacao semantica assistida");
|
|
3400
|
+
console.log(`- Escopo: ${resultado.escopo}`);
|
|
3401
|
+
console.log(`- De: ${resultado.de}`);
|
|
3402
|
+
console.log(`- Para: ${resultado.para}`);
|
|
3403
|
+
console.log(`- Arquivos afetados: ${resultado.arquivos.length}`);
|
|
3404
|
+
console.log(`- Sugestoes: ${resultado.sugestoes.length}`);
|
|
3405
|
+
if (resultado.sugestoes.length > 0) {
|
|
3406
|
+
console.log("- Primeiras sugestoes:");
|
|
3407
|
+
for (const sugestao of resultado.sugestoes.slice(0, 12)) {
|
|
3408
|
+
console.log(` - ${sugestao.arquivo}:${sugestao.linha} :: ${sugestao.atual} -> ${sugestao.sugerido}`);
|
|
3409
|
+
}
|
|
3410
|
+
}
|
|
3411
|
+
console.log("- Ordem operacional:");
|
|
3412
|
+
for (const passo of resultado.ordemOperacional) {
|
|
3413
|
+
console.log(` - ${passo}`);
|
|
3414
|
+
}
|
|
3415
|
+
return resultado.sucesso ? 0 : 1;
|
|
3416
|
+
}
|
|
3140
3417
|
async function comandoImportar(fonte, diretorio, saida, namespaceBase, emJson) {
|
|
3141
3418
|
const resultado = await importarProjetoLegado(fonte, diretorio, namespaceBase);
|
|
3142
3419
|
const resumo = resumoImportacao(resultado);
|
|
@@ -3666,6 +3943,11 @@ async function comandoVerificar(entrada, baseSaida, cwd = process.cwd()) {
|
|
|
3666
3943
|
console.error(incompatibilidade.incompatibilidade);
|
|
3667
3944
|
return 1;
|
|
3668
3945
|
}
|
|
3946
|
+
const preflight = avaliarPreflightVerificacao(configuracoesAlvo);
|
|
3947
|
+
if (!preflight.ok) {
|
|
3948
|
+
imprimirPreflightVerificacao(preflight);
|
|
3949
|
+
return 1;
|
|
3950
|
+
}
|
|
3669
3951
|
const resumos = [];
|
|
3670
3952
|
for (const modulo of modulos) {
|
|
3671
3953
|
const ir = garantirIr(modulo.resultado, modulo.caminho);
|
|
@@ -3733,6 +4015,18 @@ async function comandoVerificarJson(entrada, baseSaida, cwd = process.cwd()) {
|
|
|
3733
4015
|
}, null, 2));
|
|
3734
4016
|
return 1;
|
|
3735
4017
|
}
|
|
4018
|
+
const preflight = avaliarPreflightVerificacao(configuracoesAlvo);
|
|
4019
|
+
if (!preflight.ok) {
|
|
4020
|
+
console.log(JSON.stringify({
|
|
4021
|
+
comando: "verificar",
|
|
4022
|
+
sucesso: false,
|
|
4023
|
+
erro: "Dependencias obrigatorias ausentes para executar a verificacao.",
|
|
4024
|
+
preflight,
|
|
4025
|
+
modulos: [],
|
|
4026
|
+
totais: { modulos: 0, alvos: 0, arquivos: 0, testes: 0 },
|
|
4027
|
+
}, null, 2));
|
|
4028
|
+
return 1;
|
|
4029
|
+
}
|
|
3736
4030
|
const resumos = [];
|
|
3737
4031
|
let codigoSaida = 0;
|
|
3738
4032
|
for (const modulo of modulos) {
|
|
@@ -3855,7 +4149,13 @@ async function principal() {
|
|
|
3855
4149
|
codigoSaida = await comandoInspecionar(posicionais[0], possuiFlag(resto, "--json"), cwd);
|
|
3856
4150
|
break;
|
|
3857
4151
|
case "drift":
|
|
3858
|
-
codigoSaida = await comandoDrift(posicionais[0], possuiFlag(resto, "--json"), cwd);
|
|
4152
|
+
codigoSaida = await comandoDrift(posicionais[0], resto, possuiFlag(resto, "--json"), cwd);
|
|
4153
|
+
break;
|
|
4154
|
+
case "impacto":
|
|
4155
|
+
codigoSaida = await comandoImpacto(posicionais[0], resto, possuiFlag(resto, "--json"), cwd);
|
|
4156
|
+
break;
|
|
4157
|
+
case "renomear-semantico":
|
|
4158
|
+
codigoSaida = await comandoRenomearSemantico(posicionais[0], resto, possuiFlag(resto, "--json"), cwd);
|
|
3859
4159
|
break;
|
|
3860
4160
|
case "importar":
|
|
3861
4161
|
{
|