agentxchain 2.155.45 → 2.155.47

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.45",
3
+ "version": "2.155.47",
4
4
  "description": "CLI for AgentXchain — governed multi-agent software delivery",
5
5
  "type": "module",
6
6
  "bin": {
@@ -69,6 +69,10 @@ export const BASELINE_EXEMPT_PATH_PREFIXES = Object.freeze([
69
69
  '.agentxchain/proposed/',
70
70
  ]);
71
71
 
72
+ export const DOGFOOD_EVIDENCE_PATH_PREFIXES = Object.freeze([
73
+ '.planning/dogfood-100-turn-evidence/',
74
+ ]);
75
+
72
76
  const GENERATED_REPORT_PATH_PATTERNS = Object.freeze([
73
77
  /^\.agentxchain\/reports\/report-[^/]+\.md$/,
74
78
  /^\.agentxchain\/reports\/export-[^/]+\.json$/,
@@ -122,7 +126,8 @@ export function classifyRepoPath(filePath) {
122
126
  || pathMatchesAnyRoot(filePath, RUN_CONTINUITY_DIRECTORY_ROOTS);
123
127
  const baselineExempt = operational
124
128
  || continuityState
125
- || pathMatchesAnyPrefix(filePath, BASELINE_EXEMPT_PATH_PREFIXES);
129
+ || pathMatchesAnyPrefix(filePath, BASELINE_EXEMPT_PATH_PREFIXES)
130
+ || pathMatchesAnyPrefix(filePath, DOGFOOD_EVIDENCE_PATH_PREFIXES);
126
131
 
127
132
  return {
128
133
  operational,
@@ -148,6 +153,10 @@ export function isRunContinuityPath(filePath) {
148
153
  return classifyRepoPath(filePath).continuityState;
149
154
  }
150
155
 
156
+ export function isDogfoodEvidencePath(filePath) {
157
+ return pathMatchesAnyPrefix(filePath, DOGFOOD_EVIDENCE_PATH_PREFIXES);
158
+ }
159
+
151
160
  export function normalizeCheckpointableFiles(filesChanged) {
152
161
  return [...new Set(
153
162
  (Array.isArray(filesChanged) ? filesChanged : [])
@@ -249,8 +258,10 @@ export function observeChanges(root, baseline) {
249
258
 
250
259
  changedFiles = filterBaselineDirtyFiles(root, changedFiles, baseline);
251
260
 
252
- // Filter out orchestrator-owned operational paths (Session #19 freeze)
253
- const actorFiles = changedFiles.filter(f => !isOperationalPath(f));
261
+ // Filter out orchestrator-owned operational paths (Session #19 freeze) and
262
+ // DOGFOOD-100 proof evidence, which is operator-proof metadata for this
263
+ // repository's formal dogfood run rather than turn-authored product work.
264
+ const actorFiles = changedFiles.filter(f => !isOperationalPath(f) && !isDogfoodEvidencePath(f));
254
265
 
255
266
  return {
256
267
  files_changed: actorFiles.sort(),
@@ -36,7 +36,7 @@ import {
36
36
  } from './runner-interface.js';
37
37
 
38
38
  import { runAdmissionControl } from './admission-control.js';
39
- import { appendFileSync, mkdirSync, writeFileSync } from 'fs';
39
+ import { appendFileSync, existsSync, mkdirSync, writeFileSync } from 'fs';
40
40
  import { join, dirname } from 'path';
41
41
  import { evaluateApprovalSlaReminders } from './notification-runner.js';
42
42
  import { validatePreemptionMarker } from './intake.js';
@@ -162,6 +162,26 @@ export async function runLoop(root, config, callbacks, options = {}) {
162
162
  }
163
163
  }
164
164
 
165
+ const failedAcceptanceResult = await reattemptFailedAcceptanceTurn(root, config, state, callbacks, emit, errors);
166
+ if (failedAcceptanceResult) {
167
+ if (failedAcceptanceResult.terminal) {
168
+ return makeResult(
169
+ failedAcceptanceResult.ok,
170
+ failedAcceptanceResult.stop_reason,
171
+ loadState(root, config),
172
+ turnsExecuted,
173
+ turnHistory,
174
+ gatesApproved,
175
+ errors,
176
+ );
177
+ }
178
+ if (failedAcceptanceResult.accepted) {
179
+ turnsExecuted++;
180
+ }
181
+ turnHistory.push(...failedAcceptanceResult.history);
182
+ continue;
183
+ }
184
+
165
185
  // ── Determine concurrency mode ────────────────────────────────────────
166
186
  const maxConcurrent = getMaxConcurrentTurns(config, state.phase);
167
187
 
@@ -490,6 +510,43 @@ function isDispatchableActiveTurn(turn) {
490
510
  return ['assigned', 'dispatched', 'starting', 'running', 'retrying'].includes(turn?.status);
491
511
  }
492
512
 
513
+ async function reattemptFailedAcceptanceTurn(root, config, state, callbacks, emit, errors) {
514
+ const turn = Object.values(getActiveTurns(state)).find(t => t?.status === 'failed_acceptance');
515
+ if (!turn) return null;
516
+
517
+ const roleId = turn.assigned_role;
518
+ const stagingPath = getTurnStagingResultPath(turn.turn_id);
519
+ if (!existsSync(join(root, stagingPath))) {
520
+ errors.push(`failed_acceptance(${roleId}): missing staged result at ${stagingPath}`);
521
+ return { terminal: true, ok: false, stop_reason: 'blocked', history: [] };
522
+ }
523
+
524
+ const acceptResult = acceptTurn(root, config, { turnId: turn.turn_id });
525
+ if (!acceptResult.ok) {
526
+ errors.push(`acceptTurn(${roleId}): ${acceptResult.error}`);
527
+ return {
528
+ terminal: true,
529
+ ok: false,
530
+ stop_reason: acceptResult.error_code === 'conflict' ? 'conflict_loop' : 'blocked',
531
+ history: [{ role: roleId, turn_id: turn.turn_id, accepted: false, accept_error: acceptResult.error }],
532
+ };
533
+ }
534
+
535
+ const history = [{ role: roleId, turn_id: turn.turn_id, accepted: true }];
536
+ if (callbacks.afterAccept) {
537
+ const afterAcceptResult = await callbacks.afterAccept({ turn, acceptResult });
538
+ if (afterAcceptResult?.ok === false) {
539
+ errors.push(`afterAccept(${roleId}): ${afterAcceptResult.error}`);
540
+ if (afterAcceptResult.state) {
541
+ emit({ type: 'blocked', state: afterAcceptResult.state, reason: 'after_accept_failed' });
542
+ }
543
+ return { terminal: true, ok: false, stop_reason: 'blocked', history };
544
+ }
545
+ }
546
+ emit({ type: 'turn_accepted', turn, role: roleId, state: acceptResult.state });
547
+ return { terminal: false, accepted: true, history };
548
+ }
549
+
493
550
  /**
494
551
  * Dispatch a single turn and process its result.
495
552
  */