@riddledc/riddle-proof 0.8.63 → 0.8.65
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 +16 -0
- package/dist/chunk-5Y4V2IXI.js +178 -0
- package/dist/{chunk-DI2XNGEZ.js → chunk-B2DP2LET.js} +4 -1
- package/dist/{chunk-DDAV6D6K.js → chunk-JPRKO2DH.js} +52 -4
- package/dist/cli/index.js +3 -2
- package/dist/cli.cjs +220 -4
- package/dist/cli.js +3 -2
- package/dist/index.cjs +179 -1
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +9 -1
- package/dist/profile-suggestions.cjs +204 -0
- package/dist/profile-suggestions.d.cts +36 -0
- package/dist/profile-suggestions.d.ts +36 -0
- package/dist/profile-suggestions.js +10 -0
- package/dist/riddle-client.cjs +5 -1
- package/dist/riddle-client.d.cts +2 -1
- package/dist/riddle-client.d.ts +2 -1
- package/dist/riddle-client.js +3 -1
- package/dist/runtime/index.cjs +5 -1
- package/dist/runtime/index.d.cts +1 -1
- package/dist/runtime/index.d.ts +1 -1
- package/dist/runtime/index.js +3 -1
- package/dist/runtime/riddle-client.cjs +5 -1
- package/dist/runtime/riddle-client.d.cts +1 -1
- package/dist/runtime/riddle-client.d.ts +1 -1
- package/dist/runtime/riddle-client.js +3 -1
- package/package.json +7 -2
- package/runtime/lib/ship.py +60 -0
- package/runtime/tests/ship_artifact_publication.py +55 -0
package/README.md
CHANGED
|
@@ -179,6 +179,22 @@ or as a stronger proof base before a change loop.
|
|
|
179
179
|
}
|
|
180
180
|
```
|
|
181
181
|
|
|
182
|
+
For early proof authoring, `profile-suggest` can turn a route plus changed file,
|
|
183
|
+
selector, and changed-text hints into a conservative draft profile:
|
|
184
|
+
|
|
185
|
+
```sh
|
|
186
|
+
riddle-proof-loop profile-suggest \
|
|
187
|
+
--route /games/signal-sprint \
|
|
188
|
+
--changed-files src/Games/SignalSprint.jsx,src/Games/SignalSprint.css \
|
|
189
|
+
--selectors .signal-sprint-start \
|
|
190
|
+
--changed-text-json '[{"selector":".signal-sprint-start","text":"Proof Run"}]' \
|
|
191
|
+
--format profile
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
The suggestion helper only drafts checks and artifacts; it does not produce a
|
|
195
|
+
proof verdict. Run the generated profile with a local or hosted runner before
|
|
196
|
+
treating the packet as evidence.
|
|
197
|
+
|
|
182
198
|
Run a profile with the hosted Riddle runner:
|
|
183
199
|
|
|
184
200
|
```sh
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import {
|
|
2
|
+
RIDDLE_PROOF_PROFILE_VERSION
|
|
3
|
+
} from "./chunk-EX7TO4I5.js";
|
|
4
|
+
|
|
5
|
+
// src/profile-suggestions.ts
|
|
6
|
+
var RIDDLE_PROOF_PROFILE_SUGGESTIONS_VERSION = "riddle-proof.profile-suggestions.v1";
|
|
7
|
+
var UI_FILE_PATTERN = /\.(css|html?|jsx?|tsx?|vue|svelte|mdx)$/i;
|
|
8
|
+
var VISUAL_ASSET_PATTERN = /\.(avif|gif|jpe?g|png|svg|webp)$/i;
|
|
9
|
+
function nonEmptyStrings(values) {
|
|
10
|
+
return Array.from(new Set(
|
|
11
|
+
(values || []).filter((value) => typeof value === "string").map((value) => value.trim()).filter(Boolean)
|
|
12
|
+
));
|
|
13
|
+
}
|
|
14
|
+
function normalizeRoute(value) {
|
|
15
|
+
if (!value?.trim()) return void 0;
|
|
16
|
+
const trimmed = value.trim();
|
|
17
|
+
if (/^https?:\/\//i.test(trimmed)) return void 0;
|
|
18
|
+
return trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
|
|
19
|
+
}
|
|
20
|
+
function routeFromUrl(value) {
|
|
21
|
+
if (!value?.trim()) return void 0;
|
|
22
|
+
try {
|
|
23
|
+
const url = new URL(value);
|
|
24
|
+
return normalizeRoute(`${url.pathname}${url.search || ""}`);
|
|
25
|
+
} catch {
|
|
26
|
+
return void 0;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function slugify(value) {
|
|
30
|
+
return value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80) || "suggested-profile";
|
|
31
|
+
}
|
|
32
|
+
function inferRouteFromFile(file) {
|
|
33
|
+
const normalized = file.replace(/\\/g, "/");
|
|
34
|
+
const routeMatch = normalized.match(/(?:^|\/)(?:pages|routes|app)\/(.+?)(?:\.[^.\/]+)?$/);
|
|
35
|
+
if (!routeMatch) return void 0;
|
|
36
|
+
const route = routeMatch[1].replace(/\/index$/i, "").replace(/\/page$/i, "").replace(/\[[^/\]]+\]/g, ":param");
|
|
37
|
+
return normalizeRoute(route || "/");
|
|
38
|
+
}
|
|
39
|
+
function inferRouteFromFiles(files) {
|
|
40
|
+
for (const file of files) {
|
|
41
|
+
const route = inferRouteFromFile(file);
|
|
42
|
+
if (route) return route;
|
|
43
|
+
}
|
|
44
|
+
return void 0;
|
|
45
|
+
}
|
|
46
|
+
function uniqueChecks(checks) {
|
|
47
|
+
const seen = /* @__PURE__ */ new Set();
|
|
48
|
+
return checks.filter((check) => {
|
|
49
|
+
const key = JSON.stringify(check);
|
|
50
|
+
if (seen.has(key)) return false;
|
|
51
|
+
seen.add(key);
|
|
52
|
+
return true;
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
function changedTextEntryText(entry) {
|
|
56
|
+
return typeof entry === "string" ? entry.trim() : (entry.expected_text || entry.text || "").trim();
|
|
57
|
+
}
|
|
58
|
+
function changedTextEntrySelector(entry) {
|
|
59
|
+
return typeof entry === "string" ? void 0 : entry.selector?.trim() || void 0;
|
|
60
|
+
}
|
|
61
|
+
function changedTextEntryLabel(entry) {
|
|
62
|
+
return typeof entry === "string" ? void 0 : entry.label?.trim() || void 0;
|
|
63
|
+
}
|
|
64
|
+
function suggestionProfileName(input, route, files) {
|
|
65
|
+
if (input.name?.trim()) return input.name.trim();
|
|
66
|
+
return `suggested-${slugify(route || files[0] || "profile")}`;
|
|
67
|
+
}
|
|
68
|
+
function defaultViewports(includeMobile) {
|
|
69
|
+
const viewports = [
|
|
70
|
+
{ name: "desktop", width: 1280, height: 800 }
|
|
71
|
+
];
|
|
72
|
+
if (includeMobile !== false) {
|
|
73
|
+
viewports.push({ name: "mobile", width: 390, height: 844 });
|
|
74
|
+
}
|
|
75
|
+
return viewports;
|
|
76
|
+
}
|
|
77
|
+
function suggestRiddleProofProfileChecks(input) {
|
|
78
|
+
const changedFiles = nonEmptyStrings(input.changed_files);
|
|
79
|
+
const selectors = nonEmptyStrings(input.selectors);
|
|
80
|
+
const changedText = input.changed_text || [];
|
|
81
|
+
const route = normalizeRoute(input.route) || inferRouteFromFiles(changedFiles) || routeFromUrl(input.url);
|
|
82
|
+
const uiFiles = changedFiles.filter((file) => UI_FILE_PATTERN.test(file));
|
|
83
|
+
const visualAssets = changedFiles.filter((file) => VISUAL_ASSET_PATTERN.test(file));
|
|
84
|
+
const warnings = [];
|
|
85
|
+
const suggestions = [];
|
|
86
|
+
const setupActions = [];
|
|
87
|
+
if (!route && !input.url?.trim()) {
|
|
88
|
+
warnings.push("No route or URL was supplied; the draft profile defaults to route /.");
|
|
89
|
+
}
|
|
90
|
+
if ((uiFiles.length || visualAssets.length) && !changedText.length && !selectors.length) {
|
|
91
|
+
warnings.push("UI or visual files changed, but no changed text or selectors were supplied; add focused checks before trusting this profile.");
|
|
92
|
+
}
|
|
93
|
+
const routeOrDefault = route || "/";
|
|
94
|
+
const routeChecks = [
|
|
95
|
+
{ type: "route_loaded", expected_path: routeOrDefault }
|
|
96
|
+
];
|
|
97
|
+
suggestions.push({
|
|
98
|
+
id: "route-loaded",
|
|
99
|
+
reason: "Every browser proof should first prove that the intended route loaded.",
|
|
100
|
+
checks: routeChecks
|
|
101
|
+
});
|
|
102
|
+
const hygieneChecks = [
|
|
103
|
+
{ type: "no_fatal_console_errors" },
|
|
104
|
+
{ type: "no_mobile_horizontal_overflow" }
|
|
105
|
+
];
|
|
106
|
+
suggestions.push({
|
|
107
|
+
id: "runtime-hygiene",
|
|
108
|
+
reason: "UI changes should not introduce fatal console errors or mobile overflow.",
|
|
109
|
+
checks: hygieneChecks
|
|
110
|
+
});
|
|
111
|
+
for (const selector of selectors) {
|
|
112
|
+
suggestions.push({
|
|
113
|
+
id: `selector-${slugify(selector)}`,
|
|
114
|
+
reason: `Changed selector ${selector} should remain visible.`,
|
|
115
|
+
checks: [{ type: "selector_visible", selector }]
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
for (const entry of changedText) {
|
|
119
|
+
const text = changedTextEntryText(entry);
|
|
120
|
+
if (!text) continue;
|
|
121
|
+
const selector = changedTextEntrySelector(entry);
|
|
122
|
+
const label = changedTextEntryLabel(entry);
|
|
123
|
+
const check = selector ? { type: "selector_text_visible", selector, text, label } : { type: "text_visible", text, label };
|
|
124
|
+
suggestions.push({
|
|
125
|
+
id: `text-${slugify(`${selector || "page"}-${text}`)}`,
|
|
126
|
+
reason: selector ? `Expected text should be visible inside ${selector}.` : "Expected text should be visible on the route.",
|
|
127
|
+
checks: [check]
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
if (input.include_screenshot !== false && (uiFiles.length || visualAssets.length || selectors.length || changedText.length)) {
|
|
131
|
+
setupActions.push({ type: "screenshot", label: "suggested-proof-screenshot", full_page: true });
|
|
132
|
+
suggestions.push({
|
|
133
|
+
id: "screenshot-artifact",
|
|
134
|
+
reason: "A screenshot artifact keeps the proof packet inspectable by humans and hosted renderers.",
|
|
135
|
+
checks: [],
|
|
136
|
+
setup_actions: setupActions
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
const checks = uniqueChecks(suggestions.flatMap((suggestion) => suggestion.checks));
|
|
140
|
+
const target = {
|
|
141
|
+
...input.url?.trim() ? { url: input.url.trim() } : { route: routeOrDefault },
|
|
142
|
+
viewports: defaultViewports(input.include_mobile),
|
|
143
|
+
setup_actions: setupActions.length ? setupActions : void 0
|
|
144
|
+
};
|
|
145
|
+
const profile = {
|
|
146
|
+
version: RIDDLE_PROOF_PROFILE_VERSION,
|
|
147
|
+
name: suggestionProfileName(input, routeOrDefault, changedFiles),
|
|
148
|
+
target,
|
|
149
|
+
checks,
|
|
150
|
+
artifacts: ["screenshot", "console", "proof_json"],
|
|
151
|
+
baseline_policy: "invariant_only",
|
|
152
|
+
failure_policy: {
|
|
153
|
+
product_regression: "fail",
|
|
154
|
+
proof_insufficient: "review",
|
|
155
|
+
environment_blocked: "neutral",
|
|
156
|
+
configuration_error: "fail",
|
|
157
|
+
needs_human_review: "review"
|
|
158
|
+
},
|
|
159
|
+
metadata: {
|
|
160
|
+
suggestion_input: {
|
|
161
|
+
changed_files: changedFiles,
|
|
162
|
+
selectors,
|
|
163
|
+
changed_text_count: changedText.length
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
return {
|
|
168
|
+
version: RIDDLE_PROOF_PROFILE_SUGGESTIONS_VERSION,
|
|
169
|
+
profile,
|
|
170
|
+
suggestions,
|
|
171
|
+
warnings
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export {
|
|
176
|
+
RIDDLE_PROOF_PROFILE_SUGGESTIONS_VERSION,
|
|
177
|
+
suggestRiddleProofProfileChecks
|
|
178
|
+
};
|
|
@@ -5,6 +5,7 @@ import { tmpdir } from "os";
|
|
|
5
5
|
import path from "path";
|
|
6
6
|
var DEFAULT_RIDDLE_API_BASE_URL = "https://api.riddledc.com";
|
|
7
7
|
var DEFAULT_RIDDLE_API_KEY_FILE = "/tmp/riddle-api-key";
|
|
8
|
+
var RIDDLE_UNSUBMITTED_WAKE_HINT = "hosted worker may still be waking or waiting for a lease";
|
|
8
9
|
var RiddleApiError = class extends Error {
|
|
9
10
|
constructor(pathname, status, body) {
|
|
10
11
|
super(`Riddle API ${pathname} failed HTTP ${status}: ${body}`);
|
|
@@ -472,9 +473,10 @@ function buildPollSnapshot(jobId, job, input) {
|
|
|
472
473
|
function pollMessage(snapshot, timedOut) {
|
|
473
474
|
if (!timedOut) return void 0;
|
|
474
475
|
const submitted = snapshot.submitted_at || "not submitted";
|
|
476
|
+
const wakeHint = snapshot.running_without_submission && !snapshot.created_at && !snapshot.submitted_at ? ` ${RIDDLE_UNSUBMITTED_WAKE_HINT}.` : "";
|
|
475
477
|
const queue = snapshot.queue_elapsed_ms !== null ? ` queue_elapsed_ms=${snapshot.queue_elapsed_ms}` : "";
|
|
476
478
|
const preSubmit = snapshot.pre_submission_elapsed_ms > 0 ? ` pre_submission_elapsed_ms=${snapshot.pre_submission_elapsed_ms}` : "";
|
|
477
|
-
return `Riddle job ${snapshot.job_id} did not reach a terminal status after ${snapshot.attempt} poll attempts; status=${snapshot.status || "unknown"} submitted_at=${submitted}.${queue}${preSubmit}`;
|
|
479
|
+
return `Riddle job ${snapshot.job_id} did not reach a terminal status after ${snapshot.attempt} poll attempts; status=${snapshot.status || "unknown"} submitted_at=${submitted}.${wakeHint}${queue}${preSubmit}`;
|
|
478
480
|
}
|
|
479
481
|
async function pollRiddleJob(config, jobId, options = {}) {
|
|
480
482
|
if (!jobId?.trim()) throw new Error("jobId is required");
|
|
@@ -585,6 +587,7 @@ function createRiddleApiClient(config = {}) {
|
|
|
585
587
|
export {
|
|
586
588
|
DEFAULT_RIDDLE_API_BASE_URL,
|
|
587
589
|
DEFAULT_RIDDLE_API_KEY_FILE,
|
|
590
|
+
RIDDLE_UNSUBMITTED_WAKE_HINT,
|
|
588
591
|
RiddleApiError,
|
|
589
592
|
resolveRiddleApiKeySource,
|
|
590
593
|
resolveRiddleApiKey,
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
|
+
RIDDLE_UNSUBMITTED_WAKE_HINT,
|
|
2
3
|
createRiddleApiClient,
|
|
3
4
|
isTerminalRiddleJobStatus,
|
|
4
5
|
parseRiddleViewport
|
|
5
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-B2DP2LET.js";
|
|
6
7
|
import {
|
|
7
8
|
RIDDLE_PROOF_PR_COMMENT_MARKER,
|
|
8
9
|
buildRiddleProofPrCommentMarkdown,
|
|
9
10
|
summarizeRiddleProofPrComment
|
|
10
11
|
} from "./chunk-RZ3GXSXQ.js";
|
|
12
|
+
import {
|
|
13
|
+
suggestRiddleProofProfileChecks
|
|
14
|
+
} from "./chunk-5Y4V2IXI.js";
|
|
11
15
|
import {
|
|
12
16
|
RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION,
|
|
13
17
|
applyRiddleProofProfileArtifactCompleteness,
|
|
@@ -55,6 +59,8 @@ var KNOWN_CLI_OPTIONS = /* @__PURE__ */ new Set([
|
|
|
55
59
|
"candidatesJson",
|
|
56
60
|
"checkpointMode",
|
|
57
61
|
"checkpointVisibility",
|
|
62
|
+
"changedFiles",
|
|
63
|
+
"changedTextJson",
|
|
58
64
|
"codexCommand",
|
|
59
65
|
"codexFullAuto",
|
|
60
66
|
"codexHome",
|
|
@@ -76,6 +82,8 @@ var KNOWN_CLI_OPTIONS = /* @__PURE__ */ new Set([
|
|
|
76
82
|
"help",
|
|
77
83
|
"hostedRiddle",
|
|
78
84
|
"image",
|
|
85
|
+
"includeMobile",
|
|
86
|
+
"includeScreenshot",
|
|
79
87
|
"input",
|
|
80
88
|
"inputDir",
|
|
81
89
|
"inputFile",
|
|
@@ -86,6 +94,7 @@ var KNOWN_CLI_OPTIONS = /* @__PURE__ */ new Set([
|
|
|
86
94
|
"jobId",
|
|
87
95
|
"localCore",
|
|
88
96
|
"maxIterations",
|
|
97
|
+
"name",
|
|
89
98
|
"navigationTimeout",
|
|
90
99
|
"output",
|
|
91
100
|
"outputDir",
|
|
@@ -118,6 +127,7 @@ var KNOWN_CLI_OPTIONS = /* @__PURE__ */ new Set([
|
|
|
118
127
|
"runResponse",
|
|
119
128
|
"runner",
|
|
120
129
|
"scriptFile",
|
|
130
|
+
"selectors",
|
|
121
131
|
"sourceKind",
|
|
122
132
|
"splitViewports",
|
|
123
133
|
"stateDir",
|
|
@@ -153,6 +163,7 @@ function usage() {
|
|
|
153
163
|
" riddle-proof-loop run-profile --profile <file|json|-> --url <base-url> [--base-url <base-url>] [--runner riddle] [--viewport-name <name[,name...]>] [--strict true|false; default false] [--split-viewports true|false; default false] [--balance-preflight true|false; default true] [--poll-attempts n] [--output <dir>|--output-dir <dir>] [--result-format json|compact-json|summary|none; default json] [--quiet]",
|
|
154
164
|
" riddle-proof-loop run-profile aggregate --profile <file|json|-> --url <base-url> [--base-url <base-url>] --input-dir <dir>|--inputs <path[,path...]> [--output <dir>|--output-dir <dir>] [--result-format json|compact-json|summary|none; default json]",
|
|
155
165
|
" riddle-proof-loop run-profile recover --profile <file|json|-> --url <base-url> [--base-url <base-url>] --job <job-id> [--viewport-name <name[,name...]>] [--output <dir>|--output-dir <dir>] [--result-format json|compact-json|summary|none; default json]",
|
|
166
|
+
" riddle-proof-loop profile-suggest --route /path|--url <url> [--changed-files a,b] [--selectors .a,.b] [--changed-text-json <file|json|->] [--format json|profile]",
|
|
156
167
|
" riddle-proof-loop regression-pack run [--pack oc-flow-regression|--pack-file <file>] [--local-core true|false; default true] [--hosted-riddle true|false; default false] [--format json|markdown|compact-json; default json] [--output <dir>|--output-dir <dir>]",
|
|
157
168
|
" riddle-proof-loop pr-comment --proof-dir <dir>|--run-response <file> [--result-json <file>] --pr <number|url> [--repo owner/name] [--dry-run] [--body-file <file>] [--comment-mode update|append]",
|
|
158
169
|
" riddle-proof-loop profile-body-assertions --artifact <file|url|-> --candidates-json <file|json|-> [--required-json <file|json|->] [--format json|body-contains]",
|
|
@@ -207,6 +218,10 @@ function optionString(options, key) {
|
|
|
207
218
|
const value = options[key];
|
|
208
219
|
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
209
220
|
}
|
|
221
|
+
function optionStringList(options, key) {
|
|
222
|
+
const value = optionString(options, key);
|
|
223
|
+
return value ? value.split(",").map((item) => item.trim()).filter(Boolean) : void 0;
|
|
224
|
+
}
|
|
210
225
|
function optionBoolean(options, key) {
|
|
211
226
|
const value = options[key];
|
|
212
227
|
if (typeof value === "undefined") return void 0;
|
|
@@ -940,7 +955,7 @@ function formatByteCount(bytes) {
|
|
|
940
955
|
}
|
|
941
956
|
function riddlePollProgressLine(snapshot) {
|
|
942
957
|
const submittedAt = snapshot.submitted_at || "not-submitted";
|
|
943
|
-
const queuePart = snapshot.running_without_submission ? `
|
|
958
|
+
const queuePart = snapshot.running_without_submission ? ` waiting_for_worker_submit=${formatPollDuration(snapshot.pre_submission_elapsed_ms)} worker_wake=possible${snapshot.queue_elapsed_ms !== null ? ` queued_for=${formatPollDuration(snapshot.queue_elapsed_ms)}` : ""}` : snapshot.queue_elapsed_ms !== null ? ` queue=${formatPollDuration(snapshot.queue_elapsed_ms)}` : "";
|
|
944
959
|
const terminalPart = snapshot.terminal ? " terminal=true" : "";
|
|
945
960
|
return [
|
|
946
961
|
"[riddle-poll]",
|
|
@@ -1047,6 +1062,11 @@ function readJsonValue(value, label) {
|
|
|
1047
1062
|
}
|
|
1048
1063
|
return parsed;
|
|
1049
1064
|
}
|
|
1065
|
+
function readJsonAnyValue(value, label) {
|
|
1066
|
+
if (!value) throw new Error(`${label} is required.`);
|
|
1067
|
+
const raw = value === "-" ? readStdin() : existsSync(value) ? readFileSync(value, "utf-8") : value;
|
|
1068
|
+
return JSON.parse(raw);
|
|
1069
|
+
}
|
|
1050
1070
|
function readOptionalJsonRecord(value, label) {
|
|
1051
1071
|
if (!value) return void 0;
|
|
1052
1072
|
return readJsonValue(value, label);
|
|
@@ -1361,7 +1381,7 @@ function profileRiddleJobMarkdown(result) {
|
|
|
1361
1381
|
lines.push("- artifact recovery: used artifacts endpoint after non-terminal poll");
|
|
1362
1382
|
}
|
|
1363
1383
|
if (retryCount !== void 0 && retryCount > 0) {
|
|
1364
|
-
lines.push(`- retry recovery: replaced ${retryCount} unsubmitted job${retryCount === 1 ? "" : "s"}${staleJobIds.length ? ` (${staleJobIds.map((value) => markdownInlineCode(value)).join(", ")})` : ""}`);
|
|
1384
|
+
lines.push(`- retry recovery: replaced ${retryCount} unsubmitted hosted job${retryCount === 1 ? "" : "s"}${staleJobIds.length ? ` (${staleJobIds.map((value) => markdownInlineCode(value)).join(", ")})` : ""}; ${RIDDLE_UNSUBMITTED_WAKE_HINT}`);
|
|
1365
1385
|
}
|
|
1366
1386
|
for (const job of splitJobs.slice(0, 12)) {
|
|
1367
1387
|
const viewport = cliString(job.viewport) || "viewport";
|
|
@@ -4446,7 +4466,7 @@ async function runSingleRiddleProfileForCli(profile, options, input) {
|
|
|
4446
4466
|
}
|
|
4447
4467
|
staleJobIds.push(jobId);
|
|
4448
4468
|
if (options.quiet !== true) {
|
|
4449
|
-
process.stderr.write(`[riddle-poll] ${jobId} stayed unsubmitted for ${formatPollDuration(poll.poll?.pre_submission_elapsed_ms)}; retrying hosted run ${attempt + 1}/${retryLimit}
|
|
4469
|
+
process.stderr.write(`[riddle-poll] ${jobId} stayed unsubmitted for ${formatPollDuration(poll.poll?.pre_submission_elapsed_ms)}; ${RIDDLE_UNSUBMITTED_WAKE_HINT}; retrying hosted run ${attempt + 1}/${retryLimit}
|
|
4450
4470
|
`);
|
|
4451
4471
|
}
|
|
4452
4472
|
continue;
|
|
@@ -4747,6 +4767,34 @@ async function main() {
|
|
|
4747
4767
|
process.exitCode = result.ok ? 0 : 1;
|
|
4748
4768
|
return;
|
|
4749
4769
|
}
|
|
4770
|
+
if (command === "profile-suggest") {
|
|
4771
|
+
const changedTextJson = optionString(options, "changedTextJson");
|
|
4772
|
+
const changedText = changedTextJson ? readJsonAnyValue(changedTextJson, "--changed-text-json") : void 0;
|
|
4773
|
+
if (changedText !== void 0 && !Array.isArray(changedText)) {
|
|
4774
|
+
throw new Error("--changed-text-json must be a JSON array.");
|
|
4775
|
+
}
|
|
4776
|
+
const result = suggestRiddleProofProfileChecks({
|
|
4777
|
+
name: optionString(options, "name"),
|
|
4778
|
+
route: optionString(options, "route"),
|
|
4779
|
+
url: optionString(options, "url"),
|
|
4780
|
+
changed_files: optionStringList(options, "changedFiles"),
|
|
4781
|
+
selectors: optionStringList(options, "selectors"),
|
|
4782
|
+
changed_text: changedText,
|
|
4783
|
+
include_mobile: optionBoolean(options, "includeMobile"),
|
|
4784
|
+
include_screenshot: optionBoolean(options, "includeScreenshot")
|
|
4785
|
+
});
|
|
4786
|
+
const format = optionString(options, "format") || "json";
|
|
4787
|
+
if (format === "profile") {
|
|
4788
|
+
process.stdout.write(`${JSON.stringify(result.profile, null, 2)}
|
|
4789
|
+
`);
|
|
4790
|
+
} else if (format === "json") {
|
|
4791
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}
|
|
4792
|
+
`);
|
|
4793
|
+
} else {
|
|
4794
|
+
throw new Error("--format must be json or profile.");
|
|
4795
|
+
}
|
|
4796
|
+
return;
|
|
4797
|
+
}
|
|
4750
4798
|
if (command === "profile-body-assertions") {
|
|
4751
4799
|
const artifactText = await readTextValue(optionString(options, "artifact") ?? optionString(options, "input"), "--artifact");
|
|
4752
4800
|
const candidates = readOptionalJsonStringArray(optionString(options, "candidatesJson") ?? optionString(options, "candidateJson"), "--candidates-json") ?? [];
|
package/dist/cli/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import "../chunk-
|
|
2
|
-
import "../chunk-
|
|
1
|
+
import "../chunk-JPRKO2DH.js";
|
|
2
|
+
import "../chunk-B2DP2LET.js";
|
|
3
3
|
import "../chunk-RZ3GXSXQ.js";
|
|
4
|
+
import "../chunk-5Y4V2IXI.js";
|
|
4
5
|
import "../chunk-EX7TO4I5.js";
|
|
5
6
|
import "../chunk-P4BHU5NM.js";
|
|
6
7
|
import "../chunk-NMQIWBSB.js";
|