@riddledc/riddle-proof 0.5.57 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -2773,6 +2773,8 @@ var init_proof_run_engine = __esm({
2773
2773
  // src/index.ts
2774
2774
  var index_exports = {};
2775
2775
  __export(index_exports, {
2776
+ BASIC_GAMEPLAY_ACTION_TYPES: () => BASIC_GAMEPLAY_ACTION_TYPES,
2777
+ BASIC_GAMEPLAY_PROGRESS_CHECK_TYPES: () => BASIC_GAMEPLAY_PROGRESS_CHECK_TYPES,
2776
2778
  DEFAULT_DIAGNOSTIC_ARRAY_LIMIT: () => DEFAULT_DIAGNOSTIC_ARRAY_LIMIT,
2777
2779
  DEFAULT_DIAGNOSTIC_HISTORY_LIMIT: () => DEFAULT_DIAGNOSTIC_HISTORY_LIMIT,
2778
2780
  DEFAULT_DIAGNOSTIC_STRING_LIMIT: () => DEFAULT_DIAGNOSTIC_STRING_LIMIT,
@@ -2786,6 +2788,11 @@ __export(index_exports, {
2786
2788
  RIDDLE_PROOF_CHECKPOINT_RESPONSE_VERSION: () => RIDDLE_PROOF_CHECKPOINT_RESPONSE_VERSION,
2787
2789
  RIDDLE_PROOF_PLAYABILITY_ASSESSMENT_VERSION: () => RIDDLE_PROOF_PLAYABILITY_ASSESSMENT_VERSION,
2788
2790
  RIDDLE_PROOF_PLAYABILITY_VERSION: () => RIDDLE_PROOF_PLAYABILITY_VERSION,
2791
+ RIDDLE_PROOF_PROFILE_CHECK_TYPES: () => RIDDLE_PROOF_PROFILE_CHECK_TYPES,
2792
+ RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION: () => RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION,
2793
+ RIDDLE_PROOF_PROFILE_RESULT_VERSION: () => RIDDLE_PROOF_PROFILE_RESULT_VERSION,
2794
+ RIDDLE_PROOF_PROFILE_STATUSES: () => RIDDLE_PROOF_PROFILE_STATUSES,
2795
+ RIDDLE_PROOF_PROFILE_VERSION: () => RIDDLE_PROOF_PROFILE_VERSION,
2789
2796
  RIDDLE_PROOF_RUN_CARD_VERSION: () => RIDDLE_PROOF_RUN_CARD_VERSION,
2790
2797
  RIDDLE_PROOF_RUN_STATE_VERSION: () => RIDDLE_PROOF_RUN_STATE_VERSION,
2791
2798
  RIDDLE_PROOF_VISUAL_SESSION_FINGERPRINT_VERSION: () => RIDDLE_PROOF_VISUAL_SESSION_FINGERPRINT_VERSION,
@@ -2797,18 +2804,27 @@ __export(index_exports, {
2797
2804
  applyPrLifecycleState: () => applyPrLifecycleState,
2798
2805
  applyTerminalMetadata: () => applyTerminalMetadata,
2799
2806
  assessBasicGameplayEvidence: () => assessBasicGameplayEvidence,
2807
+ assessBasicGameplayProgressionCheck: () => assessBasicGameplayProgressionCheck,
2808
+ assessBasicGameplayProgressionChecks: () => assessBasicGameplayProgressionChecks,
2800
2809
  assessBasicGameplayRoute: () => assessBasicGameplayRoute,
2801
2810
  assessPlayabilityEvidence: () => assessPlayabilityEvidence,
2811
+ assessRiddleProofProfileEvidence: () => assessRiddleProofProfileEvidence,
2812
+ attachBasicGameplayArtifactScreenshotHashes: () => attachBasicGameplayArtifactScreenshotHashes,
2813
+ augmentBasicGameplayAssessmentWithProgressionChecks: () => augmentBasicGameplayAssessmentWithProgressionChecks,
2802
2814
  authorPacketPayloadFromCheckpointResponse: () => authorPacketPayloadFromCheckpointResponse,
2803
2815
  buildAuthorCheckpointPacket: () => buildAuthorCheckpointPacket,
2804
2816
  buildCheckpointPacketForEngineResult: () => buildCheckpointPacketForEngineResult,
2805
2817
  buildProofAssessmentCheckpointPacket: () => buildProofAssessmentCheckpointPacket,
2818
+ buildRiddleProofProfileScript: () => buildRiddleProofProfileScript,
2806
2819
  buildStageCheckpointPacket: () => buildStageCheckpointPacket,
2807
2820
  buildVisualProofSession: () => buildVisualProofSession,
2808
2821
  checkpointResponseIdentity: () => checkpointResponseIdentity,
2809
2822
  checkpointSummaryFromState: () => checkpointSummaryFromState,
2823
+ collectRiddleProfileArtifactRefs: () => collectRiddleProfileArtifactRefs,
2824
+ compactBasicGameplayText: () => compactBasicGameplayText,
2810
2825
  compactRecord: () => compactRecord,
2811
2826
  compareVisualProofSessionFingerprint: () => compareVisualProofSessionFingerprint,
2827
+ createBasicGameplayCatchRecords: () => createBasicGameplayCatchRecords,
2812
2828
  createBasicGameplayCatchSummary: () => createBasicGameplayCatchSummary,
2813
2829
  createCaptureDiagnostic: () => createCaptureDiagnostic,
2814
2830
  createCheckpointResponseTemplate: () => createCheckpointResponseTemplate,
@@ -2818,6 +2834,9 @@ __export(index_exports, {
2818
2834
  createLocalAgentAdapter: () => createCodexExecAgentAdapter,
2819
2835
  createLocalAgentJsonRunner: () => createCodexExecJsonRunner,
2820
2836
  createRiddleApiClient: () => createRiddleApiClient,
2837
+ createRiddleProofProfileConfigurationError: () => createRiddleProofProfileConfigurationError,
2838
+ createRiddleProofProfileEnvironmentBlockedResult: () => createRiddleProofProfileEnvironmentBlockedResult,
2839
+ createRiddleProofProfileInsufficientResult: () => createRiddleProofProfileInsufficientResult,
2821
2840
  createRiddleProofRunCard: () => createRiddleProofRunCard,
2822
2841
  createRunResult: () => createRunResult,
2823
2842
  createRunState: () => createRunState,
@@ -2825,6 +2844,7 @@ __export(index_exports, {
2825
2844
  deployRiddleStaticPreview: () => deployRiddleStaticPreview,
2826
2845
  extractBasicGameplayEvidence: () => extractBasicGameplayEvidence,
2827
2846
  extractPlayabilityEvidence: () => extractPlayabilityEvidence,
2847
+ extractRiddleProofProfileResult: () => extractRiddleProofProfileResult,
2828
2848
  isDuplicateCheckpointResponse: () => isDuplicateCheckpointResponse,
2829
2849
  isRiddleProofPlayabilityMode: () => isRiddleProofPlayabilityMode,
2830
2850
  isSuccessfulStatus: () => isSuccessfulStatus,
@@ -2834,16 +2854,20 @@ __export(index_exports, {
2834
2854
  normalizeCheckpointResponse: () => normalizeCheckpointResponse,
2835
2855
  normalizeIntegrationContext: () => normalizeIntegrationContext,
2836
2856
  normalizePrLifecycleState: () => normalizePrLifecycleState,
2857
+ normalizeRiddleProofProfile: () => normalizeRiddleProofProfile,
2837
2858
  normalizeRunParams: () => normalizeRunParams,
2838
2859
  normalizeTerminalMetadata: () => normalizeTerminalMetadata,
2839
2860
  parseRiddleViewport: () => parseRiddleViewport,
2840
2861
  parseVisualProofSession: () => parseVisualProofSession,
2841
2862
  pollRiddleJob: () => pollRiddleJob,
2863
+ profileStatusExitCode: () => profileStatusExitCode,
2842
2864
  proofContractFromAuthorCheckpointResponse: () => proofContractFromAuthorCheckpointResponse,
2843
2865
  readRiddleProofRunStatus: () => readRiddleProofRunStatus,
2844
2866
  recordValue: () => recordValue,
2845
2867
  redactForProofDiagnostics: () => redactForProofDiagnostics,
2868
+ resolveBasicGameplayProgressionCheckWithArtifactScreenshots: () => resolveBasicGameplayProgressionCheckWithArtifactScreenshots,
2846
2869
  resolveRiddleApiKey: () => resolveRiddleApiKey,
2870
+ resolveRiddleProofProfileTargetUrl: () => resolveRiddleProofProfileTargetUrl,
2847
2871
  riddleRequestJson: () => riddleRequestJson,
2848
2872
  runCodexExecAgentDoctor: () => runCodexExecAgentDoctor,
2849
2873
  runLocalAgentDoctor: () => runCodexExecAgentDoctor,
@@ -2851,9 +2875,12 @@ __export(index_exports, {
2851
2875
  runRiddleProofEngineHarness: () => runRiddleProofEngineHarness,
2852
2876
  runRiddleScript: () => runRiddleScript,
2853
2877
  runRiddleServerPreview: () => runRiddleServerPreview,
2878
+ sanitizeBasicGameplayJsonString: () => sanitizeBasicGameplayJsonString,
2854
2879
  setRunStatus: () => setRunStatus,
2880
+ slugifyRiddleProofProfileName: () => slugifyRiddleProofProfileName,
2855
2881
  statePathsForRunState: () => statePathsForRunState,
2856
2882
  summarizeCaptureArtifacts: () => summarizeCaptureArtifacts,
2883
+ summarizeRiddleProofProfileResult: () => summarizeRiddleProofProfileResult,
2857
2884
  visualSessionFingerprint: () => visualSessionFingerprint,
2858
2885
  visualSessionFingerprintBasis: () => visualSessionFingerprintBasis
2859
2886
  });
@@ -7623,6 +7650,34 @@ function parseJson(value) {
7623
7650
  var RIDDLE_PROOF_BASIC_GAMEPLAY_VERSION = "riddle-proof.basic-gameplay.v1";
7624
7651
  var RIDDLE_PROOF_BASIC_GAMEPLAY_ASSESSMENT_VERSION = "riddle-proof.basic-gameplay.assessment.v1";
7625
7652
  var RIDDLE_PROOF_BASIC_GAMEPLAY_CATCH_VERSION = "riddle-proof.basic-gameplay.catch.v1";
7653
+ var BASIC_GAMEPLAY_ACTION_TYPES = [
7654
+ "wait",
7655
+ "key",
7656
+ "key-down",
7657
+ "key-up",
7658
+ "hold-key",
7659
+ "repeat",
7660
+ "click",
7661
+ "click-by-text",
7662
+ "wait-for-text",
7663
+ "window-call",
7664
+ "evaluate"
7665
+ ];
7666
+ var BASIC_GAMEPLAY_PROGRESS_CHECK_TYPES = [
7667
+ "selector_count_increases",
7668
+ "selector_count_at_least",
7669
+ "selector_absent",
7670
+ "selector_text_matches",
7671
+ "number_increases",
7672
+ "number_decreases",
7673
+ "number_unchanged",
7674
+ "number_stays_equal",
7675
+ "number_equals",
7676
+ "canvas_hash_changes",
7677
+ "screenshot_hash_changes",
7678
+ "visual_hash_changes",
7679
+ "state_changes"
7680
+ ];
7626
7681
  var BASIC_GAMEPLAY_CONTAINER_KEYS = [
7627
7682
  "basic_gameplay",
7628
7683
  "basicGameplay",
@@ -7631,6 +7686,19 @@ var BASIC_GAMEPLAY_CONTAINER_KEYS = [
7631
7686
  "gameplay_proof",
7632
7687
  "gameplayProof"
7633
7688
  ];
7689
+ var ARTIFACT_VISUAL_CHANGE_CHECKS = /* @__PURE__ */ new Set([
7690
+ "canvas_hash_changes",
7691
+ "screenshot_hash_changes",
7692
+ "state_changes",
7693
+ "visual_hash_changes"
7694
+ ]);
7695
+ var PHASE_SCREENSHOT_SUFFIXES = {
7696
+ initial: "before",
7697
+ after_action: "after",
7698
+ after_continue: "after-continue",
7699
+ after_restart: "after-restart",
7700
+ revisit: "revisit"
7701
+ };
7634
7702
  function assessBasicGameplayEvidence(evidence, options = {}) {
7635
7703
  const run = extractBasicGameplayEvidence(evidence);
7636
7704
  if (!run) {
@@ -7646,12 +7714,16 @@ function assessBasicGameplayEvidence(evidence, options = {}) {
7646
7714
  route_results: []
7647
7715
  };
7648
7716
  }
7649
- const routeResults = (run.results || []).map((route) => assessBasicGameplayRoute(route, options));
7717
+ const routeResults = (run.results || []).map((route) => augmentRouteAssessmentWithProgressionChecks(
7718
+ assessBasicGameplayRoute(route, options),
7719
+ route
7720
+ ));
7650
7721
  const failingRoutes = routeResults.filter((result) => !result.ok).map((result) => ({
7651
7722
  name: result.name,
7652
7723
  path: result.path,
7653
7724
  failures: result.failures,
7654
- warnings: result.warnings
7725
+ warnings: result.warnings,
7726
+ suite_failures: result.suite_failures
7655
7727
  }));
7656
7728
  return {
7657
7729
  version: RIDDLE_PROOF_BASIC_GAMEPLAY_ASSESSMENT_VERSION,
@@ -7732,6 +7804,255 @@ function assessBasicGameplayRoute(route, options = {}) {
7732
7804
  }
7733
7805
  };
7734
7806
  }
7807
+ function sanitizeBasicGameplayJsonString(value) {
7808
+ const text = String(value ?? "");
7809
+ let output = "";
7810
+ for (let index = 0; index < text.length; index += 1) {
7811
+ const code = text.charCodeAt(index);
7812
+ if (code >= 55296 && code <= 56319) {
7813
+ const next = text.charCodeAt(index + 1);
7814
+ if (next >= 56320 && next <= 57343) {
7815
+ output += text[index] + text[index + 1];
7816
+ index += 1;
7817
+ }
7818
+ continue;
7819
+ }
7820
+ if (code >= 56320 && code <= 57343) continue;
7821
+ output += text[index];
7822
+ }
7823
+ return output;
7824
+ }
7825
+ function compactBasicGameplayText(value, max = 160) {
7826
+ const compacted = sanitizeBasicGameplayJsonString(value).replace(/\s+/g, " ").trim();
7827
+ return Array.from(compacted).slice(0, max).join("");
7828
+ }
7829
+ function assessBasicGameplayProgressionCheck(check) {
7830
+ const before = metricValue(check.before);
7831
+ const after = metricValue(check.after);
7832
+ const type = String(check.type || "");
7833
+ const hasExplicitResult = typeof check.ok === "boolean";
7834
+ let ok = hasExplicitResult ? check.ok === true : true;
7835
+ let reason = check.reason ?? null;
7836
+ if (type === "selector_count_increases") {
7837
+ ok = numberValue2(after?.count) > numberValue2(before?.count);
7838
+ reason = ok ? null : "selector_count_did_not_increase";
7839
+ } else if (type === "selector_count_at_least") {
7840
+ if (numericValue3(check.min) === null && hasExplicitResult) return resolveBasicGameplayProgressionCheckWithArtifactScreenshots({ ...check, ok, reason });
7841
+ ok = numberValue2(after?.count) >= numberValue2(check.min);
7842
+ reason = ok ? null : "selector_count_below_min";
7843
+ } else if (type === "selector_absent") {
7844
+ ok = !after?.present || numberValue2(after?.count) === 0;
7845
+ reason = ok ? null : "selector_still_present";
7846
+ } else if (type === "selector_text_matches") {
7847
+ if (!check.pattern && hasExplicitResult) return resolveBasicGameplayProgressionCheckWithArtifactScreenshots({ ...check, ok, reason });
7848
+ ok = textMatches(after?.text, check.pattern, check.flags);
7849
+ reason = ok ? null : "selector_text_did_not_match";
7850
+ } else if (type === "number_increases") {
7851
+ ok = numericValue3(before?.number) !== null && numericValue3(after?.number) !== null && numberValue2(after?.number) > numberValue2(before?.number);
7852
+ reason = ok ? null : "number_did_not_increase";
7853
+ } else if (type === "number_decreases") {
7854
+ ok = numericValue3(before?.number) !== null && numericValue3(after?.number) !== null && numberValue2(after?.number) < numberValue2(before?.number);
7855
+ reason = ok ? null : "number_did_not_decrease";
7856
+ } else if (type === "number_unchanged" || type === "number_stays_equal") {
7857
+ ok = numericValue3(before?.number) !== null && numericValue3(after?.number) !== null && numberValue2(after?.number) === numberValue2(before?.number);
7858
+ reason = ok ? null : "number_changed";
7859
+ } else if (type === "number_equals") {
7860
+ const expected = numericValue3(check.expected ?? check.value);
7861
+ if (expected === null && hasExplicitResult) return resolveBasicGameplayProgressionCheckWithArtifactScreenshots({ ...check, ok, reason });
7862
+ ok = numericValue3(after?.number) !== null && expected !== null && numberValue2(after?.number) === expected;
7863
+ reason = ok ? null : "number_did_not_equal_expected";
7864
+ } else if (type === "canvas_hash_changes") {
7865
+ ok = hashChanged(before, after, ["first_canvas_hash", "first_canvas_visual_sample_hash", "visual_sample_hash"]);
7866
+ reason = ok ? null : "canvas_or_visual_sample_hash_did_not_change";
7867
+ } else if (type === "screenshot_hash_changes") {
7868
+ ok = hashChanged(before, after, ["screenshot_hash", "visual_sample_hash", "artifact_screenshot_hash"]);
7869
+ reason = ok ? null : "screenshot_hash_did_not_change";
7870
+ } else if (type === "visual_hash_changes") {
7871
+ ok = hashChanged(before, after, ["visual_sample_hash", "screenshot_hash", "artifact_screenshot_hash"]);
7872
+ reason = ok ? null : "visual_hash_did_not_change";
7873
+ } else if (type === "state_changes") {
7874
+ ok = hashChanged(before, after, [
7875
+ "dom_signature_hash",
7876
+ "body_text_hash",
7877
+ "screenshot_hash",
7878
+ "visual_sample_hash",
7879
+ "artifact_screenshot_hash",
7880
+ "first_canvas_hash",
7881
+ "first_canvas_visual_sample_hash"
7882
+ ]);
7883
+ reason = ok ? null : "state_hash_did_not_change";
7884
+ }
7885
+ const assessed = {
7886
+ ...check,
7887
+ ok,
7888
+ reason
7889
+ };
7890
+ return resolveBasicGameplayProgressionCheckWithArtifactScreenshots(assessed);
7891
+ }
7892
+ function assessBasicGameplayProgressionChecks(route) {
7893
+ return progressionChecksForRoute(route).map((check) => assessBasicGameplayProgressionCheck(check));
7894
+ }
7895
+ function augmentBasicGameplayAssessmentWithProgressionChecks(assessment, evidence) {
7896
+ const run = extractBasicGameplayEvidence(evidence);
7897
+ if (!run?.results?.length) return assessment;
7898
+ const routeResults = assessment.route_results.map(
7899
+ (result, index) => augmentRouteAssessmentWithProgressionChecks(result, run.results?.[index] || {})
7900
+ );
7901
+ const failingRoutes = routeResults.filter((result) => !result.ok).map((result) => ({
7902
+ name: result.name,
7903
+ path: result.path,
7904
+ failures: result.failures,
7905
+ warnings: result.warnings,
7906
+ suite_failures: result.suite_failures
7907
+ }));
7908
+ return {
7909
+ ...assessment,
7910
+ passed: failingRoutes.length === 0,
7911
+ passing_routes: routeResults.filter((result) => result.ok).length,
7912
+ failing_routes: failingRoutes,
7913
+ failure_counts: countCodes(routeResults.flatMap((result) => result.failures)),
7914
+ warning_counts: countCodes(routeResults.flatMap((result) => result.warnings)),
7915
+ route_results: routeResults
7916
+ };
7917
+ }
7918
+ function resolveBasicGameplayProgressionCheckWithArtifactScreenshots(check) {
7919
+ if (check.ok !== false) return check;
7920
+ if (!ARTIFACT_VISUAL_CHANGE_CHECKS.has(String(check.type || ""))) return check;
7921
+ const beforeHash = stringValue4(metricValue(check.before)?.artifact_screenshot_hash);
7922
+ const afterHash = stringValue4(metricValue(check.after)?.artifact_screenshot_hash);
7923
+ if (!beforeHash || !afterHash || beforeHash === afterHash) return check;
7924
+ return {
7925
+ ...check,
7926
+ ok: true,
7927
+ reason: null,
7928
+ artifact_resolution: {
7929
+ source: "riddle_screenshot_artifacts",
7930
+ before_hash: beforeHash,
7931
+ after_hash: afterHash
7932
+ }
7933
+ };
7934
+ }
7935
+ function attachBasicGameplayArtifactScreenshotHashes(evidence, routesOrOptions = {}, maybeArtifacts = []) {
7936
+ const routes = Array.isArray(routesOrOptions) ? routesOrOptions : routesOrOptions.routes || [];
7937
+ const artifacts = Array.isArray(routesOrOptions) ? maybeArtifacts : routesOrOptions.artifacts || [];
7938
+ if (!evidence?.results?.length || !artifacts.length) return evidence;
7939
+ const artifactsByName = screenshotArtifactIndex(artifacts);
7940
+ if (!artifactsByName.size) return evidence;
7941
+ for (const [index, routeEvidence] of evidence.results.entries()) {
7942
+ const routeContract = routes[index] || {};
7943
+ for (const phase of Object.keys(PHASE_SCREENSHOT_SUFFIXES)) {
7944
+ attachPhaseArtifactHash(routeEvidence, routeContract, phase, artifactsByName);
7945
+ }
7946
+ const checks = progressionChecksForRoute(routeEvidence);
7947
+ const resolvedChecks = checks.map((check) => {
7948
+ const fromPhase = check.from_phase || "initial";
7949
+ const toPhase = check.to_phase || "after_action";
7950
+ if (check.before) attachPhaseArtifactHash({ ...routeEvidence, [fromPhase]: check.before }, routeContract, fromPhase, artifactsByName);
7951
+ if (check.after) attachPhaseArtifactHash({ ...routeEvidence, [toPhase]: check.after }, routeContract, toPhase, artifactsByName);
7952
+ return resolveBasicGameplayProgressionCheckWithArtifactScreenshots(check);
7953
+ });
7954
+ if (routeEvidence.progression_checks) routeEvidence.progression_checks = resolvedChecks;
7955
+ else if (routeEvidence.progressionChecks) routeEvidence.progressionChecks = resolvedChecks;
7956
+ routeEvidence.progression_failure_count = resolvedChecks.filter((check) => check.ok === false).length;
7957
+ }
7958
+ return evidence;
7959
+ }
7960
+ function createBasicGameplayCatchRecords(assessment, evidence) {
7961
+ const run = extractBasicGameplayEvidence(evidence);
7962
+ if (!run?.results?.length) return [];
7963
+ const catches = [];
7964
+ for (const route of run.results) {
7965
+ if (numberValue2(route.page_error_count) > 0) {
7966
+ catches.push({
7967
+ site: run.site || null,
7968
+ route: route.name,
7969
+ path: route.path,
7970
+ code: "fatal_page_error",
7971
+ label: "page runtime error",
7972
+ type: "page_error",
7973
+ selector: null,
7974
+ reason: stringValue4(route.first_page_error) || "page_error",
7975
+ page_errors: listValue2(route.page_errors),
7976
+ summary: `${route.name || route.path || "Route"}: page runtime error (${stringValue4(route.first_page_error) || "page_error"})`
7977
+ });
7978
+ }
7979
+ if (numberValue2(route.console_error_count) > 0) {
7980
+ catches.push({
7981
+ site: run.site || null,
7982
+ route: route.name,
7983
+ path: route.path,
7984
+ code: "critical_console_error",
7985
+ label: "console error",
7986
+ type: "console_error",
7987
+ selector: null,
7988
+ reason: stringValue4(route.first_console_error) || "console_error",
7989
+ console_errors: listValue2(route.console_errors),
7990
+ summary: `${route.name || route.path || "Route"}: console error (${stringValue4(route.first_console_error) || "console_error"})`
7991
+ });
7992
+ }
7993
+ for (const [group, phase] of [
7994
+ ["action_results", "after_action"],
7995
+ ["continued_action_results", "after_continue"],
7996
+ ["restart_action_results", "after_restart"]
7997
+ ]) {
7998
+ for (const actionResult of listValue2(route[group])) {
7999
+ if (!actionResult || actionResult.ok !== false) continue;
8000
+ const action = stringValue4(actionResult.action) || group;
8001
+ const reason = stringValue4(actionResult.reason) || "action_failed";
8002
+ catches.push({
8003
+ site: run.site || null,
8004
+ route: route.name,
8005
+ path: route.path,
8006
+ code: "action_failed",
8007
+ label: action,
8008
+ type: action,
8009
+ selector: stringValue4(actionResult.selector),
8010
+ reason,
8011
+ phase,
8012
+ action_result: actionResult,
8013
+ summary: `${route.name || route.path || "Route"}: ${action} failed (${reason})`
8014
+ });
8015
+ }
8016
+ }
8017
+ for (const check of assessBasicGameplayProgressionChecks(route).filter((item) => item.ok === false)) {
8018
+ catches.push({
8019
+ site: run.site || null,
8020
+ route: route.name,
8021
+ path: route.path,
8022
+ code: "progression_assertion_failed",
8023
+ label: check.label,
8024
+ type: String(check.type || ""),
8025
+ selector: check.selector || null,
8026
+ state_path: check.state_path || null,
8027
+ state_call: check.state_call || null,
8028
+ property_path: check.property_path || null,
8029
+ reason: check.reason || "progression_assertion_failed",
8030
+ from_phase: check.from_phase,
8031
+ to_phase: check.to_phase,
8032
+ before: compactCatchMetric(check.before),
8033
+ after: compactCatchMetric(check.after),
8034
+ summary: `${route.name || route.path || "Route"}: ${check.label || check.type || "progression check"} failed (${check.reason || "progression_assertion_failed"})`
8035
+ });
8036
+ }
8037
+ }
8038
+ if (!catches.length && assessment.failing_routes.length) {
8039
+ for (const route of assessment.failing_routes) {
8040
+ for (const code of route.failures || []) {
8041
+ catches.push({
8042
+ site: run.site || null,
8043
+ route: route.name,
8044
+ path: route.path,
8045
+ code,
8046
+ label: code,
8047
+ type: code,
8048
+ reason: code,
8049
+ summary: `${route.name || route.path || "Route"}: ${code}`
8050
+ });
8051
+ }
8052
+ }
8053
+ }
8054
+ return catches;
8055
+ }
7735
8056
  function createBasicGameplayCatchSummary(input, options = {}) {
7736
8057
  const before = summarizeAssessment(assessBasicGameplayEvidence(input.before, options));
7737
8058
  const after = input.after === void 0 ? void 0 : summarizeAssessment(assessBasicGameplayEvidence(input.after, options));
@@ -7847,6 +8168,122 @@ function changed(before, after) {
7847
8168
  function canvasHashes(canvases) {
7848
8169
  return (canvases || []).map((canvas) => canvas.hash).filter(Boolean).join("|");
7849
8170
  }
8171
+ function augmentRouteAssessmentWithProgressionChecks(result, route) {
8172
+ const progressionFailures = assessBasicGameplayProgressionChecks(route).filter((check) => check.ok === false);
8173
+ if (!progressionFailures.length) return result;
8174
+ const failures = result.failures.includes("progression_assertion_failed") ? result.failures : [...result.failures, "progression_assertion_failed"];
8175
+ return {
8176
+ ...result,
8177
+ ok: false,
8178
+ failures,
8179
+ suite_failures: [
8180
+ ...result.suite_failures || [],
8181
+ ...progressionFailures.map((check) => ({
8182
+ code: "progression_assertion_failed",
8183
+ label: check.label,
8184
+ reason: check.reason,
8185
+ selector: check.selector || null,
8186
+ state_path: check.state_path || null,
8187
+ state_call: check.state_call || null,
8188
+ property_path: check.property_path || null
8189
+ }))
8190
+ ]
8191
+ };
8192
+ }
8193
+ function progressionChecksForRoute(route) {
8194
+ return listValue2(route.progression_checks || route.progressionChecks).filter((item) => Boolean(recordValue3(item)));
8195
+ }
8196
+ function metricValue(value) {
8197
+ return recordValue3(value);
8198
+ }
8199
+ function textMatches(text, pattern, flags) {
8200
+ if (!pattern) return Boolean(text);
8201
+ try {
8202
+ return new RegExp(String(pattern), typeof flags === "string" ? flags : "i").test(String(text ?? ""));
8203
+ } catch {
8204
+ return false;
8205
+ }
8206
+ }
8207
+ function hashChanged(before, after, keys) {
8208
+ if (!before || !after) return false;
8209
+ return keys.some((key) => {
8210
+ const beforeValue = stringValue4(before[key]);
8211
+ const afterValue = stringValue4(after[key]);
8212
+ return Boolean(beforeValue && afterValue && beforeValue !== afterValue);
8213
+ });
8214
+ }
8215
+ function screenshotArtifactIndex(artifacts) {
8216
+ const index = /* @__PURE__ */ new Map();
8217
+ for (const artifact of artifacts || []) {
8218
+ const hash = stringValue4(artifact.sha256 || artifact.hash);
8219
+ if (!hash) continue;
8220
+ if (String(artifact.kind || "").toLowerCase() !== "screenshot" && !/\.png($|\?)/i.test(`${artifact.name || ""} ${artifact.path || ""} ${artifact.url || ""}`)) continue;
8221
+ const filename = artifactBasename(artifact.path || artifact.name || artifact.url);
8222
+ if (!filename) continue;
8223
+ index.set(filename.toLowerCase(), {
8224
+ ...artifact,
8225
+ sha256: hash
8226
+ });
8227
+ }
8228
+ return index;
8229
+ }
8230
+ function attachPhaseArtifactHash(routeEvidence, routeContract, phase, artifactsByName) {
8231
+ const suffix = PHASE_SCREENSHOT_SUFFIXES[phase];
8232
+ if (!suffix) return null;
8233
+ const metric = metricValue(routeEvidence[phase]);
8234
+ if (!metric) return null;
8235
+ const filename = `${routeArtifactSlug(routeEvidence, routeContract)}-${suffix}.png`.toLowerCase();
8236
+ const artifact = artifactsByName.get(filename);
8237
+ if (!artifact?.sha256) return null;
8238
+ metric.artifact_screenshot_hash = artifact.sha256;
8239
+ metric.artifact_screenshot = {
8240
+ name: artifact.name || artifactBasename(artifact.path || filename),
8241
+ path: artifact.path,
8242
+ url: artifact.url,
8243
+ kind: artifact.kind,
8244
+ sha256: artifact.sha256
8245
+ };
8246
+ return artifact.sha256;
8247
+ }
8248
+ function routeArtifactSlug(routeEvidence, routeContract) {
8249
+ return slug(routeContract.name || routeEvidence.name || routeContract.path || routeEvidence.path || "route");
8250
+ }
8251
+ function artifactBasename(value) {
8252
+ const raw = stringValue4(value);
8253
+ if (!raw) return "";
8254
+ try {
8255
+ const url = new URL(raw);
8256
+ return url.pathname.split("/").filter(Boolean).pop() || "";
8257
+ } catch {
8258
+ return raw.split(/[\\/]/).filter(Boolean).pop() || raw;
8259
+ }
8260
+ }
8261
+ function compactCatchMetric(metric) {
8262
+ const value = metricValue(metric);
8263
+ if (!value) return null;
8264
+ return {
8265
+ phase: value.phase,
8266
+ text: value.text,
8267
+ number: value.number,
8268
+ count: value.count,
8269
+ present: value.present,
8270
+ state_path: value.state_path,
8271
+ state_call: value.state_call,
8272
+ property_path: value.property_path,
8273
+ screenshot_hash: value.screenshot_hash,
8274
+ visual_sample_hash: value.visual_sample_hash,
8275
+ viewport_screenshot_hash: value.viewport_screenshot_hash,
8276
+ artifact_screenshot_hash: value.artifact_screenshot_hash,
8277
+ dom_signature_hash: value.dom_signature_hash,
8278
+ body_text_hash: value.body_text_hash,
8279
+ first_canvas_hash: value.first_canvas_hash,
8280
+ first_canvas_visual_sample_hash: value.first_canvas_visual_sample_hash,
8281
+ visible_canvas_count: value.visible_canvas_count
8282
+ };
8283
+ }
8284
+ function slug(value) {
8285
+ return String(value || "artifact").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 96) || "artifact";
8286
+ }
7850
8287
  function countCodes(codes) {
7851
8288
  const counts = {};
7852
8289
  for (const code of codes) counts[code] = (counts[code] || 0) + 1;
@@ -7870,6 +8307,9 @@ function numericValue3(value) {
7870
8307
  }
7871
8308
  return null;
7872
8309
  }
8310
+ function stringValue4(value) {
8311
+ return typeof value === "string" && value.length ? value : null;
8312
+ }
7873
8313
  function recordValue3(value) {
7874
8314
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
7875
8315
  }
@@ -7886,6 +8326,795 @@ function parseJson2(value) {
7886
8326
  }
7887
8327
  }
7888
8328
 
8329
+ // src/profile.ts
8330
+ var RIDDLE_PROOF_PROFILE_VERSION = "riddle-proof.profile.v1";
8331
+ var RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION = "riddle-proof.profile-evidence.v1";
8332
+ var RIDDLE_PROOF_PROFILE_RESULT_VERSION = "riddle-proof.profile-result.v1";
8333
+ var RIDDLE_PROOF_PROFILE_STATUSES = [
8334
+ "passed",
8335
+ "product_regression",
8336
+ "proof_insufficient",
8337
+ "environment_blocked",
8338
+ "configuration_error",
8339
+ "needs_human_review"
8340
+ ];
8341
+ var RIDDLE_PROOF_PROFILE_CHECK_TYPES = [
8342
+ "route_loaded",
8343
+ "selector_visible",
8344
+ "selector_count_at_least",
8345
+ "text_visible",
8346
+ "text_absent",
8347
+ "no_horizontal_overflow",
8348
+ "no_mobile_horizontal_overflow",
8349
+ "no_fatal_console_errors"
8350
+ ];
8351
+ var DEFAULT_VIEWPORTS = [
8352
+ { name: "desktop", width: 1280, height: 800 }
8353
+ ];
8354
+ function isRecord2(value) {
8355
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
8356
+ }
8357
+ function stringValue5(value) {
8358
+ return typeof value === "string" && value.trim() ? value.trim() : void 0;
8359
+ }
8360
+ function numberValue3(value) {
8361
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
8362
+ }
8363
+ function jsonRecord(value) {
8364
+ if (!isRecord2(value)) return void 0;
8365
+ return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, toJsonValue(child)]));
8366
+ }
8367
+ function toJsonValue(value) {
8368
+ if (value === null || value === void 0) return null;
8369
+ if (typeof value === "string" || typeof value === "boolean") return value;
8370
+ if (typeof value === "number") return Number.isFinite(value) ? value : null;
8371
+ if (Array.isArray(value)) return value.map(toJsonValue);
8372
+ if (isRecord2(value)) return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, toJsonValue(child)]));
8373
+ return String(value);
8374
+ }
8375
+ function normalizeName(value, fallback) {
8376
+ const name = stringValue5(value) || fallback;
8377
+ return name.replace(/\s+/g, " ").trim();
8378
+ }
8379
+ function slugifyRiddleProofProfileName(value) {
8380
+ return value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80) || "profile";
8381
+ }
8382
+ function normalizeViewport(input, index) {
8383
+ if (!isRecord2(input)) throw new Error(`target.viewports[${index}] must be an object.`);
8384
+ const width = numberValue3(input.width);
8385
+ const height = numberValue3(input.height);
8386
+ if (!width || !height || width < 100 || height < 100) {
8387
+ throw new Error(`target.viewports[${index}] requires numeric width and height >= 100.`);
8388
+ }
8389
+ return {
8390
+ name: normalizeName(input.name || input.label, `viewport-${index + 1}`),
8391
+ width: Math.round(width),
8392
+ height: Math.round(height)
8393
+ };
8394
+ }
8395
+ function normalizeViewports(value) {
8396
+ if (value === void 0) return [...DEFAULT_VIEWPORTS];
8397
+ if (!Array.isArray(value) || value.length === 0) throw new Error("target.viewports must be a non-empty array.");
8398
+ return value.map(normalizeViewport);
8399
+ }
8400
+ function isSupportedCheckType(value) {
8401
+ return RIDDLE_PROOF_PROFILE_CHECK_TYPES.includes(value);
8402
+ }
8403
+ function normalizeCheck(input, index) {
8404
+ if (!isRecord2(input)) throw new Error(`checks[${index}] must be an object.`);
8405
+ const type = stringValue5(input.type);
8406
+ if (!type) throw new Error(`checks[${index}].type is required.`);
8407
+ if (!isSupportedCheckType(type)) {
8408
+ throw new Error(`checks[${index}].type ${type} is not supported. Supported checks: ${RIDDLE_PROOF_PROFILE_CHECK_TYPES.join(", ")}`);
8409
+ }
8410
+ if ((type === "selector_visible" || type === "selector_count_at_least") && !stringValue5(input.selector)) {
8411
+ throw new Error(`checks[${index}] ${type} requires selector.`);
8412
+ }
8413
+ if ((type === "text_visible" || type === "text_absent") && !stringValue5(input.text) && !stringValue5(input.pattern)) {
8414
+ throw new Error(`checks[${index}] ${type} requires text or pattern.`);
8415
+ }
8416
+ if (type === "selector_count_at_least" && numberValue3(input.min_count) === void 0) {
8417
+ throw new Error(`checks[${index}] selector_count_at_least requires min_count.`);
8418
+ }
8419
+ return {
8420
+ type,
8421
+ label: stringValue5(input.label),
8422
+ expected_path: stringValue5(input.expected_path),
8423
+ selector: stringValue5(input.selector),
8424
+ text: stringValue5(input.text),
8425
+ pattern: stringValue5(input.pattern),
8426
+ flags: stringValue5(input.flags),
8427
+ min_count: numberValue3(input.min_count),
8428
+ max_overflow_px: numberValue3(input.max_overflow_px)
8429
+ };
8430
+ }
8431
+ function normalizeFailurePolicy(input) {
8432
+ const defaults = {
8433
+ product_regression: "fail",
8434
+ proof_insufficient: "fail",
8435
+ environment_blocked: "neutral",
8436
+ configuration_error: "fail",
8437
+ needs_human_review: "fail"
8438
+ };
8439
+ if (!isRecord2(input)) return defaults;
8440
+ const next = { ...defaults };
8441
+ for (const [key, value] of Object.entries(input)) {
8442
+ if (!RIDDLE_PROOF_PROFILE_STATUSES.includes(key)) continue;
8443
+ if (value === "fail" || value === "neutral" || value === "review") {
8444
+ next[key] = value;
8445
+ }
8446
+ }
8447
+ return next;
8448
+ }
8449
+ function normalizeRiddleProofProfile(input, options = {}) {
8450
+ if (!isRecord2(input)) throw new Error("profile must be a JSON object.");
8451
+ const version = stringValue5(input.version) || RIDDLE_PROOF_PROFILE_VERSION;
8452
+ if (version !== RIDDLE_PROOF_PROFILE_VERSION) {
8453
+ throw new Error(`Unsupported profile version ${version}. Expected ${RIDDLE_PROOF_PROFILE_VERSION}.`);
8454
+ }
8455
+ const targetInput = isRecord2(input.target) ? input.target : {};
8456
+ const checks = Array.isArray(input.checks) ? input.checks.map(normalizeCheck) : [];
8457
+ if (!checks.length) throw new Error("profile.checks must contain at least one check.");
8458
+ const targetUrl = stringValue5(options.url) || stringValue5(targetInput.url);
8459
+ const route = stringValue5(options.route) || stringValue5(targetInput.route);
8460
+ if (!targetUrl && !route) throw new Error("profile.target requires url or route, or pass --url.");
8461
+ return {
8462
+ version: RIDDLE_PROOF_PROFILE_VERSION,
8463
+ name: normalizeName(input.name, "riddle-proof-profile"),
8464
+ target: {
8465
+ url: targetUrl,
8466
+ route,
8467
+ viewports: options.viewports?.length ? options.viewports : normalizeViewports(targetInput.viewports),
8468
+ auth: stringValue5(targetInput.auth) || "none",
8469
+ wait_for_selector: stringValue5(targetInput.wait_for_selector) || stringValue5(targetInput.waitForSelector),
8470
+ wait_ms: numberValue3(targetInput.wait_ms) ?? numberValue3(targetInput.waitMs)
8471
+ },
8472
+ checks,
8473
+ artifacts: Array.isArray(input.artifacts) ? input.artifacts.map((item) => String(item)).filter(Boolean) : ["screenshot", "console", "dom_summary", "proof_json"],
8474
+ baseline_policy: stringValue5(input.baseline_policy) || stringValue5(input.baselinePolicy) || "invariant_only",
8475
+ failure_policy: normalizeFailurePolicy(input.failure_policy || input.failurePolicy),
8476
+ metadata: jsonRecord(input.metadata)
8477
+ };
8478
+ }
8479
+ function resolveRiddleProofProfileTargetUrl(profile) {
8480
+ const route = profile.target.route || "";
8481
+ const targetUrl = profile.target.url || "";
8482
+ if (/^https?:\/\//i.test(route)) return route;
8483
+ if (targetUrl && route) return new URL(route, targetUrl).href;
8484
+ if (targetUrl) return targetUrl;
8485
+ throw new Error("profile target URL could not be resolved.");
8486
+ }
8487
+ function routeForViewport(viewport) {
8488
+ return viewport?.route || {
8489
+ requested: "",
8490
+ observed: "",
8491
+ matched: false,
8492
+ error: "missing viewport evidence"
8493
+ };
8494
+ }
8495
+ function checkLabel(check) {
8496
+ return check.label || check.type;
8497
+ }
8498
+ function selectorKey(check) {
8499
+ return check.selector || "";
8500
+ }
8501
+ function textKey(check) {
8502
+ return check.pattern ? `pattern:${check.pattern}/${check.flags || ""}` : `text:${check.text || ""}`;
8503
+ }
8504
+ function matchText(sample, check) {
8505
+ if (check.pattern) {
8506
+ try {
8507
+ return new RegExp(check.pattern, check.flags || "").test(sample);
8508
+ } catch {
8509
+ return false;
8510
+ }
8511
+ }
8512
+ return sample.includes(check.text || "");
8513
+ }
8514
+ function successfulRoute(route) {
8515
+ return route.matched && !route.error && (route.http_status === null || route.http_status === void 0 || route.http_status < 400);
8516
+ }
8517
+ function assessCheckFromEvidence(check, evidence) {
8518
+ const viewports = evidence.viewports || [];
8519
+ if (!viewports.length) {
8520
+ return {
8521
+ type: check.type,
8522
+ label: checkLabel(check),
8523
+ status: "failed",
8524
+ evidence: {},
8525
+ message: "No viewport evidence was captured."
8526
+ };
8527
+ }
8528
+ if (check.type === "route_loaded") {
8529
+ const expectedPath = check.expected_path || new URL(evidence.target_url).pathname || "/";
8530
+ const failed = viewports.filter((viewport) => !successfulRoute({
8531
+ ...viewport.route,
8532
+ expected_path: expectedPath,
8533
+ matched: viewport.route.observed === expectedPath || viewport.route.matched
8534
+ }));
8535
+ return {
8536
+ type: check.type,
8537
+ label: checkLabel(check),
8538
+ status: failed.length ? "failed" : "passed",
8539
+ evidence: {
8540
+ expected_path: expectedPath,
8541
+ observed_paths: viewports.map((viewport) => viewport.route.observed),
8542
+ http_statuses: viewports.map((viewport) => viewport.route.http_status ?? null)
8543
+ },
8544
+ message: failed.length ? `Route did not load as ${expectedPath} in ${failed.length} viewport(s).` : void 0
8545
+ };
8546
+ }
8547
+ if (check.type === "selector_visible") {
8548
+ const key = selectorKey(check);
8549
+ const failed = viewports.filter((viewport) => (viewport.selectors?.[key]?.visible_count || 0) < 1);
8550
+ return {
8551
+ type: check.type,
8552
+ label: checkLabel(check),
8553
+ status: failed.length ? "failed" : "passed",
8554
+ evidence: {
8555
+ selector: key,
8556
+ visible_counts: viewports.map((viewport) => viewport.selectors?.[key]?.visible_count || 0)
8557
+ },
8558
+ message: failed.length ? `Selector ${key} was not visible in ${failed.length} viewport(s).` : void 0
8559
+ };
8560
+ }
8561
+ if (check.type === "selector_count_at_least") {
8562
+ const key = selectorKey(check);
8563
+ const minCount = check.min_count ?? 1;
8564
+ const failed = viewports.filter((viewport) => (viewport.selectors?.[key]?.count || 0) < minCount);
8565
+ return {
8566
+ type: check.type,
8567
+ label: checkLabel(check),
8568
+ status: failed.length ? "failed" : "passed",
8569
+ evidence: {
8570
+ selector: key,
8571
+ min_count: minCount,
8572
+ counts: viewports.map((viewport) => viewport.selectors?.[key]?.count || 0)
8573
+ },
8574
+ message: failed.length ? `Selector ${key} count was below ${minCount} in ${failed.length} viewport(s).` : void 0
8575
+ };
8576
+ }
8577
+ if (check.type === "text_visible" || check.type === "text_absent") {
8578
+ const key = textKey(check);
8579
+ const expectedVisible = check.type === "text_visible";
8580
+ const matches = viewports.map((viewport) => {
8581
+ const fromEvidence = viewport.text_matches?.[key];
8582
+ return typeof fromEvidence === "boolean" ? fromEvidence : matchText(viewport.body_text_sample || "", check);
8583
+ });
8584
+ const failed = matches.filter((matched) => matched !== expectedVisible).length;
8585
+ return {
8586
+ type: check.type,
8587
+ label: checkLabel(check),
8588
+ status: failed ? "failed" : "passed",
8589
+ evidence: {
8590
+ text: check.text || null,
8591
+ pattern: check.pattern || null,
8592
+ matches
8593
+ },
8594
+ message: failed ? `Text assertion failed in ${failed} viewport(s).` : void 0
8595
+ };
8596
+ }
8597
+ if (check.type === "no_horizontal_overflow" || check.type === "no_mobile_horizontal_overflow") {
8598
+ const maxOverflow = check.max_overflow_px ?? 4;
8599
+ const applicable = check.type === "no_mobile_horizontal_overflow" ? viewports.filter((viewport) => viewport.width <= 820) : viewports;
8600
+ if (!applicable.length) {
8601
+ return {
8602
+ type: check.type,
8603
+ label: checkLabel(check),
8604
+ status: "failed",
8605
+ evidence: { max_overflow_px: maxOverflow },
8606
+ message: "No applicable viewport evidence was captured for overflow check."
8607
+ };
8608
+ }
8609
+ const failed = applicable.filter((viewport) => (viewport.overflow_px ?? 0) > maxOverflow);
8610
+ return {
8611
+ type: check.type,
8612
+ label: checkLabel(check),
8613
+ status: failed.length ? "failed" : "passed",
8614
+ evidence: {
8615
+ max_overflow_px: maxOverflow,
8616
+ overflow_px: applicable.map((viewport) => viewport.overflow_px ?? null),
8617
+ viewports: applicable.map((viewport) => viewport.name)
8618
+ },
8619
+ message: failed.length ? `Horizontal overflow exceeded ${maxOverflow}px in ${failed.length} viewport(s).` : void 0
8620
+ };
8621
+ }
8622
+ if (check.type === "no_fatal_console_errors") {
8623
+ const fatalCount = (evidence.console?.fatal_count || 0) + (evidence.page_errors?.length || 0);
8624
+ return {
8625
+ type: check.type,
8626
+ label: checkLabel(check),
8627
+ status: fatalCount ? "failed" : "passed",
8628
+ evidence: {
8629
+ console_fatal_count: evidence.console?.fatal_count || 0,
8630
+ page_error_count: evidence.page_errors?.length || 0
8631
+ },
8632
+ message: fatalCount ? `${fatalCount} fatal browser error(s) were captured.` : void 0
8633
+ };
8634
+ }
8635
+ return {
8636
+ type: check.type,
8637
+ label: checkLabel(check),
8638
+ status: "needs_human_review",
8639
+ evidence: {},
8640
+ message: "Unsupported check type."
8641
+ };
8642
+ }
8643
+ function profileStatusFromEvidence(evidence, checks) {
8644
+ if (!evidence) return "proof_insufficient";
8645
+ const viewports = evidence.viewports || [];
8646
+ if (!viewports.length || !checks.length) return "proof_insufficient";
8647
+ if (viewports.some((viewport) => viewport.navigation_error)) return "environment_blocked";
8648
+ if (checks.some((check) => check.status === "needs_human_review")) return "needs_human_review";
8649
+ if (checks.some((check) => check.status === "failed")) return "product_regression";
8650
+ return "passed";
8651
+ }
8652
+ function assessRiddleProofProfileEvidence(profile, evidence, options = {}) {
8653
+ const capturedAt = evidence?.captured_at || (/* @__PURE__ */ new Date()).toISOString();
8654
+ const checks = evidence ? profile.checks.map((check) => assessCheckFromEvidence(check, evidence)) : [];
8655
+ const status = profileStatusFromEvidence(evidence, checks);
8656
+ const firstViewport = evidence?.viewports?.[0];
8657
+ const screenshots = (evidence?.viewports || []).map((viewport) => viewport.screenshot_label).filter((label) => Boolean(label));
8658
+ return {
8659
+ version: RIDDLE_PROOF_PROFILE_RESULT_VERSION,
8660
+ profile_name: profile.name,
8661
+ runner: options.runner || "riddle",
8662
+ status,
8663
+ baseline_policy: profile.baseline_policy,
8664
+ route: routeForViewport(firstViewport),
8665
+ artifacts: {
8666
+ screenshots,
8667
+ console: "console.json",
8668
+ proof_json: "proof.json",
8669
+ dom_summary: "dom-summary.json",
8670
+ riddle_artifacts: options.artifacts
8671
+ },
8672
+ checks,
8673
+ summary: summarizeRiddleProofProfileResult({ profile_name: profile.name, status, checks, viewports: evidence?.viewports || [] }),
8674
+ captured_at: capturedAt,
8675
+ evidence,
8676
+ riddle: options.riddle
8677
+ };
8678
+ }
8679
+ function summarizeRiddleProofProfileResult(input) {
8680
+ const passedChecks = input.checks.filter((check) => check.status === "passed").length;
8681
+ const failedChecks = input.checks.filter((check) => check.status === "failed").length;
8682
+ const viewportNames = input.viewports.map((viewport) => viewport.name).join(", ");
8683
+ if (input.status === "passed") {
8684
+ return `${input.profile_name} passed ${passedChecks} check(s) across ${input.viewports.length} viewport(s)${viewportNames ? ` (${viewportNames})` : ""}.`;
8685
+ }
8686
+ if (input.status === "product_regression") {
8687
+ return `${input.profile_name} failed ${failedChecks} product invariant(s) across ${input.viewports.length} viewport(s).`;
8688
+ }
8689
+ if (input.status === "environment_blocked") {
8690
+ return `${input.profile_name} could not collect reliable evidence because navigation or the browser environment was blocked.`;
8691
+ }
8692
+ if (input.status === "proof_insufficient") {
8693
+ return `${input.profile_name} did not produce enough evidence for a profile judgment.`;
8694
+ }
8695
+ if (input.status === "configuration_error") {
8696
+ return `${input.profile_name} has a profile configuration error.`;
8697
+ }
8698
+ return `${input.profile_name} collected artifacts but needs human review.`;
8699
+ }
8700
+ function profileStatusExitCode(profile, status) {
8701
+ if (status === "passed") return 0;
8702
+ return profile.failure_policy[status] === "neutral" ? 0 : 1;
8703
+ }
8704
+ function createRiddleProofProfileConfigurationError(name, error, runner = "riddle") {
8705
+ const message = error instanceof Error ? error.message : String(error);
8706
+ return {
8707
+ version: RIDDLE_PROOF_PROFILE_RESULT_VERSION,
8708
+ profile_name: name,
8709
+ runner,
8710
+ status: "configuration_error",
8711
+ baseline_policy: "invariant_only",
8712
+ route: { requested: "", observed: "", matched: false, error: message },
8713
+ artifacts: { screenshots: [], proof_json: "proof.json" },
8714
+ checks: [],
8715
+ summary: `${name} has a profile configuration error.`,
8716
+ captured_at: (/* @__PURE__ */ new Date()).toISOString(),
8717
+ error: message
8718
+ };
8719
+ }
8720
+ function createRiddleProofProfileEnvironmentBlockedResult(input) {
8721
+ const message = input.error instanceof Error ? input.error.message : input.error ? String(input.error) : "Riddle runner did not complete successfully.";
8722
+ return {
8723
+ version: RIDDLE_PROOF_PROFILE_RESULT_VERSION,
8724
+ profile_name: input.profile.name,
8725
+ runner: input.runner || "riddle",
8726
+ status: "environment_blocked",
8727
+ baseline_policy: input.profile.baseline_policy,
8728
+ route: { requested: resolveRiddleProofProfileTargetUrl(input.profile), observed: "", matched: false, error: message },
8729
+ artifacts: { screenshots: [], proof_json: "proof.json", riddle_artifacts: input.artifacts },
8730
+ checks: [],
8731
+ summary: `${input.profile.name} could not collect reliable evidence because the runner was blocked.`,
8732
+ captured_at: (/* @__PURE__ */ new Date()).toISOString(),
8733
+ riddle: input.riddle,
8734
+ error: message
8735
+ };
8736
+ }
8737
+ function createRiddleProofProfileInsufficientResult(input) {
8738
+ const message = input.error instanceof Error ? input.error.message : input.error ? String(input.error) : "No proof.json profile result artifact was found.";
8739
+ return {
8740
+ version: RIDDLE_PROOF_PROFILE_RESULT_VERSION,
8741
+ profile_name: input.profile.name,
8742
+ runner: input.runner || "riddle",
8743
+ status: "proof_insufficient",
8744
+ baseline_policy: input.profile.baseline_policy,
8745
+ route: { requested: resolveRiddleProofProfileTargetUrl(input.profile), observed: "", matched: false, error: message },
8746
+ artifacts: { screenshots: [], proof_json: "proof.json", riddle_artifacts: input.artifacts },
8747
+ checks: [],
8748
+ summary: `${input.profile.name} did not produce enough evidence for a profile judgment.`,
8749
+ captured_at: (/* @__PURE__ */ new Date()).toISOString(),
8750
+ riddle: input.riddle,
8751
+ error: message
8752
+ };
8753
+ }
8754
+ function runtimeScriptAssessmentSource() {
8755
+ return String.raw`
8756
+ function routeOk(route) {
8757
+ return Boolean(route && route.matched && !route.error && (route.http_status == null || route.http_status < 400));
8758
+ }
8759
+ function textMatches(sample, check) {
8760
+ if (check.pattern) {
8761
+ try { return new RegExp(check.pattern, check.flags || "").test(sample || ""); } catch { return false; }
8762
+ }
8763
+ return String(sample || "").includes(check.text || "");
8764
+ }
8765
+ function assessProfile(profile, evidence) {
8766
+ const checks = [];
8767
+ const viewports = evidence.viewports || [];
8768
+ for (const check of profile.checks || []) {
8769
+ if (check.type === "route_loaded") {
8770
+ const expectedPath = check.expected_path || new URL(evidence.target_url).pathname || "/";
8771
+ const failed = viewports.filter((viewport) => {
8772
+ const route = { ...(viewport.route || {}), expected_path: expectedPath };
8773
+ route.matched = route.observed === expectedPath || route.matched;
8774
+ return !routeOk(route);
8775
+ });
8776
+ checks.push({
8777
+ type: check.type,
8778
+ label: check.label || check.type,
8779
+ status: failed.length ? "failed" : "passed",
8780
+ evidence: {
8781
+ expected_path: expectedPath,
8782
+ observed_paths: viewports.map((viewport) => viewport.route && viewport.route.observed),
8783
+ http_statuses: viewports.map((viewport) => viewport.route ? viewport.route.http_status ?? null : null),
8784
+ },
8785
+ message: failed.length ? "Route did not load as " + expectedPath + " in " + failed.length + " viewport(s)." : undefined,
8786
+ });
8787
+ continue;
8788
+ }
8789
+ if (check.type === "selector_visible") {
8790
+ const selector = check.selector || "";
8791
+ const failed = viewports.filter((viewport) => !viewport.selectors || !viewport.selectors[selector] || viewport.selectors[selector].visible_count < 1);
8792
+ checks.push({
8793
+ type: check.type,
8794
+ label: check.label || check.type,
8795
+ status: failed.length ? "failed" : "passed",
8796
+ evidence: { selector, visible_counts: viewports.map((viewport) => viewport.selectors && viewport.selectors[selector] ? viewport.selectors[selector].visible_count : 0) },
8797
+ message: failed.length ? "Selector " + selector + " was not visible in " + failed.length + " viewport(s)." : undefined,
8798
+ });
8799
+ continue;
8800
+ }
8801
+ if (check.type === "selector_count_at_least") {
8802
+ const selector = check.selector || "";
8803
+ const minCount = check.min_count == null ? 1 : check.min_count;
8804
+ const failed = viewports.filter((viewport) => !viewport.selectors || !viewport.selectors[selector] || viewport.selectors[selector].count < minCount);
8805
+ checks.push({
8806
+ type: check.type,
8807
+ label: check.label || check.type,
8808
+ status: failed.length ? "failed" : "passed",
8809
+ evidence: { selector, min_count: minCount, counts: viewports.map((viewport) => viewport.selectors && viewport.selectors[selector] ? viewport.selectors[selector].count : 0) },
8810
+ message: failed.length ? "Selector " + selector + " count was below " + minCount + " in " + failed.length + " viewport(s)." : undefined,
8811
+ });
8812
+ continue;
8813
+ }
8814
+ if (check.type === "text_visible" || check.type === "text_absent") {
8815
+ const key = check.pattern ? "pattern:" + check.pattern + "/" + (check.flags || "") : "text:" + (check.text || "");
8816
+ const expectedVisible = check.type === "text_visible";
8817
+ const matches = viewports.map((viewport) => viewport.text_matches && typeof viewport.text_matches[key] === "boolean" ? viewport.text_matches[key] : textMatches(viewport.body_text_sample || "", check));
8818
+ const failed = matches.filter((matched) => matched !== expectedVisible).length;
8819
+ checks.push({
8820
+ type: check.type,
8821
+ label: check.label || check.type,
8822
+ status: failed ? "failed" : "passed",
8823
+ evidence: { text: check.text, pattern: check.pattern, matches },
8824
+ message: failed ? "Text assertion failed in " + failed + " viewport(s)." : undefined,
8825
+ });
8826
+ continue;
8827
+ }
8828
+ if (check.type === "no_horizontal_overflow" || check.type === "no_mobile_horizontal_overflow") {
8829
+ const maxOverflow = check.max_overflow_px == null ? 4 : check.max_overflow_px;
8830
+ const applicable = check.type === "no_mobile_horizontal_overflow" ? viewports.filter((viewport) => viewport.width <= 820) : viewports;
8831
+ if (!applicable.length) {
8832
+ checks.push({
8833
+ type: check.type,
8834
+ label: check.label || check.type,
8835
+ status: "failed",
8836
+ evidence: { max_overflow_px: maxOverflow },
8837
+ message: "No applicable viewport evidence was captured for overflow check.",
8838
+ });
8839
+ continue;
8840
+ }
8841
+ const failed = applicable.filter((viewport) => (viewport.overflow_px || 0) > maxOverflow);
8842
+ checks.push({
8843
+ type: check.type,
8844
+ label: check.label || check.type,
8845
+ status: failed.length ? "failed" : "passed",
8846
+ evidence: { max_overflow_px: maxOverflow, overflow_px: applicable.map((viewport) => viewport.overflow_px ?? null), viewports: applicable.map((viewport) => viewport.name) },
8847
+ message: failed.length ? "Horizontal overflow exceeded " + maxOverflow + "px in " + failed.length + " viewport(s)." : undefined,
8848
+ });
8849
+ continue;
8850
+ }
8851
+ if (check.type === "no_fatal_console_errors") {
8852
+ const fatalCount = ((evidence.console && evidence.console.fatal_count) || 0) + ((evidence.page_errors || []).length);
8853
+ checks.push({
8854
+ type: check.type,
8855
+ label: check.label || check.type,
8856
+ status: fatalCount ? "failed" : "passed",
8857
+ evidence: { console_fatal_count: (evidence.console && evidence.console.fatal_count) || 0, page_error_count: (evidence.page_errors || []).length },
8858
+ message: fatalCount ? String(fatalCount) + " fatal browser error(s) were captured." : undefined,
8859
+ });
8860
+ continue;
8861
+ }
8862
+ checks.push({ type: check.type, label: check.label || check.type, status: "needs_human_review", evidence: {}, message: "Unsupported check type." });
8863
+ }
8864
+ let status = "passed";
8865
+ if (!viewports.length || !checks.length) status = "proof_insufficient";
8866
+ else if (viewports.some((viewport) => viewport.navigation_error)) status = "environment_blocked";
8867
+ else if (checks.some((check) => check.status === "needs_human_review")) status = "needs_human_review";
8868
+ else if (checks.some((check) => check.status === "failed")) status = "product_regression";
8869
+ const screenshotLabels = viewports.map((viewport) => viewport.screenshot_label).filter(Boolean);
8870
+ const route = viewports[0] && viewports[0].route ? viewports[0].route : { requested: evidence.target_url, observed: "", matched: false, error: "missing viewport evidence" };
8871
+ const passedChecks = checks.filter((check) => check.status === "passed").length;
8872
+ const failedChecks = checks.filter((check) => check.status === "failed").length;
8873
+ const viewportNames = viewports.map((viewport) => viewport.name).join(", ");
8874
+ let summary = profile.name + " collected artifacts but needs human review.";
8875
+ if (status === "passed") summary = profile.name + " passed " + passedChecks + " check(s) across " + viewports.length + " viewport(s)" + (viewportNames ? " (" + viewportNames + ")." : ".");
8876
+ if (status === "product_regression") summary = profile.name + " failed " + failedChecks + " product invariant(s) across " + viewports.length + " viewport(s).";
8877
+ if (status === "environment_blocked") summary = profile.name + " could not collect reliable evidence because navigation or the browser environment was blocked.";
8878
+ if (status === "proof_insufficient") summary = profile.name + " did not produce enough evidence for a profile judgment.";
8879
+ return {
8880
+ version: "riddle-proof.profile-result.v1",
8881
+ profile_name: profile.name,
8882
+ runner: "riddle",
8883
+ status,
8884
+ baseline_policy: profile.baseline_policy || "invariant_only",
8885
+ route,
8886
+ artifacts: { screenshots: screenshotLabels, console: "console.json", proof_json: "proof.json", dom_summary: "dom-summary.json" },
8887
+ checks,
8888
+ summary,
8889
+ captured_at: evidence.captured_at,
8890
+ evidence,
8891
+ };
8892
+ }
8893
+ `;
8894
+ }
8895
+ function buildRiddleProofProfileScript(profile) {
8896
+ const targetUrl = resolveRiddleProofProfileTargetUrl(profile);
8897
+ const slug2 = slugifyRiddleProofProfileName(profile.name);
8898
+ const serializableProfile = JSON.stringify(profile);
8899
+ const serializableTargetUrl = JSON.stringify(targetUrl);
8900
+ const serializableSlug = JSON.stringify(slug2);
8901
+ return String.raw`
8902
+ const profile = ${serializableProfile};
8903
+ const targetUrl = ${serializableTargetUrl};
8904
+ const profileSlug = ${serializableSlug};
8905
+ const capturedAt = new Date().toISOString();
8906
+ const consoleEvents = [];
8907
+ const pageErrors = [];
8908
+ page.on("console", (message) => {
8909
+ const type = message.type();
8910
+ if (type === "error" || type === "warning" || type === "assert") {
8911
+ consoleEvents.push({
8912
+ type,
8913
+ text: message.text().slice(0, 1000),
8914
+ location: message.location ? message.location() : undefined,
8915
+ });
8916
+ }
8917
+ });
8918
+ page.on("pageerror", (error) => {
8919
+ pageErrors.push({ message: String(error && error.message ? error.message : error).slice(0, 1000) });
8920
+ });
8921
+ function textKey(check) {
8922
+ return check.pattern ? "pattern:" + check.pattern + "/" + (check.flags || "") : "text:" + (check.text || "");
8923
+ }
8924
+ function textMatches(sample, check) {
8925
+ if (check.pattern) {
8926
+ try { return new RegExp(check.pattern, check.flags || "").test(sample || ""); } catch { return false; }
8927
+ }
8928
+ return String(sample || "").includes(check.text || "");
8929
+ }
8930
+ function expectedPathFor(check) {
8931
+ return check.expected_path || new URL(targetUrl).pathname || "/";
8932
+ }
8933
+ async function selectorStats(selector) {
8934
+ return page.locator(selector).evaluateAll((elements) => {
8935
+ const isVisible = (element) => {
8936
+ const style = window.getComputedStyle(element);
8937
+ const rect = element.getBoundingClientRect();
8938
+ return style && style.visibility !== "hidden" && style.display !== "none" && rect.width > 0 && rect.height > 0;
8939
+ };
8940
+ return { count: elements.length, visible_count: elements.filter(isVisible).length };
8941
+ }).catch((error) => ({ count: 0, visible_count: 0, error: String(error && error.message ? error.message : error).slice(0, 500) }));
8942
+ }
8943
+ async function captureViewport(viewport) {
8944
+ await page.setViewportSize({ width: viewport.width, height: viewport.height });
8945
+ let httpStatus = null;
8946
+ let navigationError;
8947
+ let waitError;
8948
+ try {
8949
+ const response = await page.goto(targetUrl, { waitUntil: "domcontentloaded", timeout: 45000 });
8950
+ httpStatus = response ? response.status() : null;
8951
+ } catch (error) {
8952
+ navigationError = String(error && error.message ? error.message : error).slice(0, 1000);
8953
+ }
8954
+ if (!navigationError && profile.target.wait_for_selector) {
8955
+ try {
8956
+ await page.waitForSelector(profile.target.wait_for_selector, { state: "visible", timeout: 15000 });
8957
+ } catch (error) {
8958
+ waitError = String(error && error.message ? error.message : error).slice(0, 1000);
8959
+ }
8960
+ }
8961
+ if (!navigationError && profile.target.wait_ms) {
8962
+ await page.waitForTimeout(profile.target.wait_ms);
8963
+ }
8964
+ const dom = await page.evaluate(() => {
8965
+ const body = document.body;
8966
+ const documentElement = document.documentElement;
8967
+ const text = (body ? body.innerText : "").replace(/\s+/g, " ").trim();
8968
+ return {
8969
+ url: location.href,
8970
+ pathname: location.pathname,
8971
+ title: document.title,
8972
+ body_text_length: text.length,
8973
+ body_text_sample: text.slice(0, 8000),
8974
+ scroll_width: documentElement ? documentElement.scrollWidth : 0,
8975
+ client_width: documentElement ? documentElement.clientWidth : window.innerWidth,
8976
+ };
8977
+ }).catch((error) => ({
8978
+ url: page.url(),
8979
+ pathname: "",
8980
+ title: "",
8981
+ body_text_length: 0,
8982
+ body_text_sample: "",
8983
+ scroll_width: 0,
8984
+ client_width: viewport.width,
8985
+ evaluation_error: String(error && error.message ? error.message : error).slice(0, 1000),
8986
+ }));
8987
+ const selectors = {};
8988
+ const text_matches = {};
8989
+ for (const check of profile.checks || []) {
8990
+ if ((check.type === "selector_visible" || check.type === "selector_count_at_least") && check.selector) {
8991
+ selectors[check.selector] = await selectorStats(check.selector);
8992
+ }
8993
+ if ((check.type === "text_visible" || check.type === "text_absent") && (check.text || check.pattern)) {
8994
+ text_matches[textKey(check)] = textMatches(dom.body_text_sample || "", check);
8995
+ }
8996
+ }
8997
+ const screenshotLabel = profileSlug + "-" + viewport.name;
8998
+ try {
8999
+ if (typeof saveScreenshot === "function") await saveScreenshot(screenshotLabel);
9000
+ } catch (error) {
9001
+ pageErrors.push({ message: "saveScreenshot failed: " + String(error && error.message ? error.message : error).slice(0, 500) });
9002
+ }
9003
+ const expectedPath = profile.checks.find((check) => check.type === "route_loaded" && check.expected_path)?.expected_path || new URL(targetUrl).pathname || "/";
9004
+ return {
9005
+ name: viewport.name,
9006
+ width: viewport.width,
9007
+ height: viewport.height,
9008
+ url: dom.url,
9009
+ route: {
9010
+ requested: targetUrl,
9011
+ observed: dom.pathname,
9012
+ expected_path: expectedPath,
9013
+ matched: dom.pathname === expectedPath,
9014
+ http_status: httpStatus,
9015
+ error: navigationError || waitError || undefined,
9016
+ },
9017
+ title: dom.title,
9018
+ body_text_length: dom.body_text_length,
9019
+ body_text_sample: dom.body_text_sample,
9020
+ scroll_width: dom.scroll_width,
9021
+ client_width: dom.client_width,
9022
+ overflow_px: Math.max(0, (dom.scroll_width || 0) - (dom.client_width || viewport.width)),
9023
+ selectors,
9024
+ text_matches,
9025
+ screenshot_label: screenshotLabel,
9026
+ navigation_error: navigationError,
9027
+ wait_error: waitError,
9028
+ };
9029
+ }
9030
+ ${runtimeScriptAssessmentSource()}
9031
+ const viewports = [];
9032
+ for (const viewport of profile.target.viewports || []) {
9033
+ viewports.push(await captureViewport(viewport));
9034
+ }
9035
+ const evidence = {
9036
+ version: "riddle-proof.profile-evidence.v1",
9037
+ profile_name: profile.name,
9038
+ target_url: targetUrl,
9039
+ baseline_policy: profile.baseline_policy || "invariant_only",
9040
+ captured_at: capturedAt,
9041
+ viewports,
9042
+ console: {
9043
+ events: consoleEvents,
9044
+ fatal_count: consoleEvents.filter((event) => event.type === "error" || event.type === "assert").length,
9045
+ },
9046
+ page_errors: pageErrors,
9047
+ dom_summary: {
9048
+ viewport_count: viewports.length,
9049
+ routes: viewports.map((viewport) => viewport.route),
9050
+ titles: viewports.map((viewport) => viewport.title),
9051
+ overflow_px: viewports.map((viewport) => viewport.overflow_px),
9052
+ },
9053
+ };
9054
+ const result = assessProfile(profile, evidence);
9055
+ if (typeof saveJson === "function") {
9056
+ await saveJson("proof.json", result);
9057
+ await saveJson("console.json", { events: consoleEvents, page_errors: pageErrors });
9058
+ await saveJson("dom-summary.json", evidence.dom_summary);
9059
+ }
9060
+ return result;
9061
+ `.trim();
9062
+ }
9063
+ function collectRiddleProfileArtifactRefs(input) {
9064
+ const refs = [];
9065
+ const seen = /* @__PURE__ */ new Set();
9066
+ function add(item, source) {
9067
+ if (!isRecord2(item)) return;
9068
+ const name = stringValue5(item.name) || stringValue5(item.filename) || "";
9069
+ const url = stringValue5(item.url);
9070
+ const path6 = stringValue5(item.path);
9071
+ if (!name && !url && !path6) return;
9072
+ const key = `${name}:${url || path6 || ""}`;
9073
+ if (seen.has(key)) return;
9074
+ seen.add(key);
9075
+ refs.push({
9076
+ name,
9077
+ url,
9078
+ path: path6,
9079
+ kind: stringValue5(item.kind) || stringValue5(item.type),
9080
+ content_type: stringValue5(item.content_type) || stringValue5(item.contentType),
9081
+ source
9082
+ });
9083
+ }
9084
+ function visit(value, source) {
9085
+ if (Array.isArray(value)) {
9086
+ for (const item of value) add(item, source);
9087
+ return;
9088
+ }
9089
+ if (!isRecord2(value)) return;
9090
+ for (const key of ["artifacts", "outputs", "screenshots", "files"]) {
9091
+ if (Array.isArray(value[key])) visit(value[key], key);
9092
+ }
9093
+ }
9094
+ visit(input, "artifacts");
9095
+ return refs;
9096
+ }
9097
+ function extractRiddleProofProfileResult(input) {
9098
+ if (!isRecord2(input)) return void 0;
9099
+ if (input.version === RIDDLE_PROOF_PROFILE_RESULT_VERSION) return input;
9100
+ const candidates = [
9101
+ input.result,
9102
+ input.return_value,
9103
+ input.value,
9104
+ input.profile_result,
9105
+ isRecord2(input["proof.json"]) ? input["proof.json"] : void 0,
9106
+ isRecord2(input._proof_json) ? input._proof_json : void 0
9107
+ ];
9108
+ for (const candidate of candidates) {
9109
+ const result = extractRiddleProofProfileResult(candidate);
9110
+ if (result) return result;
9111
+ }
9112
+ if (isRecord2(input._artifact_json)) {
9113
+ return extractRiddleProofProfileResult(input._artifact_json["proof.json"]);
9114
+ }
9115
+ return void 0;
9116
+ }
9117
+
7889
9118
  // src/riddle-client.ts
7890
9119
  var import_node_child_process4 = require("child_process");
7891
9120
  var import_node_fs5 = require("fs");
@@ -8120,6 +9349,8 @@ function createRiddleApiClient(config = {}) {
8120
9349
  }
8121
9350
  // Annotate the CommonJS export names for ESM import in node:
8122
9351
  0 && (module.exports = {
9352
+ BASIC_GAMEPLAY_ACTION_TYPES,
9353
+ BASIC_GAMEPLAY_PROGRESS_CHECK_TYPES,
8123
9354
  DEFAULT_DIAGNOSTIC_ARRAY_LIMIT,
8124
9355
  DEFAULT_DIAGNOSTIC_HISTORY_LIMIT,
8125
9356
  DEFAULT_DIAGNOSTIC_STRING_LIMIT,
@@ -8133,6 +9364,11 @@ function createRiddleApiClient(config = {}) {
8133
9364
  RIDDLE_PROOF_CHECKPOINT_RESPONSE_VERSION,
8134
9365
  RIDDLE_PROOF_PLAYABILITY_ASSESSMENT_VERSION,
8135
9366
  RIDDLE_PROOF_PLAYABILITY_VERSION,
9367
+ RIDDLE_PROOF_PROFILE_CHECK_TYPES,
9368
+ RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION,
9369
+ RIDDLE_PROOF_PROFILE_RESULT_VERSION,
9370
+ RIDDLE_PROOF_PROFILE_STATUSES,
9371
+ RIDDLE_PROOF_PROFILE_VERSION,
8136
9372
  RIDDLE_PROOF_RUN_CARD_VERSION,
8137
9373
  RIDDLE_PROOF_RUN_STATE_VERSION,
8138
9374
  RIDDLE_PROOF_VISUAL_SESSION_FINGERPRINT_VERSION,
@@ -8144,18 +9380,27 @@ function createRiddleApiClient(config = {}) {
8144
9380
  applyPrLifecycleState,
8145
9381
  applyTerminalMetadata,
8146
9382
  assessBasicGameplayEvidence,
9383
+ assessBasicGameplayProgressionCheck,
9384
+ assessBasicGameplayProgressionChecks,
8147
9385
  assessBasicGameplayRoute,
8148
9386
  assessPlayabilityEvidence,
9387
+ assessRiddleProofProfileEvidence,
9388
+ attachBasicGameplayArtifactScreenshotHashes,
9389
+ augmentBasicGameplayAssessmentWithProgressionChecks,
8149
9390
  authorPacketPayloadFromCheckpointResponse,
8150
9391
  buildAuthorCheckpointPacket,
8151
9392
  buildCheckpointPacketForEngineResult,
8152
9393
  buildProofAssessmentCheckpointPacket,
9394
+ buildRiddleProofProfileScript,
8153
9395
  buildStageCheckpointPacket,
8154
9396
  buildVisualProofSession,
8155
9397
  checkpointResponseIdentity,
8156
9398
  checkpointSummaryFromState,
9399
+ collectRiddleProfileArtifactRefs,
9400
+ compactBasicGameplayText,
8157
9401
  compactRecord,
8158
9402
  compareVisualProofSessionFingerprint,
9403
+ createBasicGameplayCatchRecords,
8159
9404
  createBasicGameplayCatchSummary,
8160
9405
  createCaptureDiagnostic,
8161
9406
  createCheckpointResponseTemplate,
@@ -8165,6 +9410,9 @@ function createRiddleApiClient(config = {}) {
8165
9410
  createLocalAgentAdapter,
8166
9411
  createLocalAgentJsonRunner,
8167
9412
  createRiddleApiClient,
9413
+ createRiddleProofProfileConfigurationError,
9414
+ createRiddleProofProfileEnvironmentBlockedResult,
9415
+ createRiddleProofProfileInsufficientResult,
8168
9416
  createRiddleProofRunCard,
8169
9417
  createRunResult,
8170
9418
  createRunState,
@@ -8172,6 +9420,7 @@ function createRiddleApiClient(config = {}) {
8172
9420
  deployRiddleStaticPreview,
8173
9421
  extractBasicGameplayEvidence,
8174
9422
  extractPlayabilityEvidence,
9423
+ extractRiddleProofProfileResult,
8175
9424
  isDuplicateCheckpointResponse,
8176
9425
  isRiddleProofPlayabilityMode,
8177
9426
  isSuccessfulStatus,
@@ -8181,16 +9430,20 @@ function createRiddleApiClient(config = {}) {
8181
9430
  normalizeCheckpointResponse,
8182
9431
  normalizeIntegrationContext,
8183
9432
  normalizePrLifecycleState,
9433
+ normalizeRiddleProofProfile,
8184
9434
  normalizeRunParams,
8185
9435
  normalizeTerminalMetadata,
8186
9436
  parseRiddleViewport,
8187
9437
  parseVisualProofSession,
8188
9438
  pollRiddleJob,
9439
+ profileStatusExitCode,
8189
9440
  proofContractFromAuthorCheckpointResponse,
8190
9441
  readRiddleProofRunStatus,
8191
9442
  recordValue,
8192
9443
  redactForProofDiagnostics,
9444
+ resolveBasicGameplayProgressionCheckWithArtifactScreenshots,
8193
9445
  resolveRiddleApiKey,
9446
+ resolveRiddleProofProfileTargetUrl,
8194
9447
  riddleRequestJson,
8195
9448
  runCodexExecAgentDoctor,
8196
9449
  runLocalAgentDoctor,
@@ -8198,9 +9451,12 @@ function createRiddleApiClient(config = {}) {
8198
9451
  runRiddleProofEngineHarness,
8199
9452
  runRiddleScript,
8200
9453
  runRiddleServerPreview,
9454
+ sanitizeBasicGameplayJsonString,
8201
9455
  setRunStatus,
9456
+ slugifyRiddleProofProfileName,
8202
9457
  statePathsForRunState,
8203
9458
  summarizeCaptureArtifacts,
9459
+ summarizeRiddleProofProfileResult,
8204
9460
  visualSessionFingerprint,
8205
9461
  visualSessionFingerprintBasis
8206
9462
  });