@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/README.md +91 -0
- package/dist/basic-gameplay.cjs +437 -4
- package/dist/basic-gameplay.d.cts +121 -2
- package/dist/basic-gameplay.d.ts +121 -2
- package/dist/basic-gameplay.js +23 -3
- package/dist/chunk-7NMAU4DP.js +808 -0
- package/dist/chunk-AAIASO2C.js +699 -0
- package/dist/cli.cjs +950 -0
- package/dist/cli.js +192 -3
- package/dist/engine-harness.js +2 -2
- package/dist/index.cjs +1258 -2
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +60 -4
- package/dist/profile.cjs +848 -0
- package/dist/profile.d.cts +175 -0
- package/dist/profile.d.ts +175 -0
- package/dist/profile.js +38 -0
- package/examples/profiles/page-content-basic.json +26 -0
- package/package.json +8 -2
- package/dist/chunk-53DJMNQ6.js +0 -276
- package/dist/{chunk-2FBF2UDZ.js → chunk-D3M2FAYQ.js} +3 -3
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) =>
|
|
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
|
});
|