@riddledc/riddle-proof 0.8.78 → 0.8.80
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 +39 -0
- package/dist/advanced/index.d.cts +1 -1
- package/dist/advanced/index.d.ts +1 -1
- package/dist/advanced/proof-run-engine.d.cts +1 -1
- package/dist/advanced/proof-run-engine.d.ts +1 -1
- package/dist/change-proof.js +2 -2
- package/dist/{chunk-7N6X54WG.js → chunk-6T6ZAK77.js} +1 -1
- package/dist/{chunk-RQPCKRKT.js → chunk-A4EF4M3B.js} +1 -1
- package/dist/{chunk-6VFS2JFR.js → chunk-IL7MLYB5.js} +1 -1
- package/dist/{chunk-HSGZV2NK.js → chunk-N7EETHYG.js} +20 -5
- package/dist/{chunk-FCSJZBC5.js → chunk-ZNVYJFR7.js} +341 -4
- package/dist/cli/index.js +5 -5
- package/dist/cli.cjs +354 -5
- package/dist/cli.js +5 -5
- package/dist/index.cjs +344 -4
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +10 -4
- package/dist/pr-comment.js +3 -3
- package/dist/profile/index.cjs +344 -4
- package/dist/profile/index.d.cts +1 -1
- package/dist/profile/index.d.ts +1 -1
- package/dist/profile/index.js +7 -1
- package/dist/profile-suggestions.js +2 -2
- package/dist/profile.cjs +344 -4
- package/dist/profile.d.cts +38 -3
- package/dist/profile.d.ts +38 -3
- package/dist/profile.js +7 -1
- package/dist/{proof-run-engine-DmUqh7Cw.d.cts → proof-run-engine-Baiv6l3A.d.cts} +3 -3
- package/dist/{proof-run-engine-CsQshTUX.d.ts → proof-run-engine-MiKZt9oY.d.ts} +3 -3
- package/dist/proof-run-engine.d.cts +1 -1
- package/dist/proof-run-engine.d.ts +1 -1
- package/examples/profiles/ordered-trace.json +58 -0
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import "../chunk-
|
|
1
|
+
import "../chunk-N7EETHYG.js";
|
|
2
2
|
import "../chunk-5IFZSUPF.js";
|
|
3
3
|
import "../chunk-JFQXAJH2.js";
|
|
4
|
-
import "../chunk-
|
|
5
|
-
import "../chunk-
|
|
6
|
-
import "../chunk-
|
|
4
|
+
import "../chunk-6T6ZAK77.js";
|
|
5
|
+
import "../chunk-A4EF4M3B.js";
|
|
6
|
+
import "../chunk-IL7MLYB5.js";
|
|
7
7
|
import "../chunk-MEVVL4TI.js";
|
|
8
|
-
import "../chunk-
|
|
8
|
+
import "../chunk-ZNVYJFR7.js";
|
|
9
9
|
import "../chunk-KXLEN4SA.js";
|
|
10
10
|
import "../chunk-WLUMLHII.js";
|
|
11
11
|
import "../chunk-CGJX7LJO.js";
|
package/dist/cli.cjs
CHANGED
|
@@ -8775,6 +8775,7 @@ var RIDDLE_PROOF_PROFILE_CHECK_TYPES = [
|
|
|
8775
8775
|
"selector_text_visible",
|
|
8776
8776
|
"selector_text_absent",
|
|
8777
8777
|
"selector_text_order",
|
|
8778
|
+
"ordered_trace",
|
|
8778
8779
|
"observe_within",
|
|
8779
8780
|
"frame_text_visible",
|
|
8780
8781
|
"frame_url_equals",
|
|
@@ -8838,6 +8839,21 @@ var RIDDLE_PROOF_PROFILE_NETWORK_ABORT_ERROR_CODES = [
|
|
|
8838
8839
|
"timedout",
|
|
8839
8840
|
"failed"
|
|
8840
8841
|
];
|
|
8842
|
+
var RIDDLE_PROOF_ORDERED_TRACE_OPERATORS = [
|
|
8843
|
+
"exists",
|
|
8844
|
+
"equals",
|
|
8845
|
+
"not_equals",
|
|
8846
|
+
"truthy",
|
|
8847
|
+
"falsy",
|
|
8848
|
+
"gt",
|
|
8849
|
+
"gte",
|
|
8850
|
+
"lt",
|
|
8851
|
+
"lte",
|
|
8852
|
+
"abs_gt",
|
|
8853
|
+
"abs_gte",
|
|
8854
|
+
"abs_lt",
|
|
8855
|
+
"abs_lte"
|
|
8856
|
+
];
|
|
8841
8857
|
function uniqueNonEmptyStrings(values) {
|
|
8842
8858
|
const seen = /* @__PURE__ */ new Set();
|
|
8843
8859
|
const result = [];
|
|
@@ -9129,6 +9145,185 @@ function resolveJsonPath(root, path7) {
|
|
|
9129
9145
|
}
|
|
9130
9146
|
return { exists: true, value: current };
|
|
9131
9147
|
}
|
|
9148
|
+
function assessRiddleProofOrderedTrace(trace, events) {
|
|
9149
|
+
const insufficient = (reason, traceLength = Array.isArray(trace) ? trace.length : 0, witnesses2 = [], missingEvent, missingPaths) => ({
|
|
9150
|
+
version: "riddle-proof.ordered-trace-assessment.v1",
|
|
9151
|
+
status: "proof_insufficient",
|
|
9152
|
+
trace_length: traceLength,
|
|
9153
|
+
witnesses: witnesses2,
|
|
9154
|
+
missing_event: missingEvent,
|
|
9155
|
+
missing_paths: missingPaths,
|
|
9156
|
+
reason
|
|
9157
|
+
});
|
|
9158
|
+
const parsePath = (path7) => {
|
|
9159
|
+
const segments = [];
|
|
9160
|
+
let token = "";
|
|
9161
|
+
const pushToken = () => {
|
|
9162
|
+
const value = token.trim();
|
|
9163
|
+
if (value) segments.push(value);
|
|
9164
|
+
token = "";
|
|
9165
|
+
};
|
|
9166
|
+
for (let index = 0; index < path7.length; index += 1) {
|
|
9167
|
+
const char = path7[index];
|
|
9168
|
+
if (char === ".") {
|
|
9169
|
+
pushToken();
|
|
9170
|
+
continue;
|
|
9171
|
+
}
|
|
9172
|
+
if (char !== "[") {
|
|
9173
|
+
token += char;
|
|
9174
|
+
continue;
|
|
9175
|
+
}
|
|
9176
|
+
pushToken();
|
|
9177
|
+
const closeIndex = path7.indexOf("]", index + 1);
|
|
9178
|
+
if (closeIndex === -1) throw new Error(`unterminated bracket at ${index}`);
|
|
9179
|
+
const bracket = path7.slice(index + 1, closeIndex).trim();
|
|
9180
|
+
if (!bracket) throw new Error(`empty bracket at ${index}`);
|
|
9181
|
+
if (/^\d+$/.test(bracket)) {
|
|
9182
|
+
segments.push(Number(bracket));
|
|
9183
|
+
} else {
|
|
9184
|
+
segments.push(bracket.replace(/^['"]|['"]$/g, ""));
|
|
9185
|
+
}
|
|
9186
|
+
index = closeIndex;
|
|
9187
|
+
}
|
|
9188
|
+
pushToken();
|
|
9189
|
+
return segments;
|
|
9190
|
+
};
|
|
9191
|
+
const resolve = (root, path7) => {
|
|
9192
|
+
let segments;
|
|
9193
|
+
try {
|
|
9194
|
+
segments = parsePath(path7);
|
|
9195
|
+
} catch {
|
|
9196
|
+
return { exists: false };
|
|
9197
|
+
}
|
|
9198
|
+
let current = root;
|
|
9199
|
+
for (const segment of segments) {
|
|
9200
|
+
if (Array.isArray(current)) {
|
|
9201
|
+
const index = typeof segment === "number" ? segment : /^\d+$/.test(segment) ? Number(segment) : -1;
|
|
9202
|
+
if (index < 0 || index >= current.length) return { exists: false };
|
|
9203
|
+
current = current[index];
|
|
9204
|
+
continue;
|
|
9205
|
+
}
|
|
9206
|
+
if (typeof segment !== "string" || current === null || typeof current !== "object") return { exists: false };
|
|
9207
|
+
if (!Object.hasOwn(current, segment)) return { exists: false };
|
|
9208
|
+
current = current[segment];
|
|
9209
|
+
}
|
|
9210
|
+
return { exists: true, value: current };
|
|
9211
|
+
};
|
|
9212
|
+
const valuesEqual = (left, right) => {
|
|
9213
|
+
if (Object.is(left, right)) return true;
|
|
9214
|
+
if (Array.isArray(left) || Array.isArray(right)) {
|
|
9215
|
+
return Array.isArray(left) && Array.isArray(right) && left.length === right.length && left.every((value, index) => valuesEqual(value, right[index]));
|
|
9216
|
+
}
|
|
9217
|
+
if (left === null || right === null || typeof left !== "object" || typeof right !== "object") return false;
|
|
9218
|
+
const leftRecord = left;
|
|
9219
|
+
const rightRecord = right;
|
|
9220
|
+
const leftKeys = Object.keys(leftRecord).sort();
|
|
9221
|
+
const rightKeys = Object.keys(rightRecord).sort();
|
|
9222
|
+
return leftKeys.length === rightKeys.length && leftKeys.every((key, index) => key === rightKeys[index] && valuesEqual(leftRecord[key], rightRecord[key]));
|
|
9223
|
+
};
|
|
9224
|
+
const numericOperator = (op) => [
|
|
9225
|
+
"gt",
|
|
9226
|
+
"gte",
|
|
9227
|
+
"lt",
|
|
9228
|
+
"lte",
|
|
9229
|
+
"abs_gt",
|
|
9230
|
+
"abs_gte",
|
|
9231
|
+
"abs_lt",
|
|
9232
|
+
"abs_lte"
|
|
9233
|
+
].includes(op);
|
|
9234
|
+
const matches = (value, predicate) => {
|
|
9235
|
+
if (predicate.op === "exists") return true;
|
|
9236
|
+
if (predicate.op === "equals") return valuesEqual(value, predicate.value);
|
|
9237
|
+
if (predicate.op === "not_equals") return !valuesEqual(value, predicate.value);
|
|
9238
|
+
if (predicate.op === "truthy") return Boolean(value);
|
|
9239
|
+
if (predicate.op === "falsy") return !value;
|
|
9240
|
+
const observed = typeof value === "number" ? value : Number.NaN;
|
|
9241
|
+
const expected = typeof predicate.value === "number" ? predicate.value : Number.NaN;
|
|
9242
|
+
if (!Number.isFinite(observed) || !Number.isFinite(expected)) return false;
|
|
9243
|
+
const candidate = predicate.op.startsWith("abs_") ? Math.abs(observed) : observed;
|
|
9244
|
+
if (predicate.op === "gt" || predicate.op === "abs_gt") return candidate > expected;
|
|
9245
|
+
if (predicate.op === "gte" || predicate.op === "abs_gte") return candidate >= expected;
|
|
9246
|
+
if (predicate.op === "lt" || predicate.op === "abs_lt") return candidate < expected;
|
|
9247
|
+
return candidate <= expected;
|
|
9248
|
+
};
|
|
9249
|
+
if (!Array.isArray(trace) || trace.length === 0) return insufficient("trace_missing_or_empty");
|
|
9250
|
+
if (!Array.isArray(events) || events.length === 0) return insufficient("events_missing", trace.length);
|
|
9251
|
+
for (const event of events) {
|
|
9252
|
+
const missingPaths = event.predicates.filter((predicate) => !trace.some((sample) => {
|
|
9253
|
+
const resolved = resolve(sample, predicate.path);
|
|
9254
|
+
return resolved.exists && (!numericOperator(predicate.op) || typeof resolved.value === "number" && Number.isFinite(resolved.value));
|
|
9255
|
+
})).map((predicate) => predicate.path);
|
|
9256
|
+
if (missingPaths.length) {
|
|
9257
|
+
return insufficient("required_trace_field_missing", trace.length, [], event.label, Array.from(new Set(missingPaths)));
|
|
9258
|
+
}
|
|
9259
|
+
}
|
|
9260
|
+
const witnesses = [];
|
|
9261
|
+
let cursor = 0;
|
|
9262
|
+
for (const event of events) {
|
|
9263
|
+
let witnessIndex = -1;
|
|
9264
|
+
for (let index = cursor; index < trace.length; index += 1) {
|
|
9265
|
+
if (event.predicates.every((predicate) => {
|
|
9266
|
+
const resolved = resolve(trace[index], predicate.path);
|
|
9267
|
+
return resolved.exists && matches(resolved.value, predicate);
|
|
9268
|
+
})) {
|
|
9269
|
+
witnessIndex = index;
|
|
9270
|
+
break;
|
|
9271
|
+
}
|
|
9272
|
+
}
|
|
9273
|
+
if (witnessIndex < 0) {
|
|
9274
|
+
return {
|
|
9275
|
+
version: "riddle-proof.ordered-trace-assessment.v1",
|
|
9276
|
+
status: "failed",
|
|
9277
|
+
trace_length: trace.length,
|
|
9278
|
+
witnesses,
|
|
9279
|
+
missing_event: event.label,
|
|
9280
|
+
reason: "ordered_event_not_observed"
|
|
9281
|
+
};
|
|
9282
|
+
}
|
|
9283
|
+
witnesses.push({
|
|
9284
|
+
label: event.label,
|
|
9285
|
+
index: witnessIndex,
|
|
9286
|
+
observations: event.predicates.map((predicate) => {
|
|
9287
|
+
const observed = resolve(trace[witnessIndex], predicate.path).value;
|
|
9288
|
+
return {
|
|
9289
|
+
path: predicate.path,
|
|
9290
|
+
op: predicate.op,
|
|
9291
|
+
expected: predicate.value,
|
|
9292
|
+
observed
|
|
9293
|
+
};
|
|
9294
|
+
})
|
|
9295
|
+
});
|
|
9296
|
+
cursor = witnessIndex + 1;
|
|
9297
|
+
}
|
|
9298
|
+
return {
|
|
9299
|
+
version: "riddle-proof.ordered-trace-assessment.v1",
|
|
9300
|
+
status: "passed",
|
|
9301
|
+
trace_length: trace.length,
|
|
9302
|
+
witnesses
|
|
9303
|
+
};
|
|
9304
|
+
}
|
|
9305
|
+
function assessRiddleProofOrderedTraceSetupResults(results, setupActionLabel, tracePath, events) {
|
|
9306
|
+
const insufficient = (reason) => ({
|
|
9307
|
+
version: "riddle-proof.ordered-trace-assessment.v1",
|
|
9308
|
+
status: "proof_insufficient",
|
|
9309
|
+
trace_length: 0,
|
|
9310
|
+
witnesses: [],
|
|
9311
|
+
reason
|
|
9312
|
+
});
|
|
9313
|
+
if (!Array.isArray(results)) return insufficient("setup_results_missing");
|
|
9314
|
+
const source = results.find((item) => item && typeof item === "object" && !Array.isArray(item) && item.label === setupActionLabel);
|
|
9315
|
+
if (!source) return insufficient("setup_action_result_missing");
|
|
9316
|
+
if (!Object.hasOwn(source, "returned")) return insufficient("setup_action_return_missing");
|
|
9317
|
+
const segments = tracePath.split(".").map((segment) => segment.trim()).filter(Boolean);
|
|
9318
|
+
let trace = source.returned;
|
|
9319
|
+
for (const segment of segments) {
|
|
9320
|
+
if (trace === null || typeof trace !== "object" || Array.isArray(trace) || !Object.hasOwn(trace, segment)) {
|
|
9321
|
+
return insufficient("trace_path_missing");
|
|
9322
|
+
}
|
|
9323
|
+
trace = trace[segment];
|
|
9324
|
+
}
|
|
9325
|
+
return assessRiddleProofOrderedTrace(trace, events);
|
|
9326
|
+
}
|
|
9132
9327
|
function evaluateHttpStatusBodyJsonAssertion(root, assertion) {
|
|
9133
9328
|
const resolved = resolveJsonPath(root, assertion.path);
|
|
9134
9329
|
const errors = [];
|
|
@@ -9235,6 +9430,7 @@ function profileSetupWindowCallReceipts(results) {
|
|
|
9235
9430
|
return results.filter((result) => profileSetupResultAction(result) === "window_call").map((result) => {
|
|
9236
9431
|
const receipt = {
|
|
9237
9432
|
ordinal: result.ordinal ?? null,
|
|
9433
|
+
label: result.label ?? null,
|
|
9238
9434
|
ok: result.ok !== false,
|
|
9239
9435
|
path: result.path ?? null,
|
|
9240
9436
|
return_captured: result.return_captured ?? null,
|
|
@@ -9253,6 +9449,7 @@ function profileSetupWindowEvalReceipts(results) {
|
|
|
9253
9449
|
return results.filter((result) => profileSetupResultAction(result) === "window_eval").map((result) => {
|
|
9254
9450
|
const receipt = {
|
|
9255
9451
|
ordinal: result.ordinal ?? null,
|
|
9452
|
+
label: result.label ?? null,
|
|
9256
9453
|
ok: result.ok !== false,
|
|
9257
9454
|
script_length: result.script_length ?? null,
|
|
9258
9455
|
return_captured: result.return_captured ?? null,
|
|
@@ -10525,6 +10722,51 @@ function dialogCountFieldForCheckType(type) {
|
|
|
10525
10722
|
if (type === "dialog_dismiss_count_equals") return "dialog_dismiss_count";
|
|
10526
10723
|
return "dialog_count";
|
|
10527
10724
|
}
|
|
10725
|
+
function normalizeOrderedTraceEvents(value, label) {
|
|
10726
|
+
if (value === void 0) return void 0;
|
|
10727
|
+
if (!Array.isArray(value) || !value.length) throw new Error(`${label} must be a non-empty array.`);
|
|
10728
|
+
const seenLabels = /* @__PURE__ */ new Set();
|
|
10729
|
+
return value.map((item, eventIndex) => {
|
|
10730
|
+
const eventLabel = `${label}[${eventIndex}]`;
|
|
10731
|
+
if (!isRecord2(item)) throw new Error(`${eventLabel} must be an object.`);
|
|
10732
|
+
const name = stringFromOwn(item, "label", "name", "event");
|
|
10733
|
+
if (!name) throw new Error(`${eventLabel}.label is required.`);
|
|
10734
|
+
if (seenLabels.has(name)) throw new Error(`${eventLabel}.label must be unique.`);
|
|
10735
|
+
seenLabels.add(name);
|
|
10736
|
+
const predicatesInput = item.predicates ?? item.all ?? item.where;
|
|
10737
|
+
if (!Array.isArray(predicatesInput) || !predicatesInput.length) {
|
|
10738
|
+
throw new Error(`${eventLabel}.predicates must be a non-empty array.`);
|
|
10739
|
+
}
|
|
10740
|
+
const predicates = predicatesInput.map((predicateInput, predicateIndex) => {
|
|
10741
|
+
const predicateLabel = `${eventLabel}.predicates[${predicateIndex}]`;
|
|
10742
|
+
if (!isRecord2(predicateInput)) throw new Error(`${predicateLabel} must be an object.`);
|
|
10743
|
+
const path7 = stringFromOwn(predicateInput, "path", "field", "key");
|
|
10744
|
+
if (!path7) throw new Error(`${predicateLabel}.path is required.`);
|
|
10745
|
+
const op = stringFromOwn(predicateInput, "op", "operator");
|
|
10746
|
+
if (!op || !RIDDLE_PROOF_ORDERED_TRACE_OPERATORS.includes(op)) {
|
|
10747
|
+
throw new Error(`${predicateLabel}.op must be one of ${RIDDLE_PROOF_ORDERED_TRACE_OPERATORS.join(", ")}.`);
|
|
10748
|
+
}
|
|
10749
|
+
const requiresValue = !["exists", "truthy", "falsy"].includes(op);
|
|
10750
|
+
const hasValue = hasOwn(predicateInput, "value") || hasOwn(predicateInput, "expected");
|
|
10751
|
+
if (requiresValue && !hasValue) throw new Error(`${predicateLabel}.value is required for ${op}.`);
|
|
10752
|
+
const value2 = hasOwn(predicateInput, "value") ? predicateInput.value : predicateInput.expected;
|
|
10753
|
+
if (["gt", "gte", "lt", "lte", "abs_gt", "abs_gte", "abs_lt", "abs_lte"].includes(op)) {
|
|
10754
|
+
if (typeof value2 !== "number" || !Number.isFinite(value2)) {
|
|
10755
|
+
throw new Error(`${predicateLabel}.value must be a finite number for ${op}.`);
|
|
10756
|
+
}
|
|
10757
|
+
if (op.startsWith("abs_") && value2 < 0) {
|
|
10758
|
+
throw new Error(`${predicateLabel}.value must be non-negative for ${op}.`);
|
|
10759
|
+
}
|
|
10760
|
+
}
|
|
10761
|
+
return {
|
|
10762
|
+
path: path7,
|
|
10763
|
+
op,
|
|
10764
|
+
value: requiresValue ? toJsonValue(value2) : void 0
|
|
10765
|
+
};
|
|
10766
|
+
});
|
|
10767
|
+
return { label: name, predicates };
|
|
10768
|
+
});
|
|
10769
|
+
}
|
|
10528
10770
|
function normalizeCheck(input, index) {
|
|
10529
10771
|
if (!isRecord2(input)) throw new Error(`checks[${index}] must be an object.`);
|
|
10530
10772
|
const type = stringValue3(input.type);
|
|
@@ -10575,6 +10817,17 @@ function normalizeCheck(input, index) {
|
|
|
10575
10817
|
if (!stringValue3(input.selector)) throw new Error(`checks[${index}] selector_text_order requires selector.`);
|
|
10576
10818
|
if (!expectedTexts?.length) throw new Error(`checks[${index}] selector_text_order requires expected_texts.`);
|
|
10577
10819
|
}
|
|
10820
|
+
const setupActionLabel = stringFromOwn(input, "setup_action_label", "setupActionLabel", "source_action_label", "sourceActionLabel");
|
|
10821
|
+
const tracePath = stringFromOwn(input, "trace_path", "tracePath", "path");
|
|
10822
|
+
const orderedTraceEvents = normalizeOrderedTraceEvents(
|
|
10823
|
+
input.events ?? input.sequence ?? input.ordered_events ?? input.orderedEvents,
|
|
10824
|
+
`checks[${index}].events`
|
|
10825
|
+
);
|
|
10826
|
+
if (type === "ordered_trace") {
|
|
10827
|
+
if (!setupActionLabel) throw new Error(`checks[${index}] ordered_trace requires setup_action_label.`);
|
|
10828
|
+
if (!tracePath) throw new Error(`checks[${index}] ordered_trace requires trace_path.`);
|
|
10829
|
+
if (!orderedTraceEvents?.length) throw new Error(`checks[${index}] ordered_trace requires events.`);
|
|
10830
|
+
}
|
|
10578
10831
|
const expectedRoutes = normalizeRouteInventoryRoutes(input.expected_routes ?? input.expectedRoutes, index);
|
|
10579
10832
|
if (type === "route_inventory" && !expectedRoutes?.length) {
|
|
10580
10833
|
throw new Error(`checks[${index}] route_inventory requires expected_routes.`);
|
|
@@ -10647,6 +10900,9 @@ function normalizeCheck(input, index) {
|
|
|
10647
10900
|
body_not_patterns: bodyNotPatterns,
|
|
10648
10901
|
body_json_assertions: bodyJsonAssertions,
|
|
10649
10902
|
expected_texts: expectedTexts,
|
|
10903
|
+
setup_action_label: type === "ordered_trace" ? setupActionLabel : void 0,
|
|
10904
|
+
trace_path: type === "ordered_trace" ? tracePath : void 0,
|
|
10905
|
+
events: type === "ordered_trace" ? orderedTraceEvents : void 0,
|
|
10650
10906
|
link_selector: stringValue3(input.link_selector) || stringValue3(input.linkSelector),
|
|
10651
10907
|
source_selector: stringValue3(input.source_selector) || stringValue3(input.sourceSelector),
|
|
10652
10908
|
route_path_prefix: stringValue3(input.route_path_prefix) || stringValue3(input.routePathPrefix),
|
|
@@ -10713,6 +10969,20 @@ function normalizeRiddleProofProfile(input, options = {}) {
|
|
|
10713
10969
|
const targetUrl = stringValue3(options.url) || stringValue3(targetInput.url);
|
|
10714
10970
|
const route = stringValue3(options.route) || stringValue3(targetInput.route);
|
|
10715
10971
|
if (!targetUrl && !route) throw new Error("profile.target requires url or route, or pass --url.");
|
|
10972
|
+
const setupActions = normalizeSetupActions(targetInput.setup_actions ?? targetInput.setupActions);
|
|
10973
|
+
for (const [index, check] of checks.entries()) {
|
|
10974
|
+
if (check.type !== "ordered_trace") continue;
|
|
10975
|
+
const matches = (setupActions || []).filter((action) => action.label === check.setup_action_label);
|
|
10976
|
+
if (matches.length !== 1) {
|
|
10977
|
+
throw new Error(`checks[${index}] ordered_trace setup_action_label must match exactly one target.setup_actions label.`);
|
|
10978
|
+
}
|
|
10979
|
+
if (!["window_eval", "window_call", "window_call_until"].includes(matches[0].type)) {
|
|
10980
|
+
throw new Error(`checks[${index}] ordered_trace source action must capture a window_eval, window_call, or window_call_until return.`);
|
|
10981
|
+
}
|
|
10982
|
+
if (matches[0].capture_return === false) {
|
|
10983
|
+
throw new Error(`checks[${index}] ordered_trace source action must not set capture_return to false.`);
|
|
10984
|
+
}
|
|
10985
|
+
}
|
|
10716
10986
|
return {
|
|
10717
10987
|
version: RIDDLE_PROOF_PROFILE_VERSION,
|
|
10718
10988
|
name: normalizeName(input.name, "riddle-proof-profile"),
|
|
@@ -10725,7 +10995,7 @@ function normalizeRiddleProofProfile(input, options = {}) {
|
|
|
10725
10995
|
wait_for_selector: stringValue3(targetInput.wait_for_selector) || stringValue3(targetInput.waitForSelector),
|
|
10726
10996
|
wait_ms: numberValue2(targetInput.wait_ms) ?? numberValue2(targetInput.waitMs),
|
|
10727
10997
|
screenshot_full_page: normalizeTargetScreenshotFullPage(targetInput),
|
|
10728
|
-
setup_actions:
|
|
10998
|
+
setup_actions: setupActions,
|
|
10729
10999
|
network_mocks: normalizeNetworkMocks(targetInput.network_mocks ?? targetInput.networkMocks)
|
|
10730
11000
|
},
|
|
10731
11001
|
checks,
|
|
@@ -11738,6 +12008,32 @@ function assessCheckFromEvidence(check, evidence) {
|
|
|
11738
12008
|
message: failed ? `Selector ${key} text order failed in ${failed} viewport(s).` : void 0
|
|
11739
12009
|
};
|
|
11740
12010
|
}
|
|
12011
|
+
if (check.type === "ordered_trace") {
|
|
12012
|
+
const assessments = viewports.map((viewport) => ({
|
|
12013
|
+
viewport: viewport.name,
|
|
12014
|
+
assessment: assessRiddleProofOrderedTraceSetupResults(
|
|
12015
|
+
viewport.setup_action_results,
|
|
12016
|
+
check.setup_action_label || "",
|
|
12017
|
+
check.trace_path || "",
|
|
12018
|
+
check.events || []
|
|
12019
|
+
)
|
|
12020
|
+
}));
|
|
12021
|
+
const insufficient = assessments.filter((item) => item.assessment.status === "proof_insufficient");
|
|
12022
|
+
const failed = assessments.filter((item) => item.assessment.status === "failed");
|
|
12023
|
+
const status = insufficient.length ? "proof_insufficient" : failed.length ? "failed" : "passed";
|
|
12024
|
+
return {
|
|
12025
|
+
type: check.type,
|
|
12026
|
+
label: checkLabel(check),
|
|
12027
|
+
status,
|
|
12028
|
+
evidence: {
|
|
12029
|
+
setup_action_label: check.setup_action_label || "",
|
|
12030
|
+
trace_path: check.trace_path || "",
|
|
12031
|
+
events: toJsonValue((check.events || []).map((event) => event.label)),
|
|
12032
|
+
viewports: toJsonValue(assessments)
|
|
12033
|
+
},
|
|
12034
|
+
message: insufficient.length ? `Ordered trace evidence was insufficient in ${insufficient.length} viewport(s).` : failed.length ? `Ordered trace did not contain the required event sequence in ${failed.length} viewport(s).` : void 0
|
|
12035
|
+
};
|
|
12036
|
+
}
|
|
11741
12037
|
if (check.type === "observe_within") {
|
|
11742
12038
|
const key = observeWithinKey(check);
|
|
11743
12039
|
const timeoutMs = observeWithinTimeoutMs(check);
|
|
@@ -12237,6 +12533,7 @@ function profileStatusFromEvidence(profile, evidence, checks) {
|
|
|
12237
12533
|
if (!viewports.length || !checks.length) return "proof_insufficient";
|
|
12238
12534
|
if (viewports.some((viewport) => viewport.navigation_error)) return "environment_blocked";
|
|
12239
12535
|
if (expectedViewportCount && viewports.length < expectedViewportCount) return "proof_insufficient";
|
|
12536
|
+
if (checks.some((check) => check.status === "proof_insufficient")) return "proof_insufficient";
|
|
12240
12537
|
if (checks.some((check) => check.status === "needs_human_review")) return "needs_human_review";
|
|
12241
12538
|
if (checks.some((check) => check.status === "failed")) return "product_regression";
|
|
12242
12539
|
return "passed";
|
|
@@ -12566,8 +12863,12 @@ function createRiddleProofProfileInsufficientResult(input) {
|
|
|
12566
12863
|
error: message
|
|
12567
12864
|
};
|
|
12568
12865
|
}
|
|
12569
|
-
function runtimeScriptAssessmentSource() {
|
|
12866
|
+
function runtimeScriptAssessmentSource(includeOrderedTrace = false) {
|
|
12867
|
+
const orderedTraceSource = includeOrderedTrace ? String.raw`
|
|
12868
|
+
const assessRiddleProofOrderedTrace = ${assessRiddleProofOrderedTrace.toString()};
|
|
12869
|
+
const assessRiddleProofOrderedTraceSetupResults = ${assessRiddleProofOrderedTraceSetupResults.toString()};` : "";
|
|
12570
12870
|
return String.raw`
|
|
12871
|
+
${orderedTraceSource}
|
|
12571
12872
|
function normalizeRoutePath(path) {
|
|
12572
12873
|
const value = path || "/";
|
|
12573
12874
|
if (value === "/") return "/";
|
|
@@ -13397,6 +13698,7 @@ function profileSetupWindowCallReceipts(results) {
|
|
|
13397
13698
|
.map((result) => {
|
|
13398
13699
|
const receipt = {
|
|
13399
13700
|
ordinal: result.ordinal ?? null,
|
|
13701
|
+
label: result.label ?? null,
|
|
13400
13702
|
ok: result.ok !== false,
|
|
13401
13703
|
path: result.path ?? null,
|
|
13402
13704
|
return_captured: result.return_captured ?? null,
|
|
@@ -13417,6 +13719,7 @@ function profileSetupWindowEvalReceipts(results) {
|
|
|
13417
13719
|
.map((result) => {
|
|
13418
13720
|
const receipt = {
|
|
13419
13721
|
ordinal: result.ordinal ?? null,
|
|
13722
|
+
label: result.label ?? null,
|
|
13420
13723
|
ok: result.ok !== false,
|
|
13421
13724
|
script_length: result.script_length ?? null,
|
|
13422
13725
|
return_captured: result.return_captured ?? null,
|
|
@@ -14232,6 +14535,36 @@ function assessProfile(profile, evidence) {
|
|
|
14232
14535
|
});
|
|
14233
14536
|
continue;
|
|
14234
14537
|
}
|
|
14538
|
+
if (check.type === "ordered_trace") {
|
|
14539
|
+
const assessments = checkViewports.map((viewport) => ({
|
|
14540
|
+
viewport: viewport.name,
|
|
14541
|
+
assessment: assessRiddleProofOrderedTraceSetupResults(
|
|
14542
|
+
viewport.setup_action_results,
|
|
14543
|
+
check.setup_action_label || "",
|
|
14544
|
+
check.trace_path || "",
|
|
14545
|
+
check.events || [],
|
|
14546
|
+
),
|
|
14547
|
+
}));
|
|
14548
|
+
const insufficient = assessments.filter((item) => item.assessment.status === "proof_insufficient");
|
|
14549
|
+
const failed = assessments.filter((item) => item.assessment.status === "failed");
|
|
14550
|
+
checks.push({
|
|
14551
|
+
type: check.type,
|
|
14552
|
+
label: check.label || check.type,
|
|
14553
|
+
status: insufficient.length ? "proof_insufficient" : failed.length ? "failed" : "passed",
|
|
14554
|
+
evidence: {
|
|
14555
|
+
setup_action_label: check.setup_action_label || "",
|
|
14556
|
+
trace_path: check.trace_path || "",
|
|
14557
|
+
events: (check.events || []).map((event) => event.label),
|
|
14558
|
+
viewports: assessments,
|
|
14559
|
+
},
|
|
14560
|
+
message: insufficient.length
|
|
14561
|
+
? "Ordered trace evidence was insufficient in " + insufficient.length + " viewport(s)."
|
|
14562
|
+
: failed.length
|
|
14563
|
+
? "Ordered trace did not contain the required event sequence in " + failed.length + " viewport(s)."
|
|
14564
|
+
: undefined,
|
|
14565
|
+
});
|
|
14566
|
+
continue;
|
|
14567
|
+
}
|
|
14235
14568
|
if (check.type === "observe_within") {
|
|
14236
14569
|
const key = observeWithinKey(check);
|
|
14237
14570
|
const timeoutMs = observeWithinTimeoutMs(check);
|
|
@@ -14588,6 +14921,7 @@ function assessProfile(profile, evidence) {
|
|
|
14588
14921
|
if (!viewports.length || !checks.length) status = "proof_insufficient";
|
|
14589
14922
|
else if (viewports.some((viewport) => viewport.navigation_error)) status = "environment_blocked";
|
|
14590
14923
|
else if (expectedViewportCount && viewports.length < expectedViewportCount) status = "proof_insufficient";
|
|
14924
|
+
else if (checks.some((check) => check.status === "proof_insufficient")) status = "proof_insufficient";
|
|
14591
14925
|
else if (checks.some((check) => check.status === "needs_human_review")) status = "needs_human_review";
|
|
14592
14926
|
else if (checks.some((check) => check.status === "failed")) status = "product_regression";
|
|
14593
14927
|
const screenshotLabels = profileScreenshotLabels(viewports);
|
|
@@ -15519,7 +15853,7 @@ let activeViewportName = null;
|
|
|
15519
15853
|
async function executeSetupAction(action, ordinal, viewport) {
|
|
15520
15854
|
const type = setupActionType(action);
|
|
15521
15855
|
const frameSelector = setupFrameSelector(action);
|
|
15522
|
-
const base = { ok: false, action: type || "unknown", ordinal, selector: action.selector || null, frame_selector: frameSelector || null, optional: action.optional === true };
|
|
15856
|
+
const base = { ok: false, action: type || "unknown", ordinal, label: action.label || null, selector: action.selector || null, frame_selector: frameSelector || null, optional: action.optional === true };
|
|
15523
15857
|
const timeout = setupNumber(action.timeout_ms, 5000);
|
|
15524
15858
|
try {
|
|
15525
15859
|
if (type === "wait") {
|
|
@@ -18171,7 +18505,7 @@ async function captureViewport(viewport) {
|
|
|
18171
18505
|
wait_error: waitError,
|
|
18172
18506
|
};
|
|
18173
18507
|
}
|
|
18174
|
-
${runtimeScriptAssessmentSource()}
|
|
18508
|
+
${runtimeScriptAssessmentSource(profile.checks.some((check) => check.type === "ordered_trace"))}
|
|
18175
18509
|
const viewports = [];
|
|
18176
18510
|
function buildProfileEvidence(currentViewports) {
|
|
18177
18511
|
const expectedViewportCount = (profile.target.viewports || []).length;
|
|
@@ -23812,7 +24146,22 @@ function profileHttpStatusSummaryMarkdown(result) {
|
|
|
23812
24146
|
}
|
|
23813
24147
|
function profileResultTargetUrl(result) {
|
|
23814
24148
|
const legacyRoute = result.route;
|
|
23815
|
-
|
|
24149
|
+
const observed = result.route.observed;
|
|
24150
|
+
const requested = result.route.requested || legacyRoute.url || result.evidence?.target_url;
|
|
24151
|
+
if (observed) {
|
|
24152
|
+
try {
|
|
24153
|
+
return new URL(observed, requested).href;
|
|
24154
|
+
} catch {
|
|
24155
|
+
}
|
|
24156
|
+
}
|
|
24157
|
+
if (requested) {
|
|
24158
|
+
try {
|
|
24159
|
+
return new URL(requested).href;
|
|
24160
|
+
} catch {
|
|
24161
|
+
return requested;
|
|
24162
|
+
}
|
|
24163
|
+
}
|
|
24164
|
+
return observed || "unknown";
|
|
23816
24165
|
}
|
|
23817
24166
|
function profileObservationForOutput(result, outputDir, options) {
|
|
23818
24167
|
if (options.observation) return options.observation;
|
package/dist/cli.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import "./chunk-
|
|
2
|
+
import "./chunk-N7EETHYG.js";
|
|
3
3
|
import "./chunk-5IFZSUPF.js";
|
|
4
4
|
import "./chunk-JFQXAJH2.js";
|
|
5
|
-
import "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
5
|
+
import "./chunk-6T6ZAK77.js";
|
|
6
|
+
import "./chunk-A4EF4M3B.js";
|
|
7
|
+
import "./chunk-IL7MLYB5.js";
|
|
8
8
|
import "./chunk-MEVVL4TI.js";
|
|
9
|
-
import "./chunk-
|
|
9
|
+
import "./chunk-ZNVYJFR7.js";
|
|
10
10
|
import "./chunk-KXLEN4SA.js";
|
|
11
11
|
import "./chunk-WLUMLHII.js";
|
|
12
12
|
import "./chunk-CGJX7LJO.js";
|