@codexa/cli 9.0.31 → 9.0.33
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/architect.ts +52 -87
- package/commands/check.ts +22 -23
- package/commands/clear.ts +42 -48
- package/commands/decide.ts +46 -44
- package/commands/discover.ts +81 -94
- package/commands/integration.test.ts +262 -313
- package/commands/knowledge.test.ts +56 -61
- package/commands/knowledge.ts +126 -131
- package/commands/patterns.ts +28 -43
- package/commands/plan.ts +50 -48
- package/commands/product.ts +57 -59
- package/commands/research.ts +64 -77
- package/commands/review.ts +100 -86
- package/commands/simplify.ts +24 -35
- package/commands/spec-resolver.test.ts +52 -48
- package/commands/spec-resolver.ts +21 -23
- package/commands/standards.ts +20 -27
- package/commands/sync.ts +2 -8
- package/commands/task.ts +106 -97
- package/commands/team.test.ts +22 -83
- package/commands/team.ts +62 -50
- package/commands/utils.ts +83 -81
- package/context/assembly.ts +0 -1
- package/context/generator.ts +66 -79
- package/context/sections.ts +8 -14
- package/db/connection.ts +209 -19
- package/db/schema.test.ts +288 -299
- package/db/schema.ts +298 -394
- package/db/test-helpers.ts +18 -29
- package/gates/standards-validator.test.ts +83 -86
- package/gates/standards-validator.ts +9 -41
- package/gates/validator.test.ts +13 -22
- package/gates/validator.ts +69 -107
- package/package.json +2 -1
- package/protocol/process-return.ts +41 -57
- package/simplify/prompt-builder.test.ts +44 -42
- package/simplify/prompt-builder.ts +12 -14
- package/workflow.ts +159 -174
package/commands/decide.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { dbGet, dbAll, dbRun } from "../db/connection";
|
|
2
2
|
import { initSchema, getNextDecisionId } from "../db/schema";
|
|
3
3
|
import { resolveSpec } from "./spec-resolver";
|
|
4
4
|
import { CodexaError } from "../errors";
|
|
@@ -137,18 +137,18 @@ export function detectConflicts(
|
|
|
137
137
|
};
|
|
138
138
|
}
|
|
139
139
|
|
|
140
|
-
export function decide(title: string, decision: string, options: { rationale?: string; force?: boolean; specId?: string }): void {
|
|
141
|
-
initSchema();
|
|
140
|
+
export async function decide(title: string, decision: string, options: { rationale?: string; force?: boolean; specId?: string }): Promise<void> {
|
|
141
|
+
await initSchema();
|
|
142
142
|
|
|
143
|
-
const db = getDb();
|
|
144
143
|
const now = new Date().toISOString();
|
|
145
144
|
|
|
146
145
|
const spec = resolveSpec(options.specId);
|
|
147
146
|
|
|
148
147
|
// Verificar conflitos com decisoes existentes
|
|
149
|
-
const existingDecisions =
|
|
150
|
-
|
|
151
|
-
|
|
148
|
+
const existingDecisions = await dbAll<any>(
|
|
149
|
+
"SELECT * FROM decisions WHERE spec_id = ? AND status = 'active'",
|
|
150
|
+
[spec.id]
|
|
151
|
+
);
|
|
152
152
|
|
|
153
153
|
if (existingDecisions.length > 0 && !options.force) {
|
|
154
154
|
const analysis = detectConflicts(title, decision, existingDecisions);
|
|
@@ -172,16 +172,17 @@ export function decide(title: string, decision: string, options: { rationale?: s
|
|
|
172
172
|
}
|
|
173
173
|
|
|
174
174
|
// Pegar task atual em execucao
|
|
175
|
-
const currentTask =
|
|
176
|
-
|
|
177
|
-
|
|
175
|
+
const currentTask = await dbGet<any>(
|
|
176
|
+
"SELECT * FROM tasks WHERE spec_id = ? AND status = 'running' LIMIT 1",
|
|
177
|
+
[spec.id]
|
|
178
|
+
);
|
|
178
179
|
|
|
179
180
|
let decisionId = "";
|
|
180
181
|
let retries = 3;
|
|
181
182
|
while (retries > 0) {
|
|
182
|
-
decisionId = getNextDecisionId(spec.id);
|
|
183
|
+
decisionId = await getNextDecisionId(spec.id);
|
|
183
184
|
try {
|
|
184
|
-
|
|
185
|
+
await dbRun(
|
|
185
186
|
`INSERT INTO decisions (id, spec_id, task_ref, title, decision, rationale, status, created_at)
|
|
186
187
|
VALUES (?, ?, ?, ?, ?, ?, 'active', ?)`,
|
|
187
188
|
[
|
|
@@ -213,16 +214,15 @@ export function decide(title: string, decision: string, options: { rationale?: s
|
|
|
213
214
|
console.log();
|
|
214
215
|
}
|
|
215
216
|
|
|
216
|
-
export function listDecisions(json: boolean = false, specId?: string): void {
|
|
217
|
-
initSchema();
|
|
218
|
-
|
|
219
|
-
const db = getDb();
|
|
217
|
+
export async function listDecisions(json: boolean = false, specId?: string): Promise<void> {
|
|
218
|
+
await initSchema();
|
|
220
219
|
|
|
221
220
|
const spec = resolveSpec(specId);
|
|
222
221
|
|
|
223
|
-
const decisions =
|
|
224
|
-
|
|
225
|
-
|
|
222
|
+
const decisions = await dbAll<any>(
|
|
223
|
+
"SELECT * FROM decisions WHERE spec_id = ? ORDER BY created_at",
|
|
224
|
+
[spec.id]
|
|
225
|
+
);
|
|
226
226
|
|
|
227
227
|
if (json) {
|
|
228
228
|
console.log(JSON.stringify({ decisions }));
|
|
@@ -247,14 +247,14 @@ export function listDecisions(json: boolean = false, specId?: string): void {
|
|
|
247
247
|
}
|
|
248
248
|
}
|
|
249
249
|
|
|
250
|
-
export function revokeDecision(decisionId: string, reason?: string, specId?: string): void {
|
|
251
|
-
initSchema();
|
|
252
|
-
const db = getDb();
|
|
250
|
+
export async function revokeDecision(decisionId: string, reason?: string, specId?: string): Promise<void> {
|
|
251
|
+
await initSchema();
|
|
253
252
|
const spec = resolveSpec(specId);
|
|
254
253
|
|
|
255
|
-
const decision =
|
|
256
|
-
|
|
257
|
-
|
|
254
|
+
const decision = await dbGet<any>(
|
|
255
|
+
"SELECT * FROM decisions WHERE id = ? AND spec_id = ?",
|
|
256
|
+
[decisionId, spec.id]
|
|
257
|
+
);
|
|
258
258
|
|
|
259
259
|
if (!decision) {
|
|
260
260
|
throw new CodexaError(`Decisao '${decisionId}' nao encontrada no spec '${spec.id}'.`);
|
|
@@ -266,14 +266,15 @@ export function revokeDecision(decisionId: string, reason?: string, specId?: str
|
|
|
266
266
|
|
|
267
267
|
const now = new Date().toISOString();
|
|
268
268
|
|
|
269
|
-
|
|
269
|
+
await dbRun("UPDATE decisions SET status = 'revoked' WHERE id = ?", [decisionId]);
|
|
270
270
|
|
|
271
271
|
// Registrar como knowledge para subagentes saberem da revogacao
|
|
272
|
-
const currentTask =
|
|
273
|
-
|
|
274
|
-
|
|
272
|
+
const currentTask = await dbGet<any>(
|
|
273
|
+
"SELECT * FROM tasks WHERE spec_id = ? AND status = 'running' LIMIT 1",
|
|
274
|
+
[spec.id]
|
|
275
|
+
);
|
|
275
276
|
|
|
276
|
-
|
|
277
|
+
await dbRun(
|
|
277
278
|
`INSERT INTO knowledge (spec_id, task_origin, category, content, severity, broadcast_to, created_at)
|
|
278
279
|
VALUES (?, ?, 'decision', ?, 'warning', 'all', ?)`,
|
|
279
280
|
[
|
|
@@ -290,19 +291,19 @@ export function revokeDecision(decisionId: string, reason?: string, specId?: str
|
|
|
290
291
|
console.log();
|
|
291
292
|
}
|
|
292
293
|
|
|
293
|
-
export function supersedeDecision(
|
|
294
|
+
export async function supersedeDecision(
|
|
294
295
|
oldDecisionId: string,
|
|
295
296
|
newTitle: string,
|
|
296
297
|
newDecision: string,
|
|
297
298
|
options: { rationale?: string; specId?: string }
|
|
298
|
-
): void {
|
|
299
|
-
initSchema();
|
|
300
|
-
const db = getDb();
|
|
299
|
+
): Promise<void> {
|
|
300
|
+
await initSchema();
|
|
301
301
|
const spec = resolveSpec(options.specId);
|
|
302
302
|
|
|
303
|
-
const oldDec =
|
|
304
|
-
|
|
305
|
-
|
|
303
|
+
const oldDec = await dbGet<any>(
|
|
304
|
+
"SELECT * FROM decisions WHERE id = ? AND spec_id = ?",
|
|
305
|
+
[oldDecisionId, spec.id]
|
|
306
|
+
);
|
|
306
307
|
|
|
307
308
|
if (!oldDec) {
|
|
308
309
|
throw new CodexaError(`Decisao '${oldDecisionId}' nao encontrada no spec '${spec.id}'.`);
|
|
@@ -313,17 +314,18 @@ export function supersedeDecision(
|
|
|
313
314
|
}
|
|
314
315
|
|
|
315
316
|
const now = new Date().toISOString();
|
|
316
|
-
const currentTask =
|
|
317
|
-
|
|
318
|
-
|
|
317
|
+
const currentTask = await dbGet<any>(
|
|
318
|
+
"SELECT * FROM tasks WHERE spec_id = ? AND status = 'running' LIMIT 1",
|
|
319
|
+
[spec.id]
|
|
320
|
+
);
|
|
319
321
|
|
|
320
322
|
// Criar nova decisao (com retry para colisao de ID)
|
|
321
323
|
let newDecisionId = "";
|
|
322
324
|
let retries = 3;
|
|
323
325
|
while (retries > 0) {
|
|
324
|
-
newDecisionId = getNextDecisionId(spec.id);
|
|
326
|
+
newDecisionId = await getNextDecisionId(spec.id);
|
|
325
327
|
try {
|
|
326
|
-
|
|
328
|
+
await dbRun(
|
|
327
329
|
`INSERT INTO decisions (id, spec_id, task_ref, title, decision, rationale, status, created_at)
|
|
328
330
|
VALUES (?, ?, ?, ?, ?, ?, 'active', ?)`,
|
|
329
331
|
[newDecisionId, spec.id, currentTask?.number || null, newTitle, newDecision, options.rationale || null, now]
|
|
@@ -339,13 +341,13 @@ export function supersedeDecision(
|
|
|
339
341
|
}
|
|
340
342
|
|
|
341
343
|
// Marcar antiga como superseded
|
|
342
|
-
|
|
344
|
+
await dbRun(
|
|
343
345
|
"UPDATE decisions SET status = 'superseded' WHERE id = ?",
|
|
344
346
|
[oldDecisionId]
|
|
345
347
|
);
|
|
346
348
|
|
|
347
349
|
// Registrar como knowledge
|
|
348
|
-
|
|
350
|
+
await dbRun(
|
|
349
351
|
`INSERT INTO knowledge (spec_id, task_origin, category, content, severity, broadcast_to, created_at)
|
|
350
352
|
VALUES (?, ?, 'decision', ?, 'warning', 'all', ?)`,
|
|
351
353
|
[
|
package/commands/discover.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { dbGet, dbAll, dbRun } from "../db/connection";
|
|
2
2
|
import { initSchema } from "../db/schema";
|
|
3
3
|
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "fs";
|
|
4
4
|
import { join } from "path";
|
|
@@ -76,11 +76,10 @@ async function detectFull(): Promise<UnifiedDetectionResult> {
|
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
export async function discoverStart(json: boolean = false): Promise<void> {
|
|
79
|
-
initSchema();
|
|
80
|
-
const db = getDb();
|
|
79
|
+
await initSchema();
|
|
81
80
|
|
|
82
81
|
// Verificar se ja foi descoberto
|
|
83
|
-
const existing =
|
|
82
|
+
const existing = await dbGet("SELECT * FROM project WHERE id = 'default'", ["default"]);
|
|
84
83
|
if (existing) {
|
|
85
84
|
console.log("\nProjeto ja foi descoberto.");
|
|
86
85
|
console.log("Use: discover show para ver detalhes");
|
|
@@ -151,7 +150,7 @@ export async function discoverStart(json: boolean = false): Promise<void> {
|
|
|
151
150
|
|
|
152
151
|
// Salvar temporariamente para confirm poder usar
|
|
153
152
|
// Include extended info for richer context
|
|
154
|
-
|
|
153
|
+
await dbRun(
|
|
155
154
|
`INSERT OR REPLACE INTO project (id, name, stack, discovered_at, updated_at)
|
|
156
155
|
VALUES ('pending', 'pending', ?, datetime('now'), datetime('now'))`,
|
|
157
156
|
[JSON.stringify({
|
|
@@ -168,11 +167,10 @@ export async function discoverStart(json: boolean = false): Promise<void> {
|
|
|
168
167
|
);
|
|
169
168
|
}
|
|
170
169
|
|
|
171
|
-
export function discoverConfirm(): void {
|
|
172
|
-
initSchema();
|
|
173
|
-
const db = getDb();
|
|
170
|
+
export async function discoverConfirm(): Promise<void> {
|
|
171
|
+
await initSchema();
|
|
174
172
|
|
|
175
|
-
const pending =
|
|
173
|
+
const pending = await dbGet<any>("SELECT * FROM project WHERE id = 'pending'", ["pending"]);
|
|
176
174
|
if (!pending) {
|
|
177
175
|
throw new CodexaError("Nenhuma descoberta pendente.\nExecute: discover start primeiro");
|
|
178
176
|
}
|
|
@@ -181,8 +179,8 @@ export function discoverConfirm(): void {
|
|
|
181
179
|
const now = new Date().toISOString();
|
|
182
180
|
|
|
183
181
|
// Mover de pending para default
|
|
184
|
-
|
|
185
|
-
|
|
182
|
+
await dbRun("DELETE FROM project WHERE id = 'pending'", ["pending"]);
|
|
183
|
+
await dbRun(
|
|
186
184
|
`INSERT INTO project (id, name, stack, discovered_at, updated_at, cli_version, last_discover_at)
|
|
187
185
|
VALUES ('default', ?, ?, ?, ?, ?, ?)`,
|
|
188
186
|
["Projeto", JSON.stringify(data.stack), now, now, pkg.version, now]
|
|
@@ -192,7 +190,7 @@ export function discoverConfirm(): void {
|
|
|
192
190
|
const structure = data.structure as StructureDetection;
|
|
193
191
|
|
|
194
192
|
if (structure.components) {
|
|
195
|
-
|
|
193
|
+
await dbRun(
|
|
196
194
|
`INSERT INTO standards (category, scope, rule, examples, semantic_query, expect, source, created_at)
|
|
197
195
|
VALUES ('structure', 'frontend', ?, ?, ?, 'no_match', 'detected', ?)`,
|
|
198
196
|
[
|
|
@@ -205,7 +203,7 @@ export function discoverConfirm(): void {
|
|
|
205
203
|
}
|
|
206
204
|
|
|
207
205
|
if (structure.services) {
|
|
208
|
-
|
|
206
|
+
await dbRun(
|
|
209
207
|
`INSERT INTO standards (category, scope, rule, examples, semantic_query, expect, source, created_at)
|
|
210
208
|
VALUES ('structure', 'backend', ?, ?, ?, 'no_match', 'detected', ?)`,
|
|
211
209
|
[
|
|
@@ -218,7 +216,7 @@ export function discoverConfirm(): void {
|
|
|
218
216
|
}
|
|
219
217
|
|
|
220
218
|
if (structure.schema) {
|
|
221
|
-
|
|
219
|
+
await dbRun(
|
|
222
220
|
`INSERT INTO standards (category, scope, rule, examples, semantic_query, expect, source, created_at)
|
|
223
221
|
VALUES ('structure', 'database', ?, ?, ?, 'no_match', 'detected', ?)`,
|
|
224
222
|
[
|
|
@@ -231,7 +229,7 @@ export function discoverConfirm(): void {
|
|
|
231
229
|
}
|
|
232
230
|
|
|
233
231
|
if (structure.types) {
|
|
234
|
-
|
|
232
|
+
await dbRun(
|
|
235
233
|
`INSERT INTO standards (category, scope, rule, examples, semantic_query, expect, source, created_at)
|
|
236
234
|
VALUES ('structure', 'all', ?, ?, ?, 'no_match', 'detected', ?)`,
|
|
237
235
|
[
|
|
@@ -244,7 +242,7 @@ export function discoverConfirm(): void {
|
|
|
244
242
|
}
|
|
245
243
|
|
|
246
244
|
// Standards de nomenclatura padrao (sem semantic_query — grepai busca conteudo, nao nomes de arquivo)
|
|
247
|
-
|
|
245
|
+
await dbRun(
|
|
248
246
|
`INSERT INTO standards (category, scope, rule, examples, anti_examples, source, created_at)
|
|
249
247
|
VALUES ('naming', 'frontend', ?, ?, ?, 'detected', ?)`,
|
|
250
248
|
[
|
|
@@ -255,7 +253,7 @@ export function discoverConfirm(): void {
|
|
|
255
253
|
]
|
|
256
254
|
);
|
|
257
255
|
|
|
258
|
-
|
|
256
|
+
await dbRun(
|
|
259
257
|
`INSERT INTO standards (category, scope, rule, examples, anti_examples, source, created_at)
|
|
260
258
|
VALUES ('naming', 'backend', ?, ?, ?, 'detected', ?)`,
|
|
261
259
|
[
|
|
@@ -267,9 +265,10 @@ export function discoverConfirm(): void {
|
|
|
267
265
|
);
|
|
268
266
|
|
|
269
267
|
// Gerar arquivo standards.md
|
|
270
|
-
generateStandardsMarkdown();
|
|
268
|
+
await generateStandardsMarkdown();
|
|
271
269
|
|
|
272
|
-
const
|
|
270
|
+
const standardsRow = await dbGet<any>("SELECT COUNT(*) as c FROM standards", []);
|
|
271
|
+
const standardsCount = standardsRow?.c ?? 0;
|
|
273
272
|
|
|
274
273
|
// Auto-setup: deep-explore agent
|
|
275
274
|
ensureDeepExploreAgent();
|
|
@@ -285,7 +284,7 @@ export function discoverConfirm(): void {
|
|
|
285
284
|
}
|
|
286
285
|
|
|
287
286
|
console.log("\nProjeto descoberto e configurado!");
|
|
288
|
-
console.log(`Standards criados: ${standardsCount
|
|
287
|
+
console.log(`Standards criados: ${standardsCount}`);
|
|
289
288
|
if (semanticCount > 0) {
|
|
290
289
|
console.log(`Patterns semanticos detectados: ${semanticCount}`);
|
|
291
290
|
}
|
|
@@ -293,17 +292,16 @@ export function discoverConfirm(): void {
|
|
|
293
292
|
console.log("\nProximo passo: /codexa:feature para iniciar uma feature\n");
|
|
294
293
|
}
|
|
295
294
|
|
|
296
|
-
export function discoverShow(json: boolean = false): void {
|
|
297
|
-
initSchema();
|
|
298
|
-
const db = getDb();
|
|
295
|
+
export async function discoverShow(json: boolean = false): Promise<void> {
|
|
296
|
+
await initSchema();
|
|
299
297
|
|
|
300
|
-
const project =
|
|
298
|
+
const project = await dbGet<any>("SELECT * FROM project WHERE id = 'default'", ["default"]);
|
|
301
299
|
|
|
302
300
|
if (!project) {
|
|
303
301
|
throw new CodexaError("Projeto nao descoberto.\nExecute: discover start");
|
|
304
302
|
}
|
|
305
303
|
|
|
306
|
-
const standards =
|
|
304
|
+
const standards = await dbAll<any>("SELECT * FROM standards ORDER BY category, scope", []);
|
|
307
305
|
const stack = JSON.parse(project.stack);
|
|
308
306
|
|
|
309
307
|
if (json) {
|
|
@@ -336,7 +334,7 @@ export function discoverShow(json: boolean = false): void {
|
|
|
336
334
|
console.log("Arquivo: .codexa/standards.md\n");
|
|
337
335
|
}
|
|
338
336
|
|
|
339
|
-
export function discoverSetStack(options: {
|
|
337
|
+
export async function discoverSetStack(options: {
|
|
340
338
|
frontend?: string;
|
|
341
339
|
backend?: string;
|
|
342
340
|
database?: string;
|
|
@@ -344,11 +342,10 @@ export function discoverSetStack(options: {
|
|
|
344
342
|
styling?: string;
|
|
345
343
|
auth?: string;
|
|
346
344
|
testing?: string;
|
|
347
|
-
}): void {
|
|
348
|
-
initSchema();
|
|
349
|
-
const db = getDb();
|
|
345
|
+
}): Promise<void> {
|
|
346
|
+
await initSchema();
|
|
350
347
|
|
|
351
|
-
|
|
348
|
+
const pending = await dbGet<any>("SELECT * FROM project WHERE id = 'pending'", ["pending"]);
|
|
352
349
|
let data: any;
|
|
353
350
|
|
|
354
351
|
if (pending) {
|
|
@@ -366,7 +363,7 @@ export function discoverSetStack(options: {
|
|
|
366
363
|
if (options.auth) data.stack.auth = options.auth;
|
|
367
364
|
if (options.testing) data.stack.testing = options.testing;
|
|
368
365
|
|
|
369
|
-
|
|
366
|
+
await dbRun(
|
|
370
367
|
`INSERT OR REPLACE INTO project (id, name, stack, discovered_at, updated_at)
|
|
371
368
|
VALUES ('pending', 'pending', ?, datetime('now'), datetime('now'))`,
|
|
372
369
|
[JSON.stringify(data)]
|
|
@@ -379,22 +376,20 @@ export function discoverSetStack(options: {
|
|
|
379
376
|
console.log("\nPara confirmar: discover confirm\n");
|
|
380
377
|
}
|
|
381
378
|
|
|
382
|
-
export function discoverReset(): void {
|
|
383
|
-
initSchema();
|
|
384
|
-
const db = getDb();
|
|
379
|
+
export async function discoverReset(): Promise<void> {
|
|
380
|
+
await initSchema();
|
|
385
381
|
|
|
386
|
-
|
|
387
|
-
|
|
382
|
+
await dbRun("DELETE FROM project");
|
|
383
|
+
await dbRun("DELETE FROM standards");
|
|
388
384
|
|
|
389
385
|
console.log("\nDescoberta resetada.");
|
|
390
386
|
console.log("Execute: discover start para refazer\n");
|
|
391
387
|
}
|
|
392
388
|
|
|
393
389
|
export async function discoverRefresh(options: { force?: boolean } = {}): Promise<void> {
|
|
394
|
-
initSchema();
|
|
395
|
-
const db = getDb();
|
|
390
|
+
await initSchema();
|
|
396
391
|
|
|
397
|
-
const currentProject =
|
|
392
|
+
const currentProject = await dbGet<any>("SELECT * FROM project WHERE id = 'default'", ["default"]);
|
|
398
393
|
if (!currentProject) {
|
|
399
394
|
throw new CodexaError("Projeto nao descoberto.\nExecute: discover start primeiro");
|
|
400
395
|
}
|
|
@@ -434,7 +429,7 @@ export async function discoverRefresh(options: { force?: boolean } = {}): Promis
|
|
|
434
429
|
// Aplicar mudanças
|
|
435
430
|
const now = new Date().toISOString();
|
|
436
431
|
|
|
437
|
-
|
|
432
|
+
await dbRun(
|
|
438
433
|
`UPDATE project SET stack = ?, updated_at = ? WHERE id = 'default'`,
|
|
439
434
|
[JSON.stringify(newStack), now]
|
|
440
435
|
);
|
|
@@ -443,17 +438,18 @@ export async function discoverRefresh(options: { force?: boolean } = {}): Promis
|
|
|
443
438
|
for (const change of stackChanges) {
|
|
444
439
|
if (change.to) {
|
|
445
440
|
// Adicionar ou atualizar standard de stack
|
|
446
|
-
const existing =
|
|
447
|
-
`SELECT id FROM standards WHERE category = 'stack' AND rule LIKE
|
|
448
|
-
|
|
441
|
+
const existing = await dbGet<any>(
|
|
442
|
+
`SELECT id FROM standards WHERE category = 'stack' AND rule LIKE ?`,
|
|
443
|
+
[`%${change.key}%`]
|
|
444
|
+
);
|
|
449
445
|
|
|
450
446
|
if (existing) {
|
|
451
|
-
|
|
447
|
+
await dbRun(
|
|
452
448
|
`UPDATE standards SET rule = ?, updated_at = ? WHERE id = ?`,
|
|
453
449
|
[`${change.key}: ${change.to}`, now, existing.id]
|
|
454
450
|
);
|
|
455
451
|
} else {
|
|
456
|
-
|
|
452
|
+
await dbRun(
|
|
457
453
|
`INSERT INTO standards (category, scope, rule, enforcement, source, created_at)
|
|
458
454
|
VALUES ('stack', 'all', ?, 'required', 'refresh', ?)`,
|
|
459
455
|
[`${change.key}: ${change.to}`, now]
|
|
@@ -463,7 +459,7 @@ export async function discoverRefresh(options: { force?: boolean } = {}): Promis
|
|
|
463
459
|
}
|
|
464
460
|
|
|
465
461
|
// Regenerar standards.md
|
|
466
|
-
generateStandardsMarkdown();
|
|
462
|
+
await generateStandardsMarkdown();
|
|
467
463
|
|
|
468
464
|
console.log("\n✓ Stack atualizado com sucesso!");
|
|
469
465
|
console.log("✓ Standards regenerados\n");
|
|
@@ -474,10 +470,9 @@ export async function discoverRefresh(options: { force?: boolean } = {}): Promis
|
|
|
474
470
|
}
|
|
475
471
|
|
|
476
472
|
export async function discoverIncremental(): Promise<void> {
|
|
477
|
-
initSchema();
|
|
478
|
-
const db = getDb();
|
|
473
|
+
await initSchema();
|
|
479
474
|
|
|
480
|
-
const project =
|
|
475
|
+
const project = await dbGet<any>("SELECT * FROM project WHERE id = 'default'", ["default"]);
|
|
481
476
|
if (!project) {
|
|
482
477
|
throw new CodexaError("Projeto nao descoberto.\nExecute: discover start primeiro");
|
|
483
478
|
}
|
|
@@ -521,7 +516,7 @@ export async function discoverIncremental(): Promise<void> {
|
|
|
521
516
|
|
|
522
517
|
// Atualizar timestamp mesmo sem mudancas
|
|
523
518
|
const now = new Date().toISOString();
|
|
524
|
-
|
|
519
|
+
await dbRun("UPDATE project SET last_discover_at = ? WHERE id = 'default'", [now]);
|
|
525
520
|
return;
|
|
526
521
|
}
|
|
527
522
|
|
|
@@ -539,7 +534,7 @@ export async function discoverIncremental(): Promise<void> {
|
|
|
539
534
|
const scope = inferScopeFromPath(file);
|
|
540
535
|
|
|
541
536
|
for (const util of utilities) {
|
|
542
|
-
upsertUtility({
|
|
537
|
+
await upsertUtility({
|
|
543
538
|
filePath: file,
|
|
544
539
|
utilityName: util.name,
|
|
545
540
|
utilityType: util.type,
|
|
@@ -583,7 +578,7 @@ export async function discoverIncremental(): Promise<void> {
|
|
|
583
578
|
// Atualizar timestamp
|
|
584
579
|
console.log("\n[3/3] Atualizando timestamp...");
|
|
585
580
|
const now = new Date().toISOString();
|
|
586
|
-
|
|
581
|
+
await dbRun("UPDATE project SET last_discover_at = ?, updated_at = ? WHERE id = 'default'", [now, now]);
|
|
587
582
|
|
|
588
583
|
// Resumo
|
|
589
584
|
console.log("\n" + "═".repeat(50));
|
|
@@ -596,10 +591,9 @@ export async function discoverIncremental(): Promise<void> {
|
|
|
596
591
|
console.log("═".repeat(50) + "\n");
|
|
597
592
|
}
|
|
598
593
|
|
|
599
|
-
function generateStandardsMarkdown(): void {
|
|
600
|
-
const
|
|
601
|
-
const
|
|
602
|
-
const standards = db.query("SELECT * FROM standards ORDER BY category, scope").all() as any[];
|
|
594
|
+
async function generateStandardsMarkdown(): Promise<void> {
|
|
595
|
+
const project = await dbGet<any>("SELECT * FROM project WHERE id = 'default'", ["default"]);
|
|
596
|
+
const standards = await dbAll<any>("SELECT * FROM standards ORDER BY category, scope", []);
|
|
603
597
|
|
|
604
598
|
if (!project) return;
|
|
605
599
|
|
|
@@ -716,9 +710,8 @@ interface ImplementationPattern {
|
|
|
716
710
|
extracted_from: number;
|
|
717
711
|
}
|
|
718
712
|
|
|
719
|
-
export function discoverPatterns(options: { category?: string; json?: boolean } = {}): void {
|
|
720
|
-
initSchema();
|
|
721
|
-
const db = getDb();
|
|
713
|
+
export async function discoverPatterns(options: { category?: string; json?: boolean } = {}): Promise<void> {
|
|
714
|
+
await initSchema();
|
|
722
715
|
|
|
723
716
|
let query = "SELECT * FROM implementation_patterns";
|
|
724
717
|
const params: string[] = [];
|
|
@@ -730,7 +723,7 @@ export function discoverPatterns(options: { category?: string; json?: boolean }
|
|
|
730
723
|
|
|
731
724
|
query += " ORDER BY category, name";
|
|
732
725
|
|
|
733
|
-
const patterns =
|
|
726
|
+
const patterns = await dbAll<any>(query, params);
|
|
734
727
|
|
|
735
728
|
if (patterns.length === 0) {
|
|
736
729
|
console.log("\nNenhum pattern extraido ainda.");
|
|
@@ -783,11 +776,10 @@ export function discoverPatterns(options: { category?: string; json?: boolean }
|
|
|
783
776
|
console.log("Para exportar: discover export-patterns\n");
|
|
784
777
|
}
|
|
785
778
|
|
|
786
|
-
export function discoverPatternsShow(name: string, json: boolean = false): void {
|
|
787
|
-
initSchema();
|
|
788
|
-
const db = getDb();
|
|
779
|
+
export async function discoverPatternsShow(name: string, json: boolean = false): Promise<void> {
|
|
780
|
+
await initSchema();
|
|
789
781
|
|
|
790
|
-
const pattern =
|
|
782
|
+
const pattern = await dbGet<any>("SELECT * FROM implementation_patterns WHERE name = ?", [name]);
|
|
791
783
|
|
|
792
784
|
if (!pattern) {
|
|
793
785
|
throw new CodexaError(`Pattern '${name}' nao encontrado.\nUse: discover patterns para listar todos`);
|
|
@@ -872,7 +864,7 @@ export function discoverPatternsShow(name: string, json: boolean = false): void
|
|
|
872
864
|
console.log("\n");
|
|
873
865
|
}
|
|
874
866
|
|
|
875
|
-
export function discoverPatternAdd(options: {
|
|
867
|
+
export async function discoverPatternAdd(options: {
|
|
876
868
|
category: string;
|
|
877
869
|
name: string;
|
|
878
870
|
scope: string;
|
|
@@ -883,19 +875,18 @@ export function discoverPatternAdd(options: {
|
|
|
883
875
|
antiPatterns?: string;
|
|
884
876
|
confidence?: number;
|
|
885
877
|
extractedFrom?: number;
|
|
886
|
-
}): void {
|
|
887
|
-
initSchema();
|
|
888
|
-
const db = getDb();
|
|
878
|
+
}): Promise<void> {
|
|
879
|
+
await initSchema();
|
|
889
880
|
|
|
890
881
|
// Verificar se pattern ja existe
|
|
891
|
-
const existing =
|
|
882
|
+
const existing = await dbGet("SELECT id FROM implementation_patterns WHERE name = ?", [options.name]);
|
|
892
883
|
if (existing) {
|
|
893
884
|
throw new CodexaError(`Pattern '${options.name}' ja existe.\nUse: discover pattern-edit para modificar`);
|
|
894
885
|
}
|
|
895
886
|
|
|
896
887
|
const now = new Date().toISOString();
|
|
897
888
|
|
|
898
|
-
|
|
889
|
+
await dbRun(
|
|
899
890
|
`INSERT INTO implementation_patterns
|
|
900
891
|
(category, name, scope, applies_to, structure, template, examples, anti_patterns, confidence, extracted_from, created_at, updated_at)
|
|
901
892
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
@@ -916,13 +907,13 @@ export function discoverPatternAdd(options: {
|
|
|
916
907
|
);
|
|
917
908
|
|
|
918
909
|
// Regenerar patterns.md
|
|
919
|
-
generatePatternsMarkdown();
|
|
910
|
+
await generatePatternsMarkdown();
|
|
920
911
|
|
|
921
912
|
console.log(`\n✓ Pattern '${options.name}' adicionado com sucesso!`);
|
|
922
913
|
console.log("Arquivo atualizado: .codexa/patterns.md\n");
|
|
923
914
|
}
|
|
924
915
|
|
|
925
|
-
export function discoverPatternEdit(name: string, options: {
|
|
916
|
+
export async function discoverPatternEdit(name: string, options: {
|
|
926
917
|
category?: string;
|
|
927
918
|
scope?: string;
|
|
928
919
|
appliesTo?: string;
|
|
@@ -931,11 +922,10 @@ export function discoverPatternEdit(name: string, options: {
|
|
|
931
922
|
examples?: string;
|
|
932
923
|
antiPatterns?: string;
|
|
933
924
|
confidence?: number;
|
|
934
|
-
}): void {
|
|
935
|
-
initSchema();
|
|
936
|
-
const db = getDb();
|
|
925
|
+
}): Promise<void> {
|
|
926
|
+
await initSchema();
|
|
937
927
|
|
|
938
|
-
const existing =
|
|
928
|
+
const existing = await dbGet<any>("SELECT * FROM implementation_patterns WHERE name = ?", [name]);
|
|
939
929
|
if (!existing) {
|
|
940
930
|
throw new CodexaError(`Pattern '${name}' nao encontrado.\nUse: discover patterns para listar todos`);
|
|
941
931
|
}
|
|
@@ -984,42 +974,40 @@ export function discoverPatternEdit(name: string, options: {
|
|
|
984
974
|
params.push(new Date().toISOString());
|
|
985
975
|
params.push(name);
|
|
986
976
|
|
|
987
|
-
|
|
977
|
+
await dbRun(
|
|
988
978
|
`UPDATE implementation_patterns SET ${updates.join(", ")} WHERE name = ?`,
|
|
989
979
|
params
|
|
990
980
|
);
|
|
991
981
|
|
|
992
982
|
// Regenerar patterns.md
|
|
993
|
-
generatePatternsMarkdown();
|
|
983
|
+
await generatePatternsMarkdown();
|
|
994
984
|
|
|
995
985
|
console.log(`\n✓ Pattern '${name}' atualizado com sucesso!`);
|
|
996
986
|
console.log("Arquivo atualizado: .codexa/patterns.md\n");
|
|
997
987
|
}
|
|
998
988
|
|
|
999
|
-
export function discoverPatternRemove(name: string): void {
|
|
1000
|
-
initSchema();
|
|
1001
|
-
const db = getDb();
|
|
989
|
+
export async function discoverPatternRemove(name: string): Promise<void> {
|
|
990
|
+
await initSchema();
|
|
1002
991
|
|
|
1003
|
-
const existing =
|
|
992
|
+
const existing = await dbGet("SELECT id FROM implementation_patterns WHERE name = ?", [name]);
|
|
1004
993
|
if (!existing) {
|
|
1005
994
|
throw new CodexaError(`Pattern '${name}' nao encontrado.`);
|
|
1006
995
|
}
|
|
1007
996
|
|
|
1008
|
-
|
|
997
|
+
await dbRun("DELETE FROM implementation_patterns WHERE name = ?", [name]);
|
|
1009
998
|
|
|
1010
999
|
// Regenerar patterns.md
|
|
1011
|
-
generatePatternsMarkdown();
|
|
1000
|
+
await generatePatternsMarkdown();
|
|
1012
1001
|
|
|
1013
1002
|
console.log(`\n✓ Pattern '${name}' removido com sucesso!`);
|
|
1014
1003
|
console.log("Arquivo atualizado: .codexa/patterns.md\n");
|
|
1015
1004
|
}
|
|
1016
1005
|
|
|
1017
|
-
export function discoverRefreshPatterns(): void {
|
|
1018
|
-
initSchema();
|
|
1019
|
-
const db = getDb();
|
|
1006
|
+
export async function discoverRefreshPatterns(): Promise<void> {
|
|
1007
|
+
await initSchema();
|
|
1020
1008
|
|
|
1021
1009
|
// Verificar se projeto foi descoberto
|
|
1022
|
-
const project =
|
|
1010
|
+
const project = await dbGet<any>("SELECT * FROM project WHERE id = 'default'", ["default"]);
|
|
1023
1011
|
if (!project) {
|
|
1024
1012
|
throw new CodexaError("Projeto nao descoberto.\nExecute: discover start primeiro");
|
|
1025
1013
|
}
|
|
@@ -1030,9 +1018,8 @@ export function discoverRefreshPatterns(): void {
|
|
|
1030
1018
|
console.log(" discover pattern-add --category component --name my-pattern ...\n");
|
|
1031
1019
|
}
|
|
1032
1020
|
|
|
1033
|
-
export function generatePatternsMarkdown(): void {
|
|
1034
|
-
const
|
|
1035
|
-
const patterns = db.query("SELECT * FROM implementation_patterns ORDER BY category, name").all() as any[];
|
|
1021
|
+
export async function generatePatternsMarkdown(): Promise<void> {
|
|
1022
|
+
const patterns = await dbAll<any>("SELECT * FROM implementation_patterns ORDER BY category, name", []);
|
|
1036
1023
|
|
|
1037
1024
|
if (patterns.length === 0) return;
|
|
1038
1025
|
|
|
@@ -1120,8 +1107,8 @@ export function generatePatternsMarkdown(): void {
|
|
|
1120
1107
|
writeFileSync(mdPath, md);
|
|
1121
1108
|
}
|
|
1122
1109
|
|
|
1123
|
-
export function discoverExportPatterns(): void {
|
|
1124
|
-
generatePatternsMarkdown();
|
|
1110
|
+
export async function discoverExportPatterns(): Promise<void> {
|
|
1111
|
+
await generatePatternsMarkdown();
|
|
1125
1112
|
console.log("\n✓ Arquivo .codexa/patterns.md regenerado!\n");
|
|
1126
1113
|
}
|
|
1127
1114
|
|
|
@@ -1312,4 +1299,4 @@ function ensureGrepaiPermissions(): void {
|
|
|
1312
1299
|
writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
1313
1300
|
console.log("✓ Permissoes de grepai adicionadas em .claude/settings.local.json");
|
|
1314
1301
|
}
|
|
1315
|
-
}
|
|
1302
|
+
}
|