@riddledc/riddle-proof 0.8.71 → 0.8.73

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/README.md CHANGED
@@ -226,6 +226,12 @@ split viewport matrix, the preflight estimates the 30-second hosted minimum per
226
226
  viewport and returns an `environment_blocked` result without starting partial
227
227
  jobs when the account balance cannot cover the intended sweep. Use
228
228
  `--balance-preflight=false` to bypass this check.
229
+ Hosted runs also preflight profile artifact requirements before spending a
230
+ browser job. `artifact_manifest` / `artifact-manifest.json` are local runner
231
+ receipts, so a hosted profile that requires them returns `configuration_error`
232
+ with an explanation instead of submitting a job. Hosted profiles should require
233
+ only artifacts the hosted browser run produces: `screenshot`, `console`,
234
+ `dom_summary`, and `proof_json`.
229
235
 
230
236
  ## Regression Packs
231
237
 
@@ -539,6 +545,10 @@ stable enough for Playwright's default click actionability checks. Use `press`
539
545
  with a Playwright key name, such as `Enter`, `Space`, or `ArrowLeft`,
540
546
  when a route's intended browser control is keyboard-driven; omit `selector` for
541
547
  a page-level key press, or provide `selector` to press against a focused element.
548
+ Target-level `wait_for_selector` runs immediately after navigation and before
549
+ `setup_actions`. If setup creates the ready state, for example by seeding
550
+ localStorage and reloading an authenticated fixture, put the readiness wait in
551
+ `setup_actions` after the state change instead.
542
552
  For canvas games that read key state rather than keypress events, add `hold_ms`
543
553
  or `holdMs` to keep the key down before releasing it. When the profile needs
544
554
  to observe or wait on runtime evidence while a key remains held, use paired
@@ -3486,6 +3486,35 @@ function profileStatusFromEvidence(profile, evidence, checks) {
3486
3486
  if (checks.some((check) => check.status === "failed")) return "product_regression";
3487
3487
  return "passed";
3488
3488
  }
3489
+ var RIDDLE_PROOF_HOSTED_PROFILE_ARTIFACTS = [
3490
+ "screenshot",
3491
+ "console",
3492
+ "dom_summary",
3493
+ "proof_json"
3494
+ ];
3495
+ function preflightRiddleProofProfileRunnerArtifacts(profile, runner) {
3496
+ const requested = uniqueNonEmptyStrings(profile.artifacts || []);
3497
+ if (runner !== "riddle") {
3498
+ return {
3499
+ ok: true,
3500
+ runner,
3501
+ requested,
3502
+ local_only: [],
3503
+ hosted_artifacts: [...RIDDLE_PROOF_HOSTED_PROFILE_ARTIFACTS]
3504
+ };
3505
+ }
3506
+ const localOnly = requested.filter(profileArtifactIsHostedLocalOnly);
3507
+ const subject = localOnly.join(", ");
3508
+ const message = localOnly.length ? `${subject} ${localOnly.length === 1 ? "is" : "are"} local-runner output; hosted runs produce proof_json, console, dom_summary, and screenshots. Remove ${localOnly.length === 1 ? "it" : "them"} from profile.artifacts for --runner riddle.` : void 0;
3509
+ return {
3510
+ ok: localOnly.length === 0,
3511
+ runner,
3512
+ requested,
3513
+ local_only: localOnly,
3514
+ hosted_artifacts: [...RIDDLE_PROOF_HOSTED_PROFILE_ARTIFACTS],
3515
+ message
3516
+ };
3517
+ }
3489
3518
  function assessRiddleProofProfileArtifactCompleteness(profile, result, artifacts) {
3490
3519
  const required = profileRequiredArtifactKeys(profile, result);
3491
3520
  const missing = required.filter((key) => !profileArtifactKeyPresent(key, artifacts));
@@ -3550,6 +3579,16 @@ function normalizeProfileArtifactRole(input) {
3550
3579
  if (normalized === "proof" || normalized === "proof_json" || normalized === "proof.json") return "proof.json";
3551
3580
  return normalizeRiddleProfileArtifactName(input.trim()).toLowerCase();
3552
3581
  }
3582
+ function profileArtifactIsHostedLocalOnly(input) {
3583
+ const raw = input.trim().toLowerCase();
3584
+ const normalized = raw.replace(/[\s-]+/g, "_");
3585
+ const role = normalizeProfileArtifactRole(input);
3586
+ return [
3587
+ raw,
3588
+ normalized,
3589
+ role
3590
+ ].some((value) => value === "artifact_manifest" || value === "artifact_manifest.json" || value === "artifact-manifest" || value === "artifact-manifest.json");
3591
+ }
3553
3592
  function profileArtifactKeyPresent(key, artifacts) {
3554
3593
  if (key.startsWith("screenshot:")) {
3555
3594
  const label = key.slice("screenshot:".length);
@@ -3641,19 +3680,32 @@ function profileStatusExitCode(profile, status) {
3641
3680
  if (status === "passed") return 0;
3642
3681
  return profile.failure_policy[status] === "neutral" ? 0 : 1;
3643
3682
  }
3644
- function createRiddleProofProfileConfigurationError(name, error, runner = "riddle") {
3683
+ function createRiddleProofProfileConfigurationError(profileOrName, error, runner = "riddle", options = {}) {
3684
+ const profile = typeof profileOrName === "string" ? void 0 : profileOrName;
3685
+ const name = profile ? profile.name : String(profileOrName);
3645
3686
  const message = error instanceof Error ? error.message : String(error);
3687
+ let requested = "";
3688
+ if (profile) {
3689
+ try {
3690
+ requested = resolveRiddleProofProfileTargetUrl(profile);
3691
+ } catch {
3692
+ requested = "";
3693
+ }
3694
+ }
3646
3695
  return {
3647
3696
  version: RIDDLE_PROOF_PROFILE_RESULT_VERSION,
3648
3697
  profile_name: name,
3649
3698
  runner,
3650
3699
  status: "configuration_error",
3651
- baseline_policy: "invariant_only",
3652
- route: { requested: "", observed: "", matched: false, error: message },
3700
+ baseline_policy: profile?.baseline_policy || "invariant_only",
3701
+ route: { requested, observed: "", matched: false, error: message },
3653
3702
  artifacts: { screenshots: [], proof_json: "proof.json" },
3654
3703
  checks: [],
3655
3704
  summary: `${name} has a profile configuration error.`,
3656
3705
  captured_at: (/* @__PURE__ */ new Date()).toISOString(),
3706
+ metadata: profile?.metadata,
3707
+ warnings: options.warnings?.length ? options.warnings : void 0,
3708
+ configuration_blocker: options.configurationBlocker,
3657
3709
  error: message
3658
3710
  };
3659
3711
  }
@@ -9564,6 +9616,8 @@ export {
9564
9616
  resolveRiddleProofProfileTimeoutSec,
9565
9617
  preflightRiddleProofProfileHttpStatusChecks,
9566
9618
  resolveRiddleProofProfileRouteUrl,
9619
+ RIDDLE_PROOF_HOSTED_PROFILE_ARTIFACTS,
9620
+ preflightRiddleProofProfileRunnerArtifacts,
9567
9621
  assessRiddleProofProfileArtifactCompleteness,
9568
9622
  applyRiddleProofProfileArtifactCompleteness,
9569
9623
  assessRiddleProofProfileEvidence,
@@ -11,23 +11,25 @@ import {
11
11
  } from "./chunk-CWRIXP5H.js";
12
12
  import {
13
13
  suggestRiddleProofProfileChecks
14
- } from "./chunk-5Y4V2IXI.js";
14
+ } from "./chunk-UE4I7RTI.js";
15
15
  import {
16
16
  RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION,
17
17
  applyRiddleProofProfileArtifactCompleteness,
18
18
  assessRiddleProofProfileEvidence,
19
19
  buildRiddleProofProfileScript,
20
20
  collectRiddleProfileArtifactRefs,
21
+ createRiddleProofProfileConfigurationError,
21
22
  createRiddleProofProfileEnvironmentBlockedResult,
22
23
  createRiddleProofProfileInsufficientResult,
23
24
  deriveRiddleProofArtifactBodyAssertions,
24
25
  extractRiddleProofProfileResult,
25
26
  normalizeRiddleProofProfile,
26
27
  preflightRiddleProofProfileHttpStatusChecks,
28
+ preflightRiddleProofProfileRunnerArtifacts,
27
29
  profileStatusExitCode,
28
30
  resolveRiddleProofProfileTargetUrl,
29
31
  resolveRiddleProofProfileTimeoutSec
30
- } from "./chunk-EX7TO4I5.js";
32
+ } from "./chunk-GG2D3MFZ.js";
31
33
  import {
32
34
  createDisabledRiddleProofAgentAdapter,
33
35
  readRiddleProofRunStatus,
@@ -321,6 +323,7 @@ function compactRunProfileResult(result, options) {
321
323
  checks: compactProfileChecks(result),
322
324
  warnings: result.warnings,
323
325
  environment_blocker: result.environment_blocker,
326
+ configuration_blocker: result.configuration_blocker,
324
327
  metadata: result.metadata,
325
328
  riddle: result.riddle,
326
329
  artifacts: result.artifacts,
@@ -1256,15 +1259,83 @@ function profileHttpStatusPreflightSummary(result) {
1256
1259
  return `${lines.join("\n")}
1257
1260
  `;
1258
1261
  }
1262
+ function profilePlainStatusLabel(status) {
1263
+ if (status === "passed") return "passed";
1264
+ if (status === "product_regression") return "product issue";
1265
+ if (status === "proof_insufficient") return "missing evidence";
1266
+ if (status === "environment_blocked") return "environment blocked";
1267
+ if (status === "configuration_error") return "configuration issue";
1268
+ return "needs review";
1269
+ }
1270
+ function profilePlainCheckSummary(result) {
1271
+ const total = result.checks.length;
1272
+ const passed = result.checks.filter((check) => check.status === "passed").length;
1273
+ const failed = result.checks.filter((check) => check.status === "failed").length;
1274
+ const review = result.checks.filter((check) => check.status === "needs_human_review").length;
1275
+ const skipped = result.checks.filter((check) => check.status === "skipped").length;
1276
+ const evidenceViewportNames = (result.evidence?.viewports || []).map((viewport) => cliString(viewport.name)).filter((name) => Boolean(name));
1277
+ const setupViewportNames = evidenceViewportNames.length ? [] : profileSetupSummaryViewports(result).map((viewport) => cliString(viewport.name)).filter((name) => Boolean(name));
1278
+ const viewportNames = evidenceViewportNames.length ? evidenceViewportNames : setupViewportNames;
1279
+ const route = result.route?.requested || result.route?.observed;
1280
+ const countText = total === 1 ? "1 check" : `${total} checks`;
1281
+ const viewportText = viewportNames.length ? ` across ${viewportNames.length} viewport${viewportNames.length === 1 ? "" : "s"} (${viewportNames.join(", ")})` : "";
1282
+ const routeText = route ? ` on ${markdownInlineCode(route, 120)}` : "";
1283
+ const outcomes = [
1284
+ passed ? `${passed} passed` : "",
1285
+ failed ? `${failed} failed` : "",
1286
+ review ? `${review} needs review` : "",
1287
+ skipped ? `${skipped} skipped` : ""
1288
+ ].filter(Boolean).join(", ");
1289
+ if (!total) return route ? `No browser checks were recorded for ${markdownInlineCode(route, 120)}.` : "No browser checks were recorded.";
1290
+ return `${countText}${viewportText}${routeText}; ${outcomes || "no completed checks"}.`;
1291
+ }
1292
+ function profileArtifactRefIsScreenshot(artifact) {
1293
+ const kind = cliString(artifact.kind)?.toLowerCase() || "";
1294
+ const contentType = cliString(artifact.content_type)?.toLowerCase() || "";
1295
+ const text = [artifact.name, artifact.url, artifact.path].map((value) => cliString(value)).filter(Boolean).join(" ");
1296
+ return kind === "screenshot" || contentType.startsWith("image/") || /\.(png|jpe?g|webp)(?:$|[?#])/i.test(text);
1297
+ }
1298
+ function profileArtifactDisplay(artifact) {
1299
+ const name = artifact.name || artifact.kind || "artifact";
1300
+ const location = artifact.url || artifact.path;
1301
+ return location ? `${name}: ${location}` : name;
1302
+ }
1303
+ function profilePlainArtifactSummary(result) {
1304
+ const hostedArtifacts = result.artifacts.riddle_artifacts || [];
1305
+ const hostedScreenshot = hostedArtifacts.find(profileArtifactRefIsScreenshot);
1306
+ if (hostedScreenshot) return `Hosted screenshot ${profileArtifactDisplay(hostedScreenshot)}`;
1307
+ const hostedProof = hostedArtifacts.find((artifact) => {
1308
+ const name = (artifact.name || artifact.url || artifact.path || "").toLowerCase();
1309
+ return name.includes("proof.json");
1310
+ });
1311
+ if (hostedProof) return `Hosted proof JSON ${profileArtifactDisplay(hostedProof)}`;
1312
+ if (result.artifacts.screenshots?.length) return `Screenshot ${markdownInlineCode(result.artifacts.screenshots[0])}`;
1313
+ if (result.artifacts.proof_json) return `Proof JSON ${markdownInlineCode(result.artifacts.proof_json)}`;
1314
+ return "profile-result.json and summary.md";
1315
+ }
1316
+ function profilePlainNextStep(result) {
1317
+ if (result.status === "passed") return "Use this packet as scoped browser evidence, then review the linked artifacts before merge.";
1318
+ if (result.status === "product_regression") return "Fix the failed product check(s), then rerun this profile.";
1319
+ if (result.status === "proof_insufficient") return "Adjust the profile or runner so the required evidence artifacts are produced, then rerun.";
1320
+ if (result.status === "environment_blocked") return "Fix the runner or environment blocker, then rerun.";
1321
+ if (result.status === "configuration_error") return result.error ? `Fix the profile setup: ${result.error}` : "Fix the profile setup, then rerun.";
1322
+ return "Review the artifacts manually, then refine the profile if the verdict should be automated.";
1323
+ }
1259
1324
  function profileResultMarkdown(result) {
1260
1325
  const lines = [
1261
1326
  `# Riddle Proof Profile: ${result.profile_name}`,
1262
1327
  "",
1263
- `Status: ${result.status}`,
1264
- `Runner: ${result.runner}`,
1265
- `Captured: ${result.captured_at}`,
1328
+ `Result: ${profilePlainStatusLabel(result.status)}`,
1329
+ `What was checked: ${profilePlainCheckSummary(result)}`,
1330
+ `Artifact that proves it: ${profilePlainArtifactSummary(result)}`,
1331
+ `What to do next: ${profilePlainNextStep(result)}`,
1266
1332
  "",
1267
- result.summary,
1333
+ "## Details",
1334
+ "",
1335
+ `- Status: ${result.status}`,
1336
+ `- Runner: ${result.runner}`,
1337
+ `- Captured: ${result.captured_at}`,
1338
+ `- Summary: ${result.summary}`,
1268
1339
  ""
1269
1340
  ];
1270
1341
  if (Array.isArray(result.warnings) && result.warnings.length) {
@@ -1316,6 +1387,10 @@ function profileResultMarkdown(result) {
1316
1387
  if (httpStatusSummaryLines.length) {
1317
1388
  lines.push("", "## HTTP Status", "", ...httpStatusSummaryLines);
1318
1389
  }
1390
+ const configurationBlockerLines = profileConfigurationBlockerMarkdown(result);
1391
+ if (configurationBlockerLines.length) {
1392
+ lines.push("", "## Configuration Blocker", "", ...configurationBlockerLines);
1393
+ }
1319
1394
  const environmentBlockerLines = profileEnvironmentBlockerMarkdown(result);
1320
1395
  if (environmentBlockerLines.length) {
1321
1396
  lines.push("", "## Environment Blocker", "", ...environmentBlockerLines);
@@ -3166,7 +3241,26 @@ function profileEnvironmentBlockerMarkdown(result) {
3166
3241
  if (apiKeySource) lines.push(`- auth: ${apiKeySource}${apiKeyFile ? ` ${apiKeyFile}` : ""}`);
3167
3242
  return lines;
3168
3243
  }
3244
+ function profileConfigurationBlockerMarkdown(result) {
3245
+ const blocker = cliRecord(result.configuration_blocker);
3246
+ if (!blocker) return [];
3247
+ const lines = [];
3248
+ const reason = cliString(blocker.reason);
3249
+ const source = cliString(blocker.source);
3250
+ const requestedArtifacts = cliStringArray(blocker.requested_artifacts);
3251
+ const localOnlyArtifacts = cliStringArray(blocker.local_only_artifacts);
3252
+ const hostedArtifacts = cliStringArray(blocker.hosted_artifacts);
3253
+ if (reason) lines.push(`- reason: ${reason}`);
3254
+ if (source) lines.push(`- source: ${source}`);
3255
+ if (localOnlyArtifacts.length) lines.push(`- local-only artifact(s): ${localOnlyArtifacts.map((value) => markdownInlineCode(value)).join(", ")}`);
3256
+ if (hostedArtifacts.length) lines.push(`- hosted artifact(s): ${hostedArtifacts.map((value) => markdownInlineCode(value)).join(", ")}`);
3257
+ if (requestedArtifacts.length) lines.push(`- requested artifact(s): ${requestedArtifacts.map((value) => markdownInlineCode(value)).join(", ")}`);
3258
+ return lines;
3259
+ }
3169
3260
  function profileCliDiagnosticLine(result) {
3261
+ if (result.status === "configuration_error") {
3262
+ return result.error ? `[riddle-profile] configuration_error: ${result.error}` : void 0;
3263
+ }
3170
3264
  if (result.status !== "environment_blocked") return void 0;
3171
3265
  const blocker = cliRecord(result.environment_blocker);
3172
3266
  if (blocker?.reason === "insufficient_balance") {
@@ -4635,6 +4729,20 @@ async function runProfileForCli(profile, options) {
4635
4729
  if (runner !== "riddle") {
4636
4730
  throw new Error(`Unsupported --runner ${runner}. The current CLI supports --runner riddle.`);
4637
4731
  }
4732
+ const artifactPreflight = preflightRiddleProofProfileRunnerArtifacts(profile, runner);
4733
+ if (!artifactPreflight.ok) {
4734
+ const message = artifactPreflight.message || "Profile artifacts are not supported by the selected runner.";
4735
+ return createRiddleProofProfileConfigurationError(profile, message, runner, {
4736
+ warnings: [message],
4737
+ configurationBlocker: {
4738
+ source: "profile_artifacts",
4739
+ reason: "local_only_artifact_requested",
4740
+ requested_artifacts: artifactPreflight.requested,
4741
+ local_only_artifacts: artifactPreflight.local_only,
4742
+ hosted_artifacts: artifactPreflight.hosted_artifacts
4743
+ }
4744
+ });
4745
+ }
4638
4746
  const client = createRiddleApiClient(riddleClientConfig(options));
4639
4747
  const balanceBlocked = await preflightRiddleProfileBalanceForCli(profile, options, { client, runner });
4640
4748
  if (balanceBlocked) return balanceBlocked;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  RIDDLE_PROOF_PROFILE_VERSION
3
- } from "./chunk-EX7TO4I5.js";
3
+ } from "./chunk-GG2D3MFZ.js";
4
4
 
5
5
  // src/profile-suggestions.ts
6
6
  var RIDDLE_PROOF_PROFILE_SUGGESTIONS_VERSION = "riddle-proof.profile-suggestions.v1";
package/dist/cli/index.js CHANGED
@@ -1,8 +1,8 @@
1
- import "../chunk-RJVA5KKM.js";
1
+ import "../chunk-ICIJTEHD.js";
2
2
  import "../chunk-B2DP2LET.js";
3
3
  import "../chunk-CWRIXP5H.js";
4
- import "../chunk-5Y4V2IXI.js";
5
- import "../chunk-EX7TO4I5.js";
4
+ import "../chunk-UE4I7RTI.js";
5
+ import "../chunk-GG2D3MFZ.js";
6
6
  import "../chunk-WLUMLHII.js";
7
7
  import "../chunk-CGJX7LJO.js";
8
8
  import "../chunk-UTCL7FEZ.js";
package/dist/cli.cjs CHANGED
@@ -11948,6 +11948,35 @@ function profileStatusFromEvidence(profile, evidence, checks) {
11948
11948
  if (checks.some((check) => check.status === "failed")) return "product_regression";
11949
11949
  return "passed";
11950
11950
  }
11951
+ var RIDDLE_PROOF_HOSTED_PROFILE_ARTIFACTS = [
11952
+ "screenshot",
11953
+ "console",
11954
+ "dom_summary",
11955
+ "proof_json"
11956
+ ];
11957
+ function preflightRiddleProofProfileRunnerArtifacts(profile, runner) {
11958
+ const requested = uniqueNonEmptyStrings(profile.artifacts || []);
11959
+ if (runner !== "riddle") {
11960
+ return {
11961
+ ok: true,
11962
+ runner,
11963
+ requested,
11964
+ local_only: [],
11965
+ hosted_artifacts: [...RIDDLE_PROOF_HOSTED_PROFILE_ARTIFACTS]
11966
+ };
11967
+ }
11968
+ const localOnly = requested.filter(profileArtifactIsHostedLocalOnly);
11969
+ const subject = localOnly.join(", ");
11970
+ const message = localOnly.length ? `${subject} ${localOnly.length === 1 ? "is" : "are"} local-runner output; hosted runs produce proof_json, console, dom_summary, and screenshots. Remove ${localOnly.length === 1 ? "it" : "them"} from profile.artifacts for --runner riddle.` : void 0;
11971
+ return {
11972
+ ok: localOnly.length === 0,
11973
+ runner,
11974
+ requested,
11975
+ local_only: localOnly,
11976
+ hosted_artifacts: [...RIDDLE_PROOF_HOSTED_PROFILE_ARTIFACTS],
11977
+ message
11978
+ };
11979
+ }
11951
11980
  function assessRiddleProofProfileArtifactCompleteness(profile, result, artifacts) {
11952
11981
  const required = profileRequiredArtifactKeys(profile, result);
11953
11982
  const missing = required.filter((key) => !profileArtifactKeyPresent(key, artifacts));
@@ -12012,6 +12041,16 @@ function normalizeProfileArtifactRole(input) {
12012
12041
  if (normalized === "proof" || normalized === "proof_json" || normalized === "proof.json") return "proof.json";
12013
12042
  return normalizeRiddleProfileArtifactName(input.trim()).toLowerCase();
12014
12043
  }
12044
+ function profileArtifactIsHostedLocalOnly(input) {
12045
+ const raw = input.trim().toLowerCase();
12046
+ const normalized = raw.replace(/[\s-]+/g, "_");
12047
+ const role = normalizeProfileArtifactRole(input);
12048
+ return [
12049
+ raw,
12050
+ normalized,
12051
+ role
12052
+ ].some((value) => value === "artifact_manifest" || value === "artifact_manifest.json" || value === "artifact-manifest" || value === "artifact-manifest.json");
12053
+ }
12015
12054
  function profileArtifactKeyPresent(key, artifacts) {
12016
12055
  if (key.startsWith("screenshot:")) {
12017
12056
  const label = key.slice("screenshot:".length);
@@ -12103,6 +12142,35 @@ function profileStatusExitCode(profile, status) {
12103
12142
  if (status === "passed") return 0;
12104
12143
  return profile.failure_policy[status] === "neutral" ? 0 : 1;
12105
12144
  }
12145
+ function createRiddleProofProfileConfigurationError(profileOrName, error, runner = "riddle", options = {}) {
12146
+ const profile = typeof profileOrName === "string" ? void 0 : profileOrName;
12147
+ const name = profile ? profile.name : String(profileOrName);
12148
+ const message = error instanceof Error ? error.message : String(error);
12149
+ let requested = "";
12150
+ if (profile) {
12151
+ try {
12152
+ requested = resolveRiddleProofProfileTargetUrl(profile);
12153
+ } catch {
12154
+ requested = "";
12155
+ }
12156
+ }
12157
+ return {
12158
+ version: RIDDLE_PROOF_PROFILE_RESULT_VERSION,
12159
+ profile_name: name,
12160
+ runner,
12161
+ status: "configuration_error",
12162
+ baseline_policy: profile?.baseline_policy || "invariant_only",
12163
+ route: { requested, observed: "", matched: false, error: message },
12164
+ artifacts: { screenshots: [], proof_json: "proof.json" },
12165
+ checks: [],
12166
+ summary: `${name} has a profile configuration error.`,
12167
+ captured_at: (/* @__PURE__ */ new Date()).toISOString(),
12168
+ metadata: profile?.metadata,
12169
+ warnings: options.warnings?.length ? options.warnings : void 0,
12170
+ configuration_blocker: options.configurationBlocker,
12171
+ error: message
12172
+ };
12173
+ }
12106
12174
  function createRiddleProofProfileEnvironmentBlockedResult(input) {
12107
12175
  const message = input.error instanceof Error ? input.error.message : input.error ? String(input.error) : "Riddle runner did not complete successfully.";
12108
12176
  const environmentBlocker = input.environmentBlocker || extractRiddleRunnerBlocker(message);
@@ -18817,6 +18885,7 @@ function compactRunProfileResult(result, options) {
18817
18885
  checks: compactProfileChecks(result),
18818
18886
  warnings: result.warnings,
18819
18887
  environment_blocker: result.environment_blocker,
18888
+ configuration_blocker: result.configuration_blocker,
18820
18889
  metadata: result.metadata,
18821
18890
  riddle: result.riddle,
18822
18891
  artifacts: result.artifacts,
@@ -19752,15 +19821,83 @@ function profileHttpStatusPreflightSummary(result) {
19752
19821
  return `${lines.join("\n")}
19753
19822
  `;
19754
19823
  }
19824
+ function profilePlainStatusLabel(status) {
19825
+ if (status === "passed") return "passed";
19826
+ if (status === "product_regression") return "product issue";
19827
+ if (status === "proof_insufficient") return "missing evidence";
19828
+ if (status === "environment_blocked") return "environment blocked";
19829
+ if (status === "configuration_error") return "configuration issue";
19830
+ return "needs review";
19831
+ }
19832
+ function profilePlainCheckSummary(result) {
19833
+ const total = result.checks.length;
19834
+ const passed = result.checks.filter((check) => check.status === "passed").length;
19835
+ const failed = result.checks.filter((check) => check.status === "failed").length;
19836
+ const review = result.checks.filter((check) => check.status === "needs_human_review").length;
19837
+ const skipped = result.checks.filter((check) => check.status === "skipped").length;
19838
+ const evidenceViewportNames = (result.evidence?.viewports || []).map((viewport) => cliString(viewport.name)).filter((name) => Boolean(name));
19839
+ const setupViewportNames = evidenceViewportNames.length ? [] : profileSetupSummaryViewports(result).map((viewport) => cliString(viewport.name)).filter((name) => Boolean(name));
19840
+ const viewportNames = evidenceViewportNames.length ? evidenceViewportNames : setupViewportNames;
19841
+ const route = result.route?.requested || result.route?.observed;
19842
+ const countText = total === 1 ? "1 check" : `${total} checks`;
19843
+ const viewportText = viewportNames.length ? ` across ${viewportNames.length} viewport${viewportNames.length === 1 ? "" : "s"} (${viewportNames.join(", ")})` : "";
19844
+ const routeText = route ? ` on ${markdownInlineCode(route, 120)}` : "";
19845
+ const outcomes = [
19846
+ passed ? `${passed} passed` : "",
19847
+ failed ? `${failed} failed` : "",
19848
+ review ? `${review} needs review` : "",
19849
+ skipped ? `${skipped} skipped` : ""
19850
+ ].filter(Boolean).join(", ");
19851
+ if (!total) return route ? `No browser checks were recorded for ${markdownInlineCode(route, 120)}.` : "No browser checks were recorded.";
19852
+ return `${countText}${viewportText}${routeText}; ${outcomes || "no completed checks"}.`;
19853
+ }
19854
+ function profileArtifactRefIsScreenshot2(artifact) {
19855
+ const kind = cliString(artifact.kind)?.toLowerCase() || "";
19856
+ const contentType = cliString(artifact.content_type)?.toLowerCase() || "";
19857
+ const text = [artifact.name, artifact.url, artifact.path].map((value) => cliString(value)).filter(Boolean).join(" ");
19858
+ return kind === "screenshot" || contentType.startsWith("image/") || /\.(png|jpe?g|webp)(?:$|[?#])/i.test(text);
19859
+ }
19860
+ function profileArtifactDisplay(artifact) {
19861
+ const name = artifact.name || artifact.kind || "artifact";
19862
+ const location = artifact.url || artifact.path;
19863
+ return location ? `${name}: ${location}` : name;
19864
+ }
19865
+ function profilePlainArtifactSummary(result) {
19866
+ const hostedArtifacts = result.artifacts.riddle_artifacts || [];
19867
+ const hostedScreenshot = hostedArtifacts.find(profileArtifactRefIsScreenshot2);
19868
+ if (hostedScreenshot) return `Hosted screenshot ${profileArtifactDisplay(hostedScreenshot)}`;
19869
+ const hostedProof = hostedArtifacts.find((artifact) => {
19870
+ const name = (artifact.name || artifact.url || artifact.path || "").toLowerCase();
19871
+ return name.includes("proof.json");
19872
+ });
19873
+ if (hostedProof) return `Hosted proof JSON ${profileArtifactDisplay(hostedProof)}`;
19874
+ if (result.artifacts.screenshots?.length) return `Screenshot ${markdownInlineCode(result.artifacts.screenshots[0])}`;
19875
+ if (result.artifacts.proof_json) return `Proof JSON ${markdownInlineCode(result.artifacts.proof_json)}`;
19876
+ return "profile-result.json and summary.md";
19877
+ }
19878
+ function profilePlainNextStep(result) {
19879
+ if (result.status === "passed") return "Use this packet as scoped browser evidence, then review the linked artifacts before merge.";
19880
+ if (result.status === "product_regression") return "Fix the failed product check(s), then rerun this profile.";
19881
+ if (result.status === "proof_insufficient") return "Adjust the profile or runner so the required evidence artifacts are produced, then rerun.";
19882
+ if (result.status === "environment_blocked") return "Fix the runner or environment blocker, then rerun.";
19883
+ if (result.status === "configuration_error") return result.error ? `Fix the profile setup: ${result.error}` : "Fix the profile setup, then rerun.";
19884
+ return "Review the artifacts manually, then refine the profile if the verdict should be automated.";
19885
+ }
19755
19886
  function profileResultMarkdown(result) {
19756
19887
  const lines = [
19757
19888
  `# Riddle Proof Profile: ${result.profile_name}`,
19758
19889
  "",
19759
- `Status: ${result.status}`,
19760
- `Runner: ${result.runner}`,
19761
- `Captured: ${result.captured_at}`,
19890
+ `Result: ${profilePlainStatusLabel(result.status)}`,
19891
+ `What was checked: ${profilePlainCheckSummary(result)}`,
19892
+ `Artifact that proves it: ${profilePlainArtifactSummary(result)}`,
19893
+ `What to do next: ${profilePlainNextStep(result)}`,
19762
19894
  "",
19763
- result.summary,
19895
+ "## Details",
19896
+ "",
19897
+ `- Status: ${result.status}`,
19898
+ `- Runner: ${result.runner}`,
19899
+ `- Captured: ${result.captured_at}`,
19900
+ `- Summary: ${result.summary}`,
19764
19901
  ""
19765
19902
  ];
19766
19903
  if (Array.isArray(result.warnings) && result.warnings.length) {
@@ -19812,6 +19949,10 @@ function profileResultMarkdown(result) {
19812
19949
  if (httpStatusSummaryLines.length) {
19813
19950
  lines.push("", "## HTTP Status", "", ...httpStatusSummaryLines);
19814
19951
  }
19952
+ const configurationBlockerLines = profileConfigurationBlockerMarkdown(result);
19953
+ if (configurationBlockerLines.length) {
19954
+ lines.push("", "## Configuration Blocker", "", ...configurationBlockerLines);
19955
+ }
19815
19956
  const environmentBlockerLines = profileEnvironmentBlockerMarkdown(result);
19816
19957
  if (environmentBlockerLines.length) {
19817
19958
  lines.push("", "## Environment Blocker", "", ...environmentBlockerLines);
@@ -21662,7 +21803,26 @@ function profileEnvironmentBlockerMarkdown(result) {
21662
21803
  if (apiKeySource) lines.push(`- auth: ${apiKeySource}${apiKeyFile ? ` ${apiKeyFile}` : ""}`);
21663
21804
  return lines;
21664
21805
  }
21806
+ function profileConfigurationBlockerMarkdown(result) {
21807
+ const blocker = cliRecord(result.configuration_blocker);
21808
+ if (!blocker) return [];
21809
+ const lines = [];
21810
+ const reason = cliString(blocker.reason);
21811
+ const source = cliString(blocker.source);
21812
+ const requestedArtifacts = cliStringArray(blocker.requested_artifacts);
21813
+ const localOnlyArtifacts = cliStringArray(blocker.local_only_artifacts);
21814
+ const hostedArtifacts = cliStringArray(blocker.hosted_artifacts);
21815
+ if (reason) lines.push(`- reason: ${reason}`);
21816
+ if (source) lines.push(`- source: ${source}`);
21817
+ if (localOnlyArtifacts.length) lines.push(`- local-only artifact(s): ${localOnlyArtifacts.map((value) => markdownInlineCode(value)).join(", ")}`);
21818
+ if (hostedArtifacts.length) lines.push(`- hosted artifact(s): ${hostedArtifacts.map((value) => markdownInlineCode(value)).join(", ")}`);
21819
+ if (requestedArtifacts.length) lines.push(`- requested artifact(s): ${requestedArtifacts.map((value) => markdownInlineCode(value)).join(", ")}`);
21820
+ return lines;
21821
+ }
21665
21822
  function profileCliDiagnosticLine(result) {
21823
+ if (result.status === "configuration_error") {
21824
+ return result.error ? `[riddle-profile] configuration_error: ${result.error}` : void 0;
21825
+ }
21666
21826
  if (result.status !== "environment_blocked") return void 0;
21667
21827
  const blocker = cliRecord(result.environment_blocker);
21668
21828
  if (blocker?.reason === "insufficient_balance") {
@@ -23131,6 +23291,20 @@ async function runProfileForCli(profile, options) {
23131
23291
  if (runner !== "riddle") {
23132
23292
  throw new Error(`Unsupported --runner ${runner}. The current CLI supports --runner riddle.`);
23133
23293
  }
23294
+ const artifactPreflight = preflightRiddleProofProfileRunnerArtifacts(profile, runner);
23295
+ if (!artifactPreflight.ok) {
23296
+ const message = artifactPreflight.message || "Profile artifacts are not supported by the selected runner.";
23297
+ return createRiddleProofProfileConfigurationError(profile, message, runner, {
23298
+ warnings: [message],
23299
+ configurationBlocker: {
23300
+ source: "profile_artifacts",
23301
+ reason: "local_only_artifact_requested",
23302
+ requested_artifacts: artifactPreflight.requested,
23303
+ local_only_artifacts: artifactPreflight.local_only,
23304
+ hosted_artifacts: artifactPreflight.hosted_artifacts
23305
+ }
23306
+ });
23307
+ }
23134
23308
  const client = createRiddleApiClient(riddleClientConfig(options));
23135
23309
  const balanceBlocked = await preflightRiddleProfileBalanceForCli(profile, options, { client, runner });
23136
23310
  if (balanceBlocked) return balanceBlocked;
package/dist/cli.js CHANGED
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
- import "./chunk-RJVA5KKM.js";
2
+ import "./chunk-ICIJTEHD.js";
3
3
  import "./chunk-B2DP2LET.js";
4
4
  import "./chunk-CWRIXP5H.js";
5
- import "./chunk-5Y4V2IXI.js";
6
- import "./chunk-EX7TO4I5.js";
5
+ import "./chunk-UE4I7RTI.js";
6
+ import "./chunk-GG2D3MFZ.js";
7
7
  import "./chunk-WLUMLHII.js";
8
8
  import "./chunk-CGJX7LJO.js";
9
9
  import "./chunk-UTCL7FEZ.js";