@riddledc/riddle-proof 0.7.7 → 0.7.9

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
@@ -2917,6 +2917,7 @@ __export(index_exports, {
2917
2917
  RIDDLE_PROOF_PROFILE_CHECK_TYPES: () => RIDDLE_PROOF_PROFILE_CHECK_TYPES,
2918
2918
  RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION: () => RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION,
2919
2919
  RIDDLE_PROOF_PROFILE_RESULT_VERSION: () => RIDDLE_PROOF_PROFILE_RESULT_VERSION,
2920
+ RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES: () => RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES,
2920
2921
  RIDDLE_PROOF_PROFILE_STATUSES: () => RIDDLE_PROOF_PROFILE_STATUSES,
2921
2922
  RIDDLE_PROOF_PROFILE_VERSION: () => RIDDLE_PROOF_PROFILE_VERSION,
2922
2923
  RIDDLE_PROOF_RUN_CARD_VERSION: () => RIDDLE_PROOF_RUN_CARD_VERSION,
@@ -7818,6 +7819,10 @@ var BASIC_GAMEPLAY_ACTION_TYPES = [
7818
7819
  "repeat",
7819
7820
  "click",
7820
7821
  "click-by-text",
7822
+ "canvas-click",
7823
+ "canvas-pointer-down",
7824
+ "canvas-pointer-move",
7825
+ "canvas-pointer-up",
7821
7826
  "wait-for-text",
7822
7827
  "window-call",
7823
7828
  "evaluate"
@@ -8521,6 +8526,12 @@ var RIDDLE_PROOF_PROFILE_CHECK_TYPES = [
8521
8526
  "no_mobile_horizontal_overflow",
8522
8527
  "no_fatal_console_errors"
8523
8528
  ];
8529
+ var RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES = [
8530
+ "click",
8531
+ "wait",
8532
+ "wait_for_selector",
8533
+ "wait_for_text"
8534
+ ];
8524
8535
  var DEFAULT_VIEWPORTS = [
8525
8536
  { name: "desktop", width: 1280, height: 800 }
8526
8537
  ];
@@ -8573,6 +8584,41 @@ function normalizeViewports(value) {
8573
8584
  function isSupportedCheckType(value) {
8574
8585
  return RIDDLE_PROOF_PROFILE_CHECK_TYPES.includes(value);
8575
8586
  }
8587
+ function normalizeSetupActionType(value, index) {
8588
+ const normalized = String(value || "").trim().replace(/-/g, "_");
8589
+ if (RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES.includes(normalized)) {
8590
+ return normalized;
8591
+ }
8592
+ throw new Error(`target.setup_actions[${index}].type ${value || "(missing)"} is not supported. Supported actions: ${RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES.join(", ")}`);
8593
+ }
8594
+ function normalizeSetupAction(input, index) {
8595
+ if (!isRecord2(input)) throw new Error(`target.setup_actions[${index}] must be an object.`);
8596
+ const type = normalizeSetupActionType(stringValue5(input.type), index);
8597
+ const selector = stringValue5(input.selector);
8598
+ if ((type === "click" || type === "wait_for_selector" || type === "wait_for_text") && !selector) {
8599
+ throw new Error(`target.setup_actions[${index}] ${type} requires selector.`);
8600
+ }
8601
+ if (type === "wait_for_text" && !stringValue5(input.text) && !stringValue5(input.pattern)) {
8602
+ throw new Error(`target.setup_actions[${index}] wait_for_text requires text or pattern.`);
8603
+ }
8604
+ return {
8605
+ type,
8606
+ selector,
8607
+ text: stringValue5(input.text),
8608
+ pattern: stringValue5(input.pattern),
8609
+ flags: stringValue5(input.flags),
8610
+ index: numberValue3(input.index),
8611
+ ms: numberValue3(input.ms) ?? numberValue3(input.wait_ms) ?? numberValue3(input.waitMs),
8612
+ timeout_ms: numberValue3(input.timeout_ms) ?? numberValue3(input.timeoutMs),
8613
+ after_ms: numberValue3(input.after_ms) ?? numberValue3(input.afterMs),
8614
+ continue_on_failure: input.continue_on_failure === true || input.continueOnFailure === true
8615
+ };
8616
+ }
8617
+ function normalizeSetupActions(value) {
8618
+ if (value === void 0) return void 0;
8619
+ if (!Array.isArray(value)) throw new Error("target.setup_actions must be an array.");
8620
+ return value.map(normalizeSetupAction);
8621
+ }
8576
8622
  function normalizeCheck(input, index) {
8577
8623
  if (!isRecord2(input)) throw new Error(`checks[${index}] must be an object.`);
8578
8624
  const type = stringValue5(input.type);
@@ -8640,7 +8686,8 @@ function normalizeRiddleProofProfile(input, options = {}) {
8640
8686
  viewports: options.viewports?.length ? options.viewports : normalizeViewports(targetInput.viewports),
8641
8687
  auth: stringValue5(targetInput.auth) || "none",
8642
8688
  wait_for_selector: stringValue5(targetInput.wait_for_selector) || stringValue5(targetInput.waitForSelector),
8643
- wait_ms: numberValue3(targetInput.wait_ms) ?? numberValue3(targetInput.waitMs)
8689
+ wait_ms: numberValue3(targetInput.wait_ms) ?? numberValue3(targetInput.waitMs),
8690
+ setup_actions: normalizeSetupActions(targetInput.setup_actions ?? targetInput.setupActions)
8644
8691
  },
8645
8692
  checks,
8646
8693
  artifacts: Array.isArray(input.artifacts) ? input.artifacts.map((item) => String(item)).filter(Boolean) : ["screenshot", "console", "dom_summary", "proof_json"],
@@ -8813,6 +8860,48 @@ function assessCheckFromEvidence(check, evidence) {
8813
8860
  message: "Unsupported check type."
8814
8861
  };
8815
8862
  }
8863
+ function assessSetupActionsFromEvidence(profile, evidence) {
8864
+ if (!profile.target.setup_actions?.length) return void 0;
8865
+ const actionCount = profile.target.setup_actions.length;
8866
+ const failed = [];
8867
+ const viewports = evidence.viewports || [];
8868
+ for (const viewport of viewports) {
8869
+ const results = viewport.setup_action_results || [];
8870
+ for (const result of results) {
8871
+ if (result.ok === false) {
8872
+ failed.push({
8873
+ viewport: viewport.name,
8874
+ action: result.action ?? result.type ?? null,
8875
+ selector: result.selector ?? null,
8876
+ reason: result.reason ?? result.error ?? null
8877
+ });
8878
+ }
8879
+ }
8880
+ if (results.length < actionCount && results.every((result) => result.ok !== false)) {
8881
+ failed.push({
8882
+ viewport: viewport.name,
8883
+ action: "setup_actions",
8884
+ selector: null,
8885
+ reason: `missing setup action results: ${results.length}/${actionCount}`
8886
+ });
8887
+ }
8888
+ }
8889
+ return {
8890
+ type: "setup_actions_succeeded",
8891
+ label: "setup actions succeeded",
8892
+ status: failed.length ? "failed" : "passed",
8893
+ evidence: {
8894
+ action_count: actionCount,
8895
+ viewports: viewports.map((viewport) => ({
8896
+ name: viewport.name,
8897
+ ok: (viewport.setup_action_results || []).length >= actionCount && (viewport.setup_action_results || []).every((result) => result.ok !== false),
8898
+ result_count: (viewport.setup_action_results || []).length
8899
+ })),
8900
+ failed
8901
+ },
8902
+ message: failed.length ? `Setup actions failed in ${failed.length} viewport action(s).` : void 0
8903
+ };
8904
+ }
8816
8905
  function profileStatusFromEvidence(evidence, checks) {
8817
8906
  if (!evidence) return "proof_insufficient";
8818
8907
  const viewports = evidence.viewports || [];
@@ -8824,7 +8913,10 @@ function profileStatusFromEvidence(evidence, checks) {
8824
8913
  }
8825
8914
  function assessRiddleProofProfileEvidence(profile, evidence, options = {}) {
8826
8915
  const capturedAt = evidence?.captured_at || (/* @__PURE__ */ new Date()).toISOString();
8827
- const checks = evidence ? profile.checks.map((check) => assessCheckFromEvidence(check, evidence)) : [];
8916
+ const checks = evidence ? [
8917
+ assessSetupActionsFromEvidence(profile, evidence),
8918
+ ...profile.checks.map((check) => assessCheckFromEvidence(check, evidence))
8919
+ ].filter((check) => Boolean(check)) : [];
8828
8920
  const status = profileStatusFromEvidence(evidence, checks);
8829
8921
  const firstViewport = evidence?.viewports?.[0];
8830
8922
  const screenshots = (evidence?.viewports || []).map((viewport) => viewport.screenshot_label).filter((label) => Boolean(label));
@@ -8938,6 +9030,47 @@ function textMatches(sample, check) {
8938
9030
  function assessProfile(profile, evidence) {
8939
9031
  const checks = [];
8940
9032
  const viewports = evidence.viewports || [];
9033
+ if (profile.target && Array.isArray(profile.target.setup_actions) && profile.target.setup_actions.length) {
9034
+ const actionCount = profile.target.setup_actions.length;
9035
+ const failed = [];
9036
+ for (const viewport of viewports) {
9037
+ const results = viewport.setup_action_results || [];
9038
+ for (const result of results) {
9039
+ if (result && result.ok === false) {
9040
+ failed.push({
9041
+ viewport: viewport.name,
9042
+ action: result.action || result.type || null,
9043
+ selector: result.selector || null,
9044
+ reason: result.reason || result.error || null,
9045
+ });
9046
+ }
9047
+ }
9048
+ if (results.length < actionCount && results.every((result) => !result || result.ok !== false)) {
9049
+ failed.push({
9050
+ viewport: viewport.name,
9051
+ action: "setup_actions",
9052
+ selector: null,
9053
+ reason: "missing setup action results: " + results.length + "/" + actionCount,
9054
+ });
9055
+ }
9056
+ }
9057
+ checks.push({
9058
+ type: "setup_actions_succeeded",
9059
+ label: "setup actions succeeded",
9060
+ status: failed.length ? "failed" : "passed",
9061
+ evidence: {
9062
+ action_count: actionCount,
9063
+ viewports: viewports.map((viewport) => ({
9064
+ name: viewport.name,
9065
+ ok: (viewport.setup_action_results || []).length >= actionCount
9066
+ && (viewport.setup_action_results || []).every((result) => !result || result.ok !== false),
9067
+ result_count: (viewport.setup_action_results || []).length,
9068
+ })),
9069
+ failed,
9070
+ },
9071
+ message: failed.length ? "Setup actions failed in " + failed.length + " viewport action(s)." : undefined,
9072
+ });
9073
+ }
8941
9074
  for (const check of profile.checks || []) {
8942
9075
  if (check.type === "route_loaded") {
8943
9076
  const expectedPath = check.expected_path || new URL(evidence.target_url).pathname || "/";
@@ -9100,6 +9233,92 @@ function textMatches(sample, check) {
9100
9233
  }
9101
9234
  return String(sample || "").includes(check.text || "");
9102
9235
  }
9236
+ function setupActionType(action) {
9237
+ return String(action && action.type ? action.type : "").replace(/-/g, "_");
9238
+ }
9239
+ function setupNumber(value, fallback) {
9240
+ const number = Number(value);
9241
+ return Number.isFinite(number) && number >= 0 ? number : fallback;
9242
+ }
9243
+ function setupTextMatches(sample, action) {
9244
+ if (action.pattern) {
9245
+ try { return new RegExp(action.pattern, action.flags || "").test(sample || ""); } catch { return false; }
9246
+ }
9247
+ return String(sample || "").includes(action.text || "");
9248
+ }
9249
+ async function setupLocatorText(locator, index) {
9250
+ return await locator.nth(index).textContent({ timeout: 1000 }).catch(() => "");
9251
+ }
9252
+ async function executeSetupAction(action, ordinal) {
9253
+ const type = setupActionType(action);
9254
+ const base = { ok: false, action: type || "unknown", ordinal, selector: action.selector || null };
9255
+ const timeout = setupNumber(action.timeout_ms, 5000);
9256
+ try {
9257
+ if (type === "wait") {
9258
+ const ms = setupNumber(action.ms, 500);
9259
+ await page.waitForTimeout(ms);
9260
+ return { ...base, ok: true, ms };
9261
+ }
9262
+ if (type === "wait_for_selector") {
9263
+ await page.waitForSelector(action.selector, { state: "visible", timeout });
9264
+ return { ...base, ok: true, timeout_ms: timeout };
9265
+ }
9266
+ if (type === "click") {
9267
+ const locator = page.locator(action.selector);
9268
+ const count = await locator.count();
9269
+ if (!count) return { ...base, reason: "selector_not_found", count };
9270
+ let targetIndex = Number.isInteger(action.index) ? action.index : 0;
9271
+ let matchedText = null;
9272
+ if (action.text || action.pattern) {
9273
+ targetIndex = -1;
9274
+ for (let index = 0; index < count; index += 1) {
9275
+ const text = await setupLocatorText(locator, index);
9276
+ if (setupTextMatches(text, action)) {
9277
+ targetIndex = index;
9278
+ matchedText = text;
9279
+ break;
9280
+ }
9281
+ }
9282
+ if (targetIndex < 0) return { ...base, reason: "text_not_found", count };
9283
+ }
9284
+ if (targetIndex < 0 || targetIndex >= count) return { ...base, reason: "index_out_of_range", count, target_index: targetIndex };
9285
+ await locator.nth(targetIndex).click({ timeout });
9286
+ return { ...base, ok: true, count, target_index: targetIndex, text: matchedText };
9287
+ }
9288
+ if (type === "wait_for_text") {
9289
+ const locator = page.locator(action.selector);
9290
+ const startedAt = Date.now();
9291
+ let lastText = "";
9292
+ while (Date.now() - startedAt <= timeout) {
9293
+ const count = await locator.count().catch(() => 0);
9294
+ for (let index = 0; index < count; index += 1) {
9295
+ const text = await setupLocatorText(locator, index);
9296
+ lastText = text || lastText;
9297
+ if (setupTextMatches(text, action)) {
9298
+ return { ...base, ok: true, text, target_index: index, timeout_ms: timeout };
9299
+ }
9300
+ }
9301
+ await page.waitForTimeout(100);
9302
+ }
9303
+ return { ...base, reason: "text_not_found", text: lastText, timeout_ms: timeout };
9304
+ }
9305
+ return { ...base, reason: "unsupported_action" };
9306
+ } catch (error) {
9307
+ return { ...base, error: String(error && error.message ? error.message : error).slice(0, 1000) };
9308
+ }
9309
+ }
9310
+ async function executeSetupActions(actions) {
9311
+ const results = [];
9312
+ for (let index = 0; index < (actions || []).length; index += 1) {
9313
+ const action = actions[index] || {};
9314
+ const result = await executeSetupAction(action, index);
9315
+ results.push(result);
9316
+ const afterMs = setupNumber(action.after_ms, 0);
9317
+ if (afterMs) await page.waitForTimeout(afterMs);
9318
+ if (result.ok === false && action.continue_on_failure !== true) break;
9319
+ }
9320
+ return results;
9321
+ }
9103
9322
  function expectedPathFor(check) {
9104
9323
  return check.expected_path || new URL(targetUrl).pathname || "/";
9105
9324
  }
@@ -9134,6 +9353,9 @@ async function captureViewport(viewport) {
9134
9353
  if (!navigationError && profile.target.wait_ms) {
9135
9354
  await page.waitForTimeout(profile.target.wait_ms);
9136
9355
  }
9356
+ const setupActionResults = (!navigationError && !waitError)
9357
+ ? await executeSetupActions(profile.target.setup_actions || [])
9358
+ : [];
9137
9359
  const dom = await page.evaluate(() => {
9138
9360
  const body = document.body;
9139
9361
  const documentElement = document.documentElement;
@@ -9195,6 +9417,7 @@ async function captureViewport(viewport) {
9195
9417
  overflow_px: Math.max(0, (dom.scroll_width || 0) - (dom.client_width || viewport.width)),
9196
9418
  selectors,
9197
9419
  text_matches,
9420
+ setup_action_results: setupActionResults,
9198
9421
  screenshot_label: screenshotLabel,
9199
9422
  navigation_error: navigationError,
9200
9423
  wait_error: waitError,
@@ -9540,6 +9763,7 @@ function createRiddleApiClient(config = {}) {
9540
9763
  RIDDLE_PROOF_PROFILE_CHECK_TYPES,
9541
9764
  RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION,
9542
9765
  RIDDLE_PROOF_PROFILE_RESULT_VERSION,
9766
+ RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES,
9543
9767
  RIDDLE_PROOF_PROFILE_STATUSES,
9544
9768
  RIDDLE_PROOF_PROFILE_VERSION,
9545
9769
  RIDDLE_PROOF_RUN_CARD_VERSION,
package/dist/index.d.cts CHANGED
@@ -10,5 +10,5 @@ export { CreateCaptureDiagnosticInput, DEFAULT_DIAGNOSTIC_ARRAY_LIMIT, DEFAULT_D
10
10
  export { BuildVisualProofSessionInput, RIDDLE_PROOF_VISUAL_SESSION_FINGERPRINT_VERSION, RIDDLE_PROOF_VISUAL_SESSION_VERSION, VisualProofSessionMismatch, buildVisualProofSession, compareVisualProofSessionFingerprint, parseVisualProofSession, visualSessionFingerprint, visualSessionFingerprintBasis } from './proof-session.cjs';
11
11
  export { AssessPlayabilityOptions, RIDDLE_PROOF_PLAYABILITY_ASSESSMENT_VERSION, RIDDLE_PROOF_PLAYABILITY_VERSION, RiddleProofPlayabilityAssessment, RiddleProofPlayabilityEvidence, assessPlayabilityEvidence, extractPlayabilityEvidence, isRiddleProofPlayabilityMode } from './playability.cjs';
12
12
  export { AssessBasicGameplayOptions, AttachBasicGameplayArtifactOptions, BASIC_GAMEPLAY_ACTION_TYPES, BASIC_GAMEPLAY_PROGRESS_CHECK_TYPES, BasicGameplayActionResult, BasicGameplayActionType, BasicGameplayArtifactResolution, BasicGameplayAssessmentSummary, BasicGameplayCanvasState, BasicGameplayCatchRecord, BasicGameplayChangeSummary, BasicGameplayFailureCode, BasicGameplayFixReference, BasicGameplayMetric, BasicGameplayMobileEvidence, BasicGameplayProgressCheckType, BasicGameplayProgressionCheck, BasicGameplayProofArtifact, BasicGameplayRouteReference, BasicGameplaySnapshot, BasicGameplaySuiteFailure, BasicGameplayWarningCode, CreateBasicGameplayCatchSummaryInput, RIDDLE_PROOF_BASIC_GAMEPLAY_ASSESSMENT_VERSION, RIDDLE_PROOF_BASIC_GAMEPLAY_CATCH_VERSION, RIDDLE_PROOF_BASIC_GAMEPLAY_VERSION, RiddleProofBasicGameplayAssessment, RiddleProofBasicGameplayCatchSummary, RiddleProofBasicGameplayEvidence, RiddleProofBasicGameplayRouteAssessment, RiddleProofBasicGameplayRouteEvidence, assessBasicGameplayEvidence, assessBasicGameplayProgressionCheck, assessBasicGameplayProgressionChecks, assessBasicGameplayRoute, attachBasicGameplayArtifactScreenshotHashes, augmentBasicGameplayAssessmentWithProgressionChecks, compactBasicGameplayText, createBasicGameplayCatchRecords, createBasicGameplayCatchSummary, extractBasicGameplayEvidence, resolveBasicGameplayProgressionCheckWithArtifactScreenshots, sanitizeBasicGameplayJsonString } from './basic-gameplay.cjs';
13
- export { NormalizeRiddleProofProfileOptions, RIDDLE_PROOF_PROFILE_CHECK_TYPES, RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION, RIDDLE_PROOF_PROFILE_RESULT_VERSION, RIDDLE_PROOF_PROFILE_STATUSES, RIDDLE_PROOF_PROFILE_VERSION, RiddleProofProfile, RiddleProofProfileArtifactRef, RiddleProofProfileBaselinePolicy, RiddleProofProfileCheck, RiddleProofProfileCheckResult, RiddleProofProfileCheckType, RiddleProofProfileEvidence, RiddleProofProfileFailureAction, RiddleProofProfileResult, RiddleProofProfileRouteEvidence, RiddleProofProfileRunner, RiddleProofProfileStatus, RiddleProofProfileTarget, RiddleProofProfileViewport, RiddleProofProfileViewportEvidence, assessRiddleProofProfileEvidence, buildRiddleProofProfileScript, collectRiddleProfileArtifactRefs, createRiddleProofProfileConfigurationError, createRiddleProofProfileEnvironmentBlockedResult, createRiddleProofProfileInsufficientResult, extractRiddleProofProfileResult, normalizeRiddleProofProfile, profileStatusExitCode, resolveRiddleProofProfileTargetUrl, slugifyRiddleProofProfileName, summarizeRiddleProofProfileResult } from './profile.cjs';
13
+ export { NormalizeRiddleProofProfileOptions, RIDDLE_PROOF_PROFILE_CHECK_TYPES, RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION, RIDDLE_PROOF_PROFILE_RESULT_VERSION, RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES, RIDDLE_PROOF_PROFILE_STATUSES, RIDDLE_PROOF_PROFILE_VERSION, RiddleProofProfile, RiddleProofProfileArtifactRef, RiddleProofProfileBaselinePolicy, RiddleProofProfileCheck, RiddleProofProfileCheckResult, RiddleProofProfileCheckType, RiddleProofProfileEvidence, RiddleProofProfileFailureAction, RiddleProofProfileResult, RiddleProofProfileRouteEvidence, RiddleProofProfileRunner, RiddleProofProfileSetupAction, RiddleProofProfileSetupActionType, RiddleProofProfileStatus, RiddleProofProfileTarget, RiddleProofProfileViewport, RiddleProofProfileViewportEvidence, assessRiddleProofProfileEvidence, buildRiddleProofProfileScript, collectRiddleProfileArtifactRefs, createRiddleProofProfileConfigurationError, createRiddleProofProfileEnvironmentBlockedResult, createRiddleProofProfileInsufficientResult, extractRiddleProofProfileResult, normalizeRiddleProofProfile, profileStatusExitCode, resolveRiddleProofProfileTargetUrl, slugifyRiddleProofProfileName, summarizeRiddleProofProfileResult } from './profile.cjs';
14
14
  export { DEFAULT_RIDDLE_API_BASE_URL, DEFAULT_RIDDLE_API_KEY_FILE, RiddleApiError, RiddleClientConfig, RiddleFetch, RiddlePollJobResult, RiddlePreviewDeployResult, RiddleRunScriptInput, RiddleServerPreviewInput, RiddleServerPreviewResult, createRiddleApiClient, deployRiddleStaticPreview, isTerminalRiddleJobStatus, parseRiddleViewport, pollRiddleJob, resolveRiddleApiKey, riddleRequestJson, runRiddleScript, runRiddleServerPreview } from './riddle-client.cjs';
package/dist/index.d.ts CHANGED
@@ -10,5 +10,5 @@ export { CreateCaptureDiagnosticInput, DEFAULT_DIAGNOSTIC_ARRAY_LIMIT, DEFAULT_D
10
10
  export { BuildVisualProofSessionInput, RIDDLE_PROOF_VISUAL_SESSION_FINGERPRINT_VERSION, RIDDLE_PROOF_VISUAL_SESSION_VERSION, VisualProofSessionMismatch, buildVisualProofSession, compareVisualProofSessionFingerprint, parseVisualProofSession, visualSessionFingerprint, visualSessionFingerprintBasis } from './proof-session.js';
11
11
  export { AssessPlayabilityOptions, RIDDLE_PROOF_PLAYABILITY_ASSESSMENT_VERSION, RIDDLE_PROOF_PLAYABILITY_VERSION, RiddleProofPlayabilityAssessment, RiddleProofPlayabilityEvidence, assessPlayabilityEvidence, extractPlayabilityEvidence, isRiddleProofPlayabilityMode } from './playability.js';
12
12
  export { AssessBasicGameplayOptions, AttachBasicGameplayArtifactOptions, BASIC_GAMEPLAY_ACTION_TYPES, BASIC_GAMEPLAY_PROGRESS_CHECK_TYPES, BasicGameplayActionResult, BasicGameplayActionType, BasicGameplayArtifactResolution, BasicGameplayAssessmentSummary, BasicGameplayCanvasState, BasicGameplayCatchRecord, BasicGameplayChangeSummary, BasicGameplayFailureCode, BasicGameplayFixReference, BasicGameplayMetric, BasicGameplayMobileEvidence, BasicGameplayProgressCheckType, BasicGameplayProgressionCheck, BasicGameplayProofArtifact, BasicGameplayRouteReference, BasicGameplaySnapshot, BasicGameplaySuiteFailure, BasicGameplayWarningCode, CreateBasicGameplayCatchSummaryInput, RIDDLE_PROOF_BASIC_GAMEPLAY_ASSESSMENT_VERSION, RIDDLE_PROOF_BASIC_GAMEPLAY_CATCH_VERSION, RIDDLE_PROOF_BASIC_GAMEPLAY_VERSION, RiddleProofBasicGameplayAssessment, RiddleProofBasicGameplayCatchSummary, RiddleProofBasicGameplayEvidence, RiddleProofBasicGameplayRouteAssessment, RiddleProofBasicGameplayRouteEvidence, assessBasicGameplayEvidence, assessBasicGameplayProgressionCheck, assessBasicGameplayProgressionChecks, assessBasicGameplayRoute, attachBasicGameplayArtifactScreenshotHashes, augmentBasicGameplayAssessmentWithProgressionChecks, compactBasicGameplayText, createBasicGameplayCatchRecords, createBasicGameplayCatchSummary, extractBasicGameplayEvidence, resolveBasicGameplayProgressionCheckWithArtifactScreenshots, sanitizeBasicGameplayJsonString } from './basic-gameplay.js';
13
- export { NormalizeRiddleProofProfileOptions, RIDDLE_PROOF_PROFILE_CHECK_TYPES, RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION, RIDDLE_PROOF_PROFILE_RESULT_VERSION, RIDDLE_PROOF_PROFILE_STATUSES, RIDDLE_PROOF_PROFILE_VERSION, RiddleProofProfile, RiddleProofProfileArtifactRef, RiddleProofProfileBaselinePolicy, RiddleProofProfileCheck, RiddleProofProfileCheckResult, RiddleProofProfileCheckType, RiddleProofProfileEvidence, RiddleProofProfileFailureAction, RiddleProofProfileResult, RiddleProofProfileRouteEvidence, RiddleProofProfileRunner, RiddleProofProfileStatus, RiddleProofProfileTarget, RiddleProofProfileViewport, RiddleProofProfileViewportEvidence, assessRiddleProofProfileEvidence, buildRiddleProofProfileScript, collectRiddleProfileArtifactRefs, createRiddleProofProfileConfigurationError, createRiddleProofProfileEnvironmentBlockedResult, createRiddleProofProfileInsufficientResult, extractRiddleProofProfileResult, normalizeRiddleProofProfile, profileStatusExitCode, resolveRiddleProofProfileTargetUrl, slugifyRiddleProofProfileName, summarizeRiddleProofProfileResult } from './profile.js';
13
+ export { NormalizeRiddleProofProfileOptions, RIDDLE_PROOF_PROFILE_CHECK_TYPES, RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION, RIDDLE_PROOF_PROFILE_RESULT_VERSION, RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES, RIDDLE_PROOF_PROFILE_STATUSES, RIDDLE_PROOF_PROFILE_VERSION, RiddleProofProfile, RiddleProofProfileArtifactRef, RiddleProofProfileBaselinePolicy, RiddleProofProfileCheck, RiddleProofProfileCheckResult, RiddleProofProfileCheckType, RiddleProofProfileEvidence, RiddleProofProfileFailureAction, RiddleProofProfileResult, RiddleProofProfileRouteEvidence, RiddleProofProfileRunner, RiddleProofProfileSetupAction, RiddleProofProfileSetupActionType, RiddleProofProfileStatus, RiddleProofProfileTarget, RiddleProofProfileViewport, RiddleProofProfileViewportEvidence, assessRiddleProofProfileEvidence, buildRiddleProofProfileScript, collectRiddleProfileArtifactRefs, createRiddleProofProfileConfigurationError, createRiddleProofProfileEnvironmentBlockedResult, createRiddleProofProfileInsufficientResult, extractRiddleProofProfileResult, normalizeRiddleProofProfile, profileStatusExitCode, resolveRiddleProofProfileTargetUrl, slugifyRiddleProofProfileName, summarizeRiddleProofProfileResult } from './profile.js';
14
14
  export { DEFAULT_RIDDLE_API_BASE_URL, DEFAULT_RIDDLE_API_KEY_FILE, RiddleApiError, RiddleClientConfig, RiddleFetch, RiddlePollJobResult, RiddlePreviewDeployResult, RiddleRunScriptInput, RiddleServerPreviewInput, RiddleServerPreviewResult, createRiddleApiClient, deployRiddleStaticPreview, isTerminalRiddleJobStatus, parseRiddleViewport, pollRiddleJob, resolveRiddleApiKey, riddleRequestJson, runRiddleScript, runRiddleServerPreview } from './riddle-client.js';
package/dist/index.js CHANGED
@@ -36,11 +36,12 @@ import {
36
36
  extractBasicGameplayEvidence,
37
37
  resolveBasicGameplayProgressionCheckWithArtifactScreenshots,
38
38
  sanitizeBasicGameplayJsonString
39
- } from "./chunk-AHW7SL3W.js";
39
+ } from "./chunk-5A4SL6CX.js";
40
40
  import {
41
41
  RIDDLE_PROOF_PROFILE_CHECK_TYPES,
42
42
  RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION,
43
43
  RIDDLE_PROOF_PROFILE_RESULT_VERSION,
44
+ RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES,
44
45
  RIDDLE_PROOF_PROFILE_STATUSES,
45
46
  RIDDLE_PROOF_PROFILE_VERSION,
46
47
  assessRiddleProofProfileEvidence,
@@ -55,7 +56,7 @@ import {
55
56
  resolveRiddleProofProfileTargetUrl,
56
57
  slugifyRiddleProofProfileName,
57
58
  summarizeRiddleProofProfileResult
58
- } from "./chunk-7NMAU4DP.js";
59
+ } from "./chunk-NUSUGO2P.js";
59
60
  import {
60
61
  DEFAULT_RIDDLE_API_BASE_URL,
61
62
  DEFAULT_RIDDLE_API_KEY_FILE,
@@ -153,6 +154,7 @@ export {
153
154
  RIDDLE_PROOF_PROFILE_CHECK_TYPES,
154
155
  RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION,
155
156
  RIDDLE_PROOF_PROFILE_RESULT_VERSION,
157
+ RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES,
156
158
  RIDDLE_PROOF_PROFILE_STATUSES,
157
159
  RIDDLE_PROOF_PROFILE_VERSION,
158
160
  RIDDLE_PROOF_RUN_CARD_VERSION,
package/dist/profile.cjs CHANGED
@@ -23,6 +23,7 @@ __export(profile_exports, {
23
23
  RIDDLE_PROOF_PROFILE_CHECK_TYPES: () => RIDDLE_PROOF_PROFILE_CHECK_TYPES,
24
24
  RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION: () => RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION,
25
25
  RIDDLE_PROOF_PROFILE_RESULT_VERSION: () => RIDDLE_PROOF_PROFILE_RESULT_VERSION,
26
+ RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES: () => RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES,
26
27
  RIDDLE_PROOF_PROFILE_STATUSES: () => RIDDLE_PROOF_PROFILE_STATUSES,
27
28
  RIDDLE_PROOF_PROFILE_VERSION: () => RIDDLE_PROOF_PROFILE_VERSION,
28
29
  assessRiddleProofProfileEvidence: () => assessRiddleProofProfileEvidence,
@@ -60,6 +61,12 @@ var RIDDLE_PROOF_PROFILE_CHECK_TYPES = [
60
61
  "no_mobile_horizontal_overflow",
61
62
  "no_fatal_console_errors"
62
63
  ];
64
+ var RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES = [
65
+ "click",
66
+ "wait",
67
+ "wait_for_selector",
68
+ "wait_for_text"
69
+ ];
63
70
  var DEFAULT_VIEWPORTS = [
64
71
  { name: "desktop", width: 1280, height: 800 }
65
72
  ];
@@ -112,6 +119,41 @@ function normalizeViewports(value) {
112
119
  function isSupportedCheckType(value) {
113
120
  return RIDDLE_PROOF_PROFILE_CHECK_TYPES.includes(value);
114
121
  }
122
+ function normalizeSetupActionType(value, index) {
123
+ const normalized = String(value || "").trim().replace(/-/g, "_");
124
+ if (RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES.includes(normalized)) {
125
+ return normalized;
126
+ }
127
+ throw new Error(`target.setup_actions[${index}].type ${value || "(missing)"} is not supported. Supported actions: ${RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES.join(", ")}`);
128
+ }
129
+ function normalizeSetupAction(input, index) {
130
+ if (!isRecord(input)) throw new Error(`target.setup_actions[${index}] must be an object.`);
131
+ const type = normalizeSetupActionType(stringValue(input.type), index);
132
+ const selector = stringValue(input.selector);
133
+ if ((type === "click" || type === "wait_for_selector" || type === "wait_for_text") && !selector) {
134
+ throw new Error(`target.setup_actions[${index}] ${type} requires selector.`);
135
+ }
136
+ if (type === "wait_for_text" && !stringValue(input.text) && !stringValue(input.pattern)) {
137
+ throw new Error(`target.setup_actions[${index}] wait_for_text requires text or pattern.`);
138
+ }
139
+ return {
140
+ type,
141
+ selector,
142
+ text: stringValue(input.text),
143
+ pattern: stringValue(input.pattern),
144
+ flags: stringValue(input.flags),
145
+ index: numberValue(input.index),
146
+ ms: numberValue(input.ms) ?? numberValue(input.wait_ms) ?? numberValue(input.waitMs),
147
+ timeout_ms: numberValue(input.timeout_ms) ?? numberValue(input.timeoutMs),
148
+ after_ms: numberValue(input.after_ms) ?? numberValue(input.afterMs),
149
+ continue_on_failure: input.continue_on_failure === true || input.continueOnFailure === true
150
+ };
151
+ }
152
+ function normalizeSetupActions(value) {
153
+ if (value === void 0) return void 0;
154
+ if (!Array.isArray(value)) throw new Error("target.setup_actions must be an array.");
155
+ return value.map(normalizeSetupAction);
156
+ }
115
157
  function normalizeCheck(input, index) {
116
158
  if (!isRecord(input)) throw new Error(`checks[${index}] must be an object.`);
117
159
  const type = stringValue(input.type);
@@ -179,7 +221,8 @@ function normalizeRiddleProofProfile(input, options = {}) {
179
221
  viewports: options.viewports?.length ? options.viewports : normalizeViewports(targetInput.viewports),
180
222
  auth: stringValue(targetInput.auth) || "none",
181
223
  wait_for_selector: stringValue(targetInput.wait_for_selector) || stringValue(targetInput.waitForSelector),
182
- wait_ms: numberValue(targetInput.wait_ms) ?? numberValue(targetInput.waitMs)
224
+ wait_ms: numberValue(targetInput.wait_ms) ?? numberValue(targetInput.waitMs),
225
+ setup_actions: normalizeSetupActions(targetInput.setup_actions ?? targetInput.setupActions)
183
226
  },
184
227
  checks,
185
228
  artifacts: Array.isArray(input.artifacts) ? input.artifacts.map((item) => String(item)).filter(Boolean) : ["screenshot", "console", "dom_summary", "proof_json"],
@@ -352,6 +395,48 @@ function assessCheckFromEvidence(check, evidence) {
352
395
  message: "Unsupported check type."
353
396
  };
354
397
  }
398
+ function assessSetupActionsFromEvidence(profile, evidence) {
399
+ if (!profile.target.setup_actions?.length) return void 0;
400
+ const actionCount = profile.target.setup_actions.length;
401
+ const failed = [];
402
+ const viewports = evidence.viewports || [];
403
+ for (const viewport of viewports) {
404
+ const results = viewport.setup_action_results || [];
405
+ for (const result of results) {
406
+ if (result.ok === false) {
407
+ failed.push({
408
+ viewport: viewport.name,
409
+ action: result.action ?? result.type ?? null,
410
+ selector: result.selector ?? null,
411
+ reason: result.reason ?? result.error ?? null
412
+ });
413
+ }
414
+ }
415
+ if (results.length < actionCount && results.every((result) => result.ok !== false)) {
416
+ failed.push({
417
+ viewport: viewport.name,
418
+ action: "setup_actions",
419
+ selector: null,
420
+ reason: `missing setup action results: ${results.length}/${actionCount}`
421
+ });
422
+ }
423
+ }
424
+ return {
425
+ type: "setup_actions_succeeded",
426
+ label: "setup actions succeeded",
427
+ status: failed.length ? "failed" : "passed",
428
+ evidence: {
429
+ action_count: actionCount,
430
+ viewports: viewports.map((viewport) => ({
431
+ name: viewport.name,
432
+ ok: (viewport.setup_action_results || []).length >= actionCount && (viewport.setup_action_results || []).every((result) => result.ok !== false),
433
+ result_count: (viewport.setup_action_results || []).length
434
+ })),
435
+ failed
436
+ },
437
+ message: failed.length ? `Setup actions failed in ${failed.length} viewport action(s).` : void 0
438
+ };
439
+ }
355
440
  function profileStatusFromEvidence(evidence, checks) {
356
441
  if (!evidence) return "proof_insufficient";
357
442
  const viewports = evidence.viewports || [];
@@ -363,7 +448,10 @@ function profileStatusFromEvidence(evidence, checks) {
363
448
  }
364
449
  function assessRiddleProofProfileEvidence(profile, evidence, options = {}) {
365
450
  const capturedAt = evidence?.captured_at || (/* @__PURE__ */ new Date()).toISOString();
366
- const checks = evidence ? profile.checks.map((check) => assessCheckFromEvidence(check, evidence)) : [];
451
+ const checks = evidence ? [
452
+ assessSetupActionsFromEvidence(profile, evidence),
453
+ ...profile.checks.map((check) => assessCheckFromEvidence(check, evidence))
454
+ ].filter((check) => Boolean(check)) : [];
367
455
  const status = profileStatusFromEvidence(evidence, checks);
368
456
  const firstViewport = evidence?.viewports?.[0];
369
457
  const screenshots = (evidence?.viewports || []).map((viewport) => viewport.screenshot_label).filter((label) => Boolean(label));
@@ -477,6 +565,47 @@ function textMatches(sample, check) {
477
565
  function assessProfile(profile, evidence) {
478
566
  const checks = [];
479
567
  const viewports = evidence.viewports || [];
568
+ if (profile.target && Array.isArray(profile.target.setup_actions) && profile.target.setup_actions.length) {
569
+ const actionCount = profile.target.setup_actions.length;
570
+ const failed = [];
571
+ for (const viewport of viewports) {
572
+ const results = viewport.setup_action_results || [];
573
+ for (const result of results) {
574
+ if (result && result.ok === false) {
575
+ failed.push({
576
+ viewport: viewport.name,
577
+ action: result.action || result.type || null,
578
+ selector: result.selector || null,
579
+ reason: result.reason || result.error || null,
580
+ });
581
+ }
582
+ }
583
+ if (results.length < actionCount && results.every((result) => !result || result.ok !== false)) {
584
+ failed.push({
585
+ viewport: viewport.name,
586
+ action: "setup_actions",
587
+ selector: null,
588
+ reason: "missing setup action results: " + results.length + "/" + actionCount,
589
+ });
590
+ }
591
+ }
592
+ checks.push({
593
+ type: "setup_actions_succeeded",
594
+ label: "setup actions succeeded",
595
+ status: failed.length ? "failed" : "passed",
596
+ evidence: {
597
+ action_count: actionCount,
598
+ viewports: viewports.map((viewport) => ({
599
+ name: viewport.name,
600
+ ok: (viewport.setup_action_results || []).length >= actionCount
601
+ && (viewport.setup_action_results || []).every((result) => !result || result.ok !== false),
602
+ result_count: (viewport.setup_action_results || []).length,
603
+ })),
604
+ failed,
605
+ },
606
+ message: failed.length ? "Setup actions failed in " + failed.length + " viewport action(s)." : undefined,
607
+ });
608
+ }
480
609
  for (const check of profile.checks || []) {
481
610
  if (check.type === "route_loaded") {
482
611
  const expectedPath = check.expected_path || new URL(evidence.target_url).pathname || "/";
@@ -639,6 +768,92 @@ function textMatches(sample, check) {
639
768
  }
640
769
  return String(sample || "").includes(check.text || "");
641
770
  }
771
+ function setupActionType(action) {
772
+ return String(action && action.type ? action.type : "").replace(/-/g, "_");
773
+ }
774
+ function setupNumber(value, fallback) {
775
+ const number = Number(value);
776
+ return Number.isFinite(number) && number >= 0 ? number : fallback;
777
+ }
778
+ function setupTextMatches(sample, action) {
779
+ if (action.pattern) {
780
+ try { return new RegExp(action.pattern, action.flags || "").test(sample || ""); } catch { return false; }
781
+ }
782
+ return String(sample || "").includes(action.text || "");
783
+ }
784
+ async function setupLocatorText(locator, index) {
785
+ return await locator.nth(index).textContent({ timeout: 1000 }).catch(() => "");
786
+ }
787
+ async function executeSetupAction(action, ordinal) {
788
+ const type = setupActionType(action);
789
+ const base = { ok: false, action: type || "unknown", ordinal, selector: action.selector || null };
790
+ const timeout = setupNumber(action.timeout_ms, 5000);
791
+ try {
792
+ if (type === "wait") {
793
+ const ms = setupNumber(action.ms, 500);
794
+ await page.waitForTimeout(ms);
795
+ return { ...base, ok: true, ms };
796
+ }
797
+ if (type === "wait_for_selector") {
798
+ await page.waitForSelector(action.selector, { state: "visible", timeout });
799
+ return { ...base, ok: true, timeout_ms: timeout };
800
+ }
801
+ if (type === "click") {
802
+ const locator = page.locator(action.selector);
803
+ const count = await locator.count();
804
+ if (!count) return { ...base, reason: "selector_not_found", count };
805
+ let targetIndex = Number.isInteger(action.index) ? action.index : 0;
806
+ let matchedText = null;
807
+ if (action.text || action.pattern) {
808
+ targetIndex = -1;
809
+ for (let index = 0; index < count; index += 1) {
810
+ const text = await setupLocatorText(locator, index);
811
+ if (setupTextMatches(text, action)) {
812
+ targetIndex = index;
813
+ matchedText = text;
814
+ break;
815
+ }
816
+ }
817
+ if (targetIndex < 0) return { ...base, reason: "text_not_found", count };
818
+ }
819
+ if (targetIndex < 0 || targetIndex >= count) return { ...base, reason: "index_out_of_range", count, target_index: targetIndex };
820
+ await locator.nth(targetIndex).click({ timeout });
821
+ return { ...base, ok: true, count, target_index: targetIndex, text: matchedText };
822
+ }
823
+ if (type === "wait_for_text") {
824
+ const locator = page.locator(action.selector);
825
+ const startedAt = Date.now();
826
+ let lastText = "";
827
+ while (Date.now() - startedAt <= timeout) {
828
+ const count = await locator.count().catch(() => 0);
829
+ for (let index = 0; index < count; index += 1) {
830
+ const text = await setupLocatorText(locator, index);
831
+ lastText = text || lastText;
832
+ if (setupTextMatches(text, action)) {
833
+ return { ...base, ok: true, text, target_index: index, timeout_ms: timeout };
834
+ }
835
+ }
836
+ await page.waitForTimeout(100);
837
+ }
838
+ return { ...base, reason: "text_not_found", text: lastText, timeout_ms: timeout };
839
+ }
840
+ return { ...base, reason: "unsupported_action" };
841
+ } catch (error) {
842
+ return { ...base, error: String(error && error.message ? error.message : error).slice(0, 1000) };
843
+ }
844
+ }
845
+ async function executeSetupActions(actions) {
846
+ const results = [];
847
+ for (let index = 0; index < (actions || []).length; index += 1) {
848
+ const action = actions[index] || {};
849
+ const result = await executeSetupAction(action, index);
850
+ results.push(result);
851
+ const afterMs = setupNumber(action.after_ms, 0);
852
+ if (afterMs) await page.waitForTimeout(afterMs);
853
+ if (result.ok === false && action.continue_on_failure !== true) break;
854
+ }
855
+ return results;
856
+ }
642
857
  function expectedPathFor(check) {
643
858
  return check.expected_path || new URL(targetUrl).pathname || "/";
644
859
  }
@@ -673,6 +888,9 @@ async function captureViewport(viewport) {
673
888
  if (!navigationError && profile.target.wait_ms) {
674
889
  await page.waitForTimeout(profile.target.wait_ms);
675
890
  }
891
+ const setupActionResults = (!navigationError && !waitError)
892
+ ? await executeSetupActions(profile.target.setup_actions || [])
893
+ : [];
676
894
  const dom = await page.evaluate(() => {
677
895
  const body = document.body;
678
896
  const documentElement = document.documentElement;
@@ -734,6 +952,7 @@ async function captureViewport(viewport) {
734
952
  overflow_px: Math.max(0, (dom.scroll_width || 0) - (dom.client_width || viewport.width)),
735
953
  selectors,
736
954
  text_matches,
955
+ setup_action_results: setupActionResults,
737
956
  screenshot_label: screenshotLabel,
738
957
  navigation_error: navigationError,
739
958
  wait_error: waitError,
@@ -831,6 +1050,7 @@ function extractRiddleProofProfileResult(input) {
831
1050
  RIDDLE_PROOF_PROFILE_CHECK_TYPES,
832
1051
  RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION,
833
1052
  RIDDLE_PROOF_PROFILE_RESULT_VERSION,
1053
+ RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES,
834
1054
  RIDDLE_PROOF_PROFILE_STATUSES,
835
1055
  RIDDLE_PROOF_PROFILE_VERSION,
836
1056
  assessRiddleProofProfileEvidence,