@codexa/cli 9.0.3 → 9.0.4

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/workflow.ts CHANGED
@@ -6,7 +6,7 @@ import { checkRequest, checkApprove, checkReject } from "./commands/check";
6
6
  import { taskNext, taskStart, taskDone } from "./commands/task";
7
7
  import { decide, listDecisions } from "./commands/decide";
8
8
  import { reviewStart, reviewApprove, reviewSkip } from "./commands/review";
9
- import { addKnowledge, listKnowledge, acknowledgeKnowledge, queryGraph, resolveKnowledge } from "./commands/knowledge";
9
+ import { addKnowledge, listKnowledge, acknowledgeKnowledge, queryGraph, resolveKnowledge, compactKnowledge } from "./commands/knowledge";
10
10
  import { status, contextExport, recover, contextUpdate, contextDetail } from "./commands/utils";
11
11
  import {
12
12
  discoverStart,
@@ -40,12 +40,12 @@ import {
40
40
  architectCancel,
41
41
  } from "./commands/architect";
42
42
  import { initSchema } from "./db/schema";
43
- import { getDb } from "./db/connection";
43
+ import { getDb, closeDb } from "./db/connection";
44
44
  import { execSync } from "child_process";
45
45
  import { existsSync, readFileSync } from "fs";
46
46
  import { join } from "path";
47
47
  import pkg from "./package.json";
48
- import { CodexaError, ValidationError } from "./errors";
48
+ import { CodexaError, ValidationError, GateError } from "./errors";
49
49
 
50
50
  function checkVersionSync(): void {
51
51
  // 1. Check CLI vs Plugin (dev repo only)
@@ -103,9 +103,27 @@ function checkVersionSync(): void {
103
103
  function handleError(e: unknown): never {
104
104
  if (e instanceof CodexaError) {
105
105
  console.error(`\n${e.message}\n`);
106
+
107
+ // v9.3: Exibir diagnostico e passos de recuperacao para falhas de gate
108
+ if (e instanceof GateError && e.recovery) {
109
+ console.error("\u2500".repeat(50));
110
+ console.error("DIAGNOSTICO:");
111
+ console.error(` ${e.recovery.diagnostic}\n`);
112
+ console.error("PASSOS PARA CORRIGIR:");
113
+ for (const step of e.recovery.steps) {
114
+ console.error(` \u2192 ${step}`);
115
+ }
116
+ if (e.recovery.command) {
117
+ console.error(`\nPara mais detalhes: ${e.recovery.command}`);
118
+ }
119
+ console.error();
120
+ }
121
+
122
+ closeDb();
106
123
  process.exit(e.exitCode);
107
124
  }
108
125
  console.error(`\n[ERRO INESPERADO] ${(e as Error).message}\n`);
126
+ closeDb();
109
127
  process.exit(1);
110
128
  }
111
129
 
@@ -114,10 +132,14 @@ function wrapAction<T extends (...args: any[]) => any>(fn: T): T {
114
132
  try {
115
133
  const result = fn(...args);
116
134
  if (result instanceof Promise) {
117
- return result.catch(handleError);
135
+ return result.catch((e) => {
136
+ closeDb();
137
+ handleError(e);
138
+ });
118
139
  }
119
140
  return result;
120
141
  } catch (e) {
142
+ closeDb();
121
143
  handleError(e);
122
144
  }
123
145
  }) as T;
@@ -130,15 +152,7 @@ program
130
152
  .description(`Codexa Workflow v${pkg.version} - Sistema de workflow para Claude Code`)
131
153
  .version(pkg.version)
132
154
  .hook("preAction", () => {
133
- try {
134
- checkVersionSync();
135
- } catch (e) {
136
- if (e instanceof CodexaError) {
137
- console.error(`\n${e.message}\n`);
138
- process.exit(e.exitCode);
139
- }
140
- throw e;
141
- }
155
+ checkVersionSync();
142
156
  });
143
157
 
144
158
  // ═══════════════════════════════════════════════════════════════
@@ -160,8 +174,9 @@ planCmd
160
174
  .command("show")
161
175
  .description("Mostra o plano atual")
162
176
  .option("--json", "Saida em JSON")
177
+ .option("--spec <id>", "ID do spec (padrao: mais recente)")
163
178
  .action((options) => {
164
- planShow(options.json);
179
+ planShow(options.json, options.spec);
165
180
  });
166
181
 
167
182
  planCmd
@@ -172,15 +187,17 @@ planCmd
172
187
  .option("--depends <ids>", "IDs das tasks que esta depende (ex: 1,2)")
173
188
  .option("--files <files>", "Arquivos esperados (ex: src/a.ts,src/b.ts)")
174
189
  .option("--sequential", "Marca como sequencial (nao paralelizavel)")
190
+ .option("--spec <id>", "ID do spec (padrao: mais recente)")
175
191
  .action((options) => {
176
- planTaskAdd(options);
192
+ planTaskAdd({ ...options, specId: options.spec });
177
193
  });
178
194
 
179
195
  planCmd
180
196
  .command("cancel")
181
197
  .description("Cancela a feature atual (soft-cancel, preserva historico)")
182
- .action(() => {
183
- planCancel();
198
+ .option("--spec <id>", "ID do spec (padrao: mais recente)")
199
+ .action((options) => {
200
+ planCancel(options.spec);
184
201
  });
185
202
 
186
203
  // ═══════════════════════════════════════════════════════════════
@@ -192,22 +209,25 @@ const checkCmd = program.command("check").description("Comandos da fase CHECK");
192
209
  checkCmd
193
210
  .command("request")
194
211
  .description("Solicita aprovacao do plano")
195
- .action(() => {
196
- checkRequest();
212
+ .option("--spec <id>", "ID do spec (padrao: mais recente)")
213
+ .action((options) => {
214
+ checkRequest(options.spec);
197
215
  });
198
216
 
199
217
  checkCmd
200
218
  .command("approve")
201
219
  .description("Aprova o plano")
202
- .action(() => {
203
- checkApprove();
220
+ .option("--spec <id>", "ID do spec (padrao: mais recente)")
221
+ .action((options) => {
222
+ checkApprove(options.spec);
204
223
  });
205
224
 
206
225
  checkCmd
207
226
  .command("reject <reason>")
208
227
  .description("Rejeita o plano com motivo")
209
- .action((reason: string) => {
210
- checkReject(reason);
228
+ .option("--spec <id>", "ID do spec (padrao: mais recente)")
229
+ .action((reason: string, options) => {
230
+ checkReject(reason, options.spec);
211
231
  });
212
232
 
213
233
  // ═══════════════════════════════════════════════════════════════
@@ -220,8 +240,9 @@ taskCmd
220
240
  .command("next")
221
241
  .description("Mostra proximas tasks disponiveis")
222
242
  .option("--json", "Saida em JSON")
243
+ .option("--spec <id>", "ID do spec (padrao: mais recente)")
223
244
  .action(wrapAction((options) => {
224
- taskNext(options.json);
245
+ taskNext(options.json, options.spec);
225
246
  }));
226
247
 
227
248
  taskCmd
@@ -229,8 +250,9 @@ taskCmd
229
250
  .description("Inicia task(s) - pode ser multiplas separadas por virgula")
230
251
  .option("--json", "Saida em JSON")
231
252
  .option("--full-context", "Incluir contexto completo (modo legado)")
253
+ .option("--spec <id>", "ID do spec (padrao: mais recente)")
232
254
  .action(wrapAction((ids: string, options) => {
233
- taskStart(ids, options.json, options.fullContext);
255
+ taskStart(ids, options.json, options.fullContext, options.spec);
234
256
  }));
235
257
 
236
258
  taskCmd
@@ -290,16 +312,18 @@ program
290
312
  .description("Registra uma decisao")
291
313
  .option("--rationale <text>", "Justificativa da decisao")
292
314
  .option("--force", "Ignorar deteccao de conflitos")
315
+ .option("--spec <id>", "ID do spec (padrao: mais recente)")
293
316
  .action((title: string, decision: string, options) => {
294
- decide(title, decision, options);
317
+ decide(title, decision, { ...options, specId: options.spec });
295
318
  });
296
319
 
297
320
  program
298
321
  .command("decisions")
299
322
  .description("Lista decisoes")
300
323
  .option("--json", "Saida em JSON")
324
+ .option("--spec <id>", "ID do spec (padrao: mais recente)")
301
325
  .action((options) => {
302
- listDecisions(options.json);
326
+ listDecisions(options.json, options.spec);
303
327
  });
304
328
 
305
329
  // ═══════════════════════════════════════════════════════════════
@@ -315,12 +339,14 @@ knowledgeCmd
315
339
  .requiredOption("--category <cat>", "Categoria (discovery, decision, blocker, pattern, constraint)")
316
340
  .option("--severity <level>", "Severidade (info, warning, critical)", "info")
317
341
  .option("--broadcast <target>", "Destino (all ou IDs separados por virgula)", "all")
342
+ .option("--spec <id>", "ID do spec (padrao: mais recente)")
318
343
  .action((options) => {
319
344
  addKnowledge({
320
345
  content: options.content,
321
346
  category: options.category,
322
347
  severity: options.severity,
323
348
  broadcastTo: options.broadcast,
349
+ specId: options.spec,
324
350
  });
325
351
  });
326
352
 
@@ -331,23 +357,26 @@ knowledgeCmd
331
357
  .option("--category <cat>", "Filtrar por categoria")
332
358
  .option("--severity <level>", "Filtrar por severidade (critical, warning, info)")
333
359
  .option("--json", "Saida em JSON")
360
+ .option("--spec <id>", "ID do spec (padrao: mais recente)")
334
361
  .action((options) => {
335
- listKnowledge(options);
362
+ listKnowledge({ ...options, specId: options.spec });
336
363
  });
337
364
 
338
365
  knowledgeCmd
339
366
  .command("ack <id>")
340
367
  .description("Marca knowledge como lido pela task atual")
341
- .action((id: string) => {
342
- acknowledgeKnowledge(id);
368
+ .option("--spec <id>", "ID do spec (padrao: mais recente)")
369
+ .action((id: string, options) => {
370
+ acknowledgeKnowledge(id, options.spec);
343
371
  });
344
372
 
345
373
  knowledgeCmd
346
374
  .command("resolve <ids>")
347
375
  .description("Resolve/reconhece knowledge item(s) critico(s)")
348
376
  .option("--resolution <text>", "Descricao de como o blocker foi resolvido")
349
- .action((ids: string, opts: { resolution?: string }) => {
350
- resolveKnowledge(ids, opts.resolution);
377
+ .option("--spec <id>", "ID do spec (padrao: mais recente)")
378
+ .action((ids: string, opts: { resolution?: string; spec?: string }) => {
379
+ resolveKnowledge(ids, opts.resolution, opts.spec);
351
380
  });
352
381
 
353
382
  knowledgeCmd
@@ -356,8 +385,19 @@ knowledgeCmd
356
385
  .option("--file <path>", "Buscar relacoes de um arquivo")
357
386
  .option("--decision <id>", "Buscar arquivos afetados por uma decisao")
358
387
  .option("--json", "Saida em JSON")
388
+ .option("--spec <id>", "ID do spec (padrao: mais recente)")
389
+ .action((options) => {
390
+ queryGraph({ ...options, specId: options.spec });
391
+ });
392
+
393
+ knowledgeCmd
394
+ .command("compact")
395
+ .description("Compacta knowledge (merge similares, arquivar antigos)")
396
+ .option("--spec <id>", "ID do spec (padrao: todos)")
397
+ .option("--dry-run", "Apenas mostrar o que seria compactado")
398
+ .option("--json", "Saida em JSON")
359
399
  .action((options) => {
360
- queryGraph(options);
400
+ compactKnowledge({ specId: options.spec, dryRun: options.dryRun, json: options.json });
361
401
  });
362
402
 
363
403
  // ═══════════════════════════════════════════════════════════════
@@ -370,22 +410,27 @@ reviewCmd
370
410
  .command("start")
371
411
  .description("Inicia o review")
372
412
  .option("--json", "Saida em JSON")
413
+ .option("--spec <id>", "ID do spec (padrao: mais recente)")
373
414
  .action((options) => {
374
- reviewStart(options.json);
415
+ reviewStart(options.json, options.spec);
375
416
  });
376
417
 
377
418
  reviewCmd
378
419
  .command("approve")
379
420
  .description("Aprova o review e finaliza a feature")
380
- .action(() => {
381
- reviewApprove();
421
+ .option("--spec <id>", "ID do spec (padrao: mais recente)")
422
+ .option("--force", "Aprovar mesmo com score baixo (<50)")
423
+ .option("--force-reason <reason>", "Motivo para aprovacao forcada")
424
+ .action((options) => {
425
+ reviewApprove({ specId: options.spec, force: options.force, forceReason: options.forceReason });
382
426
  });
383
427
 
384
428
  reviewCmd
385
429
  .command("skip")
386
430
  .description("Pula o review e finaliza a feature diretamente")
387
- .action(() => {
388
- reviewSkip();
431
+ .option("--spec <id>", "ID do spec (padrao: mais recente)")
432
+ .action((options) => {
433
+ reviewSkip(options.spec);
389
434
  });
390
435
 
391
436
  // ═══════════════════════════════════════════════════════════════
@@ -396,8 +441,9 @@ program
396
441
  .command("status")
397
442
  .description("Mostra status atual")
398
443
  .option("--json", "Saida em JSON")
444
+ .option("--spec <id>", "ID do spec (padrao: todos ativos)")
399
445
  .action((options) => {
400
- status(options.json);
446
+ status(options.json, options.spec);
401
447
  });
402
448
 
403
449
  const contextCmd = program.command("context").description("Comandos de contexto");
@@ -406,8 +452,9 @@ contextCmd
406
452
  .command("export")
407
453
  .description("Exporta contexto para subagent")
408
454
  .option("--task <id>", "ID da task especifica")
455
+ .option("--spec <id>", "ID do spec (padrao: mais recente)")
409
456
  .action((options) => {
410
- contextExport({ ...options, json: true }); // Sempre JSON
457
+ contextExport({ ...options, json: true, specId: options.spec }); // Sempre JSON
411
458
  });
412
459
 
413
460
  contextCmd
@@ -416,16 +463,18 @@ contextCmd
416
463
  .option("--approach <text>", "Adiciona nova abordagem descoberta")
417
464
  .option("--pattern <text>", "Registra padrao identificado no codigo")
418
465
  .option("--constraint <text>", "Adiciona nova limitacao encontrada")
466
+ .option("--spec <id>", "ID do spec (padrao: mais recente)")
419
467
  .action((options) => {
420
- contextUpdate(options);
468
+ contextUpdate({ ...options, specId: options.spec });
421
469
  });
422
470
 
423
471
  contextCmd
424
472
  .command("detail <section>")
425
473
  .description("Mostra secao especifica do contexto (standards, decisions, patterns, knowledge, architecture)")
426
474
  .option("--json", "Output JSON")
427
- .action((section: string, opts: { json?: boolean }) => {
428
- contextDetail(section, opts.json);
475
+ .option("--spec <id>", "ID do spec (padrao: mais recente)")
476
+ .action((section: string, opts: { json?: boolean; spec?: string }) => {
477
+ contextDetail(section, opts.json, opts.spec);
429
478
  });
430
479
 
431
480
  // Manter compatibilidade: context sem subcomando = export
@@ -433,8 +482,9 @@ program
433
482
  .command("ctx")
434
483
  .description("Alias para context export (compatibilidade)")
435
484
  .option("--task <id>", "ID da task especifica")
485
+ .option("--spec <id>", "ID do spec (padrao: mais recente)")
436
486
  .action((options) => {
437
- contextExport({ ...options, json: true });
487
+ contextExport({ ...options, json: true, specId: options.spec });
438
488
  });
439
489
 
440
490
  program
@@ -500,7 +550,7 @@ discoverCmd
500
550
  });
501
551
 
502
552
  discoverCmd
503
- .command("reset")
553
+ .command("reset", { hidden: true })
504
554
  .description("Reseta descoberta para refazer")
505
555
  .action(() => {
506
556
  discoverReset();
@@ -568,7 +618,7 @@ discoverCmd
568
618
  });
569
619
 
570
620
  discoverCmd
571
- .command("pattern-edit <name>")
621
+ .command("pattern-edit <name>", { hidden: true })
572
622
  .description("Edita um implementation pattern")
573
623
  .option("--category <cat>", "Nova categoria")
574
624
  .option("--scope <scope>", "Novo escopo")
@@ -618,7 +668,7 @@ discoverCmd
618
668
  });
619
669
 
620
670
  discoverCmd
621
- .command("analyze-file <path>")
671
+ .command("analyze-file <path>", { hidden: true })
622
672
  .description("Analisa estrutura de um arquivo (imports, exports, convencoes)")
623
673
  .option("--json", "Saida em JSON")
624
674
  .action((path, options) => {
@@ -627,7 +677,7 @@ discoverCmd
627
677
 
628
678
  // v9.0: Analise profunda com metadata enriquecida + grepai
629
679
  discoverCmd
630
- .command("analyze-deep <files...>")
680
+ .command("analyze-deep <files...>", { hidden: true })
631
681
  .description("Analise profunda de arquivos (hooks, patterns, directives)")
632
682
  .option("--json", "Saida em JSON")
633
683
  .action((files, options) => {
@@ -637,7 +687,7 @@ discoverCmd
637
687
 
638
688
  // v9.0: Anti-patterns de gate bypasses
639
689
  discoverCmd
640
- .command("extract-anti-patterns")
690
+ .command("extract-anti-patterns", { hidden: true })
641
691
  .description("Extrai anti-patterns do historico de gate bypasses")
642
692
  .action(() => {
643
693
  const { extractAntiPatternsFromHistory } = require("./commands/patterns");
@@ -645,7 +695,7 @@ discoverCmd
645
695
  });
646
696
 
647
697
  discoverCmd
648
- .command("export-patterns")
698
+ .command("export-patterns", { hidden: true })
649
699
  .description("Regenera arquivo patterns.md")
650
700
  .action(() => {
651
701
  discoverExportPatterns();
@@ -863,11 +913,12 @@ program
863
913
  .description("Limpa tasks/features mantendo configuracoes do projeto (standards, patterns, PRD)")
864
914
  .option("--force", "Confirma a limpeza (sem isso apenas mostra o que sera removido)")
865
915
  .option("--show", "Mostra estado atual dos arquivos do workflow")
916
+ .option("--spec <id>", "Limpa apenas o spec especificado")
866
917
  .action((options) => {
867
918
  if (options.show) {
868
919
  clearShow();
869
920
  } else {
870
- clearTasks({ force: options.force });
921
+ clearTasks({ force: options.force, specId: options.spec });
871
922
  }
872
923
  });
873
924