agentxchain 2.155.3 → 2.155.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/package.json +1 -1
- package/src/lib/turn-result-validator.js +120 -4
package/package.json
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
import { existsSync, readFileSync } from 'fs';
|
|
16
|
-
import { join } from 'path';
|
|
16
|
+
import { dirname, join } from 'path';
|
|
17
17
|
import { getActiveTurn } from './governed-state.js';
|
|
18
18
|
import { getInvalidPhaseTransitionReason } from './gate-evaluator.js';
|
|
19
19
|
import { validateIdleExpansionTurnResult } from './idle-expansion-result-validator.js';
|
|
@@ -71,6 +71,8 @@ export function validateStagedTurnResult(root, state, config, opts = {}) {
|
|
|
71
71
|
return result('schema', 'schema_error', [`Invalid JSON in ${stagingRel}: ${err.message}`]);
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
+
const activeTurn = getActiveTurn(state) || state?.current_turn || null;
|
|
75
|
+
|
|
74
76
|
// ── Pre-validation normalization ───────────────────────────────────────
|
|
75
77
|
// Build context for role/phase-aware normalization rules
|
|
76
78
|
const normContext = {};
|
|
@@ -80,7 +82,6 @@ export function validateStagedTurnResult(root, state, config, opts = {}) {
|
|
|
80
82
|
// current_turn compatibility alias for callers that pass a state shape
|
|
81
83
|
// built outside loadProjectState() (e.g. raw fixtures). Both surfaces are
|
|
82
84
|
// live per DEC-CURRENT-TURN-COMPAT-ALIAS-001 — current_turn is not legacy.
|
|
83
|
-
const activeTurn = getActiveTurn(state) || state.current_turn;
|
|
84
85
|
if (activeTurn) {
|
|
85
86
|
const roleKey = activeTurn.assigned_role || activeTurn.role;
|
|
86
87
|
normContext.assignedRole = roleKey;
|
|
@@ -92,7 +93,17 @@ export function validateStagedTurnResult(root, state, config, opts = {}) {
|
|
|
92
93
|
}
|
|
93
94
|
const { normalized, corrections } = normalizeTurnResult(turnResult, config, normContext);
|
|
94
95
|
turnResult = normalized;
|
|
95
|
-
const
|
|
96
|
+
const sidecarResult = maybeAttachIdleExpansionSidecar(
|
|
97
|
+
root,
|
|
98
|
+
stagingRel,
|
|
99
|
+
turnResult,
|
|
100
|
+
buildIdleExpansionValidationContext(state, opts, activeTurn),
|
|
101
|
+
);
|
|
102
|
+
turnResult = sidecarResult.turnResult;
|
|
103
|
+
const normWarnings = [
|
|
104
|
+
...corrections.map((c) => `[normalized] ${c}`),
|
|
105
|
+
...sidecarResult.warnings,
|
|
106
|
+
];
|
|
96
107
|
|
|
97
108
|
// ── Stage A: Schema Validation ─────────────────────────────────────────
|
|
98
109
|
const schemaErrors = validateSchema(turnResult);
|
|
@@ -100,7 +111,6 @@ export function validateStagedTurnResult(root, state, config, opts = {}) {
|
|
|
100
111
|
return result('schema', 'schema_error', schemaErrors);
|
|
101
112
|
}
|
|
102
113
|
|
|
103
|
-
const activeTurn = getActiveTurn(state) || state?.current_turn || null;
|
|
104
114
|
const idleExpansionResult = validateIdleExpansionTurnResult(turnResult, buildIdleExpansionValidationContext(state, opts, activeTurn));
|
|
105
115
|
if (idleExpansionResult.errors.length > 0) {
|
|
106
116
|
return result('schema', 'schema_error', idleExpansionResult.errors, idleExpansionResult.warnings);
|
|
@@ -468,6 +478,112 @@ function buildIdleExpansionValidationContext(state, opts, activeTurn) {
|
|
|
468
478
|
};
|
|
469
479
|
}
|
|
470
480
|
|
|
481
|
+
function maybeAttachIdleExpansionSidecar(root, stagingRel, turnResult, context) {
|
|
482
|
+
if (context.required !== true || turnResult?.idle_expansion_result !== undefined) {
|
|
483
|
+
return { turnResult, warnings: [] };
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
const sidecarRel = join(dirname(stagingRel), 'idle-expansion-result.json');
|
|
487
|
+
const sidecarAbs = join(root, sidecarRel);
|
|
488
|
+
if (!existsSync(sidecarAbs)) {
|
|
489
|
+
return { turnResult, warnings: [] };
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
let raw;
|
|
493
|
+
try {
|
|
494
|
+
raw = readFileSync(sidecarAbs, 'utf8');
|
|
495
|
+
} catch (err) {
|
|
496
|
+
return { turnResult, warnings: [`[normalized] Cannot read idle expansion sidecar ${sidecarRel}: ${err.message}`] };
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
let sidecar;
|
|
500
|
+
try {
|
|
501
|
+
sidecar = JSON.parse(raw);
|
|
502
|
+
} catch (err) {
|
|
503
|
+
return { turnResult, warnings: [`[normalized] Invalid JSON in idle expansion sidecar ${sidecarRel}: ${err.message}`] };
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
const idleExpansionResult = normalizeIdleExpansionSidecar(sidecar, context);
|
|
507
|
+
return {
|
|
508
|
+
turnResult: {
|
|
509
|
+
...turnResult,
|
|
510
|
+
idle_expansion_result: idleExpansionResult,
|
|
511
|
+
},
|
|
512
|
+
warnings: [`[normalized] Loaded idle_expansion_result from ${sidecarRel}.`],
|
|
513
|
+
};
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
function normalizeIdleExpansionSidecar(sidecar, context) {
|
|
517
|
+
if (!sidecar || typeof sidecar !== 'object' || Array.isArray(sidecar)) {
|
|
518
|
+
return sidecar;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
const result = {
|
|
522
|
+
...sidecar,
|
|
523
|
+
expansion_iteration: Number.isInteger(sidecar.expansion_iteration)
|
|
524
|
+
? sidecar.expansion_iteration
|
|
525
|
+
: context.expansionIteration,
|
|
526
|
+
};
|
|
527
|
+
|
|
528
|
+
const intent = sidecar.new_intake_intent || sidecar.proposed_intent;
|
|
529
|
+
if (sidecar.kind === 'new_intake_intent' && intent && typeof intent === 'object' && !Array.isArray(intent)) {
|
|
530
|
+
result.new_intake_intent = {
|
|
531
|
+
title: intent.title,
|
|
532
|
+
charter: intent.charter,
|
|
533
|
+
acceptance_contract: intent.acceptance_contract,
|
|
534
|
+
priority: intent.priority,
|
|
535
|
+
template: intent.template,
|
|
536
|
+
};
|
|
537
|
+
result.vision_traceability = normalizeVisionTraceabilityForTurnResult(
|
|
538
|
+
sidecar.vision_traceability || intent.vision_traceability,
|
|
539
|
+
);
|
|
540
|
+
} else if (sidecar.vision_traceability !== undefined) {
|
|
541
|
+
result.vision_traceability = normalizeVisionTraceabilityForTurnResult(sidecar.vision_traceability);
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
if (
|
|
545
|
+
sidecar.kind === 'vision_exhausted'
|
|
546
|
+
&& sidecar.vision_exhausted
|
|
547
|
+
&& typeof sidecar.vision_exhausted === 'object'
|
|
548
|
+
&& !Array.isArray(sidecar.vision_exhausted)
|
|
549
|
+
&& Array.isArray(sidecar.vision_exhausted.classification)
|
|
550
|
+
) {
|
|
551
|
+
result.vision_exhausted = {
|
|
552
|
+
...sidecar.vision_exhausted,
|
|
553
|
+
classification: sidecar.vision_exhausted.classification.map((entry) => {
|
|
554
|
+
if (!entry || typeof entry !== 'object' || Array.isArray(entry)) {
|
|
555
|
+
return entry;
|
|
556
|
+
}
|
|
557
|
+
return {
|
|
558
|
+
...entry,
|
|
559
|
+
vision_heading: entry.vision_heading || entry.heading,
|
|
560
|
+
};
|
|
561
|
+
}),
|
|
562
|
+
};
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
return result;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
function normalizeVisionTraceabilityForTurnResult(traceability) {
|
|
569
|
+
if (!Array.isArray(traceability)) {
|
|
570
|
+
return traceability;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
return traceability.map((entry) => {
|
|
574
|
+
if (typeof entry === 'string') {
|
|
575
|
+
return { vision_heading: entry };
|
|
576
|
+
}
|
|
577
|
+
if (!entry || typeof entry !== 'object' || Array.isArray(entry)) {
|
|
578
|
+
return entry;
|
|
579
|
+
}
|
|
580
|
+
return {
|
|
581
|
+
...entry,
|
|
582
|
+
vision_heading: entry.vision_heading || entry.heading,
|
|
583
|
+
};
|
|
584
|
+
});
|
|
585
|
+
}
|
|
586
|
+
|
|
471
587
|
// ── Stage B: Assignment Validation ───────────────────────────────────────────
|
|
472
588
|
|
|
473
589
|
function validateAssignment(tr, state) {
|