@codexa/cli 9.0.7 → 9.0.9
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/commands/decide.ts +120 -3
- package/commands/discover.ts +18 -9
- package/commands/integration.test.ts +754 -0
- package/commands/knowledge.test.ts +2 -6
- package/commands/knowledge.ts +20 -4
- package/commands/patterns.ts +8 -644
- package/commands/product.ts +41 -104
- package/commands/spec-resolver.test.ts +2 -13
- package/commands/standards.ts +33 -3
- package/commands/task.ts +21 -4
- package/commands/utils.test.ts +25 -87
- package/commands/utils.ts +20 -82
- package/context/assembly.ts +11 -12
- package/context/domains.test.ts +300 -0
- package/context/domains.ts +157 -0
- package/context/generator.ts +14 -13
- package/context/index.ts +6 -1
- package/context/references.test.ts +159 -0
- package/context/references.ts +159 -0
- package/context/sections.ts +18 -1
- package/db/schema.ts +40 -5
- package/db/test-helpers.ts +33 -0
- package/gates/standards-validator.test.ts +447 -0
- package/gates/standards-validator.ts +164 -125
- package/gates/typecheck-validator.ts +296 -92
- package/gates/validator.ts +93 -8
- package/package.json +1 -1
- package/protocol/process-return.ts +39 -4
- package/workflow.ts +54 -84
|
@@ -13,11 +13,13 @@ import { getDb } from "../db/connection";
|
|
|
13
13
|
import { SubagentReturn, Knowledge } from "./subagent-protocol";
|
|
14
14
|
import { addReasoning, addGraphRelation, upsertUtility, getNextDecisionId } from "../db/schema";
|
|
15
15
|
import { extractUtilitiesFromFile, inferScopeFromPath } from "../commands/patterns";
|
|
16
|
+
import { detectConflicts } from "../commands/decide";
|
|
16
17
|
|
|
17
18
|
interface ProcessResult {
|
|
18
19
|
success: boolean;
|
|
19
20
|
knowledgeAdded: number;
|
|
20
21
|
decisionsAdded: number;
|
|
22
|
+
conflictsDetected: number;
|
|
21
23
|
artifactsAdded: number;
|
|
22
24
|
patternsAdded: number;
|
|
23
25
|
reasoningAdded: number; // v8.0
|
|
@@ -42,6 +44,7 @@ export function processSubagentReturn(
|
|
|
42
44
|
success: true,
|
|
43
45
|
knowledgeAdded: 0,
|
|
44
46
|
decisionsAdded: 0,
|
|
47
|
+
conflictsDetected: 0,
|
|
45
48
|
artifactsAdded: 0,
|
|
46
49
|
patternsAdded: 0,
|
|
47
50
|
reasoningAdded: 0,
|
|
@@ -102,6 +105,39 @@ export function processSubagentReturn(
|
|
|
102
105
|
}
|
|
103
106
|
}
|
|
104
107
|
|
|
108
|
+
// 2b. v9.5: Conflict check (WARNING, nao bloqueia subagent)
|
|
109
|
+
if (savedDecisionIds.length > 0) {
|
|
110
|
+
try {
|
|
111
|
+
const existingDecisions = db
|
|
112
|
+
.query("SELECT * FROM decisions WHERE spec_id = ? AND status = 'active'")
|
|
113
|
+
.all(specId) as any[];
|
|
114
|
+
|
|
115
|
+
for (const dec of data.decisions_made!) {
|
|
116
|
+
const othersOnly = existingDecisions.filter(
|
|
117
|
+
(d) => !savedDecisionIds.includes(d.id)
|
|
118
|
+
);
|
|
119
|
+
if (othersOnly.length === 0) continue;
|
|
120
|
+
|
|
121
|
+
const analysis = detectConflicts(dec.title, dec.decision, othersOnly);
|
|
122
|
+
if (analysis.hasConflict) {
|
|
123
|
+
for (const conflict of analysis.conflictingDecisions) {
|
|
124
|
+
db.run(
|
|
125
|
+
`INSERT INTO knowledge (spec_id, task_origin, category, content, severity, broadcast_to, created_at)
|
|
126
|
+
VALUES (?, ?, 'decision', ?, 'warning', 'all', ?)`,
|
|
127
|
+
[specId, taskId,
|
|
128
|
+
`CONFLITO DE DECISAO: "${dec.title}" pode conflitar com "${conflict.title}" (${conflict.id}). Motivo: ${conflict.reason}`,
|
|
129
|
+
now]
|
|
130
|
+
);
|
|
131
|
+
result.conflictsDetected++;
|
|
132
|
+
result.knowledgeAdded++;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
} catch (e) {
|
|
137
|
+
result.errors.push(`Aviso conflict detection: ${(e as Error).message}`);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
105
141
|
// 3. Registrar Artifacts (files_created e files_modified)
|
|
106
142
|
const allFiles = [
|
|
107
143
|
...data.files_created.map((f) => ({ path: f, action: "created" })),
|
|
@@ -246,7 +282,6 @@ export function processSubagentReturn(
|
|
|
246
282
|
targetType: "file",
|
|
247
283
|
targetId: file,
|
|
248
284
|
relation: "creates",
|
|
249
|
-
strength: 1.0,
|
|
250
285
|
});
|
|
251
286
|
result.relationsAdded++;
|
|
252
287
|
}
|
|
@@ -259,7 +294,6 @@ export function processSubagentReturn(
|
|
|
259
294
|
targetType: "file",
|
|
260
295
|
targetId: file,
|
|
261
296
|
relation: "modifies",
|
|
262
|
-
strength: 1.0,
|
|
263
297
|
});
|
|
264
298
|
result.relationsAdded++;
|
|
265
299
|
}
|
|
@@ -274,7 +308,6 @@ export function processSubagentReturn(
|
|
|
274
308
|
targetType: "file",
|
|
275
309
|
targetId: file,
|
|
276
310
|
relation: "implements",
|
|
277
|
-
strength: 0.8,
|
|
278
311
|
});
|
|
279
312
|
result.relationsAdded++;
|
|
280
313
|
}
|
|
@@ -291,7 +324,6 @@ export function processSubagentReturn(
|
|
|
291
324
|
targetType: "file",
|
|
292
325
|
targetId: file,
|
|
293
326
|
relation: "extracted_from",
|
|
294
|
-
strength: 0.9,
|
|
295
327
|
});
|
|
296
328
|
result.relationsAdded++;
|
|
297
329
|
}
|
|
@@ -354,6 +386,9 @@ export function formatProcessResult(result: ProcessResult): string {
|
|
|
354
386
|
if (result.decisionsAdded > 0) {
|
|
355
387
|
output += ` + ${result.decisionsAdded} decisao(es) registrada(s)\n`;
|
|
356
388
|
}
|
|
389
|
+
if (result.conflictsDetected > 0) {
|
|
390
|
+
output += ` [!] ${result.conflictsDetected} conflito(s) de decisao detectado(s) (ver: knowledge list)\n`;
|
|
391
|
+
}
|
|
357
392
|
if (result.artifactsAdded > 0) {
|
|
358
393
|
output += ` + ${result.artifactsAdded} artefato(s) registrado(s)\n`;
|
|
359
394
|
}
|
package/workflow.ts
CHANGED
|
@@ -4,10 +4,10 @@ import { Command } from "commander";
|
|
|
4
4
|
import { planStart, planShow, planTaskAdd, planCancel } from "./commands/plan";
|
|
5
5
|
import { checkRequest, checkApprove, checkReject } from "./commands/check";
|
|
6
6
|
import { taskNext, taskStart, taskDone } from "./commands/task";
|
|
7
|
-
import { decide, listDecisions } from "./commands/decide";
|
|
7
|
+
import { decide, listDecisions, revokeDecision, supersedeDecision } from "./commands/decide";
|
|
8
8
|
import { reviewStart, reviewApprove, reviewSkip } from "./commands/review";
|
|
9
9
|
import { addKnowledge, listKnowledge, acknowledgeKnowledge, queryGraph, resolveKnowledge, compactKnowledge } from "./commands/knowledge";
|
|
10
|
-
import { status, contextExport, recover,
|
|
10
|
+
import { status, contextExport, recover, contextDetail } from "./commands/utils";
|
|
11
11
|
import {
|
|
12
12
|
discoverStart,
|
|
13
13
|
discoverConfirm,
|
|
@@ -26,9 +26,8 @@ import {
|
|
|
26
26
|
} from "./commands/discover";
|
|
27
27
|
import { clearTasks, clearShow } from "./commands/clear";
|
|
28
28
|
import { standardsList, standardsAdd, standardsEdit, standardsRemove, standardsExport } from "./commands/standards";
|
|
29
|
-
import {
|
|
29
|
+
import { productImport, productSet, productConfirm, productShow, productReset } from "./commands/product";
|
|
30
30
|
import { researchStart, researchShow, researchFill, researchMapAgent, researchReset } from "./commands/research";
|
|
31
|
-
import { patternsExtract, patternsAnalyze } from "./commands/patterns";
|
|
32
31
|
import { syncAgents } from "./commands/sync";
|
|
33
32
|
import {
|
|
34
33
|
architectStart,
|
|
@@ -327,6 +326,24 @@ program
|
|
|
327
326
|
listDecisions(options.json, options.spec);
|
|
328
327
|
});
|
|
329
328
|
|
|
329
|
+
program
|
|
330
|
+
.command("decide:revoke <id>")
|
|
331
|
+
.description("Revoga uma decisao ativa")
|
|
332
|
+
.option("--reason <text>", "Motivo da revogacao")
|
|
333
|
+
.option("--spec <id>", "ID do spec (padrao: mais recente)")
|
|
334
|
+
.action(wrapAction((id: string, options) => {
|
|
335
|
+
revokeDecision(id, options.reason, options.spec);
|
|
336
|
+
}));
|
|
337
|
+
|
|
338
|
+
program
|
|
339
|
+
.command("decide:supersede <id> <title> <decision>")
|
|
340
|
+
.description("Substitui uma decisao ativa por uma nova")
|
|
341
|
+
.option("--rationale <text>", "Justificativa da nova decisao")
|
|
342
|
+
.option("--spec <id>", "ID do spec (padrao: mais recente)")
|
|
343
|
+
.action(wrapAction((id: string, title: string, decision: string, options) => {
|
|
344
|
+
supersedeDecision(id, title, decision, { rationale: options.rationale, specId: options.spec });
|
|
345
|
+
}));
|
|
346
|
+
|
|
330
347
|
// ═══════════════════════════════════════════════════════════════
|
|
331
348
|
// KNOWLEDGE BROADCAST
|
|
332
349
|
// ═══════════════════════════════════════════════════════════════
|
|
@@ -458,17 +475,6 @@ contextCmd
|
|
|
458
475
|
contextExport({ ...options, json: true, specId: options.spec }); // Sempre JSON
|
|
459
476
|
});
|
|
460
477
|
|
|
461
|
-
contextCmd
|
|
462
|
-
.command("update")
|
|
463
|
-
.description("Atualiza contexto durante implementacao")
|
|
464
|
-
.option("--approach <text>", "Adiciona nova abordagem descoberta")
|
|
465
|
-
.option("--pattern <text>", "Registra padrao identificado no codigo")
|
|
466
|
-
.option("--constraint <text>", "Adiciona nova limitacao encontrada")
|
|
467
|
-
.option("--spec <id>", "ID do spec (padrao: mais recente)")
|
|
468
|
-
.action((options) => {
|
|
469
|
-
contextUpdate({ ...options, specId: options.spec });
|
|
470
|
-
});
|
|
471
|
-
|
|
472
478
|
contextCmd
|
|
473
479
|
.command("detail <section>")
|
|
474
480
|
.description("Mostra secao especifica do contexto (standards, decisions, patterns, knowledge, architecture)")
|
|
@@ -546,8 +552,29 @@ discoverCmd
|
|
|
546
552
|
.option("--styling <value>", "Styling (tailwind, styled-components)")
|
|
547
553
|
.option("--auth <value>", "Auth (supabase, next-auth, clerk)")
|
|
548
554
|
.option("--testing <value>", "Testing (vitest, jest, playwright)")
|
|
549
|
-
.
|
|
550
|
-
|
|
555
|
+
.option("--typecheck-command <cmd>", "Comando custom de typecheck (ex: 'mypy --strict', 'go vet ./...'). Vazio para usar preset automatico.")
|
|
556
|
+
.action((options) => {
|
|
557
|
+
// Tratar typecheck-command separadamente
|
|
558
|
+
if (options.typecheckCommand !== undefined) {
|
|
559
|
+
const { initSchema } = require("./db/schema");
|
|
560
|
+
const { getDb } = require("./db/connection");
|
|
561
|
+
initSchema();
|
|
562
|
+
const db = getDb();
|
|
563
|
+
const value = options.typecheckCommand === "" ? null : options.typecheckCommand;
|
|
564
|
+
db.run("UPDATE project SET typecheck_command = ? WHERE id = 'default'", [value]);
|
|
565
|
+
if (value) {
|
|
566
|
+
console.log(`\n[ok] Typecheck command configurado: ${value}`);
|
|
567
|
+
} else {
|
|
568
|
+
console.log(`\n[ok] Typecheck command removido (usando preset automatico da stack)`);
|
|
569
|
+
}
|
|
570
|
+
console.log(" Sera usado no gate 4.5 (typecheck-pass) em cada task done.\n");
|
|
571
|
+
}
|
|
572
|
+
// Tratar stack options normalmente
|
|
573
|
+
const stackOptions = { ...options };
|
|
574
|
+
delete stackOptions.typecheckCommand;
|
|
575
|
+
if (Object.keys(stackOptions).length > 0) {
|
|
576
|
+
discoverSetStack(stackOptions);
|
|
577
|
+
}
|
|
551
578
|
});
|
|
552
579
|
|
|
553
580
|
discoverCmd
|
|
@@ -656,45 +683,6 @@ discoverCmd
|
|
|
656
683
|
discoverRefreshPatterns();
|
|
657
684
|
});
|
|
658
685
|
|
|
659
|
-
// v8.0: Extração automática de patterns via grepai
|
|
660
|
-
discoverCmd
|
|
661
|
-
.command("extract-patterns")
|
|
662
|
-
.description("Extrai patterns automaticamente via grepai (busca semântica)")
|
|
663
|
-
.option("--scope <scope>", "Escopo (frontend, backend, database, testing)")
|
|
664
|
-
.option("--all", "Extrair de todos os escopos")
|
|
665
|
-
.option("--dry-run", "Apenas mostrar o que seria extraido")
|
|
666
|
-
.option("--json", "Saida em JSON")
|
|
667
|
-
.action((options) => {
|
|
668
|
-
patternsExtract(options);
|
|
669
|
-
});
|
|
670
|
-
|
|
671
|
-
discoverCmd
|
|
672
|
-
.command("analyze-file <path>", { hidden: true })
|
|
673
|
-
.description("Analisa estrutura de um arquivo (imports, exports, convencoes)")
|
|
674
|
-
.option("--json", "Saida em JSON")
|
|
675
|
-
.action((path, options) => {
|
|
676
|
-
patternsAnalyze(path, options.json);
|
|
677
|
-
});
|
|
678
|
-
|
|
679
|
-
// v9.0: Analise profunda com metadata enriquecida + grepai
|
|
680
|
-
discoverCmd
|
|
681
|
-
.command("analyze-deep <files...>", { hidden: true })
|
|
682
|
-
.description("Analise profunda de arquivos (hooks, patterns, directives)")
|
|
683
|
-
.option("--json", "Saida em JSON")
|
|
684
|
-
.action((files, options) => {
|
|
685
|
-
const { patternsAnalyzeDeep } = require("./commands/patterns");
|
|
686
|
-
patternsAnalyzeDeep(files, options.json);
|
|
687
|
-
});
|
|
688
|
-
|
|
689
|
-
// v9.0: Anti-patterns de gate bypasses
|
|
690
|
-
discoverCmd
|
|
691
|
-
.command("extract-anti-patterns", { hidden: true })
|
|
692
|
-
.description("Extrai anti-patterns do historico de gate bypasses")
|
|
693
|
-
.action(() => {
|
|
694
|
-
const { extractAntiPatternsFromHistory } = require("./commands/patterns");
|
|
695
|
-
extractAntiPatternsFromHistory();
|
|
696
|
-
});
|
|
697
|
-
|
|
698
686
|
discoverCmd
|
|
699
687
|
.command("export-patterns", { hidden: true })
|
|
700
688
|
.description("Regenera arquivo patterns.md")
|
|
@@ -729,6 +717,8 @@ standardsCmd
|
|
|
729
717
|
.option("--enforcement <level>", "Nivel de enforcement (required, recommended)")
|
|
730
718
|
.option("--required", "Alias para --enforcement required")
|
|
731
719
|
.option("--recommended", "Alias para --enforcement recommended")
|
|
720
|
+
.option("--semantic-query <query>", "Query semantica para grepai (ingles)")
|
|
721
|
+
.option("--expect <type>", "Expectativa: no_match ou must_match", "no_match")
|
|
732
722
|
.action((options) => {
|
|
733
723
|
// Resolver aliases de enforcement
|
|
734
724
|
let enforcement = options.enforcement;
|
|
@@ -742,6 +732,8 @@ standardsCmd
|
|
|
742
732
|
examples: options.examples,
|
|
743
733
|
antiExamples: options.antiExamples,
|
|
744
734
|
enforcement: enforcement,
|
|
735
|
+
semanticQuery: options.semanticQuery,
|
|
736
|
+
expect: options.expect,
|
|
745
737
|
});
|
|
746
738
|
});
|
|
747
739
|
|
|
@@ -752,12 +744,16 @@ standardsCmd
|
|
|
752
744
|
.option("--examples <list>", "Novos exemplos")
|
|
753
745
|
.option("--anti-examples <list>", "Novos anti-exemplos")
|
|
754
746
|
.option("--enforcement <level>", "Novo nivel de enforcement")
|
|
747
|
+
.option("--semantic-query <query>", "Query semantica para grepai (ingles)")
|
|
748
|
+
.option("--expect <type>", "Expectativa: no_match ou must_match")
|
|
755
749
|
.action((id, options) => {
|
|
756
750
|
standardsEdit(id, {
|
|
757
751
|
rule: options.rule,
|
|
758
752
|
examples: options.examples,
|
|
759
753
|
antiExamples: options.antiExamples,
|
|
760
754
|
enforcement: options.enforcement,
|
|
755
|
+
semanticQuery: options.semanticQuery,
|
|
756
|
+
expect: options.expect,
|
|
761
757
|
});
|
|
762
758
|
});
|
|
763
759
|
|
|
@@ -781,14 +777,6 @@ standardsCmd
|
|
|
781
777
|
|
|
782
778
|
const productCmd = program.command("product").description("Comandos de contexto de produto (PRD)");
|
|
783
779
|
|
|
784
|
-
productCmd
|
|
785
|
-
.command("guide")
|
|
786
|
-
.description("Inicia modo guiado para definir contexto de produto")
|
|
787
|
-
.option("--json", "Saida em JSON")
|
|
788
|
-
.action((options) => {
|
|
789
|
-
productGuide(options.json);
|
|
790
|
-
});
|
|
791
|
-
|
|
792
780
|
productCmd
|
|
793
781
|
.command("import")
|
|
794
782
|
.description("Importa PRD existente")
|
|
@@ -809,30 +797,12 @@ productCmd
|
|
|
809
797
|
.option("--successMetrics <list>", "Metricas de sucesso (separadas por virgula)")
|
|
810
798
|
.option("--outOfScope <list>", "Itens fora do escopo (separados por virgula)")
|
|
811
799
|
.option("--constraints <list>", "Restricoes (separadas por virgula)")
|
|
800
|
+
.option("--goal <spec>", "Adiciona objetivo (formato: categoria:texto:prioridade)")
|
|
801
|
+
.option("--feature <spec>", "Adiciona feature (formato: nome:descricao:prioridade)")
|
|
812
802
|
.action((options) => {
|
|
813
803
|
productSet(options);
|
|
814
804
|
});
|
|
815
805
|
|
|
816
|
-
productCmd
|
|
817
|
-
.command("goal-add")
|
|
818
|
-
.description("Adiciona um objetivo do produto")
|
|
819
|
-
.requiredOption("--category <cat>", "Categoria (negocio, tecnico, usuario, operacional)")
|
|
820
|
-
.requiredOption("--goal <text>", "Descricao do objetivo")
|
|
821
|
-
.option("--priority <level>", "Prioridade (high, medium, low)", "medium")
|
|
822
|
-
.action((options) => {
|
|
823
|
-
productGoalAdd(options);
|
|
824
|
-
});
|
|
825
|
-
|
|
826
|
-
productCmd
|
|
827
|
-
.command("feature-add")
|
|
828
|
-
.description("Adiciona uma feature core do produto")
|
|
829
|
-
.requiredOption("--name <name>", "Nome da feature")
|
|
830
|
-
.option("--description <text>", "Descricao da feature")
|
|
831
|
-
.option("--priority <level>", "Prioridade (high, medium, low)", "medium")
|
|
832
|
-
.action((options) => {
|
|
833
|
-
productFeatureAdd(options);
|
|
834
|
-
});
|
|
835
|
-
|
|
836
806
|
productCmd
|
|
837
807
|
.command("show")
|
|
838
808
|
.description("Mostra contexto de produto")
|