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