agentxchain 2.67.0 → 2.69.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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentxchain",
3
- "version": "2.67.0",
3
+ "version": "2.69.0",
4
4
  "description": "CLI for AgentXchain — governed multi-agent software delivery",
5
5
  "type": "module",
6
6
  "bin": {
@@ -61,7 +61,16 @@ function printEvent(evt) {
61
61
  const runId = evt.run_id ? evt.run_id.slice(0, 12) : '—';
62
62
  const phase = evt.phase || '—';
63
63
  const turnInfo = evt.turn?.role_id ? ` [${evt.turn.role_id}]` : '';
64
- console.log(`${chalk.dim(ts)} ${type} ${chalk.cyan(runId)} ${phase}${turnInfo}`);
64
+ const rejectionDetail = evt.event_type === 'turn_rejected' && evt.payload?.reason
65
+ ? ` — ${evt.payload.reason}${evt.payload.failed_stage ? ` (${evt.payload.failed_stage})` : ''}`
66
+ : '';
67
+ const phaseTransitionDetail = evt.event_type === 'phase_entered' && evt.payload?.from && evt.payload?.to
68
+ ? ` ${evt.payload.from} → ${evt.payload.to}${evt.payload.trigger ? ` (${evt.payload.trigger})` : ''}`
69
+ : '';
70
+ const gateFailedDetail = evt.event_type === 'gate_failed' && evt.payload?.from_phase
71
+ ? ` ${evt.payload.from_phase} → ${evt.payload.to_phase || '?'}${evt.payload.reasons?.length ? ` — ${evt.payload.reasons[0]}` : ''}${evt.payload.gate_id ? ` (${evt.payload.gate_id})` : ''}`
72
+ : '';
73
+ console.log(`${chalk.dim(ts)} ${type} ${chalk.cyan(runId)} ${phase}${turnInfo}${rejectionDetail}${phaseTransitionDetail}${gateFailedDetail}`);
65
74
  }
66
75
 
67
76
  function colorEventType(type) {
@@ -77,6 +86,7 @@ function colorEventType(type) {
77
86
  escalation_resolved: chalk.green,
78
87
  gate_pending: chalk.yellow,
79
88
  gate_approved: chalk.green,
89
+ gate_failed: chalk.red,
80
90
  };
81
91
  const colorFn = colors[type] || chalk.white;
82
92
  return colorFn(pad(type, 22));
@@ -2853,6 +2853,7 @@ function _acceptGovernedTurnLocked(root, config, opts) {
2853
2853
  });
2854
2854
 
2855
2855
  if (gateResult.action === 'advance') {
2856
+ const prevPhase = updatedState.phase;
2856
2857
  updatedState.phase = gateResult.next_phase;
2857
2858
  updatedState.phase_entered_at = now;
2858
2859
  updatedState.last_gate_failure = null;
@@ -2861,6 +2862,18 @@ function _acceptGovernedTurnLocked(root, config, opts) {
2861
2862
  [gateResult.gate_id || 'no_gate']: 'passed',
2862
2863
  };
2863
2864
  updatedState.queued_phase_transition = null;
2865
+ emitRunEvent(root, 'phase_entered', {
2866
+ run_id: updatedState.run_id,
2867
+ phase: updatedState.phase,
2868
+ status: updatedState.status,
2869
+ turn: { turn_id: currentTurn.turn_id, role_id: currentTurn.assigned_role },
2870
+ payload: {
2871
+ from: prevPhase,
2872
+ to: gateResult.next_phase,
2873
+ gate_id: gateResult.gate_id || 'no_gate',
2874
+ trigger: 'auto',
2875
+ },
2876
+ });
2864
2877
  } else if (gateResult.action === 'awaiting_human_approval') {
2865
2878
  // Evaluate approval policy — may auto-approve
2866
2879
  const approvalResult = evaluateApprovalPolicy({
@@ -2871,6 +2884,7 @@ function _acceptGovernedTurnLocked(root, config, opts) {
2871
2884
  });
2872
2885
 
2873
2886
  if (approvalResult.action === 'auto_approve') {
2887
+ const prevPhase = updatedState.phase;
2874
2888
  updatedState.phase = gateResult.next_phase;
2875
2889
  updatedState.phase_entered_at = now;
2876
2890
  updatedState.last_gate_failure = null;
@@ -2890,6 +2904,18 @@ function _acceptGovernedTurnLocked(root, config, opts) {
2890
2904
  gate_id: gateResult.gate_id,
2891
2905
  timestamp: now,
2892
2906
  });
2907
+ emitRunEvent(root, 'phase_entered', {
2908
+ run_id: updatedState.run_id,
2909
+ phase: updatedState.phase,
2910
+ status: updatedState.status,
2911
+ turn: { turn_id: currentTurn.turn_id, role_id: currentTurn.assigned_role },
2912
+ payload: {
2913
+ from: prevPhase,
2914
+ to: gateResult.next_phase,
2915
+ gate_id: gateResult.gate_id || 'no_gate',
2916
+ trigger: 'auto_approved',
2917
+ },
2918
+ });
2893
2919
  } else {
2894
2920
  updatedState.status = 'paused';
2895
2921
  updatedState.blocked_on = `human_approval:${gateResult.gate_id}`;
@@ -2926,6 +2952,18 @@ function _acceptGovernedTurnLocked(root, config, opts) {
2926
2952
  type: 'gate_failure',
2927
2953
  ...gateFailure,
2928
2954
  });
2955
+ emitRunEvent(root, 'gate_failed', {
2956
+ run_id: updatedState.run_id,
2957
+ phase: updatedState.phase,
2958
+ status: updatedState.status,
2959
+ turn: { turn_id: currentTurn.turn_id, role_id: currentTurn.assigned_role },
2960
+ payload: {
2961
+ gate_id: gateResult.gate_id || 'no_gate',
2962
+ from_phase: state.phase,
2963
+ to_phase: gateResult.transition_request || state.queued_phase_transition?.to || null,
2964
+ reasons: gateFailure.reasons || [],
2965
+ },
2966
+ });
2929
2967
  } else if (state.queued_phase_transition) {
2930
2968
  updatedState.queued_phase_transition = null;
2931
2969
  }
@@ -3331,7 +3369,13 @@ export function rejectGovernedTurn(root, config, validationResult, reasonOrOptio
3331
3369
  phase: updatedState.phase,
3332
3370
  status: updatedState.status,
3333
3371
  turn: { turn_id: currentTurn.turn_id, role_id: currentTurn.assigned_role },
3334
- payload: { attempt: currentAttempt, retrying: true },
3372
+ payload: {
3373
+ attempt: currentAttempt,
3374
+ retrying: true,
3375
+ reason: rejectionContext.reason,
3376
+ failed_stage: rejectionContext.failed_stage,
3377
+ ...(rejectionContext.validation_errors?.length ? { validation_errors: rejectionContext.validation_errors } : {}),
3378
+ },
3335
3379
  });
3336
3380
  return {
3337
3381
  ok: true,
@@ -3398,7 +3442,14 @@ export function rejectGovernedTurn(root, config, validationResult, reasonOrOptio
3398
3442
  phase: updatedState.phase,
3399
3443
  status: 'blocked',
3400
3444
  turn: { turn_id: currentTurn.turn_id, role_id: currentTurn.assigned_role },
3401
- payload: { attempt: currentAttempt, retrying: false, escalated: true },
3445
+ payload: {
3446
+ attempt: currentAttempt,
3447
+ retrying: false,
3448
+ escalated: true,
3449
+ reason: rejectionContext.reason,
3450
+ failed_stage: rejectionContext.failed_stage,
3451
+ ...(rejectionContext.validation_errors?.length ? { validation_errors: rejectionContext.validation_errors } : {}),
3452
+ },
3402
3453
  });
3403
3454
  emitRunEvent(root, 'run_blocked', {
3404
3455
  run_id: updatedState.run_id,
@@ -3527,7 +3578,12 @@ export function approvePhaseTransition(root, config) {
3527
3578
  run_id: updatedState.run_id,
3528
3579
  phase: updatedState.phase,
3529
3580
  status: 'active',
3530
- payload: { from: transition.from },
3581
+ payload: {
3582
+ from: transition.from,
3583
+ to: transition.to,
3584
+ gate_id: transition.gate || 'no_gate',
3585
+ trigger: 'human_approved',
3586
+ },
3531
3587
  });
3532
3588
 
3533
3589
  // Session checkpoint — non-fatal
@@ -23,6 +23,7 @@ export const VALID_RUN_EVENTS = [
23
23
  'escalation_resolved',
24
24
  'gate_pending',
25
25
  'gate_approved',
26
+ 'gate_failed',
26
27
  'budget_exceeded_warn',
27
28
  ];
28
29