xytara 2.6.0 → 2.8.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.
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+
3
+ const assert = require("assert");
4
+ const {
5
+ buildOperatorObservabilityPack,
6
+ validateOperatorObservabilityBoundary
7
+ } = require("../lib/operator_intelligence");
8
+ const { createRuntimeState } = require("../lib/commerce_runtime");
9
+
10
+ function clone(value) {
11
+ return JSON.parse(JSON.stringify(value));
12
+ }
13
+
14
+ function assertRejected(pack, expectedCode) {
15
+ const validation = validateOperatorObservabilityBoundary(pack);
16
+ assert.strictEqual(validation.observability_boundary_valid, false, `expected ${expectedCode} to block operator observability boundary`);
17
+ assert.strictEqual(
18
+ validation.rejection_codes.includes(expectedCode),
19
+ true,
20
+ `missing deterministic rejection code ${expectedCode}`
21
+ );
22
+ return validation;
23
+ }
24
+
25
+ function main() {
26
+ const pack = buildOperatorObservabilityPack(createRuntimeState());
27
+ const validation = validateOperatorObservabilityBoundary(pack);
28
+ assert.strictEqual(pack.category, "machine-commerce-operator-observability-pack", "operator observability category mismatch");
29
+ assert.strictEqual(validation.observability_boundary_valid, true, "operator observability boundary should validate");
30
+ assert.deepStrictEqual(validation.rejection_codes, [], "operator observability boundary should not carry rejections");
31
+ assert.strictEqual(pack.deterministic_rejection_codes.length >= 8, true, "operator observability rejection codes missing");
32
+
33
+ const missingBoundary = clone(pack);
34
+ missingBoundary.boundary = "unsafe";
35
+ assertRejected(missingBoundary, "boundary_missing");
36
+
37
+ const missingSurface = clone(pack);
38
+ delete missingSurface.linked_surfaces.payment_ledger_ref;
39
+ assertRejected(missingSurface, "missing_linked_surface");
40
+
41
+ const mutationSurface = clone(pack);
42
+ mutationSurface.linked_surfaces.payment_ledger_ref = "/v1/payment-ledger/refund";
43
+ assertRejected(mutationSurface, "mutation_surface_linked");
44
+
45
+ const settlementSubmit = clone(pack);
46
+ settlementSubmit.linked_surfaces.settlement_ref = "/v1/settlement/bsv-teranode/submit";
47
+ assertRejected(settlementSubmit, "settlement_submission_surface_linked");
48
+
49
+ const fundMovement = clone(pack);
50
+ fundMovement.linked_surfaces.operator_intelligence_ref = "/v1/treasury/release";
51
+ assertRejected(fundMovement, "fund_movement_surface_linked");
52
+
53
+ const unsafeAction = clone(pack);
54
+ unsafeAction.attention_queue = [{
55
+ lane: "settlement",
56
+ priority: "high",
57
+ action: "submit_settlement_now",
58
+ surface_ref: "/v1/settlement/bsv-teranode",
59
+ reason: "bad action"
60
+ }];
61
+ assertRejected(unsafeAction, "unsafe_attention_action");
62
+
63
+ const secretMaterial = clone(pack);
64
+ secretMaterial.operator_token = "sk_live_accidental_secret";
65
+ assertRejected(secretMaterial, "secret_material_forbidden");
66
+
67
+ const badCount = clone(pack);
68
+ badCount.counts.quote_count = "1";
69
+ assertRejected(badCount, "count_not_number");
70
+
71
+ const output = {
72
+ ok: true,
73
+ product: "xytara",
74
+ category: "xytara-operator-observability-boundary-verification",
75
+ status: "operator_observability_stays_read_only_without_secret_material_or_mutation_surfaces",
76
+ deterministic_rejection_code_count: pack.deterministic_rejection_codes.length,
77
+ adversarial_case_count: 8,
78
+ boundary: validation.boundary
79
+ };
80
+ process.stdout.write(`${JSON.stringify(output, null, 2)}\n`);
81
+ }
82
+
83
+ main();
@@ -0,0 +1,124 @@
1
+ "use strict";
2
+
3
+ const assert = require("assert");
4
+ const {
5
+ buildPricingExperimentPlan,
6
+ summarizePricingExperimentPlan,
7
+ validatePricingExperimentLaunchRequest
8
+ } = require("../lib/pricing_optimization_contract");
9
+ const { createRuntimeState } = require("../lib/commerce_runtime");
10
+
11
+ function populateMaturePricingState(state) {
12
+ for (let index = 0; index < 100; index += 1) {
13
+ state.quotes.set(`quote_${index}`, {
14
+ quote_id: `quote_${index}`,
15
+ status: index < 50 ? "executed" : "expired",
16
+ amount_minor: 40,
17
+ task_refs: ["adapter.mcp.invoke"],
18
+ payment_protocol: "x402",
19
+ settlement_mode: "bsv_teranode"
20
+ });
21
+ }
22
+ for (let index = 0; index < 20; index += 1) {
23
+ state.paymentLedger.push({
24
+ payment_id: `payment_${index}`,
25
+ status: "recorded",
26
+ amount_minor: 40
27
+ });
28
+ state.transactions.set(`txn_${index}`, {
29
+ transaction: {
30
+ transaction_id: `txn_${index}`,
31
+ status: "completed"
32
+ }
33
+ });
34
+ }
35
+ }
36
+
37
+ function buildValidLaunchRequest(candidate) {
38
+ const rollback_trigger_thresholds = {};
39
+ for (const trigger of candidate.rollback_triggers) {
40
+ rollback_trigger_thresholds[trigger] = "operator_defined_threshold";
41
+ }
42
+ return {
43
+ experiment_id: candidate.experiment_id,
44
+ target_surface: candidate.target_surface,
45
+ operator_approval_ref: "ops.pricing.approval.2026-04-22",
46
+ baseline_metrics_ref: "ops.pricing.baseline.2026-04-22",
47
+ rollback_trigger_thresholds,
48
+ public_checkout_copy_review_ref: "ops.pricing.copy_review.2026-04-22",
49
+ post_experiment_review_window_days: 14
50
+ };
51
+ }
52
+
53
+ function assertRejected(plan, request, expectedCode) {
54
+ const validation = validatePricingExperimentLaunchRequest(plan, request);
55
+ assert.strictEqual(validation.launch_allowed, false, `expected ${expectedCode} to block pricing experiment launch`);
56
+ assert.strictEqual(
57
+ validation.rejection_codes.includes(expectedCode),
58
+ true,
59
+ `missing deterministic rejection code ${expectedCode}`
60
+ );
61
+ return validation;
62
+ }
63
+
64
+ function main() {
65
+ const state = createRuntimeState();
66
+ const plan = buildPricingExperimentPlan(state);
67
+ const summary = summarizePricingExperimentPlan(state);
68
+
69
+ assert.strictEqual(plan.experiment_plan_version, "xytara-pricing-experiment-plan-v1", "pricing experiment plan version mismatch");
70
+ assert.strictEqual(plan.allow_experiment_launch, false, "empty state must not allow pricing experiments");
71
+ assert.strictEqual(plan.experiment_state, "blocked_collect_more_live_data", "empty state experiment gate mismatch");
72
+ assert.strictEqual(plan.required_minimum_live_sample.quote_count, 100, "quote sample floor mismatch");
73
+ assert.strictEqual(plan.required_minimum_live_sample.payment_ledger_count, 20, "payment sample floor mismatch");
74
+ assert.strictEqual(plan.required_minimum_live_sample.execution_transaction_count, 20, "execution sample floor mismatch");
75
+ assert.strictEqual(plan.candidate_experiments.length >= 3, true, "candidate experiments missing");
76
+ assert.strictEqual(
77
+ plan.candidate_experiments.every((entry) => entry.allowed_now === false),
78
+ true,
79
+ "candidate experiments should be blocked while sparse"
80
+ );
81
+ assert.strictEqual(
82
+ plan.blocked_actions.includes("start_price_ab_test_from_sparse_signals"),
83
+ true,
84
+ "sparse-signal blocked action missing"
85
+ );
86
+ assert.strictEqual(summary.category, "machine-commerce-pricing-experiment-plan-summary", "summary category mismatch");
87
+ assert.strictEqual(summary.allow_experiment_launch, false, "summary experiment launch guard mismatch");
88
+ assert.strictEqual(summary.deterministic_rejection_code_count >= 9, true, "pricing rejection code count missing");
89
+
90
+ assertRejected(plan, buildValidLaunchRequest(plan.candidate_experiments[0]), "pricing_sample_too_sparse");
91
+ assertRejected(plan, { experiment_id: "unknown_experiment" }, "experiment_not_registered");
92
+
93
+ const matureState = createRuntimeState();
94
+ populateMaturePricingState(matureState);
95
+ const maturePlan = buildPricingExperimentPlan(matureState);
96
+ const matureCandidate = maturePlan.candidate_experiments[0];
97
+ const validLaunchRequest = buildValidLaunchRequest(matureCandidate);
98
+ const validLaunch = validatePricingExperimentLaunchRequest(maturePlan, validLaunchRequest);
99
+ assert.strictEqual(maturePlan.allow_experiment_launch, true, "mature state should allow operator-reviewed experiments");
100
+ assert.strictEqual(validLaunch.launch_allowed, true, "valid mature launch request should pass");
101
+ assert.deepStrictEqual(validLaunch.rejection_codes, [], "valid launch request must not carry rejection codes");
102
+
103
+ assertRejected(maturePlan, { ...validLaunchRequest, operator_approval_ref: null }, "operator_approval_missing");
104
+ assertRejected(maturePlan, { ...validLaunchRequest, baseline_metrics_ref: null }, "baseline_metrics_missing");
105
+ assertRejected(maturePlan, { ...validLaunchRequest, rollback_trigger_thresholds: {} }, "rollback_trigger_thresholds_missing");
106
+ assertRejected(maturePlan, { ...validLaunchRequest, public_checkout_copy_review_ref: null }, "public_checkout_copy_review_missing");
107
+ assertRejected(maturePlan, { ...validLaunchRequest, post_experiment_review_window_days: 0 }, "post_experiment_review_window_missing");
108
+ assertRejected(maturePlan, { ...validLaunchRequest, target_surface: "wrong_surface" }, "target_surface_mismatch");
109
+
110
+ const output = {
111
+ ok: true,
112
+ product: "xytara",
113
+ category: "xytara-pricing-experiment-plan-verification",
114
+ status: "experiment_plan_blocks_sparse_signal_and_malformed_launch_requests",
115
+ candidate_experiment_count: plan.candidate_experiments.length,
116
+ launch_requirement_count: plan.launch_requirements.length,
117
+ deterministic_rejection_code_count: plan.deterministic_rejection_codes.length,
118
+ adversarial_case_count: 8,
119
+ boundary: plan.boundary
120
+ };
121
+ process.stdout.write(`${JSON.stringify(output, null, 2)}\n`);
122
+ }
123
+
124
+ main();
@@ -0,0 +1,251 @@
1
+ "use strict";
2
+
3
+ const assert = require("assert");
4
+ const fs = require("fs");
5
+ const path = require("path");
6
+ const { execFileSync } = require("child_process");
7
+
8
+ function ensureReleaseCandidate() {
9
+ const releaseOutput = execFileSync(process.execPath, [
10
+ path.resolve(__dirname, "..", "bin", "xytara-release.js"),
11
+ "--candidate",
12
+ "--summary"
13
+ ], {
14
+ cwd: path.resolve(__dirname, ".."),
15
+ encoding: "utf8"
16
+ });
17
+ const releaseCandidate = JSON.parse(releaseOutput);
18
+ assert.strictEqual(releaseCandidate.product, "xytara", "release candidate product mismatch");
19
+ }
20
+
21
+ function ensurePersistenceConfig() {
22
+ const stateFile = process.env.XYTARA_STATE_FILE;
23
+ const supabaseUrl = process.env.XYTARA_SUPABASE_URL;
24
+ const supabaseServiceRoleKey = process.env.XYTARA_SUPABASE_SERVICE_ROLE_KEY;
25
+
26
+ const fileConfigured = typeof stateFile === "string" && stateFile.trim().length > 0;
27
+ const supabaseConfigured =
28
+ typeof supabaseUrl === "string" &&
29
+ supabaseUrl.trim().length > 0 &&
30
+ typeof supabaseServiceRoleKey === "string" &&
31
+ supabaseServiceRoleKey.trim().length > 0;
32
+
33
+ assert.strictEqual(
34
+ fileConfigured || supabaseConfigured,
35
+ true,
36
+ "configure XYTARA_STATE_FILE on persistent disk or XYTARA_SUPABASE_URL + XYTARA_SUPABASE_SERVICE_ROLE_KEY before treating xytara as production-ready"
37
+ );
38
+
39
+ if (fileConfigured) {
40
+ const resolvedPath = path.resolve(stateFile);
41
+ const parentDirectory = path.dirname(resolvedPath);
42
+ assert.strictEqual(
43
+ fs.existsSync(parentDirectory),
44
+ true,
45
+ `XYTARA_STATE_FILE parent directory does not exist: ${parentDirectory}`
46
+ );
47
+ fs.accessSync(parentDirectory, fs.constants.W_OK);
48
+ }
49
+ }
50
+
51
+ function ensureProductionSecurityConfig() {
52
+ const verificationMode = String(process.env.XYTARA_PAYMENT_VERIFICATION_MODE || "").trim() || "presence";
53
+ assert.notStrictEqual(
54
+ verificationMode,
55
+ "presence",
56
+ "set XYTARA_PAYMENT_VERIFICATION_MODE to local_signed or stronger before treating xytara as production-ready"
57
+ );
58
+
59
+ if (verificationMode === "local_signed") {
60
+ const walletRegistryJson = String(process.env.XYTARA_WALLET_REGISTRY_JSON || "").trim();
61
+ assert.strictEqual(walletRegistryJson.length > 0, true, "configure XYTARA_WALLET_REGISTRY_JSON before using local_signed payment verification");
62
+ const parsed = JSON.parse(walletRegistryJson);
63
+ assert.strictEqual(Array.isArray(parsed), true, "XYTARA_WALLET_REGISTRY_JSON must be a JSON array");
64
+ assert.strictEqual(parsed.length > 0, true, "register at least one enabled wallet in XYTARA_WALLET_REGISTRY_JSON before treating xytara as production-ready");
65
+ }
66
+
67
+ assert.strictEqual(
68
+ String(process.env.XYTARA_CREDIT_BRIDGE_BEARER_TOKEN || "").trim().length > 0,
69
+ true,
70
+ "configure XYTARA_CREDIT_BRIDGE_BEARER_TOKEN before treating xytara as production-ready"
71
+ );
72
+ assert.strictEqual(
73
+ String(process.env.XYTARA_ACCOUNT_AUTH_BEARER_TOKEN || "").trim().length > 0,
74
+ true,
75
+ "configure XYTARA_ACCOUNT_AUTH_BEARER_TOKEN before treating xytara as production-ready"
76
+ );
77
+ }
78
+
79
+ function ensureTreasuryConfig() {
80
+ const treasuryPath = String(process.env.XYTARA_TREASURY_DESTINATIONS_PATH || "").trim();
81
+ assert.strictEqual(
82
+ treasuryPath.length > 0,
83
+ true,
84
+ "configure XYTARA_TREASURY_DESTINATIONS_PATH before treating xytara as production-ready"
85
+ );
86
+ const resolvedPath = path.resolve(treasuryPath);
87
+ assert.strictEqual(fs.existsSync(resolvedPath), true, `treasury destinations file does not exist: ${resolvedPath}`);
88
+ const parsed = JSON.parse(fs.readFileSync(resolvedPath, "utf8"));
89
+ const configuredRails = Object.values(parsed || {}).filter((entry) =>
90
+ entry
91
+ && typeof entry === "object"
92
+ && typeof entry.external_ref === "string"
93
+ && entry.external_ref.trim().length > 0
94
+ );
95
+ assert.strictEqual(
96
+ configuredRails.length > 0,
97
+ true,
98
+ "configure at least one treasury destination external_ref before treating xytara as production-ready"
99
+ );
100
+ }
101
+
102
+ function ensureCallbackDeliveryConfig() {
103
+ const callbackDeliveryEnabled = String(process.env.XYTARA_CALLBACK_DELIVERY_ENABLED || "true").trim().toLowerCase() !== "false";
104
+ if (!callbackDeliveryEnabled) return;
105
+ assert.strictEqual(
106
+ String(process.env.XYTARA_CALLBACK_SIGNING_SECRET || "").trim().length > 0,
107
+ true,
108
+ "configure XYTARA_CALLBACK_SIGNING_SECRET before treating xytara as production-ready"
109
+ );
110
+ }
111
+
112
+ function ensureHostedCheckoutIngressSecurity() {
113
+ const verificationRequired = String(
114
+ process.env.XYTARA_CHECKOUT_WEBHOOK_VERIFICATION_REQUIRED
115
+ || process.env.XYTARA_HOSTED_CHECKOUT_ENABLED
116
+ || "true"
117
+ ).trim().toLowerCase();
118
+ if (["false", "0", "no", "off"].includes(verificationRequired)) {
119
+ return;
120
+ }
121
+ assert.strictEqual(
122
+ String(process.env.XYTARA_CHECKOUT_WEBHOOK_SECRET || process.env.XYTARA_HOSTED_CHECKOUT_WEBHOOK_SECRET || "").trim().length > 0,
123
+ true,
124
+ "configure XYTARA_CHECKOUT_WEBHOOK_SECRET before treating hosted-checkout ingress as production-ready"
125
+ );
126
+ }
127
+
128
+ function ensureL402Config() {
129
+ const l402Enabled = String(process.env.XYTARA_L402_ENABLED || "false").trim().toLowerCase() === "true";
130
+ if (!l402Enabled) return;
131
+ assert.strictEqual(
132
+ String(process.env.XYTARA_L402_SHARED_SECRET || "").trim().length > 0,
133
+ true,
134
+ "configure XYTARA_L402_SHARED_SECRET before treating the L402 ingress as production-ready"
135
+ );
136
+ }
137
+
138
+ function ensureBoltConfig() {
139
+ const boltEnabled = String(process.env.XYTARA_BOLT_ENABLED || "false").trim().toLowerCase() === "true";
140
+ if (!boltEnabled) return;
141
+ assert.strictEqual(
142
+ String(process.env.XYTARA_BOLT_SHARED_SECRET || "").trim().length > 0,
143
+ true,
144
+ "configure XYTARA_BOLT_SHARED_SECRET before treating the BOLT ingress as production-ready"
145
+ );
146
+ }
147
+
148
+ function ensureMppConfig() {
149
+ const mppEnabled = String(process.env.XYTARA_MPP_ENABLED || "false").trim().toLowerCase() === "true";
150
+ if (!mppEnabled) return;
151
+ assert.strictEqual(
152
+ String(process.env.XYTARA_MPP_SHARED_SECRET || "").trim().length > 0,
153
+ true,
154
+ "configure XYTARA_MPP_SHARED_SECRET before treating the MPP ingress as production-ready"
155
+ );
156
+ }
157
+
158
+ function ensureRateLimitConfig() {
159
+ const rateLimitEnabled = String(process.env.XYTARA_RATE_LIMIT_ENABLED || "true").trim().toLowerCase() !== "false";
160
+ assert.strictEqual(
161
+ rateLimitEnabled,
162
+ true,
163
+ "keep XYTARA_RATE_LIMIT_ENABLED=true before treating xytara as production-ready unless you have an equivalent upstream control"
164
+ );
165
+ const windowMs = Number(process.env.XYTARA_RATE_LIMIT_WINDOW_MS || 0);
166
+ const maxRequests = Number(process.env.XYTARA_RATE_LIMIT_MAX_REQUESTS || 0);
167
+ assert.strictEqual(Number.isFinite(windowMs) && windowMs > 0, true, "configure XYTARA_RATE_LIMIT_WINDOW_MS to a positive value");
168
+ assert.strictEqual(Number.isFinite(maxRequests) && maxRequests > 0, true, "configure XYTARA_RATE_LIMIT_MAX_REQUESTS to a positive value");
169
+ }
170
+
171
+ function ensureExecutionTargetConfig() {
172
+ const raw = String(process.env.XYTARA_EXECUTION_TARGETS_JSON || "").trim();
173
+ const requireTargets = String(process.env.XYTARA_EXTERNAL_EXECUTION_REQUIRED || "false").trim().toLowerCase() === "true";
174
+ if (!raw) {
175
+ assert.strictEqual(
176
+ requireTargets,
177
+ false,
178
+ "configure XYTARA_EXECUTION_TARGETS_JSON before treating xytara as production-ready when XYTARA_EXTERNAL_EXECUTION_REQUIRED=true"
179
+ );
180
+ return;
181
+ }
182
+
183
+ const parsed = JSON.parse(raw);
184
+ assert.strictEqual(Array.isArray(parsed), true, "XYTARA_EXECUTION_TARGETS_JSON must be a JSON array");
185
+ assert.strictEqual(parsed.length > 0, true, "configure at least one execution target in XYTARA_EXECUTION_TARGETS_JSON");
186
+ parsed.forEach((entry, index) => {
187
+ assert.strictEqual(
188
+ entry && typeof entry === "object" && !Array.isArray(entry),
189
+ true,
190
+ `execution target ${index + 1} must be an object`
191
+ );
192
+ assert.strictEqual(
193
+ typeof entry.endpoint_url === "string" && entry.endpoint_url.trim().length > 0,
194
+ true,
195
+ `execution target ${index + 1} must include endpoint_url`
196
+ );
197
+ assert.strictEqual(
198
+ Boolean(
199
+ (typeof entry.task_ref === "string" && entry.task_ref.trim().length > 0)
200
+ || (typeof entry.tool_name === "string" && entry.tool_name.trim().length > 0)
201
+ || (typeof entry.integration_id === "string" && entry.integration_id.trim().length > 0)
202
+ ),
203
+ true,
204
+ `execution target ${index + 1} must match at least one of task_ref, tool_name, or integration_id`
205
+ );
206
+ });
207
+ }
208
+
209
+ function ensureNativeSettlementConfig() {
210
+ const runtimeMode = String(process.env.XYTARA_BSV_TERANODE_SETTLEMENT_RUNTIME_MODE || "mock").trim().toLowerCase() || "mock";
211
+ assert.notStrictEqual(
212
+ runtimeMode,
213
+ "mock",
214
+ "configure XYTARA_BSV_TERANODE_SETTLEMENT_RUNTIME_MODE to observe, arc, or another live runtime mode before treating xytara as production-ready"
215
+ );
216
+ assert.strictEqual(
217
+ String(process.env.XYTARA_BSV_TERANODE_MERCHANT_ADDRESS || process.env.XYTARA_BSV_TERANODE_MERCHANT_PAYMAIL || "").trim().length > 0,
218
+ true,
219
+ "configure XYTARA_BSV_TERANODE_MERCHANT_ADDRESS or XYTARA_BSV_TERANODE_MERCHANT_PAYMAIL before treating xytara as production-ready"
220
+ );
221
+ if (runtimeMode === "arc") {
222
+ assert.strictEqual(
223
+ String(process.env.XYTARA_BSV_TERANODE_RPC_URL || "").trim().length > 0,
224
+ true,
225
+ "configure XYTARA_BSV_TERANODE_RPC_URL before treating arc settlement mode as production-ready"
226
+ );
227
+ assert.strictEqual(
228
+ String(process.env.XYTARA_BSV_TERANODE_RPC_API_KEY || "").trim().length > 0,
229
+ true,
230
+ "configure XYTARA_BSV_TERANODE_RPC_API_KEY before treating arc settlement mode as production-ready"
231
+ );
232
+ }
233
+ }
234
+
235
+ function main() {
236
+ ensureReleaseCandidate();
237
+ ensurePersistenceConfig();
238
+ ensureProductionSecurityConfig();
239
+ ensureTreasuryConfig();
240
+ ensureCallbackDeliveryConfig();
241
+ ensureHostedCheckoutIngressSecurity();
242
+ ensureL402Config();
243
+ ensureBoltConfig();
244
+ ensureMppConfig();
245
+ ensureRateLimitConfig();
246
+ ensureExecutionTargetConfig();
247
+ ensureNativeSettlementConfig();
248
+ console.log("xytara verify:production-readiness passed");
249
+ }
250
+
251
+ main();
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+
3
+ const assert = require("assert");
4
+ const path = require("path");
5
+ const { execFileSync, execSync } = require("child_process");
6
+ const packageJson = require("../package.json");
7
+
8
+ function parsePackDryRun() {
9
+ const output = execSync("npm pack --dry-run --json", {
10
+ cwd: path.resolve(__dirname, ".."),
11
+ encoding: "utf8"
12
+ });
13
+ const parsed = JSON.parse(output);
14
+ return Array.isArray(parsed) ? parsed[0] : parsed;
15
+ }
16
+
17
+ function main() {
18
+ const releaseOutput = execFileSync(process.execPath, [
19
+ path.resolve(__dirname, "..", "bin", "xytara-release.js"),
20
+ "--candidate",
21
+ "--summary"
22
+ ], {
23
+ cwd: path.resolve(__dirname, ".."),
24
+ encoding: "utf8"
25
+ });
26
+ const releaseCandidate = JSON.parse(releaseOutput);
27
+ assert.strictEqual(releaseCandidate.product, "xytara", "release candidate product mismatch");
28
+ assert.strictEqual(releaseCandidate.publish_access, "public", "release candidate publish access mismatch");
29
+ assert.strictEqual(releaseCandidate.checklist_count >= 5, true, "release candidate checklist count mismatch");
30
+
31
+ const dryRun = parsePackDryRun();
32
+ assert.strictEqual(dryRun.name, packageJson.name, "npm pack dry-run name mismatch");
33
+ assert.strictEqual(dryRun.version, packageJson.version, "npm pack dry-run version mismatch");
34
+ assert.strictEqual(Array.isArray(dryRun.files), true, "npm pack dry-run file list missing");
35
+ assert.strictEqual(dryRun.files.some((entry) => entry.path === "bin/xytara-run.js"), true, "npm pack dry-run missing xytara-run");
36
+ assert.strictEqual(dryRun.files.some((entry) => entry.path === "bin/xytara-first-run.js"), true, "npm pack dry-run missing xytara-first-run");
37
+ assert.strictEqual(dryRun.files.some((entry) => entry.path === "bin/xytara-release.js"), true, "npm pack dry-run missing xytara-release");
38
+ assert.strictEqual(dryRun.files.some((entry) => entry.path === "scripts/verify_release_candidate.js"), true, "npm pack dry-run missing release verifier script");
39
+ assert.strictEqual(dryRun.files.some((entry) => entry.path === "scripts/verify_framework_provider_promotion.js"), true, "npm pack dry-run missing framework provider promotion verifier script");
40
+ assert.strictEqual(dryRun.files.some((entry) => entry.path === "scripts/verify_operator_observability_boundary.js"), true, "npm pack dry-run missing operator observability boundary verifier script");
41
+ assert.strictEqual(dryRun.files.some((entry) => entry.path === "scripts/verify_pricing_experiment_plan.js"), true, "npm pack dry-run missing pricing experiment verifier script");
42
+ assert.strictEqual(dryRun.files.some((entry) => entry.path === "scripts/verify_treasury_public_boundary.js"), true, "npm pack dry-run missing treasury public boundary verifier script");
43
+ assert.strictEqual(dryRun.files.some((entry) => entry.path === "scripts/verify_all.js"), true, "npm pack dry-run missing package verifier script");
44
+ assert.strictEqual(dryRun.files.some((entry) => entry.path === "lib/framework_provider_promotion.js"), true, "npm pack dry-run missing framework provider promotion pack");
45
+ assert.strictEqual(dryRun.files.some((entry) => entry.path === "README.md"), true, "npm pack dry-run missing README");
46
+ assert.strictEqual(dryRun.files.some((entry) => entry.path === "RELEASE_NOTES.md"), true, "npm pack dry-run missing release notes");
47
+ assert.strictEqual(dryRun.files.some((entry) => entry.path === "START_HERE.md"), true, "npm pack dry-run missing start-here");
48
+ assert.strictEqual(dryRun.files.some((entry) => entry.path === "SERVICE_CONTRACT.md"), true, "npm pack dry-run missing service contract");
49
+ assert.strictEqual(dryRun.files.some((entry) => entry.path === "TREASURY_DESTINATIONS.example.json"), true, "npm pack dry-run missing treasury destinations example");
50
+ assert.strictEqual(dryRun.files.some((entry) => entry.path === "TREASURY_DESTINATIONS.production.template.json"), true, "npm pack dry-run missing treasury destinations production template");
51
+ assert.strictEqual(dryRun.files.some((entry) => entry.path === "OPERATOR_START_HERE.md"), false, "npm pack dry-run should not ship operator start-here");
52
+ assert.strictEqual(dryRun.files.some((entry) => entry.path === "OPERATIONS_RUNBOOK.md"), false, "npm pack dry-run should not ship operations runbook");
53
+ assert.strictEqual(dryRun.files.some((entry) => entry.path === "PUBLISH_PLAN.md"), false, "npm pack dry-run should not ship publish plan");
54
+ assert.strictEqual(dryRun.files.length >= 10, true, "npm pack dry-run file count too small");
55
+
56
+ console.log("xytara verify:release-candidate passed");
57
+ }
58
+
59
+ main();