agentxchain 2.40.0 → 2.42.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.40.0",
3
+ "version": "2.42.0",
4
4
  "description": "CLI for AgentXchain — governed multi-agent software delivery",
5
5
  "type": "module",
6
6
  "bin": {
@@ -56,6 +56,8 @@ ALLOWED_RELEASE_PATHS=(
56
56
  ".agentxchain-conformance/capabilities.json"
57
57
  "website-v2/docs/protocol-implementor-guide.mdx"
58
58
  ".planning/LAUNCH_EVIDENCE_REPORT.md"
59
+ "website-v2/static/llms.txt"
60
+ "website-v2/static/sitemap.xml"
59
61
  "cli/homebrew/agentxchain.rb"
60
62
  "cli/homebrew/README.md"
61
63
  )
@@ -168,6 +170,17 @@ if ! grep -qE "^# Launch Evidence Report — AgentXchain v${ESCAPED_VERSION}" "$
168
170
  SURFACE_ERRORS+=("LAUNCH_EVIDENCE_REPORT.md title does not carry v${TARGET_VERSION}")
169
171
  fi
170
172
 
173
+ # 4h. llms.txt must list the current release notes route
174
+ CURRENT_RELEASE_ROUTE="/docs/releases/${RELEASE_DOC_ID}"
175
+ if ! grep -q "${CURRENT_RELEASE_ROUTE}" "${REPO_ROOT}/website-v2/static/llms.txt" 2>/dev/null; then
176
+ SURFACE_ERRORS+=("website-v2/static/llms.txt does not list '${CURRENT_RELEASE_ROUTE}'")
177
+ fi
178
+
179
+ # 4i. sitemap.xml must list the current release notes route
180
+ if ! grep -q "${CURRENT_RELEASE_ROUTE}" "${REPO_ROOT}/website-v2/static/sitemap.xml" 2>/dev/null; then
181
+ SURFACE_ERRORS+=("website-v2/static/sitemap.xml does not list '${CURRENT_RELEASE_ROUTE}'")
182
+ fi
183
+
171
184
  if [[ "${#SURFACE_ERRORS[@]}" -gt 0 ]]; then
172
185
  echo "FAIL: ${#SURFACE_ERRORS[@]} version-surface(s) not aligned to ${TARGET_VERSION}:" >&2
173
186
  printf ' - %s\n' "${SURFACE_ERRORS[@]}" >&2
@@ -176,7 +189,7 @@ if [[ "${#SURFACE_ERRORS[@]}" -gt 0 ]]; then
176
189
  echo "create release identity when governed surfaces are stale." >&2
177
190
  exit 1
178
191
  fi
179
- echo " OK: all 7 governed version surfaces reference ${TARGET_VERSION}"
192
+ echo " OK: all 9 governed version surfaces reference ${TARGET_VERSION}"
180
193
 
181
194
  # 5. Auto-align Homebrew mirror to target version
182
195
  # The formula URL and README version/tarball are updated automatically.
@@ -79,6 +79,7 @@ export function validateStagedTurnResult(root, state, config, opts = {}) {
79
79
  const activeTurn = getActiveTurn(state) || state.current_turn;
80
80
  if (activeTurn) {
81
81
  const roleKey = activeTurn.assigned_role || activeTurn.role;
82
+ normContext.assignedRole = roleKey;
82
83
  const roleConfig = config?.roles?.[roleKey];
83
84
  if (roleConfig) {
84
85
  normContext.writeAuthority = roleConfig.write_authority;
@@ -562,6 +563,23 @@ export function normalizeTurnResult(tr, config, context = {}) {
562
563
  }
563
564
 
564
565
  const normalized = { ...tr };
566
+ const routing = config?.routing;
567
+ const phaseNames = routing ? Object.keys(routing) : [];
568
+ const currentPhase = context.phase;
569
+ const currentPhaseIndex = currentPhase ? phaseNames.indexOf(currentPhase) : -1;
570
+ const isKnownPhase = currentPhaseIndex >= 0;
571
+ const isTerminalPhase = isKnownPhase && currentPhaseIndex === phaseNames.length - 1;
572
+ const nextPhase = isKnownPhase && currentPhaseIndex + 1 < phaseNames.length
573
+ ? phaseNames[currentPhaseIndex + 1]
574
+ : null;
575
+ const allowedNextRoles = isKnownPhase ? (routing?.[currentPhase]?.allowed_next_roles || []) : [];
576
+ const assignedRole = context.assignedRole || normalized.role || null;
577
+ const isReviewOnly = context.writeAuthority === 'review_only';
578
+
579
+ const pickAllowedRoleFallback = () => {
580
+ if (allowedNextRoles.length === 0) return null;
581
+ return allowedNextRoles.find((role) => role !== assignedRole) || allowedNextRoles[0] || null;
582
+ };
565
583
 
566
584
  // ── Rule 0: infer missing status only when intent is unambiguous ──────
567
585
  if (!('status' in normalized)) {
@@ -604,7 +622,6 @@ export function normalizeTurnResult(tr, config, context = {}) {
604
622
  }
605
623
 
606
624
  // ── Rule 2: exit-gate-as-phase auto-correction ────────────────────────
607
- const routing = config?.routing;
608
625
  const gates = config?.gates;
609
626
  if (
610
627
  typeof normalized.phase_transition_request === 'string' &&
@@ -670,6 +687,80 @@ export function normalizeTurnResult(tr, config, context = {}) {
670
687
  }
671
688
  }
672
689
 
690
+ // ── Rule 4: infer missing lifecycle signal for completed turns ────────
691
+ if (
692
+ isKnownPhase &&
693
+ isReviewOnly &&
694
+ normalized.status === 'completed' &&
695
+ normalized.run_completion_request == null &&
696
+ !normalized.phase_transition_request
697
+ ) {
698
+ if (isTerminalPhase) {
699
+ normalized.run_completion_request = true;
700
+ corrections.push(
701
+ `run_completion_request: inferred true for completed terminal phase "${currentPhase}"`
702
+ );
703
+ } else if (nextPhase) {
704
+ normalized.phase_transition_request = nextPhase;
705
+ corrections.push(
706
+ `phase_transition_request: inferred next phase "${nextPhase}" for completed phase "${currentPhase}"`
707
+ );
708
+ }
709
+ }
710
+
711
+ // ── Rule 5: correct invalid or non-forward lifecycle requests ─────────
712
+ if (
713
+ isKnownPhase &&
714
+ isReviewOnly &&
715
+ normalized.status === 'completed' &&
716
+ typeof normalized.phase_transition_request === 'string' &&
717
+ !normalized.run_completion_request
718
+ ) {
719
+ const requested = normalized.phase_transition_request;
720
+ const requestedIndex = phaseNames.indexOf(requested);
721
+ const invalidPhase = !(requested in (routing || {}));
722
+ const notForward = requestedIndex >= 0 && requestedIndex <= currentPhaseIndex;
723
+
724
+ if (invalidPhase || notForward) {
725
+ if (nextPhase) {
726
+ normalized.phase_transition_request = nextPhase;
727
+ corrections.push(
728
+ `phase_transition_request: corrected "${requested}" to forward phase "${nextPhase}"`
729
+ );
730
+ } else if (isTerminalPhase) {
731
+ normalized.phase_transition_request = null;
732
+ normalized.run_completion_request = true;
733
+ corrections.push(
734
+ `phase_transition_request: corrected terminal/non-forward "${requested}" to run_completion_request: true`
735
+ );
736
+ }
737
+ }
738
+ }
739
+
740
+ // ── Rule 6: repair routing-illegal next-role signals only when safe ───
741
+ if (isReviewOnly && normalized.run_completion_request === true && !normalized.phase_transition_request) {
742
+ if (normalized.proposed_next_role !== 'human') {
743
+ normalized.proposed_next_role = 'human';
744
+ corrections.push('proposed_next_role: corrected to "human" for run completion');
745
+ }
746
+ } else if (
747
+ isKnownPhase &&
748
+ isReviewOnly &&
749
+ normalized.status === 'completed' &&
750
+ typeof normalized.proposed_next_role === 'string' &&
751
+ normalized.proposed_next_role !== 'human' &&
752
+ allowedNextRoles.length > 0 &&
753
+ !allowedNextRoles.includes(normalized.proposed_next_role)
754
+ ) {
755
+ const fallback = pickAllowedRoleFallback();
756
+ if (fallback) {
757
+ corrections.push(
758
+ `proposed_next_role: corrected "${normalized.proposed_next_role}" to allowed role "${fallback}"`
759
+ );
760
+ normalized.proposed_next_role = fallback;
761
+ }
762
+ }
763
+
673
764
  return { normalized, corrections };
674
765
  }
675
766