@codexa/cli 9.0.2 → 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/commands/architect.test.ts +531 -0
- package/commands/architect.ts +75 -17
- package/commands/check.ts +7 -17
- package/commands/clear.ts +40 -1
- package/commands/decide.ts +37 -49
- package/commands/discover.ts +136 -28
- package/commands/knowledge.test.ts +160 -0
- package/commands/knowledge.ts +192 -102
- package/commands/patterns.test.ts +169 -0
- package/commands/patterns.ts +6 -13
- package/commands/plan.test.ts +73 -0
- package/commands/plan.ts +18 -66
- package/commands/product.ts +8 -17
- package/commands/research.ts +4 -3
- package/commands/review.ts +190 -28
- package/commands/spec-resolver.test.ts +119 -0
- package/commands/spec-resolver.ts +90 -0
- package/commands/standards.ts +7 -15
- package/commands/sync.ts +89 -0
- package/commands/task.ts +72 -167
- package/commands/utils.test.ts +100 -0
- package/commands/utils.ts +78 -706
- package/db/schema.test.ts +760 -0
- package/db/schema.ts +284 -130
- package/gates/validator.test.ts +675 -0
- package/gates/validator.ts +112 -27
- package/package.json +3 -1
- package/protocol/process-return.ts +25 -93
- package/protocol/subagent-protocol.test.ts +936 -0
- package/protocol/subagent-protocol.ts +19 -1
- package/workflow.ts +176 -67
package/commands/task.ts
CHANGED
|
@@ -1,27 +1,26 @@
|
|
|
1
1
|
import { getDb } from "../db/connection";
|
|
2
|
-
import { initSchema, getPatternsForFiles, getPatternsByScope,
|
|
2
|
+
import { initSchema, getPatternsForFiles, getPatternsByScope, getRecentReasoning, claimTask, recordAgentPerformance } from "../db/schema";
|
|
3
3
|
import { enforceGate } from "../gates/validator";
|
|
4
4
|
import { parseSubagentReturn, formatValidationErrors } from "../protocol/subagent-protocol";
|
|
5
5
|
import { processSubagentReturn, formatProcessResult } from "../protocol/process-return";
|
|
6
6
|
import { getContextForSubagent, getMinimalContextForSubagent } from "./utils";
|
|
7
7
|
import { getUnreadKnowledgeForTask } from "./knowledge";
|
|
8
|
+
import { loadTemplate } from "../templates/loader";
|
|
9
|
+
import { TaskStateError, ValidationError, KnowledgeBlockError } from "../errors";
|
|
10
|
+
import { resolveSpec, resolveSpecOrNull } from "./spec-resolver";
|
|
8
11
|
|
|
9
|
-
export function taskNext(json: boolean = false): void {
|
|
12
|
+
export function taskNext(json: boolean = false, specId?: string): void {
|
|
10
13
|
initSchema();
|
|
11
14
|
|
|
12
15
|
const db = getDb();
|
|
13
|
-
const spec =
|
|
14
|
-
.query("SELECT * FROM specs WHERE phase = 'implementing' ORDER BY created_at DESC LIMIT 1")
|
|
15
|
-
.get() as any;
|
|
16
|
+
const spec = resolveSpecOrNull(specId, ["implementing"]);
|
|
16
17
|
|
|
17
18
|
if (!spec) {
|
|
18
19
|
if (json) {
|
|
19
20
|
console.log(JSON.stringify({ available: [], message: "Nenhuma feature em implementacao" }));
|
|
20
|
-
|
|
21
|
-
console.error("\nNenhuma feature em fase de implementacao.");
|
|
22
|
-
console.error("Aprove o plano com: check approve\n");
|
|
21
|
+
return;
|
|
23
22
|
}
|
|
24
|
-
|
|
23
|
+
throw new TaskStateError("Nenhuma feature em fase de implementacao.\nAprove o plano com: check approve");
|
|
25
24
|
}
|
|
26
25
|
|
|
27
26
|
// Buscar tasks pendentes cujas dependencias estao todas concluidas
|
|
@@ -101,16 +100,14 @@ export function taskNext(json: boolean = false): void {
|
|
|
101
100
|
console.log(`Use: task start <id> ou task start <id1>,<id2>,...\n`);
|
|
102
101
|
}
|
|
103
102
|
|
|
104
|
-
export function taskStart(ids: string, json: boolean = false, fullContext: boolean = false): void {
|
|
103
|
+
export function taskStart(ids: string, json: boolean = false, fullContext: boolean = false, specId?: string): void {
|
|
105
104
|
initSchema();
|
|
106
105
|
enforceGate("task-start");
|
|
107
106
|
|
|
108
107
|
const db = getDb();
|
|
109
108
|
const now = new Date().toISOString();
|
|
110
109
|
|
|
111
|
-
const spec =
|
|
112
|
-
.query("SELECT * FROM specs WHERE phase = 'implementing' ORDER BY created_at DESC LIMIT 1")
|
|
113
|
-
.get() as any;
|
|
110
|
+
const spec = resolveSpec(specId, ["implementing"]);
|
|
114
111
|
|
|
115
112
|
const taskIds = ids.split(",").map((s) => parseInt(s.trim()));
|
|
116
113
|
const startedTasks: any[] = [];
|
|
@@ -119,20 +116,19 @@ export function taskStart(ids: string, json: boolean = false, fullContext: boole
|
|
|
119
116
|
const task = db.query("SELECT * FROM tasks WHERE id = ?").get(taskId) as any;
|
|
120
117
|
|
|
121
118
|
if (!task) {
|
|
122
|
-
|
|
123
|
-
process.exit(2);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
if (task.status !== "pending") {
|
|
127
|
-
console.error(`\nTask #${task.number} nao esta pendente (status: ${task.status}).\n`);
|
|
128
|
-
process.exit(2);
|
|
119
|
+
throw new TaskStateError(`Task #${taskId} nao encontrada.`);
|
|
129
120
|
}
|
|
130
121
|
|
|
131
122
|
// Validar dependencias para esta task especifica
|
|
132
123
|
enforceGate("task-start", { taskId });
|
|
133
124
|
|
|
134
|
-
//
|
|
135
|
-
|
|
125
|
+
// Claim atomico: UPDATE ... WHERE status = 'pending'
|
|
126
|
+
if (!claimTask(taskId)) {
|
|
127
|
+
const current = db.query("SELECT status FROM tasks WHERE id = ?").get(taskId) as any;
|
|
128
|
+
throw new TaskStateError(
|
|
129
|
+
`Task #${task.number} nao pode ser iniciada (status atual: ${current?.status || "desconhecido"}).`
|
|
130
|
+
);
|
|
131
|
+
}
|
|
136
132
|
|
|
137
133
|
startedTasks.push(task);
|
|
138
134
|
}
|
|
@@ -233,77 +229,15 @@ export function taskStart(ids: string, json: boolean = false, fullContext: boole
|
|
|
233
229
|
// NOVO v7.4: Implementation patterns extraidos do projeto
|
|
234
230
|
implementationPatterns: formattedPatterns,
|
|
235
231
|
// Contexto para o SUBAGENT (o orquestrador deve passar isso via Task tool)
|
|
236
|
-
subagentContext:
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
║ NAO descreva. NAO planeje. NAO simule. EXECUTE AGORA. ║
|
|
240
|
-
║ Se retornar sem usar Write/Edit, a task FALHA. ║
|
|
241
|
-
╚══════════════════════════════════════════════════════════════════════════════╝
|
|
242
|
-
|
|
243
|
-
ARQUIVOS QUE VOCE DEVE CRIAR (use Write para cada um):
|
|
244
|
-
${taskFiles.map(f => ` - ${f}`).join('\n') || ' (nenhum arquivo especificado - analise o contexto)'}
|
|
245
|
-
|
|
246
|
-
╔══════════════════════════════════════════════════════════════════════════════╗
|
|
247
|
-
║ POLLING OBRIGATORIO: Verifique blockers a cada 3 arquivos modificados ║
|
|
248
|
-
╚══════════════════════════════════════════════════════════════════════════════╝
|
|
249
|
-
|
|
250
|
-
ANTES de criar o 4o, 7o, 10o arquivo (a cada 3), execute:
|
|
251
|
-
codexa knowledge list --severity critical --unread
|
|
252
|
-
|
|
253
|
-
Se retornar QUALQUER blocker:
|
|
254
|
-
1. PARE imediatamente
|
|
255
|
-
2. Retorne com status "blocked" e inclua o blocker encontrado
|
|
256
|
-
3. NAO continue criando arquivos apos encontrar blocker
|
|
257
|
-
|
|
258
|
-
CHECKLIST OBRIGATORIO (verifique ANTES de retornar):
|
|
259
|
-
- [ ] Usei Write ou Edit para criar/modificar arquivos?
|
|
260
|
-
- [ ] Verifiquei blockers a cada 3 arquivos?
|
|
261
|
-
- [ ] Os arquivos que vou listar em files_created EXISTEM no disco?
|
|
262
|
-
|
|
263
|
-
Se nao marcou todos os items, PARE e corrija AGORA.
|
|
264
|
-
|
|
265
|
-
CONTEXTO ON-DEMAND: Se precisar de mais contexto alem do fornecido, execute:
|
|
266
|
-
codexa context detail standards # Regras do projeto
|
|
267
|
-
codexa context detail decisions # Decisoes tomadas
|
|
268
|
-
codexa context detail patterns # Patterns de codigo
|
|
269
|
-
codexa context detail knowledge # Discoveries de outras tasks
|
|
270
|
-
NAO execute todos - apenas o que for NECESSARIO para sua task.
|
|
271
|
-
`.trim(),
|
|
232
|
+
subagentContext: loadTemplate("subagent-context", {
|
|
233
|
+
filesList: taskFiles.map(f => ` - ${f}`).join('\n') || ' (nenhum arquivo especificado - analise o contexto)',
|
|
234
|
+
}),
|
|
272
235
|
// Instrucoes de retorno para o SUBAGENT
|
|
273
|
-
subagentReturnProtocol:
|
|
274
|
-
|
|
275
|
-
{
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
"files_created": ["path/arquivo.ts"],
|
|
279
|
-
"files_modified": ["path/outro.ts"],
|
|
280
|
-
"reasoning": {
|
|
281
|
-
"approach": "OBRIGATORIO (min 20 chars): Como voce abordou o problema e POR QUE tomou essas decisoes",
|
|
282
|
-
"challenges": ["Desafios encontrados"],
|
|
283
|
-
"recommendations": "Sugestoes para proximas tasks"
|
|
284
|
-
},
|
|
285
|
-
"patterns_discovered": ["Pattern identificado"],
|
|
286
|
-
"decisions_made": [{"title": "...", "decision": "..."}],
|
|
287
|
-
"blockers": ["Se status != completed"],
|
|
288
|
-
"knowledge_to_broadcast": [{"category": "discovery|pattern|constraint", "content": "...", "severity": "info|warning|critical"}]
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
ATENCAO: O campo "reasoning.approach" e OBRIGATORIO para status "completed".
|
|
292
|
-
Se retornar sem ele, Gate 4.4 BLOQUEIA a finalizacao da task.
|
|
293
|
-
Descreva COMO abordou o problema, nao apenas O QUE fez.
|
|
294
|
-
|
|
295
|
-
Se NAO conseguir criar arquivos (sem permissao, sem ferramentas), retorne:
|
|
296
|
-
{
|
|
297
|
-
"status": "blocked",
|
|
298
|
-
"blockers": ["Descreva por que nao conseguiu criar os arquivos"]
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
Veja .claude/agents/PROTOCOL.md para detalhes completos.
|
|
302
|
-
${formattedPatterns.length > 0 ? `
|
|
303
|
-
PATTERNS: Voce recebeu ${formattedPatterns.length} implementation patterns extraidos do projeto.
|
|
304
|
-
Use os TEMPLATES fornecidos para criar codigo CONSISTENTE com o projeto existente.
|
|
305
|
-
` : ''}
|
|
306
|
-
`.trim(),
|
|
236
|
+
subagentReturnProtocol: loadTemplate("subagent-return-protocol", {
|
|
237
|
+
patternsNote: formattedPatterns.length > 0
|
|
238
|
+
? `\nPATTERNS: Voce recebeu ${formattedPatterns.length} implementation patterns extraidos do projeto.\nUse os TEMPLATES fornecidos para criar codigo CONSISTENTE com o projeto existente.\n`
|
|
239
|
+
: '',
|
|
240
|
+
}),
|
|
307
241
|
};
|
|
308
242
|
});
|
|
309
243
|
console.log(JSON.stringify({ started: contexts }));
|
|
@@ -325,8 +259,7 @@ export function taskDone(id: string, options: { checkpoint: string; files?: stri
|
|
|
325
259
|
const task = db.query("SELECT * FROM tasks WHERE id = ?").get(taskId) as any;
|
|
326
260
|
|
|
327
261
|
if (!task) {
|
|
328
|
-
|
|
329
|
-
process.exit(2);
|
|
262
|
+
throw new TaskStateError(`Task #${taskId} nao encontrada.`);
|
|
330
263
|
}
|
|
331
264
|
|
|
332
265
|
const spec = db.query("SELECT * FROM specs WHERE id = ?").get(task.spec_id) as any;
|
|
@@ -344,10 +277,11 @@ export function taskDone(id: string, options: { checkpoint: string; files?: stri
|
|
|
344
277
|
const parseResult = parseSubagentReturn(options.output);
|
|
345
278
|
|
|
346
279
|
if (!parseResult.success) {
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
280
|
+
throw new ValidationError(
|
|
281
|
+
formatValidationErrors(parseResult) +
|
|
282
|
+
"\nTask NAO pode ser completada sem retorno valido." +
|
|
283
|
+
"\nCorrija o formato do retorno do subagent e tente novamente."
|
|
284
|
+
);
|
|
351
285
|
}
|
|
352
286
|
|
|
353
287
|
subagentData = parseResult.data!;
|
|
@@ -411,14 +345,19 @@ export function taskDone(id: string, options: { checkpoint: string; files?: stri
|
|
|
411
345
|
.filter((k: any) => k.severity === 'critical' && k.task_origin !== taskId);
|
|
412
346
|
if (unackedCritical.length > 0) {
|
|
413
347
|
if (!options.force) {
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
348
|
+
// Task permanece em "running" (subagent output ja processado acima).
|
|
349
|
+
// Nao pode ser marcada "done" ate knowledge ser reconhecido.
|
|
350
|
+
const items = unackedCritical.map(
|
|
351
|
+
(k: any) => ` [X] ${k.content} (de Task #${k.task_origin})`
|
|
352
|
+
).join("\n");
|
|
353
|
+
|
|
354
|
+
throw new KnowledgeBlockError(
|
|
355
|
+
`BLOQUEADO: ${unackedCritical.length} knowledge(s) critico(s) nao reconhecido(s):\n${items}\n\n` +
|
|
356
|
+
`O subagent NAO verificou o polling obrigatorio.\n` +
|
|
357
|
+
`Reconheca com: knowledge ack <id>\n` +
|
|
358
|
+
`Ou force com: task done ${id} --checkpoint "..." --force --force-reason "motivo"`,
|
|
359
|
+
unackedCritical
|
|
360
|
+
);
|
|
422
361
|
} else {
|
|
423
362
|
console.log(`\n[!] AVISO: ${unackedCritical.length} knowledge(s) critico(s) ignorado(s) (--force usado)`);
|
|
424
363
|
for (const k of unackedCritical) {
|
|
@@ -469,6 +408,30 @@ export function taskDone(id: string, options: { checkpoint: string; files?: stri
|
|
|
469
408
|
[checkpoint, now, taskId]
|
|
470
409
|
);
|
|
471
410
|
|
|
411
|
+
// v9.3: Registrar performance do agente
|
|
412
|
+
try {
|
|
413
|
+
const agentType = task.agent || "general-purpose";
|
|
414
|
+
const startedAt = task.started_at ? new Date(task.started_at).getTime() : Date.now();
|
|
415
|
+
const duration = Date.now() - startedAt;
|
|
416
|
+
const bypassCount = (db.query(
|
|
417
|
+
"SELECT COUNT(*) as c FROM gate_bypasses WHERE task_id = ?"
|
|
418
|
+
).get(taskId) as any)?.c || 0;
|
|
419
|
+
const totalGates = 7;
|
|
420
|
+
|
|
421
|
+
recordAgentPerformance({
|
|
422
|
+
agentType,
|
|
423
|
+
specId: spec.id,
|
|
424
|
+
taskId,
|
|
425
|
+
gatesPassedFirstTry: Math.max(0, totalGates - bypassCount),
|
|
426
|
+
gatesTotal: totalGates,
|
|
427
|
+
bypassesUsed: bypassCount,
|
|
428
|
+
filesCreated: subagentData?.files_created?.length || 0,
|
|
429
|
+
filesModified: subagentData?.files_modified?.length || 0,
|
|
430
|
+
contextSizeBytes: 0,
|
|
431
|
+
executionDurationMs: duration,
|
|
432
|
+
});
|
|
433
|
+
} catch { /* nao-critico: nao falhar task done por tracking de performance */ }
|
|
434
|
+
|
|
472
435
|
// Registrar artefatos se NAO veio do subagent (ja foi processado acima)
|
|
473
436
|
if (!subagentData && options.files) {
|
|
474
437
|
const files = options.files.split(",").map((s) => s.trim());
|
|
@@ -494,73 +457,15 @@ export function taskDone(id: string, options: { checkpoint: string; files?: stri
|
|
|
494
457
|
[checkpoint, now, spec.id]
|
|
495
458
|
);
|
|
496
459
|
|
|
497
|
-
// Criar snapshot automatico COMPLETO
|
|
498
|
-
const allTasks = db.query("SELECT * FROM tasks WHERE spec_id = ?").all(spec.id) as any[];
|
|
499
|
-
const allDecisions = db.query("SELECT * FROM decisions WHERE spec_id = ?").all(spec.id) as any[];
|
|
500
|
-
const allArtifacts = db.query("SELECT * FROM artifacts WHERE spec_id = ?").all(spec.id) as any[];
|
|
501
|
-
const context = db.query("SELECT * FROM context WHERE spec_id = ?").get(spec.id);
|
|
502
|
-
|
|
503
|
-
const snapshotData = {
|
|
504
|
-
spec,
|
|
505
|
-
context,
|
|
506
|
-
tasks: allTasks,
|
|
507
|
-
decisions: allDecisions,
|
|
508
|
-
artifacts: allArtifacts,
|
|
509
|
-
checkpoint: options.checkpoint,
|
|
510
|
-
taskCompleted: task.number,
|
|
511
|
-
timestamp: now,
|
|
512
|
-
};
|
|
513
|
-
db.run("INSERT INTO snapshots (spec_id, data, trigger, created_at) VALUES (?, ?, 'auto', ?)", [
|
|
514
|
-
spec.id,
|
|
515
|
-
JSON.stringify(snapshotData),
|
|
516
|
-
now,
|
|
517
|
-
]);
|
|
518
|
-
|
|
519
|
-
// v8.1: Gerar session summary automaticamente
|
|
520
|
-
try {
|
|
521
|
-
const taskDecisions = allDecisions.filter((d) => d.task_ref === task.number);
|
|
522
|
-
const taskArtifacts = allArtifacts.filter((a) => a.task_ref === task.number);
|
|
523
|
-
const blockers = db.query(
|
|
524
|
-
"SELECT content FROM knowledge WHERE spec_id = ? AND task_origin = ? AND category = 'blocker'"
|
|
525
|
-
).all(spec.id, taskId) as any[];
|
|
526
|
-
const reasoning = getRecentReasoning(spec.id, 5);
|
|
527
|
-
const nextSteps: string[] = [];
|
|
528
|
-
|
|
529
|
-
// Extrair recommendations do reasoning
|
|
530
|
-
for (const r of reasoning) {
|
|
531
|
-
if (r.category === 'recommendation' && r.thought) {
|
|
532
|
-
nextSteps.push(r.thought);
|
|
533
|
-
}
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
// Se nao completou tudo, sugerir proximo passo
|
|
537
|
-
if (doneCount.c < totalCount.c) {
|
|
538
|
-
nextSteps.push(`Continuar implementacao: ${totalCount.c - doneCount.c} tasks restantes`);
|
|
539
|
-
} else {
|
|
540
|
-
nextSteps.push("Todas tasks concluidas. Iniciar review.");
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
addSessionSummary(spec.id, {
|
|
544
|
-
startTime: task.completed_at || now, // approximation
|
|
545
|
-
endTime: now,
|
|
546
|
-
summary: `Task #${task.number} (${task.name}) concluida. ${checkpoint}`,
|
|
547
|
-
decisions: taskDecisions.map((d: any) => `${d.title}: ${d.decision}`),
|
|
548
|
-
blockers: blockers.map((b: any) => b.content),
|
|
549
|
-
nextSteps,
|
|
550
|
-
tasksCompleted: 1,
|
|
551
|
-
filesCreated: taskArtifacts.filter((a: any) => a.action === 'created').length,
|
|
552
|
-
filesModified: taskArtifacts.filter((a: any) => a.action === 'modified').length,
|
|
553
|
-
});
|
|
554
|
-
} catch (e) {
|
|
555
|
-
// Session summary e best-effort, nao deve bloquear o fluxo
|
|
556
|
-
}
|
|
557
|
-
|
|
558
460
|
console.log(`\nTask #${task.number} concluida!`);
|
|
559
461
|
console.log(`Checkpoint: ${options.checkpoint}`);
|
|
560
462
|
console.log(`Progresso: ${doneCount.c}/${totalCount.c} tasks`);
|
|
561
463
|
|
|
562
464
|
if (doneCount.c === totalCount.c) {
|
|
563
465
|
// Mostrar resumo completo da implementacao
|
|
466
|
+
const allTasks = db.query("SELECT * FROM tasks WHERE spec_id = ?").all(spec.id) as any[];
|
|
467
|
+
const allDecisions = db.query("SELECT * FROM decisions WHERE spec_id = ?").all(spec.id) as any[];
|
|
468
|
+
const allArtifacts = db.query("SELECT * FROM artifacts WHERE spec_id = ?").all(spec.id) as any[];
|
|
564
469
|
showImplementationSummary(spec.id, allTasks, allArtifacts, allDecisions);
|
|
565
470
|
} else {
|
|
566
471
|
console.log(`\nProximas tasks: task next\n`);
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v9.3: Tests for AGENT_SECTIONS filtering (P3.1 — Context Intelligence)
|
|
3
|
+
*/
|
|
4
|
+
import { describe, it, expect } from "bun:test";
|
|
5
|
+
import { AGENT_SECTIONS } from "./utils";
|
|
6
|
+
|
|
7
|
+
describe("AGENT_SECTIONS (P3.1 — Context Intelligence)", () => {
|
|
8
|
+
it("testing-unit gets focused sections without PRODUTO or STACK", () => {
|
|
9
|
+
const sections = AGENT_SECTIONS["testing-unit"];
|
|
10
|
+
expect(sections).toBeDefined();
|
|
11
|
+
expect(sections).toContain("STANDARDS");
|
|
12
|
+
expect(sections).toContain("DECISOES");
|
|
13
|
+
expect(sections).toContain("ALERTAS");
|
|
14
|
+
expect(sections).toContain("PATTERNS");
|
|
15
|
+
expect(sections).toContain("UTILITIES");
|
|
16
|
+
expect(sections).toContain("HINTS");
|
|
17
|
+
expect(sections).not.toContain("PRODUTO");
|
|
18
|
+
expect(sections).not.toContain("STACK");
|
|
19
|
+
expect(sections).not.toContain("ARQUITETURA");
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it("deep-explore gets minimal sections", () => {
|
|
23
|
+
const sections = AGENT_SECTIONS["deep-explore"];
|
|
24
|
+
expect(sections).toBeDefined();
|
|
25
|
+
expect(sections).toHaveLength(2);
|
|
26
|
+
expect(sections).toContain("STACK");
|
|
27
|
+
expect(sections).toContain("ARQUITETURA");
|
|
28
|
+
expect(sections).not.toContain("HINTS");
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it("security-specialist gets security-relevant sections", () => {
|
|
32
|
+
const sections = AGENT_SECTIONS["security-specialist"];
|
|
33
|
+
expect(sections).toBeDefined();
|
|
34
|
+
expect(sections).toContain("STANDARDS");
|
|
35
|
+
expect(sections).toContain("DECISOES");
|
|
36
|
+
expect(sections).toContain("ALERTAS");
|
|
37
|
+
expect(sections).toContain("STACK");
|
|
38
|
+
expect(sections).toContain("HINTS");
|
|
39
|
+
expect(sections).not.toContain("PATTERNS");
|
|
40
|
+
expect(sections).not.toContain("UTILITIES");
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it("expert-code-reviewer gets review-relevant sections", () => {
|
|
44
|
+
const sections = AGENT_SECTIONS["expert-code-reviewer"];
|
|
45
|
+
expect(sections).toBeDefined();
|
|
46
|
+
expect(sections).toContain("STANDARDS");
|
|
47
|
+
expect(sections).toContain("DECISOES");
|
|
48
|
+
expect(sections).toContain("ARQUITETURA");
|
|
49
|
+
expect(sections).toContain("UTILITIES");
|
|
50
|
+
expect(sections).toContain("ALERTAS");
|
|
51
|
+
expect(sections).toContain("HINTS");
|
|
52
|
+
expect(sections).not.toContain("PRODUTO");
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it("unknown agent types are not in the map (get all sections)", () => {
|
|
56
|
+
expect(AGENT_SECTIONS["frontend-next"]).toBeUndefined();
|
|
57
|
+
expect(AGENT_SECTIONS["database-postgres"]).toBeUndefined();
|
|
58
|
+
expect(AGENT_SECTIONS["backend-javascript"]).toBeUndefined();
|
|
59
|
+
expect(AGENT_SECTIONS["general-purpose"]).toBeUndefined();
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it("filtering logic: known agent filters sections", () => {
|
|
63
|
+
const allSections = [
|
|
64
|
+
{ name: "PRODUTO", content: "...", priority: 7 },
|
|
65
|
+
{ name: "STANDARDS", content: "...", priority: 1 },
|
|
66
|
+
{ name: "ALERTAS", content: "...", priority: 2 },
|
|
67
|
+
{ name: "STACK", content: "...", priority: 11 },
|
|
68
|
+
{ name: "ARQUITETURA", content: "...", priority: 3 },
|
|
69
|
+
{ name: "DECISOES", content: "...", priority: 4 },
|
|
70
|
+
{ name: "PATTERNS", content: "...", priority: 9 },
|
|
71
|
+
];
|
|
72
|
+
|
|
73
|
+
const agentType = "deep-explore";
|
|
74
|
+
const allowed = AGENT_SECTIONS[agentType];
|
|
75
|
+
const filtered = allowed
|
|
76
|
+
? allSections.filter(s => allowed.includes(s.name))
|
|
77
|
+
: allSections;
|
|
78
|
+
|
|
79
|
+
expect(filtered).toHaveLength(2);
|
|
80
|
+
expect(filtered.map(s => s.name)).toContain("STACK");
|
|
81
|
+
expect(filtered.map(s => s.name)).toContain("ARQUITETURA");
|
|
82
|
+
expect(filtered.map(s => s.name)).not.toContain("PRODUTO");
|
|
83
|
+
expect(filtered.map(s => s.name)).not.toContain("STANDARDS");
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it("filtering logic: unknown agent keeps all sections", () => {
|
|
87
|
+
const allSections = [
|
|
88
|
+
{ name: "PRODUTO", content: "...", priority: 7 },
|
|
89
|
+
{ name: "STANDARDS", content: "...", priority: 1 },
|
|
90
|
+
];
|
|
91
|
+
|
|
92
|
+
const agentType = "frontend-next"; // not in AGENT_SECTIONS
|
|
93
|
+
const allowed = AGENT_SECTIONS[agentType];
|
|
94
|
+
const filtered = allowed
|
|
95
|
+
? allSections.filter(s => allowed.includes(s.name))
|
|
96
|
+
: allSections;
|
|
97
|
+
|
|
98
|
+
expect(filtered).toHaveLength(2); // All kept
|
|
99
|
+
});
|
|
100
|
+
});
|