agentxchain 2.93.0 → 2.94.0
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
CHANGED
|
@@ -575,6 +575,11 @@ function renderContext(state, config, root, turn, role) {
|
|
|
575
575
|
lines.push(` - ${req}`);
|
|
576
576
|
}
|
|
577
577
|
}
|
|
578
|
+
if (Array.isArray(dc.required_decision_ids) && dc.required_decision_ids.length > 0) {
|
|
579
|
+
lines.push(`- **Required decisions:** ${dc.required_decision_ids.join(', ')}`);
|
|
580
|
+
lines.push('');
|
|
581
|
+
lines.push('Your accepted turn must emit these decision IDs in `decisions[]` before the parent review may advance the phase or complete the run.');
|
|
582
|
+
}
|
|
578
583
|
lines.push('');
|
|
579
584
|
lines.push('Focus exclusively on the charter above. Do not expand scope beyond the delegation.');
|
|
580
585
|
lines.push('');
|
|
@@ -599,9 +604,14 @@ function renderContext(state, config, root, turn, role) {
|
|
|
599
604
|
if (result.verification?.status) {
|
|
600
605
|
lines.push(`- **Verification:** ${result.verification.status}`);
|
|
601
606
|
}
|
|
607
|
+
if (Array.isArray(result.required_decision_ids) && result.required_decision_ids.length > 0) {
|
|
608
|
+
lines.push(`- **Required decisions:** ${result.required_decision_ids.join(', ')}`);
|
|
609
|
+
lines.push(`- **Satisfied decisions:** ${(result.satisfied_decision_ids || []).join(', ') || 'none'}`);
|
|
610
|
+
lines.push(`- **Missing decisions:** ${(result.missing_decision_ids || []).join(', ') || 'none'}`);
|
|
611
|
+
}
|
|
602
612
|
lines.push('');
|
|
603
613
|
}
|
|
604
|
-
lines.push('Evaluate whether each delegation met its acceptance contract.');
|
|
614
|
+
lines.push('Evaluate whether each delegation met its acceptance contract and returned any required named decisions.');
|
|
605
615
|
lines.push('Your turn result should assess the delegation outcomes and decide next steps.');
|
|
606
616
|
lines.push('');
|
|
607
617
|
}
|
package/src/lib/export.js
CHANGED
|
@@ -279,6 +279,9 @@ export function buildDelegationSummary(files) {
|
|
|
279
279
|
delegation_id: del.id,
|
|
280
280
|
to_role: del.to_role,
|
|
281
281
|
charter: del.charter,
|
|
282
|
+
required_decision_ids: Array.isArray(del.required_decision_ids) ? del.required_decision_ids : [],
|
|
283
|
+
satisfied_decision_ids: Array.isArray(reviewResult?.satisfied_decision_ids) ? reviewResult.satisfied_decision_ids : [],
|
|
284
|
+
missing_decision_ids: Array.isArray(reviewResult?.missing_decision_ids) ? reviewResult.missing_decision_ids : [],
|
|
282
285
|
status: reviewResult?.status || child?.status || 'pending',
|
|
283
286
|
child_turn_id: child?.turn_id || null,
|
|
284
287
|
};
|
|
@@ -2152,6 +2152,7 @@ export function assignGovernedTurn(root, config, roleId) {
|
|
|
2152
2152
|
parent_role: pendingDelegation.parent_role,
|
|
2153
2153
|
charter: pendingDelegation.charter,
|
|
2154
2154
|
acceptance_contract: pendingDelegation.acceptance_contract,
|
|
2155
|
+
required_decision_ids: pendingDelegation.required_decision_ids || [],
|
|
2155
2156
|
};
|
|
2156
2157
|
// Mark the delegation as active
|
|
2157
2158
|
pendingDelegation.status = 'active';
|
|
@@ -2742,6 +2743,7 @@ function _acceptGovernedTurnLocked(root, config, opts) {
|
|
|
2742
2743
|
to_role: delegation.to_role,
|
|
2743
2744
|
charter: delegation.charter,
|
|
2744
2745
|
acceptance_contract: delegation.acceptance_contract,
|
|
2746
|
+
required_decision_ids: delegation.required_decision_ids || [],
|
|
2745
2747
|
})),
|
|
2746
2748
|
}
|
|
2747
2749
|
: {}),
|
|
@@ -2753,6 +2755,7 @@ function _acceptGovernedTurnLocked(root, config, opts) {
|
|
|
2753
2755
|
parent_role: currentTurn.delegation_context.parent_role,
|
|
2754
2756
|
charter: currentTurn.delegation_context.charter,
|
|
2755
2757
|
acceptance_contract: currentTurn.delegation_context.acceptance_contract,
|
|
2758
|
+
required_decision_ids: currentTurn.delegation_context.required_decision_ids || [],
|
|
2756
2759
|
},
|
|
2757
2760
|
}
|
|
2758
2761
|
: {}),
|
|
@@ -2833,6 +2836,7 @@ function _acceptGovernedTurnLocked(root, config, opts) {
|
|
|
2833
2836
|
to_role: del.to_role,
|
|
2834
2837
|
charter: del.charter,
|
|
2835
2838
|
acceptance_contract: del.acceptance_contract,
|
|
2839
|
+
required_decision_ids: del.required_decision_ids || [],
|
|
2836
2840
|
status: 'pending',
|
|
2837
2841
|
child_turn_id: null,
|
|
2838
2842
|
created_at: now,
|
|
@@ -2859,12 +2863,23 @@ function _acceptGovernedTurnLocked(root, config, opts) {
|
|
|
2859
2863
|
// Build delegation review context
|
|
2860
2864
|
const delegationResults = parentDelegations.map(d => {
|
|
2861
2865
|
const childHistory = nextHistoryEntries.find(h => h.turn_id === d.child_turn_id);
|
|
2866
|
+
const childDecisionIds = Array.isArray(childHistory?.decisions)
|
|
2867
|
+
? childHistory.decisions
|
|
2868
|
+
.map((decision) => decision?.id)
|
|
2869
|
+
.filter((id) => typeof id === 'string')
|
|
2870
|
+
: [];
|
|
2871
|
+
const requiredDecisionIds = Array.isArray(d.required_decision_ids) ? d.required_decision_ids : [];
|
|
2872
|
+
const satisfiedDecisionIds = requiredDecisionIds.filter((id) => childDecisionIds.includes(id));
|
|
2873
|
+
const missingDecisionIds = requiredDecisionIds.filter((id) => !childDecisionIds.includes(id));
|
|
2862
2874
|
return {
|
|
2863
2875
|
delegation_id: d.delegation_id,
|
|
2864
2876
|
child_turn_id: d.child_turn_id,
|
|
2865
2877
|
to_role: d.to_role,
|
|
2866
2878
|
charter: d.charter,
|
|
2867
2879
|
acceptance_contract: d.acceptance_contract,
|
|
2880
|
+
required_decision_ids: requiredDecisionIds,
|
|
2881
|
+
satisfied_decision_ids: satisfiedDecisionIds,
|
|
2882
|
+
missing_decision_ids: missingDecisionIds,
|
|
2868
2883
|
summary: childHistory?.summary || '(no summary)',
|
|
2869
2884
|
status: d.status,
|
|
2870
2885
|
files_changed: childHistory?.files_changed || [],
|
package/src/lib/report.js
CHANGED
|
@@ -33,6 +33,9 @@ function normalizeDelegationSummary(summary) {
|
|
|
33
33
|
delegation_id: delegation.delegation_id,
|
|
34
34
|
to_role: delegation.to_role,
|
|
35
35
|
charter: delegation.charter,
|
|
36
|
+
required_decision_ids: Array.isArray(delegation.required_decision_ids) ? delegation.required_decision_ids : [],
|
|
37
|
+
satisfied_decision_ids: Array.isArray(delegation.satisfied_decision_ids) ? delegation.satisfied_decision_ids : [],
|
|
38
|
+
missing_decision_ids: Array.isArray(delegation.missing_decision_ids) ? delegation.missing_decision_ids : [],
|
|
36
39
|
status: delegation.status,
|
|
37
40
|
child_turn_id: delegation.child_turn_id,
|
|
38
41
|
});
|
|
@@ -1290,6 +1293,11 @@ export function formatGovernanceReportText(report) {
|
|
|
1290
1293
|
lines.push(` - ${chain.parent_role} (${chain.parent_turn_id}) | outcome: ${chain.outcome} | review: ${chain.review_turn_id || 'pending'}`);
|
|
1291
1294
|
for (const delegation of chain.delegations) {
|
|
1292
1295
|
lines.push(` ${delegation.delegation_id} -> ${delegation.to_role} | ${delegation.status} | child: ${delegation.child_turn_id || 'pending'} | ${delegation.charter}`);
|
|
1296
|
+
if (delegation.required_decision_ids?.length > 0) {
|
|
1297
|
+
lines.push(` required decisions: ${delegation.required_decision_ids.join(', ')}`);
|
|
1298
|
+
lines.push(` satisfied decisions: ${delegation.satisfied_decision_ids.join(', ') || 'none'}`);
|
|
1299
|
+
lines.push(` missing decisions: ${delegation.missing_decision_ids.join(', ') || 'none'}`);
|
|
1300
|
+
}
|
|
1293
1301
|
}
|
|
1294
1302
|
}
|
|
1295
1303
|
}
|
|
@@ -1773,7 +1781,7 @@ export function formatGovernanceReportMarkdown(report) {
|
|
|
1773
1781
|
if (run.delegation_summary?.delegation_chains?.length > 0) {
|
|
1774
1782
|
lines.push('', '## Delegation Summary', '');
|
|
1775
1783
|
lines.push(`- Total delegations issued: ${run.delegation_summary.total_delegations_issued}`, '');
|
|
1776
|
-
lines.push('| Parent Role | Parent Turn | Outcome | Review Turn | Delegation | Child Turn | Status | Charter |', '
|
|
1784
|
+
lines.push('| Parent Role | Parent Turn | Outcome | Review Turn | Delegation | Child Turn | Status | Required Decisions | Missing Decisions | Charter |', '|-------------|-------------|---------|-------------|------------|------------|--------|--------------------|-------------------|---------|');
|
|
1777
1785
|
for (const chain of run.delegation_summary.delegation_chains) {
|
|
1778
1786
|
for (let i = 0; i < chain.delegations.length; i++) {
|
|
1779
1787
|
const delegation = chain.delegations[i];
|
|
@@ -1782,7 +1790,9 @@ export function formatGovernanceReportMarkdown(report) {
|
|
|
1782
1790
|
const outcome = i === 0 ? `\`${chain.outcome}\`` : '';
|
|
1783
1791
|
const reviewTurn = i === 0 ? `\`${chain.review_turn_id || 'pending'}\`` : '';
|
|
1784
1792
|
const charter = delegation.charter.replace(/\|/g, '\\|');
|
|
1785
|
-
|
|
1793
|
+
const requiredDecisions = (delegation.required_decision_ids || []).join(', ').replace(/\|/g, '\\|') || '—';
|
|
1794
|
+
const missingDecisions = (delegation.missing_decision_ids || []).join(', ').replace(/\|/g, '\\|') || '—';
|
|
1795
|
+
lines.push(`| ${parentRole} | ${parentTurn} | ${outcome} | ${reviewTurn} | \`${delegation.delegation_id}\` → \`${delegation.to_role}\` | \`${delegation.child_turn_id || 'pending'}\` | \`${delegation.status}\` | ${requiredDecisions} | ${missingDecisions} | ${charter} |`);
|
|
1786
1796
|
}
|
|
1787
1797
|
}
|
|
1788
1798
|
}
|
|
@@ -2392,11 +2402,13 @@ function renderRunHtml(report) {
|
|
|
2392
2402
|
`<code>${esc(d.delegation_id)}</code> → <code>${esc(d.to_role)}</code>`,
|
|
2393
2403
|
`<code>${esc(d.child_turn_id || 'pending')}</code>`,
|
|
2394
2404
|
badge(d.status),
|
|
2405
|
+
esc((d.required_decision_ids || []).join(', ') || '\u2014'),
|
|
2406
|
+
esc((d.missing_decision_ids || []).join(', ') || '\u2014'),
|
|
2395
2407
|
esc(d.charter),
|
|
2396
2408
|
]);
|
|
2397
2409
|
}
|
|
2398
2410
|
}
|
|
2399
|
-
delHtml += htmlTable(['Parent Role', 'Parent Turn', 'Outcome', 'Review Turn', 'Delegation', 'Child Turn', 'Status', 'Charter'], rows);
|
|
2411
|
+
delHtml += htmlTable(['Parent Role', 'Parent Turn', 'Outcome', 'Review Turn', 'Delegation', 'Child Turn', 'Status', 'Required Decisions', 'Missing Decisions', 'Charter'], rows);
|
|
2400
2412
|
sections.push(`<div class="section">${htmlSection('Delegation Summary', delHtml)}</div>`);
|
|
2401
2413
|
}
|
|
2402
2414
|
|
|
@@ -268,6 +268,16 @@
|
|
|
268
268
|
"items": { "type": "string", "minLength": 1 },
|
|
269
269
|
"minItems": 1,
|
|
270
270
|
"description": "What the delegate must achieve for this delegation to be considered complete."
|
|
271
|
+
},
|
|
272
|
+
"required_decision_ids": {
|
|
273
|
+
"type": "array",
|
|
274
|
+
"items": {
|
|
275
|
+
"type": "string",
|
|
276
|
+
"pattern": "^DEC-\\d+$"
|
|
277
|
+
},
|
|
278
|
+
"minItems": 1,
|
|
279
|
+
"uniqueItems": true,
|
|
280
|
+
"description": "Optional named decisions the delegated child must emit before the parent review turn may advance phase/run lifecycle."
|
|
271
281
|
}
|
|
272
282
|
}
|
|
273
283
|
}
|
|
@@ -263,6 +263,16 @@ function validateSchema(tr) {
|
|
|
263
263
|
}
|
|
264
264
|
}
|
|
265
265
|
|
|
266
|
+
if ('delegations' in tr) {
|
|
267
|
+
if (!Array.isArray(tr.delegations)) {
|
|
268
|
+
errors.push('delegations must be an array.');
|
|
269
|
+
} else {
|
|
270
|
+
for (let i = 0; i < tr.delegations.length; i++) {
|
|
271
|
+
errors.push(...validateDelegation(tr.delegations[i], i));
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
266
276
|
errors.push(...collectUnfilledTemplatePlaceholderErrors(tr));
|
|
267
277
|
|
|
268
278
|
return errors;
|
|
@@ -382,6 +392,54 @@ function validateObjection(obj, index) {
|
|
|
382
392
|
return errors;
|
|
383
393
|
}
|
|
384
394
|
|
|
395
|
+
function validateDelegation(del, index) {
|
|
396
|
+
const errors = [];
|
|
397
|
+
const prefix = `delegations[${index}]`;
|
|
398
|
+
|
|
399
|
+
if (del === null || typeof del !== 'object' || Array.isArray(del)) {
|
|
400
|
+
return [`${prefix} must be an object.`];
|
|
401
|
+
}
|
|
402
|
+
if (typeof del.id !== 'string' || !/^del-\d{3}$/.test(del.id)) {
|
|
403
|
+
errors.push(`${prefix}.id must match pattern del-NNN.`);
|
|
404
|
+
}
|
|
405
|
+
if (typeof del.to_role !== 'string' || !/^[a-z0-9_-]+$/.test(del.to_role)) {
|
|
406
|
+
errors.push(`${prefix}.to_role must match pattern ^[a-z0-9_-]+$.`);
|
|
407
|
+
}
|
|
408
|
+
if (typeof del.charter !== 'string' || !del.charter.trim()) {
|
|
409
|
+
errors.push(`${prefix}.charter must be a non-empty string.`);
|
|
410
|
+
}
|
|
411
|
+
if (!Array.isArray(del.acceptance_contract) || del.acceptance_contract.length === 0) {
|
|
412
|
+
errors.push(`${prefix}.acceptance_contract must be a non-empty array.`);
|
|
413
|
+
} else {
|
|
414
|
+
for (let i = 0; i < del.acceptance_contract.length; i++) {
|
|
415
|
+
if (typeof del.acceptance_contract[i] !== 'string' || !del.acceptance_contract[i].trim()) {
|
|
416
|
+
errors.push(`${prefix}.acceptance_contract[${i}] must be a non-empty string.`);
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
if (del.required_decision_ids !== undefined) {
|
|
421
|
+
if (!Array.isArray(del.required_decision_ids) || del.required_decision_ids.length === 0) {
|
|
422
|
+
errors.push(`${prefix}.required_decision_ids must be a non-empty array when provided.`);
|
|
423
|
+
} else {
|
|
424
|
+
const seen = new Set();
|
|
425
|
+
for (let i = 0; i < del.required_decision_ids.length; i++) {
|
|
426
|
+
const id = del.required_decision_ids[i];
|
|
427
|
+
if (typeof id !== 'string' || !/^DEC-\d+$/.test(id)) {
|
|
428
|
+
errors.push(`${prefix}.required_decision_ids[${i}] must match pattern DEC-NNN.`);
|
|
429
|
+
continue;
|
|
430
|
+
}
|
|
431
|
+
if (seen.has(id)) {
|
|
432
|
+
errors.push(`${prefix}.required_decision_ids contains duplicate "${id}".`);
|
|
433
|
+
continue;
|
|
434
|
+
}
|
|
435
|
+
seen.add(id);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
return errors;
|
|
441
|
+
}
|
|
442
|
+
|
|
385
443
|
// ── Stage B: Assignment Validation ───────────────────────────────────────────
|
|
386
444
|
|
|
387
445
|
function validateAssignment(tr, state) {
|
|
@@ -563,6 +621,7 @@ function validateProtocol(tr, state, config) {
|
|
|
563
621
|
|
|
564
622
|
const role = config.roles?.[tr.role];
|
|
565
623
|
const writeAuthority = role?.write_authority;
|
|
624
|
+
const activeTurn = getActiveTurn(state) || state?.current_turn || null;
|
|
566
625
|
|
|
567
626
|
// Challenge requirement: review_only roles MUST raise at least one objection
|
|
568
627
|
if (config.rules?.challenge_required !== false) {
|
|
@@ -628,7 +687,6 @@ function validateProtocol(tr, state, config) {
|
|
|
628
687
|
}
|
|
629
688
|
|
|
630
689
|
// No recursive delegation: if this turn is a delegation review, it cannot delegate further
|
|
631
|
-
const activeTurn = state?.active_turns ? Object.values(state.active_turns)[0] : null;
|
|
632
690
|
if (activeTurn?.delegation_context) {
|
|
633
691
|
errors.push('Delegation review turns cannot contain further delegations.');
|
|
634
692
|
}
|
|
@@ -663,6 +721,26 @@ function validateProtocol(tr, state, config) {
|
|
|
663
721
|
}
|
|
664
722
|
}
|
|
665
723
|
|
|
724
|
+
if (activeTurn?.delegation_review) {
|
|
725
|
+
const unmetDecisionContracts = (activeTurn.delegation_review.results || [])
|
|
726
|
+
.filter((result) => Array.isArray(result?.missing_decision_ids) && result.missing_decision_ids.length > 0);
|
|
727
|
+
if (unmetDecisionContracts.length > 0) {
|
|
728
|
+
const detail = unmetDecisionContracts
|
|
729
|
+
.map((result) => `${result.delegation_id}: ${result.missing_decision_ids.join(', ')}`)
|
|
730
|
+
.join('; ');
|
|
731
|
+
if (tr.phase_transition_request) {
|
|
732
|
+
errors.push(
|
|
733
|
+
`Delegation review cannot request phase transition while required child decisions are missing: ${detail}.`
|
|
734
|
+
);
|
|
735
|
+
}
|
|
736
|
+
if (tr.run_completion_request) {
|
|
737
|
+
errors.push(
|
|
738
|
+
`Delegation review cannot request run completion while required child decisions are missing: ${detail}.`
|
|
739
|
+
);
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
|
|
666
744
|
return { errors, warnings };
|
|
667
745
|
}
|
|
668
746
|
|