@codexa/cli 9.0.21 → 9.0.22
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 +11 -1
- package/gates/validator.ts +9 -1
- package/package.json +1 -1
- package/protocol/subagent-protocol.ts +24 -9
package/commands/decide.ts
CHANGED
|
@@ -107,10 +107,20 @@ export function detectConflicts(
|
|
|
107
107
|
|
|
108
108
|
// Verificar sobreposicao alta de keywords (mesmo topico, decisoes diferentes?)
|
|
109
109
|
if (conflicts.every((c) => c.id !== existing.id)) {
|
|
110
|
+
// v10.1: Skip exact duplicates (same title+decision = not a conflict)
|
|
111
|
+
if (
|
|
112
|
+
newTitle.trim().toLowerCase() === existing.title?.trim().toLowerCase() &&
|
|
113
|
+
newDecision.trim().toLowerCase() === existing.decision?.trim().toLowerCase()
|
|
114
|
+
) {
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
|
|
110
118
|
const intersection = [...newKeywords].filter((k) => existingKeywords.has(k));
|
|
111
119
|
const similarity = intersection.length / Math.max(newKeywords.size, existingKeywords.size);
|
|
112
120
|
|
|
113
|
-
|
|
121
|
+
// v10.1: Raised threshold from 0.4 to 0.7 to reduce false positives
|
|
122
|
+
// Complementary decisions (e.g. "Use REST" + "Use JWT") were falsely flagged
|
|
123
|
+
if (similarity > 0.7 && intersection.length >= 3) {
|
|
114
124
|
conflicts.push({
|
|
115
125
|
id: existing.id,
|
|
116
126
|
title: existing.title,
|
package/gates/validator.ts
CHANGED
|
@@ -493,9 +493,17 @@ function executeCheck(check: string, context: any): { passed: boolean; details?:
|
|
|
493
493
|
.all(dcTask.spec_id) as any[];
|
|
494
494
|
if (existingDecisions.length === 0) return { passed: true };
|
|
495
495
|
|
|
496
|
+
// v10.1: Filter out decisions from the CURRENT task.
|
|
497
|
+
// processSubagentReturn() already saved them to DB before this gate runs,
|
|
498
|
+
// so without filtering, the new decisions would match against themselves.
|
|
499
|
+
const priorDecisions = existingDecisions.filter(
|
|
500
|
+
(d: any) => d.task_ref !== dcTask.number
|
|
501
|
+
);
|
|
502
|
+
if (priorDecisions.length === 0) return { passed: true };
|
|
503
|
+
|
|
496
504
|
const allConflicts: string[] = [];
|
|
497
505
|
for (const dec of context.subagentData.decisions_made) {
|
|
498
|
-
const analysis = detectConflicts(dec.title, dec.decision,
|
|
506
|
+
const analysis = detectConflicts(dec.title, dec.decision, priorDecisions);
|
|
499
507
|
if (analysis.hasConflict) {
|
|
500
508
|
for (const conflict of analysis.conflictingDecisions) {
|
|
501
509
|
allConflicts.push(
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codexa/cli",
|
|
3
|
-
"version": "9.0.
|
|
3
|
+
"version": "9.0.22",
|
|
4
4
|
"description": "Orchestrated workflow system for Claude Code - manages feature development through parallel subagents with structured phases, gates, and quality enforcement.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -316,20 +316,35 @@ export function parseSubagentReturn(input: string): ParseResult {
|
|
|
316
316
|
}
|
|
317
317
|
}
|
|
318
318
|
|
|
319
|
-
// v9.0: Validacao de reasoning
|
|
319
|
+
// v9.0: Validacao de reasoning para status "completed" (Gate 4.4)
|
|
320
|
+
// v10.1: Auto-derive reasoning from summary when missing (graceful degradation)
|
|
320
321
|
if (parsed.status === "completed") {
|
|
321
322
|
if (!parsed.reasoning || typeof parsed.reasoning !== "object") {
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
323
|
+
// Auto-derive reasoning from summary instead of hard-failing
|
|
324
|
+
const summary = typeof parsed.summary === "string" ? parsed.summary : "";
|
|
325
|
+
if (summary.length >= 20) {
|
|
326
|
+
parsed.reasoning = { approach: summary };
|
|
327
|
+
console.warn("[protocol] reasoning ausente — auto-derivado do summary");
|
|
328
|
+
} else {
|
|
329
|
+
errors.push(
|
|
330
|
+
"Status 'completed' requer campo 'reasoning' com pelo menos 'approach'. " +
|
|
331
|
+
"Isso preserva contexto entre tasks. Exemplo: {\"reasoning\": {\"approach\": \"Descreva como abordou o problema\"}}"
|
|
332
|
+
);
|
|
333
|
+
}
|
|
326
334
|
} else {
|
|
327
335
|
const r = parsed.reasoning as Record<string, unknown>;
|
|
328
336
|
if (!r.approach || typeof r.approach !== "string" || (r.approach as string).length < 20) {
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
337
|
+
// Auto-derive approach from summary if approach is too short
|
|
338
|
+
const summary = typeof parsed.summary === "string" ? parsed.summary : "";
|
|
339
|
+
if (summary.length >= 20) {
|
|
340
|
+
(parsed.reasoning as Record<string, unknown>).approach = summary;
|
|
341
|
+
console.warn("[protocol] reasoning.approach insuficiente — auto-derivado do summary");
|
|
342
|
+
} else {
|
|
343
|
+
errors.push(
|
|
344
|
+
"Campo 'reasoning.approach' obrigatorio com minimo 20 caracteres para status 'completed'. " +
|
|
345
|
+
"Descreva COMO voce abordou o problema, nao apenas O QUE fez."
|
|
346
|
+
);
|
|
347
|
+
}
|
|
333
348
|
}
|
|
334
349
|
}
|
|
335
350
|
}
|