@riddledc/riddle-proof 0.7.183 → 0.7.184

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.js CHANGED
@@ -13,7 +13,7 @@ import {
13
13
  profileStatusExitCode,
14
14
  resolveRiddleProofProfileTargetUrl,
15
15
  resolveRiddleProofProfileTimeoutSec
16
- } from "./chunk-X24EJSIU.js";
16
+ } from "./chunk-5MBIRRA7.js";
17
17
  import {
18
18
  createRiddleApiClient,
19
19
  isTerminalRiddleJobStatus,
@@ -396,6 +396,10 @@ function profileResultMarkdown(result) {
396
396
  if (result.warnings.length > 12) lines.push(`- ${result.warnings.length - 12} additional warning(s) omitted.`);
397
397
  lines.push("");
398
398
  }
399
+ const packMetadataLines = profilePackMetadataMarkdown(result);
400
+ if (packMetadataLines.length) {
401
+ lines.push("## Proof Pack", "", ...packMetadataLines, "");
402
+ }
399
403
  lines.push("## Checks", "");
400
404
  for (const check of result.checks) {
401
405
  lines.push(`- ${check.status}: ${profileCheckMarkdownLabel(check)}`);
@@ -405,6 +409,18 @@ function profileResultMarkdown(result) {
405
409
  if (setupSummaryLines.length) {
406
410
  lines.push("", "## Setup Summary", "", ...setupSummaryLines);
407
411
  }
412
+ const reachabilitySummaryLines = profileReachabilitySummaryMarkdown(result);
413
+ if (reachabilitySummaryLines.length) {
414
+ lines.push("", "## Reachability", "", ...reachabilitySummaryLines);
415
+ }
416
+ const stateContractSummaryLines = profileStateContractSummaryMarkdown(result);
417
+ if (stateContractSummaryLines.length) {
418
+ lines.push("", "## State Contract", "", ...stateContractSummaryLines);
419
+ }
420
+ const sideCaveatSummaryLines = profileSideCaveatSummaryMarkdown(result);
421
+ if (sideCaveatSummaryLines.length) {
422
+ lines.push("", "## Side Caveats", "", ...sideCaveatSummaryLines);
423
+ }
408
424
  const networkMockSummaryLines = profileNetworkMockSummaryMarkdown(result);
409
425
  if (networkMockSummaryLines.length) {
410
426
  lines.push("", "## Network Mocks", "", ...networkMockSummaryLines);
@@ -503,6 +519,222 @@ function profileRiddleJobMarkdown(result) {
503
519
  if (splitJobs.length > 12) lines.push(`- ${splitJobs.length - 12} additional split job(s) omitted.`);
504
520
  return lines;
505
521
  }
522
+ function profileMetadataStringArray(value) {
523
+ return Array.isArray(value) ? value.map((item) => typeof item === "string" ? item.trim() : "").filter((item) => Boolean(item)) : [];
524
+ }
525
+ function profileSetupSummaryRecord(result) {
526
+ const setupCheck = result.checks.find((check) => check.type === "setup_actions_succeeded");
527
+ return cliRecord(setupCheck?.evidence?.setup_summary);
528
+ }
529
+ function profileSetupSummaryViewports(result) {
530
+ const setupSummary = profileSetupSummaryRecord(result);
531
+ return Array.isArray(setupSummary?.viewports) ? setupSummary.viewports.map(cliRecord).filter((viewport) => Boolean(viewport)) : [];
532
+ }
533
+ function profileHasPassedCheck(result, types) {
534
+ return result.checks.some((check) => types.includes(check.type) && check.status === "passed");
535
+ }
536
+ function profileHasCheck(result, types) {
537
+ return result.checks.some((check) => types.includes(check.type));
538
+ }
539
+ function profileSetupScreenshotCount(viewports) {
540
+ return viewports.reduce((sum, viewport) => {
541
+ const setupScreenshots = Array.isArray(viewport.setup_screenshots) ? viewport.setup_screenshots.filter((label) => typeof label === "string" && label.trim()).length : 0;
542
+ const finalScreenshot = cliString(viewport.final_screenshot) || cliString(viewport.screenshot_label) ? 1 : 0;
543
+ return sum + setupScreenshots + finalScreenshot;
544
+ }, 0);
545
+ }
546
+ function profileSetupReceiptTotal(viewports, key) {
547
+ return viewports.reduce((sum, viewport) => sum + setupReceiptArray(viewport, key).filter((receipt) => receipt.ok !== false).length, 0);
548
+ }
549
+ function profileSetupFailureCount(viewports) {
550
+ return viewports.reduce((sum, viewport) => {
551
+ const failed = Array.isArray(viewport.failed) ? viewport.failed : [];
552
+ return sum + failed.filter((failure) => Boolean(cliRecord(failure))).length;
553
+ }, 0);
554
+ }
555
+ function profileSetupObstructionCount(viewports) {
556
+ return viewports.reduce((sum, viewport) => {
557
+ const failed = Array.isArray(viewport.failed) ? viewport.failed.map(cliRecord).filter((failure) => Boolean(failure)) : [];
558
+ return sum + failed.filter((failure) => Boolean(setupFailureObstructionSnippet(cliString(failure.reason)))).length;
559
+ }, 0);
560
+ }
561
+ function profileResultHasArtifact(result) {
562
+ return Boolean(
563
+ result.artifacts.proof_json || result.artifacts.console || result.artifacts.dom_summary || result.artifacts.screenshots?.length || result.artifacts.riddle_artifacts?.some((artifact) => artifact.url || artifact.path || artifact.name)
564
+ );
565
+ }
566
+ function profileReceiptSignalStatus(hasSignal, presentReason, missingReason) {
567
+ return hasSignal ? { status: "present", reason: presentReason } : { status: "missing", reason: missingReason };
568
+ }
569
+ function profilePackReceiptStatus(result, metadata, receipt) {
570
+ const text = receipt.toLowerCase();
571
+ const setupSummary = profileSetupSummaryRecord(result);
572
+ const setupViewports = profileSetupSummaryViewports(result);
573
+ const evidenceViewports = Array.isArray(result.evidence?.viewports) ? result.evidence.viewports : [];
574
+ const setupResultCount = setupViewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.result_count) || 0), 0);
575
+ const setupScreenshotCount = profileSetupScreenshotCount(setupViewports);
576
+ const screenshotCount = (result.artifacts.screenshots?.length || 0) + evidenceViewports.filter((viewport) => cliString(viewport.screenshot_label)).length + setupScreenshotCount;
577
+ const windowEvalCount = profileSetupReceiptTotal(setupViewports, "window_eval");
578
+ const valueReceipts = [
579
+ ...setupViewports.flatMap((viewport) => setupReceiptArray(viewport, "window_eval")),
580
+ ...setupViewports.flatMap((viewport) => setupReceiptArray(viewport, "window_call"))
581
+ ].filter((item) => item.ok !== false);
582
+ const clickCount = setupViewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.clicked_total) || 0), 0) + profileSetupReceiptTotal(setupViewports, "click") + profileSetupReceiptTotal(setupViewports, "click_count");
583
+ const setupFailureCount = profileSetupFailureCount(setupViewports);
584
+ const setupObstructionCount = profileSetupObstructionCount(setupViewports);
585
+ const inputDispatchCount = profileSetupReceiptTotal(setupViewports, "drag") + profileSetupReceiptTotal(setupViewports, "tap") + profileSetupReceiptTotal(setupViewports, "press") + profileSetupReceiptTotal(setupViewports, "keyboard_sequence");
586
+ const canvasReceipts = setupViewports.flatMap((viewport) => setupReceiptArray(viewport, "canvas_signature"));
587
+ const hasCanvasChange = canvasReceipts.some((item) => item.ok !== false && item.changed === true);
588
+ const canvasSignatureHashes = canvasReceipts.filter((item) => item.ok !== false).map((item) => cliString(item.hash)).filter(Boolean);
589
+ const hasCanvasSignatureChange = hasCanvasChange || new Set(canvasSignatureHashes).size >= 2;
590
+ const hasNaturalInput = setupNaturalInputSummaryMarkdown(setupViewports).length > 0;
591
+ const hasStateContract = profileStateContractSummaryMarkdown(result).length > 0 || Boolean(cliRecord(metadata.declared_state_contract));
592
+ const hasInvalidStateReceipt = valueReceipts.some((item) => {
593
+ const state = setupReturnSummaryValue(item, ["state", "nextState"]);
594
+ return typeof state === "string" && state.toLowerCase().includes("invalid");
595
+ });
596
+ const hasErrorDetailReceipt = valueReceipts.some((item) => setupReturnSummaryValue(item, ["hasErrorDetail", "errorDetail", "error_detail"]) === true);
597
+ const hasGridEvidence = valueReceipts.some((item) => setupReturnSummaryValue(item, ["itemCount", "grid.width", "gridWidth", "visibleGridCount"]) !== void 0);
598
+ const hasVisibleControlReceipt = valueReceipts.some((item) => setupReturnSummaryValue(item, ["visibleButtonCount", "visibleControlCount"]) !== void 0 || setupReturnSummaryValue(item, ["buttonStillVisible", "controlStillVisible"]) === true);
599
+ const hasToolSelectionReceipt = valueReceipts.some((item) => setupReturnSummaryValue(item, ["rectangleChecked", "toolSelected", "toolChecked", "selected"]) === true);
600
+ const hasStateGrowthReceipt = valueReceipts.some((item) => {
601
+ const delta = cliFiniteNumber(setupReturnSummaryValue(item, ["delta", "countDelta", "itemDelta", "stateDelta"]));
602
+ if (delta !== void 0 && delta > 0) return true;
603
+ const before = cliFiniteNumber(setupReturnSummaryValue(item, ["before", "beforeCount", "previousCount"]));
604
+ const after = cliFiniteNumber(setupReturnSummaryValue(item, ["after", "afterCount", "itemCount", "count"]));
605
+ return before !== void 0 && after !== void 0 && after > before;
606
+ });
607
+ const hasReachability = profileReachabilitySummaryMarkdown(result).length > 0 || result.checks.some((check) => check.type === "selector_visible" && Boolean(cliRecord(check.evidence)?.selector));
608
+ const hasOverflowEvidence = result.checks.some((check) => check.type === "no_horizontal_overflow" || check.type === "no_mobile_horizontal_overflow" || check.type === "frame_no_horizontal_overflow") || evidenceViewports.some((viewport) => (cliFiniteNumber(viewport.overflow_px) || 0) > 0 || (cliFiniteNumber(viewport.bounds_overflow_px) || 0) > 0 || Boolean(viewport.overflow_offenders?.length));
609
+ const hasConsoleAccounting = profileHasCheck(result, ["no_console_warnings", "no_fatal_console_errors"]) || Boolean(result.evidence?.console || result.evidence?.page_errors);
610
+ const hasDomSummary = Boolean(result.artifacts.dom_summary || result.evidence?.dom_summary);
611
+ const hasProofJson = Boolean(result.artifacts.proof_json || result.version === "riddle-proof.profile-result.v1");
612
+ const hasRouteViewport = Boolean(result.route?.requested || result.route?.observed) && Boolean(evidenceViewports.length || result.route?.matched !== void 0);
613
+ const hasSetupReceipts = setupResultCount > 0 || Boolean(setupSummary);
614
+ const hasTextVisibility = profileHasPassedCheck(result, ["text_visible", "selector_text_visible", "selector_visible"]);
615
+ const hasTextAbsence = profileHasPassedCheck(result, ["text_absent", "selector_text_absent"]);
616
+ const hasMeasuredStateChange = hasNaturalInput || hasCanvasChange || valueReceipts.some((item) => setupReturnSummaryValue(item, ["changed"]) === true || setupReturnSummaryValue(item, ["nonWhiteDelta", "darkDelta", "pixelDelta", "movementDelta"]) !== void 0);
617
+ if (text.includes("artifact link") || text.includes("artifact path")) {
618
+ return profileReceiptSignalStatus(profileResultHasArtifact(result), "artifact references listed", "no artifact references found");
619
+ }
620
+ if (text.includes("proof json")) return profileReceiptSignalStatus(hasProofJson, "proof JSON artifact named", "proof JSON artifact missing");
621
+ if (text.includes("dom summary")) return profileReceiptSignalStatus(hasDomSummary, "DOM summary evidence present", "DOM summary evidence missing");
622
+ if (text.includes("console") || text.includes("warning") || text.includes("fatal") || text.includes("browser warning") || text.includes("graphics")) {
623
+ return profileReceiptSignalStatus(hasConsoleAccounting, "console checks or evidence present", "console accounting evidence missing");
624
+ }
625
+ if (text.includes("route") && text.includes("viewport")) {
626
+ return profileReceiptSignalStatus(hasRouteViewport, "route and viewport evidence present", "route or viewport evidence missing");
627
+ }
628
+ if (text.includes("setup action")) {
629
+ return profileReceiptSignalStatus(hasSetupReceipts, "setup receipts present", "setup receipts missing");
630
+ }
631
+ if (text.includes("declared state contract")) {
632
+ return profileReceiptSignalStatus(hasStateContract, "state contract metadata or receipts present", "state contract evidence missing");
633
+ }
634
+ if (text.includes("stale") || text.includes("absence")) {
635
+ return profileReceiptSignalStatus(hasTextAbsence, "absence check passed", "absence check missing");
636
+ }
637
+ if (text.includes("recovered") || text.includes("final state")) {
638
+ return profileReceiptSignalStatus(hasStateContract || hasTextVisibility, "final state receipt present", "final state receipt missing");
639
+ }
640
+ if (text.includes("error detail")) {
641
+ const hasRequiredState = !text.includes("invalid") || hasInvalidStateReceipt;
642
+ return profileReceiptSignalStatus(
643
+ hasRequiredState && hasErrorDetailReceipt,
644
+ "error-detail state receipt present",
645
+ "error-detail state receipt missing"
646
+ );
647
+ }
648
+ if (text.includes("invalid state")) {
649
+ return profileReceiptSignalStatus(hasStateContract || hasInvalidStateReceipt, "invalid-state receipt present", "invalid-state receipt missing");
650
+ }
651
+ if (text.includes("retry") || text.includes("repair") || text.includes("reset") || text.includes("affordance")) {
652
+ return profileReceiptSignalStatus(hasStateContract || clickCount > 0, "affordance or transition receipt present", "affordance receipt missing");
653
+ }
654
+ if (text.includes("failure") || text.includes("mutation")) {
655
+ return profileReceiptSignalStatus(hasStateContract || windowEvalCount > 0 || clickCount > 0, "failure or mutation receipt present", "failure or mutation receipt missing");
656
+ }
657
+ if (text.includes("initial") && (text.includes("visible") || text.includes("state"))) {
658
+ return profileReceiptSignalStatus(hasTextVisibility || screenshotCount > 0, "initial visible-state evidence present", "initial state evidence missing");
659
+ }
660
+ if (text.includes("state-growth") || text.includes("state growth") || text.includes("growth receipt") || text.includes("grid grows") || text.includes("state") && text.includes("after the click")) {
661
+ return profileReceiptSignalStatus(hasStateGrowthReceipt, "state-growth receipt present", "state-growth receipt missing");
662
+ }
663
+ if (text.includes("visible grid") || text.includes("control evidence") || text.includes("grid") && text.includes("control")) {
664
+ return profileReceiptSignalStatus(
665
+ hasGridEvidence && (hasVisibleControlReceipt || hasReachability),
666
+ "visible grid/control evidence present",
667
+ "visible grid/control evidence missing"
668
+ );
669
+ }
670
+ if (text.includes("tool") && text.includes("selected") || text.includes("rectangle tool")) {
671
+ return profileReceiptSignalStatus(hasToolSelectionReceipt, "tool-selection receipt present", "tool-selection receipt missing");
672
+ }
673
+ if (text.includes("canvas signature")) {
674
+ return profileReceiptSignalStatus(hasCanvasSignatureChange, "canvas signature change evidence present", "canvas signature evidence missing");
675
+ }
676
+ if (text.includes("selector count") || text.includes("visible count") || text.includes("control visibility") || text.includes("reachability gate") || text.includes("visible control")) {
677
+ return profileReceiptSignalStatus(hasReachability, "selector visibility or reachability evidence present", "reachability evidence missing");
678
+ }
679
+ if (text.includes("overflow") || text.includes("clipped") || text.includes("fit")) {
680
+ return profileReceiptSignalStatus(hasOverflowEvidence, "overflow evidence present", "overflow evidence missing");
681
+ }
682
+ if (text.includes("click receipt") || text.includes("obstruction receipt") || text.includes("state mutation")) {
683
+ return profileReceiptSignalStatus(clickCount > 0 || setupObstructionCount > 0, "click or obstruction receipt present", "click or obstruction receipt missing");
684
+ }
685
+ if (text.includes("target selector") || text.includes("target selector/text")) {
686
+ return profileReceiptSignalStatus(hasReachability || hasTextVisibility, "selector or text check evidence present", "selector/text evidence missing");
687
+ }
688
+ if (text.includes("intercepting element")) {
689
+ if (setupObstructionCount > 0) return { status: "present", reason: "obstruction receipt present" };
690
+ return setupFailureCount > 0 ? { status: "missing", reason: "setup failed without intercepting element evidence" } : { status: "manual", reason: "only applies when blocked" };
691
+ }
692
+ if (text.includes("before and after state")) {
693
+ return profileReceiptSignalStatus(
694
+ hasStateContract || valueReceipts.length >= 2 || screenshotCount >= 2,
695
+ "before/after state evidence present",
696
+ "before/after state evidence missing"
697
+ );
698
+ }
699
+ if (text.includes("screenshot")) {
700
+ const needsBoundaryScreenshots = text.includes("each") || text.includes("before and after") || text.includes("state boundary");
701
+ return profileReceiptSignalStatus(
702
+ needsBoundaryScreenshots ? screenshotCount >= 2 : screenshotCount > 0,
703
+ needsBoundaryScreenshots ? "multiple screenshots present" : "screenshot evidence present",
704
+ needsBoundaryScreenshots ? "multiple screenshots missing" : "screenshot evidence missing"
705
+ );
706
+ }
707
+ if (text.includes("input dispatch") || text.includes("pointer") || text.includes("touch") || text.includes("key event") || text.includes("trusted-event")) {
708
+ return profileReceiptSignalStatus(inputDispatchCount > 0 || hasNaturalInput, "input dispatch evidence present", "input dispatch evidence missing");
709
+ }
710
+ if (text.includes("measured") || text.includes("state-change") || text.includes("pixel delta") || text.includes("movement receipt") || text.includes("canvas hash")) {
711
+ return profileReceiptSignalStatus(hasMeasuredStateChange, "measured-change evidence present", "measured-change evidence missing");
712
+ }
713
+ return { status: "manual", reason: "semantic receipt requires audit review" };
714
+ }
715
+ function profilePackMetadataMarkdown(result) {
716
+ const metadata = cliRecord(result.metadata);
717
+ if (!metadata) return [];
718
+ const packId = cliString(metadata.pack_id);
719
+ const packPublicName = cliString(metadata.pack_public_name);
720
+ const requiredReceipts = profileMetadataStringArray(metadata.required_receipts);
721
+ if (!packId && !packPublicName && !requiredReceipts.length) return [];
722
+ const lines = [];
723
+ const packParts = [
724
+ packId ? markdownInlineCode(packId) : "",
725
+ packPublicName ? packPublicName : ""
726
+ ].filter(Boolean);
727
+ if (packParts.length) lines.push(`- pack: ${packParts.join(" - ")}`);
728
+ if (requiredReceipts.length) {
729
+ lines.push(`- required receipts: ${requiredReceipts.length}`);
730
+ for (const receipt of requiredReceipts.slice(0, 20)) {
731
+ const item = profilePackReceiptStatus(result, metadata, receipt);
732
+ lines.push(` - ${item.status}: ${receipt} (${item.reason})`);
733
+ }
734
+ if (requiredReceipts.length > 20) lines.push(` - ${requiredReceipts.length - 20} additional required receipt(s) omitted.`);
735
+ }
736
+ return lines;
737
+ }
506
738
  function markdownInlineCode(value, maxLength = 80) {
507
739
  const normalized = value.replace(/\s+/g, " ").trim();
508
740
  const clipped = normalized.length > maxLength ? `${normalized.slice(0, Math.max(0, maxLength - 3))}...` : normalized;
@@ -764,6 +996,221 @@ function setupNaturalInputSummaryMarkdown(viewports) {
764
996
  }
765
997
  return lines;
766
998
  }
999
+ function reachabilityFailureReason(reason) {
1000
+ if (!reason) return void 0;
1001
+ const noVisibleMatch = /No visible match for selector [\s\S]*?:\s*([^\n]+)/.exec(reason);
1002
+ if (noVisibleMatch?.[1]) return noVisibleMatch[1].trim().slice(0, 120);
1003
+ if (/no_visible_match/.test(reason)) return "no_visible_match";
1004
+ if (/not visible/i.test(reason)) return "not_visible";
1005
+ return void 0;
1006
+ }
1007
+ function viewportTopBoundsOverflowPx(viewport) {
1008
+ const direct = cliFiniteNumber(viewport.bounds_overflow_px);
1009
+ if (direct !== void 0 && direct > 0) return direct;
1010
+ const offenders = Array.isArray(viewport.overflow_offenders) ? viewport.overflow_offenders.map(cliRecord).filter((item) => Boolean(item)) : [];
1011
+ for (const offender of offenders) {
1012
+ const overflow = cliFiniteNumber(offender.bounds_overflow_px) ?? cliFiniteNumber(offender.overflow_px) ?? cliFiniteNumber(offender.overflow);
1013
+ if (overflow !== void 0 && overflow > 0) return overflow;
1014
+ }
1015
+ const scrollOverflow = cliFiniteNumber(viewport.overflow_px);
1016
+ return scrollOverflow !== void 0 && scrollOverflow > 0 ? scrollOverflow : void 0;
1017
+ }
1018
+ function profileReachabilitySummaryMarkdown(result) {
1019
+ const evidenceViewports = Array.isArray(result.evidence?.viewports) ? result.evidence.viewports.map((viewport) => cliRecord(viewport)).filter((viewport) => Boolean(viewport)) : [];
1020
+ if (!evidenceViewports.length) return [];
1021
+ const evidenceByName = /* @__PURE__ */ new Map();
1022
+ for (const viewport of evidenceViewports) {
1023
+ const name = cliString(viewport.name);
1024
+ if (name) evidenceByName.set(name, viewport);
1025
+ }
1026
+ const receipts = [];
1027
+ const seen = /* @__PURE__ */ new Set();
1028
+ const addReceipt = (viewportName, selector, reason) => {
1029
+ const viewport = evidenceByName.get(viewportName);
1030
+ if (!viewport) return;
1031
+ const selectors = cliRecord(viewport.selectors);
1032
+ const selectorEvidence = cliRecord(selectors?.[selector]);
1033
+ const count = cliFiniteNumber(selectorEvidence?.count);
1034
+ const visibleCount = cliFiniteNumber(selectorEvidence?.visible_count);
1035
+ if (count === void 0 || count <= 0 || visibleCount === void 0 || visibleCount > 0) return;
1036
+ const key = `${viewportName}\0${selector}`;
1037
+ if (seen.has(key)) return;
1038
+ seen.add(key);
1039
+ const reasonText = reason || "no_visible_match";
1040
+ const boundsOverflow = viewportTopBoundsOverflowPx(viewport);
1041
+ receipts.push(`- reachability ${viewportName}: ${markdownInlineCode(selector, 120)} exists ${count}, visible ${visibleCount}, reason ${markdownInlineCode(reasonText, 80)}${boundsOverflow === void 0 ? "" : `, top bounds overflow ${boundsOverflow}px`}`);
1042
+ };
1043
+ const setupCheck = result.checks.find((check) => check.type === "setup_actions_succeeded");
1044
+ const setupSummary = cliRecord(setupCheck?.evidence?.setup_summary);
1045
+ const setupViewports = Array.isArray(setupSummary?.viewports) ? setupSummary.viewports.map(cliRecord).filter((viewport) => Boolean(viewport)) : [];
1046
+ for (const viewport of setupViewports) {
1047
+ const viewportName = cliString(viewport.name) || "viewport";
1048
+ const failed = [
1049
+ ...Array.isArray(viewport.failed) ? viewport.failed : [],
1050
+ ...Array.isArray(viewport.optional_failed) ? viewport.optional_failed : []
1051
+ ].map(cliRecord).filter((failure) => Boolean(failure));
1052
+ for (const failure of failed) {
1053
+ const selector = cliString(failure.selector);
1054
+ const reason = reachabilityFailureReason(cliString(failure.reason));
1055
+ if (selector && reason) addReceipt(viewportName, selector, reason);
1056
+ }
1057
+ }
1058
+ for (const check of result.checks) {
1059
+ if (check.type !== "selector_visible" || check.status !== "failed") continue;
1060
+ const evidence = cliRecord(check.evidence);
1061
+ const selector = cliString(evidence?.selector);
1062
+ if (!selector) continue;
1063
+ for (const viewport of evidenceViewports) {
1064
+ const viewportName = cliString(viewport.name) || "viewport";
1065
+ addReceipt(viewportName, selector, "no_visible_match");
1066
+ }
1067
+ }
1068
+ if (receipts.length > 8) {
1069
+ return [...receipts.slice(0, 8), `- ${receipts.length - 8} additional reachability receipt(s) omitted.`];
1070
+ }
1071
+ return receipts;
1072
+ }
1073
+ function stateContractReceiptName(receipt, fallbackIndex) {
1074
+ const storedTo = cliString(receipt.return_stored_to);
1075
+ if (!storedTo) return `receipt-${fallbackIndex + 1}`;
1076
+ const parts = storedTo.split(".").map((part) => part.trim()).filter(Boolean);
1077
+ return parts[parts.length - 1] || storedTo;
1078
+ }
1079
+ function stateContractReceiptValue(receipt) {
1080
+ const value = setupReturnSummaryValue(receipt, [
1081
+ "state",
1082
+ "nextState",
1083
+ "terminalState",
1084
+ "finalState",
1085
+ "status",
1086
+ "phase"
1087
+ ]);
1088
+ return cliValueLabel(value);
1089
+ }
1090
+ function stateContractSignalParts(receipts) {
1091
+ const names = [
1092
+ "hasValidate",
1093
+ "hasTryFix",
1094
+ "hasErrorDetail",
1095
+ "hasValid",
1096
+ "hasInvalid",
1097
+ "invalidGone",
1098
+ "staleGone",
1099
+ "staleCopyGone",
1100
+ "repairedTrailingCommaGone",
1101
+ "hasSuccess",
1102
+ "hasFailure",
1103
+ "hasRetry",
1104
+ "hasError",
1105
+ "success",
1106
+ "recovered"
1107
+ ];
1108
+ const seen = /* @__PURE__ */ new Set();
1109
+ const parts = [];
1110
+ for (const receipt of receipts) {
1111
+ for (const name of names) {
1112
+ const value = setupReturnSummaryValue(receipt, [name]);
1113
+ if (value === void 0) continue;
1114
+ const label = cliValueLabel(value);
1115
+ if (label === void 0) continue;
1116
+ const part = `${name}=${label}`;
1117
+ if (seen.has(part)) continue;
1118
+ seen.add(part);
1119
+ parts.push(part);
1120
+ if (parts.length >= 8) return parts;
1121
+ }
1122
+ }
1123
+ return parts;
1124
+ }
1125
+ function profileStateContractSummaryMarkdown(result) {
1126
+ const setupCheck = result.checks.find((check) => check.type === "setup_actions_succeeded");
1127
+ const setupSummary = cliRecord(setupCheck?.evidence?.setup_summary);
1128
+ const viewports = Array.isArray(setupSummary?.viewports) ? setupSummary.viewports.map(cliRecord).filter((viewport) => Boolean(viewport)) : [];
1129
+ const lines = [];
1130
+ for (const viewport of viewports.slice(0, 8)) {
1131
+ const name = cliString(viewport.name) || "viewport";
1132
+ const receipts = [
1133
+ ...setupReceiptArray(viewport, "window_eval"),
1134
+ ...setupReceiptArray(viewport, "window_call"),
1135
+ ...setupReceiptArray(viewport, "window_call_until")
1136
+ ].filter((receipt) => receipt.ok !== false);
1137
+ const states = receipts.map((receipt, index) => ({
1138
+ name: stateContractReceiptName(receipt, index),
1139
+ state: stateContractReceiptValue(receipt)
1140
+ })).filter((receipt) => Boolean(receipt.state));
1141
+ if (states.length < 2) continue;
1142
+ const stateChain = states.slice(0, 6).map((receipt) => `${markdownInlineCode(receipt.name, 60)}=${markdownInlineCode(receipt.state, 80)}`).join(" -> ");
1143
+ const omitted = states.length > 6 ? ` (+${states.length - 6} more)` : "";
1144
+ const signals = stateContractSignalParts(receipts);
1145
+ lines.push(`- state contract ${name}: ${stateChain}${omitted}${signals.length ? `; signals ${signals.map((part) => markdownInlineCode(part, 80)).join(", ")}` : ""}`);
1146
+ }
1147
+ return lines;
1148
+ }
1149
+ function sideCaveatAllowlistPart(evidence, totalKey, allowedKey) {
1150
+ const total = cliFiniteNumber(evidence[totalKey]);
1151
+ const allowed = cliFiniteNumber(evidence[allowedKey]);
1152
+ if (total === void 0 || allowed === void 0 || allowed <= 0) return void 0;
1153
+ return `${allowed}/${total} allowed`;
1154
+ }
1155
+ function sideCaveatAllowlistCounts(evidence) {
1156
+ const textCount = Array.isArray(evidence.allowed_console_texts) ? evidence.allowed_console_texts.filter((value) => typeof value === "string" && value.trim()).length : 0;
1157
+ const patternCount = Array.isArray(evidence.allowed_console_patterns) ? evidence.allowed_console_patterns.filter((value) => typeof value === "string" && value.trim()).length : 0;
1158
+ return textCount || patternCount ? `allowlist ${textCount} text${textCount === 1 ? "" : "s"}, ${patternCount} pattern${patternCount === 1 ? "" : "s"}` : void 0;
1159
+ }
1160
+ function overflowCheckFailed(result) {
1161
+ return result.checks.some((check) => check.status === "failed" && (check.type === "no_horizontal_overflow" || check.type === "no_mobile_horizontal_overflow" || check.type === "frame_no_horizontal_overflow"));
1162
+ }
1163
+ function sideCaveatOverflowLine(viewport) {
1164
+ const name = cliString(viewport.name) || "viewport";
1165
+ const scrollOverflow = cliFiniteNumber(viewport.overflow_px);
1166
+ const boundsOverflow = cliFiniteNumber(viewport.bounds_overflow_px);
1167
+ if ((scrollOverflow === void 0 || scrollOverflow <= 0) && (boundsOverflow === void 0 || boundsOverflow <= 0)) return void 0;
1168
+ const parts = [
1169
+ scrollOverflow !== void 0 && scrollOverflow > 0 ? `scroll overflow ${scrollOverflow}px` : "",
1170
+ boundsOverflow !== void 0 && boundsOverflow > 0 ? `bounds overflow ${boundsOverflow}px` : ""
1171
+ ].filter(Boolean);
1172
+ const offenders = Array.isArray(viewport.overflow_offenders) ? viewport.overflow_offenders.map(cliRecord).filter((item) => Boolean(item)) : [];
1173
+ const offender = offenders.find((item) => {
1174
+ const overflow = cliFiniteNumber(item.bounds_overflow_px) ?? cliFiniteNumber(item.overflow_px) ?? cliFiniteNumber(item.overflow);
1175
+ return overflow !== void 0 && overflow > 0;
1176
+ });
1177
+ const offenderSelector = cliString(offender?.selector);
1178
+ const offenderOverflow = offender ? cliFiniteNumber(offender.bounds_overflow_px) ?? cliFiniteNumber(offender.overflow_px) ?? cliFiniteNumber(offender.overflow) : void 0;
1179
+ return `- side caveat layout ${name}: ${parts.join(", ")}${offenderSelector && offenderOverflow !== void 0 ? `; top offender ${markdownInlineCode(offenderSelector, 100)} ${offenderOverflow}px` : ""}`;
1180
+ }
1181
+ function profileSideCaveatSummaryMarkdown(result) {
1182
+ const lines = [];
1183
+ for (const check of result.checks) {
1184
+ if (check.status !== "passed") continue;
1185
+ const evidence = cliRecord(check.evidence);
1186
+ if (!evidence) continue;
1187
+ if (check.type === "no_console_warnings") {
1188
+ const allowed = sideCaveatAllowlistPart(evidence, "total_console_warning_count", "allowed_console_warning_count");
1189
+ if (allowed) {
1190
+ const allowlist = sideCaveatAllowlistCounts(evidence);
1191
+ lines.push(`- side caveat console warnings: ${allowed}${allowlist ? `; ${allowlist}` : ""}`);
1192
+ }
1193
+ }
1194
+ if (check.type === "no_fatal_console_errors") {
1195
+ const consoleAllowed = sideCaveatAllowlistPart(evidence, "total_console_fatal_count", "allowed_console_fatal_count");
1196
+ const pageAllowed = sideCaveatAllowlistPart(evidence, "total_page_error_count", "allowed_page_error_count");
1197
+ const parts = [
1198
+ consoleAllowed ? `console fatal ${consoleAllowed}` : "",
1199
+ pageAllowed ? `page errors ${pageAllowed}` : "",
1200
+ sideCaveatAllowlistCounts(evidence)
1201
+ ].filter(Boolean);
1202
+ if (parts.length) lines.push(`- side caveat fatal errors: ${parts.join("; ")}`);
1203
+ }
1204
+ }
1205
+ if (!overflowCheckFailed(result) && Array.isArray(result.evidence?.viewports)) {
1206
+ for (const viewport of result.evidence.viewports.slice(0, 8)) {
1207
+ const line = sideCaveatOverflowLine(cliRecord(viewport) || {});
1208
+ if (line) lines.push(line);
1209
+ }
1210
+ if (result.evidence.viewports.length > 8) lines.push(`- ${result.evidence.viewports.length - 8} additional viewport side caveat(s) omitted.`);
1211
+ }
1212
+ return lines.slice(0, 12);
1213
+ }
767
1214
  function balancedSetupReceiptDetails(groups, limit) {
768
1215
  if (limit <= 0) return [];
769
1216
  const total = groups.reduce((sum, group) => sum + group.length, 0);
@@ -1481,7 +1928,7 @@ async function readArtifactJson(artifact) {
1481
1928
  async function profileResultFromRiddleArtifacts(profile, artifacts, fallbackInputs) {
1482
1929
  for (const input of fallbackInputs) {
1483
1930
  const result = extractRiddleProofProfileResult(input);
1484
- if (result) return result;
1931
+ if (result) return withProfileMetadata(profile, result);
1485
1932
  }
1486
1933
  const proofArtifacts = artifacts.filter((artifact) => /(^|\/)proof\.json(?:\.json)?$/i.test(artifact.name || artifact.url || artifact.path || "")).sort((left, right) => {
1487
1934
  const leftName = left.name || left.url || left.path || "";
@@ -1491,7 +1938,7 @@ async function profileResultFromRiddleArtifacts(profile, artifacts, fallbackInpu
1491
1938
  for (const artifact of proofArtifacts) {
1492
1939
  const parsed = await readArtifactJson(artifact);
1493
1940
  const result = extractRiddleProofProfileResult(parsed);
1494
- if (result) return result;
1941
+ if (result) return withProfileMetadata(profile, result);
1495
1942
  }
1496
1943
  const evidenceArtifacts = artifacts.filter((artifact) => /profile-evidence|evidence\.json/i.test(artifact.name || artifact.url || artifact.path || ""));
1497
1944
  for (const artifact of evidenceArtifacts) {
@@ -1502,6 +1949,16 @@ async function profileResultFromRiddleArtifacts(profile, artifacts, fallbackInpu
1502
1949
  }
1503
1950
  return void 0;
1504
1951
  }
1952
+ function withProfileMetadata(profile, result) {
1953
+ if (!profile.metadata || !Object.keys(profile.metadata).length) return result;
1954
+ return {
1955
+ ...result,
1956
+ metadata: {
1957
+ ...profile.metadata,
1958
+ ...result.metadata || {}
1959
+ }
1960
+ };
1961
+ }
1505
1962
  function withRiddleMetadata(result, input) {
1506
1963
  const poll = input.poll;
1507
1964
  const staleJobIds = input.staleJobIds?.filter(Boolean);
@@ -1845,7 +2302,7 @@ async function runSingleRiddleProfileForCli(profile, options, input) {
1845
2302
  jobId = typeof created.job_id === "string" ? created.job_id : typeof created.id === "string" ? created.id : "";
1846
2303
  if (!jobId) {
1847
2304
  const directResult = extractRiddleProofProfileResult(created);
1848
- return directResult ? withRiddleMetadata(directResult, { artifacts: collectRiddleProfileArtifactRefs(created) }) : createRiddleProofProfileInsufficientResult({ profile, runner, error: "Riddle run response was missing job_id.", artifacts: collectRiddleProfileArtifactRefs(created) });
2305
+ return directResult ? withRiddleMetadata(withProfileMetadata(profile, directResult), { artifacts: collectRiddleProfileArtifactRefs(created) }) : createRiddleProofProfileInsufficientResult({ profile, runner, error: "Riddle run response was missing job_id.", artifacts: collectRiddleProfileArtifactRefs(created) });
1849
2306
  }
1850
2307
  poll = await client.pollJob(jobId, pollOptions);
1851
2308
  if (attempt < retryLimit && shouldRetryUnsubmittedRiddleJob(poll)) {
package/dist/index.cjs CHANGED
@@ -12193,6 +12193,7 @@ function assessRiddleProofProfileEvidence(profile, evidence, options = {}) {
12193
12193
  checks,
12194
12194
  summary: summarizeRiddleProofProfileResult({ profile_name: profile.name, status, checks, viewports: evidence?.viewports || [] }),
12195
12195
  captured_at: capturedAt,
12196
+ metadata: profile.metadata,
12196
12197
  warnings: warnings.length ? warnings : void 0,
12197
12198
  evidence,
12198
12199
  riddle: options.riddle
@@ -12254,6 +12255,7 @@ function createRiddleProofProfileEnvironmentBlockedResult(input) {
12254
12255
  checks: [],
12255
12256
  summary: summarizeEnvironmentBlockedRunner(input.profile.name, environmentBlocker),
12256
12257
  captured_at: (/* @__PURE__ */ new Date()).toISOString(),
12258
+ metadata: input.profile.metadata,
12257
12259
  warnings: warnings.length ? warnings : void 0,
12258
12260
  riddle: input.riddle,
12259
12261
  environment_blocker: environmentBlocker,
@@ -12330,6 +12332,7 @@ function createRiddleProofProfileInsufficientResult(input) {
12330
12332
  checks: [],
12331
12333
  summary: `${input.profile.name} did not produce enough evidence for a profile judgment.`,
12332
12334
  captured_at: (/* @__PURE__ */ new Date()).toISOString(),
12335
+ metadata: input.profile.metadata,
12333
12336
  warnings: warnings.length ? warnings : void 0,
12334
12337
  riddle: input.riddle,
12335
12338
  error: message
@@ -14256,6 +14259,7 @@ function assessProfile(profile, evidence) {
14256
14259
  checks,
14257
14260
  summary,
14258
14261
  captured_at: evidence.captured_at,
14262
+ metadata: profile.metadata,
14259
14263
  warnings: profileWarnings.length ? profileWarnings : undefined,
14260
14264
  evidence,
14261
14265
  };
package/dist/index.js CHANGED
@@ -62,7 +62,7 @@ import {
62
62
  resolveRiddleProofProfileTimeoutSec,
63
63
  slugifyRiddleProofProfileName,
64
64
  summarizeRiddleProofProfileResult
65
- } from "./chunk-X24EJSIU.js";
65
+ } from "./chunk-5MBIRRA7.js";
66
66
  import {
67
67
  DEFAULT_RIDDLE_API_BASE_URL,
68
68
  DEFAULT_RIDDLE_API_KEY_FILE,
package/dist/profile.cjs CHANGED
@@ -3507,6 +3507,7 @@ function assessRiddleProofProfileEvidence(profile, evidence, options = {}) {
3507
3507
  checks,
3508
3508
  summary: summarizeRiddleProofProfileResult({ profile_name: profile.name, status, checks, viewports: evidence?.viewports || [] }),
3509
3509
  captured_at: capturedAt,
3510
+ metadata: profile.metadata,
3510
3511
  warnings: warnings.length ? warnings : void 0,
3511
3512
  evidence,
3512
3513
  riddle: options.riddle
@@ -3568,6 +3569,7 @@ function createRiddleProofProfileEnvironmentBlockedResult(input) {
3568
3569
  checks: [],
3569
3570
  summary: summarizeEnvironmentBlockedRunner(input.profile.name, environmentBlocker),
3570
3571
  captured_at: (/* @__PURE__ */ new Date()).toISOString(),
3572
+ metadata: input.profile.metadata,
3571
3573
  warnings: warnings.length ? warnings : void 0,
3572
3574
  riddle: input.riddle,
3573
3575
  environment_blocker: environmentBlocker,
@@ -3644,6 +3646,7 @@ function createRiddleProofProfileInsufficientResult(input) {
3644
3646
  checks: [],
3645
3647
  summary: `${input.profile.name} did not produce enough evidence for a profile judgment.`,
3646
3648
  captured_at: (/* @__PURE__ */ new Date()).toISOString(),
3649
+ metadata: input.profile.metadata,
3647
3650
  warnings: warnings.length ? warnings : void 0,
3648
3651
  riddle: input.riddle,
3649
3652
  error: message
@@ -5570,6 +5573,7 @@ function assessProfile(profile, evidence) {
5570
5573
  checks,
5571
5574
  summary,
5572
5575
  captured_at: evidence.captured_at,
5576
+ metadata: profile.metadata,
5573
5577
  warnings: profileWarnings.length ? profileWarnings : undefined,
5574
5578
  evidence,
5575
5579
  };
@@ -387,6 +387,7 @@ interface RiddleProofProfileResult {
387
387
  checks: RiddleProofProfileCheckResult[];
388
388
  summary: string;
389
389
  captured_at: string;
390
+ metadata?: Record<string, JsonValue>;
390
391
  warnings?: string[];
391
392
  evidence?: RiddleProofProfileEvidence;
392
393
  riddle?: {
package/dist/profile.d.ts CHANGED
@@ -387,6 +387,7 @@ interface RiddleProofProfileResult {
387
387
  checks: RiddleProofProfileCheckResult[];
388
388
  summary: string;
389
389
  captured_at: string;
390
+ metadata?: Record<string, JsonValue>;
390
391
  warnings?: string[];
391
392
  evidence?: RiddleProofProfileEvidence;
392
393
  riddle?: {
package/dist/profile.js CHANGED
@@ -23,7 +23,7 @@ import {
23
23
  resolveRiddleProofProfileTimeoutSec,
24
24
  slugifyRiddleProofProfileName,
25
25
  summarizeRiddleProofProfileResult
26
- } from "./chunk-X24EJSIU.js";
26
+ } from "./chunk-5MBIRRA7.js";
27
27
  export {
28
28
  RIDDLE_PROOF_PROFILE_CHECK_TYPES,
29
29
  RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION,
@@ -120,7 +120,7 @@ declare function buildSetupArgs(params: WorkflowParams, config: ReturnType<typeo
120
120
  target_image_hash: string;
121
121
  viewport_matrix_json: string;
122
122
  deterministic_setup_json: string;
123
- reference: "prod" | "before" | "both";
123
+ reference: "before" | "prod" | "both";
124
124
  base_branch: string;
125
125
  before_ref: string;
126
126
  allow_static_preview_fallback: string;
@@ -120,7 +120,7 @@ declare function buildSetupArgs(params: WorkflowParams, config: ReturnType<typeo
120
120
  target_image_hash: string;
121
121
  viewport_matrix_json: string;
122
122
  deterministic_setup_json: string;
123
- reference: "prod" | "before" | "both";
123
+ reference: "before" | "prod" | "both";
124
124
  base_branch: string;
125
125
  before_ref: string;
126
126
  allow_static_preview_fallback: string;