@riddledc/riddle-proof 0.7.152 → 0.7.154

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/dist/cli.cjs CHANGED
@@ -6856,12 +6856,14 @@ async function pollRiddleJob(config, jobId, options = {}) {
6856
6856
  const attempts = Math.max(1, Math.floor(options.attempts ?? (options.wait ? 300 : 1)));
6857
6857
  const intervalMs = Math.max(0, Math.floor(options.intervalMs ?? 2e3));
6858
6858
  const progressEveryMs = Math.max(0, Math.floor(options.progressEveryMs ?? 1e4));
6859
+ const unsubmittedTimeoutMs = Math.max(0, Math.floor(options.unsubmittedTimeoutMs ?? 0));
6859
6860
  const startedAt = Date.now();
6860
6861
  let job = null;
6861
6862
  let lastSnapshot = null;
6862
6863
  let lastProgressAt = 0;
6863
6864
  let lastProgressKey = "";
6864
6865
  let preSubmissionElapsedMs = 0;
6866
+ let unsubmittedTimedOut = false;
6865
6867
  for (let index = 0; index < attempts; index += 1) {
6866
6868
  job = await riddleRequestJson(config, `/v1/jobs/${jobId}`);
6867
6869
  const observedAt = Date.now();
@@ -6892,7 +6894,11 @@ async function pollRiddleJob(config, jobId, options = {}) {
6892
6894
  await options.onProgress(lastSnapshot);
6893
6895
  }
6894
6896
  }
6897
+ unsubmittedTimedOut = Boolean(
6898
+ options.wait && unsubmittedTimeoutMs > 0 && lastSnapshot.running_without_submission && !lastSnapshot.created_at && !lastSnapshot.submitted_at && preSubmissionElapsedMs >= unsubmittedTimeoutMs
6899
+ );
6895
6900
  if (lastSnapshot.terminal) break;
6901
+ if (unsubmittedTimedOut) break;
6896
6902
  if (index + 1 < attempts) {
6897
6903
  await new Promise((resolve) => setTimeout(resolve, intervalMs));
6898
6904
  }
@@ -6917,6 +6923,8 @@ async function pollRiddleJob(config, jobId, options = {}) {
6917
6923
  ...snapshot,
6918
6924
  timed_out: timedOut,
6919
6925
  interval_ms: intervalMs,
6926
+ unsubmitted_timeout: unsubmittedTimedOut || void 0,
6927
+ unsubmitted_timeout_ms: unsubmittedTimedOut ? unsubmittedTimeoutMs : void 0,
6920
6928
  message: pollMessage(snapshot, timedOut)
6921
6929
  }
6922
6930
  };
@@ -7429,6 +7437,8 @@ function profileSetupWindowCallReceipts(results) {
7429
7437
  };
7430
7438
  if (result.returned !== void 0) receipt.returned = result.returned;
7431
7439
  if (result.expected_return !== void 0) receipt.expected_return = result.expected_return;
7440
+ const returnSummary = profileSetupReturnSummary(result);
7441
+ if (returnSummary.length) receipt.return_summary = returnSummary;
7432
7442
  return receipt;
7433
7443
  });
7434
7444
  }
@@ -7444,6 +7454,40 @@ function profileSetupWindowEvalReceipts(results) {
7444
7454
  };
7445
7455
  if (result.returned !== void 0) receipt.returned = result.returned;
7446
7456
  if (result.expected_return !== void 0) receipt.expected_return = result.expected_return;
7457
+ const returnSummary = profileSetupReturnSummary(result);
7458
+ if (returnSummary.length) receipt.return_summary = returnSummary;
7459
+ return receipt;
7460
+ });
7461
+ }
7462
+ function profileSetupReturnSummaryFields(result) {
7463
+ const input = result.return_summary_fields;
7464
+ if (!Array.isArray(input)) return [];
7465
+ const fields = [];
7466
+ for (const item of input) {
7467
+ if (typeof item === "string") {
7468
+ const path8 = item.trim();
7469
+ if (path8) fields.push({ path: path8 });
7470
+ continue;
7471
+ }
7472
+ if (!isRecord(item)) continue;
7473
+ const path7 = stringValue2(item.path) ?? stringValue2(item.key) ?? stringValue2(item.json_path) ?? stringValue2(item.jsonPath);
7474
+ if (!path7) continue;
7475
+ const label = stringValue2(item.label) ?? stringValue2(item.name) ?? stringValue2(item.title);
7476
+ fields.push(label ? { path: path7, label } : { path: path7 });
7477
+ }
7478
+ return fields;
7479
+ }
7480
+ function profileSetupReturnSummary(result) {
7481
+ if (result.returned === void 0) return [];
7482
+ return profileSetupReturnSummaryFields(result).map((field) => {
7483
+ const resolved = resolveJsonPath(result.returned, field.path);
7484
+ const receipt = {
7485
+ label: field.label || field.path,
7486
+ path: field.path,
7487
+ exists: resolved.exists
7488
+ };
7489
+ if (resolved.exists) receipt.value = toJsonValue(resolved.value);
7490
+ if (resolved.error) receipt.reason = resolved.error;
7447
7491
  return receipt;
7448
7492
  });
7449
7493
  }
@@ -7632,6 +7676,37 @@ function normalizeSetupActionArgs(input, index) {
7632
7676
  }
7633
7677
  return argsInput.map(toJsonValue);
7634
7678
  }
7679
+ function normalizeReturnSummaryFields(input, index) {
7680
+ const fieldsInput = valueFromOwn(
7681
+ input,
7682
+ "return_summary_fields",
7683
+ "returnSummaryFields",
7684
+ "summary_fields",
7685
+ "summaryFields",
7686
+ "receipt_fields",
7687
+ "receiptFields",
7688
+ "return_receipt_fields",
7689
+ "returnReceiptFields"
7690
+ );
7691
+ if (fieldsInput === void 0) return void 0;
7692
+ if (!Array.isArray(fieldsInput)) {
7693
+ throw new Error(`target.setup_actions[${index}].return_summary_fields must be an array.`);
7694
+ }
7695
+ return fieldsInput.map((field, fieldIndex) => {
7696
+ if (typeof field === "string") {
7697
+ const path8 = field.trim();
7698
+ if (!path8) throw new Error(`target.setup_actions[${index}].return_summary_fields[${fieldIndex}] requires path.`);
7699
+ return { path: path8 };
7700
+ }
7701
+ if (!isRecord(field)) {
7702
+ throw new Error(`target.setup_actions[${index}].return_summary_fields[${fieldIndex}] must be a string path or object.`);
7703
+ }
7704
+ const path7 = stringFromOwn(field, "path", "key", "json_path", "jsonPath");
7705
+ if (!path7) throw new Error(`target.setup_actions[${index}].return_summary_fields[${fieldIndex}] requires path.`);
7706
+ const label = stringFromOwn(field, "label", "name", "title");
7707
+ return label ? { path: path7, label } : { path: path7 };
7708
+ });
7709
+ }
7635
7710
  function normalizeSetupActionRepeat(input, index) {
7636
7711
  const repeat = numberValue(valueFromOwn(input, "repeat", "repeat_count", "repeatCount", "times"));
7637
7712
  if (repeat === void 0) return void 0;
@@ -7853,6 +7928,7 @@ function normalizeSetupAction(input, index) {
7853
7928
  expect_return: hasExpectedReturn ? toJsonValue(valueFromOwn(input, "expect_return", "expectReturn", "expected_return", "expectedReturn")) : void 0,
7854
7929
  store_return_to: storeReturnTo,
7855
7930
  capture_return: captureReturn,
7931
+ return_summary_fields: normalizeReturnSummaryFields(input, index),
7856
7932
  until_path: untilPath,
7857
7933
  until_expected_value: hasUntilExpectedValue ? toJsonValue(valueFromOwn(input, "until_expected_value", "untilExpectedValue", "until_expected", "untilExpected", "until_value", "untilValue", "expected_value", "expectedValue", "expected")) : void 0,
7858
7934
  max_calls: maxCalls,
@@ -10875,6 +10951,8 @@ function profileSetupWindowCallReceipts(results) {
10875
10951
  };
10876
10952
  if (result.returned !== undefined) receipt.returned = result.returned;
10877
10953
  if (result.expected_return !== undefined) receipt.expected_return = result.expected_return;
10954
+ const returnSummary = profileSetupReturnSummary(result);
10955
+ if (returnSummary.length) receipt.return_summary = returnSummary;
10878
10956
  return receipt;
10879
10957
  });
10880
10958
  }
@@ -10892,9 +10970,43 @@ function profileSetupWindowEvalReceipts(results) {
10892
10970
  };
10893
10971
  if (result.returned !== undefined) receipt.returned = result.returned;
10894
10972
  if (result.expected_return !== undefined) receipt.expected_return = result.expected_return;
10973
+ const returnSummary = profileSetupReturnSummary(result);
10974
+ if (returnSummary.length) receipt.return_summary = returnSummary;
10895
10975
  return receipt;
10896
10976
  });
10897
10977
  }
10978
+ function profileSetupReturnSummaryFields(result) {
10979
+ const input = result && result.return_summary_fields;
10980
+ if (!Array.isArray(input)) return [];
10981
+ const fields = [];
10982
+ for (const item of input) {
10983
+ if (typeof item === "string") {
10984
+ const path = item.trim();
10985
+ if (path) fields.push({ path });
10986
+ continue;
10987
+ }
10988
+ if (!item || typeof item !== "object" || Array.isArray(item)) continue;
10989
+ const path = String(item.path || item.key || item.json_path || item.jsonPath || "").trim();
10990
+ if (!path) continue;
10991
+ const label = String(item.label || item.name || item.title || "").trim();
10992
+ fields.push(label ? { path, label } : { path });
10993
+ }
10994
+ return fields;
10995
+ }
10996
+ function profileSetupReturnSummary(result) {
10997
+ if (!result || result.returned === undefined) return [];
10998
+ return profileSetupReturnSummaryFields(result).map((field) => {
10999
+ const resolved = resolveJsonProbePath(result.returned, field.path);
11000
+ const receipt = {
11001
+ label: field.label || field.path,
11002
+ path: field.path,
11003
+ exists: Boolean(resolved.exists),
11004
+ };
11005
+ if (resolved.exists) receipt.value = setupJsonValue(resolved.value);
11006
+ if (resolved.error) receipt.reason = resolved.error;
11007
+ return receipt;
11008
+ });
11009
+ }
10898
11010
  function profileSetupRangeValueReceipts(results) {
10899
11011
  return (results || [])
10900
11012
  .filter((result) => result && profileSetupResultAction(result) === "set_range_value")
@@ -12629,6 +12741,7 @@ async function executeSetupAction(action, ordinal, viewport) {
12629
12741
  const script = String(action.script || action.code || action.source || action.body || "");
12630
12742
  const args = Array.isArray(action.args) ? action.args : [];
12631
12743
  const storeReturnTo = String(action.store_return_to || action.storeReturnTo || action.save_return_to || action.saveReturnTo || action.assign_return_to || action.assignReturnTo || action.return_state_path || action.returnStatePath || "").trim();
12744
+ const returnSummaryFields = Array.isArray(action.return_summary_fields) ? action.return_summary_fields : [];
12632
12745
  if (!script.trim()) return { ...base, reason: "missing_script" };
12633
12746
  const scope = await setupActionScope(action, timeout);
12634
12747
  if (!scope.ok) return setupScopeFailure(base, scope);
@@ -12658,6 +12771,7 @@ async function executeSetupAction(action, ordinal, viewport) {
12658
12771
  return_captured: captureReturn,
12659
12772
  expected_return: hasExpectation ? setupJsonValue(expected) : undefined,
12660
12773
  return_stored_to: result.return_stored_to || storeReturnTo || undefined,
12774
+ return_summary_fields: returnSummaryFields.length ? setupJsonValue(returnSummaryFields) : undefined,
12661
12775
  reason: result.ok ? (expectationMet ? undefined : "unexpected_return_value") : result.reason,
12662
12776
  store_reason: result.store_reason || undefined,
12663
12777
  error: result.error || undefined,
@@ -12667,6 +12781,7 @@ async function executeSetupAction(action, ordinal, viewport) {
12667
12781
  const path = String(action.path || action.function_path || action.functionPath || "");
12668
12782
  const args = Array.isArray(action.args) ? action.args : [];
12669
12783
  const storeReturnTo = String(action.store_return_to || action.storeReturnTo || action.save_return_to || action.saveReturnTo || action.assign_return_to || action.assignReturnTo || action.return_state_path || action.returnStatePath || "").trim();
12784
+ const returnSummaryFields = Array.isArray(action.return_summary_fields) ? action.return_summary_fields : [];
12670
12785
  if (!path) return { ...base, path, reason: "missing_path" };
12671
12786
  const scope = await setupActionScope(action, timeout);
12672
12787
  if (!scope.ok) return setupScopeFailure(base, scope);
@@ -12696,6 +12811,7 @@ async function executeSetupAction(action, ordinal, viewport) {
12696
12811
  return_captured: captureReturn,
12697
12812
  expected_return: hasExpectation ? setupJsonValue(expected) : undefined,
12698
12813
  return_stored_to: result.return_stored_to || storeReturnTo || undefined,
12814
+ return_summary_fields: returnSummaryFields.length ? setupJsonValue(returnSummaryFields) : undefined,
12699
12815
  reason: result.ok ? (expectationMet ? undefined : "unexpected_return_value") : result.reason,
12700
12816
  store_reason: result.store_reason || undefined,
12701
12817
  error: result.error || undefined,
@@ -14741,6 +14857,8 @@ function runProfileStrictOption(options) {
14741
14857
  function runProfileSplitViewportsOption(options) {
14742
14858
  return optionBoolean(options, "splitViewports") ?? false;
14743
14859
  }
14860
+ var DEFAULT_PROFILE_UNSUBMITTED_RETRY_TIMEOUT_MS = 9e4;
14861
+ var DEFAULT_PROFILE_UNSUBMITTED_RETRIES = 1;
14744
14862
  function optionNumber(options, ...keys) {
14745
14863
  for (const key of keys) {
14746
14864
  const value = optionString(options, key);
@@ -14748,6 +14866,11 @@ function optionNumber(options, ...keys) {
14748
14866
  }
14749
14867
  return void 0;
14750
14868
  }
14869
+ function optionInteger(options, fallback, ...keys) {
14870
+ const value = optionNumber(options, ...keys);
14871
+ if (value === void 0 || !Number.isFinite(value)) return fallback;
14872
+ return Math.floor(value);
14873
+ }
14751
14874
  function profileOutputDirOption(options) {
14752
14875
  return optionString(options, "output") ?? optionString(options, "outputDir");
14753
14876
  }
@@ -15065,6 +15188,8 @@ function profileRiddleJobMarkdown(result) {
15065
15188
  const submittedAt = cliString(riddle.submitted_at);
15066
15189
  const completedAt = cliString(riddle.completed_at);
15067
15190
  const artifactRecovery = riddle.artifact_recovery === true;
15191
+ const retryCount = cliFiniteNumber(riddle.retry_count);
15192
+ const staleJobIds = Array.isArray(riddle.stale_job_ids) ? riddle.stale_job_ids.map((value) => cliString(value)).filter((value) => Boolean(value)) : [];
15068
15193
  const parts = [
15069
15194
  mode ? `mode ${markdownInlineCode(mode)}` : "",
15070
15195
  jobCount === void 0 ? "" : `jobs ${jobCount}`,
@@ -15084,6 +15209,9 @@ function profileRiddleJobMarkdown(result) {
15084
15209
  if (artifactRecovery) {
15085
15210
  lines.push("- artifact recovery: used artifacts endpoint after non-terminal poll");
15086
15211
  }
15212
+ if (retryCount !== void 0 && retryCount > 0) {
15213
+ lines.push(`- retry recovery: replaced ${retryCount} unsubmitted job${retryCount === 1 ? "" : "s"}${staleJobIds.length ? ` (${staleJobIds.map((value) => markdownInlineCode(value)).join(", ")})` : ""}`);
15214
+ }
15087
15215
  const splitJobs = Array.isArray(riddle.split_jobs) ? riddle.split_jobs.map(cliRecord).filter((job) => Boolean(job)) : [];
15088
15216
  for (const job of splitJobs.slice(0, 12)) {
15089
15217
  const viewport = cliString(job.viewport) || "viewport";
@@ -15093,6 +15221,7 @@ function profileRiddleJobMarkdown(result) {
15093
15221
  const splitElapsedMs = cliFiniteNumber(job.elapsed_ms);
15094
15222
  const splitPreSubmissionElapsedMs = cliFiniteNumber(job.pre_submission_elapsed_ms);
15095
15223
  const splitArtifactRecovery = job.artifact_recovery === true;
15224
+ const splitRetryCount = cliFiniteNumber(job.retry_count);
15096
15225
  lines.push(
15097
15226
  `- ${viewport}: ${[
15098
15227
  splitJobId ? `job ${markdownInlineCode(splitJobId)}` : "",
@@ -15100,6 +15229,7 @@ function profileRiddleJobMarkdown(result) {
15100
15229
  splitTerminal === void 0 ? "" : `terminal ${splitTerminal ? "true" : "false"}`,
15101
15230
  splitElapsedMs === void 0 ? "" : `elapsed ${formatPollDuration(splitElapsedMs)}`,
15102
15231
  splitPreSubmissionElapsedMs === void 0 || splitPreSubmissionElapsedMs < 1e3 ? "" : `pre-submit ${formatPollDuration(splitPreSubmissionElapsedMs)}`,
15232
+ splitRetryCount === void 0 || splitRetryCount <= 0 ? "" : `retries ${splitRetryCount}`,
15103
15233
  splitArtifactRecovery ? "artifact recovery" : ""
15104
15234
  ].filter(Boolean).join(", ") || "job metadata unavailable"}`
15105
15235
  );
@@ -15254,6 +15384,15 @@ function cliValueLabel(value) {
15254
15384
  return String(value);
15255
15385
  }
15256
15386
  }
15387
+ function cliReturnSummaryLabel(value) {
15388
+ if (!Array.isArray(value)) return void 0;
15389
+ const parts = value.map(cliRecord).filter((item) => Boolean(item)).map((item) => {
15390
+ const label = cliString(item.label) || cliString(item.path) || "value";
15391
+ const observed = item.exists === false ? "missing" : cliValueLabel(item.value);
15392
+ return `${label}=${observed ?? "null"}`;
15393
+ }).filter(Boolean);
15394
+ return parts.length ? parts.join(", ") : void 0;
15395
+ }
15257
15396
  function cliStringArray(value) {
15258
15397
  return Array.isArray(value) ? value.filter((entry) => typeof entry === "string" && Boolean(entry.trim())) : [];
15259
15398
  }
@@ -15428,10 +15567,11 @@ function profileSetupSummaryMarkdown(result) {
15428
15567
  const storedTo = cliString(receipt.return_stored_to);
15429
15568
  const returned = cliValueLabel(receipt.returned);
15430
15569
  const expected = cliValueLabel(receipt.expected_return);
15570
+ const returnSummary = cliReturnSummaryLabel(receipt.return_summary);
15431
15571
  const captured = receipt.return_captured === true ? "captured" : receipt.return_captured === false ? "not captured" : "capture unknown";
15432
15572
  const ok = receipt.ok === false ? "failed" : "ok";
15433
15573
  const reason = cliString(receipt.reason);
15434
- lines.push(`- ${name} window_call: ${ok}, ${markdownInlineCode(path7)}${storedTo ? `, stored ${markdownInlineCode(storedTo)}` : ""}, return ${captured}${expected === void 0 ? "" : `, expected ${markdownInlineCode(expected, 80)}`}${returned === void 0 ? "" : `, returned ${markdownInlineCode(returned, 80)}`}${reason ? `, reason ${markdownInlineCode(reason, 100)}` : ""}`);
15574
+ lines.push(`- ${name} window_call: ${ok}, ${markdownInlineCode(path7)}${storedTo ? `, stored ${markdownInlineCode(storedTo)}` : ""}, return ${captured}${expected === void 0 ? "" : `, expected ${markdownInlineCode(expected, 80)}`}${returnSummary ? `, summary ${markdownInlineCode(returnSummary, 140)}` : ""}${returned === void 0 ? "" : `, returned ${markdownInlineCode(returned, 80)}`}${reason ? `, reason ${markdownInlineCode(reason, 100)}` : ""}`);
15435
15575
  }
15436
15576
  if (windowCallDetails.length > 12) lines.push(`- ${windowCallDetails.length - 12} additional window_call receipt(s) omitted.`);
15437
15577
  const windowEvalDetails = viewports.flatMap((viewport) => {
@@ -15444,10 +15584,11 @@ function profileSetupSummaryMarkdown(result) {
15444
15584
  const storedTo = cliString(receipt.return_stored_to);
15445
15585
  const returned = cliValueLabel(receipt.returned);
15446
15586
  const expected = cliValueLabel(receipt.expected_return);
15587
+ const returnSummary = cliReturnSummaryLabel(receipt.return_summary);
15447
15588
  const captured = receipt.return_captured === true ? "captured" : receipt.return_captured === false ? "not captured" : "capture unknown";
15448
15589
  const ok = receipt.ok === false ? "failed" : "ok";
15449
15590
  const reason = cliString(receipt.reason);
15450
- lines.push(`- ${name} window_eval: ${ok}${scriptLength === void 0 ? "" : `, script ${scriptLength} chars`}${storedTo ? `, stored ${markdownInlineCode(storedTo)}` : ""}, return ${captured}${expected === void 0 ? "" : `, expected ${markdownInlineCode(expected, 80)}`}${returned === void 0 ? "" : `, returned ${markdownInlineCode(returned, 80)}`}${reason ? `, reason ${markdownInlineCode(reason, 100)}` : ""}`);
15591
+ lines.push(`- ${name} window_eval: ${ok}${scriptLength === void 0 ? "" : `, script ${scriptLength} chars`}${storedTo ? `, stored ${markdownInlineCode(storedTo)}` : ""}, return ${captured}${expected === void 0 ? "" : `, expected ${markdownInlineCode(expected, 80)}`}${returnSummary ? `, summary ${markdownInlineCode(returnSummary, 140)}` : ""}${returned === void 0 ? "" : `, returned ${markdownInlineCode(returned, 80)}`}${reason ? `, reason ${markdownInlineCode(reason, 100)}` : ""}`);
15451
15592
  }
15452
15593
  if (windowEvalDetails.length > 12) lines.push(`- ${windowEvalDetails.length - 12} additional window_eval receipt(s) omitted.`);
15453
15594
  const windowCallUntilDetails = viewports.flatMap((viewport) => {
@@ -15739,6 +15880,7 @@ async function profileResultFromRiddleArtifacts(profile, artifacts, fallbackInpu
15739
15880
  }
15740
15881
  function withRiddleMetadata(result, input) {
15741
15882
  const poll = input.poll;
15883
+ const staleJobIds = input.staleJobIds?.filter(Boolean);
15742
15884
  return {
15743
15885
  ...result,
15744
15886
  riddle: {
@@ -15755,6 +15897,8 @@ function withRiddleMetadata(result, input) {
15755
15897
  attempt: poll?.attempt ?? result.riddle?.attempt,
15756
15898
  attempts: poll?.attempts ?? result.riddle?.attempts,
15757
15899
  timed_out: poll?.timed_out ?? result.riddle?.timed_out,
15900
+ retry_count: input.retryCount ?? result.riddle?.retry_count,
15901
+ stale_job_ids: staleJobIds?.length ? staleJobIds : result.riddle?.stale_job_ids,
15758
15902
  artifact_recovery: input.artifactRecovery ?? result.riddle?.artifact_recovery
15759
15903
  },
15760
15904
  artifacts: {
@@ -15825,6 +15969,40 @@ function riddleMetadataFromPoll(jobId, poll) {
15825
15969
  timed_out: poll.poll?.timed_out
15826
15970
  };
15827
15971
  }
15972
+ function profileUnsubmittedRetryTimeoutMs(options) {
15973
+ return Math.max(0, optionInteger(
15974
+ options,
15975
+ DEFAULT_PROFILE_UNSUBMITTED_RETRY_TIMEOUT_MS,
15976
+ "unsubmittedTimeoutMs",
15977
+ "unsubmittedJobTimeoutMs",
15978
+ "submitTimeoutMs"
15979
+ ));
15980
+ }
15981
+ function profileUnsubmittedRetryLimit(options) {
15982
+ return Math.max(0, optionInteger(
15983
+ options,
15984
+ DEFAULT_PROFILE_UNSUBMITTED_RETRIES,
15985
+ "unsubmittedRetries",
15986
+ "unsubmittedJobRetries",
15987
+ "submitRetries"
15988
+ ));
15989
+ }
15990
+ function shouldRetryUnsubmittedRiddleJob(poll) {
15991
+ return poll.terminal !== true && poll.poll?.unsubmitted_timeout === true && !poll.poll.created_at && !poll.poll.submitted_at;
15992
+ }
15993
+ function riddlePollOptionsForProfile(options) {
15994
+ return {
15995
+ wait: true,
15996
+ attempts: optionNumber(options, "pollAttempts", "attempts"),
15997
+ intervalMs: optionNumber(options, "intervalMs"),
15998
+ progressEveryMs: optionNumber(options, "progressEveryMs"),
15999
+ unsubmittedTimeoutMs: profileUnsubmittedRetryTimeoutMs(options),
16000
+ onProgress: options.quiet !== true ? (snapshot) => {
16001
+ process.stderr.write(`${riddlePollProgressLine(snapshot)}
16002
+ `);
16003
+ } : void 0
16004
+ };
16005
+ }
15828
16006
  function profileForSplitViewport(profile, viewport) {
15829
16007
  return {
15830
16008
  ...profile,
@@ -15872,6 +16050,8 @@ function splitViewportRiddleMetadata(childRuns) {
15872
16050
  attempt: result.riddle?.attempt,
15873
16051
  attempts: result.riddle?.attempts,
15874
16052
  timed_out: result.riddle?.timed_out,
16053
+ retry_count: result.riddle?.retry_count,
16054
+ stale_job_ids: result.riddle?.stale_job_ids,
15875
16055
  artifact_recovery: result.riddle?.artifact_recovery
15876
16056
  }));
15877
16057
  return {
@@ -15883,6 +16063,8 @@ function splitViewportRiddleMetadata(childRuns) {
15883
16063
  queue_elapsed_ms: sumDefinedNumbers(splitJobs.map((job) => job.queue_elapsed_ms)),
15884
16064
  pre_submission_elapsed_ms: sumDefinedNumbers(splitJobs.map((job) => job.pre_submission_elapsed_ms)),
15885
16065
  elapsed_ms: sumDefinedNumbers(splitJobs.map((job) => job.elapsed_ms)),
16066
+ retry_count: splitJobs.reduce((sum, job) => sum + (typeof job.retry_count === "number" && Number.isFinite(job.retry_count) ? job.retry_count : 0), 0),
16067
+ stale_job_ids: splitJobs.flatMap((job) => Array.isArray(job.stale_job_ids) ? job.stale_job_ids : []),
15886
16068
  split_jobs: splitJobs
15887
16069
  };
15888
16070
  }
@@ -15970,37 +16152,48 @@ async function runSingleRiddleProfileForCli(profile, options, input) {
15970
16152
  const { client, runner } = input;
15971
16153
  const targetUrl = resolveRiddleProofProfileTargetUrl(profile);
15972
16154
  let created;
15973
- try {
15974
- created = await client.runScript({
15975
- url: targetUrl,
15976
- script: buildRiddleProofProfileScript(profile),
15977
- viewport: profile.target.viewports[0],
15978
- timeoutSec: resolveRiddleProofProfileTimeoutSec(
15979
- profile,
15980
- optionString(options, "timeout") ? Number(optionString(options, "timeout")) : void 0
15981
- ),
15982
- strict: runProfileStrictOption(options),
15983
- sync: options.sync === true ? true : void 0
15984
- });
15985
- } catch (error) {
15986
- return createRiddleProofProfileEnvironmentBlockedResult({ profile, runner, error });
16155
+ let poll;
16156
+ let jobId = "";
16157
+ const staleJobIds = [];
16158
+ const retryLimit = profileUnsubmittedRetryLimit(options);
16159
+ const pollOptions = riddlePollOptionsForProfile(options);
16160
+ for (let attempt = 0; attempt <= retryLimit; attempt += 1) {
16161
+ try {
16162
+ created = await client.runScript({
16163
+ url: targetUrl,
16164
+ script: buildRiddleProofProfileScript(profile),
16165
+ viewport: profile.target.viewports[0],
16166
+ timeoutSec: resolveRiddleProofProfileTimeoutSec(
16167
+ profile,
16168
+ optionString(options, "timeout") ? Number(optionString(options, "timeout")) : void 0
16169
+ ),
16170
+ strict: runProfileStrictOption(options),
16171
+ sync: options.sync === true ? true : void 0
16172
+ });
16173
+ } catch (error) {
16174
+ return createRiddleProofProfileEnvironmentBlockedResult({ profile, runner, error });
16175
+ }
16176
+ jobId = typeof created.job_id === "string" ? created.job_id : typeof created.id === "string" ? created.id : "";
16177
+ if (!jobId) {
16178
+ const directResult = extractRiddleProofProfileResult(created);
16179
+ return directResult ? withRiddleMetadata(directResult, { artifacts: collectRiddleProfileArtifactRefs(created) }) : createRiddleProofProfileInsufficientResult({ profile, runner, error: "Riddle run response was missing job_id.", artifacts: collectRiddleProfileArtifactRefs(created) });
16180
+ }
16181
+ poll = await client.pollJob(jobId, pollOptions);
16182
+ if (attempt < retryLimit && shouldRetryUnsubmittedRiddleJob(poll)) {
16183
+ staleJobIds.push(jobId);
16184
+ if (options.quiet !== true) {
16185
+ process.stderr.write(`[riddle-poll] ${jobId} stayed unsubmitted for ${formatPollDuration(poll.poll?.pre_submission_elapsed_ms)}; retrying hosted run ${attempt + 1}/${retryLimit}
16186
+ `);
16187
+ }
16188
+ continue;
16189
+ }
16190
+ break;
15987
16191
  }
15988
- const jobId = typeof created.job_id === "string" ? created.job_id : typeof created.id === "string" ? created.id : "";
15989
- if (!jobId) {
15990
- const directResult = extractRiddleProofProfileResult(created);
15991
- return directResult ? withRiddleMetadata(directResult, { artifacts: collectRiddleProfileArtifactRefs(created) }) : createRiddleProofProfileInsufficientResult({ profile, runner, error: "Riddle run response was missing job_id.", artifacts: collectRiddleProfileArtifactRefs(created) });
16192
+ if (!poll) {
16193
+ return createRiddleProofProfileEnvironmentBlockedResult({ profile, runner, error: "Riddle job polling did not produce a result." });
15992
16194
  }
15993
- const poll = await client.pollJob(jobId, {
15994
- wait: true,
15995
- attempts: optionNumber(options, "pollAttempts", "attempts"),
15996
- intervalMs: optionNumber(options, "intervalMs"),
15997
- progressEveryMs: optionNumber(options, "progressEveryMs"),
15998
- onProgress: options.quiet !== true ? (snapshot) => {
15999
- process.stderr.write(`${riddlePollProgressLine(snapshot)}
16000
- `);
16001
- } : void 0
16002
- });
16003
16195
  const artifacts = collectRiddleProfileArtifactRefs(poll.artifacts);
16196
+ const retryCount = staleJobIds.length || void 0;
16004
16197
  if (!poll.ok || !poll.terminal) {
16005
16198
  const recoveredResult = await recoverProfileResultFromRiddleArtifacts(profile, {
16006
16199
  client,
@@ -16008,12 +16201,18 @@ async function runSingleRiddleProfileForCli(profile, options, input) {
16008
16201
  jobId,
16009
16202
  poll
16010
16203
  });
16011
- if (recoveredResult) return recoveredResult;
16204
+ if (recoveredResult) {
16205
+ return withRiddleMetadata(recoveredResult, { retryCount, staleJobIds });
16206
+ }
16012
16207
  return createRiddleProofProfileEnvironmentBlockedResult({
16013
16208
  profile,
16014
16209
  runner,
16015
16210
  error: `Riddle job ${jobId} ended with status ${poll.status || "unknown"}.`,
16016
- riddle: riddleMetadataFromPoll(jobId, poll),
16211
+ riddle: {
16212
+ ...riddleMetadataFromPoll(jobId, poll),
16213
+ retry_count: retryCount,
16214
+ stale_job_ids: staleJobIds.length ? staleJobIds : void 0
16215
+ },
16017
16216
  artifacts
16018
16217
  });
16019
16218
  }
@@ -16031,7 +16230,9 @@ async function runSingleRiddleProfileForCli(profile, options, input) {
16031
16230
  status: poll.status,
16032
16231
  terminal: poll.terminal,
16033
16232
  poll: poll.poll,
16034
- artifacts
16233
+ artifacts,
16234
+ retryCount,
16235
+ staleJobIds
16035
16236
  });
16036
16237
  }
16037
16238
  async function runSplitViewportProfileForCli(profile, options, input) {