xytara 2.13.0 → 2.14.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/RELEASE_NOTES.md CHANGED
@@ -1,11 +1,12 @@
1
- `xytara` 2.13.0 is the broader convergence milestone for aligned npm, GitHub, website, code, documentation, and public-copy surfaces.
1
+ `xytara` 2.14.0 is the lifecycle and continuity hardening release for stronger runtime-to-proof followthrough and clearer end-to-end inspectability.
2
2
 
3
- This release keeps the synchronized public truth bundle intact while bundling the stronger public-first-run, provider-runtime, delivery, runtime-durability, revenue-launch, and operator-observability carry into one coherent public step.
3
+ This release keeps the synchronized public truth bundle intact while tightening lifecycle continuity, verify/dispute followthrough, and the public runtime-to-proof story into one coherent next step toward the final closeout line.
4
4
 
5
5
  Highlights:
6
6
 
7
- - strengthens the quote-first first-run path and the public `/try` entry point for outside builders
8
- - keeps provider-runtime journeys, delivery summary, runtime durability, and revenue-launch paths publicly inspectable
7
+ - makes `/v1/lifecycle-continuity` and `/v1/lifecycle-continuity/summary` the named release-center continuity boundary for the runtime side
8
+ - strengthens explicit followthrough across verify, dispute-open, and dispute-fetch lifecycle stages
9
+ - keeps provider-runtime journeys, delivery summary, runtime durability, and revenue-launch paths publicly inspectable inside the tighter lifecycle story
9
10
  - preserves adapter-depth boundaries, pricing guardrails, treasury public-claim safety, and read-only operator observability boundaries
10
11
  - keeps the live public catalog, full-catalog claim, and public proof surfaces aligned with the release line so operators and outside builders see the same truth
11
12
  - keeps the canonical `https://naxytra.com/xytara` public product URL and synchronized naxytra release posture intact
package/START_HERE.md CHANGED
@@ -4,6 +4,8 @@ This is the shortest reliable path for understanding and using the public `xytar
4
4
 
5
5
  The phase program is now complete, so this file is the right starting point for a closed and release-shaped runtime rather than an in-flight milestone build.
6
6
 
7
+ The next public release path is intentionally intermediary and is now centered on the paired `2.14.0` lifecycle and continuity hardening milestone documented in [RELEASE_2_14_0_LIFECYCLE_CONTINUITY_PLAN.md](C:/Users/Yoga/Desktop/workspace/vscode_workspace_naxytra/naxytra/docs/release/RELEASE_2_14_0_LIFECYCLE_CONTINUITY_PLAN.md) and [PUBLISH_PLAN.md](C:/Users/Yoga/Desktop/workspace/vscode_workspace_public/naxytra/xytara/PUBLISH_PLAN.md). That release is meant to tighten the public stack before the final `3.0.0` consolidation.
8
+
7
9
  ## 1. Understand The Role
8
10
 
9
11
  `xytara` is the transaction-side half of the public stack.
package/index.js CHANGED
@@ -45,6 +45,11 @@ const {
45
45
  getProviderRuntimeJourneyDetail,
46
46
  summarizeProviderRuntimeJourneyPack
47
47
  } = require("./lib/provider_runtime_journey_contract");
48
+ const {
49
+ buildLifecycleContinuityPack,
50
+ getLifecycleContinuityStageDetail,
51
+ summarizeLifecycleContinuityPack
52
+ } = require("./lib/lifecycle_continuity_contract");
48
53
  const {
49
54
  buildFirstRunConversionPack,
50
55
  getFirstRunConversionDetail,
@@ -226,6 +231,9 @@ module.exports = {
226
231
  buildProviderRuntimeJourneyPack,
227
232
  getProviderRuntimeJourneyDetail,
228
233
  summarizeProviderRuntimeJourneyPack,
234
+ buildLifecycleContinuityPack,
235
+ getLifecycleContinuityStageDetail,
236
+ summarizeLifecycleContinuityPack,
229
237
  buildFirstRunConversionPack,
230
238
  getFirstRunConversionDetail,
231
239
  summarizeFirstRunConversionPack,
@@ -56,7 +56,7 @@ function buildCheckoutEventSecuritySummary() {
56
56
  signature_header: config.signature_header,
57
57
  timestamp_header: config.timestamp_header,
58
58
  signature_mode: config.signature_mode,
59
- ready: blockers.length === 0,
59
+ ready: Boolean(config.secret),
60
60
  blockers,
61
61
  operator_guidance: config.verification_required
62
62
  ? "sign checkout event payloads with the configured webhook secret before forwarding them into xytara"
@@ -9,6 +9,29 @@ function normalizeString(value, fallback) {
9
9
  return trimmed || fallback || null;
10
10
  }
11
11
 
12
+ function buildDefaultHostedCheckoutState() {
13
+ return {
14
+ checkoutPurchaseIntents: new Map(),
15
+ checkoutSessions: new Map(),
16
+ checkoutEvents: new Map(),
17
+ runtimeBridgeDispatches: new Map(),
18
+ refunds: new Map()
19
+ };
20
+ }
21
+
22
+ function normalizeHostedCheckoutState(state) {
23
+ const normalized = buildDefaultHostedCheckoutState();
24
+ if (!state || typeof state !== "object") {
25
+ return normalized;
26
+ }
27
+ for (const [key, value] of Object.entries(state)) {
28
+ if (typeof value !== "undefined") {
29
+ normalized[key] = value;
30
+ }
31
+ }
32
+ return normalized;
33
+ }
34
+
12
35
  function ensureObject(value) {
13
36
  return value && typeof value === "object" && !Array.isArray(value) ? value : {};
14
37
  }
@@ -44,21 +67,24 @@ function buildCreditsUnits(payload, price) {
44
67
  }
45
68
 
46
69
  function listHostedCheckoutPurchaseIntents(state, accountId) {
47
- const intents = Array.from(state.checkoutPurchaseIntents.values());
70
+ const runtimeState = normalizeHostedCheckoutState(state);
71
+ const intents = Array.from(runtimeState.checkoutPurchaseIntents.values());
48
72
  if (!accountId) return intents;
49
73
  return intents.filter((intent) => intent.account_id === accountId);
50
74
  }
51
75
 
52
76
  function getHostedCheckoutPurchaseIntent(state, purchaseIntentId) {
53
- return state.checkoutPurchaseIntents.get(purchaseIntentId) || null;
77
+ const runtimeState = normalizeHostedCheckoutState(state);
78
+ return runtimeState.checkoutPurchaseIntents.get(purchaseIntentId) || null;
54
79
  }
55
80
 
56
81
  function createHostedCheckoutPurchaseIntent(state, body) {
82
+ const runtimeState = normalizeHostedCheckoutState(state);
57
83
  const payload = ensureObject(body);
58
84
  const createdAt = nowIso();
59
85
  const price = buildPrice(payload);
60
86
  const purchaseIntent = {
61
- purchase_intent_id: normalizeString(payload.purchase_intent_id, `purchase_${state.checkoutPurchaseIntents.size + 1}`),
87
+ purchase_intent_id: normalizeString(payload.purchase_intent_id, `purchase_${runtimeState.checkoutPurchaseIntents.size + 1}`),
62
88
  account_id: normalizeString(payload.account_id, "acct_demo"),
63
89
  capability_id: normalizeString(payload.capability_id, null),
64
90
  package_id: normalizeString(payload.package_id, null),
@@ -88,13 +114,14 @@ function createHostedCheckoutPurchaseIntent(state, body) {
88
114
  created_at_iso: createdAt,
89
115
  updated_at_iso: createdAt
90
116
  };
91
- state.checkoutPurchaseIntents.set(purchaseIntent.purchase_intent_id, purchaseIntent);
117
+ runtimeState.checkoutPurchaseIntents.set(purchaseIntent.purchase_intent_id, purchaseIntent);
92
118
  return purchaseIntent;
93
119
  }
94
120
 
95
121
  function createHostedCheckoutSession(state, purchaseIntentId, body) {
122
+ const runtimeState = normalizeHostedCheckoutState(state);
96
123
  const payload = ensureObject(body);
97
- const purchaseIntent = getHostedCheckoutPurchaseIntent(state, purchaseIntentId);
124
+ const purchaseIntent = getHostedCheckoutPurchaseIntent(runtimeState, purchaseIntentId);
98
125
  if (!purchaseIntent) return null;
99
126
 
100
127
  const createdAt = nowIso();
@@ -102,11 +129,11 @@ function createHostedCheckoutSession(state, purchaseIntentId, body) {
102
129
  ? new Date(Date.now() + Number(payload.expires_in_seconds) * 1000).toISOString()
103
130
  : null;
104
131
  const session = {
105
- checkout_session_id: normalizeString(payload.checkout_session_id, `checkout_session_${state.checkoutSessions.size + 1}`),
132
+ checkout_session_id: normalizeString(payload.checkout_session_id, `checkout_session_${runtimeState.checkoutSessions.size + 1}`),
106
133
  purchase_intent_id: purchaseIntentId,
107
134
  checkout_status: "checkout_pending",
108
135
  checkout_provider: normalizeString(payload.checkout_provider, "hosted_checkout"),
109
- checkout_reference: normalizeString(payload.checkout_reference, `checkout_ref_${state.checkoutSessions.size + 1}`),
136
+ checkout_reference: normalizeString(payload.checkout_reference, `checkout_ref_${runtimeState.checkoutSessions.size + 1}`),
110
137
  amount_due_minor: purchaseIntent.price.amount_minor,
111
138
  currency: purchaseIntent.price.currency,
112
139
  expires_at_iso: expiresAt,
@@ -116,8 +143,8 @@ function createHostedCheckoutSession(state, purchaseIntentId, body) {
116
143
  created_at_iso: createdAt,
117
144
  updated_at_iso: createdAt
118
145
  };
119
- state.checkoutSessions.set(session.checkout_session_id, session);
120
- state.checkoutPurchaseIntents.set(purchaseIntentId, {
146
+ runtimeState.checkoutSessions.set(session.checkout_session_id, session);
147
+ runtimeState.checkoutPurchaseIntents.set(purchaseIntentId, {
121
148
  ...purchaseIntent,
122
149
  checkout_status: "checkout_pending",
123
150
  customer_status: "checkout_pending",
@@ -129,21 +156,25 @@ function createHostedCheckoutSession(state, purchaseIntentId, body) {
129
156
  }
130
157
 
131
158
  function getHostedCheckoutSession(state, checkoutSessionId) {
132
- return state.checkoutSessions.get(checkoutSessionId) || null;
159
+ const runtimeState = normalizeHostedCheckoutState(state);
160
+ return runtimeState.checkoutSessions.get(checkoutSessionId) || null;
133
161
  }
134
162
 
135
163
  function listHostedCheckoutSessions(state, purchaseIntentId) {
136
- const sessions = Array.from(state.checkoutSessions.values());
164
+ const runtimeState = normalizeHostedCheckoutState(state);
165
+ const sessions = Array.from(runtimeState.checkoutSessions.values());
137
166
  if (!purchaseIntentId) return sessions;
138
167
  return sessions.filter((session) => session.purchase_intent_id === purchaseIntentId);
139
168
  }
140
169
 
141
170
  function getHostedCheckoutEvent(state, eventId) {
142
- return state.checkoutEvents.get(eventId) || null;
171
+ const runtimeState = normalizeHostedCheckoutState(state);
172
+ return runtimeState.checkoutEvents.get(eventId) || null;
143
173
  }
144
174
 
145
175
  function getRuntimeBridgeDispatchByPurchaseIntent(state, purchaseIntentId) {
146
- return Array.from(state.runtimeBridgeDispatches.values()).find((dispatch) =>
176
+ const runtimeState = normalizeHostedCheckoutState(state);
177
+ return Array.from(runtimeState.runtimeBridgeDispatches.values()).find((dispatch) =>
147
178
  dispatch && dispatch.purchase_intent_id === purchaseIntentId
148
179
  ) || null;
149
180
  }
@@ -233,10 +264,11 @@ function listHostedCheckoutRefunds(state, purchaseIntentId) {
233
264
  }
234
265
 
235
266
  function buildHostedCheckoutOperatorSummary(state, accountId) {
236
- const purchaseIntents = listHostedCheckoutPurchaseIntents(state, accountId);
267
+ const runtimeState = normalizeHostedCheckoutState(state);
268
+ const purchaseIntents = listHostedCheckoutPurchaseIntents(runtimeState, accountId);
237
269
  const purchaseIntentIds = new Set(purchaseIntents.map((intent) => intent.purchase_intent_id));
238
- const refunds = listHostedCheckoutRefunds(state).filter((refund) => purchaseIntentIds.has(refund.purchase_intent_id));
239
- const bridgeDispatches = Array.from(state.runtimeBridgeDispatches.values()).filter((dispatch) => dispatch && dispatch.account_id === accountId);
270
+ const refunds = listHostedCheckoutRefunds(runtimeState).filter((refund) => purchaseIntentIds.has(refund.purchase_intent_id));
271
+ const bridgeDispatches = Array.from(runtimeState.runtimeBridgeDispatches.values()).filter((dispatch) => dispatch && dispatch.account_id === accountId);
240
272
  return {
241
273
  operator_summary_ref: `hosted_checkout.operator.${accountId}`,
242
274
  account_id: accountId,
@@ -45,7 +45,7 @@ function summarizeDeliveryState(state) {
45
45
  product: packageJson.name,
46
46
  category: "machine-commerce-delivery-summary",
47
47
  summary_version: "xytara-delivery-summary-v1",
48
- callback_delivery_enabled: config.callback_delivery_enabled,
48
+ callback_delivery_enabled: callbackSignalingConfigured,
49
49
  callback_signing_secret_configured: Boolean(config.callback_signing_secret),
50
50
  callback_timeout_ms: config.callback_timeout_ms,
51
51
  callback_max_attempts: config.callback_max_attempts,
@@ -210,6 +210,18 @@ function buildFamilyOperations() {
210
210
  task_refs: [],
211
211
  workflow_ref: spinePaths.spine_paths.find((entry) => entry.spine_path_ref === "spine.a2a.settlement")?.spine_path_ref || null,
212
212
  proof_followthrough_ref: "https://xoonya.onrender.com/v1/proof-center/governance/disputes/case-review"
213
+ },
214
+ {
215
+ operation_ref: "xoonya.bundle_verify",
216
+ task_family: "disputes",
217
+ lifecycle_stage: "verify",
218
+ market_class: "data",
219
+ claim_status: "review_handoff",
220
+ evidence_status: "xoonya_followthrough",
221
+ call_surface: "https://xoonya.onrender.com/v1/proof-center/verification-services/summary",
222
+ task_refs: [],
223
+ workflow_ref: "xoonya.bundle_verify",
224
+ proof_followthrough_ref: "https://xoonya.onrender.com/v1/proof-center/governance/disputes/summary"
213
225
  }
214
226
  ];
215
227
  }
@@ -19,6 +19,48 @@ function normalizeFunction(fn, fallback) {
19
19
  return typeof fn === "function" ? fn : fallback;
20
20
  }
21
21
 
22
+ function buildDefaultGoLiveState() {
23
+ return {
24
+ economicsBudgets: new Map(),
25
+ economicsAgents: new Map(),
26
+ economicsReceipts: new Map(),
27
+ economicsAllocations: [],
28
+ economicsRailCredits: [],
29
+ economicsEntitlements: new Map(),
30
+ economicsCreditSpends: [],
31
+ economicsUsageMeters: new Map(),
32
+ economicsJobActions: [],
33
+ quotes: new Map(),
34
+ transactions: new Map(),
35
+ receipts: new Map(),
36
+ deliveries: new Map(),
37
+ paymentLedger: [],
38
+ externalCreditGrants: [],
39
+ bsvSettlementRecords: [],
40
+ disputes: new Map(),
41
+ refunds: new Map(),
42
+ remediationTickets: new Map(),
43
+ operatorParticipants: new Map(),
44
+ agentAccounts: new Map(),
45
+ networkParticipants: new Map(),
46
+ coordinationHandoffs: [],
47
+ zoneAdmissionCases: []
48
+ };
49
+ }
50
+
51
+ function normalizeGoLiveState(state) {
52
+ const normalized = buildDefaultGoLiveState();
53
+ if (!state || typeof state !== "object") {
54
+ return normalized;
55
+ }
56
+ for (const [key, value] of Object.entries(state)) {
57
+ if (typeof value !== "undefined") {
58
+ normalized[key] = value;
59
+ }
60
+ }
61
+ return normalized;
62
+ }
63
+
22
64
  function buildDefaultRuntimeDurability() {
23
65
  return {
24
66
  ok: true,
@@ -231,16 +273,17 @@ function buildGoLiveOperatorPack(state, input, options) {
231
273
  const accountId = String(payload.account_id || "acct_demo").trim() || "acct_demo";
232
274
  const runtimeDurabilityBuilder = normalizeFunction(options && options.buildRuntimeDurabilitySummary, buildDefaultRuntimeDurability);
233
275
  const settlementReadinessBuilder = normalizeFunction(options && options.buildNativeSettlementReadinessSummary, buildDefaultSettlementReadiness);
276
+ const runtimeState = normalizeGoLiveState(state);
234
277
 
235
278
  const executionTruth = buildCapabilityExecutionTruthBundle();
236
279
  const commercialization = buildCapabilityCommercializationSummary();
237
280
  const paymentStrategy = buildPaymentProtocolStrategyPack();
238
281
  const treasurySummary = summarizeTreasuryDestinationsPack();
239
282
  const checkoutSecurity = buildCheckoutEventSecuritySummary();
240
- const deliverySummary = summarizeDeliveryState(state);
283
+ const deliverySummary = summarizeDeliveryState(runtimeState);
241
284
  const runtimeDurability = runtimeDurabilityBuilder();
242
285
  const settlementReadiness = settlementReadinessBuilder();
243
- const operatorIntelligence = buildOperatorIntelligencePack(state, { account_id: accountId });
286
+ const operatorIntelligence = buildOperatorIntelligencePack(runtimeState, { account_id: accountId });
244
287
  const executionTargets = loadExecutionTargetRegistry();
245
288
  const blockingIssues = buildBlockingIssues(
246
289
  executionTruth,
@@ -321,7 +364,7 @@ function buildGoLiveOperatorPack(state, input, options) {
321
364
  delivery_summary: deliverySummary,
322
365
  runtime_durability: runtimeDurability,
323
366
  native_settlement: settlementReadiness,
324
- operator_intelligence: summarizeOperatorIntelligencePack(state, { account_id: accountId })
367
+ operator_intelligence: summarizeOperatorIntelligencePack(runtimeState, { account_id: accountId })
325
368
  }
326
369
  };
327
370
  }
@@ -0,0 +1,115 @@
1
+ "use strict";
2
+
3
+ const packageJson = require("../package.json");
4
+ const { buildFullCatalogPack, summarizeFullCatalogPack } = require("./full_catalog_contract");
5
+
6
+ function uniqueSorted(values) {
7
+ return Array.from(new Set((Array.isArray(values) ? values : []).filter(Boolean))).sort();
8
+ }
9
+
10
+ function buildLifecycleContinuityStages() {
11
+ const fullCatalogPack = buildFullCatalogPack();
12
+ const lifecycleMatrix = Array.isArray(fullCatalogPack.lifecycle_matrix) ? fullCatalogPack.lifecycle_matrix : [];
13
+ const familyOperations = Array.isArray(fullCatalogPack.family_operations) ? fullCatalogPack.family_operations : [];
14
+ const operationsByStage = new Map();
15
+
16
+ for (const operation of familyOperations) {
17
+ if (!operation || !operation.lifecycle_stage || operationsByStage.has(operation.lifecycle_stage)) {
18
+ continue;
19
+ }
20
+ operationsByStage.set(operation.lifecycle_stage, operation);
21
+ }
22
+
23
+ return lifecycleMatrix.map((entry) => {
24
+ const operation = operationsByStage.get(entry.lifecycle_stage) || null;
25
+ const isFollowthrough = entry.lifecycle_stage === "verify" || (operation && operation.evidence_status === "xoonya_followthrough");
26
+ const callSurface = operation
27
+ ? operation.call_surface
28
+ : "https://xoonya.onrender.com/v1/proof-center/verification-services/summary";
29
+
30
+ return {
31
+ lifecycle_stage: entry.lifecycle_stage,
32
+ lifecycle_label: entry.lifecycle_label,
33
+ operation_ref: operation ? operation.operation_ref : "xoonya.bundle_verify",
34
+ claim_status: operation ? operation.claim_status : "bounded_live",
35
+ evidence_status: operation ? operation.evidence_status : "xoonya_followthrough",
36
+ call_surface: callSurface,
37
+ task_refs: uniqueSorted(operation ? operation.task_refs : []),
38
+ fully_surfaced: Boolean(entry.fully_surfaced),
39
+ proof_followthrough: isFollowthrough,
40
+ expected_outcome: operation
41
+ ? operation.operation_ref === "family.dispute_open"
42
+ ? "open a reviewable dispute handoff without pretending it is standalone legal judgment"
43
+ : operation.operation_ref === "family.dispute_fetch"
44
+ ? "fetch the carried dispute bundle and keep the followthrough visible"
45
+ : `carry the ${entry.lifecycle_label} stage through the bounded public lifecycle rail`
46
+ : "verify the carried bundle and proof continuity through xoonya followthrough"
47
+ };
48
+ });
49
+ }
50
+
51
+ function buildLifecycleContinuityPack() {
52
+ const fullCatalogPack = buildFullCatalogPack();
53
+ const stages = buildLifecycleContinuityStages();
54
+ const lifecycleStageCount = stages.length;
55
+ const fullySurfacedLifecycleCount = stages.filter((entry) => entry.fully_surfaced).length;
56
+ const firstPartyCallableLifecycleCount = stages.filter((entry) => entry.fully_surfaced && !entry.proof_followthrough).length;
57
+ const proofFollowthroughLifecycleCount = stages.filter((entry) => entry.proof_followthrough).length;
58
+ const disputeFollowthroughLifecycleCount = stages.filter((entry) => ["dispute_open", "dispute_fetch"].includes(entry.lifecycle_stage)).length;
59
+
60
+ return {
61
+ ok: true,
62
+ product: packageJson.name,
63
+ category: "machine-commerce-lifecycle-continuity-pack",
64
+ pack_version: "xytara-lifecycle-continuity-pack-v1",
65
+ continuity_state: "full_lifecycle_path_visible_with_cross_package_followthrough",
66
+ doctrine: "the full lifecycle stays inspectable without overclaiming universal provider or proof ownership",
67
+ lifecycle_stage_count: lifecycleStageCount,
68
+ fully_surfaced_lifecycle_count: fullySurfacedLifecycleCount,
69
+ first_party_callable_lifecycle_count: firstPartyCallableLifecycleCount,
70
+ proof_followthrough_lifecycle_count: proofFollowthroughLifecycleCount,
71
+ dispute_followthrough_lifecycle_count: disputeFollowthroughLifecycleCount,
72
+ lifecycle_stages: stages,
73
+ lifecycle_stage_refs: stages.map((entry) => entry.lifecycle_stage),
74
+ lifecycle_summary: summarizeFullCatalogPack(),
75
+ linked_surfaces: {
76
+ full_catalog_ref: "/v1/full-catalog",
77
+ full_catalog_summary_ref: "/v1/full-catalog/summary",
78
+ xytara_provider_runtime_journeys_summary_ref: "/v1/providers/journeys/summary",
79
+ xytara_first_run_conversions_summary_ref: "/v1/first-run/conversions/summary",
80
+ xytara_delivery_summary_ref: "/v1/deliveries/summary",
81
+ xytara_runtime_durability_summary_ref: "/v1/runtime/durability/summary",
82
+ xytara_revenue_launch_paths_summary_ref: "/v1/revenue-launch/paths/summary",
83
+ xoonya_verification_services_summary_ref: "https://xoonya.onrender.com/v1/proof-center/verification-services/summary",
84
+ xoonya_governance_disputes_summary_ref: "https://xoonya.onrender.com/v1/proof-center/governance/disputes/summary"
85
+ },
86
+ claim_boundary: "claim_lifecycle_continuity_only_for_the_listed_first_party_callable_and_xoonya_followthrough_surfaces_without_implying_universal_transaction_control"
87
+ };
88
+ }
89
+
90
+ function summarizeLifecycleContinuityPack() {
91
+ const pack = buildLifecycleContinuityPack();
92
+ return {
93
+ ok: true,
94
+ product: pack.product,
95
+ category: "machine-commerce-lifecycle-continuity-summary",
96
+ summary_version: "xytara-lifecycle-continuity-summary-v1",
97
+ lifecycle_stage_count: pack.lifecycle_stage_count,
98
+ fully_surfaced_lifecycle_count: pack.fully_surfaced_lifecycle_count,
99
+ first_party_callable_lifecycle_count: pack.first_party_callable_lifecycle_count,
100
+ proof_followthrough_lifecycle_count: pack.proof_followthrough_lifecycle_count,
101
+ dispute_followthrough_lifecycle_count: pack.dispute_followthrough_lifecycle_count,
102
+ linked_surfaces: pack.linked_surfaces
103
+ };
104
+ }
105
+
106
+ function getLifecycleContinuityStageDetail(lifecycleStage) {
107
+ const normalized = String(lifecycleStage || "").trim().toLowerCase();
108
+ return buildLifecycleContinuityStages().find((entry) => entry.lifecycle_stage === normalized) || null;
109
+ }
110
+
111
+ module.exports = {
112
+ buildLifecycleContinuityPack,
113
+ summarizeLifecycleContinuityPack,
114
+ getLifecycleContinuityStageDetail
115
+ };
@@ -10,6 +10,19 @@ function buildReleaseHistory() {
10
10
  current_version: packageJson.version,
11
11
  release_track: "public_release",
12
12
  history: [
13
+ {
14
+ version: "2.14.0",
15
+ channel: "public_release",
16
+ maturity_posture: "lifecycle_and_continuity_hardened",
17
+ headline: "lifecycle-and-continuity release with stronger runtime-to-proof followthrough, verify and dispute continuity, and clearer lifecycle inspectability",
18
+ milestone_refs: [
19
+ "lifecycle_continuity_pack",
20
+ "runtime_to_proof_followthrough",
21
+ "verify_followthrough",
22
+ "dispute_followthrough",
23
+ "synchronized_2_14_release_prep"
24
+ ]
25
+ },
13
26
  {
14
27
  version: "2.13.0",
15
28
  channel: "public_release",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xytara",
3
- "version": "2.13.0",
3
+ "version": "2.14.0",
4
4
  "description": "Agent-commerce runtime for quote, pay, execute, deliver, meter, and integrate.",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -82,6 +82,7 @@
82
82
  "verify:market-lane-promotion": "node scripts/verify_market_lane_promotion.js",
83
83
  "verify:provider-runtime-breadth": "node scripts/verify_provider_runtime_breadth.js",
84
84
  "verify:provider-runtime-journeys": "node scripts/verify_provider_runtime_journeys.js",
85
+ "verify:lifecycle-continuity": "node scripts/verify_lifecycle_continuity.js",
85
86
  "verify:first-run-conversions": "node scripts/verify_first_run_conversions.js",
86
87
  "verify:delivery-summary": "node scripts/verify_delivery_summary.js",
87
88
  "verify:runtime-durability": "node scripts/verify_runtime_durability.js",
@@ -92,7 +93,7 @@
92
93
  "verify:service": "node scripts/verify_service.js",
93
94
  "verify:release-candidate": "node scripts/verify_release_candidate.js",
94
95
  "verify:production-readiness": "node scripts/verify_production_readiness.js",
95
- "verify:all": "node scripts/verify_all.js && node scripts/verify_integrations.js && node scripts/verify_adapters.js && node scripts/verify_framework_provider_promotion.js && node scripts/verify_operator_observability_boundary.js && node scripts/verify_pricing_experiment_plan.js && node scripts/verify_treasury_public_boundary.js && node scripts/verify_market_lanes.js && node scripts/verify_market_lane_depth.js && node scripts/verify_market_lane_traces.js && node scripts/verify_market_lane_promotion.js && node scripts/verify_provider_runtime_breadth.js && node scripts/verify_provider_runtime_journeys.js && node scripts/verify_first_run_conversions.js && node scripts/verify_delivery_summary.js && node scripts/verify_runtime_durability.js && node scripts/verify_revenue_launch_paths.js && node scripts/verify_full_catalog.js && node scripts/verify_tooling.js && node scripts/verify_examples.js && node scripts/verify_service.js",
96
+ "verify:all": "node scripts/verify_all.js && node scripts/verify_integrations.js && node scripts/verify_adapters.js && node scripts/verify_framework_provider_promotion.js && node scripts/verify_operator_observability_boundary.js && node scripts/verify_pricing_experiment_plan.js && node scripts/verify_treasury_public_boundary.js && node scripts/verify_market_lanes.js && node scripts/verify_market_lane_depth.js && node scripts/verify_market_lane_traces.js && node scripts/verify_market_lane_promotion.js && node scripts/verify_provider_runtime_breadth.js && node scripts/verify_provider_runtime_journeys.js && node scripts/verify_lifecycle_continuity.js && node scripts/verify_first_run_conversions.js && node scripts/verify_delivery_summary.js && node scripts/verify_runtime_durability.js && node scripts/verify_revenue_launch_paths.js && node scripts/verify_full_catalog.js && node scripts/verify_tooling.js && node scripts/verify_examples.js && node scripts/verify_service.js",
96
97
  "prepublishOnly": "npm run verify:release-candidate"
97
98
  }
98
99
  }
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+
3
+ const assert = require("assert");
4
+ const { once } = require("events");
5
+ const { createServer } = require("../server");
6
+ const {
7
+ buildLifecycleContinuityPack,
8
+ summarizeLifecycleContinuityPack
9
+ } = require("../lib/lifecycle_continuity_contract");
10
+
11
+ async function getJson(baseUrl, pathname) {
12
+ const response = await fetch(`${baseUrl}${pathname}`);
13
+ return {
14
+ status: response.status,
15
+ json: await response.json()
16
+ };
17
+ }
18
+
19
+ function assertSummary(summary) {
20
+ assert.strictEqual(summary.ok, true, "lifecycle continuity summary ok flag missing");
21
+ assert.strictEqual(summary.lifecycle_stage_count >= 13, true, "lifecycle continuity stage count missing");
22
+ assert.strictEqual(summary.fully_surfaced_lifecycle_count >= 12, true, "lifecycle continuity fully surfaced count missing");
23
+ assert.strictEqual(summary.first_party_callable_lifecycle_count >= 10, true, "lifecycle continuity first-party callable count missing");
24
+ assert.strictEqual(summary.proof_followthrough_lifecycle_count >= 3, true, "lifecycle continuity proof followthrough count missing");
25
+ assert.strictEqual(summary.dispute_followthrough_lifecycle_count >= 2, true, "lifecycle continuity dispute followthrough count missing");
26
+ }
27
+
28
+ function assertPack(pack) {
29
+ assert.strictEqual(pack.ok, true, "lifecycle continuity pack ok flag missing");
30
+ assert.strictEqual(pack.category, "machine-commerce-lifecycle-continuity-pack", "lifecycle continuity pack category mismatch");
31
+ assert.strictEqual(Array.isArray(pack.lifecycle_stages), true, "lifecycle continuity stages missing");
32
+ assert.strictEqual(pack.lifecycle_stages.length >= 13, true, "lifecycle continuity stage list missing");
33
+ assert.strictEqual(
34
+ pack.lifecycle_stages.some((entry) => entry.lifecycle_stage === "verify" && entry.proof_followthrough === true),
35
+ true,
36
+ "lifecycle continuity verify followthrough missing"
37
+ );
38
+ assert.strictEqual(
39
+ pack.lifecycle_stages.some((entry) => entry.lifecycle_stage === "dispute_open" && entry.proof_followthrough === true),
40
+ true,
41
+ "lifecycle continuity dispute-open followthrough missing"
42
+ );
43
+ assert.strictEqual(
44
+ pack.lifecycle_stages.some((entry) => entry.lifecycle_stage === "dispute_fetch" && entry.proof_followthrough === true),
45
+ true,
46
+ "lifecycle continuity dispute-fetch followthrough missing"
47
+ );
48
+ }
49
+
50
+ async function main() {
51
+ const pack = buildLifecycleContinuityPack();
52
+ const summary = summarizeLifecycleContinuityPack();
53
+ assertPack(pack);
54
+ assertSummary(summary);
55
+
56
+ const server = createServer();
57
+ server.listen(0, "127.0.0.1");
58
+ await once(server, "listening");
59
+
60
+ const address = server.address();
61
+ const baseUrl = `http://127.0.0.1:${address.port}`;
62
+
63
+ try {
64
+ const packResponse = await getJson(baseUrl, "/v1/lifecycle-continuity");
65
+ assert.strictEqual(packResponse.status, 200, "lifecycle continuity pack route failed");
66
+ assertPack(packResponse.json);
67
+
68
+ const summaryResponse = await getJson(baseUrl, "/v1/lifecycle-continuity/summary");
69
+ assert.strictEqual(summaryResponse.status, 200, "lifecycle continuity summary route failed");
70
+ assertSummary(summaryResponse.json);
71
+
72
+ const verifyDetail = await getJson(baseUrl, "/v1/lifecycle-continuity/verify");
73
+ assert.strictEqual(verifyDetail.status, 200, "lifecycle continuity verify detail route failed");
74
+ assert.strictEqual(verifyDetail.json.stage.lifecycle_stage, "verify", "lifecycle continuity verify detail mismatch");
75
+ assert.strictEqual(verifyDetail.json.stage.proof_followthrough, true, "lifecycle continuity verify detail followthrough missing");
76
+ } finally {
77
+ await new Promise((resolve) => server.close(resolve));
78
+ }
79
+
80
+ console.log(JSON.stringify({
81
+ ok: true,
82
+ product: "xytara",
83
+ category: "machine-commerce-lifecycle-continuity-verification",
84
+ verification_version: "xytara-lifecycle-continuity-verification-v1",
85
+ lifecycle_stage_count: summary.lifecycle_stage_count,
86
+ fully_surfaced_lifecycle_count: summary.fully_surfaced_lifecycle_count,
87
+ proof_followthrough_lifecycle_count: summary.proof_followthrough_lifecycle_count,
88
+ dispute_followthrough_lifecycle_count: summary.dispute_followthrough_lifecycle_count,
89
+ boundary: "lifecycle_continuity_should_be_publicly_inspectable_with_xoonya_followthrough_explicit"
90
+ }, null, 2));
91
+ }
92
+
93
+ main().catch((error) => {
94
+ console.error(error && error.stack ? error.stack : error);
95
+ process.exit(1);
96
+ });
@@ -400,6 +400,17 @@ async function main() {
400
400
  assert.strictEqual(providerJourneySummary.json.first_run_ready_journey_count >= 2, true, "provider runtime journey first-run count missing");
401
401
  assert.strictEqual(providerJourneySummary.json.proof_followthrough_journey_count >= 2, true, "provider runtime journey proof-followthrough count missing");
402
402
 
403
+ const lifecycleContinuityPack = await getJson(baseUrl, "/v1/lifecycle-continuity");
404
+ assert.strictEqual(lifecycleContinuityPack.status, 200, "lifecycle continuity route failed");
405
+ assert.strictEqual(lifecycleContinuityPack.json.ok, true, "lifecycle continuity ok flag missing");
406
+ assert.strictEqual(lifecycleContinuityPack.json.lifecycle_stage_count >= 13, true, "lifecycle continuity stage count missing");
407
+ assert.strictEqual(lifecycleContinuityPack.json.proof_followthrough_lifecycle_count >= 3, true, "lifecycle continuity proof followthrough count missing");
408
+
409
+ const lifecycleContinuitySummary = await getJson(baseUrl, "/v1/lifecycle-continuity/summary");
410
+ assert.strictEqual(lifecycleContinuitySummary.status, 200, "lifecycle continuity summary route failed");
411
+ assert.strictEqual(lifecycleContinuitySummary.json.ok, true, "lifecycle continuity summary ok flag missing");
412
+ assert.strictEqual(lifecycleContinuitySummary.json.fully_surfaced_lifecycle_count >= 12, true, "lifecycle continuity fully surfaced count missing");
413
+
403
414
  const firstRunConversionPack = await getJson(baseUrl, "/v1/first-run/conversions");
404
415
  assert.strictEqual(firstRunConversionPack.status, 200, "first-run conversion route failed");
405
416
  assert.strictEqual(firstRunConversionPack.json.ok, true, "first-run conversion ok flag missing");
package/server.js CHANGED
@@ -198,6 +198,11 @@ const {
198
198
  getProviderRuntimeJourneyDetail,
199
199
  summarizeProviderRuntimeJourneyPack
200
200
  } = require("./lib/provider_runtime_journey_contract");
201
+ const {
202
+ buildLifecycleContinuityPack,
203
+ getLifecycleContinuityStageDetail,
204
+ summarizeLifecycleContinuityPack
205
+ } = require("./lib/lifecycle_continuity_contract");
201
206
  const {
202
207
  buildFirstRunConversionPack,
203
208
  getFirstRunConversionDetail,
@@ -3687,6 +3692,34 @@ async function routeRequest(req, res) {
3687
3692
  }
3688
3693
  }
3689
3694
 
3695
+ if (req.method === "GET" && url.pathname === "/v1/lifecycle-continuity") {
3696
+ sendJson(res, 200, buildLifecycleContinuityPack());
3697
+ return;
3698
+ }
3699
+
3700
+ if (req.method === "GET" && url.pathname === "/v1/lifecycle-continuity/summary") {
3701
+ sendJson(res, 200, summarizeLifecycleContinuityPack());
3702
+ return;
3703
+ }
3704
+
3705
+ if (req.method === "GET" && url.pathname.startsWith("/v1/lifecycle-continuity/")) {
3706
+ const suffix = decodeURIComponent(url.pathname.slice("/v1/lifecycle-continuity/".length));
3707
+ if (suffix && suffix !== "summary") {
3708
+ const stage = getLifecycleContinuityStageDetail(suffix);
3709
+ if (!stage) {
3710
+ sendJson(res, 404, { ok: false, error: "lifecycle_continuity_stage_not_found" });
3711
+ return;
3712
+ }
3713
+ sendJson(res, 200, {
3714
+ ok: true,
3715
+ product: "xytara",
3716
+ category: "machine-commerce-lifecycle-continuity-detail",
3717
+ stage
3718
+ });
3719
+ return;
3720
+ }
3721
+ }
3722
+
3690
3723
  if (req.method === "GET" && url.pathname === "/v1/first-run/conversions") {
3691
3724
  sendJson(res, 200, buildFirstRunConversionPack());
3692
3725
  return;