agentxchain 2.155.0 → 2.155.2

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.155.0",
3
+ "version": "2.155.2",
4
4
  "description": "CLI for AgentXchain — governed multi-agent software delivery",
5
5
  "type": "module",
6
6
  "bin": {
@@ -349,7 +349,7 @@ async function runDueSchedules(context, opts = {}) {
349
349
  // ---------------------------------------------------------------------------
350
350
 
351
351
  function isSessionTerminal(session) {
352
- return ['completed', 'idle_exit', 'failed', 'stopped', 'vision_exhausted', 'vision_expansion_exhausted'].includes(session?.status);
352
+ return ['completed', 'idle_exit', 'failed', 'stopped', 'vision_exhausted', 'vision_expansion_exhausted', 'session_budget'].includes(session?.status);
353
353
  }
354
354
 
355
355
  function getContinuousEnabledScheduleIds(config) {
@@ -498,6 +498,7 @@ async function advanceScheduleContinuousSession(context, entry, opts = {}) {
498
498
  blocked: 'continuous_blocked',
499
499
  vision_exhausted: 'continuous_vision_exhausted',
500
500
  vision_expansion_exhausted: 'continuous_vision_expansion_exhausted',
501
+ session_budget: 'continuous_session_budget_exhausted',
501
502
  running: 'continuous_running',
502
503
  };
503
504
  let schedStatus = statusMap[step.status] || 'continuous_running';
@@ -1148,14 +1148,37 @@ export async function advanceContinuousRunOnce(context, session, contOpts, execu
1148
1148
  // Session budget check (cumulative spend across all runs) — before idle policy
1149
1149
  const sessionBudget = session.per_session_max_usd ?? contOpts.perSessionMaxUsd ?? null;
1150
1150
  if (sessionBudget != null && (session.cumulative_spent_usd || 0) >= sessionBudget) {
1151
- session.status = 'completed';
1151
+ session.status = 'session_budget';
1152
1152
  session.budget_exhausted = true;
1153
1153
  writeContinuousSession(root, session);
1154
1154
  log(`Session budget exhausted: $${(session.cumulative_spent_usd || 0).toFixed(2)} spent of $${sessionBudget.toFixed(2)} limit.`);
1155
- return { ok: true, status: 'completed', action: 'session_budget_exhausted', stop_reason: 'session_budget' };
1155
+ return { ok: true, status: 'session_budget', action: 'session_budget_exhausted', stop_reason: 'session_budget' };
1156
+ }
1157
+
1158
+ reconcileContinuousStartupState(context, session, contOpts, log);
1159
+
1160
+ const reconcileBlock = maybeAutoReconcileOperatorCommits(context, session, contOpts, log);
1161
+ if (reconcileBlock) return reconcileBlock;
1162
+
1163
+ const startupGovernedState = loadProjectState(root, context.config);
1164
+ if (startupGovernedState?.status === 'blocked') {
1165
+ const retried = await maybeAutoRetryGhostBlocker(context, session, contOpts, startupGovernedState, log);
1166
+ if (retried) return retried;
1167
+ session.status = 'paused';
1168
+ writeContinuousSession(root, session);
1169
+ return {
1170
+ ok: true,
1171
+ status: 'blocked',
1172
+ action: 'still_blocked',
1173
+ run_id: session.current_run_id || startupGovernedState.run_id || null,
1174
+ recovery_action: getBlockedRecoveryAction(startupGovernedState),
1175
+ blocked_category: getBlockedCategory(startupGovernedState),
1176
+ };
1156
1177
  }
1157
1178
 
1158
- // Idle-cycle check: on_idle policy determines behavior
1179
+ // Idle-cycle check: on_idle policy determines behavior. This MUST run after
1180
+ // startup blocked/reconcile checks so perpetual mode cannot enqueue new
1181
+ // idle-expansion work into a run that is already ineligible to start.
1159
1182
  if (session.idle_cycles >= contOpts.maxIdleCycles) {
1160
1183
  if (contOpts.onIdle === 'perpetual' && contOpts.idleExpansion) {
1161
1184
  // BUG-60: perpetual mode — dispatch PM idle-expansion instead of exiting
@@ -1193,11 +1216,6 @@ export async function advanceContinuousRunOnce(context, session, contOpts, execu
1193
1216
  return { ok: true, status: 'idle_exit', action: 'max_idle_reached', stop_reason: 'idle_exit' };
1194
1217
  }
1195
1218
 
1196
- reconcileContinuousStartupState(context, session, contOpts, log);
1197
-
1198
- const reconcileBlock = maybeAutoReconcileOperatorCommits(context, session, contOpts, log);
1199
- if (reconcileBlock) return reconcileBlock;
1200
-
1201
1219
  // Paused-session guard: if session is paused (blocked run awaiting unblock),
1202
1220
  // check governed state before attempting to advance. Without this guard, the
1203
1221
  // loop would try to startIntent() on a blocked project, hit the blocked-state
@@ -1634,7 +1652,7 @@ export async function executeContinuousRun(context, contOpts, executeGovernedRun
1634
1652
  const step = await advanceContinuousRunOnce(context, session, contOpts, executeGovernedRun, log);
1635
1653
 
1636
1654
  // Terminal states
1637
- if (step.status === 'completed' || step.status === 'idle_exit' || step.status === 'failed' || step.status === 'blocked' || step.status === 'stopped' || step.status === 'vision_exhausted' || step.status === 'vision_expansion_exhausted') {
1655
+ if (step.status === 'completed' || step.status === 'idle_exit' || step.status === 'failed' || step.status === 'blocked' || step.status === 'stopped' || step.status === 'vision_exhausted' || step.status === 'vision_expansion_exhausted' || step.status === 'session_budget') {
1638
1656
  const terminalMessage = describeContinuousTerminalStep(step, contOpts);
1639
1657
  if (terminalMessage) {
1640
1658
  log(terminalMessage);