@riddledc/riddle-proof 0.7.85 → 0.7.87

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.
@@ -1703,6 +1703,7 @@ function createRiddleProofProfileConfigurationError(name, error, runner = "riddl
1703
1703
  }
1704
1704
  function createRiddleProofProfileEnvironmentBlockedResult(input) {
1705
1705
  const message = input.error instanceof Error ? input.error.message : input.error ? String(input.error) : "Riddle runner did not complete successfully.";
1706
+ const environmentBlocker = extractRiddleRunnerBlocker(message);
1706
1707
  return {
1707
1708
  version: RIDDLE_PROOF_PROFILE_RESULT_VERSION,
1708
1709
  profile_name: input.profile.name,
@@ -1712,12 +1713,64 @@ function createRiddleProofProfileEnvironmentBlockedResult(input) {
1712
1713
  route: { requested: resolveRiddleProofProfileTargetUrl(input.profile), observed: "", matched: false, error: message },
1713
1714
  artifacts: { screenshots: [], proof_json: "proof.json", riddle_artifacts: input.artifacts },
1714
1715
  checks: [],
1715
- summary: `${input.profile.name} could not collect reliable evidence because the runner was blocked.`,
1716
+ summary: summarizeEnvironmentBlockedRunner(input.profile.name, environmentBlocker),
1716
1717
  captured_at: (/* @__PURE__ */ new Date()).toISOString(),
1717
1718
  riddle: input.riddle,
1719
+ environment_blocker: environmentBlocker,
1718
1720
  error: message
1719
1721
  };
1720
1722
  }
1723
+ function extractRiddleRunnerBlocker(message) {
1724
+ const apiError = message.match(/^Riddle API\s+(\S+)\s+failed HTTP\s+(\d+):\s+(\{[\s\S]*\})$/);
1725
+ if (!apiError) return void 0;
1726
+ const details = {
1727
+ source: "riddle_api",
1728
+ endpoint: apiError[1],
1729
+ http_status: Number(apiError[2])
1730
+ };
1731
+ let payload;
1732
+ try {
1733
+ const parsed = JSON.parse(apiError[3]);
1734
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
1735
+ payload = parsed;
1736
+ }
1737
+ } catch {
1738
+ payload = void 0;
1739
+ }
1740
+ const copyScalar = (key) => {
1741
+ const value = payload?.[key];
1742
+ if (typeof value === "string" || typeof value === "boolean") details[key] = value;
1743
+ if (typeof value === "number" && Number.isFinite(value)) details[key] = value;
1744
+ };
1745
+ for (const key of ["error", "required_seconds", "available_seconds", "deficit_seconds", "minimum_purchase_dollars"]) {
1746
+ copyScalar(key);
1747
+ }
1748
+ const httpStatus = typeof details.http_status === "number" ? details.http_status : void 0;
1749
+ const errorText = typeof details.error === "string" ? details.error.toLowerCase() : "";
1750
+ if (httpStatus === 402 && errorText.includes("balance")) {
1751
+ details.reason = "insufficient_balance";
1752
+ }
1753
+ return details;
1754
+ }
1755
+ function summarizeEnvironmentBlockedRunner(profileName, blocker) {
1756
+ if (blocker?.reason === "insufficient_balance") {
1757
+ const required = typeof blocker.required_seconds === "number" ? blocker.required_seconds : void 0;
1758
+ const available = typeof blocker.available_seconds === "number" ? blocker.available_seconds : void 0;
1759
+ const deficit = typeof blocker.deficit_seconds === "number" ? blocker.deficit_seconds : void 0;
1760
+ const parts = [
1761
+ required === void 0 ? "" : `required ${required}s`,
1762
+ available === void 0 ? "" : `available ${available}s`,
1763
+ deficit === void 0 ? "" : `deficit ${deficit}s`
1764
+ ].filter(Boolean);
1765
+ return `${profileName} could not start because Riddle balance was insufficient${parts.length ? ` (${parts.join(", ")})` : ""}.`;
1766
+ }
1767
+ if (blocker?.source === "riddle_api") {
1768
+ const endpoint = typeof blocker.endpoint === "string" ? blocker.endpoint : "Riddle API";
1769
+ const status = typeof blocker.http_status === "number" ? blocker.http_status : void 0;
1770
+ return `${profileName} could not start because ${endpoint} returned${status === void 0 ? "" : ` HTTP ${status}`}.`;
1771
+ }
1772
+ return `${profileName} could not collect reliable evidence because the runner was blocked.`;
1773
+ }
1721
1774
  function createRiddleProofProfileInsufficientResult(input) {
1722
1775
  const message = input.error instanceof Error ? input.error.message : input.error ? String(input.error) : "No proof.json profile result artifact was found.";
1723
1776
  return {
package/dist/cli.cjs CHANGED
@@ -8574,6 +8574,7 @@ function profileStatusExitCode(profile, status) {
8574
8574
  }
8575
8575
  function createRiddleProofProfileEnvironmentBlockedResult(input) {
8576
8576
  const message = input.error instanceof Error ? input.error.message : input.error ? String(input.error) : "Riddle runner did not complete successfully.";
8577
+ const environmentBlocker = extractRiddleRunnerBlocker(message);
8577
8578
  return {
8578
8579
  version: RIDDLE_PROOF_PROFILE_RESULT_VERSION,
8579
8580
  profile_name: input.profile.name,
@@ -8583,12 +8584,64 @@ function createRiddleProofProfileEnvironmentBlockedResult(input) {
8583
8584
  route: { requested: resolveRiddleProofProfileTargetUrl(input.profile), observed: "", matched: false, error: message },
8584
8585
  artifacts: { screenshots: [], proof_json: "proof.json", riddle_artifacts: input.artifacts },
8585
8586
  checks: [],
8586
- summary: `${input.profile.name} could not collect reliable evidence because the runner was blocked.`,
8587
+ summary: summarizeEnvironmentBlockedRunner(input.profile.name, environmentBlocker),
8587
8588
  captured_at: (/* @__PURE__ */ new Date()).toISOString(),
8588
8589
  riddle: input.riddle,
8590
+ environment_blocker: environmentBlocker,
8589
8591
  error: message
8590
8592
  };
8591
8593
  }
8594
+ function extractRiddleRunnerBlocker(message) {
8595
+ const apiError = message.match(/^Riddle API\s+(\S+)\s+failed HTTP\s+(\d+):\s+(\{[\s\S]*\})$/);
8596
+ if (!apiError) return void 0;
8597
+ const details = {
8598
+ source: "riddle_api",
8599
+ endpoint: apiError[1],
8600
+ http_status: Number(apiError[2])
8601
+ };
8602
+ let payload;
8603
+ try {
8604
+ const parsed = JSON.parse(apiError[3]);
8605
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
8606
+ payload = parsed;
8607
+ }
8608
+ } catch {
8609
+ payload = void 0;
8610
+ }
8611
+ const copyScalar = (key) => {
8612
+ const value = payload?.[key];
8613
+ if (typeof value === "string" || typeof value === "boolean") details[key] = value;
8614
+ if (typeof value === "number" && Number.isFinite(value)) details[key] = value;
8615
+ };
8616
+ for (const key of ["error", "required_seconds", "available_seconds", "deficit_seconds", "minimum_purchase_dollars"]) {
8617
+ copyScalar(key);
8618
+ }
8619
+ const httpStatus = typeof details.http_status === "number" ? details.http_status : void 0;
8620
+ const errorText = typeof details.error === "string" ? details.error.toLowerCase() : "";
8621
+ if (httpStatus === 402 && errorText.includes("balance")) {
8622
+ details.reason = "insufficient_balance";
8623
+ }
8624
+ return details;
8625
+ }
8626
+ function summarizeEnvironmentBlockedRunner(profileName, blocker) {
8627
+ if (blocker?.reason === "insufficient_balance") {
8628
+ const required = typeof blocker.required_seconds === "number" ? blocker.required_seconds : void 0;
8629
+ const available = typeof blocker.available_seconds === "number" ? blocker.available_seconds : void 0;
8630
+ const deficit = typeof blocker.deficit_seconds === "number" ? blocker.deficit_seconds : void 0;
8631
+ const parts = [
8632
+ required === void 0 ? "" : `required ${required}s`,
8633
+ available === void 0 ? "" : `available ${available}s`,
8634
+ deficit === void 0 ? "" : `deficit ${deficit}s`
8635
+ ].filter(Boolean);
8636
+ return `${profileName} could not start because Riddle balance was insufficient${parts.length ? ` (${parts.join(", ")})` : ""}.`;
8637
+ }
8638
+ if (blocker?.source === "riddle_api") {
8639
+ const endpoint = typeof blocker.endpoint === "string" ? blocker.endpoint : "Riddle API";
8640
+ const status = typeof blocker.http_status === "number" ? blocker.http_status : void 0;
8641
+ return `${profileName} could not start because ${endpoint} returned${status === void 0 ? "" : ` HTTP ${status}`}.`;
8642
+ }
8643
+ return `${profileName} could not collect reliable evidence because the runner was blocked.`;
8644
+ }
8592
8645
  function createRiddleProofProfileInsufficientResult(input) {
8593
8646
  const message = input.error instanceof Error ? input.error.message : input.error ? String(input.error) : "No proof.json profile result artifact was found.";
8594
8647
  return {
@@ -11256,7 +11309,7 @@ function usage() {
11256
11309
  " riddle-proof-loop respond --state-path <path> --response-json <file|json|->",
11257
11310
  " riddle-proof-loop respond --state-path <path> --decision <decision> --summary <text> [--payload-json <file|json|->]",
11258
11311
  " riddle-proof-loop status --state-path <path>",
11259
- " riddle-proof-loop run-profile --profile <file|json|-> --url <base-url> [--runner riddle] [--strict true|false] [--poll-attempts n] [--output <dir>] [--quiet]",
11312
+ " riddle-proof-loop run-profile --profile <file|json|-> --url <base-url> [--runner riddle] [--strict true|false] [--poll-attempts n] [--output <dir>|--output-dir <dir>] [--quiet]",
11260
11313
  " riddle-proof-loop riddle-preview-deploy <build-dir> <label>",
11261
11314
  " riddle-proof-loop riddle-server-preview <directory> --script-file <file> [--path /route] [--wait-for-selector selector]",
11262
11315
  " riddle-proof-loop riddle-run-script --url <url> --script-file <file> [--viewport 1280x720] [--strict true|false]",
@@ -11318,6 +11371,9 @@ function optionNumber(options, ...keys) {
11318
11371
  }
11319
11372
  return void 0;
11320
11373
  }
11374
+ function profileOutputDirOption(options) {
11375
+ return optionString(options, "output") ?? optionString(options, "outputDir");
11376
+ }
11321
11377
  function readStdin() {
11322
11378
  return (0, import_node_fs6.readFileSync)(0, "utf-8");
11323
11379
  }
@@ -11546,6 +11602,10 @@ function profileResultMarkdown(result) {
11546
11602
  if (routeInventorySummaryLines.length) {
11547
11603
  lines.push("", "## Route Inventory", "", ...routeInventorySummaryLines);
11548
11604
  }
11605
+ const environmentBlockerLines = profileEnvironmentBlockerMarkdown(result);
11606
+ if (environmentBlockerLines.length) {
11607
+ lines.push("", "## Environment Blocker", "", ...environmentBlockerLines);
11608
+ }
11549
11609
  if (result.artifacts.riddle_artifacts?.length) {
11550
11610
  lines.push("", "## Riddle Artifacts", "");
11551
11611
  for (const artifact of result.artifacts.riddle_artifacts.slice(0, 40)) {
@@ -11637,6 +11697,30 @@ function cliString(value) {
11637
11697
  function cliStringArray(value) {
11638
11698
  return Array.isArray(value) ? value.filter((entry) => typeof entry === "string" && Boolean(entry.trim())) : [];
11639
11699
  }
11700
+ function profileEnvironmentBlockerMarkdown(result) {
11701
+ const blocker = cliRecord(result.environment_blocker);
11702
+ if (!blocker) return [];
11703
+ const lines = [];
11704
+ const reason = cliString(blocker.reason);
11705
+ const source = cliString(blocker.source);
11706
+ const endpoint = cliString(blocker.endpoint);
11707
+ const httpStatus = cliFiniteNumber(blocker.http_status);
11708
+ const error = cliString(blocker.error);
11709
+ const requiredSeconds = cliFiniteNumber(blocker.required_seconds);
11710
+ const availableSeconds = cliFiniteNumber(blocker.available_seconds);
11711
+ const deficitSeconds = cliFiniteNumber(blocker.deficit_seconds);
11712
+ const minimumPurchaseDollars = cliFiniteNumber(blocker.minimum_purchase_dollars);
11713
+ if (reason) lines.push(`- reason: ${reason}`);
11714
+ if (source || endpoint || httpStatus !== void 0) {
11715
+ lines.push(`- source: ${source || "runner"}${endpoint ? ` ${endpoint}` : ""}${httpStatus === void 0 ? "" : ` HTTP ${httpStatus}`}`);
11716
+ }
11717
+ if (error) lines.push(`- error: ${error}`);
11718
+ if (requiredSeconds !== void 0 || availableSeconds !== void 0 || deficitSeconds !== void 0) {
11719
+ lines.push(`- seconds: required ${requiredSeconds ?? "unknown"}, available ${availableSeconds ?? "unknown"}, deficit ${deficitSeconds ?? "unknown"}`);
11720
+ }
11721
+ if (minimumPurchaseDollars !== void 0) lines.push(`- minimum purchase: $${minimumPurchaseDollars}`);
11722
+ return lines;
11723
+ }
11640
11724
  function profileSetupSummaryMarkdown(result) {
11641
11725
  const setupCheck = result.checks.find((check) => check.type === "setup_actions_succeeded");
11642
11726
  const setupSummary = cliRecord(setupCheck?.evidence?.setup_summary);
@@ -11935,7 +12019,7 @@ async function main() {
11935
12019
  if (command === "run-profile") {
11936
12020
  const profile = normalizeProfileForCli(options);
11937
12021
  const result = await runProfileForCli(profile, options);
11938
- writeProfileOutput(optionString(options, "output"), result);
12022
+ writeProfileOutput(profileOutputDirOption(options), result);
11939
12023
  process.stdout.write(`${JSON.stringify(result, null, 2)}
11940
12024
  `);
11941
12025
  process.exitCode = profileStatusExitCode(profile, result.status);
package/dist/cli.js CHANGED
@@ -10,7 +10,7 @@ import {
10
10
  profileStatusExitCode,
11
11
  resolveRiddleProofProfileTargetUrl,
12
12
  resolveRiddleProofProfileTimeoutSec
13
- } from "./chunk-3Y35UIZO.js";
13
+ } from "./chunk-CEBHV23V.js";
14
14
  import {
15
15
  createRiddleApiClient,
16
16
  parseRiddleViewport
@@ -44,7 +44,7 @@ function usage() {
44
44
  " riddle-proof-loop respond --state-path <path> --response-json <file|json|->",
45
45
  " riddle-proof-loop respond --state-path <path> --decision <decision> --summary <text> [--payload-json <file|json|->]",
46
46
  " riddle-proof-loop status --state-path <path>",
47
- " riddle-proof-loop run-profile --profile <file|json|-> --url <base-url> [--runner riddle] [--strict true|false] [--poll-attempts n] [--output <dir>] [--quiet]",
47
+ " riddle-proof-loop run-profile --profile <file|json|-> --url <base-url> [--runner riddle] [--strict true|false] [--poll-attempts n] [--output <dir>|--output-dir <dir>] [--quiet]",
48
48
  " riddle-proof-loop riddle-preview-deploy <build-dir> <label>",
49
49
  " riddle-proof-loop riddle-server-preview <directory> --script-file <file> [--path /route] [--wait-for-selector selector]",
50
50
  " riddle-proof-loop riddle-run-script --url <url> --script-file <file> [--viewport 1280x720] [--strict true|false]",
@@ -106,6 +106,9 @@ function optionNumber(options, ...keys) {
106
106
  }
107
107
  return void 0;
108
108
  }
109
+ function profileOutputDirOption(options) {
110
+ return optionString(options, "output") ?? optionString(options, "outputDir");
111
+ }
109
112
  function readStdin() {
110
113
  return readFileSync(0, "utf-8");
111
114
  }
@@ -334,6 +337,10 @@ function profileResultMarkdown(result) {
334
337
  if (routeInventorySummaryLines.length) {
335
338
  lines.push("", "## Route Inventory", "", ...routeInventorySummaryLines);
336
339
  }
340
+ const environmentBlockerLines = profileEnvironmentBlockerMarkdown(result);
341
+ if (environmentBlockerLines.length) {
342
+ lines.push("", "## Environment Blocker", "", ...environmentBlockerLines);
343
+ }
337
344
  if (result.artifacts.riddle_artifacts?.length) {
338
345
  lines.push("", "## Riddle Artifacts", "");
339
346
  for (const artifact of result.artifacts.riddle_artifacts.slice(0, 40)) {
@@ -425,6 +432,30 @@ function cliString(value) {
425
432
  function cliStringArray(value) {
426
433
  return Array.isArray(value) ? value.filter((entry) => typeof entry === "string" && Boolean(entry.trim())) : [];
427
434
  }
435
+ function profileEnvironmentBlockerMarkdown(result) {
436
+ const blocker = cliRecord(result.environment_blocker);
437
+ if (!blocker) return [];
438
+ const lines = [];
439
+ const reason = cliString(blocker.reason);
440
+ const source = cliString(blocker.source);
441
+ const endpoint = cliString(blocker.endpoint);
442
+ const httpStatus = cliFiniteNumber(blocker.http_status);
443
+ const error = cliString(blocker.error);
444
+ const requiredSeconds = cliFiniteNumber(blocker.required_seconds);
445
+ const availableSeconds = cliFiniteNumber(blocker.available_seconds);
446
+ const deficitSeconds = cliFiniteNumber(blocker.deficit_seconds);
447
+ const minimumPurchaseDollars = cliFiniteNumber(blocker.minimum_purchase_dollars);
448
+ if (reason) lines.push(`- reason: ${reason}`);
449
+ if (source || endpoint || httpStatus !== void 0) {
450
+ lines.push(`- source: ${source || "runner"}${endpoint ? ` ${endpoint}` : ""}${httpStatus === void 0 ? "" : ` HTTP ${httpStatus}`}`);
451
+ }
452
+ if (error) lines.push(`- error: ${error}`);
453
+ if (requiredSeconds !== void 0 || availableSeconds !== void 0 || deficitSeconds !== void 0) {
454
+ lines.push(`- seconds: required ${requiredSeconds ?? "unknown"}, available ${availableSeconds ?? "unknown"}, deficit ${deficitSeconds ?? "unknown"}`);
455
+ }
456
+ if (minimumPurchaseDollars !== void 0) lines.push(`- minimum purchase: $${minimumPurchaseDollars}`);
457
+ return lines;
458
+ }
428
459
  function profileSetupSummaryMarkdown(result) {
429
460
  const setupCheck = result.checks.find((check) => check.type === "setup_actions_succeeded");
430
461
  const setupSummary = cliRecord(setupCheck?.evidence?.setup_summary);
@@ -723,7 +754,7 @@ async function main() {
723
754
  if (command === "run-profile") {
724
755
  const profile = normalizeProfileForCli(options);
725
756
  const result = await runProfileForCli(profile, options);
726
- writeProfileOutput(optionString(options, "output"), result);
757
+ writeProfileOutput(profileOutputDirOption(options), result);
727
758
  process.stdout.write(`${JSON.stringify(result, null, 2)}
728
759
  `);
729
760
  process.exitCode = profileStatusExitCode(profile, result.status);
package/dist/index.cjs CHANGED
@@ -10431,6 +10431,7 @@ function createRiddleProofProfileConfigurationError(name, error, runner = "riddl
10431
10431
  }
10432
10432
  function createRiddleProofProfileEnvironmentBlockedResult(input) {
10433
10433
  const message = input.error instanceof Error ? input.error.message : input.error ? String(input.error) : "Riddle runner did not complete successfully.";
10434
+ const environmentBlocker = extractRiddleRunnerBlocker(message);
10434
10435
  return {
10435
10436
  version: RIDDLE_PROOF_PROFILE_RESULT_VERSION,
10436
10437
  profile_name: input.profile.name,
@@ -10440,12 +10441,64 @@ function createRiddleProofProfileEnvironmentBlockedResult(input) {
10440
10441
  route: { requested: resolveRiddleProofProfileTargetUrl(input.profile), observed: "", matched: false, error: message },
10441
10442
  artifacts: { screenshots: [], proof_json: "proof.json", riddle_artifacts: input.artifacts },
10442
10443
  checks: [],
10443
- summary: `${input.profile.name} could not collect reliable evidence because the runner was blocked.`,
10444
+ summary: summarizeEnvironmentBlockedRunner(input.profile.name, environmentBlocker),
10444
10445
  captured_at: (/* @__PURE__ */ new Date()).toISOString(),
10445
10446
  riddle: input.riddle,
10447
+ environment_blocker: environmentBlocker,
10446
10448
  error: message
10447
10449
  };
10448
10450
  }
10451
+ function extractRiddleRunnerBlocker(message) {
10452
+ const apiError = message.match(/^Riddle API\s+(\S+)\s+failed HTTP\s+(\d+):\s+(\{[\s\S]*\})$/);
10453
+ if (!apiError) return void 0;
10454
+ const details = {
10455
+ source: "riddle_api",
10456
+ endpoint: apiError[1],
10457
+ http_status: Number(apiError[2])
10458
+ };
10459
+ let payload;
10460
+ try {
10461
+ const parsed = JSON.parse(apiError[3]);
10462
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
10463
+ payload = parsed;
10464
+ }
10465
+ } catch {
10466
+ payload = void 0;
10467
+ }
10468
+ const copyScalar = (key) => {
10469
+ const value = payload?.[key];
10470
+ if (typeof value === "string" || typeof value === "boolean") details[key] = value;
10471
+ if (typeof value === "number" && Number.isFinite(value)) details[key] = value;
10472
+ };
10473
+ for (const key of ["error", "required_seconds", "available_seconds", "deficit_seconds", "minimum_purchase_dollars"]) {
10474
+ copyScalar(key);
10475
+ }
10476
+ const httpStatus = typeof details.http_status === "number" ? details.http_status : void 0;
10477
+ const errorText = typeof details.error === "string" ? details.error.toLowerCase() : "";
10478
+ if (httpStatus === 402 && errorText.includes("balance")) {
10479
+ details.reason = "insufficient_balance";
10480
+ }
10481
+ return details;
10482
+ }
10483
+ function summarizeEnvironmentBlockedRunner(profileName, blocker) {
10484
+ if (blocker?.reason === "insufficient_balance") {
10485
+ const required = typeof blocker.required_seconds === "number" ? blocker.required_seconds : void 0;
10486
+ const available = typeof blocker.available_seconds === "number" ? blocker.available_seconds : void 0;
10487
+ const deficit = typeof blocker.deficit_seconds === "number" ? blocker.deficit_seconds : void 0;
10488
+ const parts = [
10489
+ required === void 0 ? "" : `required ${required}s`,
10490
+ available === void 0 ? "" : `available ${available}s`,
10491
+ deficit === void 0 ? "" : `deficit ${deficit}s`
10492
+ ].filter(Boolean);
10493
+ return `${profileName} could not start because Riddle balance was insufficient${parts.length ? ` (${parts.join(", ")})` : ""}.`;
10494
+ }
10495
+ if (blocker?.source === "riddle_api") {
10496
+ const endpoint = typeof blocker.endpoint === "string" ? blocker.endpoint : "Riddle API";
10497
+ const status = typeof blocker.http_status === "number" ? blocker.http_status : void 0;
10498
+ return `${profileName} could not start because ${endpoint} returned${status === void 0 ? "" : ` HTTP ${status}`}.`;
10499
+ }
10500
+ return `${profileName} could not collect reliable evidence because the runner was blocked.`;
10501
+ }
10449
10502
  function createRiddleProofProfileInsufficientResult(input) {
10450
10503
  const message = input.error instanceof Error ? input.error.message : input.error ? String(input.error) : "No proof.json profile result artifact was found.";
10451
10504
  return {
package/dist/index.js CHANGED
@@ -58,7 +58,7 @@ import {
58
58
  resolveRiddleProofProfileTimeoutSec,
59
59
  slugifyRiddleProofProfileName,
60
60
  summarizeRiddleProofProfileResult
61
- } from "./chunk-3Y35UIZO.js";
61
+ } from "./chunk-CEBHV23V.js";
62
62
  import {
63
63
  DEFAULT_RIDDLE_API_BASE_URL,
64
64
  DEFAULT_RIDDLE_API_KEY_FILE,
package/dist/profile.cjs CHANGED
@@ -1746,6 +1746,7 @@ function createRiddleProofProfileConfigurationError(name, error, runner = "riddl
1746
1746
  }
1747
1747
  function createRiddleProofProfileEnvironmentBlockedResult(input) {
1748
1748
  const message = input.error instanceof Error ? input.error.message : input.error ? String(input.error) : "Riddle runner did not complete successfully.";
1749
+ const environmentBlocker = extractRiddleRunnerBlocker(message);
1749
1750
  return {
1750
1751
  version: RIDDLE_PROOF_PROFILE_RESULT_VERSION,
1751
1752
  profile_name: input.profile.name,
@@ -1755,12 +1756,64 @@ function createRiddleProofProfileEnvironmentBlockedResult(input) {
1755
1756
  route: { requested: resolveRiddleProofProfileTargetUrl(input.profile), observed: "", matched: false, error: message },
1756
1757
  artifacts: { screenshots: [], proof_json: "proof.json", riddle_artifacts: input.artifacts },
1757
1758
  checks: [],
1758
- summary: `${input.profile.name} could not collect reliable evidence because the runner was blocked.`,
1759
+ summary: summarizeEnvironmentBlockedRunner(input.profile.name, environmentBlocker),
1759
1760
  captured_at: (/* @__PURE__ */ new Date()).toISOString(),
1760
1761
  riddle: input.riddle,
1762
+ environment_blocker: environmentBlocker,
1761
1763
  error: message
1762
1764
  };
1763
1765
  }
1766
+ function extractRiddleRunnerBlocker(message) {
1767
+ const apiError = message.match(/^Riddle API\s+(\S+)\s+failed HTTP\s+(\d+):\s+(\{[\s\S]*\})$/);
1768
+ if (!apiError) return void 0;
1769
+ const details = {
1770
+ source: "riddle_api",
1771
+ endpoint: apiError[1],
1772
+ http_status: Number(apiError[2])
1773
+ };
1774
+ let payload;
1775
+ try {
1776
+ const parsed = JSON.parse(apiError[3]);
1777
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
1778
+ payload = parsed;
1779
+ }
1780
+ } catch {
1781
+ payload = void 0;
1782
+ }
1783
+ const copyScalar = (key) => {
1784
+ const value = payload?.[key];
1785
+ if (typeof value === "string" || typeof value === "boolean") details[key] = value;
1786
+ if (typeof value === "number" && Number.isFinite(value)) details[key] = value;
1787
+ };
1788
+ for (const key of ["error", "required_seconds", "available_seconds", "deficit_seconds", "minimum_purchase_dollars"]) {
1789
+ copyScalar(key);
1790
+ }
1791
+ const httpStatus = typeof details.http_status === "number" ? details.http_status : void 0;
1792
+ const errorText = typeof details.error === "string" ? details.error.toLowerCase() : "";
1793
+ if (httpStatus === 402 && errorText.includes("balance")) {
1794
+ details.reason = "insufficient_balance";
1795
+ }
1796
+ return details;
1797
+ }
1798
+ function summarizeEnvironmentBlockedRunner(profileName, blocker) {
1799
+ if (blocker?.reason === "insufficient_balance") {
1800
+ const required = typeof blocker.required_seconds === "number" ? blocker.required_seconds : void 0;
1801
+ const available = typeof blocker.available_seconds === "number" ? blocker.available_seconds : void 0;
1802
+ const deficit = typeof blocker.deficit_seconds === "number" ? blocker.deficit_seconds : void 0;
1803
+ const parts = [
1804
+ required === void 0 ? "" : `required ${required}s`,
1805
+ available === void 0 ? "" : `available ${available}s`,
1806
+ deficit === void 0 ? "" : `deficit ${deficit}s`
1807
+ ].filter(Boolean);
1808
+ return `${profileName} could not start because Riddle balance was insufficient${parts.length ? ` (${parts.join(", ")})` : ""}.`;
1809
+ }
1810
+ if (blocker?.source === "riddle_api") {
1811
+ const endpoint = typeof blocker.endpoint === "string" ? blocker.endpoint : "Riddle API";
1812
+ const status = typeof blocker.http_status === "number" ? blocker.http_status : void 0;
1813
+ return `${profileName} could not start because ${endpoint} returned${status === void 0 ? "" : ` HTTP ${status}`}.`;
1814
+ }
1815
+ return `${profileName} could not collect reliable evidence because the runner was blocked.`;
1816
+ }
1764
1817
  function createRiddleProofProfileInsufficientResult(input) {
1765
1818
  const message = input.error instanceof Error ? input.error.message : input.error ? String(input.error) : "No proof.json profile result artifact was found.";
1766
1819
  return {
@@ -253,6 +253,7 @@ interface RiddleProofProfileResult {
253
253
  status?: string | null;
254
254
  terminal?: boolean;
255
255
  };
256
+ environment_blocker?: Record<string, JsonValue>;
256
257
  error?: string;
257
258
  }
258
259
  interface RiddleProofProfileArtifactRef {
package/dist/profile.d.ts CHANGED
@@ -253,6 +253,7 @@ interface RiddleProofProfileResult {
253
253
  status?: string | null;
254
254
  terminal?: boolean;
255
255
  };
256
+ environment_blocker?: Record<string, JsonValue>;
256
257
  error?: string;
257
258
  }
258
259
  interface RiddleProofProfileArtifactRef {
package/dist/profile.js CHANGED
@@ -19,7 +19,7 @@ import {
19
19
  resolveRiddleProofProfileTimeoutSec,
20
20
  slugifyRiddleProofProfileName,
21
21
  summarizeRiddleProofProfileResult
22
- } from "./chunk-3Y35UIZO.js";
22
+ } from "./chunk-CEBHV23V.js";
23
23
  export {
24
24
  RIDDLE_PROOF_PROFILE_CHECK_TYPES,
25
25
  RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@riddledc/riddle-proof",
3
- "version": "0.7.85",
3
+ "version": "0.7.87",
4
4
  "description": "Reusable Riddle Proof contracts and helpers for evidence-backed agent changes.",
5
5
  "license": "MIT",
6
6
  "author": "RiddleDC",