@riddledc/riddle-proof 0.7.226 → 0.8.1

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.
Files changed (132) hide show
  1. package/dist/adapters/codex-exec-agent.cjs +893 -0
  2. package/dist/adapters/codex-exec-agent.d.cts +3 -0
  3. package/dist/adapters/codex-exec-agent.d.ts +3 -0
  4. package/dist/adapters/codex-exec-agent.js +13 -0
  5. package/dist/adapters/codex.cjs +893 -0
  6. package/dist/adapters/codex.d.cts +3 -0
  7. package/dist/adapters/codex.d.ts +3 -0
  8. package/dist/adapters/codex.js +13 -0
  9. package/dist/adapters/local-agent.cjs +893 -0
  10. package/dist/adapters/local-agent.d.cts +3 -0
  11. package/dist/adapters/local-agent.d.ts +3 -0
  12. package/dist/adapters/local-agent.js +13 -0
  13. package/dist/adapters/openclaw.cjs +213 -0
  14. package/dist/adapters/openclaw.d.cts +2 -0
  15. package/dist/adapters/openclaw.d.ts +2 -0
  16. package/dist/adapters/openclaw.js +17 -0
  17. package/dist/advanced/engine-harness.cjs +5701 -0
  18. package/dist/advanced/engine-harness.d.cts +2 -0
  19. package/dist/advanced/engine-harness.d.ts +2 -0
  20. package/dist/advanced/engine-harness.js +16 -0
  21. package/dist/advanced/index.cjs +6242 -0
  22. package/dist/advanced/index.d.cts +5 -0
  23. package/dist/advanced/index.d.ts +5 -0
  24. package/dist/advanced/index.js +23 -0
  25. package/dist/advanced/proof-run-core.cjs +1085 -0
  26. package/dist/advanced/proof-run-core.d.cts +1 -0
  27. package/dist/advanced/proof-run-core.d.ts +1 -0
  28. package/dist/advanced/proof-run-core.js +59 -0
  29. package/dist/advanced/proof-run-engine.cjs +2905 -0
  30. package/dist/advanced/proof-run-engine.d.cts +2 -0
  31. package/dist/advanced/proof-run-engine.d.ts +2 -0
  32. package/dist/advanced/proof-run-engine.js +10 -0
  33. package/dist/advanced/runner.cjs +833 -0
  34. package/dist/advanced/runner.d.cts +2 -0
  35. package/dist/advanced/runner.d.ts +2 -0
  36. package/dist/advanced/runner.js +12 -0
  37. package/dist/app-contract/index.cjs +24 -0
  38. package/dist/app-contract/index.d.cts +1 -0
  39. package/dist/app-contract/index.d.ts +1 -0
  40. package/dist/app-contract/index.js +2 -0
  41. package/dist/basic-gameplay.js +1 -0
  42. package/dist/checkpoint.js +1 -0
  43. package/dist/chunk-BHL4JSGM.js +1900 -0
  44. package/dist/chunk-BTN76IGW.js +115 -0
  45. package/dist/{chunk-TGHTM66Z.js → chunk-COERZX63.js} +10 -2
  46. package/dist/{chunk-QUAZAMOM.js → chunk-IWLQQ5S5.js} +12 -2
  47. package/dist/chunk-MLKGABMK.js +9 -0
  48. package/dist/chunk-OFSECTSC.js +0 -0
  49. package/dist/{chunk-GBVEQQIM.js → chunk-TJ63IE65.js} +36 -1
  50. package/dist/chunk-VZD5LH7U.js +4138 -0
  51. package/dist/cli/index.cjs +18 -0
  52. package/dist/cli/index.d.cts +2 -0
  53. package/dist/cli/index.d.ts +2 -0
  54. package/dist/cli/index.js +12 -0
  55. package/dist/cli.d.cts +1 -0
  56. package/dist/cli.d.ts +1 -0
  57. package/dist/cli.js +8 -4139
  58. package/dist/codex-exec-agent.d.cts +1 -1
  59. package/dist/codex-exec-agent.d.ts +1 -1
  60. package/dist/codex-exec-agent.js +1 -0
  61. package/dist/diagnostics.js +1 -0
  62. package/dist/engine-harness-CMACHP6A.d.ts +96 -0
  63. package/dist/engine-harness-LBfqbFSe.d.cts +96 -0
  64. package/dist/engine-harness.d.cts +2 -79
  65. package/dist/engine-harness.d.ts +2 -79
  66. package/dist/engine-harness.js +3 -2
  67. package/dist/index.d.cts +2 -2
  68. package/dist/index.d.ts +2 -2
  69. package/dist/index.js +4 -3
  70. package/dist/local-agent.d.cts +1 -1
  71. package/dist/local-agent.d.ts +1 -1
  72. package/dist/local-agent.js +1 -0
  73. package/dist/openclaw.js +8 -107
  74. package/dist/playability.js +1 -0
  75. package/dist/profile/index.cjs +9403 -0
  76. package/dist/profile/index.d.cts +2 -0
  77. package/dist/profile/index.d.ts +2 -0
  78. package/dist/profile/index.js +53 -0
  79. package/dist/profile.js +1 -0
  80. package/dist/proof-run-core-CE0jx7wL.d.cts +359 -0
  81. package/dist/proof-run-core-CE0jx7wL.d.ts +359 -0
  82. package/dist/proof-run-core.d.cts +1 -322
  83. package/dist/proof-run-core.d.ts +1 -322
  84. package/dist/proof-run-core.js +2 -1
  85. package/dist/proof-run-engine-CSSc0mNn.d.ts +764 -0
  86. package/dist/proof-run-engine-HSRpUeBi.d.cts +764 -0
  87. package/dist/proof-run-engine.d.cts +2 -757
  88. package/dist/proof-run-engine.d.ts +2 -757
  89. package/dist/proof-run-engine.js +5 -1885
  90. package/dist/proof-session.js +1 -0
  91. package/dist/result.js +1 -0
  92. package/dist/riddle-client.js +1 -0
  93. package/dist/run-card.js +1 -0
  94. package/dist/runner-4LJ5z0D-.d.cts +29 -0
  95. package/dist/runner-BdQpOkZD.d.ts +29 -0
  96. package/dist/runner.d.cts +2 -22
  97. package/dist/runner.d.ts +2 -22
  98. package/dist/runner.js +3 -2
  99. package/dist/runtime/index.cjs +528 -0
  100. package/dist/runtime/index.d.cts +1 -0
  101. package/dist/runtime/index.d.ts +1 -0
  102. package/dist/runtime/index.js +37 -0
  103. package/dist/runtime/riddle-client.cjs +528 -0
  104. package/dist/runtime/riddle-client.d.cts +1 -0
  105. package/dist/runtime/riddle-client.d.ts +1 -0
  106. package/dist/runtime/riddle-client.js +37 -0
  107. package/dist/spec/checkpoint.cjs +807 -0
  108. package/dist/spec/checkpoint.d.cts +2 -0
  109. package/dist/spec/checkpoint.d.ts +2 -0
  110. package/dist/spec/checkpoint.js +34 -0
  111. package/dist/spec/index.cjs +1510 -0
  112. package/dist/spec/index.d.cts +5 -0
  113. package/dist/spec/index.d.ts +5 -0
  114. package/dist/spec/index.js +80 -0
  115. package/dist/spec/result.cjs +259 -0
  116. package/dist/spec/result.d.cts +2 -0
  117. package/dist/spec/result.d.ts +2 -0
  118. package/dist/spec/result.js +21 -0
  119. package/dist/spec/run-card.cjs +287 -0
  120. package/dist/spec/run-card.d.cts +2 -0
  121. package/dist/spec/run-card.d.ts +2 -0
  122. package/dist/spec/run-card.js +11 -0
  123. package/dist/spec/state.cjs +541 -0
  124. package/dist/spec/state.d.cts +2 -0
  125. package/dist/spec/state.d.ts +2 -0
  126. package/dist/spec/state.js +28 -0
  127. package/dist/spec/types.cjs +18 -0
  128. package/dist/spec/types.d.cts +1 -0
  129. package/dist/spec/types.d.ts +1 -0
  130. package/dist/spec/types.js +1 -0
  131. package/dist/state.js +1 -0
  132. package/package.json +95 -2
package/dist/cli.js CHANGED
@@ -1,4144 +1,13 @@
1
1
  #!/usr/bin/env node
2
- import {
3
- RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION,
4
- assessRiddleProofProfileEvidence,
5
- buildRiddleProofProfileScript,
6
- collectRiddleProfileArtifactRefs,
7
- createRiddleProofProfileEnvironmentBlockedResult,
8
- createRiddleProofProfileInsufficientResult,
9
- deriveRiddleProofArtifactBodyAssertions,
10
- extractRiddleProofProfileResult,
11
- normalizeRiddleProofProfile,
12
- preflightRiddleProofProfileHttpStatusChecks,
13
- profileStatusExitCode,
14
- resolveRiddleProofProfileTargetUrl,
15
- resolveRiddleProofProfileTimeoutSec
16
- } from "./chunk-PEWAIEER.js";
17
- import {
18
- createRiddleApiClient,
19
- isTerminalRiddleJobStatus,
20
- parseRiddleViewport
21
- } from "./chunk-TWTEUS7R.js";
22
- import {
23
- createDisabledRiddleProofAgentAdapter,
24
- readRiddleProofRunStatus,
25
- runRiddleProofEngineHarness
26
- } from "./chunk-QUAZAMOM.js";
2
+ import "./chunk-VZD5LH7U.js";
3
+ import "./chunk-PEWAIEER.js";
4
+ import "./chunk-TWTEUS7R.js";
5
+ import "./chunk-IWLQQ5S5.js";
27
6
  import "./chunk-OHJQRDST.js";
28
7
  import "./chunk-Y2KTBACQ.js";
29
- import "./chunk-GBVEQQIM.js";
30
- import {
31
- createCheckpointResponseTemplate
32
- } from "./chunk-2CFVREFI.js";
8
+ import "./chunk-TJ63IE65.js";
9
+ import "./chunk-2CFVREFI.js";
33
10
  import "./chunk-JFQXAJH2.js";
34
- import {
35
- createCodexExecAgentAdapter,
36
- runCodexExecAgentDoctor
37
- } from "./chunk-7F5LNUGR.js";
11
+ import "./chunk-7F5LNUGR.js";
38
12
  import "./chunk-VY4Y5U57.js";
39
-
40
- // src/cli.ts
41
- import { existsSync, mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from "fs";
42
- import path from "path";
43
- var RIDDLE_PROFILE_BALANCE_PREFLIGHT_MIN_SECONDS_PER_JOB = 30;
44
- var KNOWN_CLI_OPTIONS = /* @__PURE__ */ new Set([
45
- "agent",
46
- "apiBaseUrl",
47
- "apiKey",
48
- "apiKeyFile",
49
- "artifact",
50
- "attempts",
51
- "balancePreflight",
52
- "baseUrl",
53
- "candidateJson",
54
- "candidatesJson",
55
- "checkpointMode",
56
- "checkpointVisibility",
57
- "codexCommand",
58
- "codexFullAuto",
59
- "codexHome",
60
- "codexModel",
61
- "codexSandbox",
62
- "codexTimeoutMs",
63
- "command",
64
- "continueWithStage",
65
- "createdAt",
66
- "decision",
67
- "defaultReviewer",
68
- "defaultShipMode",
69
- "exclude",
70
- "format",
71
- "framework",
72
- "help",
73
- "image",
74
- "input",
75
- "inputDir",
76
- "inputFile",
77
- "inputFiles",
78
- "inputs",
79
- "intervalMs",
80
- "job",
81
- "jobId",
82
- "maxIterations",
83
- "navigationTimeout",
84
- "output",
85
- "outputDir",
86
- "path",
87
- "payloadJson",
88
- "pollAttempts",
89
- "pollIntervalMs",
90
- "port",
91
- "profile",
92
- "progressEveryMs",
93
- "quiet",
94
- "readinessPath",
95
- "readinessTimeout",
96
- "reasonsJson",
97
- "requestJson",
98
- "requiredJson",
99
- "responseJson",
100
- "resultFormat",
101
- "resultsDir",
102
- "riddleEngineModuleUrl",
103
- "riddleProofDir",
104
- "route",
105
- "runDir",
106
- "runner",
107
- "scriptFile",
108
- "sourceKind",
109
- "splitViewports",
110
- "stateDir",
111
- "statePath",
112
- "strict",
113
- "submitRetries",
114
- "submitTimeoutMs",
115
- "summary",
116
- "sync",
117
- "timeout",
118
- "url",
119
- "unsubmittedJobRetries",
120
- "unsubmittedJobTimeoutMs",
121
- "unsubmittedRetries",
122
- "unsubmittedTimeoutMs",
123
- "viewport",
124
- "viewportName",
125
- "viewportNames",
126
- "viewports",
127
- "wait",
128
- "waitForSelector"
129
- ]);
130
- function usage() {
131
- return [
132
- "Usage:",
133
- " riddle-proof-loop run --request-json <file|json|-> [--agent disabled|local] [--checkpoint-mode yield|auto]",
134
- " riddle-proof-loop checkpoint --state-path <path> [--decision <decision>] [--format json|markdown]",
135
- " riddle-proof-loop respond --state-path <path> --response-json <file|json|->",
136
- " riddle-proof-loop respond --state-path <path> --decision <decision> --summary <text> [--payload-json <file|json|->]",
137
- " riddle-proof-loop status --state-path <path>",
138
- " 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]",
139
- " 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]",
140
- " 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]",
141
- " riddle-proof-loop profile-body-assertions --artifact <file|url|-> --candidates-json <file|json|-> [--required-json <file|json|->] [--format json|body-contains]",
142
- " riddle-proof-loop profile-http-status-preflight --profile <file|json|-> --url <base-url> [--format json|summary]",
143
- " riddle-proof-loop riddle-preview-deploy <build-dir> <label> [--framework spa|static]",
144
- " riddle-proof-loop riddle-server-preview <directory> --script-file <file> [--path /route] [--wait-for-selector selector]",
145
- " riddle-proof-loop riddle-run-script --url <url> --script-file <file> [--viewport 1280x720] [--strict true|false]",
146
- " riddle-proof-loop riddle-poll <job-id> [--wait] [--attempts n] [--quiet]",
147
- " riddle-proof-loop doctor local [--codex-command <path>]",
148
- "",
149
- "The default CLI run mode is checkpoint-mode=yield unless --agent local is used.",
150
- "Compatibility aliases: --agent codex_exec and doctor codex_exec."
151
- ].join("\n");
152
- }
153
- function parseArgs(argv) {
154
- const positional = [];
155
- const options = {};
156
- for (let index = 0; index < argv.length; index += 1) {
157
- const arg = argv[index];
158
- if (!arg.startsWith("--")) {
159
- positional.push(arg);
160
- continue;
161
- }
162
- const raw = arg.slice(2);
163
- const equalIndex = raw.indexOf("=");
164
- const rawKey = equalIndex >= 0 ? raw.slice(0, equalIndex) : raw;
165
- const key = rawKey.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
166
- if (equalIndex >= 0) {
167
- options[key] = raw.slice(equalIndex + 1);
168
- continue;
169
- }
170
- const next = argv[index + 1];
171
- if (!next || next.startsWith("--")) {
172
- options[key] = true;
173
- continue;
174
- }
175
- options[key] = next;
176
- index += 1;
177
- }
178
- return { positional, options };
179
- }
180
- function optionKeyToFlagName(key) {
181
- return key.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);
182
- }
183
- function validateCliOptions(options) {
184
- const unknown = Object.keys(options).filter((key) => !KNOWN_CLI_OPTIONS.has(key));
185
- if (!unknown.length) return;
186
- const flags = unknown.map((key) => `--${optionKeyToFlagName(key)}`).join(", ");
187
- throw new Error(`Unknown option${unknown.length === 1 ? "" : "s"}: ${flags}. Run riddle-proof-loop help for usage.`);
188
- }
189
- function optionString(options, key) {
190
- const value = options[key];
191
- return typeof value === "string" && value.trim() ? value.trim() : void 0;
192
- }
193
- function optionBoolean(options, key) {
194
- const value = options[key];
195
- if (typeof value === "undefined") return void 0;
196
- if (typeof value === "boolean") return value;
197
- const normalized = value.trim().toLowerCase();
198
- if (["true", "1", "yes", "y"].includes(normalized)) return true;
199
- if (["false", "0", "no", "n"].includes(normalized)) return false;
200
- const flag = key.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);
201
- throw new Error(`--${flag} must be true or false.`);
202
- }
203
- function runProfileStrictOption(options) {
204
- return optionBoolean(options, "strict") ?? false;
205
- }
206
- function runProfileBalancePreflightOption(options) {
207
- return optionBoolean(options, "balancePreflight") ?? true;
208
- }
209
- function runProfileSplitViewportsOption(options) {
210
- return optionBoolean(options, "splitViewports") ?? false;
211
- }
212
- function runProfileViewportNamesOption(options) {
213
- const raw = optionString(options, "viewportName") ?? optionString(options, "viewportNames");
214
- if (!raw) return [];
215
- return raw.split(",").map((part) => part.trim()).filter(Boolean);
216
- }
217
- var DEFAULT_PROFILE_UNSUBMITTED_RETRY_TIMEOUT_MS = 9e4;
218
- var DEFAULT_PROFILE_UNSUBMITTED_RETRIES = 2;
219
- function optionNumber(options, ...keys) {
220
- for (const key of keys) {
221
- const value = optionString(options, key);
222
- if (value !== void 0) return Number(value);
223
- }
224
- return void 0;
225
- }
226
- function optionInteger(options, fallback, ...keys) {
227
- const value = optionNumber(options, ...keys);
228
- if (value === void 0 || !Number.isFinite(value)) return fallback;
229
- return Math.floor(value);
230
- }
231
- function profileOutputDirOption(options) {
232
- return optionString(options, "output") ?? optionString(options, "outputDir");
233
- }
234
- function runProfileResultFormatOption(options) {
235
- const format = optionString(options, "resultFormat") ?? "json";
236
- if (format === "compact") return "compact-json";
237
- if (format === "json" || format === "compact-json" || format === "summary" || format === "none") return format;
238
- throw new Error("--result-format must be json, compact-json, summary, or none.");
239
- }
240
- function compactProfileCheckCounts(result) {
241
- return result.checks.reduce((counts, check) => {
242
- const status = String(check.status || "unknown");
243
- counts[status] = (counts[status] || 0) + 1;
244
- counts.total = (counts.total || 0) + 1;
245
- return counts;
246
- }, { total: 0 });
247
- }
248
- function compactProfileChecks(result) {
249
- return result.checks.map((check) => ({
250
- type: check.type,
251
- label: check.label,
252
- status: check.status,
253
- message: check.message
254
- }));
255
- }
256
- function compactRunProfileResult(result, options) {
257
- const outputDir = profileOutputDirOption(options);
258
- return {
259
- version: "riddle-proof.profile-compact-result.v1",
260
- profile_name: result.profile_name,
261
- runner: result.runner,
262
- status: result.status,
263
- summary: result.summary,
264
- captured_at: result.captured_at,
265
- baseline_policy: result.baseline_policy,
266
- route: result.route,
267
- check_counts: compactProfileCheckCounts(result),
268
- checks: compactProfileChecks(result),
269
- warnings: result.warnings,
270
- environment_blocker: result.environment_blocker,
271
- metadata: result.metadata,
272
- riddle: result.riddle,
273
- artifacts: result.artifacts,
274
- output_dir: outputDir,
275
- output_files: outputDir ? {
276
- profile_result: "profile-result.json",
277
- summary: "summary.md",
278
- proof_json: result.evidence ? "proof.json" : void 0,
279
- console: result.evidence?.console ? "console.json" : void 0,
280
- dom_summary: result.evidence?.dom_summary ? "dom-summary.json" : void 0
281
- } : void 0
282
- };
283
- }
284
- function writeRunProfileResult(result, options) {
285
- const format = runProfileResultFormatOption(options);
286
- if (format === "none") return;
287
- if (format === "summary") {
288
- process.stdout.write(profileResultMarkdown(result));
289
- return;
290
- }
291
- if (format === "compact-json") {
292
- process.stdout.write(`${JSON.stringify(compactRunProfileResult(result, options), null, 2)}
293
- `);
294
- return;
295
- }
296
- process.stdout.write(`${JSON.stringify(result, null, 2)}
297
- `);
298
- }
299
- function previewFrameworkOption(options) {
300
- const framework = optionString(options, "framework") ?? "static";
301
- if (framework === "spa" || framework === "static") return framework;
302
- throw new Error("--framework must be spa or static.");
303
- }
304
- function readStdin() {
305
- return readFileSync(0, "utf-8");
306
- }
307
- async function readTextValue(value, label) {
308
- if (!value) throw new Error(`${label} is required.`);
309
- if (value === "-") return readStdin();
310
- if (/^https?:\/\//i.test(value)) {
311
- const response = await fetch(value);
312
- const text = await response.text();
313
- if (!response.ok) throw new Error(`${label} URL failed HTTP ${response.status}: ${text.slice(0, 500)}`);
314
- return text;
315
- }
316
- if (existsSync(value)) return readFileSync(value, "utf-8");
317
- throw new Error(`${label} must be a readable file path, URL, or -.`);
318
- }
319
- function formatPollDuration(ms) {
320
- if (typeof ms !== "number" || !Number.isFinite(ms)) return "n/a";
321
- const seconds = Math.max(0, Math.round(ms / 1e3));
322
- const minutes = Math.floor(seconds / 60);
323
- const remainder = seconds % 60;
324
- return minutes > 0 ? `${minutes}m${String(remainder).padStart(2, "0")}s` : `${seconds}s`;
325
- }
326
- function riddlePollProgressLine(snapshot) {
327
- const submittedAt = snapshot.submitted_at || "not-submitted";
328
- const queuePart = snapshot.running_without_submission ? ` waiting_for_submit=${formatPollDuration(snapshot.pre_submission_elapsed_ms)}${snapshot.queue_elapsed_ms !== null ? ` queued_for=${formatPollDuration(snapshot.queue_elapsed_ms)}` : ""}` : snapshot.queue_elapsed_ms !== null ? ` queue=${formatPollDuration(snapshot.queue_elapsed_ms)}` : "";
329
- const terminalPart = snapshot.terminal ? " terminal=true" : "";
330
- return [
331
- "[riddle-poll]",
332
- snapshot.job_id,
333
- `status=${snapshot.status || "unknown"}`,
334
- `attempt=${snapshot.attempt}/${snapshot.attempts}`,
335
- `elapsed=${formatPollDuration(snapshot.elapsed_ms)}`,
336
- `submitted_at=${submittedAt}${queuePart}${terminalPart}`
337
- ].join(" ");
338
- }
339
- function readJsonValue(value, label) {
340
- if (!value) throw new Error(`${label} is required.`);
341
- const raw = value === "-" ? readStdin() : existsSync(value) ? readFileSync(value, "utf-8") : value;
342
- const parsed = JSON.parse(raw);
343
- if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
344
- throw new Error(`${label} must be a JSON object.`);
345
- }
346
- return parsed;
347
- }
348
- function readOptionalJsonRecord(value, label) {
349
- if (!value) return void 0;
350
- return readJsonValue(value, label);
351
- }
352
- function readOptionalJsonStringArray(value, label) {
353
- if (!value) return void 0;
354
- const parsed = value === "-" ? JSON.parse(readStdin()) : existsSync(value) ? JSON.parse(readFileSync(value, "utf-8")) : JSON.parse(value);
355
- if (!Array.isArray(parsed) || parsed.some((item) => typeof item !== "string")) {
356
- throw new Error(`${label} must be a JSON array of strings.`);
357
- }
358
- return parsed;
359
- }
360
- function readRunState(statePath) {
361
- const parsed = readJsonValue(statePath, "--state-path");
362
- if (parsed.version !== "riddle-proof.run-state.v1" || !Array.isArray(parsed.events)) {
363
- throw new Error(`${statePath} is not a riddle-proof.run-state.v1 file.`);
364
- }
365
- return parsed;
366
- }
367
- function hasPlaceholderValue(value) {
368
- if (typeof value === "string") return /\bTODO\b/.test(value);
369
- if (Array.isArray(value)) return value.some(hasPlaceholderValue);
370
- if (value && typeof value === "object") {
371
- return Object.values(value).some(hasPlaceholderValue);
372
- }
373
- return false;
374
- }
375
- function markdownJson(value) {
376
- return JSON.stringify(value ?? null, null, 2);
377
- }
378
- function formatCheckpointMarkdown(input) {
379
- const packet = input.checkpointPacket;
380
- const runCard = input.runCard;
381
- const lines = [
382
- "# Riddle Proof Checkpoint",
383
- "",
384
- `Run: ${packet.run_id}`,
385
- `State: ${input.statePath}`,
386
- `Status: ${input.status || "awaiting_checkpoint"}`,
387
- `Stage: ${packet.stage}`,
388
- `Checkpoint: ${packet.checkpoint}`,
389
- `Kind: ${packet.kind}`,
390
- "",
391
- "## Goal",
392
- "",
393
- runCard?.goal?.change_request || packet.change_request,
394
- "",
395
- "## Next Action",
396
- "",
397
- packet.question,
398
- "",
399
- "## Allowed Decisions",
400
- "",
401
- ...packet.allowed_decisions.map((decision) => `- ${decision}`),
402
- ""
403
- ];
404
- if (packet.artifacts?.length) {
405
- lines.push("## Artifacts", "");
406
- for (const artifact of packet.artifacts) {
407
- lines.push(`- ${artifact.role}: ${artifact.url || artifact.path || artifact.name || "available"}`);
408
- }
409
- lines.push("");
410
- }
411
- if (packet.evidence_excerpt && Object.keys(packet.evidence_excerpt).length) {
412
- lines.push("## Evidence Excerpt", "", "```json", markdownJson(packet.evidence_excerpt), "```", "");
413
- }
414
- if (packet.state_excerpt && Object.keys(packet.state_excerpt).length) {
415
- lines.push("## State Excerpt", "", "```json", markdownJson(packet.state_excerpt), "```", "");
416
- }
417
- lines.push(
418
- "## Response Template",
419
- "",
420
- "```json",
421
- markdownJson(input.responseTemplate),
422
- "```",
423
- "",
424
- "## Next Command",
425
- "",
426
- "```sh",
427
- `riddle-proof-loop respond --state-path ${input.statePath} --decision ${input.responseTemplate.decision} --summary <summary> --payload-json <file|json|->`,
428
- "```",
429
- ""
430
- );
431
- return `${lines.join("\n")}
432
- `;
433
- }
434
- function checkpointResponseForFlags(statePath, options) {
435
- const state = readRunState(statePath);
436
- if (!state.checkpoint_packet) {
437
- throw new Error(`${statePath} has no pending checkpoint packet. Use status to inspect the current run state.`);
438
- }
439
- const decision = optionString(options, "decision");
440
- const summary = optionString(options, "summary");
441
- if (!decision || !summary) {
442
- throw new Error("--decision and --summary are required when --response-json is not supplied.");
443
- }
444
- if (!state.checkpoint_packet.allowed_decisions.includes(decision)) {
445
- throw new Error(`--decision ${decision} is not allowed for ${state.checkpoint_packet.checkpoint}. Allowed decisions: ${state.checkpoint_packet.allowed_decisions.join(", ")}`);
446
- }
447
- const payload = readOptionalJsonRecord(optionString(options, "payloadJson"), "--payload-json");
448
- const reasons = readOptionalJsonStringArray(optionString(options, "reasonsJson"), "--reasons-json");
449
- const response = createCheckpointResponseTemplate(state.checkpoint_packet, {
450
- decision,
451
- summary,
452
- payload,
453
- reasons,
454
- continue_with_stage: optionString(options, "continueWithStage"),
455
- source_kind: optionString(options, "sourceKind") || "codex",
456
- created_at: optionString(options, "createdAt")
457
- });
458
- if (!payload && hasPlaceholderValue(response.payload)) {
459
- throw new Error(`--payload-json is required for ${decision} at ${state.checkpoint_packet.checkpoint}; the generated template contains placeholders.`);
460
- }
461
- if (!reasons && hasPlaceholderValue(response.reasons)) {
462
- delete response.reasons;
463
- }
464
- return response;
465
- }
466
- function codexConfig(options) {
467
- const codexFullAuto = optionString(options, "codexFullAuto");
468
- return {
469
- codexCommand: optionString(options, "codexCommand"),
470
- codexHome: optionString(options, "codexHome"),
471
- codexModel: optionString(options, "codexModel"),
472
- codexTimeoutMs: optionString(options, "codexTimeoutMs") ? Number(optionString(options, "codexTimeoutMs")) : void 0,
473
- codexSandbox: optionString(options, "codexSandbox"),
474
- codexFullAuto: codexFullAuto === "false" ? false : void 0
475
- };
476
- }
477
- function isLocalAgentMode(value) {
478
- return value === "local" || value === "local_exec" || value === "codex_exec";
479
- }
480
- function agentFor(options) {
481
- const agentMode = optionString(options, "agent") || "disabled";
482
- if (isLocalAgentMode(agentMode)) return createCodexExecAgentAdapter(codexConfig(options));
483
- if (agentMode === "disabled") return createDisabledRiddleProofAgentAdapter();
484
- throw new Error(`Unsupported --agent ${agentMode}. Use disabled or local.`);
485
- }
486
- function riddleClientConfig(options) {
487
- return {
488
- apiKey: optionString(options, "apiKey"),
489
- apiKeyFile: optionString(options, "apiKeyFile"),
490
- apiBaseUrl: optionString(options, "apiBaseUrl")
491
- };
492
- }
493
- function parseProfileViewports(value) {
494
- if (!value) return void 0;
495
- return value.split(",").map((part, index) => {
496
- const trimmed = part.trim();
497
- const named = /^([a-zA-Z0-9_-]+)=(\d+x\d+)$/.exec(trimmed);
498
- const viewport = parseRiddleViewport(named ? named[2] : trimmed);
499
- if (!viewport) throw new Error(`Invalid viewport ${trimmed}.`);
500
- return {
501
- name: named ? named[1] : `viewport-${index + 1}`,
502
- width: viewport.width,
503
- height: viewport.height
504
- };
505
- });
506
- }
507
- function normalizeProfileForCli(options) {
508
- const rawProfile = readJsonValue(optionString(options, "profile"), "--profile");
509
- return normalizeRiddleProofProfile(rawProfile, {
510
- url: optionString(options, "url") ?? optionString(options, "baseUrl"),
511
- route: optionString(options, "route"),
512
- viewports: parseProfileViewports(optionString(options, "viewports") || optionString(options, "viewport"))
513
- });
514
- }
515
- function profileHttpStatusPreflightSummary(result) {
516
- const lines = [
517
- result.summary,
518
- `Profile: ${result.profile_name}`,
519
- `Target: ${result.target_url}`,
520
- `Checked: ${result.checked}`,
521
- `Failed: ${result.failed}`
522
- ];
523
- for (const check of result.checks) {
524
- lines.push(`- ${check.ok ? "passed" : "failed"}: ${check.method} ${check.url}`);
525
- if (!check.ok) {
526
- if (check.status !== null) lines.push(` status: ${check.status}`);
527
- if (check.error) lines.push(` error: ${check.error}`);
528
- if (check.body_contains_missing.length) lines.push(` missing body_contains: ${check.body_contains_missing.join(", ")}`);
529
- if (check.body_not_contains_found.length) lines.push(` found body_not_contains: ${check.body_not_contains_found.join(", ")}`);
530
- if (check.body_not_patterns_found.length) lines.push(` found body_not_patterns: ${check.body_not_patterns_found.join(", ")}`);
531
- }
532
- }
533
- return `${lines.join("\n")}
534
- `;
535
- }
536
- function profileResultMarkdown(result) {
537
- const lines = [
538
- `# Riddle Proof Profile: ${result.profile_name}`,
539
- "",
540
- `Status: ${result.status}`,
541
- `Runner: ${result.runner}`,
542
- `Captured: ${result.captured_at}`,
543
- "",
544
- result.summary,
545
- ""
546
- ];
547
- if (Array.isArray(result.warnings) && result.warnings.length) {
548
- lines.push("## Profile Warnings", "");
549
- for (const warning of result.warnings.slice(0, 12)) {
550
- lines.push(`- ${warning}`);
551
- }
552
- if (result.warnings.length > 12) lines.push(`- ${result.warnings.length - 12} additional warning(s) omitted.`);
553
- lines.push("");
554
- }
555
- const packMetadataLines = profilePackMetadataMarkdown(result);
556
- if (packMetadataLines.length) {
557
- lines.push("## Proof Pack", "", ...packMetadataLines, "");
558
- }
559
- lines.push("## Checks", "");
560
- for (const check of result.checks) {
561
- lines.push(`- ${check.status}: ${profileCheckMarkdownLabel(check)}`);
562
- if (check.message) lines.push(` ${check.message}`);
563
- }
564
- const setupSummaryLines = profileSetupSummaryMarkdown(result);
565
- if (setupSummaryLines.length) {
566
- lines.push("", "## Setup Summary", "", ...setupSummaryLines);
567
- }
568
- const reachabilitySummaryLines = profileReachabilitySummaryMarkdown(result);
569
- if (reachabilitySummaryLines.length) {
570
- lines.push("", "## Reachability", "", ...reachabilitySummaryLines);
571
- }
572
- const stateContractSummaryLines = profileStateContractSummaryMarkdown(result);
573
- if (stateContractSummaryLines.length) {
574
- lines.push("", "## State Contract", "", ...stateContractSummaryLines);
575
- }
576
- const sideCaveatSummaryLines = profileSideCaveatSummaryMarkdown(result);
577
- if (sideCaveatSummaryLines.length) {
578
- lines.push("", "## Side Caveats", "", ...sideCaveatSummaryLines);
579
- }
580
- const networkMockSummaryLines = profileNetworkMockSummaryMarkdown(result);
581
- if (networkMockSummaryLines.length) {
582
- lines.push("", "## Network Mocks", "", ...networkMockSummaryLines);
583
- }
584
- const routeInventorySummaryLines = profileRouteInventorySummaryMarkdown(result);
585
- if (routeInventorySummaryLines.length) {
586
- lines.push("", "## Route Inventory", "", ...routeInventorySummaryLines);
587
- }
588
- const linkStatusSummaryLines = profileLinkStatusSummaryMarkdown(result);
589
- if (linkStatusSummaryLines.length) {
590
- lines.push("", "## Link Status", "", ...linkStatusSummaryLines);
591
- }
592
- const httpStatusSummaryLines = profileHttpStatusSummaryMarkdown(result);
593
- if (httpStatusSummaryLines.length) {
594
- lines.push("", "## HTTP Status", "", ...httpStatusSummaryLines);
595
- }
596
- const environmentBlockerLines = profileEnvironmentBlockerMarkdown(result);
597
- if (environmentBlockerLines.length) {
598
- lines.push("", "## Environment Blocker", "", ...environmentBlockerLines);
599
- }
600
- const riddleJobLines = profileRiddleJobMarkdown(result);
601
- if (riddleJobLines.length) {
602
- lines.push("", "## Riddle Job", "", ...riddleJobLines);
603
- }
604
- if (result.artifacts.riddle_artifacts?.length) {
605
- lines.push("", "## Riddle Artifacts", "");
606
- for (const artifact of result.artifacts.riddle_artifacts.slice(0, 40)) {
607
- lines.push(`- ${artifact.name || artifact.kind || "artifact"}${artifact.url ? `: ${artifact.url}` : ""}`);
608
- }
609
- }
610
- return `${lines.join("\n")}
611
- `;
612
- }
613
- function profileRiddleJobMarkdown(result) {
614
- const riddle = cliRecord(result.riddle);
615
- if (!riddle) return [];
616
- const jobId = cliString(riddle.job_id);
617
- const mode = cliString(riddle.mode);
618
- const jobCount = cliFiniteNumber(riddle.job_count);
619
- const status = cliString(riddle.status);
620
- const terminal = typeof riddle.terminal === "boolean" ? riddle.terminal : void 0;
621
- const queueElapsedMs = cliFiniteNumber(riddle.queue_elapsed_ms);
622
- const elapsedMs = cliFiniteNumber(riddle.elapsed_ms);
623
- const preSubmissionElapsedMs = cliFiniteNumber(riddle.pre_submission_elapsed_ms);
624
- const attempt = cliFiniteNumber(riddle.attempt);
625
- const attempts = cliFiniteNumber(riddle.attempts);
626
- const submittedAt = cliString(riddle.submitted_at);
627
- const completedAt = cliString(riddle.completed_at);
628
- const artifactRecovery = riddle.artifact_recovery === true;
629
- const retryCount = cliFiniteNumber(riddle.retry_count);
630
- const staleJobIds = Array.isArray(riddle.stale_job_ids) ? riddle.stale_job_ids.map((value) => cliString(value)).filter((value) => Boolean(value)) : [];
631
- const splitJobs = Array.isArray(riddle.split_jobs) ? riddle.split_jobs.map(cliRecord).filter((job) => Boolean(job)) : [];
632
- const parts = [
633
- mode ? `mode ${markdownInlineCode(mode)}` : "",
634
- jobCount === void 0 ? "" : `jobs ${jobCount}`,
635
- jobId ? `job ${markdownInlineCode(jobId)}` : "",
636
- status ? `status ${markdownInlineCode(status)}` : "",
637
- terminal === void 0 ? "" : `terminal ${terminal ? "true" : "false"}`
638
- ].filter(Boolean);
639
- const lines = parts.length ? [`- ${parts.join(", ")}`] : [];
640
- if (queueElapsedMs !== void 0 || elapsedMs !== void 0 || attempt !== void 0 || attempts !== void 0) {
641
- if (splitJobs.length) {
642
- const maxChildQueueElapsedMs = maxDefinedNumbers(splitJobs.map((job) => cliFiniteNumber(job.queue_elapsed_ms)));
643
- const maxChildElapsedMs = maxDefinedNumbers(splitJobs.map((job) => cliFiniteNumber(job.elapsed_ms)));
644
- const maxChildPreSubmissionElapsedMs = maxDefinedNumbers(splitJobs.map((job) => cliFiniteNumber(job.pre_submission_elapsed_ms)));
645
- lines.push(
646
- `- child poll totals: queue ${formatPollDuration(queueElapsedMs)}, elapsed ${formatPollDuration(elapsedMs)}${preSubmissionElapsedMs === void 0 || preSubmissionElapsedMs < 1e3 ? "" : `, pre-submit ${formatPollDuration(preSubmissionElapsedMs)}`}; max child queue ${formatPollDuration(maxChildQueueElapsedMs)}, max child elapsed ${formatPollDuration(maxChildElapsedMs)}${maxChildPreSubmissionElapsedMs === void 0 || maxChildPreSubmissionElapsedMs < 1e3 ? "" : `, max child pre-submit ${formatPollDuration(maxChildPreSubmissionElapsedMs)}`}`
647
- );
648
- } else {
649
- lines.push(
650
- `- poll: queue ${formatPollDuration(queueElapsedMs)}, elapsed ${formatPollDuration(elapsedMs)}${preSubmissionElapsedMs === void 0 || preSubmissionElapsedMs < 1e3 ? "" : `, pre-submit ${formatPollDuration(preSubmissionElapsedMs)}`}${attempt === void 0 ? "" : `, attempt ${attempt}${attempts === void 0 ? "" : `/${attempts}`}`}`
651
- );
652
- }
653
- }
654
- if (submittedAt || completedAt) {
655
- lines.push(`- timing:${submittedAt ? ` submitted ${markdownInlineCode(submittedAt)}` : ""}${completedAt ? ` completed ${markdownInlineCode(completedAt)}` : ""}`);
656
- }
657
- if (artifactRecovery) {
658
- lines.push("- artifact recovery: used artifacts endpoint after non-terminal poll");
659
- }
660
- if (retryCount !== void 0 && retryCount > 0) {
661
- lines.push(`- retry recovery: replaced ${retryCount} unsubmitted job${retryCount === 1 ? "" : "s"}${staleJobIds.length ? ` (${staleJobIds.map((value) => markdownInlineCode(value)).join(", ")})` : ""}`);
662
- }
663
- for (const job of splitJobs.slice(0, 12)) {
664
- const viewport = cliString(job.viewport) || "viewport";
665
- const splitJobId = cliString(job.job_id);
666
- const splitStatus = cliString(job.status);
667
- const splitTerminal = typeof job.terminal === "boolean" ? job.terminal : void 0;
668
- const splitElapsedMs = cliFiniteNumber(job.elapsed_ms);
669
- const splitPreSubmissionElapsedMs = cliFiniteNumber(job.pre_submission_elapsed_ms);
670
- const splitArtifactRecovery = job.artifact_recovery === true;
671
- const splitRetryCount = cliFiniteNumber(job.retry_count);
672
- lines.push(
673
- `- ${viewport}: ${[
674
- splitJobId ? `job ${markdownInlineCode(splitJobId)}` : "",
675
- splitStatus ? `status ${markdownInlineCode(splitStatus)}` : "",
676
- splitTerminal === void 0 ? "" : `terminal ${splitTerminal ? "true" : "false"}`,
677
- splitElapsedMs === void 0 ? "" : `elapsed ${formatPollDuration(splitElapsedMs)}`,
678
- splitPreSubmissionElapsedMs === void 0 || splitPreSubmissionElapsedMs < 1e3 ? "" : `pre-submit ${formatPollDuration(splitPreSubmissionElapsedMs)}`,
679
- splitRetryCount === void 0 || splitRetryCount <= 0 ? "" : `retries ${splitRetryCount}`,
680
- splitArtifactRecovery ? "artifact recovery" : ""
681
- ].filter(Boolean).join(", ") || "job metadata unavailable"}`
682
- );
683
- }
684
- if (splitJobs.length > 12) lines.push(`- ${splitJobs.length - 12} additional split job(s) omitted.`);
685
- return lines;
686
- }
687
- function maxDefinedNumbers(values) {
688
- const numbers = values.filter((value) => typeof value === "number" && Number.isFinite(value));
689
- return numbers.length ? Math.max(...numbers) : void 0;
690
- }
691
- function profileMetadataStringArray(value) {
692
- return Array.isArray(value) ? value.map((item) => typeof item === "string" ? item.trim() : "").filter((item) => Boolean(item)) : [];
693
- }
694
- function profileSetupSummaryRecord(result) {
695
- const setupCheck = result.checks.find((check) => check.type === "setup_actions_succeeded");
696
- return cliRecord(setupCheck?.evidence?.setup_summary);
697
- }
698
- function profileSetupSummaryViewports(result) {
699
- const setupSummary = profileSetupSummaryRecord(result);
700
- return Array.isArray(setupSummary?.viewports) ? setupSummary.viewports.map(cliRecord).filter((viewport) => Boolean(viewport)) : [];
701
- }
702
- function profileHasPassedCheck(result, types) {
703
- return result.checks.some((check) => types.includes(check.type) && check.status === "passed");
704
- }
705
- function profileHasCheck(result, types) {
706
- return result.checks.some((check) => types.includes(check.type));
707
- }
708
- function profileSetupScreenshotCount(viewports) {
709
- return viewports.reduce((sum, viewport) => {
710
- const setupScreenshots = Array.isArray(viewport.setup_screenshots) ? viewport.setup_screenshots.filter((label) => typeof label === "string" && label.trim()).length : 0;
711
- const finalScreenshot = cliString(viewport.final_screenshot) || cliString(viewport.screenshot_label) ? 1 : 0;
712
- return sum + setupScreenshots + finalScreenshot;
713
- }, 0);
714
- }
715
- function profileSetupReceiptTotal(viewports, key) {
716
- return viewports.reduce((sum, viewport) => sum + setupReceiptArray(viewport, key).filter((receipt) => receipt.ok !== false).length, 0);
717
- }
718
- function profileSetupActionCount(viewports, action) {
719
- return viewports.reduce((sum, viewport) => {
720
- const actionCounts = cliRecord(viewport.action_counts);
721
- return sum + (cliFiniteNumber(actionCounts?.[action]) || 0);
722
- }, 0);
723
- }
724
- function profileSetupFailureCount(viewports) {
725
- return viewports.reduce((sum, viewport) => {
726
- const failed = Array.isArray(viewport.failed) ? viewport.failed : [];
727
- return sum + failed.filter((failure) => Boolean(cliRecord(failure))).length;
728
- }, 0);
729
- }
730
- function profileSetupObstructionCount(viewports) {
731
- return viewports.reduce((sum, viewport) => {
732
- const failed = Array.isArray(viewport.failed) ? viewport.failed.map(cliRecord).filter((failure) => Boolean(failure)) : [];
733
- return sum + failed.filter((failure) => Boolean(setupFailureObstructionSnippet(cliString(failure.reason)))).length;
734
- }, 0);
735
- }
736
- function profileResultHasArtifact(result) {
737
- return Boolean(
738
- result.artifacts.proof_json || result.artifacts.console || result.artifacts.dom_summary || result.artifacts.screenshots?.length || result.artifacts.riddle_artifacts?.some((artifact) => artifact.url || artifact.path || artifact.name)
739
- );
740
- }
741
- function profileReceiptSignalStatus(hasSignal, presentReason, missingReason) {
742
- return hasSignal ? { status: "present", reason: presentReason } : { status: "missing", reason: missingReason };
743
- }
744
- function profileViewportNameList(viewports) {
745
- const names = [...new Set(viewports.map((viewport) => cliString(viewport.name) || cliString(viewport.viewport)).filter((name) => Boolean(name)))];
746
- if (!names.length) return "unnamed";
747
- const shown = names.slice(0, 6).join(", ");
748
- return names.length > 6 ? `${shown}, +${names.length - 6} more` : shown;
749
- }
750
- function profileEveryRouteViewportStatus(result, setupSummary, setupViewports, evidenceViewports) {
751
- const evidenceViewportRecords = evidenceViewports.map(cliRecord).filter((viewport) => Boolean(viewport));
752
- const domSummary = cliRecord(result.evidence?.dom_summary);
753
- const expectedViewportCount = cliFiniteNumber(domSummary?.expected_viewport_count) ?? cliFiniteNumber(setupSummary?.viewport_count) ?? cliFiniteNumber(domSummary?.viewport_count) ?? Math.max(evidenceViewportRecords.length, setupViewports.length);
754
- const evidenceWithRoute = evidenceViewportRecords.filter((viewport) => Boolean(cliRecord(viewport.route)) || Boolean(result.route) && Boolean(cliString(viewport.screenshot_label)));
755
- const setupOkCount = setupViewports.filter((viewport) => viewport.ok !== false).length;
756
- const setupComplete = !setupViewports.length || setupOkCount >= expectedViewportCount;
757
- if (expectedViewportCount > 0 && evidenceWithRoute.length >= expectedViewportCount && setupComplete) {
758
- return {
759
- status: "present",
760
- reason: `route/setup evidence present for all ${expectedViewportCount} viewport(s): ${profileViewportNameList(evidenceWithRoute)}`
761
- };
762
- }
763
- const setupPart = setupViewports.length ? `, setup ok ${setupOkCount}/${expectedViewportCount}` : "";
764
- return {
765
- status: "missing",
766
- reason: `route/viewport evidence incomplete: expected ${expectedViewportCount}, route evidence ${evidenceWithRoute.length}${setupPart}`
767
- };
768
- }
769
- function compactProfileReceiptReason(value, limit = 180) {
770
- const text = cliString(value)?.replace(/\s+/g, " ").trim();
771
- if (!text) return void 0;
772
- return text.length <= limit ? text : `${text.slice(0, Math.max(0, limit - 3)).trimEnd()}...`;
773
- }
774
- function profileCleanupInventoryHaystack(receipt) {
775
- const returnStoredTo = cliString(receipt.return_stored_to) || "";
776
- const reason = cliString(receipt.reason) || "";
777
- const error = cliString(receipt.error) || "";
778
- const summary = cliReturnSummaryLabel(receipt.return_summary) || "";
779
- return `${returnStoredTo} ${reason} ${error} ${summary}`.toLowerCase();
780
- }
781
- function profileIsCleanupInventoryReceipt(receipt) {
782
- const haystack = profileCleanupInventoryHaystack(receipt);
783
- return haystack.includes("cleanup") || haystack.includes("post-cleanup") || haystack.includes("stale") || haystack.includes("statehygiene") || haystack.includes("state hygiene") || haystack.includes("remained after") || haystack.includes("still present");
784
- }
785
- function profileIsCleanupPhaseInventoryReceipt(receipt) {
786
- const storedTo = (cliString(receipt.return_stored_to) || "").toLowerCase();
787
- const storedSegments = storedTo.split(/[.[\]/]/).filter(Boolean);
788
- const storedSegment = storedSegments[storedSegments.length - 1] || storedTo;
789
- const state = (cliString(setupReturnSummaryValue(receipt, ["state", "phase"])) || "").toLowerCase();
790
- const summary = (cliReturnSummaryLabel(receipt.return_summary) || "").toLowerCase();
791
- const markers = [storedSegment, state, summary];
792
- return markers.some((marker) => marker === "cleanup" || marker === "postcleanup" || marker === "post-cleanup" || marker === "aftercleanup" || marker === "after-cleanup" || marker.includes("post-cleanup") || marker.includes("after-cleanup") || marker.includes("after-clear") || marker.includes("after-reset") || marker.includes("after-undo") || marker.includes("after-discard") || marker.includes("after-new"));
793
- }
794
- function profileCleanupPhaseInventoryReceipts(setupViewports) {
795
- return setupViewports.flatMap((viewport) => [
796
- ...setupReceiptArray(viewport, "window_eval"),
797
- ...setupReceiptArray(viewport, "window_call")
798
- ]).filter((receipt) => profileIsCleanupInventoryReceipt(receipt) && profileIsCleanupPhaseInventoryReceipt(receipt));
799
- }
800
- function profileFailedCleanupInventoryReceiptReason(receipt) {
801
- if (receipt.ok === false) {
802
- const error = cliString(receipt.error);
803
- const reason = cliString(receipt.reason);
804
- return compactProfileReceiptReason(error) || compactProfileReceiptReason(reason) || "cleanup inventory failed";
805
- }
806
- const parts = [];
807
- if (setupReturnedSummaryValue(receipt, ["ok"]) === false) parts.push("ok=false");
808
- if (setupReturnedSummaryValue(receipt, ["success"]) === false) parts.push("success=false");
809
- const staleCount = cliFiniteNumber(setupReturnSummaryValue(receipt, ["staleCount"]));
810
- if (staleCount !== void 0 && staleCount > 0) parts.push(`staleCount=${staleCount}`);
811
- const staleNames = setupReturnSummaryValue(receipt, ["staleNames"]);
812
- if (Array.isArray(staleNames) && staleNames.length > 0) {
813
- const staleNamesLabel = cliValueLabel(staleNames);
814
- if (staleNamesLabel) parts.push(`staleNames=${compactProfileReceiptReason(staleNamesLabel, 120) ?? staleNamesLabel}`);
815
- }
816
- const productIssue = setupReturnedSummaryValue(receipt, ["productIssue", "issue"]);
817
- const productIssueLabel = typeof productIssue === "string" ? compactProfileReceiptReason(productIssue, 120) : void 0;
818
- if (parts.length && productIssueLabel) parts.push(productIssueLabel);
819
- return parts.length ? parts.join(", ") : void 0;
820
- }
821
- function profileFailedCleanupInventoryReason(setupViewports) {
822
- const receipts = profileCleanupPhaseInventoryReceipts(setupViewports);
823
- for (const receipt of [...receipts].reverse()) {
824
- const reason = profileFailedCleanupInventoryReceiptReason(receipt);
825
- if (reason) return reason;
826
- }
827
- return void 0;
828
- }
829
- function profilePassedCleanupInventoryReceiptReason(receipt) {
830
- if (receipt.ok === false) return void 0;
831
- if (setupReturnedSummaryValue(receipt, ["ok"]) === false) return void 0;
832
- if (setupReturnedSummaryValue(receipt, ["success"]) === false) return void 0;
833
- const staleCount = cliFiniteNumber(setupReturnSummaryValue(receipt, ["staleCount"]));
834
- const staleNames = setupReturnSummaryValue(receipt, ["staleNames"]);
835
- if (staleCount !== 0 || !Array.isArray(staleNames) || staleNames.length !== 0) return void 0;
836
- return "staleCount=0, staleNames=[]";
837
- }
838
- function profilePassedCleanupInventoryReason(setupViewports) {
839
- const receipts = profileCleanupPhaseInventoryReceipts(setupViewports);
840
- for (const receipt of [...receipts].reverse()) {
841
- const reason = profilePassedCleanupInventoryReceiptReason(receipt);
842
- if (reason) return reason;
843
- }
844
- return void 0;
845
- }
846
- function profileHasRouteExitAffordanceReceipt(receipts) {
847
- const affordanceFields = [
848
- "navVisibleBeforeExit",
849
- "navVisible",
850
- "navigationVisible",
851
- "exitVisible",
852
- "exitControlVisible",
853
- "routeExitVisible",
854
- "homeLinkVisible"
855
- ];
856
- const routeFields = ["route", "afterRoute", "nextRoute", "browserPath", "path"];
857
- return receipts.some((receipt) => {
858
- if (affordanceFields.some((name) => setupReturnSummaryValue(receipt, [name]) !== void 0)) return true;
859
- const storedTo = cliString(receipt.return_stored_to) || "";
860
- const summary = cliReturnSummaryLabel(receipt.return_summary) || "";
861
- const reason = cliString(receipt.reason) || "";
862
- const haystack = `${storedTo} ${summary} ${reason}`.toLowerCase();
863
- const mentionsRouteExit = haystack.includes("routeexit") || haystack.includes("route-exit") || haystack.includes("route exit") || haystack.includes("afterrouteexit") || haystack.includes("after route exit");
864
- if (!mentionsRouteExit) return false;
865
- return routeFields.some((name) => setupReturnSummaryValue(receipt, [name]) !== void 0) || haystack.includes("route=") || haystack.includes("browserpath=");
866
- });
867
- }
868
- function profileCleanupLabelMatches(value) {
869
- if (!value) return false;
870
- return /\b(cleanup|clean|clear|reset|undo|discard|new)\b/i.test(value);
871
- }
872
- function profileHasCleanupBoundaryAffordanceReceipt(receipts) {
873
- const visibleFields = [
874
- "cleanupControlVisible",
875
- "cleanupVisible",
876
- "clearControlVisible",
877
- "resetControlVisible",
878
- "undoVisible",
879
- "discardVisible",
880
- "newControlVisible",
881
- "exitControlVisible"
882
- ];
883
- const textFields = [
884
- "cleanupControlText",
885
- "cleanupText",
886
- "clearControlText",
887
- "resetControlText",
888
- "undoText",
889
- "discardText",
890
- "newControlText",
891
- "exitControlText",
892
- "controlText",
893
- "affordanceText"
894
- ];
895
- return receipts.some((receipt) => {
896
- const storedTo = cliString(receipt.return_stored_to) || "";
897
- const label = cliString(receipt.label) || "";
898
- const path2 = cliString(receipt.path) || cliString(receipt.function_name) || "";
899
- const summary = cliReturnSummaryLabel(receipt.return_summary) || "";
900
- const haystack = `${storedTo} ${label} ${path2} ${summary}`.toLowerCase();
901
- const mentionsCleanupBoundary = haystack.includes("cleanup") || haystack.includes("precleanup") || haystack.includes("pre-cleanup") || haystack.includes("boundary") || haystack.includes("undo") || haystack.includes("clear") || haystack.includes("reset") || haystack.includes("discard");
902
- const visibleControl = visibleFields.some((name) => setupReturnSummaryValue(receipt, [name]) === true);
903
- const controlText = textFields.map((name) => cliString(setupReturnSummaryValue(receipt, [name]))).find((value) => profileCleanupLabelMatches(value));
904
- return mentionsCleanupBoundary && (visibleControl || Boolean(controlText));
905
- });
906
- }
907
- function profileVisibleCleanupActionCount(setupViewports) {
908
- const keys = /* @__PURE__ */ new Set();
909
- const clickedReceipts = setupViewports.flatMap((viewport) => [
910
- ...setupReceiptArray(viewport, "clicked"),
911
- ...setupReceiptArray(viewport, "tap"),
912
- ...setupReceiptArray(viewport, "tap_until")
913
- ]);
914
- clickedReceipts.forEach((receipt, index) => {
915
- if (receipt.ok === false) return;
916
- const text = cliString(receipt.text) || cliString(receipt.label) || cliString(receipt.target) || cliString(receipt.selector);
917
- if (!profileCleanupLabelMatches(text)) return;
918
- const ordinal = cliFiniteNumber(receipt.ordinal);
919
- keys.add(ordinal === void 0 ? `idx:${index}:${text}` : `ord:${ordinal}:${text}`);
920
- });
921
- return keys.size;
922
- }
923
- function profileHasOfflineAudioMetricsReceipt(receipts) {
924
- const metricFields = [
925
- "mixPeak",
926
- "mixRms",
927
- "maxPeak",
928
- "avgRms",
929
- "audioPeak",
930
- "audioRms",
931
- "offlinePeak",
932
- "offlineRms",
933
- "peak",
934
- "rms"
935
- ];
936
- const metricFieldNames = new Set(metricFields.map((name) => name.toLowerCase()));
937
- const positiveMetricValue = (value) => {
938
- const number = cliFiniteNumber(value);
939
- return number !== void 0 && number > 0;
940
- };
941
- const metricSummaryItem = (item) => {
942
- const label = (cliString(item.label) || "").toLowerCase();
943
- const path2 = (cliString(item.path) || "").toLowerCase();
944
- const tail = (path2.split(".").filter(Boolean).pop() || label).toLowerCase();
945
- const normalizedLabel = label.replace(/[^a-z0-9]+/g, "");
946
- const normalizedTail = tail.replace(/[^a-z0-9]+/g, "");
947
- return metricFieldNames.has(normalizedLabel) || metricFieldNames.has(normalizedTail) || /(^|\.)(mixhealth|monitormetrics|instrumentmetrics)\.(peak|rms)$/.test(path2);
948
- };
949
- return receipts.some((receipt) => {
950
- if (metricFields.some((name) => positiveMetricValue(setupReturnSummaryValue(receipt, [name])))) return true;
951
- const summaries = Array.isArray(receipt.return_summary) ? receipt.return_summary.map(cliRecord).filter((item) => Boolean(item)) : [];
952
- return summaries.some((item) => metricSummaryItem(item) && positiveMetricValue(item.value));
953
- });
954
- }
955
- function profileHasActiveRouteLocalProofReceipt(receipts) {
956
- return receipts.some((receipt) => {
957
- const route = cliString(setupReturnSummaryValue(receipt, ["route", "browserPath", "path"]));
958
- if (!route) return false;
959
- const proofVersion = cliString(setupReturnSummaryValue(receipt, ["proofVersion", "proof_version", "proofKind", "proof_kind"]));
960
- const globalCount = cliFiniteNumber(setupReturnSummaryValue(receipt, ["globalCount", "activeGlobalCount", "activeGlobals.length"]));
961
- const globalNames = setupReturnSummaryValue(receipt, ["globalNames", "activeGlobals"]);
962
- const enabled = setupReturnSummaryValue(receipt, ["enabled", "proofEnabled", "proof_enabled"]) === true;
963
- const ready = setupReturnSummaryValue(receipt, ["ready", "proofReady", "proof_ready"]) === true;
964
- const supportsProofFeature = setupReturnSummaryValue(receipt, ["supportsOfflineAudio", "supportsProof", "proofSupported"]) === true;
965
- const autopilotActive = setupReturnSummaryValue(receipt, ["autopilot", "autopilotEnabled", "autopilot_enabled"]) === true;
966
- const runtimeMetricPresent = [
967
- "metricsPresent",
968
- "frameMetricsPresent",
969
- "runtimeMetricsPresent",
970
- "routeMetricsPresent"
971
- ].some((name) => setupReturnSummaryValue(receipt, [name]) === true);
972
- const runtimeMetricMeasured = [
973
- "heightPx",
974
- "centerPx",
975
- "targetHeight",
976
- "frameCount",
977
- "elapsedMs",
978
- "distance",
979
- "speed",
980
- "velocity",
981
- "planLength",
982
- "stepDelta",
983
- "afterSteps",
984
- "beforeSteps"
985
- ].some((name) => cliFiniteNumber(setupReturnSummaryValue(receipt, [name])) !== void 0);
986
- return Boolean(
987
- proofVersion || enabled || ready || supportsProofFeature || autopilotActive || runtimeMetricPresent || runtimeMetricMeasured || globalCount !== void 0 && globalCount > 0 || Array.isArray(globalNames) && globalNames.length > 0
988
- );
989
- });
990
- }
991
- function profileLowerSummaryValue(receipt, names) {
992
- return names.map((name) => cliString(setupReturnSummaryValue(receipt, [name]))?.toLowerCase()).find((value) => Boolean(value)) || "";
993
- }
994
- function profileHasTerminalLossReceipt(receipts) {
995
- return receipts.some((receipt) => {
996
- const status = profileLowerSummaryValue(receipt, ["status", "state", "phase"]);
997
- const outcome = profileLowerSummaryValue(receipt, ["lastOutcome", "outcome", "terminalOutcome", "terminal"]);
998
- const lastFlightLost = setupReturnSummaryValue(receipt, ["lastFlightLost", "lost"]) === true;
999
- const outOfBounds = setupReturnSummaryValue(receipt, ["lastFlightOutOfBounds", "outOfBounds"]) === true;
1000
- const storedTo = cliString(receipt.return_stored_to) || "";
1001
- const label = cliString(receipt.label) || "";
1002
- const path2 = cliString(receipt.path) || cliString(receipt.function_name) || "";
1003
- const haystack = `${storedTo} ${label} ${path2}`.toLowerCase();
1004
- const labelsLoss = haystack.includes("loss") || haystack.includes("lost") || haystack.includes("terminal");
1005
- if (!labelsLoss && !lastFlightLost && !outOfBounds) return false;
1006
- return lastFlightLost || outOfBounds || ["over", "lost", "loss", "failed", "failure", "game_over", "gameover"].includes(status) || ["lost", "loss", "failed", "failure", "game_over", "gameover"].includes(outcome);
1007
- });
1008
- }
1009
- function profileHasTerminalGameOverReceipt(receipts) {
1010
- return receipts.some((receipt) => {
1011
- const status = profileLowerSummaryValue(receipt, ["status", "state", "phase"]);
1012
- const outcome = profileLowerSummaryValue(receipt, ["lastOutcome", "outcome", "terminalOutcome", "terminal", "result"]);
1013
- const gameOver = setupReturnSummaryValue(receipt, ["gameOver", "game_over", "isGameOver"]) === true;
1014
- const caught = setupReturnSummaryValue(receipt, ["caught", "playerCaught", "wasCaught"]) === true;
1015
- const storedTo = cliString(receipt.return_stored_to) || "";
1016
- const label = cliString(receipt.label) || "";
1017
- const path2 = cliString(receipt.path) || cliString(receipt.function_name) || "";
1018
- const slot = cliString(setupReturnSummaryValue(receipt, ["slot"])) || "";
1019
- const haystack = `${storedTo} ${label} ${path2} ${slot}`.toLowerCase();
1020
- const labelsTerminal = haystack.includes("gameover") || haystack.includes("game_over") || haystack.includes("game-over") || haystack.includes("game over") || haystack.includes("terminal") || haystack.includes("caught") || haystack.includes("catch");
1021
- const terminalStatus = ["over", "game_over", "gameover"].includes(status) || ["game_over", "gameover"].includes(outcome);
1022
- if (!labelsTerminal && !caught && !gameOver && !terminalStatus) return false;
1023
- return gameOver || caught || terminalStatus;
1024
- });
1025
- }
1026
- function profileHasTerminalSuccessReceipt(receipts) {
1027
- return receipts.some((receipt) => {
1028
- const status = profileLowerSummaryValue(receipt, ["status", "state", "phase"]);
1029
- const outcome = profileLowerSummaryValue(receipt, ["lastOutcome", "outcome", "terminalOutcome", "terminal", "result"]);
1030
- const storedTo = cliString(receipt.return_stored_to) || "";
1031
- const label = cliString(receipt.label) || "";
1032
- const path2 = cliString(receipt.path) || cliString(receipt.function_name) || "";
1033
- const haystack = `${storedTo} ${label} ${path2}`.toLowerCase();
1034
- if (haystack.includes("shot")) return false;
1035
- const labelsSuccess = haystack.includes("success") || haystack.includes("terminal") || haystack.includes("completed") || haystack.includes("complete");
1036
- const success = setupReturnSummaryValue(receipt, ["success", "passed", "completed"]) === true;
1037
- const targetHit = setupReturnSummaryValue(receipt, ["lastFlightTargetHit", "targetHit"]) === true;
1038
- const gateHit = setupReturnSummaryValue(receipt, ["lastFlight.passedThroughGate", "passedThroughGate", "gate"]) === true;
1039
- const bucketHit = setupReturnSummaryValue(receipt, ["lastFlight.bucketHit", "bucketHit", "bucket"]) === true;
1040
- if (!labelsSuccess && !success && !targetHit && !gateHit && !bucketHit) return false;
1041
- return success || targetHit || gateHit || bucketHit || ["success", "won", "complete", "completed", "passed"].includes(status) || ["success", "won", "complete", "completed", "passed"].includes(outcome);
1042
- });
1043
- }
1044
- function profileHasControlledLaunchReceipt(receipts, expected) {
1045
- return receipts.some((receipt) => {
1046
- const shotKind = profileLowerSummaryValue(receipt, ["lastShotKind", "shotKind", "kind"]);
1047
- const shotStatus = profileLowerSummaryValue(receipt, ["lastShotStatus", "shotStatus"]);
1048
- const outcome = profileLowerSummaryValue(receipt, ["lastOutcome", "outcome"]);
1049
- if (expected === "success") {
1050
- return shotKind === "success" && (!shotStatus || shotStatus === "success" || outcome === "success");
1051
- }
1052
- return ["failure", "failed", "miss", "lost", "loss"].includes(shotKind) || ["failure", "failed", "miss", "lost", "loss"].includes(shotStatus) || ["failure", "failed", "miss", "lost", "loss"].includes(outcome);
1053
- });
1054
- }
1055
- function profileHasRouteContinuationReceipt(receipts) {
1056
- return receipts.some((receipt) => {
1057
- const fromRoute = cliString(setupReturnSummaryValue(receipt, ["fromRoute", "from", "previousRoute", "sourceRoute"]));
1058
- const target = cliString(setupReturnSummaryValue(receipt, ["target", "nextHref", "toRoute", "nextRoute", "href"]));
1059
- const afterRoute = cliString(setupReturnSummaryValue(receipt, ["routeAfterPush", "afterRoute", "route", "observedRoute"]));
1060
- if (!fromRoute || !target && !afterRoute) return false;
1061
- const storedTo = cliString(receipt.return_stored_to) || "";
1062
- const label = cliString(receipt.label) || "";
1063
- const path2 = cliString(receipt.path) || cliString(receipt.function_name) || "";
1064
- const summary = cliReturnSummaryLabel(receipt.return_summary) || "";
1065
- const haystack = `${storedTo} ${label} ${path2} ${summary}`.toLowerCase();
1066
- return haystack.includes("navigation") || haystack.includes("continuation") || haystack.includes("route") || haystack.includes("next") || haystack.includes("target");
1067
- });
1068
- }
1069
- function profileHasRecoveredStateReceipt(receipts) {
1070
- return receipts.some((receipt) => {
1071
- const storedTo = cliString(receipt.return_stored_to) || "";
1072
- const label = cliString(receipt.label) || "";
1073
- const path2 = cliString(receipt.path) || cliString(receipt.function_name) || "";
1074
- const summary = cliReturnSummaryLabel(receipt.return_summary) || "";
1075
- const haystack = `${storedTo} ${label} ${path2} ${summary}`.toLowerCase();
1076
- const labelsRecovery = haystack.includes("recover") || haystack.includes("repaired") || haystack.includes("repair") || haystack.includes("retry") || haystack.includes("restart") || haystack.includes("play again") || haystack.includes("playagain") || haystack.includes("play-again") || haystack.includes("try fix") || haystack.includes("tryfix") || haystack.includes("after-fix") || haystack.includes("fixed");
1077
- if (!labelsRecovery) return false;
1078
- const status = profileLowerSummaryValue(receipt, ["status", "state", "phase"]);
1079
- const outcome = profileLowerSummaryValue(receipt, ["lastOutcome", "outcome", "result", "retryOutcome", "retry_outcome"]);
1080
- const hasRecoveredState = ["valid", "success", "recovered", "fixed", "ready"].includes(status) || ["valid", "success", "recovered", "fixed", "ready", "running_after_retry", "ready_after_retry"].includes(outcome);
1081
- const hasValid = setupReturnSummaryValue(receipt, ["hasValid", "valid", "isValid"]) === true;
1082
- const hasInvalid = setupReturnSummaryValue(receipt, ["hasInvalid", "invalid", "isInvalid"]);
1083
- const success = setupReturnSummaryValue(receipt, ["success", "recovered", "fixed"]) === true;
1084
- const leftTerminalState = setupReturnSummaryValue(receipt, ["leftTerminalState", "left_terminal_state"]) === true;
1085
- const retrySurfaceReady = setupReturnSummaryValue(receipt, ["retrySurfaceReady", "retry_surface_ready"]) === true;
1086
- return hasRecoveredState || success || hasValid && hasInvalid === false || leftTerminalState && retrySurfaceReady;
1087
- });
1088
- }
1089
- function profileHasSequenceInputReceipt(receipts) {
1090
- let hasSequenceContract = false;
1091
- let hasInputReadyState = false;
1092
- let hasSequenceOutcome = false;
1093
- for (const receipt of receipts) {
1094
- const storedTo = cliString(receipt.return_stored_to) || "";
1095
- const label = cliString(receipt.label) || "";
1096
- const path2 = cliString(receipt.path) || cliString(receipt.function_name) || "";
1097
- const slot = profileLowerSummaryValue(receipt, ["slot", "phase", "state"]);
1098
- const statusText = profileLowerSummaryValue(receipt, ["statusText", "status", "message"]);
1099
- const summary = cliReturnSummaryLabel(receipt.return_summary) || "";
1100
- const haystack = `${storedTo} ${label} ${path2} ${slot} ${statusText} ${summary}`.toLowerCase();
1101
- const sequenceText = [
1102
- "expectedSequence",
1103
- "expectedLevel2Sequence",
1104
- "inputSequence",
1105
- "targetSequence",
1106
- "sequence",
1107
- "pattern"
1108
- ].map((name) => cliString(setupReturnSummaryValue(receipt, [name]))?.toLowerCase()).find(Boolean) || "";
1109
- const sequenceArray = [
1110
- setupReturnSummaryValue(receipt, ["expectedSequence"]),
1111
- setupReturnSummaryValue(receipt, ["expectedLevel2Sequence"]),
1112
- setupReturnSummaryValue(receipt, ["inputSequence"]),
1113
- setupReturnSummaryValue(receipt, ["targetSequence"]),
1114
- setupReturnSummaryValue(receipt, ["sequence"])
1115
- ].some((value) => Array.isArray(value) && value.length > 0);
1116
- const mentionsSequence = Boolean(sequenceArray || sequenceText) || haystack.includes("sequence") || haystack.includes("short-long") || haystack.includes("short,long") || haystack.includes("short long") || haystack.includes("long-short") || haystack.includes("long,short") || haystack.includes("long short");
1117
- if (mentionsSequence) hasSequenceContract = true;
1118
- const level = cliFiniteNumber(setupReturnSummaryValue(receipt, ["level"]));
1119
- const expectedSteps = cliFiniteNumber(setupReturnSummaryValue(receipt, ["expectedSteps", "stepCount", "sequenceLength"]));
1120
- const controlsEnabled = setupReturnSummaryValue(receipt, ["controlsEnabled", "inputControlsEnabled", "inputEnabled", "canInput"]) === true || setupReturnSummaryValue(receipt, ["shortDisabled"]) === false || setupReturnSummaryValue(receipt, ["longDisabled"]) === false;
1121
- const inputReady = haystack.includes("input") || statusText.includes("your turn") || statusText.includes("ready");
1122
- if (inputReady && (controlsEnabled || level !== void 0 || expectedSteps !== void 0)) {
1123
- hasInputReadyState = true;
1124
- }
1125
- const success = setupReturnSummaryValue(receipt, ["success", "passed"]) === true || statusText.includes("perfect") || statusText.includes("success");
1126
- const failure = statusText.includes("miss") || statusText.includes("failure") || setupReturnSummaryValue(receipt, ["failed"]) === true;
1127
- const streak = cliFiniteNumber(setupReturnSummaryValue(receipt, ["streak"]));
1128
- const best = cliFiniteNumber(setupReturnSummaryValue(receipt, ["best"]));
1129
- if (mentionsSequence && (success || failure || streak !== void 0 || best !== void 0)) {
1130
- hasSequenceOutcome = true;
1131
- }
1132
- }
1133
- return hasSequenceContract && (hasInputReadyState || hasSequenceOutcome);
1134
- }
1135
- function profileHasRestartReadyReceipt(receipts) {
1136
- return receipts.some((receipt) => {
1137
- const storedTo = cliString(receipt.return_stored_to) || "";
1138
- const label = cliString(receipt.label) || "";
1139
- const path2 = cliString(receipt.path) || cliString(receipt.function_name) || "";
1140
- const slot = profileLowerSummaryValue(receipt, ["slot", "phase", "state"]);
1141
- const statusText = profileLowerSummaryValue(receipt, ["statusText", "status", "message"]);
1142
- const summary = cliReturnSummaryLabel(receipt.return_summary) || "";
1143
- const haystack = `${storedTo} ${label} ${path2} ${slot} ${statusText} ${summary}`.toLowerCase();
1144
- const labelsRestart = haystack.includes("restart") || haystack.includes("reset") || haystack.includes("reset-ready") || haystack.includes("reset ready") || haystack.includes("play again") || haystack.includes("play-again") || haystack.includes("playagain") || haystack.includes("retry");
1145
- if (!labelsRestart) return false;
1146
- const ok = receipt.ok !== false && setupReturnSummaryValue(receipt, ["ok"]) !== false;
1147
- const controlsEnabled = setupReturnSummaryValue(receipt, ["controlsEnabled", "inputControlsEnabled", "inputEnabled", "canInput"]) === true || setupReturnSummaryValue(receipt, ["shortDisabled"]) === false && setupReturnSummaryValue(receipt, ["longDisabled"]) === false;
1148
- const level = cliFiniteNumber(setupReturnSummaryValue(receipt, ["level"]));
1149
- const streak = cliFiniteNumber(setupReturnSummaryValue(receipt, ["streak"]));
1150
- const best = cliFiniteNumber(setupReturnSummaryValue(receipt, ["best"]));
1151
- const readyState = statusText.includes("your turn") || statusText.includes("ready") || setupReturnSummaryValue(receipt, ["ready", "restartReady", "restart_ready", "resetReady", "reset_ready"]) === true;
1152
- const hiddenCount = cliFiniteNumber(setupReturnSummaryValue(receipt, ["hiddenCount", "hidden_count"]));
1153
- const moves = cliFiniteNumber(setupReturnSummaryValue(receipt, ["moves", "moveCount", "move_count"]));
1154
- const winner = setupReturnSummaryValue(receipt, ["hasWinner", "winner", "won", "gameWon"]);
1155
- const resetBoardReady = hiddenCount !== void 0 && hiddenCount > 0 && moves === 0 && winner === false;
1156
- return ok && controlsEnabled && (readyState || resetBoardReady || level !== void 0 || streak !== void 0 || best !== void 0);
1157
- });
1158
- }
1159
- function profileMetadataHasGeneratedOutputContract(metadata) {
1160
- const contract = cliRecord(metadata.declared_state_contract);
1161
- if (!contract) return false;
1162
- const keys = Object.keys(contract).join(" ").toLowerCase();
1163
- const values = Object.values(contract).map((value) => cliString(value)?.toLowerCase() || "").join(" ");
1164
- const haystack = `${keys} ${values}`;
1165
- return haystack.includes("generated_output") || haystack.includes("generated output") || haystack.includes("output-size") || haystack.includes("output size") || haystack.includes("output result") || haystack.includes("optimizer size");
1166
- }
1167
- function profileHasGeneratedOutputReceipt(receipts) {
1168
- let outputReady = false;
1169
- let outputChanged = false;
1170
- for (const receipt of receipts) {
1171
- const storedTo = cliString(receipt.return_stored_to) || "";
1172
- const label = cliString(receipt.label) || "";
1173
- const path2 = cliString(receipt.path) || cliString(receipt.function_name) || "";
1174
- const summary = cliReturnSummaryLabel(receipt.return_summary) || "";
1175
- const haystack = `${storedTo} ${label} ${path2} ${summary}`.toLowerCase();
1176
- const readySignal = setupReturnSummaryValue(receipt, ["outputReady", "outputStillReady"]) === true || cliFiniteNumber(setupReturnSummaryValue(receipt, ["surfaceCount", "before.surfaceCount", "after.surfaceCount"])) !== void 0 || setupReturnSummaryValue(receipt, ["size", "before.size", "after.size", "size.text", "before.size.text", "after.size.text"]) !== void 0;
1177
- if (readySignal && (haystack.includes("output") || haystack.includes("size") || haystack.includes("result"))) {
1178
- outputReady = true;
1179
- }
1180
- const beforeBytes = cliFiniteNumber(setupReturnSummaryValue(receipt, ["before.size.outputBytes", "before.outputBytes", "beforeBytes"]));
1181
- const afterBytes = cliFiniteNumber(setupReturnSummaryValue(receipt, ["after.size.outputBytes", "after.outputBytes", "afterBytes"]));
1182
- const beforeText = cliString(setupReturnSummaryValue(receipt, ["before.size.text", "before.outputText", "beforeText"]));
1183
- const afterText = cliString(setupReturnSummaryValue(receipt, ["after.size.text", "after.outputText", "afterText"]));
1184
- const explicitChange = setupReturnSummaryValue(receipt, ["sizeChanged", "outputChanged", "resultChanged"]) === true;
1185
- const byteChange = beforeBytes !== void 0 && afterBytes !== void 0 && beforeBytes !== afterBytes;
1186
- const textChange = Boolean(beforeText && afterText && beforeText !== afterText);
1187
- if (explicitChange || byteChange || textChange) outputChanged = true;
1188
- }
1189
- return outputReady && outputChanged;
1190
- }
1191
- function profileSemanticReceiptPassed(receipt) {
1192
- if (receipt.ok === false) return false;
1193
- return setupReturnSummaryValue(receipt, ["ok", "success", "passed", "completed", "valid"]) === true;
1194
- }
1195
- function profileSemanticArrayEvidence(value) {
1196
- if (Array.isArray(value)) return value.length > 0;
1197
- const text = cliString(value);
1198
- return Boolean(text && text.trim());
1199
- }
1200
- function profileSemanticTruthyField(receipt, names) {
1201
- return names.some((name) => setupReturnSummaryValue(receipt, [name]) === true);
1202
- }
1203
- function profileHasBoardEvidence(receipt) {
1204
- return [
1205
- "board",
1206
- "beforeBoard",
1207
- "afterBoard",
1208
- "cells",
1209
- "grid",
1210
- "state"
1211
- ].some((name) => setupReturnSummaryValue(receipt, [name]) !== void 0);
1212
- }
1213
- function profileHasTurnEvidence(receipt) {
1214
- return [
1215
- "activeX",
1216
- "activeO",
1217
- "turn",
1218
- "currentTurn",
1219
- "nextTurn",
1220
- "currentPlayer",
1221
- "nextPlayer",
1222
- "isXNext"
1223
- ].some((name) => setupReturnSummaryValue(receipt, [name]) !== void 0);
1224
- }
1225
- function profileSemanticInvalidStateReason(receipts, text) {
1226
- const asksInvalidOrBlocked = text.includes("invalid") || text.includes("blocked") || text.includes("occupied") || text.includes("replay") || text.includes("ignored") || text.includes("reject") || text.includes("same board") || text.includes("unchanged");
1227
- if (!asksInvalidOrBlocked) return void 0;
1228
- const asksTurn = text.includes("turn") || text.includes("player");
1229
- for (const receipt of receipts) {
1230
- if (!profileSemanticReceiptPassed(receipt)) continue;
1231
- const unchanged = profileSemanticTruthyField(receipt, [
1232
- "sameBoard",
1233
- "same_board",
1234
- "boardUnchanged",
1235
- "stateUnchanged",
1236
- "unchanged",
1237
- "noMutation",
1238
- "no_mutation"
1239
- ]);
1240
- const blocked = profileSemanticTruthyField(receipt, [
1241
- "blocked",
1242
- "invalid",
1243
- "rejected",
1244
- "ignored",
1245
- "prevented"
1246
- ]);
1247
- if (!(unchanged || blocked)) continue;
1248
- if (!profileHasBoardEvidence(receipt)) continue;
1249
- if (asksTurn && !profileHasTurnEvidence(receipt)) continue;
1250
- const parts = [
1251
- unchanged ? "unchanged=true" : "",
1252
- blocked ? "blocked=true" : "",
1253
- profileHasTurnEvidence(receipt) ? "turn evidence present" : ""
1254
- ].filter(Boolean);
1255
- return `semantic invalid-state receipt present${parts.length ? `: ${parts.join(", ")}` : ""}`;
1256
- }
1257
- return void 0;
1258
- }
1259
- function profileSemanticTerminalLockReason(receipts, text) {
1260
- const asksLock = text.includes("lock") || text.includes("cannot mutate") || text.includes("can not mutate") || text.includes("can't mutate") || text.includes("cannot change") || text.includes("unchanged after") || text.includes("post-winner") && text.includes("click") || text.includes("post winner") && text.includes("click");
1261
- if (!asksLock) return void 0;
1262
- for (const receipt of receipts) {
1263
- if (!profileSemanticReceiptPassed(receipt)) continue;
1264
- const unchanged = profileSemanticTruthyField(receipt, [
1265
- "sameBoard",
1266
- "same_board",
1267
- "boardUnchanged",
1268
- "stateUnchanged",
1269
- "unchanged",
1270
- "noMutation",
1271
- "no_mutation",
1272
- "locked"
1273
- ]);
1274
- if (!unchanged) continue;
1275
- const hasTerminal = profileSemanticTruthyField(receipt, ["hasWinner", "winner", "won", "gameWon", "terminal", "locked"]) || profileSemanticArrayEvidence(setupReturnSummaryValue(receipt, ["winCells", "winningCells", "winningLine"])) || Boolean(cliString(setupReturnSummaryValue(receipt, ["winCellsCsv", "winnerText", "terminalText", "statusText"])));
1276
- if (!hasTerminal) continue;
1277
- return "semantic terminal-lock receipt present: unchanged=true";
1278
- }
1279
- return void 0;
1280
- }
1281
- function profileSemanticWinnerReason(receipts, text) {
1282
- const asksWinner = text.includes("winner") || text.includes("win-cell") || text.includes("winning") || /\bwin\b/.test(text);
1283
- if (!asksWinner) return void 0;
1284
- const asksCounts = text.includes("count");
1285
- const asksWinCells = text.includes("win-cell") || text.includes("winning") || text.includes("inventory") || text.includes("top-row");
1286
- const asksPlayAgain = text.includes("play again") || text.includes("play-again") || text.includes("playagain");
1287
- const asksNewGame = text.includes("new game") || text.includes("new-game") || text.includes("newgame");
1288
- const asksNewRound = text.includes("new round") || text.includes("new-round") || text.includes("newround");
1289
- const asksNewRoute = text.includes("new route") || text.includes("new-route") || text.includes("newroute");
1290
- const asksRestartReset = text.includes("restart") || text.includes("reset");
1291
- for (const receipt of receipts) {
1292
- if (!profileSemanticReceiptPassed(receipt)) continue;
1293
- const winnerText = (cliString(setupReturnSummaryValue(receipt, ["winnerText", "terminalText", "statusText"])) || "").toLowerCase();
1294
- const hasWinner = profileSemanticTruthyField(receipt, ["hasWinner", "winner", "won", "gameWon"]) || winnerText.includes("win") || profileSemanticArrayEvidence(setupReturnSummaryValue(receipt, ["winCells", "winningCells", "winningLine"])) || Boolean(cliString(setupReturnSummaryValue(receipt, ["winCellsCsv"])));
1295
- if (!hasWinner) continue;
1296
- const hasCounts = [
1297
- "xCount",
1298
- "oCount",
1299
- "count",
1300
- "filledCount",
1301
- "winnerCount",
1302
- "score"
1303
- ].some((name) => setupReturnSummaryValue(receipt, [name]) !== void 0);
1304
- const hasWinCells = profileSemanticArrayEvidence(setupReturnSummaryValue(receipt, ["winCells", "winningCells", "winningLine"])) || Boolean(cliString(setupReturnSummaryValue(receipt, ["winCellsCsv"])));
1305
- const hasPlayAgain = profileSemanticTruthyField(receipt, [
1306
- "playAgainVisible",
1307
- "play_again_visible"
1308
- ]);
1309
- const hasNewGame = profileSemanticTruthyField(receipt, [
1310
- "hasNewGame",
1311
- "newGameVisible",
1312
- "new_game_visible"
1313
- ]);
1314
- const hasNewRound = profileSemanticTruthyField(receipt, [
1315
- "hasNewRound",
1316
- "newRoundVisible",
1317
- "new_round_visible"
1318
- ]);
1319
- const hasNewRoute = profileSemanticTruthyField(receipt, [
1320
- "hasNewRoute",
1321
- "newRouteVisible",
1322
- "new_route_visible"
1323
- ]);
1324
- const hasRestartReset = profileSemanticTruthyField(receipt, [
1325
- "restartVisible",
1326
- "restart_visible",
1327
- "resetVisible",
1328
- "reset_visible"
1329
- ]);
1330
- if (asksCounts && !hasCounts) continue;
1331
- if (asksWinCells && !hasWinCells) continue;
1332
- if (asksPlayAgain && !hasPlayAgain) continue;
1333
- if (asksNewGame && !hasNewGame) continue;
1334
- if (asksNewRound && !hasNewRound) continue;
1335
- if (asksNewRoute && !hasNewRoute) continue;
1336
- if (asksRestartReset && !(hasPlayAgain || hasNewGame || hasNewRound || hasNewRoute || hasRestartReset)) continue;
1337
- const hasResetStyleRecovery = hasNewGame || hasNewRound || hasNewRoute || hasRestartReset;
1338
- const matchedRequestedResetStyle = !asksPlayAgain && (asksNewGame && hasNewGame || asksNewRound && hasNewRound || asksNewRoute && hasNewRoute || asksRestartReset && hasResetStyleRecovery);
1339
- const recoveryControlReason = matchedRequestedResetStyle || !hasPlayAgain && hasResetStyleRecovery ? "restart/reset visible" : hasPlayAgain ? "play-again visible" : "";
1340
- const parts = [
1341
- hasCounts ? "counts present" : "",
1342
- hasWinCells ? "win cells present" : "",
1343
- recoveryControlReason
1344
- ].filter(Boolean);
1345
- return `semantic winner receipt present${parts.length ? `: ${parts.join(", ")}` : ""}`;
1346
- }
1347
- return void 0;
1348
- }
1349
- function profileSemanticStateReceiptReason(receipts, text) {
1350
- return profileSemanticTerminalLockReason(receipts, text) || profileSemanticInvalidStateReason(receipts, text) || profileSemanticWinnerReason(receipts, text);
1351
- }
1352
- function profilePackReceiptStatus(result, metadata, receipt) {
1353
- const text = receipt.toLowerCase();
1354
- const setupSummary = profileSetupSummaryRecord(result);
1355
- const setupViewports = profileSetupSummaryViewports(result);
1356
- const evidenceViewports = Array.isArray(result.evidence?.viewports) ? result.evidence.viewports : [];
1357
- const setupResultCount = setupViewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.result_count) || 0), 0);
1358
- const setupScreenshotCount = profileSetupScreenshotCount(setupViewports);
1359
- const screenshotCount = (result.artifacts.screenshots?.length || 0) + evidenceViewports.filter((viewport) => cliString(viewport.screenshot_label)).length + setupScreenshotCount;
1360
- const windowEvalCount = profileSetupReceiptTotal(setupViewports, "window_eval");
1361
- const setupActionValueReceipts = setupViewports.flatMap((viewport) => setupReceiptArray(viewport, "setup_action_results")).concat(evidenceViewports.flatMap((viewport) => setupReceiptArray(cliRecord(viewport) || {}, "setup_action_results"))).filter((item) => {
1362
- const action = cliString(item.action);
1363
- return action === "window_eval" || action === "window_call" || action === "window_call_until" || action === "assert_window_value" || action === "assert_window_number";
1364
- });
1365
- const valueReceipts = [
1366
- ...setupViewports.flatMap((viewport) => setupReceiptArray(viewport, "window_eval")),
1367
- ...setupViewports.flatMap((viewport) => setupReceiptArray(viewport, "window_call")),
1368
- ...setupViewports.flatMap((viewport) => setupReceiptArray(viewport, "window_call_until")),
1369
- ...setupActionValueReceipts
1370
- ].filter((item) => item.ok !== false);
1371
- const clickCount = setupViewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.clicked_total) || 0), 0) + profileSetupReceiptTotal(setupViewports, "click") + profileSetupReceiptTotal(setupViewports, "click_count");
1372
- const clickSequenceCount = setupViewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.click_sequence_total) || 0), 0);
1373
- const clickFallbackTapKeys = /* @__PURE__ */ new Set();
1374
- [
1375
- ...setupViewports.flatMap((viewport) => setupReceiptArray(viewport, "clicked")),
1376
- ...evidenceViewports.flatMap((viewport) => setupReceiptArray(cliRecord(viewport) || {}, "setup_action_results"))
1377
- ].forEach((receipt2, index) => {
1378
- if (receipt2.ok === false || receipt2.fallback_to_tap !== true) return;
1379
- const action = cliString(receipt2.action);
1380
- if (action && action !== "click") return;
1381
- const ordinal = cliFiniteNumber(receipt2.ordinal);
1382
- const selector = cliString(receipt2.selector) || "";
1383
- const frameSelector = cliString(receipt2.frame_selector) || "";
1384
- clickFallbackTapKeys.add(`${ordinal === void 0 ? `idx:${index}` : `ord:${ordinal}`}:${frameSelector}:${selector}`);
1385
- });
1386
- const clickFallbackTapCount = clickFallbackTapKeys.size;
1387
- const tapUntilCount = profileSetupReceiptTotal(setupViewports, "tap_until");
1388
- const visibleUiActionCount = clickCount + profileSetupReceiptTotal(setupViewports, "tap") + tapUntilCount;
1389
- const visibleCleanupActionCount = profileVisibleCleanupActionCount(setupViewports);
1390
- const setupFailureCount = profileSetupFailureCount(setupViewports);
1391
- const setupObstructionCount = profileSetupObstructionCount(setupViewports);
1392
- const keyboardReceipts = setupViewports.flatMap((viewport) => setupReceiptArray(viewport, "keyboard")).filter((item) => item.ok !== false);
1393
- const keyboardReceiptDispatchCount = keyboardReceipts.length;
1394
- const keyboardActionDispatchCount = ["press", "key_down", "key_up", "keyboard_sequence"].reduce((sum, action) => sum + profileSetupActionCount(setupViewports, action), 0);
1395
- const keyboardDispatchCount = keyboardReceiptDispatchCount > 0 ? keyboardReceiptDispatchCount : keyboardActionDispatchCount;
1396
- const keyboardKeyMatches = (item, expected) => {
1397
- const key = (cliString(item.key) || cliString(item.code) || "").toLowerCase();
1398
- return key === expected || key.includes(expected);
1399
- };
1400
- const hasKeyboardKeyDownReceipt = keyboardReceipts.some((item) => cliString(item.action) === "key_down") || profileSetupActionCount(setupViewports, "key_down") > 0;
1401
- const hasKeyboardKeyUpReceipt = keyboardReceipts.some((item) => cliString(item.action) === "key_up") || profileSetupActionCount(setupViewports, "key_up") > 0;
1402
- const hasShiftKeyDownReceipt = keyboardReceipts.some((item) => cliString(item.action) === "key_down" && keyboardKeyMatches(item, "shift"));
1403
- const hasShiftKeyUpReceipt = keyboardReceipts.some((item) => cliString(item.action) === "key_up" && keyboardKeyMatches(item, "shift"));
1404
- const inputDispatchCount = profileSetupReceiptTotal(setupViewports, "drag") + profileSetupReceiptTotal(setupViewports, "tap") + tapUntilCount + clickCount + clickSequenceCount + profileSetupReceiptTotal(setupViewports, "press") + profileSetupReceiptTotal(setupViewports, "keyboard_sequence") + keyboardDispatchCount;
1405
- const canvasReceipts = setupViewports.flatMap((viewport) => setupReceiptArray(viewport, "canvas_signature"));
1406
- const hasCanvasChange = canvasReceipts.some((item) => item.ok !== false && item.changed === true);
1407
- const canvasSignatureHashes = canvasReceipts.filter((item) => item.ok !== false).map((item) => cliString(item.hash)).filter(Boolean);
1408
- const hasCanvasSignatureChange = hasCanvasChange || new Set(canvasSignatureHashes).size >= 2;
1409
- const hasNaturalInput = setupNaturalInputSummaryMarkdown(setupViewports).length > 0;
1410
- const hasStateContract = profileStateContractSummaryMarkdown(result).length > 0 || Boolean(cliRecord(metadata.declared_state_contract));
1411
- const hasInvalidStateReceipt = valueReceipts.some((item) => {
1412
- const state = setupReturnSummaryValue(item, ["state", "nextState"]);
1413
- return typeof state === "string" && state.toLowerCase().includes("invalid");
1414
- });
1415
- const hasErrorDetailReceipt = valueReceipts.some((item) => setupReturnSummaryValue(item, ["hasErrorDetail", "errorDetail", "error_detail"]) === true);
1416
- const hasGridEvidence = valueReceipts.some((item) => setupReturnSummaryValue(item, ["itemCount", "grid.width", "gridWidth", "visibleGridCount"]) !== void 0);
1417
- const hasVisibleControlReceipt = valueReceipts.some((item) => setupReturnSummaryValue(item, ["visibleButtonCount", "visibleControlCount"]) !== void 0 || setupReturnSummaryValue(item, ["buttonStillVisible", "controlStillVisible"]) === true);
1418
- const hasToolSelectionReceipt = valueReceipts.some((item) => setupReturnSummaryValue(item, ["rectangleChecked", "toolSelected", "toolChecked", "selected"]) === true);
1419
- const hasStateGrowthReceipt = valueReceipts.some((item) => {
1420
- const delta = cliFiniteNumber(setupReturnSummaryValue(item, ["delta", "countDelta", "itemDelta", "stateDelta"]));
1421
- if (delta !== void 0 && delta > 0) return true;
1422
- const before = cliFiniteNumber(setupReturnSummaryValue(item, ["before", "beforeCount", "previousCount"]));
1423
- const after = cliFiniteNumber(setupReturnSummaryValue(item, ["after", "afterCount", "itemCount", "count"]));
1424
- return before !== void 0 && after !== void 0 && after > before;
1425
- });
1426
- const stateGrowthMetricNames = [
1427
- "best",
1428
- "streak",
1429
- "score",
1430
- "level",
1431
- "progress",
1432
- "coins",
1433
- "totalCoins",
1434
- "totalEarned",
1435
- "saveTotalCoins",
1436
- "saveTotalClicks",
1437
- "perClick",
1438
- "perSecond",
1439
- "clickPowerLevel",
1440
- "autoClickerLevel"
1441
- ];
1442
- const hasPositiveStateGrowthMetric = valueReceipts.some((item) => stateGrowthMetricNames.some((name) => {
1443
- const storedTo = cliString(item.return_stored_to) || "";
1444
- const label = cliString(item.label) || "";
1445
- const path2 = cliString(item.path) || cliString(item.function_name) || "";
1446
- const slot = profileLowerSummaryValue(item, ["slot", "phase", "state"]);
1447
- const statusText = profileLowerSummaryValue(item, ["statusText", "status", "message"]);
1448
- const haystack = `${storedTo} ${label} ${path2} ${slot} ${statusText}`.toLowerCase();
1449
- const stateGrowthOutcome = haystack.includes("growth") || haystack.includes("success") || haystack.includes("after") || haystack.includes("add") || haystack.includes("upgrade") || haystack.includes("bought") || haystack.includes("perfect") || setupReturnSummaryValue(item, ["success", "passed"]) === true;
1450
- if (!stateGrowthOutcome) return false;
1451
- const value = cliFiniteNumber(setupReturnSummaryValue(item, [name]));
1452
- return value !== void 0 && value > 0;
1453
- }));
1454
- const hasReachability = profileReachabilitySummaryMarkdown(result).length > 0 || result.checks.some((check) => check.type === "selector_visible" && Boolean(cliRecord(check.evidence)?.selector));
1455
- const hasOverflowEvidence = result.checks.some((check) => check.type === "no_horizontal_overflow" || check.type === "no_mobile_horizontal_overflow" || check.type === "frame_no_horizontal_overflow") || evidenceViewports.some((viewport) => (cliFiniteNumber(viewport.overflow_px) || 0) > 0 || (cliFiniteNumber(viewport.bounds_overflow_px) || 0) > 0 || Boolean(viewport.overflow_offenders?.length));
1456
- const hasConsoleAccounting = profileHasCheck(result, ["no_console_warnings", "no_fatal_console_errors"]) || Boolean(result.evidence?.console || result.evidence?.page_errors);
1457
- const hasDomSummary = Boolean(result.artifacts.dom_summary || result.evidence?.dom_summary);
1458
- const hasProofJson = Boolean(result.artifacts.proof_json || result.version === "riddle-proof.profile-result.v1");
1459
- const hasRouteViewport = Boolean(result.route?.requested || result.route?.observed) && Boolean(evidenceViewports.length || result.route?.matched !== void 0);
1460
- const hasSetupReceipts = setupResultCount > 0 || Boolean(setupSummary);
1461
- const hasTextVisibility = profileHasPassedCheck(result, ["text_visible", "selector_text_visible", "selector_visible"]);
1462
- const hasTextAbsence = profileHasPassedCheck(result, ["text_absent", "selector_text_absent"]);
1463
- const measuredStateMetricNames = [
1464
- "delta",
1465
- "stateDelta",
1466
- "positionDelta",
1467
- "movementDelta",
1468
- "speedDelta",
1469
- "velocityDelta",
1470
- "distanceDelta",
1471
- "distanceGain",
1472
- "scoreDelta",
1473
- "scoreGain",
1474
- "energyDelta",
1475
- "energyDrop",
1476
- "energyRecovered",
1477
- "progressDelta",
1478
- "progressGain",
1479
- "stepDelta",
1480
- "deliveryDelta",
1481
- "deliveriesDelta",
1482
- "remainingDelta"
1483
- ];
1484
- const hasMeasuredStateMetric = valueReceipts.some((item) => measuredStateMetricNames.some((name) => {
1485
- const value = cliFiniteNumber(setupReturnSummaryValue(item, [name]));
1486
- return value !== void 0 && Math.abs(value) > 0;
1487
- }));
1488
- const measuredAbsoluteStateMetricNames = [
1489
- "coins",
1490
- "totalCoins",
1491
- "totalEarned",
1492
- "totalClicks",
1493
- "saveCoins",
1494
- "saveTotalCoins",
1495
- "saveTotalClicks",
1496
- "perClick",
1497
- "perSecond",
1498
- "measuredCps",
1499
- "clickPowerLevel",
1500
- "autoClickerLevel",
1501
- "level",
1502
- "score",
1503
- "count",
1504
- "itemCount",
1505
- "progress"
1506
- ];
1507
- const hasMeasuredAbsoluteStateChange = measuredAbsoluteStateMetricNames.some((name) => {
1508
- const values = valueReceipts.map((item) => cliFiniteNumber(setupReturnSummaryValue(item, [name]))).filter((value) => value !== void 0 && Number.isFinite(value));
1509
- if (values.length < 2) return false;
1510
- return Math.max(...values) > Math.min(...values);
1511
- });
1512
- const hasMeasuredStateChange = hasNaturalInput || hasCanvasChange || valueReceipts.some((item) => setupReturnSummaryValue(item, ["changed"]) === true || setupReturnSummaryValue(item, ["nonWhiteDelta", "darkDelta", "pixelDelta", "movementDelta"]) !== void 0) || hasMeasuredStateMetric || hasMeasuredAbsoluteStateChange;
1513
- const hasStorageStabilityReceipt = valueReceipts.some((item) => setupReturnSummaryValue(item, ["storageStable", "storage_stable", "saveStable", "save_stable", "persistenceStable", "persistence_stable"]) === true);
1514
- const hasPersistedReturnStateReceipt = valueReceipts.some((item) => setupReturnSummaryValue(item, ["persistedFromHome", "persisted_from_home", "persistenceRestored", "persistence_restored", "restoredFromStorage", "restored_from_storage"]) === true || setupReturnSummaryValue(item, ["persisted", "restored", "reloaded"]) === true && (setupReturnSummaryValue(item, ["saveCoins", "saveTotalCoins", "saveTotalClicks", "saveTotal", "level", "coins"]) !== void 0 || cliString(item.return_stored_to)?.toLowerCase().includes("return")));
1515
- const hasMovingPlayabilityReceipt = valueReceipts.some((item) => {
1516
- const started = setupReturnSummaryValue(item, ["started", "runStarted", "playStarted"]) === true;
1517
- const distance = cliFiniteNumber(setupReturnSummaryValue(item, ["distance", "distanceMeters", "travelDistance"]));
1518
- const speed = cliFiniteNumber(setupReturnSummaryValue(item, ["speed", "velocity"]));
1519
- return started && (distance !== void 0 && distance > 0 || speed !== void 0 && speed > 0);
1520
- });
1521
- const hasAcceptedPlayabilityInputReceipt = valueReceipts.some((item) => {
1522
- const accepted = setupReturnSummaryValue(item, ["acceptedInput", "inputAccepted", "steeringAccepted", "touchInputAccepted"]) === true;
1523
- const inputModality = (cliString(setupReturnSummaryValue(item, ["inputModality", "inputKind", "pointerType", "modality"])) || "").toLowerCase();
1524
- const distance = cliFiniteNumber(setupReturnSummaryValue(item, ["distance", "distanceMeters", "travelDistance"]));
1525
- const speed = cliFiniteNumber(setupReturnSummaryValue(item, ["speed", "velocity"]));
1526
- const moving = distance !== void 0 && distance > 0 || speed !== void 0 && speed > 0;
1527
- return accepted && Boolean(inputModality) && inputModality !== "none" && moving;
1528
- });
1529
- const hasRouteExitAffordanceReceipt = profileHasRouteExitAffordanceReceipt(valueReceipts);
1530
- const hasCleanupBoundaryAffordanceReceipt = profileHasCleanupBoundaryAffordanceReceipt(valueReceipts);
1531
- const hasOfflineAudioMetricsReceipt = profileHasOfflineAudioMetricsReceipt(valueReceipts);
1532
- const hasActiveRouteLocalProofReceipt = profileHasActiveRouteLocalProofReceipt(valueReceipts);
1533
- const hasTerminalLossReceipt = profileHasTerminalLossReceipt(valueReceipts);
1534
- const hasTerminalGameOverReceipt = profileHasTerminalGameOverReceipt(valueReceipts);
1535
- const hasTerminalSuccessReceipt = profileHasTerminalSuccessReceipt(valueReceipts);
1536
- const hasControlledFailureLaunchReceipt = profileHasControlledLaunchReceipt(valueReceipts, "failure");
1537
- const hasControlledSuccessLaunchReceipt = profileHasControlledLaunchReceipt(valueReceipts, "success");
1538
- const hasRouteContinuationReceipt = profileHasRouteContinuationReceipt(valueReceipts);
1539
- const hasRecoveredStateReceipt = profileHasRecoveredStateReceipt(valueReceipts);
1540
- const hasSequenceInputReceipt = profileHasSequenceInputReceipt(valueReceipts) && (inputDispatchCount > 0 || hasNaturalInput);
1541
- const hasRestartReadyReceipt = profileHasRestartReadyReceipt(valueReceipts);
1542
- const hasGeneratedOutputContract = profileMetadataHasGeneratedOutputContract(metadata);
1543
- const hasGeneratedOutputReceipt = profileHasGeneratedOutputReceipt(valueReceipts);
1544
- const failedCleanupInventoryReason = profileFailedCleanupInventoryReason(setupViewports);
1545
- const passedCleanupInventoryReason = profilePassedCleanupInventoryReason(setupViewports);
1546
- if (text.includes("artifact link") || text.includes("artifact path")) {
1547
- return profileReceiptSignalStatus(profileResultHasArtifact(result), "artifact references listed", "no artifact references found");
1548
- }
1549
- if (text.includes("proof json")) return profileReceiptSignalStatus(hasProofJson, "proof JSON artifact named", "proof JSON artifact missing");
1550
- if (text.includes("dom summary")) return profileReceiptSignalStatus(hasDomSummary, "DOM summary evidence present", "DOM summary evidence missing");
1551
- if (text.includes("console") || text.includes("warning") || text.includes("fatal") || text.includes("browser warning") || text.includes("graphics")) {
1552
- return profileReceiptSignalStatus(hasConsoleAccounting, "console checks or evidence present", "console accounting evidence missing");
1553
- }
1554
- if (text.includes("route") && text.includes("viewport")) {
1555
- if (text.includes("every target viewport") || text.includes("all target viewport") || text.includes("every") && text.includes("viewport")) {
1556
- return profileEveryRouteViewportStatus(result, setupSummary, setupViewports, evidenceViewports);
1557
- }
1558
- return profileReceiptSignalStatus(hasRouteViewport, "route and viewport evidence present", "route or viewport evidence missing");
1559
- }
1560
- if (text.includes("setup action")) {
1561
- return profileReceiptSignalStatus(hasSetupReceipts, "setup receipts present", "setup receipts missing");
1562
- }
1563
- if (text.includes("click") && text.includes("fallback") && text.includes("tap")) {
1564
- return profileReceiptSignalStatus(
1565
- clickFallbackTapCount > 0,
1566
- `click fallback tap evidence present (${clickFallbackTapCount})`,
1567
- "click fallback tap evidence missing"
1568
- );
1569
- }
1570
- if (text.includes("tap_until") || text.includes("tap until") || text.includes("tap-until")) {
1571
- return profileReceiptSignalStatus(
1572
- tapUntilCount > 0,
1573
- `tap_until receipt present (${tapUntilCount})`,
1574
- "tap_until receipt missing"
1575
- );
1576
- }
1577
- if (text.includes("active") && (text.includes("route-local") || text.includes("route local")) && (text.includes("proof helper") || text.includes("proof api") || text.includes("proof state") || text.includes("proof globals") || text.includes("playability state") || text.includes("runtime metric") || text.includes("runtime metrics") || text.includes("route metric") || text.includes("route metrics"))) {
1578
- return profileReceiptSignalStatus(
1579
- hasActiveRouteLocalProofReceipt,
1580
- "active route-local proof receipt present",
1581
- "active route-local proof receipt missing"
1582
- );
1583
- }
1584
- if (text.includes("declared state contract")) {
1585
- return profileReceiptSignalStatus(hasStateContract, "state contract metadata or receipts present", "state contract evidence missing");
1586
- }
1587
- if (text.includes("stale") || text.includes("absence")) {
1588
- const expectsCleanupInventory = text.includes("cleanup") || text.includes("post-cleanup") || text.includes("stale-state") || text.includes("stale state") || text.includes("inventory");
1589
- if (failedCleanupInventoryReason && expectsCleanupInventory) {
1590
- return { status: "failed", reason: `cleanup inventory failed: ${failedCleanupInventoryReason}` };
1591
- }
1592
- if (passedCleanupInventoryReason && expectsCleanupInventory) {
1593
- return { status: "present", reason: `cleanup inventory passed: ${passedCleanupInventoryReason}` };
1594
- }
1595
- return profileReceiptSignalStatus(hasTextAbsence, "absence check passed", "absence check missing");
1596
- }
1597
- if (text.includes("screenshot")) {
1598
- const needsBoundaryScreenshots = text.includes("each") || text.includes("before and after") || text.includes("state boundary") || text.includes("boundaries");
1599
- return profileReceiptSignalStatus(
1600
- needsBoundaryScreenshots ? screenshotCount >= 2 : screenshotCount > 0,
1601
- needsBoundaryScreenshots ? "multiple screenshots present" : "screenshot evidence present",
1602
- needsBoundaryScreenshots ? "multiple screenshots missing" : "screenshot evidence missing"
1603
- );
1604
- }
1605
- if (text.includes("generated-output") || text.includes("generated output") || text.includes("output-size") || text.includes("output size") || (text.includes("output") || text.includes("result")) && (text.includes("mutation") || text.includes("final"))) {
1606
- return profileReceiptSignalStatus(
1607
- hasGeneratedOutputContract && hasGeneratedOutputReceipt,
1608
- "generated-output mutation receipt present",
1609
- "generated-output mutation receipt missing"
1610
- );
1611
- }
1612
- if (text.includes("recovered") || text.includes("final state")) {
1613
- return profileReceiptSignalStatus(hasStateContract || hasTextVisibility, "final state receipt present", "final state receipt missing");
1614
- }
1615
- if (text.includes("error detail")) {
1616
- const hasRequiredState = !text.includes("invalid") || hasInvalidStateReceipt;
1617
- return profileReceiptSignalStatus(
1618
- hasRequiredState && hasErrorDetailReceipt,
1619
- "error-detail state receipt present",
1620
- "error-detail state receipt missing"
1621
- );
1622
- }
1623
- if (text.includes("invalid state")) {
1624
- return profileReceiptSignalStatus(hasStateContract || hasInvalidStateReceipt, "invalid-state receipt present", "invalid-state receipt missing");
1625
- }
1626
- if ((text.includes("loss") || text.includes("lost")) && text.includes("terminal")) {
1627
- return profileReceiptSignalStatus(
1628
- hasTerminalLossReceipt,
1629
- "terminal loss receipt present",
1630
- "terminal loss receipt missing"
1631
- );
1632
- }
1633
- if (text.includes("terminal") && (text.includes("game-over") || text.includes("game over") || text.includes("gameover") || text.includes("caught") || text.includes("catch"))) {
1634
- return profileReceiptSignalStatus(
1635
- hasTerminalGameOverReceipt,
1636
- "terminal game-over receipt present",
1637
- "terminal game-over receipt missing"
1638
- );
1639
- }
1640
- if (text.includes("success") && text.includes("terminal")) {
1641
- return profileReceiptSignalStatus(
1642
- hasTerminalSuccessReceipt,
1643
- "terminal success receipt present",
1644
- "terminal success receipt missing"
1645
- );
1646
- }
1647
- if (text.includes("controlled") && text.includes("launch") && (text.includes("failure") || text.includes("failed") || text.includes("miss"))) {
1648
- return profileReceiptSignalStatus(
1649
- hasControlledFailureLaunchReceipt,
1650
- "controlled failure launch receipt present",
1651
- "controlled failure launch receipt missing"
1652
- );
1653
- }
1654
- if (text.includes("controlled") && text.includes("launch") && text.includes("success")) {
1655
- return profileReceiptSignalStatus(
1656
- hasControlledSuccessLaunchReceipt,
1657
- "controlled success launch receipt present",
1658
- "controlled success launch receipt missing"
1659
- );
1660
- }
1661
- if (text.includes("recovery action") || text.includes("recover action") || text.includes("try fix") || (text.includes("retry") || text.includes("repair")) && text.includes("action")) {
1662
- return profileReceiptSignalStatus(
1663
- visibleUiActionCount > 0 && hasRecoveredStateReceipt,
1664
- "visible recovery-action receipt present",
1665
- "visible recovery-action receipt missing"
1666
- );
1667
- }
1668
- if (text.includes("route continuation") || text.includes("route-transition") || text.includes("route transition")) {
1669
- return profileReceiptSignalStatus(
1670
- hasRouteContinuationReceipt,
1671
- "route continuation receipt present",
1672
- "route continuation receipt missing"
1673
- );
1674
- }
1675
- if (text.includes("storage-stability") || text.includes("storage stability") || text.includes("storage-stable") || text.includes("storage stable") || (text.includes("storage") || text.includes("save data")) && text.includes("stable") || text.includes("passive income") && text.includes("unmounted")) {
1676
- return profileReceiptSignalStatus(
1677
- hasStorageStabilityReceipt,
1678
- "storage-stability receipt present",
1679
- "storage-stability receipt missing"
1680
- );
1681
- }
1682
- if (text.includes("persisted return-state") || text.includes("persisted return state") || text.includes("return-state") || text.includes("return state") || (text.includes("persisted") || text.includes("persistence")) && (text.includes("return") || text.includes("reload") || text.includes("restored"))) {
1683
- return profileReceiptSignalStatus(
1684
- hasPersistedReturnStateReceipt,
1685
- "persisted return-state receipt present",
1686
- "persisted return-state receipt missing"
1687
- );
1688
- }
1689
- if (text.includes("cleanup") && text.includes("action") && (text.includes("visible ui") || text.includes("visible"))) {
1690
- return profileReceiptSignalStatus(
1691
- visibleCleanupActionCount > 0,
1692
- `visible cleanup action receipt present (${visibleCleanupActionCount})`,
1693
- "visible cleanup action receipt missing"
1694
- );
1695
- }
1696
- if (text.includes("through visible ui") || text.includes("visible ui action") || text.includes("ui-routed") || text.includes("ui routed") || text.includes("visible") && text.includes("route") && text.includes("exit") && text.includes("action") || text.includes("visible") && text.includes("mode") && text.includes("exit") && text.includes("action")) {
1697
- return profileReceiptSignalStatus(
1698
- visibleUiActionCount > 0,
1699
- "visible UI action receipt present",
1700
- "visible UI action receipt missing"
1701
- );
1702
- }
1703
- if (text.includes("route-exit affordance") || text.includes("route exit affordance") || text.includes("navigation before cleanup") || text.includes("exit control")) {
1704
- return profileReceiptSignalStatus(
1705
- hasRouteExitAffordanceReceipt || hasStateContract || clickCount > 0,
1706
- "route-exit affordance receipt present",
1707
- "affordance receipt missing"
1708
- );
1709
- }
1710
- if (text.includes("cleanup") && (text.includes("affordance") || text.includes("control") || text.includes("boundary") || text.includes("inventory"))) {
1711
- return profileReceiptSignalStatus(
1712
- hasCleanupBoundaryAffordanceReceipt,
1713
- "visible cleanup affordance receipt present",
1714
- "visible cleanup affordance receipt missing"
1715
- );
1716
- }
1717
- if (text.includes("input") && (text.includes("sequence") || text.includes("short-long") || text.includes("short long") || text.includes("long-short") || text.includes("long long") || text.includes("long short"))) {
1718
- return profileReceiptSignalStatus(
1719
- hasSequenceInputReceipt,
1720
- "sequence input receipt present",
1721
- "sequence input receipt missing"
1722
- );
1723
- }
1724
- if (text.includes("restart") && (text.includes("receipt") || text.includes("ready") || text.includes("re-enabled") || text.includes("controls"))) {
1725
- return profileReceiptSignalStatus(
1726
- hasRestartReadyReceipt,
1727
- "restart-ready receipt present",
1728
- "restart-ready receipt missing"
1729
- );
1730
- }
1731
- if (text.includes("retry") || text.includes("repair") || text.includes("reset") || text.includes("affordance")) {
1732
- return profileReceiptSignalStatus(hasStateContract || clickCount > 0, "affordance or transition receipt present", "affordance receipt missing");
1733
- }
1734
- if (text.includes("failure") || text.includes("mutation")) {
1735
- return profileReceiptSignalStatus(hasStateContract || windowEvalCount > 0 || clickCount > 0, "failure or mutation receipt present", "failure or mutation receipt missing");
1736
- }
1737
- if (text.includes("initial") && (text.includes("visible") || text.includes("state"))) {
1738
- return profileReceiptSignalStatus(hasTextVisibility || screenshotCount > 0, "initial visible-state evidence present", "initial state evidence missing");
1739
- }
1740
- if (text.includes("state-growth") || text.includes("state growth") || text.includes("growth receipt") || text.includes("grid grows") || text.includes("state") && text.includes("after the click")) {
1741
- return profileReceiptSignalStatus(hasStateGrowthReceipt || hasPositiveStateGrowthMetric, "state-growth receipt present", "state-growth receipt missing");
1742
- }
1743
- if (text.includes("visible grid") || text.includes("control evidence") || text.includes("grid") && text.includes("control")) {
1744
- return profileReceiptSignalStatus(
1745
- hasGridEvidence && (hasVisibleControlReceipt || hasReachability),
1746
- "visible grid/control evidence present",
1747
- "visible grid/control evidence missing"
1748
- );
1749
- }
1750
- if (text.includes("tool") && text.includes("selected") || text.includes("rectangle tool")) {
1751
- return profileReceiptSignalStatus(hasToolSelectionReceipt, "tool-selection receipt present", "tool-selection receipt missing");
1752
- }
1753
- if (text.includes("canvas signature")) {
1754
- return profileReceiptSignalStatus(hasCanvasSignatureChange, "canvas signature change evidence present", "canvas signature evidence missing");
1755
- }
1756
- if (text.includes("selector count") || text.includes("visible count") || text.includes("control visibility") || text.includes("reachability gate") || text.includes("visible control")) {
1757
- return profileReceiptSignalStatus(hasReachability, "selector visibility or reachability evidence present", "reachability evidence missing");
1758
- }
1759
- if (text.includes("overflow") || text.includes("clipped") || text.includes("fit")) {
1760
- return profileReceiptSignalStatus(hasOverflowEvidence, "overflow evidence present", "overflow evidence missing");
1761
- }
1762
- if (text.includes("click receipt") || text.includes("obstruction receipt") || text.includes("state mutation")) {
1763
- return profileReceiptSignalStatus(clickCount > 0 || setupObstructionCount > 0, "click or obstruction receipt present", "click or obstruction receipt missing");
1764
- }
1765
- if (text.includes("target selector") || text.includes("target selector/text")) {
1766
- return profileReceiptSignalStatus(hasReachability || hasTextVisibility, "selector or text check evidence present", "selector/text evidence missing");
1767
- }
1768
- if (text.includes("intercepting element")) {
1769
- if (setupObstructionCount > 0) return { status: "present", reason: "obstruction receipt present" };
1770
- return setupFailureCount > 0 ? { status: "missing", reason: "setup failed without intercepting element evidence" } : { status: "manual", reason: "only applies when blocked" };
1771
- }
1772
- if (text.includes("before and after state")) {
1773
- return profileReceiptSignalStatus(
1774
- hasStateContract || valueReceipts.length >= 2 || screenshotCount >= 2,
1775
- "before/after state evidence present",
1776
- "before/after state evidence missing"
1777
- );
1778
- }
1779
- if (text.includes("input") && (text.includes("playability") || text.includes("moving") || text.includes("steering") || text.includes("real") || text.includes("natural"))) {
1780
- const needsAcceptedInput = text.includes("steering") || text.includes("accepted");
1781
- const hasInputDispatch = inputDispatchCount > 0 || hasNaturalInput;
1782
- const hasInputStateReceipt = needsAcceptedInput ? hasAcceptedPlayabilityInputReceipt : hasAcceptedPlayabilityInputReceipt || hasMovingPlayabilityReceipt;
1783
- return profileReceiptSignalStatus(
1784
- hasInputDispatch && hasInputStateReceipt,
1785
- needsAcceptedInput ? "accepted playability input receipt present" : "playability input receipt present",
1786
- needsAcceptedInput ? "accepted playability input receipt missing" : "playability input receipt missing"
1787
- );
1788
- }
1789
- if (text.includes("input dispatch") || text.includes("pointer") || text.includes("touch") || text.includes("key event") || text.includes("trusted-event")) {
1790
- if (text.includes("key_down") || text.includes("key down") || text.includes("key-up") || text.includes("key_up")) {
1791
- const hasSpecificKeyboardDispatch = text.includes("shift") ? hasShiftKeyDownReceipt && hasShiftKeyUpReceipt : hasKeyboardKeyDownReceipt && hasKeyboardKeyUpReceipt;
1792
- return profileReceiptSignalStatus(
1793
- hasSpecificKeyboardDispatch,
1794
- "keyboard key_down/key_up dispatch evidence present",
1795
- "keyboard key_down/key_up dispatch evidence missing"
1796
- );
1797
- }
1798
- return profileReceiptSignalStatus(inputDispatchCount > 0 || hasNaturalInput, "input dispatch evidence present", "input dispatch evidence missing");
1799
- }
1800
- if (text.includes("offline audio") || text.includes("audio") && text.includes("metric")) {
1801
- return profileReceiptSignalStatus(
1802
- hasOfflineAudioMetricsReceipt,
1803
- "offline audio metric receipt present",
1804
- "offline audio metric receipt missing"
1805
- );
1806
- }
1807
- if (text.includes("measured") || text.includes("state-change") || text.includes("pixel delta") || text.includes("movement receipt") || text.includes("canvas hash")) {
1808
- return profileReceiptSignalStatus(hasMeasuredStateChange, "measured-change evidence present", "measured-change evidence missing");
1809
- }
1810
- const semanticStateReason = profileSemanticStateReceiptReason(valueReceipts, text);
1811
- if (semanticStateReason) {
1812
- return { status: "present", reason: semanticStateReason };
1813
- }
1814
- return { status: "manual", reason: "semantic receipt requires audit review" };
1815
- }
1816
- function profilePackMetadataMarkdown(result) {
1817
- const metadata = cliRecord(result.metadata);
1818
- if (!metadata) return [];
1819
- const packId = cliString(metadata.pack_id);
1820
- const packPublicName = cliString(metadata.pack_public_name);
1821
- const requiredReceipts = profileMetadataStringArray(metadata.required_receipts);
1822
- if (!packId && !packPublicName && !requiredReceipts.length) return [];
1823
- const lines = [];
1824
- const packParts = [
1825
- packId ? markdownInlineCode(packId) : "",
1826
- packPublicName ? packPublicName : ""
1827
- ].filter(Boolean);
1828
- if (packParts.length) lines.push(`- pack: ${packParts.join(" - ")}`);
1829
- if (requiredReceipts.length) {
1830
- const receiptStatuses = requiredReceipts.map((receipt) => ({
1831
- receipt,
1832
- item: profilePackReceiptStatus(result, metadata, receipt)
1833
- }));
1834
- const missingReceipts = receiptStatuses.filter(({ item }) => item.status === "missing").map(({ receipt }) => receipt);
1835
- const failedReceipts = receiptStatuses.filter(({ item }) => item.status === "failed").map(({ receipt }) => receipt);
1836
- const manualCount = receiptStatuses.filter(({ item }) => item.status === "manual").length;
1837
- const presentCount = receiptStatuses.filter(({ item }) => item.status === "present").length;
1838
- const completenessParts = [
1839
- `${presentCount} present`,
1840
- manualCount ? `${manualCount} manual` : "",
1841
- missingReceipts.length ? `${missingReceipts.length} missing` : "",
1842
- failedReceipts.length ? `${failedReceipts.length} failed` : ""
1843
- ].filter(Boolean);
1844
- lines.push(`- pack completeness: ${missingReceipts.length || failedReceipts.length ? "incomplete" : "complete"} (${completenessParts.join(", ")})`);
1845
- if (missingReceipts.length) {
1846
- const listed = missingReceipts.slice(0, 5).map((receipt) => markdownInlineCode(receipt, 120)).join(", ");
1847
- lines.push(`- missing required receipts: ${listed}${missingReceipts.length > 5 ? `, ${missingReceipts.length - 5} more` : ""}`);
1848
- }
1849
- if (failedReceipts.length) {
1850
- const listed = failedReceipts.slice(0, 5).map((receipt) => markdownInlineCode(receipt, 120)).join(", ");
1851
- lines.push(`- failed required receipts: ${listed}${failedReceipts.length > 5 ? `, ${failedReceipts.length - 5} more` : ""}`);
1852
- }
1853
- lines.push(`- required receipts: ${requiredReceipts.length}`);
1854
- for (const { receipt, item } of receiptStatuses.slice(0, 20)) {
1855
- lines.push(` - ${item.status}: ${receipt} (${item.reason})`);
1856
- }
1857
- if (requiredReceipts.length > 20) lines.push(` - ${requiredReceipts.length - 20} additional required receipt(s) omitted.`);
1858
- }
1859
- return lines;
1860
- }
1861
- function markdownInlineCode(value, maxLength = 80) {
1862
- const normalized = value.replace(/\s+/g, " ").trim();
1863
- const clipped = normalized.length > maxLength ? `${normalized.slice(0, Math.max(0, maxLength - 3))}...` : normalized;
1864
- return `\`${clipped.replace(/`/g, "'")}\``;
1865
- }
1866
- function profileCheckTextTarget(evidence) {
1867
- const text = cliString(evidence.text);
1868
- if (text) return markdownInlineCode(text);
1869
- const pattern = cliString(evidence.pattern);
1870
- return pattern ? `pattern ${markdownInlineCode(pattern)}` : void 0;
1871
- }
1872
- function observeWithinMarkdownReceipt(evidence) {
1873
- const viewports = Array.isArray(evidence.viewports) ? evidence.viewports.map(cliRecord).filter((viewport) => Boolean(viewport)) : [];
1874
- if (!viewports.length) return void 0;
1875
- const receipts = viewports.slice(0, 4).map((viewport) => {
1876
- const name = cliString(viewport.viewport) || cliString(viewport.name) || "viewport";
1877
- const matched = viewport.matched === true ? "matched" : viewport.matched === false ? "missed" : "observed";
1878
- const elapsedMs = cliFiniteNumber(viewport.elapsed_ms);
1879
- const attempts = cliFiniteNumber(viewport.attempts);
1880
- const sample = cliString(viewport.sample);
1881
- return `${name} ${matched}${elapsedMs === void 0 ? "" : ` in ${elapsedMs}ms`}${attempts === void 0 ? "" : `, ${attempts} attempt${attempts === 1 ? "" : "s"}`}${sample ? `, sample ${markdownInlineCode(sample, 70)}` : ""}`;
1882
- });
1883
- if (viewports.length > receipts.length) receipts.push(`${viewports.length - receipts.length} more viewport${viewports.length - receipts.length === 1 ? "" : "s"}`);
1884
- return receipts.join("; ");
1885
- }
1886
- function profileCheckMarkdownTarget(check) {
1887
- const evidence = cliRecord(check.evidence);
1888
- if (!evidence) return void 0;
1889
- const selector = cliString(evidence.selector);
1890
- if (check.type === "route_loaded") {
1891
- const expectedPath = cliString(evidence.expected_path);
1892
- return expectedPath ? markdownInlineCode(expectedPath) : void 0;
1893
- }
1894
- if (check.type === "selector_visible" || check.type === "selector_absent") {
1895
- return selector ? markdownInlineCode(selector) : void 0;
1896
- }
1897
- if (check.type === "selector_count_at_least") {
1898
- const minCount = cliFiniteNumber(evidence.min_count);
1899
- return selector && minCount !== void 0 ? `${markdownInlineCode(selector)} >= ${minCount}` : void 0;
1900
- }
1901
- if (check.type === "selector_count_equals" || check.type === "selector_count_equal" || check.type === "selector_count_eq") {
1902
- const expectedCount = cliFiniteNumber(evidence.expected_count);
1903
- return selector && expectedCount !== void 0 ? `${markdownInlineCode(selector)} = ${expectedCount}` : void 0;
1904
- }
1905
- if (check.type === "selector_text_visible" || check.type === "selector_text_absent") {
1906
- const textTarget = profileCheckTextTarget(evidence);
1907
- const verb = check.type === "selector_text_absent" ? "does not contain" : "contains";
1908
- if (selector && textTarget) return `${markdownInlineCode(selector)} ${verb} ${textTarget}`;
1909
- if (textTarget && check.type === "selector_text_absent") return `${verb} ${textTarget}`;
1910
- return selector ? markdownInlineCode(selector) : textTarget;
1911
- }
1912
- if (check.type === "selector_text_order") {
1913
- return selector ? `${markdownInlineCode(selector)} text order` : void 0;
1914
- }
1915
- if (check.type === "observe_within") {
1916
- const textTarget = profileCheckTextTarget(evidence);
1917
- const timeoutMs = cliFiniteNumber(evidence.timeout_ms);
1918
- const withinLabel = timeoutMs === void 0 ? "within timeout" : `within ${timeoutMs}ms`;
1919
- const receipt = observeWithinMarkdownReceipt(evidence);
1920
- const base = selector && textTarget ? `${markdownInlineCode(selector)} observes ${textTarget} ${withinLabel}` : selector ? `${markdownInlineCode(selector)} visible ${withinLabel}` : textTarget ? `${textTarget} ${withinLabel}` : withinLabel;
1921
- return receipt ? `${base}; ${receipt}` : base;
1922
- }
1923
- if (check.type === "text_visible" || check.type === "text_absent") {
1924
- return profileCheckTextTarget(evidence);
1925
- }
1926
- if (check.type === "frame_text_visible") {
1927
- const textTarget = profileCheckTextTarget(evidence);
1928
- if (selector && textTarget) return `${markdownInlineCode(selector)} contains ${textTarget}`;
1929
- return selector ? markdownInlineCode(selector) : textTarget;
1930
- }
1931
- if (check.type === "frame_url_equals") {
1932
- const expectedUrl = cliString(evidence.expected_url);
1933
- if (selector && expectedUrl) return `${markdownInlineCode(selector)} = ${markdownInlineCode(expectedUrl)}`;
1934
- return selector ? markdownInlineCode(selector) : expectedUrl ? markdownInlineCode(expectedUrl) : void 0;
1935
- }
1936
- if (check.type === "frame_url_matches") {
1937
- const pattern = cliString(evidence.pattern);
1938
- if (selector && pattern) return `${markdownInlineCode(selector)} matches ${markdownInlineCode(pattern)}`;
1939
- return selector ? markdownInlineCode(selector) : pattern ? `pattern ${markdownInlineCode(pattern)}` : void 0;
1940
- }
1941
- if (check.type === "frame_no_horizontal_overflow") {
1942
- const maxOverflow = cliFiniteNumber(evidence.max_overflow_px);
1943
- if (selector && maxOverflow !== void 0) return `${markdownInlineCode(selector)} <= ${maxOverflow}px`;
1944
- return selector ? markdownInlineCode(selector) : maxOverflow !== void 0 ? `<= ${maxOverflow}px` : void 0;
1945
- }
1946
- if (check.type === "http_status") {
1947
- const url = cliString(evidence.url);
1948
- const method = cliString(evidence.method);
1949
- const statuses = Array.isArray(evidence.allowed_statuses) ? evidence.allowed_statuses.map((status) => cliString(status) || String(status)).filter(Boolean) : [];
1950
- const target = [method, url ? markdownInlineCode(url) : ""].filter(Boolean).join(" ");
1951
- return statuses.length ? `${target} -> ${statuses.join("/")}` : target || void 0;
1952
- }
1953
- if (check.type === "link_status" || check.type === "artifact_link_status") {
1954
- const expectedCount = cliFiniteNumber(evidence.expected_count);
1955
- const minCount = cliFiniteNumber(evidence.min_count);
1956
- const minBytes = cliFiniteNumber(evidence.min_bytes);
1957
- const parts = [];
1958
- if (expectedCount !== void 0) parts.push(`probed links = ${expectedCount}`);
1959
- else if (minCount !== void 0) parts.push(`probed links >= ${minCount}`);
1960
- if (minBytes !== void 0) parts.push(`bytes >= ${minBytes}`);
1961
- if (selector && parts.length) return `${markdownInlineCode(selector)} ${parts.join(", ")}`;
1962
- return selector ? markdownInlineCode(selector) : parts.join(", ") || void 0;
1963
- }
1964
- if (check.type === "no_horizontal_overflow" || check.type === "no_mobile_horizontal_overflow") {
1965
- const maxOverflow = cliFiniteNumber(evidence.max_overflow_px);
1966
- return maxOverflow !== void 0 ? `<= ${maxOverflow}px` : void 0;
1967
- }
1968
- if (check.type === "no_fatal_console_errors") {
1969
- const fatalCount = cliFiniteNumber(evidence.console_fatal_count) ?? cliFiniteNumber(evidence.fatal_error_count) ?? 0;
1970
- const totalConsoleCount = cliFiniteNumber(evidence.total_console_fatal_count);
1971
- const allowedConsoleCount = cliFiniteNumber(evidence.allowed_console_fatal_count);
1972
- const parts = [`${fatalCount} unallowed fatal error${fatalCount === 1 ? "" : "s"}`];
1973
- if (totalConsoleCount !== void 0 && allowedConsoleCount !== void 0) {
1974
- parts.push(`${allowedConsoleCount}/${totalConsoleCount} console fatal allowed`);
1975
- }
1976
- return parts.join(", ");
1977
- }
1978
- if (check.type === "no_console_warnings") {
1979
- const warningCount = cliFiniteNumber(evidence.console_warning_count) ?? 0;
1980
- const totalConsoleCount = cliFiniteNumber(evidence.total_console_warning_count);
1981
- const allowedConsoleCount = cliFiniteNumber(evidence.allowed_console_warning_count);
1982
- const allowedTextCount = Array.isArray(evidence.allowed_console_texts) ? evidence.allowed_console_texts.filter((value) => typeof value === "string" && value.trim()).length : 0;
1983
- const allowedPatternCount = Array.isArray(evidence.allowed_console_patterns) ? evidence.allowed_console_patterns.filter((value) => typeof value === "string" && value.trim()).length : 0;
1984
- const parts = [`${warningCount} unallowed warning${warningCount === 1 ? "" : "s"}`];
1985
- if (totalConsoleCount !== void 0 && allowedConsoleCount !== void 0) {
1986
- parts.push(`${allowedConsoleCount}/${totalConsoleCount} warning${totalConsoleCount === 1 ? "" : "s"} allowed`);
1987
- }
1988
- if (allowedTextCount || allowedPatternCount) {
1989
- parts.push(`allowlist ${allowedTextCount} text${allowedTextCount === 1 ? "" : "s"}, ${allowedPatternCount} pattern${allowedPatternCount === 1 ? "" : "s"}`);
1990
- }
1991
- return parts.join(", ");
1992
- }
1993
- return void 0;
1994
- }
1995
- function profileCheckMarkdownLabel(check) {
1996
- const label = check.label || check.type;
1997
- const target = profileCheckMarkdownTarget(check);
1998
- return target ? `${label} (${target})` : label;
1999
- }
2000
- function cliRecord(value) {
2001
- return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
2002
- }
2003
- function cliFiniteNumber(value) {
2004
- return typeof value === "number" && Number.isFinite(value) ? value : void 0;
2005
- }
2006
- function cliString(value) {
2007
- return typeof value === "string" && value.trim() ? value.trim() : void 0;
2008
- }
2009
- function cliValueLabel(value) {
2010
- if (value === void 0) return void 0;
2011
- if (typeof value === "string") return value.trim() || void 0;
2012
- try {
2013
- const serialized = JSON.stringify(value);
2014
- return typeof serialized === "string" && serialized ? serialized : String(value);
2015
- } catch {
2016
- return String(value);
2017
- }
2018
- }
2019
- function cliReturnSummaryLabel(value) {
2020
- if (!Array.isArray(value)) return void 0;
2021
- const parts = value.map(cliRecord).filter((item) => Boolean(item)).map((item) => {
2022
- const label = cliString(item.label) || cliString(item.path) || "value";
2023
- const observed = item.exists === false ? "missing" : cliValueLabel(item.value);
2024
- return `${label}=${observed ?? "null"}`;
2025
- }).filter(Boolean);
2026
- return parts.length ? parts.join(", ") : void 0;
2027
- }
2028
- function setupFailureObstructionSnippet(reason) {
2029
- if (!reason || !reason.includes("intercepts pointer events")) return void 0;
2030
- const line = reason.split(/\r?\n/).find((item) => item.includes("intercepts pointer events"));
2031
- const match = line?.match(/-\s+(.+?)\s+intercepts pointer events/);
2032
- const snippet = match?.[1]?.replace(/\s+/g, " ").trim();
2033
- return snippet || void 0;
2034
- }
2035
- function setupReceiptArray(viewport, key) {
2036
- return Array.isArray(viewport[key]) ? viewport[key].map(cliRecord).filter((item) => Boolean(item)) : [];
2037
- }
2038
- function setupReturnSummaryValue(receipt, names) {
2039
- for (const name of names) {
2040
- if (receipt[name] !== void 0) return receipt[name];
2041
- }
2042
- return setupReturnedSummaryValue(receipt, names);
2043
- }
2044
- function setupReturnedSummaryValue(receipt, names) {
2045
- const returned = cliRecord(receipt.returned);
2046
- for (const name of names) {
2047
- if (returned?.[name] !== void 0) return returned[name];
2048
- }
2049
- const summaries = Array.isArray(receipt.return_summary) ? receipt.return_summary.map(cliRecord).filter((item) => Boolean(item)) : [];
2050
- for (const item of summaries) {
2051
- const label = cliString(item.label);
2052
- const path2 = cliString(item.path);
2053
- if (names.some((name) => label === name || path2 === name)) return item.value;
2054
- }
2055
- return void 0;
2056
- }
2057
- function setupMetricPart(receipts, label, names = [label]) {
2058
- for (const receipt of receipts) {
2059
- const value = setupReturnSummaryValue(receipt, names);
2060
- const valueLabel = cliValueLabel(value);
2061
- if (valueLabel !== void 0) return `${label}=${valueLabel}`;
2062
- }
2063
- return void 0;
2064
- }
2065
- function setupInputReceiptLabel(kind, receipt) {
2066
- const selector = cliString(receipt.selector);
2067
- const pointerType = cliString(receipt.pointer_type);
2068
- const inputDispatch = cliString(receipt.input_dispatch);
2069
- const key = cliString(receipt.key);
2070
- return [
2071
- kind,
2072
- selector ? markdownInlineCode(selector) : "",
2073
- pointerType ? markdownInlineCode(pointerType) : "",
2074
- key ? markdownInlineCode(key) : "",
2075
- inputDispatch ? `via ${markdownInlineCode(inputDispatch)}` : ""
2076
- ].filter(Boolean).join(" ");
2077
- }
2078
- function setupCanvasHashChangeLabel(receipts) {
2079
- const changed = receipts.find((receipt) => cliString(receipt.previous_hash) && cliString(receipt.hash) && receipt.changed === true);
2080
- if (changed) return `${markdownInlineCode(cliString(changed.previous_hash) || "")} -> ${markdownInlineCode(cliString(changed.hash) || "")}`;
2081
- const hashes = receipts.map((receipt) => cliString(receipt.hash)).filter((hash) => Boolean(hash));
2082
- const first = hashes[0];
2083
- const last = [...hashes].reverse().find((hash) => hash !== first);
2084
- return first && last ? `${markdownInlineCode(first)} -> ${markdownInlineCode(last)}` : void 0;
2085
- }
2086
- function setupNaturalInputSummaryMarkdown(viewports) {
2087
- const lines = [];
2088
- for (const viewport of viewports.slice(0, 8)) {
2089
- const name = cliString(viewport.name) || "viewport";
2090
- const inputReceipts = [
2091
- ...setupReceiptArray(viewport, "drag").map((receipt) => ({ kind: "drag", receipt })),
2092
- ...setupReceiptArray(viewport, "tap").map((receipt) => ({ kind: "tap", receipt })),
2093
- ...setupReceiptArray(viewport, "tap_until").map((receipt) => ({ kind: "tap_until", receipt })),
2094
- ...setupReceiptArray(viewport, "press").map((receipt) => ({ kind: "press", receipt }))
2095
- ].filter(({ receipt }) => receipt.ok !== false);
2096
- if (!inputReceipts.length) continue;
2097
- const valueReceipts = [
2098
- ...setupReceiptArray(viewport, "window_eval"),
2099
- ...setupReceiptArray(viewport, "window_call")
2100
- ].filter((receipt) => receipt.ok !== false);
2101
- const canvasReceipts = setupReceiptArray(viewport, "canvas_signature").filter((receipt) => receipt.ok !== false);
2102
- const eventParts = [
2103
- setupMetricPart(valueReceipts, "pointerDowns"),
2104
- setupMetricPart(valueReceipts, "pointerMoves"),
2105
- setupMetricPart(valueReceipts, "pointerUps"),
2106
- setupMetricPart(valueReceipts, "trustedEvents"),
2107
- setupMetricPart(valueReceipts, "eventCount")
2108
- ].filter((part) => Boolean(part));
2109
- const pixelParts = [
2110
- setupMetricPart(valueReceipts, "nonWhiteDelta"),
2111
- setupMetricPart(valueReceipts, "darkDelta")
2112
- ].filter((part) => Boolean(part));
2113
- const hashChange = setupCanvasHashChangeLabel(canvasReceipts);
2114
- if (!eventParts.length && !pixelParts.length && !hashChange) continue;
2115
- const inputText = inputReceipts.slice(0, 3).map(({ kind, receipt }) => setupInputReceiptLabel(kind, receipt)).join(", ");
2116
- const parts = [
2117
- inputText,
2118
- eventParts.length ? `events ${eventParts.join(", ")}` : "",
2119
- pixelParts.length ? `pixel deltas ${pixelParts.join(", ")}` : "",
2120
- hashChange ? `canvas hash ${hashChange}` : ""
2121
- ].filter(Boolean);
2122
- lines.push(`- natural input ${name}: ${parts.join("; ")}`);
2123
- }
2124
- return lines;
2125
- }
2126
- function reachabilityFailureReason(reason) {
2127
- if (!reason) return void 0;
2128
- const noVisibleMatch = /No visible match for selector [\s\S]*?:\s*([^\n]+)/.exec(reason);
2129
- if (noVisibleMatch?.[1]) return noVisibleMatch[1].trim().slice(0, 120);
2130
- if (/no_visible_match/.test(reason)) return "no_visible_match";
2131
- if (/not visible/i.test(reason)) return "not_visible";
2132
- return void 0;
2133
- }
2134
- function viewportTopBoundsOverflowPx(viewport) {
2135
- const direct = cliFiniteNumber(viewport.bounds_overflow_px);
2136
- if (direct !== void 0 && direct > 0) return direct;
2137
- const offenders = Array.isArray(viewport.overflow_offenders) ? viewport.overflow_offenders.map(cliRecord).filter((item) => Boolean(item)) : [];
2138
- for (const offender of offenders) {
2139
- const overflow = cliFiniteNumber(offender.bounds_overflow_px) ?? cliFiniteNumber(offender.overflow_px) ?? cliFiniteNumber(offender.overflow);
2140
- if (overflow !== void 0 && overflow > 0) return overflow;
2141
- }
2142
- const scrollOverflow = cliFiniteNumber(viewport.overflow_px);
2143
- return scrollOverflow !== void 0 && scrollOverflow > 0 ? scrollOverflow : void 0;
2144
- }
2145
- function profileReachabilitySummaryMarkdown(result) {
2146
- const evidenceViewports = Array.isArray(result.evidence?.viewports) ? result.evidence.viewports.map((viewport) => cliRecord(viewport)).filter((viewport) => Boolean(viewport)) : [];
2147
- if (!evidenceViewports.length) return [];
2148
- const evidenceByName = /* @__PURE__ */ new Map();
2149
- for (const viewport of evidenceViewports) {
2150
- const name = cliString(viewport.name);
2151
- if (name) evidenceByName.set(name, viewport);
2152
- }
2153
- const receipts = [];
2154
- const seen = /* @__PURE__ */ new Set();
2155
- const addReceipt = (viewportName, selector, reason) => {
2156
- const viewport = evidenceByName.get(viewportName);
2157
- if (!viewport) return;
2158
- const selectors = cliRecord(viewport.selectors);
2159
- const selectorEvidence = cliRecord(selectors?.[selector]);
2160
- const count = cliFiniteNumber(selectorEvidence?.count);
2161
- const visibleCount = cliFiniteNumber(selectorEvidence?.visible_count);
2162
- if (count === void 0 || count <= 0 || visibleCount === void 0 || visibleCount > 0) return;
2163
- const key = `${viewportName}\0${selector}`;
2164
- if (seen.has(key)) return;
2165
- seen.add(key);
2166
- const reasonText = reason || "no_visible_match";
2167
- const boundsOverflow = viewportTopBoundsOverflowPx(viewport);
2168
- receipts.push(`- reachability ${viewportName}: ${markdownInlineCode(selector, 120)} exists ${count}, visible ${visibleCount}, reason ${markdownInlineCode(reasonText, 80)}${boundsOverflow === void 0 ? "" : `, top bounds overflow ${boundsOverflow}px`}`);
2169
- };
2170
- const setupCheck = result.checks.find((check) => check.type === "setup_actions_succeeded");
2171
- const setupSummary = cliRecord(setupCheck?.evidence?.setup_summary);
2172
- const setupViewports = Array.isArray(setupSummary?.viewports) ? setupSummary.viewports.map(cliRecord).filter((viewport) => Boolean(viewport)) : [];
2173
- for (const viewport of setupViewports) {
2174
- const viewportName = cliString(viewport.name) || "viewport";
2175
- const failed = [
2176
- ...Array.isArray(viewport.failed) ? viewport.failed : [],
2177
- ...Array.isArray(viewport.optional_failed) ? viewport.optional_failed : []
2178
- ].map(cliRecord).filter((failure) => Boolean(failure));
2179
- for (const failure of failed) {
2180
- const selector = cliString(failure.selector);
2181
- const reason = reachabilityFailureReason(cliString(failure.reason));
2182
- if (selector && reason) addReceipt(viewportName, selector, reason);
2183
- }
2184
- }
2185
- for (const check of result.checks) {
2186
- if (check.type !== "selector_visible" || check.status !== "failed") continue;
2187
- const evidence = cliRecord(check.evidence);
2188
- const selector = cliString(evidence?.selector);
2189
- if (!selector) continue;
2190
- for (const viewport of evidenceViewports) {
2191
- const viewportName = cliString(viewport.name) || "viewport";
2192
- addReceipt(viewportName, selector, "no_visible_match");
2193
- }
2194
- }
2195
- if (receipts.length > 8) {
2196
- return [...receipts.slice(0, 8), `- ${receipts.length - 8} additional reachability receipt(s) omitted.`];
2197
- }
2198
- return receipts;
2199
- }
2200
- function stateContractReceiptName(receipt, fallbackIndex) {
2201
- const storedTo = cliString(receipt.return_stored_to);
2202
- if (!storedTo) return `receipt-${fallbackIndex + 1}`;
2203
- const parts = storedTo.split(".").map((part) => part.trim()).filter(Boolean);
2204
- return parts[parts.length - 1] || storedTo;
2205
- }
2206
- function stateContractReceiptValue(receipt) {
2207
- const value = setupReturnSummaryValue(receipt, [
2208
- "state",
2209
- "nextState",
2210
- "terminalState",
2211
- "finalState",
2212
- "status",
2213
- "phase"
2214
- ]);
2215
- return cliValueLabel(value);
2216
- }
2217
- function stateContractSignalParts(receipts) {
2218
- const names = [
2219
- "hasValidate",
2220
- "hasTryFix",
2221
- "hasErrorDetail",
2222
- "hasValid",
2223
- "hasInvalid",
2224
- "invalidGone",
2225
- "staleGone",
2226
- "staleCopyGone",
2227
- "repairedTrailingCommaGone",
2228
- "hasSuccess",
2229
- "hasFailure",
2230
- "hasRetry",
2231
- "hasError",
2232
- "success",
2233
- "recovered"
2234
- ];
2235
- const seen = /* @__PURE__ */ new Set();
2236
- const parts = [];
2237
- for (const receipt of receipts) {
2238
- for (const name of names) {
2239
- const value = setupReturnSummaryValue(receipt, [name]);
2240
- if (value === void 0) continue;
2241
- const label = cliValueLabel(value);
2242
- if (label === void 0) continue;
2243
- const part = `${name}=${label}`;
2244
- if (seen.has(part)) continue;
2245
- seen.add(part);
2246
- parts.push(part);
2247
- if (parts.length >= 8) return parts;
2248
- }
2249
- }
2250
- return parts;
2251
- }
2252
- function profileStateContractSummaryMarkdown(result) {
2253
- const setupCheck = result.checks.find((check) => check.type === "setup_actions_succeeded");
2254
- const setupSummary = cliRecord(setupCheck?.evidence?.setup_summary);
2255
- const viewports = Array.isArray(setupSummary?.viewports) ? setupSummary.viewports.map(cliRecord).filter((viewport) => Boolean(viewport)) : [];
2256
- const lines = [];
2257
- for (const viewport of viewports.slice(0, 8)) {
2258
- const name = cliString(viewport.name) || "viewport";
2259
- const receipts = [
2260
- ...setupReceiptArray(viewport, "window_eval"),
2261
- ...setupReceiptArray(viewport, "window_call"),
2262
- ...setupReceiptArray(viewport, "window_call_until")
2263
- ].filter((receipt) => receipt.ok !== false);
2264
- const states = receipts.map((receipt, index) => ({
2265
- name: stateContractReceiptName(receipt, index),
2266
- state: stateContractReceiptValue(receipt)
2267
- })).filter((receipt) => Boolean(receipt.state));
2268
- if (states.length < 2) continue;
2269
- const stateChain = states.slice(0, 6).map((receipt) => `${markdownInlineCode(receipt.name, 60)}=${markdownInlineCode(receipt.state, 80)}`).join(" -> ");
2270
- const omitted = states.length > 6 ? ` (+${states.length - 6} more)` : "";
2271
- const signals = stateContractSignalParts(receipts);
2272
- lines.push(`- state contract ${name}: ${stateChain}${omitted}${signals.length ? `; signals ${signals.map((part) => markdownInlineCode(part, 80)).join(", ")}` : ""}`);
2273
- }
2274
- return lines;
2275
- }
2276
- function sideCaveatAllowlistPart(evidence, totalKey, allowedKey) {
2277
- const total = cliFiniteNumber(evidence[totalKey]);
2278
- const allowed = cliFiniteNumber(evidence[allowedKey]);
2279
- if (total === void 0 || allowed === void 0 || allowed <= 0) return void 0;
2280
- return `${allowed}/${total} allowed`;
2281
- }
2282
- function sideCaveatAllowlistCounts(evidence) {
2283
- const textCount = Array.isArray(evidence.allowed_console_texts) ? evidence.allowed_console_texts.filter((value) => typeof value === "string" && value.trim()).length : 0;
2284
- const patternCount = Array.isArray(evidence.allowed_console_patterns) ? evidence.allowed_console_patterns.filter((value) => typeof value === "string" && value.trim()).length : 0;
2285
- return textCount || patternCount ? `allowlist ${textCount} text${textCount === 1 ? "" : "s"}, ${patternCount} pattern${patternCount === 1 ? "" : "s"}` : void 0;
2286
- }
2287
- function overflowCheckFailed(result) {
2288
- return result.checks.some((check) => check.status === "failed" && (check.type === "no_horizontal_overflow" || check.type === "no_mobile_horizontal_overflow" || check.type === "frame_no_horizontal_overflow"));
2289
- }
2290
- function sideCaveatOverflowLine(viewport) {
2291
- const name = cliString(viewport.name) || "viewport";
2292
- const scrollOverflow = cliFiniteNumber(viewport.overflow_px);
2293
- const boundsOverflow = cliFiniteNumber(viewport.bounds_overflow_px);
2294
- if ((scrollOverflow === void 0 || scrollOverflow <= 0) && (boundsOverflow === void 0 || boundsOverflow <= 0)) return void 0;
2295
- const parts = [
2296
- scrollOverflow !== void 0 && scrollOverflow > 0 ? `scroll overflow ${scrollOverflow}px` : "",
2297
- boundsOverflow !== void 0 && boundsOverflow > 0 ? `bounds overflow ${boundsOverflow}px` : ""
2298
- ].filter(Boolean);
2299
- const offenders = Array.isArray(viewport.overflow_offenders) ? viewport.overflow_offenders.map(cliRecord).filter((item) => Boolean(item)) : [];
2300
- const offender = offenders.find((item) => {
2301
- const overflow = cliFiniteNumber(item.bounds_overflow_px) ?? cliFiniteNumber(item.overflow_px) ?? cliFiniteNumber(item.overflow);
2302
- return overflow !== void 0 && overflow > 0;
2303
- });
2304
- const offenderSelector = cliString(offender?.selector);
2305
- const offenderOverflow = offender ? cliFiniteNumber(offender.bounds_overflow_px) ?? cliFiniteNumber(offender.overflow_px) ?? cliFiniteNumber(offender.overflow) : void 0;
2306
- return `- side caveat layout ${name}: ${parts.join(", ")}${offenderSelector && offenderOverflow !== void 0 ? `; top offender ${markdownInlineCode(offenderSelector, 100)} ${offenderOverflow}px` : ""}`;
2307
- }
2308
- function profileSideCaveatSummaryMarkdown(result) {
2309
- const lines = [];
2310
- for (const check of result.checks) {
2311
- if (check.status !== "passed") continue;
2312
- const evidence = cliRecord(check.evidence);
2313
- if (!evidence) continue;
2314
- if (check.type === "no_console_warnings") {
2315
- const allowed = sideCaveatAllowlistPart(evidence, "total_console_warning_count", "allowed_console_warning_count");
2316
- if (allowed) {
2317
- const allowlist = sideCaveatAllowlistCounts(evidence);
2318
- lines.push(`- side caveat console warnings: ${allowed}${allowlist ? `; ${allowlist}` : ""}`);
2319
- }
2320
- }
2321
- if (check.type === "no_fatal_console_errors") {
2322
- const consoleAllowed = sideCaveatAllowlistPart(evidence, "total_console_fatal_count", "allowed_console_fatal_count");
2323
- const pageAllowed = sideCaveatAllowlistPart(evidence, "total_page_error_count", "allowed_page_error_count");
2324
- const parts = [
2325
- consoleAllowed ? `console fatal ${consoleAllowed}` : "",
2326
- pageAllowed ? `page errors ${pageAllowed}` : "",
2327
- sideCaveatAllowlistCounts(evidence)
2328
- ].filter(Boolean);
2329
- if (parts.length) lines.push(`- side caveat fatal errors: ${parts.join("; ")}`);
2330
- }
2331
- }
2332
- if (!overflowCheckFailed(result) && Array.isArray(result.evidence?.viewports)) {
2333
- for (const viewport of result.evidence.viewports.slice(0, 8)) {
2334
- const line = sideCaveatOverflowLine(cliRecord(viewport) || {});
2335
- if (line) lines.push(line);
2336
- }
2337
- if (result.evidence.viewports.length > 8) lines.push(`- ${result.evidence.viewports.length - 8} additional viewport side caveat(s) omitted.`);
2338
- }
2339
- return lines.slice(0, 12);
2340
- }
2341
- function balancedSetupReceiptDetails(groups, limit) {
2342
- if (limit <= 0) return [];
2343
- const total = groups.reduce((sum, group) => sum + group.length, 0);
2344
- if (total <= limit) return groups.flat();
2345
- const selected = [];
2346
- const selectedKeys = /* @__PURE__ */ new Set();
2347
- const indexes = new Array(groups.length).fill(0);
2348
- const nonEmptyIndexes = groups.map((group, index) => group.length ? index : -1).filter((index) => index >= 0);
2349
- const pushReceipt = (groupIndex, itemIndex, advance = true) => {
2350
- const receipt = groups[groupIndex][itemIndex];
2351
- if (!receipt) return false;
2352
- const key = `${groupIndex}:${itemIndex}`;
2353
- if (selectedKeys.has(key)) return false;
2354
- selected.push(receipt);
2355
- selectedKeys.add(key);
2356
- if (advance) indexes[groupIndex] = Math.max(indexes[groupIndex], itemIndex + 1);
2357
- return true;
2358
- };
2359
- for (const index of nonEmptyIndexes) {
2360
- if (selected.length >= limit) return selected;
2361
- pushReceipt(index, 0);
2362
- }
2363
- for (const index of nonEmptyIndexes) {
2364
- if (selected.length >= limit) return selected;
2365
- const lastIndex = groups[index].length - 1;
2366
- if (lastIndex > 0) pushReceipt(index, lastIndex, false);
2367
- }
2368
- while (selected.length < limit) {
2369
- let progressed = false;
2370
- for (const index of nonEmptyIndexes) {
2371
- const nextIndex = indexes[index];
2372
- if (nextIndex >= groups[index].length) continue;
2373
- progressed = pushReceipt(index, nextIndex) || progressed;
2374
- if (selected.length >= limit) break;
2375
- }
2376
- if (!progressed) break;
2377
- }
2378
- return selected;
2379
- }
2380
- function cliStringArray(value) {
2381
- return Array.isArray(value) ? value.filter((entry) => typeof entry === "string" && Boolean(entry.trim())) : [];
2382
- }
2383
- function cliRouteInventoryRoutes(value) {
2384
- if (!Array.isArray(value)) return [];
2385
- return value.map((entry) => {
2386
- if (typeof entry === "string") {
2387
- const pathValue2 = entry.trim();
2388
- return pathValue2 ? { path: pathValue2 } : void 0;
2389
- }
2390
- const route = cliRecord(entry);
2391
- if (!route) return void 0;
2392
- const pathValue = cliString(route.path);
2393
- if (!pathValue) return void 0;
2394
- const nameValue = cliString(route.name);
2395
- return nameValue ? { name: nameValue, path: pathValue } : { path: pathValue };
2396
- }).filter((route) => Boolean(route));
2397
- }
2398
- function cliRouteInventoryRouteLabel(route) {
2399
- return route.name && route.name !== route.path ? `${route.name} (${route.path})` : route.path;
2400
- }
2401
- function cliRouteInventoryRouteList(routes) {
2402
- const visible = routes.slice(0, 12).map(cliRouteInventoryRouteLabel);
2403
- const omitted = routes.length > 12 ? `; ${routes.length - 12} more` : "";
2404
- return `${visible.join("; ")}${omitted}`;
2405
- }
2406
- function cliRouteInventorySourceScopeLabel(value) {
2407
- const scope = cliString(value);
2408
- if (scope === "expected_routes") return "expected routes";
2409
- if (scope === "route_path_prefix") return "route path prefix";
2410
- return scope;
2411
- }
2412
- function profileEnvironmentBlockerMarkdown(result) {
2413
- const blocker = cliRecord(result.environment_blocker);
2414
- if (!blocker) return [];
2415
- const lines = [];
2416
- const reason = cliString(blocker.reason);
2417
- const source = cliString(blocker.source);
2418
- const endpoint = cliString(blocker.endpoint);
2419
- const httpStatus = cliFiniteNumber(blocker.http_status);
2420
- const error = cliString(blocker.error);
2421
- const requiredSeconds = cliFiniteNumber(blocker.required_seconds);
2422
- const availableSeconds = cliFiniteNumber(blocker.available_seconds);
2423
- const deficitSeconds = cliFiniteNumber(blocker.deficit_seconds);
2424
- const minimumPurchaseDollars = cliFiniteNumber(blocker.minimum_purchase_dollars);
2425
- const balancePreflight = blocker.balance_preflight === true;
2426
- const jobCount = cliFiniteNumber(blocker.job_count);
2427
- const secondsPerJob = cliFiniteNumber(blocker.seconds_per_job);
2428
- const apiKeySource = cliString(blocker.api_key_source);
2429
- const apiKeyFile = cliString(blocker.api_key_file);
2430
- if (reason) lines.push(`- reason: ${reason}`);
2431
- if (source || endpoint || httpStatus !== void 0) {
2432
- lines.push(`- source: ${source || "runner"}${endpoint ? ` ${endpoint}` : ""}${httpStatus === void 0 ? "" : ` HTTP ${httpStatus}`}`);
2433
- }
2434
- if (balancePreflight) lines.push("- preflight: balance");
2435
- if (error) lines.push(`- error: ${error}`);
2436
- if (jobCount !== void 0 || secondsPerJob !== void 0) {
2437
- lines.push(`- job estimate: ${jobCount ?? "unknown"} job(s), ${secondsPerJob ?? "unknown"}s minimum per job`);
2438
- }
2439
- if (requiredSeconds !== void 0 || availableSeconds !== void 0 || deficitSeconds !== void 0) {
2440
- lines.push(`- seconds: required ${requiredSeconds ?? "unknown"}, available ${availableSeconds ?? "unknown"}, deficit ${deficitSeconds ?? "unknown"}`);
2441
- }
2442
- if (minimumPurchaseDollars !== void 0) lines.push(`- minimum purchase: $${minimumPurchaseDollars}`);
2443
- if (apiKeySource) lines.push(`- auth: ${apiKeySource}${apiKeyFile ? ` ${apiKeyFile}` : ""}`);
2444
- return lines;
2445
- }
2446
- function profileCliDiagnosticLine(result) {
2447
- if (result.status !== "environment_blocked") return void 0;
2448
- const blocker = cliRecord(result.environment_blocker);
2449
- if (blocker?.reason === "insufficient_balance") {
2450
- const requiredSeconds = cliFiniteNumber(blocker.required_seconds);
2451
- const availableSeconds = cliFiniteNumber(blocker.available_seconds);
2452
- const deficitSeconds = cliFiniteNumber(blocker.deficit_seconds);
2453
- const parts = [
2454
- requiredSeconds === void 0 ? "" : `required=${requiredSeconds}s`,
2455
- availableSeconds === void 0 ? "" : `available=${availableSeconds}s`,
2456
- deficitSeconds === void 0 ? "" : `deficit=${deficitSeconds}s`
2457
- ].filter(Boolean);
2458
- return `[riddle-profile] environment_blocked insufficient_balance${parts.length ? ` ${parts.join(" ")}` : ""}`;
2459
- }
2460
- const source = cliString(blocker?.source);
2461
- const endpoint = cliString(blocker?.endpoint);
2462
- const httpStatus = cliFiniteNumber(blocker?.http_status);
2463
- if (source || endpoint || httpStatus !== void 0) {
2464
- return `[riddle-profile] environment_blocked${source ? ` source=${source}` : ""}${endpoint ? ` endpoint=${endpoint}` : ""}${httpStatus === void 0 ? "" : ` http_status=${httpStatus}`}`;
2465
- }
2466
- return `[riddle-profile] environment_blocked ${result.summary}`;
2467
- }
2468
- function profileSetupSummaryMarkdown(result) {
2469
- const setupCheck = result.checks.find((check) => check.type === "setup_actions_succeeded");
2470
- const setupSummary = cliRecord(setupCheck?.evidence?.setup_summary);
2471
- if (!setupSummary) return [];
2472
- const viewports = Array.isArray(setupSummary.viewports) ? setupSummary.viewports.map(cliRecord).filter((viewport) => Boolean(viewport)) : [];
2473
- if (!viewports.length) return [];
2474
- const declaredActions = cliFiniteNumber(setupSummary.action_count);
2475
- const totalResults = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.result_count) || 0), 0);
2476
- const finalScreenshotCount = cliFiniteNumber(setupSummary.final_screenshot_count) ?? viewports.reduce((sum, viewport) => sum + (cliString(viewport.final_screenshot) || cliString(viewport.screenshot_label) ? 1 : 0), 0);
2477
- const finalScreenshotMode = cliString(setupSummary.final_screenshot_mode);
2478
- const setupScreenshots = viewports.reduce((sum, viewport) => {
2479
- const labels = Array.isArray(viewport.setup_screenshots) ? viewport.setup_screenshots : [];
2480
- return sum + labels.filter((label) => typeof label === "string" && label.trim()).length;
2481
- }, 0);
2482
- const clickedTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.clicked_total) || 0), 0);
2483
- const clickSequenceTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.click_sequence_total) || 0), 0);
2484
- const clickCountActionTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.click_count_action_total) || 0), 0);
2485
- const clickCountValueTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.click_count_value_total) || 0), 0);
2486
- const windowCallTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.window_call_total) || 0), 0);
2487
- const windowCallStoredTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.window_call_stored_total) || 0), 0);
2488
- const windowCallCapturedTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.window_call_captured_total) || 0), 0);
2489
- const windowEvalTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.window_eval_total) || 0), 0);
2490
- const windowEvalStoredTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.window_eval_stored_total) || 0), 0);
2491
- const windowEvalCapturedTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.window_eval_captured_total) || 0), 0);
2492
- const deterministicRuntimeTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.deterministic_runtime_total) || 0), 0);
2493
- const windowCallUntilTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.window_call_until_total) || 0), 0);
2494
- const windowCallUntilCallTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.window_call_until_call_total) || 0), 0);
2495
- const rangeValueTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.set_range_value_total) || 0), 0);
2496
- const dragTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.drag_total) || 0), 0);
2497
- const tapTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.tap_total) || 0), 0);
2498
- const tapUntilTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.tap_until_total) || 0), 0);
2499
- const tapUntilTapTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.tap_until_tap_total) || 0), 0);
2500
- const keyboardTotal = viewports.reduce((sum, viewport) => {
2501
- const total = cliFiniteNumber(viewport.keyboard_total);
2502
- return sum + (total === void 0 ? cliFiniteNumber(viewport.press_total) || 0 : total);
2503
- }, 0);
2504
- const canvasSignatureTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.canvas_signature_total) || 0), 0);
2505
- const failedTotal = viewports.reduce((sum, viewport) => sum + (Array.isArray(viewport.failed) ? viewport.failed.length : 0), 0);
2506
- const lines = [
2507
- `- setup actions: ${declaredActions === void 0 ? "unknown" : declaredActions} declared, ${totalResults} recorded result(s) across ${viewports.length} viewport(s)`,
2508
- ...finalScreenshotMode ? [`- final screenshots: ${finalScreenshotCount}, mode ${finalScreenshotMode}`] : [],
2509
- `- setup screenshots: ${setupScreenshots}`,
2510
- `- clicked targets: ${clickedTotal}${failedTotal ? `; failed setup actions: ${failedTotal}` : ""}`
2511
- ];
2512
- if (clickCountActionTotal) {
2513
- lines.push(`- click counts: ${clickCountActionTotal} action(s), click_count total ${clickCountValueTotal}`);
2514
- }
2515
- if (clickSequenceTotal) {
2516
- lines.push(`- click sequences: ${clickSequenceTotal} group(s)`);
2517
- }
2518
- if (windowCallTotal) {
2519
- lines.push(`- window_call: ${windowCallTotal} action(s), stored returns ${windowCallStoredTotal}, captured returns ${windowCallCapturedTotal}`);
2520
- }
2521
- if (windowEvalTotal) {
2522
- lines.push(`- window_eval: ${windowEvalTotal} action(s), stored returns ${windowEvalStoredTotal}, captured returns ${windowEvalCapturedTotal}`);
2523
- }
2524
- if (deterministicRuntimeTotal) {
2525
- lines.push(`- deterministic_runtime: ${deterministicRuntimeTotal} action(s)`);
2526
- }
2527
- if (windowCallUntilTotal) {
2528
- lines.push(`- window_call_until: ${windowCallUntilTotal} action(s), call_count total ${windowCallUntilCallTotal}`);
2529
- }
2530
- if (rangeValueTotal) {
2531
- lines.push(`- set_range_value: ${rangeValueTotal} action(s)`);
2532
- }
2533
- if (dragTotal) {
2534
- lines.push(`- drag: ${dragTotal} action(s)`);
2535
- }
2536
- if (tapTotal) {
2537
- lines.push(`- tap: ${tapTotal} action(s)`);
2538
- }
2539
- if (tapUntilTotal) {
2540
- lines.push(`- tap_until: ${tapUntilTotal} action(s), tap_count total ${tapUntilTapTotal}`);
2541
- }
2542
- if (keyboardTotal) {
2543
- lines.push(`- keyboard: ${keyboardTotal} action(s)`);
2544
- }
2545
- if (canvasSignatureTotal) {
2546
- lines.push(`- canvas_signature: ${canvasSignatureTotal} action(s)`);
2547
- }
2548
- lines.push(...setupNaturalInputSummaryMarkdown(viewports));
2549
- for (const viewport of viewports.slice(0, 8)) {
2550
- const name = cliString(viewport.name) || "viewport";
2551
- const ok = viewport.ok === false ? "failed" : "ok";
2552
- const resultCount = cliFiniteNumber(viewport.result_count) || 0;
2553
- const screenshotCount = Array.isArray(viewport.setup_screenshots) ? viewport.setup_screenshots.filter((label) => typeof label === "string" && label.trim()).length : 0;
2554
- const clicked = cliFiniteNumber(viewport.clicked_total) || 0;
2555
- const clickSequenceCount = cliFiniteNumber(viewport.click_sequence_total) || 0;
2556
- const clickCountActions = cliFiniteNumber(viewport.click_count_action_total) || 0;
2557
- const windowCallActions = cliFiniteNumber(viewport.window_call_total) || 0;
2558
- const windowCallStored = cliFiniteNumber(viewport.window_call_stored_total) || 0;
2559
- const windowCallCaptured = cliFiniteNumber(viewport.window_call_captured_total) || 0;
2560
- const windowEvalActions = cliFiniteNumber(viewport.window_eval_total) || 0;
2561
- const windowEvalStored = cliFiniteNumber(viewport.window_eval_stored_total) || 0;
2562
- const windowEvalCaptured = cliFiniteNumber(viewport.window_eval_captured_total) || 0;
2563
- const deterministicRuntimeActions = cliFiniteNumber(viewport.deterministic_runtime_total) || 0;
2564
- const windowCallUntilActions = cliFiniteNumber(viewport.window_call_until_total) || 0;
2565
- const windowCallUntilCalls = cliFiniteNumber(viewport.window_call_until_call_total) || 0;
2566
- const rangeValueActions = cliFiniteNumber(viewport.set_range_value_total) || 0;
2567
- const dragActions = cliFiniteNumber(viewport.drag_total) || 0;
2568
- const tapActions = cliFiniteNumber(viewport.tap_total) || 0;
2569
- const tapUntilActions = cliFiniteNumber(viewport.tap_until_total) || 0;
2570
- const tapUntilTaps = cliFiniteNumber(viewport.tap_until_tap_total) || 0;
2571
- const keyboardActions = cliFiniteNumber(viewport.keyboard_total) ?? cliFiniteNumber(viewport.press_total) ?? 0;
2572
- const canvasSignatureActions = cliFiniteNumber(viewport.canvas_signature_total) || 0;
2573
- const observedPath = cliString(viewport.observed_path);
2574
- lines.push(`- ${name}: ${ok}, ${resultCount} result(s), ${screenshotCount} setup screenshot(s), ${clicked} click(s)${clickSequenceCount ? `, ${clickSequenceCount} click sequence(s)` : ""}${clickCountActions ? `, ${clickCountActions} click_count action(s)` : ""}${rangeValueActions ? `, ${rangeValueActions} set_range_value action(s)` : ""}${dragActions ? `, ${dragActions} drag action(s)` : ""}${tapActions ? `, ${tapActions} tap action(s)` : ""}${tapUntilActions ? `, ${tapUntilActions} tap_until action(s), ${tapUntilTaps} tap(s)` : ""}${keyboardActions ? `, ${keyboardActions} keyboard action(s)` : ""}${canvasSignatureActions ? `, ${canvasSignatureActions} canvas_signature action(s)` : ""}${deterministicRuntimeActions ? `, ${deterministicRuntimeActions} deterministic_runtime action(s)` : ""}${windowCallActions ? `, ${windowCallActions} window_call action(s), ${windowCallStored} stored return(s), ${windowCallCaptured} captured return(s)` : ""}${windowEvalActions ? `, ${windowEvalActions} window_eval action(s), ${windowEvalStored} stored return(s), ${windowEvalCaptured} captured return(s)` : ""}${windowCallUntilActions ? `, ${windowCallUntilActions} window_call_until action(s), ${windowCallUntilCalls} call(s)` : ""}${observedPath ? `, path ${observedPath}` : ""}`);
2575
- }
2576
- const clickSequenceGroups = viewports.map((viewport) => {
2577
- const name = cliString(viewport.name) || "viewport";
2578
- const receipts = Array.isArray(viewport.click_sequences) ? viewport.click_sequences.map(cliRecord).filter((item) => Boolean(item)) : [];
2579
- return receipts.map((receipt) => ({ name, receipt }));
2580
- });
2581
- const clickSequenceDetails = clickSequenceGroups.flat();
2582
- const sampledClickSequenceDetails = balancedSetupReceiptDetails(clickSequenceGroups, 12);
2583
- for (const { name, receipt } of sampledClickSequenceDetails) {
2584
- const selectorTemplate = cliString(receipt.selector_template) || "target";
2585
- const valueSource = cliString(receipt.value_source);
2586
- const sequence = Array.isArray(receipt.sequence) ? receipt.sequence.map((value) => cliFiniteNumber(value)).filter((value) => value !== void 0) : [];
2587
- const sequenceText = sequence.join(",");
2588
- const omittedSequenceCount = cliFiniteNumber(receipt.omitted_sequence_count) || 0;
2589
- const clickTotal = cliFiniteNumber(receipt.click_total);
2590
- const resultCount = cliFiniteNumber(receipt.result_count);
2591
- const ordinals = Array.isArray(receipt.ordinals) ? receipt.ordinals.map((value) => cliFiniteNumber(value)).filter((value) => value !== void 0) : [];
2592
- const ordinalText = ordinals.length ? ordinals.join(",") : "";
2593
- lines.push(`- ${name} click_sequence: ${markdownInlineCode(selectorTemplate)}${valueSource ? ` ${valueSource}` : ""}${sequenceText ? ` sequence ${markdownInlineCode(sequenceText, 160)}` : ""}${omittedSequenceCount ? ` (+${omittedSequenceCount} omitted)` : ""}${clickTotal === void 0 ? "" : `, clicks ${clickTotal}`}${resultCount === void 0 ? "" : `, results ${resultCount}`}${ordinalText ? `, ordinals ${markdownInlineCode(ordinalText, 120)}` : ""}`);
2594
- }
2595
- if (clickSequenceDetails.length > sampledClickSequenceDetails.length) lines.push(`- ${clickSequenceDetails.length - sampledClickSequenceDetails.length} additional click_sequence receipt(s) omitted.`);
2596
- const dragGroups = viewports.map((viewport) => {
2597
- const name = cliString(viewport.name) || "viewport";
2598
- const receipts = Array.isArray(viewport.drag) ? viewport.drag.map(cliRecord).filter((item) => Boolean(item)) : [];
2599
- return receipts.map((receipt) => ({ name, receipt }));
2600
- });
2601
- const dragDetails = dragGroups.flat();
2602
- const sampledDragDetails = balancedSetupReceiptDetails(dragGroups, 12);
2603
- for (const { name, receipt } of sampledDragDetails) {
2604
- const selector = cliString(receipt.selector) || "target";
2605
- const pointerType = cliString(receipt.pointer_type);
2606
- const inputDispatch = cliString(receipt.input_dispatch);
2607
- const coordinateMode = cliString(receipt.coordinate_mode);
2608
- const fromX = cliValueLabel(receipt.from_x);
2609
- const fromY = cliValueLabel(receipt.from_y);
2610
- const toX = cliValueLabel(receipt.to_x);
2611
- const toY = cliValueLabel(receipt.to_y);
2612
- const steps = cliFiniteNumber(receipt.steps);
2613
- const durationMs = cliFiniteNumber(receipt.duration_ms);
2614
- const ok = receipt.ok === false ? "failed" : "ok";
2615
- const reason = cliString(receipt.reason);
2616
- const coordinateText = fromX && fromY && toX && toY ? `, ${coordinateMode ? `${coordinateMode} ` : ""}${markdownInlineCode(`${fromX},${fromY}`)} -> ${markdownInlineCode(`${toX},${toY}`)}` : "";
2617
- lines.push(`- ${name} drag: ${ok}, ${markdownInlineCode(selector)}${pointerType ? ` ${markdownInlineCode(pointerType)}` : ""}${inputDispatch ? ` via ${markdownInlineCode(inputDispatch)}` : ""}${coordinateText}${steps === void 0 ? "" : `, steps ${steps}`}${durationMs === void 0 ? "" : `, duration ${durationMs}ms`}${reason ? `, reason ${markdownInlineCode(reason, 100)}` : ""}`);
2618
- }
2619
- if (dragDetails.length > sampledDragDetails.length) lines.push(`- ${dragDetails.length - sampledDragDetails.length} additional drag receipt(s) omitted.`);
2620
- const tapGroups = viewports.map((viewport) => {
2621
- const name = cliString(viewport.name) || "viewport";
2622
- const receipts = Array.isArray(viewport.tap) ? viewport.tap.map(cliRecord).filter((item) => Boolean(item)) : [];
2623
- return receipts.map((receipt) => ({ name, receipt }));
2624
- });
2625
- const tapDetails = tapGroups.flat();
2626
- const sampledTapDetails = balancedSetupReceiptDetails(tapGroups, 12);
2627
- for (const { name, receipt } of sampledTapDetails) {
2628
- const selector = cliString(receipt.selector) || "target";
2629
- const pointerType = cliString(receipt.pointer_type);
2630
- const inputDispatch = cliString(receipt.input_dispatch);
2631
- const coordinateMode = cliString(receipt.coordinate_mode);
2632
- const x = cliValueLabel(receipt.x);
2633
- const y = cliValueLabel(receipt.y);
2634
- const durationMs = cliFiniteNumber(receipt.duration_ms);
2635
- const ok = receipt.ok === false ? "failed" : "ok";
2636
- const reason = cliString(receipt.reason);
2637
- const coordinateText = x && y ? `, ${coordinateMode ? `${coordinateMode} ` : ""}${markdownInlineCode(`${x},${y}`)}` : "";
2638
- lines.push(`- ${name} tap: ${ok}, ${markdownInlineCode(selector)}${pointerType ? ` ${markdownInlineCode(pointerType)}` : ""}${inputDispatch ? ` via ${markdownInlineCode(inputDispatch)}` : ""}${coordinateText}${durationMs === void 0 ? "" : `, duration ${durationMs}ms`}${reason ? `, reason ${markdownInlineCode(reason, 100)}` : ""}`);
2639
- }
2640
- if (tapDetails.length > sampledTapDetails.length) lines.push(`- ${tapDetails.length - sampledTapDetails.length} additional tap receipt(s) omitted.`);
2641
- const tapUntilGroups = viewports.map((viewport) => {
2642
- const name = cliString(viewport.name) || "viewport";
2643
- const receipts = Array.isArray(viewport.tap_until) ? viewport.tap_until.map(cliRecord).filter((item) => Boolean(item)) : [];
2644
- return receipts.map((receipt) => ({ name, receipt }));
2645
- });
2646
- const tapUntilDetails = tapUntilGroups.flat();
2647
- const sampledTapUntilDetails = balancedSetupReceiptDetails(tapUntilGroups, 12);
2648
- for (const { name, receipt } of sampledTapUntilDetails) {
2649
- const selector = cliString(receipt.selector) || "target";
2650
- const pointerType = cliString(receipt.pointer_type);
2651
- const inputDispatch = cliString(receipt.input_dispatch);
2652
- const coordinateMode = cliString(receipt.coordinate_mode);
2653
- const x = cliValueLabel(receipt.x);
2654
- const y = cliValueLabel(receipt.y);
2655
- const durationMs = cliFiniteNumber(receipt.duration_ms);
2656
- const untilPath = cliString(receipt.until_path) || "until_path";
2657
- const expected = cliValueLabel(receipt.until_expected_value);
2658
- const actual = cliValueLabel(receipt.until_value);
2659
- const tapCount = cliFiniteNumber(receipt.tap_count);
2660
- const maxTaps = cliFiniteNumber(receipt.max_taps) ?? cliFiniteNumber(receipt.max_calls);
2661
- const tapBurstSize = cliFiniteNumber(receipt.tap_burst_size);
2662
- const conditionCheckCount = cliFiniteNumber(receipt.condition_check_count);
2663
- const settleMs = cliFiniteNumber(receipt.settle_ms);
2664
- const elapsedMs = cliFiniteNumber(receipt.elapsed_ms);
2665
- const ok = receipt.ok === false ? "failed" : "ok";
2666
- const reason = cliString(receipt.reason);
2667
- const coordinateText = x && y ? `, ${coordinateMode ? `${coordinateMode} ` : ""}${markdownInlineCode(`${x},${y}`)}` : "";
2668
- const tapText = tapCount === void 0 ? "" : ` in ${tapCount}${maxTaps === void 0 ? "" : `/${maxTaps}`} tap(s)`;
2669
- const burstText = tapBurstSize === void 0 || tapBurstSize <= 1 ? "" : `, burst ${tapBurstSize}`;
2670
- const conditionCheckText = conditionCheckCount === void 0 ? "" : `, ${conditionCheckCount} check(s)`;
2671
- const settleText = settleMs === void 0 || settleMs <= 0 ? "" : `, settle ${settleMs}ms`;
2672
- const elapsedText = elapsedMs === void 0 ? "" : `, elapsed ${elapsedMs}ms`;
2673
- lines.push(`- ${name} tap_until: ${ok}, ${markdownInlineCode(selector)}${pointerType ? ` ${markdownInlineCode(pointerType)}` : ""}${inputDispatch ? ` via ${markdownInlineCode(inputDispatch)}` : ""}${coordinateText}${durationMs === void 0 ? "" : `, duration ${durationMs}ms`} until ${markdownInlineCode(untilPath)}${expected === void 0 ? "" : ` == ${markdownInlineCode(expected, 80)}`}${tapText}${burstText}${conditionCheckText}${settleText}${elapsedText}${actual === void 0 ? "" : `, observed ${markdownInlineCode(actual, 80)}`}${reason ? `, reason ${markdownInlineCode(reason, 100)}` : ""}`);
2674
- }
2675
- if (tapUntilDetails.length > sampledTapUntilDetails.length) lines.push(`- ${tapUntilDetails.length - sampledTapUntilDetails.length} additional tap_until receipt(s) omitted.`);
2676
- const keyboardGroups = viewports.map((viewport) => {
2677
- const name = cliString(viewport.name) || "viewport";
2678
- const rawReceipts = Array.isArray(viewport.keyboard) ? viewport.keyboard : viewport.press;
2679
- const receipts = Array.isArray(rawReceipts) ? rawReceipts.map(cliRecord).filter((item) => Boolean(item)) : [];
2680
- return receipts.map((receipt) => ({ name, receipt }));
2681
- });
2682
- const keyboardDetails = keyboardGroups.flat();
2683
- for (const group of keyboardGroups.slice(0, 8)) {
2684
- if (!group.length) continue;
2685
- const name = group[0].name;
2686
- const keys = group.map(({ receipt }) => cliString(receipt.key) || "key").filter(Boolean);
2687
- const ordinals = group.map(({ receipt }) => cliFiniteNumber(receipt.ordinal)).filter((value) => value !== void 0);
2688
- const visibleKeys = keys.slice(0, 16);
2689
- const omittedKeyCount = Math.max(0, keys.length - visibleKeys.length);
2690
- const visibleOrdinals = ordinals.slice(0, 16);
2691
- const omittedOrdinalCount = Math.max(0, ordinals.length - visibleOrdinals.length);
2692
- const keyText = visibleKeys.join(",");
2693
- const ordinalText = visibleOrdinals.join(",");
2694
- lines.push(`- ${name} keyboard_sequence: keys ${markdownInlineCode(keyText, 200)}${omittedKeyCount ? ` (+${omittedKeyCount} omitted)` : ""}${ordinalText ? `, ordinals ${markdownInlineCode(ordinalText, 120)}${omittedOrdinalCount ? ` (+${omittedOrdinalCount} omitted)` : ""}` : ""}`);
2695
- }
2696
- const sampledKeyboardDetails = balancedSetupReceiptDetails(keyboardGroups, 12);
2697
- for (const { name, receipt } of sampledKeyboardDetails) {
2698
- const action = cliString(receipt.action) || "press";
2699
- const key = cliString(receipt.key) || "key";
2700
- const selector = cliString(receipt.selector);
2701
- const frameSelector = cliString(receipt.frame_selector);
2702
- const holdMs = cliFiniteNumber(receipt.hold_ms);
2703
- const ok = receipt.ok === false ? "failed" : "ok";
2704
- const reason = cliString(receipt.reason);
2705
- lines.push(`- ${name} ${action}: ${ok}, ${markdownInlineCode(key)}${selector ? ` on ${markdownInlineCode(selector)}` : ""}${frameSelector ? ` in frame ${markdownInlineCode(frameSelector)}` : ""}${holdMs === void 0 ? "" : `, held ${holdMs}ms`}${reason ? `, reason ${markdownInlineCode(reason, 100)}` : ""}`);
2706
- }
2707
- if (keyboardDetails.length > sampledKeyboardDetails.length) lines.push(`- ${keyboardDetails.length - sampledKeyboardDetails.length} additional keyboard receipt(s) omitted.`);
2708
- const canvasSignatureGroups = viewports.map((viewport) => {
2709
- const name = cliString(viewport.name) || "viewport";
2710
- const receipts = Array.isArray(viewport.canvas_signature) ? viewport.canvas_signature.map(cliRecord).filter((item) => Boolean(item)) : [];
2711
- return receipts.map((receipt) => ({ name, receipt }));
2712
- });
2713
- const canvasSignatureDetails = canvasSignatureGroups.flat();
2714
- const sampledCanvasSignatureDetails = balancedSetupReceiptDetails(canvasSignatureGroups, 12);
2715
- for (const { name, receipt } of sampledCanvasSignatureDetails) {
2716
- const selector = cliString(receipt.selector) || "canvas";
2717
- const label = cliString(receipt.label);
2718
- const hash = cliString(receipt.hash);
2719
- const dataLength = cliFiniteNumber(receipt.data_length);
2720
- const width = cliFiniteNumber(receipt.width);
2721
- const height = cliFiniteNumber(receipt.height);
2722
- const cssWidth = cliFiniteNumber(receipt.css_width);
2723
- const cssHeight = cliFiniteNumber(receipt.css_height);
2724
- const compareTo = cliString(receipt.compare_to);
2725
- const previousHash = cliString(receipt.previous_hash);
2726
- const changed = typeof receipt.changed === "boolean" ? receipt.changed : void 0;
2727
- const storedTo = cliString(receipt.return_stored_to);
2728
- const ok = receipt.ok === false ? "failed" : "ok";
2729
- const reason = cliString(receipt.reason);
2730
- const sizeText = width === void 0 || height === void 0 ? "" : `, ${width}x${height}`;
2731
- const cssSizeText = cssWidth === void 0 || cssHeight === void 0 ? "" : `, css ${cssWidth}x${cssHeight}`;
2732
- lines.push(`- ${name} canvas_signature: ${ok}, ${markdownInlineCode(selector)}${label ? ` ${markdownInlineCode(label, 80)}` : ""}${hash ? ` hash ${markdownInlineCode(hash, 80)}` : ""}${sizeText}${cssSizeText}${dataLength === void 0 ? "" : `, data chars ${dataLength}`}${compareTo ? `, compared ${markdownInlineCode(compareTo)}` : ""}${previousHash ? ` previous ${markdownInlineCode(previousHash, 80)}` : ""}${changed === void 0 ? "" : `, changed ${changed}`}${storedTo ? `, stored ${markdownInlineCode(storedTo)}` : ""}${reason ? `, reason ${markdownInlineCode(reason, 100)}` : ""}`);
2733
- }
2734
- if (canvasSignatureDetails.length > sampledCanvasSignatureDetails.length) lines.push(`- ${canvasSignatureDetails.length - sampledCanvasSignatureDetails.length} additional canvas_signature receipt(s) omitted.`);
2735
- const canvasSignatureWarningGroups = viewports.map((viewport) => {
2736
- const name = cliString(viewport.name) || "viewport";
2737
- const warnings = Array.isArray(viewport.canvas_signature_stable_hash_groups) ? viewport.canvas_signature_stable_hash_groups.map(cliRecord).filter((item) => Boolean(item)) : [];
2738
- return warnings.map((warning) => ({ name, receipt: warning }));
2739
- });
2740
- const canvasSignatureWarnings = canvasSignatureWarningGroups.flat();
2741
- const sampledCanvasSignatureWarnings = balancedSetupReceiptDetails(canvasSignatureWarningGroups, 12);
2742
- for (const { name, receipt } of sampledCanvasSignatureWarnings) {
2743
- const selector = cliString(receipt.selector) || "canvas";
2744
- const frameSelector = cliString(receipt.frame_selector);
2745
- const hash = cliString(receipt.hash);
2746
- const count = cliFiniteNumber(receipt.count);
2747
- const labelCount = cliFiniteNumber(receipt.label_count);
2748
- const labels = cliStringArray(receipt.labels);
2749
- const omittedLabelCount = cliFiniteNumber(receipt.omitted_label_count) || 0;
2750
- const labelText = labels.length ? ` across ${labels.map((label) => markdownInlineCode(label, 60)).join(", ")}${omittedLabelCount ? `, plus ${omittedLabelCount} more` : ""}` : "";
2751
- lines.push(`- ${name} canvas_signature warning: ${markdownInlineCode(selector)}${frameSelector ? ` in frame ${markdownInlineCode(frameSelector)}` : ""} returned the same hash${hash ? ` ${markdownInlineCode(hash, 80)}` : ""} for ${count ?? labelCount ?? "multiple"} labeled capture(s)${labelText}; treat canvas signatures as diagnostic when runtime evidence or screenshots show state changes.`);
2752
- }
2753
- if (canvasSignatureWarnings.length > sampledCanvasSignatureWarnings.length) lines.push(`- ${canvasSignatureWarnings.length - sampledCanvasSignatureWarnings.length} additional canvas_signature warning(s) omitted.`);
2754
- const deterministicRuntimeGroups = viewports.map((viewport) => {
2755
- const name = cliString(viewport.name) || "viewport";
2756
- const receipts = Array.isArray(viewport.deterministic_runtime) ? viewport.deterministic_runtime.map(cliRecord).filter((item) => Boolean(item)) : [];
2757
- return receipts.map((receipt) => ({ name, receipt }));
2758
- });
2759
- const deterministicRuntimeDetails = deterministicRuntimeGroups.flat();
2760
- const sampledDeterministicRuntimeDetails = balancedSetupReceiptDetails(deterministicRuntimeGroups, 12);
2761
- for (const { name, receipt } of sampledDeterministicRuntimeDetails) {
2762
- const ok = receipt.ok === false ? "failed" : "ok";
2763
- const randomEnabled = receipt.random_enabled === true ? "on" : receipt.random_enabled === false ? "off" : "unknown";
2764
- const clockEnabled = receipt.clock_enabled === true ? "on" : receipt.clock_enabled === false ? "off" : "unknown";
2765
- const randomQueueAdded = cliFiniteNumber(receipt.random_queue_added);
2766
- const randomQueueLength = cliFiniteNumber(receipt.random_queue_length);
2767
- const randomQueueMode = cliString(receipt.random_queue_mode);
2768
- const randomUnderflowCount = cliFiniteNumber(receipt.random_underflow_count);
2769
- const previousNow = cliFiniteNumber(receipt.previous_now);
2770
- const now = cliFiniteNumber(receipt.now);
2771
- const advanceMs = cliFiniteNumber(receipt.advance_ms);
2772
- const restored = receipt.restored === true;
2773
- const reason = cliString(receipt.reason);
2774
- const randomText = randomQueueAdded === void 0 && randomQueueLength === void 0 ? `random ${randomEnabled}` : `random ${randomEnabled}${randomQueueMode ? ` ${randomQueueMode}` : ""}${randomQueueAdded === void 0 ? "" : ` +${randomQueueAdded}`}${randomQueueLength === void 0 ? "" : ` -> ${randomQueueLength}`}`;
2775
- const clockText = now === void 0 ? `clock ${clockEnabled}` : `clock ${clockEnabled}${previousNow === void 0 ? "" : ` ${previousNow} ->`} ${now}`;
2776
- lines.push(`- ${name} deterministic_runtime: ${ok}, ${restored ? "restored, " : ""}${randomText}${randomUnderflowCount ? `, underflows ${randomUnderflowCount}` : ""}, ${clockText}${advanceMs === void 0 ? "" : `, advance ${advanceMs}ms`}${reason ? `, reason ${markdownInlineCode(reason, 100)}` : ""}`);
2777
- }
2778
- if (deterministicRuntimeDetails.length > sampledDeterministicRuntimeDetails.length) lines.push(`- ${deterministicRuntimeDetails.length - sampledDeterministicRuntimeDetails.length} additional deterministic_runtime receipt(s) omitted.`);
2779
- const rangeValueGroups = viewports.map((viewport) => {
2780
- const name = cliString(viewport.name) || "viewport";
2781
- const receipts = Array.isArray(viewport.set_range_value) ? viewport.set_range_value.map(cliRecord).filter((item) => Boolean(item)) : [];
2782
- return receipts.map((receipt) => ({ name, receipt }));
2783
- });
2784
- const rangeValueDetails = rangeValueGroups.flat();
2785
- const sampledRangeValueDetails = balancedSetupReceiptDetails(rangeValueGroups, 12);
2786
- for (const { name, receipt } of sampledRangeValueDetails) {
2787
- const selector = cliString(receipt.selector) || "input[type=range]";
2788
- const requested = cliValueLabel(receipt.requested_value);
2789
- const actual = cliValueLabel(receipt.actual_value);
2790
- const before = cliValueLabel(receipt.before_value);
2791
- const valueAsNumber = cliFiniteNumber(receipt.value_as_number);
2792
- const min = cliValueLabel(receipt.min);
2793
- const max = cliValueLabel(receipt.max);
2794
- const step = cliValueLabel(receipt.step);
2795
- const ok = receipt.ok === false ? "failed" : "ok";
2796
- const reason = cliString(receipt.reason);
2797
- lines.push(`- ${name} set_range_value: ${ok}, ${markdownInlineCode(selector)}${requested === void 0 ? "" : ` requested ${markdownInlineCode(requested, 80)}`}${actual === void 0 ? "" : ` -> ${markdownInlineCode(actual, 80)}`}${before === void 0 ? "" : `, before ${markdownInlineCode(before, 80)}`}${valueAsNumber === void 0 ? "" : `, number ${valueAsNumber}`}${min === void 0 && max === void 0 ? "" : `, range ${min === void 0 ? "?" : markdownInlineCode(min, 40)}..${max === void 0 ? "?" : markdownInlineCode(max, 40)}`}${step === void 0 ? "" : ` step ${markdownInlineCode(step, 40)}`}${reason ? `, reason ${markdownInlineCode(reason, 100)}` : ""}`);
2798
- }
2799
- if (rangeValueDetails.length > sampledRangeValueDetails.length) lines.push(`- ${rangeValueDetails.length - sampledRangeValueDetails.length} additional set_range_value receipt(s) omitted.`);
2800
- const windowCallGroups = viewports.map((viewport) => {
2801
- const name = cliString(viewport.name) || "viewport";
2802
- const receipts = Array.isArray(viewport.window_call) ? viewport.window_call.map(cliRecord).filter((item) => Boolean(item)) : [];
2803
- return receipts.map((receipt) => ({ name, receipt }));
2804
- });
2805
- const windowCallDetails = windowCallGroups.flat();
2806
- const sampledWindowCallDetails = balancedSetupReceiptDetails(windowCallGroups, 12);
2807
- for (const { name, receipt } of sampledWindowCallDetails) {
2808
- const path2 = cliString(receipt.path) || "window_function";
2809
- const storedTo = cliString(receipt.return_stored_to);
2810
- const returned = cliValueLabel(receipt.returned);
2811
- const expected = cliValueLabel(receipt.expected_return);
2812
- const returnSummary = cliReturnSummaryLabel(receipt.return_summary);
2813
- const captured = receipt.return_captured === true ? "captured" : receipt.return_captured === false ? "not captured" : "capture unknown";
2814
- const ok = receipt.ok === false ? "failed" : "ok";
2815
- const reason = cliString(receipt.reason);
2816
- lines.push(`- ${name} window_call: ${ok}, ${markdownInlineCode(path2)}${storedTo ? `, stored ${markdownInlineCode(storedTo)}` : ""}, return ${captured}${expected === void 0 ? "" : `, expected ${markdownInlineCode(expected, 80)}`}${returnSummary ? `, summary ${markdownInlineCode(returnSummary, 140)}` : ""}${returned === void 0 ? "" : `, returned ${markdownInlineCode(returned, 80)}`}${reason ? `, reason ${markdownInlineCode(reason, 100)}` : ""}`);
2817
- }
2818
- if (windowCallDetails.length > sampledWindowCallDetails.length) lines.push(`- ${windowCallDetails.length - sampledWindowCallDetails.length} additional window_call receipt(s) omitted.`);
2819
- const windowEvalGroups = viewports.map((viewport) => {
2820
- const name = cliString(viewport.name) || "viewport";
2821
- const receipts = Array.isArray(viewport.window_eval) ? viewport.window_eval.map(cliRecord).filter((item) => Boolean(item)) : [];
2822
- return receipts.map((receipt) => ({ name, receipt }));
2823
- });
2824
- const windowEvalDetails = windowEvalGroups.flat();
2825
- const sampledWindowEvalDetails = balancedSetupReceiptDetails(windowEvalGroups, 12);
2826
- for (const { name, receipt } of sampledWindowEvalDetails) {
2827
- const scriptLength = cliFiniteNumber(receipt.script_length);
2828
- const storedTo = cliString(receipt.return_stored_to);
2829
- const returned = cliValueLabel(receipt.returned);
2830
- const expected = cliValueLabel(receipt.expected_return);
2831
- const returnSummary = cliReturnSummaryLabel(receipt.return_summary);
2832
- const captured = receipt.return_captured === true ? "captured" : receipt.return_captured === false ? "not captured" : "capture unknown";
2833
- const ok = receipt.ok === false ? "failed" : "ok";
2834
- const reason = cliString(receipt.reason);
2835
- lines.push(`- ${name} window_eval: ${ok}${scriptLength === void 0 ? "" : `, script ${scriptLength} chars`}${storedTo ? `, stored ${markdownInlineCode(storedTo)}` : ""}, return ${captured}${expected === void 0 ? "" : `, expected ${markdownInlineCode(expected, 80)}`}${returnSummary ? `, summary ${markdownInlineCode(returnSummary, 140)}` : ""}${returned === void 0 ? "" : `, returned ${markdownInlineCode(returned, 80)}`}${reason ? `, reason ${markdownInlineCode(reason, 100)}` : ""}`);
2836
- }
2837
- if (windowEvalDetails.length > sampledWindowEvalDetails.length) lines.push(`- ${windowEvalDetails.length - sampledWindowEvalDetails.length} additional window_eval receipt(s) omitted.`);
2838
- const windowCallUntilGroups = viewports.map((viewport) => {
2839
- const name = cliString(viewport.name) || "viewport";
2840
- const receipts = Array.isArray(viewport.window_call_until) ? viewport.window_call_until.map(cliRecord).filter((item) => Boolean(item)) : [];
2841
- return receipts.map((receipt) => ({ name, receipt }));
2842
- });
2843
- const windowCallUntilDetails = windowCallUntilGroups.flat();
2844
- const sampledWindowCallUntilDetails = balancedSetupReceiptDetails(windowCallUntilGroups, 12);
2845
- for (const { name, receipt } of sampledWindowCallUntilDetails) {
2846
- const path2 = cliString(receipt.path) || "window_function";
2847
- const untilPath = cliString(receipt.until_path) || "until_path";
2848
- const expected = cliValueLabel(receipt.until_expected_value);
2849
- const actual = cliValueLabel(receipt.until_value);
2850
- const callCount = cliFiniteNumber(receipt.call_count);
2851
- const maxCalls = cliFiniteNumber(receipt.max_calls);
2852
- const ok = receipt.ok === false ? "failed" : "ok";
2853
- const reason = cliString(receipt.reason);
2854
- const callText = callCount === void 0 ? "" : ` in ${callCount}${maxCalls === void 0 ? "" : `/${maxCalls}`} call(s)`;
2855
- lines.push(`- ${name} window_call_until: ${ok}, ${markdownInlineCode(path2)} until ${markdownInlineCode(untilPath)}${expected === void 0 ? "" : ` == ${markdownInlineCode(expected, 80)}`}${callText}${actual === void 0 ? "" : `, observed ${markdownInlineCode(actual, 80)}`}${reason ? `, reason ${markdownInlineCode(reason, 100)}` : ""}`);
2856
- }
2857
- if (windowCallUntilDetails.length > sampledWindowCallUntilDetails.length) lines.push(`- ${windowCallUntilDetails.length - sampledWindowCallUntilDetails.length} additional window_call_until receipt(s) omitted.`);
2858
- const failedDetails = viewports.flatMap((viewport) => {
2859
- const name = cliString(viewport.name) || "viewport";
2860
- const failed = Array.isArray(viewport.failed) ? viewport.failed.map(cliRecord).filter((item) => Boolean(item)) : [];
2861
- return failed.map((failure) => ({ name, failure }));
2862
- });
2863
- for (const { name, failure } of failedDetails.slice(0, 8)) {
2864
- const action = cliString(failure.action) || "setup_action";
2865
- const selector = cliString(failure.selector);
2866
- const reason = cliString(failure.reason);
2867
- const caseInsensitiveText = cliString(failure.case_insensitive_text);
2868
- const obstruction = setupFailureObstructionSnippet(reason);
2869
- lines.push(`- failed ${name}: ${action}${selector ? ` ${markdownInlineCode(selector)}` : ""}${reason ? ` reason ${markdownInlineCode(reason)}` : ""}${caseInsensitiveText ? `; case-insensitive sample ${markdownInlineCode(caseInsensitiveText, 140)}` : ""}`);
2870
- if (obstruction) {
2871
- lines.push(`- obstruction ${name}: target ${selector ? markdownInlineCode(selector) : markdownInlineCode(action)} intercepted by ${markdownInlineCode(obstruction, 120)}`);
2872
- }
2873
- }
2874
- if (failedDetails.length > 8) lines.push(`- ${failedDetails.length - 8} additional failed setup action(s) omitted.`);
2875
- if (viewports.length > 8) lines.push(`- ${viewports.length - 8} additional viewport(s) omitted from setup summary.`);
2876
- return lines;
2877
- }
2878
- function cliRecordNumber(value, key) {
2879
- return cliFiniteNumber(value[key]);
2880
- }
2881
- function profileNetworkMockSummaryMarkdown(result) {
2882
- const networkCheck = result.checks.find((check) => check.type === "network_mocks_succeeded");
2883
- const evidence = cliRecord(networkCheck?.evidence);
2884
- if (!evidence) return [];
2885
- const hitsByLabel = cliRecord(evidence.hits_by_label) || {};
2886
- const requiredHitsByLabel = cliRecord(evidence.required_hits_by_label) || {};
2887
- const maxHitsByLabel = cliRecord(evidence.max_hits_by_label) || {};
2888
- const responseHitsByLabel = cliRecord(evidence.response_hits_by_label) || {};
2889
- const labels = Array.from(/* @__PURE__ */ new Set([
2890
- ...Object.keys(hitsByLabel),
2891
- ...Object.keys(requiredHitsByLabel),
2892
- ...Object.keys(maxHitsByLabel),
2893
- ...Object.keys(responseHitsByLabel)
2894
- ])).sort();
2895
- const mockCount = cliFiniteNumber(evidence.mock_count);
2896
- const requiredCount = cliFiniteNumber(evidence.required_count);
2897
- const hitCount = cliFiniteNumber(evidence.hit_count);
2898
- const failed = Array.isArray(evidence.failed) ? evidence.failed : [];
2899
- if (!labels.length && mockCount === void 0 && hitCount === void 0 && !failed.length) return [];
2900
- const lines = [
2901
- `- mocks: ${mockCount === void 0 ? labels.length : mockCount}; total hits: ${hitCount === void 0 ? "unknown" : hitCount}${requiredCount === void 0 ? "" : `; required mocks: ${requiredCount}`}`,
2902
- `- failed mocks: ${failed.length}`
2903
- ];
2904
- for (const label of labels.slice(0, 16)) {
2905
- const parts = [`hits ${cliRecordNumber(hitsByLabel, label) ?? 0}`];
2906
- const requiredHits = cliRecordNumber(requiredHitsByLabel, label);
2907
- const maxHits = cliRecordNumber(maxHitsByLabel, label);
2908
- if (requiredHits !== void 0) parts.push(`required ${requiredHits}`);
2909
- if (maxHits !== void 0) parts.push(`max ${maxHits}`);
2910
- lines.push(`- ${label}: ${parts.join(", ")}`);
2911
- const responseHits = cliRecord(responseHitsByLabel[label]);
2912
- const responseLabels = responseHits ? Object.keys(responseHits).sort() : [];
2913
- if (responseHits && responseLabels.length) {
2914
- const responseParts = responseLabels.slice(0, 8).map((responseLabel) => `${responseLabel} ${cliRecordNumber(responseHits, responseLabel) ?? 0}`);
2915
- const omitted = responseLabels.length > 8 ? `; ${responseLabels.length - 8} additional response label(s) omitted` : "";
2916
- lines.push(`- ${label} responses: ${responseParts.join("; ")}${omitted}`);
2917
- }
2918
- }
2919
- if (labels.length > 16) lines.push(`- ${labels.length - 16} additional network mock label(s) omitted from summary.`);
2920
- return lines;
2921
- }
2922
- function profileRouteInventorySummaryMarkdown(result) {
2923
- const routeInventoryChecks = result.checks.filter((check) => check.type === "route_inventory");
2924
- const lines = [];
2925
- for (const check of routeInventoryChecks) {
2926
- const evidence = cliRecord(check.evidence);
2927
- if (!evidence) continue;
2928
- const label = check.label || check.type;
2929
- const expectedCount = cliFiniteNumber(evidence.expected_count);
2930
- const sourceLinkCount = cliFiniteNumber(evidence.source_link_count);
2931
- const sourceUniqueLinkCount = cliFiniteNumber(evidence.source_unique_link_count);
2932
- const sourceCandidateCount = cliFiniteNumber(evidence.source_candidate_count);
2933
- const sourceCandidateUniqueLinkCount = cliFiniteNumber(evidence.source_candidate_unique_link_count);
2934
- const sourceScopeLabel = cliRouteInventorySourceScopeLabel(evidence.source_link_scope);
2935
- const directRouteCount = cliFiniteNumber(evidence.direct_route_count);
2936
- const clickthroughCount = cliFiniteNumber(evidence.clickthrough_count);
2937
- const topLevelFailures = Array.isArray(evidence.failures) ? evidence.failures.length : void 0;
2938
- const viewports = Array.isArray(evidence.viewports) ? evidence.viewports.map(cliRecord).filter((viewport) => Boolean(viewport)) : [];
2939
- const viewportFailureTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.failure_count) || 0), 0);
2940
- const failureCount = topLevelFailures === void 0 ? viewportFailureTotal : topLevelFailures;
2941
- lines.push(
2942
- `- ${label}: expected ${expectedCount ?? "unknown"}, source links ${sourceLinkCount ?? "unknown"}${sourceUniqueLinkCount === void 0 ? "" : ` (${sourceUniqueLinkCount} unique)`}, direct ${directRouteCount ?? "unknown"}, clickthrough ${clickthroughCount ?? "unknown"}, failures ${failureCount}`
2943
- );
2944
- const duplicateCount = cliFiniteNumber(evidence.duplicate_source_link_count) || 0;
2945
- const duplicateLinks = cliStringArray(evidence.duplicate_source_links);
2946
- if (duplicateCount || duplicateLinks.length) {
2947
- const duplicateText = duplicateLinks.length ? `: ${duplicateLinks.slice(0, 8).join(", ")}${duplicateLinks.length > 8 ? `, ${duplicateLinks.length - 8} more` : ""}` : "";
2948
- lines.push(`- ${label} duplicate source links: ${duplicateCount}${evidence.duplicates_allowed === true ? " allowed" : ""}${duplicateText}`);
2949
- }
2950
- const expectedRoutes = cliRouteInventoryRoutes(evidence.expected_routes);
2951
- if (expectedRoutes.length) {
2952
- lines.push(`- ${label} expected routes: ${cliRouteInventoryRouteList(expectedRoutes)}`);
2953
- }
2954
- if (sourceScopeLabel || sourceCandidateCount !== void 0) {
2955
- const candidateText = sourceCandidateCount === void 0 ? "" : `; selector candidates ${sourceCandidateCount}${sourceCandidateUniqueLinkCount === void 0 ? "" : ` (${sourceCandidateUniqueLinkCount} unique)`}`;
2956
- lines.push(`- ${label} source scope: ${sourceScopeLabel || "unknown"}${candidateText}`);
2957
- }
2958
- for (const viewport of viewports.slice(0, 8)) {
2959
- const viewportName = cliString(viewport.viewport) || cliString(viewport.name) || "viewport";
2960
- const viewportSourceLinkCount = cliFiniteNumber(viewport.source_link_count);
2961
- const viewportSourceUniqueLinkCount = cliFiniteNumber(viewport.source_unique_link_count);
2962
- const viewportSourceCandidateCount = cliFiniteNumber(viewport.source_candidate_count);
2963
- const viewportSourceCandidateUniqueLinkCount = cliFiniteNumber(viewport.source_candidate_unique_link_count);
2964
- const viewportDirectRouteCount = cliFiniteNumber(viewport.direct_route_count);
2965
- const viewportClickthroughCount = cliFiniteNumber(viewport.clickthrough_count);
2966
- const viewportFailureCount = cliFiniteNumber(viewport.failure_count) || 0;
2967
- lines.push(
2968
- `- ${label} ${viewportName}: source ${viewportSourceLinkCount ?? "unknown"}${viewportSourceUniqueLinkCount === void 0 ? "" : ` (${viewportSourceUniqueLinkCount} unique)`}${viewportSourceCandidateCount === void 0 ? "" : `, selector candidates ${viewportSourceCandidateCount}${viewportSourceCandidateUniqueLinkCount === void 0 ? "" : ` (${viewportSourceCandidateUniqueLinkCount} unique)`}`}, direct ${viewportDirectRouteCount ?? "unknown"}, clickthrough ${viewportClickthroughCount ?? "unknown"}, failures ${viewportFailureCount}`
2969
- );
2970
- }
2971
- if (viewports.length > 8) lines.push(`- ${label}: ${viewports.length - 8} additional viewport(s) omitted from route inventory summary.`);
2972
- }
2973
- return lines;
2974
- }
2975
- function profileLinkStatusSummaryMarkdown(result) {
2976
- const linkStatusChecks = result.checks.filter((check) => check.type === "link_status" || check.type === "artifact_link_status");
2977
- const lines = [];
2978
- for (const check of linkStatusChecks) {
2979
- const evidence = cliRecord(check.evidence);
2980
- if (!evidence) continue;
2981
- const label = check.label || check.type;
2982
- const selector = cliString(evidence.selector);
2983
- const viewports = Array.isArray(evidence.viewports) ? evidence.viewports.map(cliRecord).filter((viewport) => Boolean(viewport)) : [];
2984
- const totals = viewports.map((viewport) => cliFiniteNumber(viewport.total_count)).filter((count) => count !== void 0);
2985
- const discoveredTotals = viewports.map((viewport) => cliFiniteNumber(viewport.discovered_count)).filter((count) => count !== void 0);
2986
- const okTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.ok_count) || 0), 0);
2987
- const failedTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.failed_count) || 0), 0);
2988
- const truncatedTotal = viewports.filter((viewport) => viewport.truncated === true).length;
2989
- const omittedTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.omitted_result_count) || 0), 0);
2990
- const minBytes = cliFiniteNumber(evidence.min_bytes);
2991
- const allowedContentTypes = Array.isArray(evidence.allowed_content_types) ? evidence.allowed_content_types.map(cliString).filter((value) => Boolean(value)) : [];
2992
- const countText = totals.length ? totals.join("/") : "unknown";
2993
- const discoveredText = discoveredTotals.length && discoveredTotals.some((count, index) => count !== totals[index]) ? `, discovered ${discoveredTotals.join("/")}` : "";
2994
- lines.push(
2995
- `- ${label}${selector ? ` ${markdownInlineCode(selector)}` : ""}: probed links ${countText}${discoveredText}, ok ${okTotal}, failures ${failedTotal}${omittedTotal ? `, compacted ${omittedTotal} result row(s)` : ""}${truncatedTotal ? `, truncated viewports ${truncatedTotal}` : ""}${minBytes !== void 0 ? `, min bytes ${minBytes}` : ""}${allowedContentTypes.length ? `, content types ${allowedContentTypes.map((value) => markdownInlineCode(value)).join(", ")}` : ""}`
2996
- );
2997
- }
2998
- return lines;
2999
- }
3000
- function profileHttpStatusAssertionCount(viewports, field, expected, passValue) {
3001
- if (!expected.length || !viewports.length) return void 0;
3002
- let passed = 0;
3003
- for (const viewport of viewports) {
3004
- const observed = cliRecord(viewport[field]);
3005
- for (const value of expected) {
3006
- if (observed?.[value] === passValue) passed += 1;
3007
- }
3008
- }
3009
- return { passed, total: expected.length * viewports.length };
3010
- }
3011
- function profileHttpStatusAssertionKeys(evidence, viewports, field) {
3012
- const explicit = cliStringArray(evidence[field]);
3013
- if (explicit.length) return explicit;
3014
- const keys = /* @__PURE__ */ new Set();
3015
- for (const viewport of viewports) {
3016
- const observed = cliRecord(viewport[field]);
3017
- if (!observed) continue;
3018
- for (const key of Object.keys(observed)) {
3019
- if (key) keys.add(key);
3020
- }
3021
- }
3022
- return [...keys];
3023
- }
3024
- function profileHttpStatusJsonAssertionCount(viewports) {
3025
- if (!viewports.length) return void 0;
3026
- let passed = 0;
3027
- let total = 0;
3028
- for (const viewport of viewports) {
3029
- if (!Array.isArray(viewport.body_json_assertions)) continue;
3030
- for (const assertion of viewport.body_json_assertions) {
3031
- const record = cliRecord(assertion);
3032
- if (!record) continue;
3033
- total += 1;
3034
- if (record.ok === true) passed += 1;
3035
- }
3036
- }
3037
- return total ? { passed, total } : void 0;
3038
- }
3039
- function profileHttpStatusSummaryMarkdown(result) {
3040
- const httpStatusChecks = result.checks.filter((check) => check.type === "http_status");
3041
- const lines = [];
3042
- for (const check of httpStatusChecks) {
3043
- const evidence = cliRecord(check.evidence);
3044
- if (!evidence) continue;
3045
- const label = check.label || check.type;
3046
- const url = cliString(evidence.url);
3047
- const method = cliString(evidence.method) || "GET";
3048
- const viewports = Array.isArray(evidence.viewports) ? evidence.viewports.map(cliRecord).filter((viewport) => Boolean(viewport)) : [];
3049
- const statuses = viewports.map((viewport) => cliFiniteNumber(viewport.status)).map((status) => status === void 0 ? "error" : String(status));
3050
- const failedTotal = Array.isArray(evidence.failures) ? evidence.failures.length : 0;
3051
- const bodyContains = profileHttpStatusAssertionCount(
3052
- viewports,
3053
- "body_contains",
3054
- profileHttpStatusAssertionKeys(evidence, viewports, "body_contains"),
3055
- true
3056
- );
3057
- const bodyNotContains = profileHttpStatusAssertionCount(
3058
- viewports,
3059
- "body_not_contains",
3060
- profileHttpStatusAssertionKeys(evidence, viewports, "body_not_contains"),
3061
- false
3062
- );
3063
- const bodyNotPatterns = profileHttpStatusAssertionCount(
3064
- viewports,
3065
- "body_not_patterns",
3066
- profileHttpStatusAssertionKeys(evidence, viewports, "body_not_patterns"),
3067
- false
3068
- );
3069
- const bodyJsonAssertions = profileHttpStatusJsonAssertionCount(viewports);
3070
- const bodyParts = [
3071
- bodyContains ? `body_contains ${bodyContains.passed}/${bodyContains.total}` : "",
3072
- bodyNotContains ? `body_not_contains clean ${bodyNotContains.passed}/${bodyNotContains.total}` : "",
3073
- bodyNotPatterns ? `body_not_patterns clean ${bodyNotPatterns.passed}/${bodyNotPatterns.total}` : "",
3074
- bodyJsonAssertions ? `body_json_assertions ${bodyJsonAssertions.passed}/${bodyJsonAssertions.total}` : ""
3075
- ].filter(Boolean);
3076
- lines.push(
3077
- `- ${label}: ${method}${url ? ` ${markdownInlineCode(url)}` : ""}, statuses ${statuses.length ? statuses.join("/") : "unknown"}${bodyParts.length ? `, ${bodyParts.join(", ")}` : ""}, failures ${failedTotal}`
3078
- );
3079
- }
3080
- return lines;
3081
- }
3082
- function writeProfileOutput(outputDir, result) {
3083
- if (!outputDir) return;
3084
- mkdirSync(outputDir, { recursive: true });
3085
- writeFileSync(path.join(outputDir, "profile-result.json"), `${JSON.stringify(result, null, 2)}
3086
- `);
3087
- writeFileSync(path.join(outputDir, "summary.md"), profileResultMarkdown(result));
3088
- if (result.evidence) writeFileSync(path.join(outputDir, "proof.json"), `${JSON.stringify(result, null, 2)}
3089
- `);
3090
- if (result.evidence?.console) writeFileSync(path.join(outputDir, "console.json"), `${JSON.stringify(result.evidence.console, null, 2)}
3091
- `);
3092
- if (result.evidence?.dom_summary) writeFileSync(path.join(outputDir, "dom-summary.json"), `${JSON.stringify(result.evidence.dom_summary, null, 2)}
3093
- `);
3094
- }
3095
- function writeRiddleJobReceipt(outputDir, input) {
3096
- if (!outputDir) return;
3097
- mkdirSync(outputDir, { recursive: true });
3098
- writeFileSync(path.join(outputDir, "riddle-job.json"), `${JSON.stringify({
3099
- version: "riddle-proof.riddle-job-receipt.v1",
3100
- profile_name: input.profile.name,
3101
- job_id: input.jobId,
3102
- target_url: input.targetUrl,
3103
- viewport: input.viewport || null,
3104
- captured_at: (/* @__PURE__ */ new Date()).toISOString(),
3105
- created: input.created || null,
3106
- recovery_command: `riddle-proof-loop run-profile recover --profile <profile> --job ${input.jobId} --output-dir ${outputDir}`
3107
- }, null, 2)}
3108
- `);
3109
- }
3110
- async function readArtifactJson(artifact) {
3111
- const target = artifact.url || artifact.path;
3112
- if (!target) return void 0;
3113
- try {
3114
- const raw = artifact.url ? await (await fetch(artifact.url)).text() : existsSync(target) ? readFileSync(target, "utf-8") : "";
3115
- if (!raw.trim()) return void 0;
3116
- const parsed = JSON.parse(raw);
3117
- return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : void 0;
3118
- } catch {
3119
- return void 0;
3120
- }
3121
- }
3122
- async function profileResultFromRiddleArtifacts(profile, artifacts, fallbackInputs) {
3123
- for (const input of fallbackInputs) {
3124
- const result = extractRiddleProofProfileResult(input);
3125
- if (result) return withProfileMetadata(profile, result);
3126
- }
3127
- const proofArtifacts = artifacts.filter((artifact) => /(^|\/)proof\.json(?:\.json)?$/i.test(artifact.name || artifact.url || artifact.path || "")).sort((left, right) => {
3128
- const leftName = left.name || left.url || left.path || "";
3129
- const rightName = right.name || right.url || right.path || "";
3130
- return Number(/proof\.json\.json$/i.test(rightName)) - Number(/proof\.json\.json$/i.test(leftName));
3131
- });
3132
- for (const artifact of proofArtifacts) {
3133
- const parsed = await readArtifactJson(artifact);
3134
- const result = extractRiddleProofProfileResult(parsed);
3135
- if (result) return withProfileMetadata(profile, result);
3136
- }
3137
- const evidenceArtifacts = artifacts.filter((artifact) => /profile-evidence|evidence\.json/i.test(artifact.name || artifact.url || artifact.path || ""));
3138
- for (const artifact of evidenceArtifacts) {
3139
- const parsed = await readArtifactJson(artifact);
3140
- if (parsed?.version === "riddle-proof.profile-evidence.v1") {
3141
- return assessRiddleProofProfileEvidence(profile, parsed, { artifacts });
3142
- }
3143
- }
3144
- return void 0;
3145
- }
3146
- function withProfileMetadata(profile, result) {
3147
- if (!profile.metadata || !Object.keys(profile.metadata).length) return result;
3148
- return {
3149
- ...result,
3150
- metadata: {
3151
- ...profile.metadata,
3152
- ...result.metadata || {}
3153
- }
3154
- };
3155
- }
3156
- function withRiddleMetadata(result, input) {
3157
- const poll = input.poll;
3158
- const staleJobIds = input.staleJobIds?.filter(Boolean);
3159
- return {
3160
- ...result,
3161
- riddle: {
3162
- ...result.riddle || {},
3163
- job_id: input.job_id || result.riddle?.job_id,
3164
- status: input.status ?? result.riddle?.status,
3165
- terminal: input.terminal ?? result.riddle?.terminal,
3166
- created_at: poll?.created_at ?? result.riddle?.created_at,
3167
- submitted_at: poll?.submitted_at ?? result.riddle?.submitted_at,
3168
- completed_at: poll?.completed_at ?? result.riddle?.completed_at,
3169
- queue_elapsed_ms: poll?.queue_elapsed_ms ?? result.riddle?.queue_elapsed_ms,
3170
- pre_submission_elapsed_ms: poll?.pre_submission_elapsed_ms ?? result.riddle?.pre_submission_elapsed_ms,
3171
- elapsed_ms: poll?.elapsed_ms ?? result.riddle?.elapsed_ms,
3172
- attempt: poll?.attempt ?? result.riddle?.attempt,
3173
- attempts: poll?.attempts ?? result.riddle?.attempts,
3174
- timed_out: poll?.timed_out ?? result.riddle?.timed_out,
3175
- retry_count: input.retryCount ?? result.riddle?.retry_count,
3176
- stale_job_ids: staleJobIds?.length ? staleJobIds : result.riddle?.stale_job_ids,
3177
- artifact_recovery: input.artifactRecovery ?? result.riddle?.artifact_recovery
3178
- },
3179
- artifacts: {
3180
- ...result.artifacts,
3181
- riddle_artifacts: input.artifacts || result.artifacts.riddle_artifacts
3182
- }
3183
- };
3184
- }
3185
- function riddleArtifactsPayloadStatus(payload) {
3186
- const record = cliRecord(payload);
3187
- return cliString(record?.status) ?? cliString(cliRecord(record?.job)?.status);
3188
- }
3189
- async function recoverProfileResultFromRiddleArtifacts(profile, input) {
3190
- if (input.poll.poll?.timed_out !== true) return void 0;
3191
- const attempts = Math.max(1, Math.floor(input.attempts ?? 3));
3192
- const intervalMs = Math.max(0, Math.floor(input.intervalMs ?? 0));
3193
- for (let attempt = 0; attempt < attempts; attempt += 1) {
3194
- let artifactPayload;
3195
- try {
3196
- artifactPayload = await input.client.requestJson(`/v1/jobs/${input.jobId}/artifacts`);
3197
- } catch {
3198
- artifactPayload = {};
3199
- }
3200
- const artifacts = collectRiddleProfileArtifactRefs(artifactPayload);
3201
- if (artifacts.length) {
3202
- const artifactStatus = riddleArtifactsPayloadStatus(artifactPayload);
3203
- const terminal = artifactStatus ? isTerminalRiddleJobStatus(artifactStatus) : true;
3204
- const recoveredPoll = input.poll.poll ? {
3205
- ...input.poll.poll,
3206
- status: artifactStatus ?? input.poll.poll.status,
3207
- terminal
3208
- } : void 0;
3209
- const artifactResult = await profileResultFromRiddleArtifacts(profile, artifacts, [artifactPayload, input.poll.job]);
3210
- if (artifactResult) {
3211
- return withRiddleMetadata(artifactResult, {
3212
- job_id: input.jobId,
3213
- status: artifactStatus ?? input.poll.status,
3214
- terminal,
3215
- poll: recoveredPoll,
3216
- artifacts,
3217
- artifactRecovery: true
3218
- });
3219
- }
3220
- if (terminal) {
3221
- return createRiddleProofProfileInsufficientResult({
3222
- profile,
3223
- runner: input.runner,
3224
- error: `Riddle job ${input.jobId} timed out in status ${input.poll.status || "unknown"}, but artifacts were recovered without a proof result.`,
3225
- riddle: {
3226
- ...riddleMetadataFromPoll(input.jobId, input.poll),
3227
- status: artifactStatus ?? input.poll.status,
3228
- terminal,
3229
- artifact_recovery: true
3230
- },
3231
- artifacts
3232
- });
3233
- }
3234
- }
3235
- if (attempt + 1 < attempts && intervalMs > 0) {
3236
- await new Promise((resolve) => setTimeout(resolve, intervalMs));
3237
- }
3238
- }
3239
- return void 0;
3240
- }
3241
- function riddleMetadataFromPoll(jobId, poll) {
3242
- return {
3243
- job_id: jobId,
3244
- status: poll.status,
3245
- terminal: poll.terminal,
3246
- created_at: poll.poll?.created_at,
3247
- submitted_at: poll.poll?.submitted_at,
3248
- completed_at: poll.poll?.completed_at,
3249
- queue_elapsed_ms: poll.poll?.queue_elapsed_ms,
3250
- pre_submission_elapsed_ms: poll.poll?.pre_submission_elapsed_ms,
3251
- elapsed_ms: poll.poll?.elapsed_ms,
3252
- attempt: poll.poll?.attempt,
3253
- attempts: poll.poll?.attempts,
3254
- timed_out: poll.poll?.timed_out
3255
- };
3256
- }
3257
- function profileUnsubmittedRetryTimeoutMs(options) {
3258
- return Math.max(0, optionInteger(
3259
- options,
3260
- DEFAULT_PROFILE_UNSUBMITTED_RETRY_TIMEOUT_MS,
3261
- "unsubmittedTimeoutMs",
3262
- "unsubmittedJobTimeoutMs",
3263
- "submitTimeoutMs"
3264
- ));
3265
- }
3266
- function profileUnsubmittedRetryLimit(options) {
3267
- return Math.max(0, optionInteger(
3268
- options,
3269
- DEFAULT_PROFILE_UNSUBMITTED_RETRIES,
3270
- "unsubmittedRetries",
3271
- "unsubmittedJobRetries",
3272
- "submitRetries"
3273
- ));
3274
- }
3275
- function shouldRetryUnsubmittedRiddleJob(poll) {
3276
- return poll.terminal !== true && poll.poll?.unsubmitted_timeout === true && !poll.poll.created_at && !poll.poll.submitted_at;
3277
- }
3278
- function riddlePollOptionsForProfile(options) {
3279
- return {
3280
- wait: true,
3281
- attempts: optionNumber(options, "pollAttempts", "attempts"),
3282
- intervalMs: optionNumber(options, "intervalMs"),
3283
- progressEveryMs: optionNumber(options, "progressEveryMs"),
3284
- unsubmittedTimeoutMs: profileUnsubmittedRetryTimeoutMs(options),
3285
- onProgress: options.quiet !== true ? (snapshot) => {
3286
- process.stderr.write(`${riddlePollProgressLine(snapshot)}
3287
- `);
3288
- } : void 0
3289
- };
3290
- }
3291
- function profileItemAppliesToSplitViewport(item, viewport) {
3292
- if (!item.viewports?.length) return true;
3293
- return Boolean(viewport.name && item.viewports.includes(viewport.name));
3294
- }
3295
- function profileForSplitViewport(profile, viewport) {
3296
- const setupActions = profile.target.setup_actions?.filter((action) => profileItemAppliesToSplitViewport(action, viewport));
3297
- return {
3298
- ...profile,
3299
- name: `${profile.name}-${viewport.name || `${viewport.width}x${viewport.height}`}`,
3300
- checks: profile.checks.filter((check) => profileItemAppliesToSplitViewport(check, viewport)),
3301
- target: {
3302
- ...profile.target,
3303
- viewports: [viewport],
3304
- ...setupActions ? { setup_actions: setupActions } : {}
3305
- },
3306
- metadata: {
3307
- ...profile.metadata || {},
3308
- split_parent_profile: profile.name,
3309
- split_viewport: viewport.name
3310
- }
3311
- };
3312
- }
3313
- function profileItemAppliesToAnySelectedViewport(item, viewports) {
3314
- if (!item.viewports?.length) return true;
3315
- const names = new Set(viewports.map((viewport) => viewport.name).filter(Boolean));
3316
- return item.viewports.some((name) => names.has(name));
3317
- }
3318
- function profileForSelectedViewports(profile, viewports) {
3319
- const suffix = viewports.map((viewport) => viewport.name || `${viewport.width}x${viewport.height}`).join("-");
3320
- const setupActions = profile.target.setup_actions?.filter((action) => profileItemAppliesToAnySelectedViewport(action, viewports));
3321
- return {
3322
- ...profile,
3323
- name: `${profile.name}-${suffix}`,
3324
- checks: profile.checks.filter((check) => profileItemAppliesToAnySelectedViewport(check, viewports)),
3325
- target: {
3326
- ...profile.target,
3327
- viewports,
3328
- ...setupActions ? { setup_actions: setupActions } : {}
3329
- },
3330
- metadata: {
3331
- ...profile.metadata || {},
3332
- selected_parent_profile: profile.name,
3333
- selected_viewports: viewports.map((viewport) => viewport.name || `${viewport.width}x${viewport.height}`)
3334
- }
3335
- };
3336
- }
3337
- function profileWithSelectedViewportNamesForCli(profile, options) {
3338
- const names = runProfileViewportNamesOption(options);
3339
- if (!names.length) return profile;
3340
- const requested = new Set(names);
3341
- const viewports = profile.target.viewports.filter((viewport) => viewport.name && requested.has(viewport.name));
3342
- const matched = new Set(viewports.map((viewport) => viewport.name).filter(Boolean));
3343
- const missing = names.filter((name) => !matched.has(name));
3344
- if (missing.length) {
3345
- const available = profile.target.viewports.map((viewport) => viewport.name).filter(Boolean).join(", ") || "none";
3346
- throw new Error(`Unknown --viewport-name ${missing.join(", ")}. Available viewport names: ${available}.`);
3347
- }
3348
- return profileForSelectedViewports(profile, viewports);
3349
- }
3350
- function safeProfileOutputSegment(value) {
3351
- const safe = value.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
3352
- return safe || "viewport";
3353
- }
3354
- function splitViewportOutputDir(outputDir, viewportName, seen) {
3355
- const base = safeProfileOutputSegment(viewportName);
3356
- const count = seen.get(base) || 0;
3357
- seen.set(base, count + 1);
3358
- return path.join(outputDir, count ? `${base}-${count + 1}` : base);
3359
- }
3360
- function profileResultPathFromInput(inputPath) {
3361
- if (!existsSync(inputPath)) throw new Error(`Profile aggregate input path does not exist: ${inputPath}`);
3362
- const stat = statSync(inputPath);
3363
- if (stat.isFile()) return [inputPath];
3364
- if (!stat.isDirectory()) throw new Error(`Profile aggregate input path must be a file or directory: ${inputPath}`);
3365
- const childProfileResults = readdirSync(inputPath, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => path.join(inputPath, entry.name, "profile-result.json")).filter((candidate) => existsSync(candidate));
3366
- if (childProfileResults.length) return childProfileResults;
3367
- const directProfileResult = path.join(inputPath, "profile-result.json");
3368
- if (existsSync(directProfileResult)) return [directProfileResult];
3369
- throw new Error(`Profile aggregate input directory has no child profile-result.json files: ${inputPath}`);
3370
- }
3371
- function runProfileAggregateInputPathsOption(options) {
3372
- const rawInputs = [
3373
- optionString(options, "input"),
3374
- optionString(options, "inputs"),
3375
- optionString(options, "inputFile"),
3376
- optionString(options, "inputFiles")
3377
- ].filter((value) => Boolean(value));
3378
- const explicitInputs = rawInputs.flatMap((raw) => raw.split(",").map((part) => part.trim()).filter(Boolean));
3379
- const inputDir = optionString(options, "inputDir") ?? optionString(options, "resultsDir") ?? optionString(options, "runDir");
3380
- const discoveredInputs = inputDir ? profileResultPathFromInput(inputDir) : [];
3381
- const paths = [...explicitInputs.flatMap(profileResultPathFromInput), ...discoveredInputs];
3382
- const uniquePaths = [...new Set(paths.map((inputPath) => path.resolve(inputPath)))];
3383
- if (!uniquePaths.length) {
3384
- throw new Error("run-profile aggregate requires --input-dir <dir> or --inputs <path[,path...]>.");
3385
- }
3386
- return uniquePaths;
3387
- }
3388
- function readProfileResultForAggregate(resultPath) {
3389
- const parsed = readJsonValue(resultPath, resultPath);
3390
- if (parsed.version !== "riddle-proof.profile-result.v1" || !Array.isArray(parsed.checks)) {
3391
- throw new Error(`Profile aggregate input is not a riddle-proof.profile-result.v1 result: ${resultPath}`);
3392
- }
3393
- return parsed;
3394
- }
3395
- function profileResultIsAggregateParent(result) {
3396
- const mode = cliString(cliRecord(result.riddle)?.mode);
3397
- return (mode === "split-viewports" || mode === "named-viewport-aggregate") && (result.evidence?.viewports?.length || 0) > 1;
3398
- }
3399
- function aggregateProfileResultViewportName(result) {
3400
- const evidenceViewports = result.evidence?.viewports || [];
3401
- if (evidenceViewports.length === 1) return evidenceViewports[0].name;
3402
- const metadata = cliRecord(result.metadata);
3403
- const splitViewport = cliString(metadata?.split_viewport);
3404
- if (splitViewport) return splitViewport;
3405
- const selectedViewports = Array.isArray(metadata?.selected_viewports) ? metadata.selected_viewports.map(cliString).filter((name) => Boolean(name)) : [];
3406
- if (selectedViewports.length === 1) return selectedViewports[0];
3407
- return void 0;
3408
- }
3409
- function aggregateProfileResultViewport(profile, result, resultPath) {
3410
- const viewportName = aggregateProfileResultViewportName(result);
3411
- const parentViewport = viewportName ? profile.target.viewports.find((viewport) => viewport.name === viewportName) : void 0;
3412
- if (parentViewport) return parentViewport;
3413
- const evidenceViewport = result.evidence?.viewports?.length === 1 ? result.evidence.viewports[0] : void 0;
3414
- if (evidenceViewport && typeof evidenceViewport.name === "string" && typeof evidenceViewport.width === "number" && Number.isFinite(evidenceViewport.width) && typeof evidenceViewport.height === "number" && Number.isFinite(evidenceViewport.height)) {
3415
- return {
3416
- name: evidenceViewport.name,
3417
- width: evidenceViewport.width,
3418
- height: evidenceViewport.height
3419
- };
3420
- }
3421
- throw new Error(`Profile aggregate input must be a single named viewport result or include selected viewport metadata: ${resultPath}`);
3422
- }
3423
- function sortAggregateChildRuns(profile, childRuns) {
3424
- const viewportOrder = new Map(profile.target.viewports.map((viewport, index) => [viewport.name, index]));
3425
- return [...childRuns].sort((a, b) => {
3426
- const aIndex = viewportOrder.get(a.viewport.name) ?? Number.MAX_SAFE_INTEGER;
3427
- const bIndex = viewportOrder.get(b.viewport.name) ?? Number.MAX_SAFE_INTEGER;
3428
- if (aIndex !== bIndex) return aIndex - bIndex;
3429
- return a.viewport.name.localeCompare(b.viewport.name);
3430
- });
3431
- }
3432
- function splitViewportArtifactRefs(input) {
3433
- return (input.result.artifacts.riddle_artifacts || []).map((artifact) => ({
3434
- ...artifact,
3435
- name: `${safeProfileOutputSegment(input.viewport.name)}/${artifact.name || artifact.kind || "artifact"}`
3436
- }));
3437
- }
3438
- function sumDefinedNumbers(values) {
3439
- const numbers = values.filter((value) => typeof value === "number" && Number.isFinite(value));
3440
- return numbers.length ? numbers.reduce((sum, value) => sum + value, 0) : void 0;
3441
- }
3442
- function splitViewportRiddleMetadata(childRuns, mode = "split-viewports") {
3443
- const splitJobs = childRuns.map(({ viewport, result }) => ({
3444
- viewport: viewport.name,
3445
- job_id: result.riddle?.job_id,
3446
- status: result.riddle?.status,
3447
- terminal: result.riddle?.terminal,
3448
- queue_elapsed_ms: result.riddle?.queue_elapsed_ms,
3449
- pre_submission_elapsed_ms: result.riddle?.pre_submission_elapsed_ms,
3450
- elapsed_ms: result.riddle?.elapsed_ms,
3451
- attempt: result.riddle?.attempt,
3452
- attempts: result.riddle?.attempts,
3453
- timed_out: result.riddle?.timed_out,
3454
- retry_count: result.riddle?.retry_count,
3455
- stale_job_ids: result.riddle?.stale_job_ids,
3456
- artifact_recovery: result.riddle?.artifact_recovery
3457
- }));
3458
- return {
3459
- mode,
3460
- job_count: childRuns.length,
3461
- status: mode,
3462
- terminal: childRuns.every(({ result }) => result.riddle?.terminal !== false),
3463
- artifact_recovery: childRuns.some(({ result }) => result.riddle?.artifact_recovery === true),
3464
- queue_elapsed_ms: sumDefinedNumbers(splitJobs.map((job) => job.queue_elapsed_ms)),
3465
- pre_submission_elapsed_ms: sumDefinedNumbers(splitJobs.map((job) => job.pre_submission_elapsed_ms)),
3466
- elapsed_ms: sumDefinedNumbers(splitJobs.map((job) => job.elapsed_ms)),
3467
- retry_count: splitJobs.reduce((sum, job) => sum + (typeof job.retry_count === "number" && Number.isFinite(job.retry_count) ? job.retry_count : 0), 0),
3468
- stale_job_ids: splitJobs.flatMap((job) => Array.isArray(job.stale_job_ids) ? job.stale_job_ids : []),
3469
- split_jobs: splitJobs
3470
- };
3471
- }
3472
- function latestCapturedAt(evidences) {
3473
- let latest = "";
3474
- let latestMs = Number.NEGATIVE_INFINITY;
3475
- for (const evidence of evidences) {
3476
- const parsed = Date.parse(evidence.captured_at);
3477
- if (Number.isFinite(parsed) && parsed >= latestMs) {
3478
- latest = evidence.captured_at;
3479
- latestMs = parsed;
3480
- }
3481
- }
3482
- return latest || (/* @__PURE__ */ new Date()).toISOString();
3483
- }
3484
- function splitViewportDomSummary(profile, childRuns, evidence) {
3485
- return {
3486
- split_viewports: true,
3487
- expected_viewport_count: profile.target.viewports.length,
3488
- viewport_count: evidence.viewports.length,
3489
- child_result_count: childRuns.length,
3490
- child_statuses: childRuns.map(({ viewport, result }) => ({
3491
- viewport: viewport.name,
3492
- profile_name: result.profile_name,
3493
- status: result.status,
3494
- job_id: result.riddle?.job_id || null
3495
- })),
3496
- routes: evidence.viewports.map((viewport) => ({
3497
- viewport: viewport.name,
3498
- requested: viewport.route.requested,
3499
- observed: viewport.route.observed,
3500
- matched: viewport.route.matched,
3501
- http_status: viewport.route.http_status ?? null
3502
- })),
3503
- titles: evidence.viewports.map((viewport) => viewport.title).filter((title) => Boolean(title)),
3504
- overflow_px: evidence.viewports.map((viewport) => viewport.overflow_px ?? null),
3505
- bounds_overflow_px: evidence.viewports.map((viewport) => viewport.bounds_overflow_px ?? null),
3506
- overflow_offender_counts: evidence.viewports.map((viewport) => (viewport.overflow_offenders || []).length),
3507
- console_event_count: evidence.console.events.length,
3508
- console_fatal_count: evidence.console.fatal_count,
3509
- page_error_count: evidence.page_errors.length,
3510
- network_mock_count: (profile.target.network_mocks || []).length,
3511
- network_mock_hit_count: (evidence.network_mocks || []).filter((event) => event.ok !== false).length
3512
- };
3513
- }
3514
- function aggregateSplitViewportEvidence(profile, childRuns) {
3515
- const evidences = childRuns.map(({ result }) => result.evidence).filter((evidence2) => Boolean(evidence2));
3516
- const viewports = evidences.flatMap((evidence2) => evidence2.viewports || []);
3517
- const consoleEvents = evidences.flatMap((evidence2) => evidence2.console?.events || []);
3518
- const pageErrors = evidences.flatMap((evidence2) => evidence2.page_errors || []);
3519
- const networkMocks = evidences.flatMap((evidence2) => evidence2.network_mocks || []);
3520
- const evidence = {
3521
- version: RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION,
3522
- profile_name: profile.name,
3523
- target_url: resolveRiddleProofProfileTargetUrl(profile),
3524
- baseline_policy: profile.baseline_policy,
3525
- captured_at: latestCapturedAt(evidences),
3526
- viewports,
3527
- console: {
3528
- events: consoleEvents,
3529
- fatal_count: evidences.reduce((sum, item) => sum + (item.console?.fatal_count || 0), 0)
3530
- },
3531
- page_errors: pageErrors,
3532
- network_mocks: networkMocks.length ? networkMocks : void 0
3533
- };
3534
- evidence.dom_summary = splitViewportDomSummary(profile, childRuns, evidence);
3535
- return evidence;
3536
- }
3537
- function splitViewportBlockedMessage(childRuns) {
3538
- const blocked = childRuns.filter(({ result }) => !result.evidence || result.status === "environment_blocked" || result.status === "configuration_error").map(({ viewport, result }) => `${viewport.name}: ${result.status}${result.error ? ` (${result.error})` : ""}`);
3539
- return `Split viewport run did not produce reliable evidence for ${blocked.join("; ")}.`;
3540
- }
3541
- function withSplitViewportWarnings(profile, result) {
3542
- const warnings = [];
3543
- if (profile.target.network_mocks?.length) {
3544
- warnings.push("Split viewport mode runs each viewport in a separate Riddle job; global network mock sequencing is assessed from aggregated events.");
3545
- }
3546
- if (!warnings.length) return result;
3547
- return {
3548
- ...result,
3549
- warnings: [.../* @__PURE__ */ new Set([...result.warnings || [], ...warnings])]
3550
- };
3551
- }
3552
- function withSplitViewportChildStatusCheck(profile, result, childRuns) {
3553
- const nonPassed = childRuns.filter(({ result: childResult }) => childResult.status !== "passed");
3554
- if (!nonPassed.length) return result;
3555
- const hasProductRegression = nonPassed.some(({ result: childResult }) => childResult.status === "product_regression");
3556
- const status = hasProductRegression ? "product_regression" : "needs_human_review";
3557
- const checkStatus = hasProductRegression ? "failed" : "needs_human_review";
3558
- const childStatuses = childRuns.map(({ viewport, result: childResult }) => ({
3559
- viewport: viewport.name,
3560
- profile_name: childResult.profile_name,
3561
- status: childResult.status,
3562
- job_id: childResult.riddle?.job_id || null
3563
- }));
3564
- const failedLabels = nonPassed.map(({ viewport, result: childResult }) => `${viewport.name}: ${childResult.status}`).join("; ");
3565
- const checks = [
3566
- {
3567
- type: "split_viewport_children",
3568
- label: "split_viewport_children",
3569
- status: checkStatus,
3570
- evidence: { child_statuses: childStatuses },
3571
- message: `Split viewport child run(s) did not all pass: ${failedLabels}.`
3572
- },
3573
- ...result.checks
3574
- ];
3575
- const viewportCount = result.evidence?.viewports?.length || profile.target.viewports.length;
3576
- const failedChecks = checks.filter((check) => check.status === "failed").length;
3577
- const summary = status === "product_regression" ? `${profile.name} failed ${failedChecks} product invariant(s) across ${viewportCount} viewport(s).` : `${profile.name} collected split viewport artifacts but needs human review.`;
3578
- return { ...result, status, checks, summary };
3579
- }
3580
- function profileRiddleJobCountForCli(profile, options) {
3581
- return runProfileSplitViewportsOption(options) && profile.target.viewports.length > 1 ? profile.target.viewports.length : 1;
3582
- }
3583
- function riddleBalanceAvailableSeconds(balance) {
3584
- const availableSeconds = cliFiniteNumber(balance.available_seconds);
3585
- if (availableSeconds !== void 0) return availableSeconds;
3586
- const totalSeconds = cliFiniteNumber(balance.total_seconds);
3587
- const reservedSeconds = cliFiniteNumber(balance.reserved_seconds) ?? 0;
3588
- return totalSeconds === void 0 ? void 0 : totalSeconds - reservedSeconds;
3589
- }
3590
- function riddleBalancePreflightMetadata(profile, options) {
3591
- const split = runProfileSplitViewportsOption(options) && profile.target.viewports.length > 1;
3592
- if (!split) return { status: "balance_preflight_blocked", terminal: false };
3593
- return {
3594
- mode: "split-viewports",
3595
- job_count: profile.target.viewports.length,
3596
- status: "balance_preflight_blocked",
3597
- terminal: false,
3598
- split_jobs: profile.target.viewports.map((viewport) => ({ viewport: viewport.name }))
3599
- };
3600
- }
3601
- function apiKeySourceBlockerMetadata(client) {
3602
- try {
3603
- const source = client.apiKeySource();
3604
- return {
3605
- api_key_source: source.source,
3606
- ...source.file ? { api_key_file: source.file } : {}
3607
- };
3608
- } catch {
3609
- return {};
3610
- }
3611
- }
3612
- function riddleApiErrorBlockerMetadata(error) {
3613
- const record = error && typeof error === "object" ? error : void 0;
3614
- const status = cliFiniteNumber(record?.status);
3615
- const pathValue = cliString(record?.path);
3616
- const body = cliString(record?.body);
3617
- return {
3618
- ...pathValue ? { endpoint: pathValue } : {},
3619
- ...status === void 0 ? {} : { http_status: status },
3620
- ...body ? { error: body } : {}
3621
- };
3622
- }
3623
- async function preflightRiddleProfileBalanceForCli(profile, options, input) {
3624
- if (!runProfileBalancePreflightOption(options)) return void 0;
3625
- let balance;
3626
- try {
3627
- balance = await input.client.getBalance();
3628
- } catch (error) {
3629
- return createRiddleProofProfileEnvironmentBlockedResult({
3630
- profile,
3631
- runner: input.runner,
3632
- error,
3633
- environmentBlocker: {
3634
- source: "riddle_api",
3635
- endpoint: "/v1/balance",
3636
- reason: "balance_preflight_failed",
3637
- balance_preflight: true,
3638
- ...riddleApiErrorBlockerMetadata(error),
3639
- ...apiKeySourceBlockerMetadata(input.client)
3640
- },
3641
- riddle: riddleBalancePreflightMetadata(profile, options)
3642
- });
3643
- }
3644
- const jobCount = profileRiddleJobCountForCli(profile, options);
3645
- const requiredSeconds = jobCount * RIDDLE_PROFILE_BALANCE_PREFLIGHT_MIN_SECONDS_PER_JOB;
3646
- const availableSeconds = riddleBalanceAvailableSeconds(balance);
3647
- if (availableSeconds === void 0 || availableSeconds >= requiredSeconds) return void 0;
3648
- const reservedSeconds = cliFiniteNumber(balance.reserved_seconds);
3649
- const totalSeconds = cliFiniteNumber(balance.total_seconds);
3650
- const holdsCount = cliFiniteNumber(balance.holds_count);
3651
- return createRiddleProofProfileEnvironmentBlockedResult({
3652
- profile,
3653
- runner: input.runner,
3654
- error: `Riddle balance preflight failed: ${availableSeconds}s available for ${jobCount} intended hosted job(s), minimum ${requiredSeconds}s required.`,
3655
- environmentBlocker: {
3656
- source: "riddle_api",
3657
- endpoint: "/v1/balance",
3658
- reason: "insufficient_balance",
3659
- error: "Insufficient available balance",
3660
- balance_preflight: true,
3661
- job_count: jobCount,
3662
- seconds_per_job: RIDDLE_PROFILE_BALANCE_PREFLIGHT_MIN_SECONDS_PER_JOB,
3663
- required_seconds: requiredSeconds,
3664
- available_seconds: availableSeconds,
3665
- deficit_seconds: requiredSeconds - availableSeconds,
3666
- ...reservedSeconds === void 0 ? {} : { reserved_seconds: reservedSeconds },
3667
- ...totalSeconds === void 0 ? {} : { total_seconds: totalSeconds },
3668
- ...holdsCount === void 0 ? {} : { holds_count: holdsCount },
3669
- ...apiKeySourceBlockerMetadata(input.client)
3670
- },
3671
- riddle: riddleBalancePreflightMetadata(profile, options)
3672
- });
3673
- }
3674
- async function runSingleRiddleProfileForCli(profile, options, input) {
3675
- const { client, runner } = input;
3676
- const targetUrl = resolveRiddleProofProfileTargetUrl(profile);
3677
- let created;
3678
- let poll;
3679
- let jobId = "";
3680
- const staleJobIds = [];
3681
- const retryLimit = profileUnsubmittedRetryLimit(options);
3682
- const pollOptions = riddlePollOptionsForProfile(options);
3683
- for (let attempt = 0; attempt <= retryLimit; attempt += 1) {
3684
- try {
3685
- created = await client.runScript({
3686
- url: targetUrl,
3687
- script: buildRiddleProofProfileScript(profile),
3688
- viewport: profile.target.viewports[0],
3689
- timeoutSec: resolveRiddleProofProfileTimeoutSec(
3690
- profile,
3691
- optionString(options, "timeout") ? Number(optionString(options, "timeout")) : void 0
3692
- ),
3693
- strict: runProfileStrictOption(options),
3694
- sync: options.sync === true ? true : void 0
3695
- });
3696
- } catch (error) {
3697
- return createRiddleProofProfileEnvironmentBlockedResult({ profile, runner, error });
3698
- }
3699
- jobId = typeof created.job_id === "string" ? created.job_id : typeof created.id === "string" ? created.id : "";
3700
- if (!jobId) {
3701
- const directResult = extractRiddleProofProfileResult(created);
3702
- return directResult ? withRiddleMetadata(withProfileMetadata(profile, directResult), { artifacts: collectRiddleProfileArtifactRefs(created) }) : createRiddleProofProfileInsufficientResult({ profile, runner, error: "Riddle run response was missing job_id.", artifacts: collectRiddleProfileArtifactRefs(created) });
3703
- }
3704
- writeRiddleJobReceipt(input.outputDir, {
3705
- profile,
3706
- jobId,
3707
- targetUrl,
3708
- viewport: profile.target.viewports[0],
3709
- created
3710
- });
3711
- poll = await client.pollJob(jobId, pollOptions);
3712
- if (attempt < retryLimit && shouldRetryUnsubmittedRiddleJob(poll)) {
3713
- const recoveredResult = await recoverProfileResultFromRiddleArtifacts(profile, {
3714
- client,
3715
- runner,
3716
- jobId,
3717
- poll,
3718
- attempts: 3,
3719
- intervalMs: Math.min(2e3, Math.max(0, poll.poll?.interval_ms ?? 0))
3720
- });
3721
- if (recoveredResult) {
3722
- return recoveredResult;
3723
- }
3724
- staleJobIds.push(jobId);
3725
- if (options.quiet !== true) {
3726
- process.stderr.write(`[riddle-poll] ${jobId} stayed unsubmitted for ${formatPollDuration(poll.poll?.pre_submission_elapsed_ms)}; retrying hosted run ${attempt + 1}/${retryLimit}
3727
- `);
3728
- }
3729
- continue;
3730
- }
3731
- break;
3732
- }
3733
- if (!poll) {
3734
- return createRiddleProofProfileEnvironmentBlockedResult({ profile, runner, error: "Riddle job polling did not produce a result." });
3735
- }
3736
- const artifacts = collectRiddleProfileArtifactRefs(poll.artifacts);
3737
- const retryCount = staleJobIds.length || void 0;
3738
- if (!poll.ok || !poll.terminal) {
3739
- const recoveredResult = await recoverProfileResultFromRiddleArtifacts(profile, {
3740
- client,
3741
- runner,
3742
- jobId,
3743
- poll,
3744
- attempts: 3,
3745
- intervalMs: Math.min(2e3, Math.max(0, poll.poll?.interval_ms ?? 0))
3746
- });
3747
- if (recoveredResult) {
3748
- return withRiddleMetadata(recoveredResult, { retryCount, staleJobIds });
3749
- }
3750
- return createRiddleProofProfileEnvironmentBlockedResult({
3751
- profile,
3752
- runner,
3753
- error: `Riddle job ${jobId} ended with status ${poll.status || "unknown"}.`,
3754
- riddle: {
3755
- ...riddleMetadataFromPoll(jobId, poll),
3756
- retry_count: retryCount,
3757
- stale_job_ids: staleJobIds.length ? staleJobIds : void 0
3758
- },
3759
- artifacts
3760
- });
3761
- }
3762
- const artifactResult = await profileResultFromRiddleArtifacts(profile, artifacts, [poll.job, poll.artifacts, created]);
3763
- if (!artifactResult) {
3764
- return createRiddleProofProfileInsufficientResult({
3765
- profile,
3766
- runner,
3767
- riddle: riddleMetadataFromPoll(jobId, poll),
3768
- artifacts
3769
- });
3770
- }
3771
- return withRiddleMetadata(artifactResult, {
3772
- job_id: jobId,
3773
- status: poll.status,
3774
- terminal: poll.terminal,
3775
- poll: poll.poll,
3776
- artifacts,
3777
- retryCount,
3778
- staleJobIds
3779
- });
3780
- }
3781
- async function runSplitViewportProfileForCli(profile, options, input) {
3782
- const outputDir = profileOutputDirOption(options);
3783
- const seenOutputNames = /* @__PURE__ */ new Map();
3784
- const childRuns = [];
3785
- for (const viewport of profile.target.viewports) {
3786
- const childProfile = profileForSplitViewport(profile, viewport);
3787
- const childOutputDir = outputDir ? splitViewportOutputDir(outputDir, viewport.name, seenOutputNames) : void 0;
3788
- const result2 = await runSingleRiddleProfileForCli(childProfile, options, { ...input, outputDir: childOutputDir });
3789
- if (childOutputDir) writeProfileOutput(childOutputDir, result2);
3790
- childRuns.push({ viewport, profile: childProfile, result: result2 });
3791
- }
3792
- const artifacts = childRuns.flatMap(splitViewportArtifactRefs);
3793
- const blocked = childRuns.filter(({ result: result2 }) => !result2.evidence || result2.status === "environment_blocked" || result2.status === "configuration_error");
3794
- if (blocked.length) {
3795
- return createRiddleProofProfileEnvironmentBlockedResult({
3796
- profile,
3797
- runner: input.runner,
3798
- error: splitViewportBlockedMessage(childRuns),
3799
- riddle: splitViewportRiddleMetadata(childRuns),
3800
- artifacts
3801
- });
3802
- }
3803
- const evidence = aggregateSplitViewportEvidence(profile, childRuns);
3804
- const result = assessRiddleProofProfileEvidence(profile, evidence, {
3805
- runner: input.runner,
3806
- riddle: splitViewportRiddleMetadata(childRuns),
3807
- artifacts
3808
- });
3809
- return withSplitViewportWarnings(profile, withSplitViewportChildStatusCheck(profile, result, childRuns));
3810
- }
3811
- async function aggregateProfileResultsForCli(profile, options) {
3812
- const resultPaths = runProfileAggregateInputPathsOption(options);
3813
- const seenViewports = /* @__PURE__ */ new Set();
3814
- const childInputs = resultPaths.map((resultPath) => ({ resultPath, result: readProfileResultForAggregate(resultPath) })).filter(({ result: result2 }) => !profileResultIsAggregateParent(result2));
3815
- if (!childInputs.length) {
3816
- throw new Error("run-profile aggregate found no single-viewport child profile results.");
3817
- }
3818
- const childRuns = sortAggregateChildRuns(profile, childInputs.map(({ resultPath, result: result2 }) => {
3819
- const viewport = aggregateProfileResultViewport(profile, result2, resultPath);
3820
- if (seenViewports.has(viewport.name)) {
3821
- throw new Error(`Profile aggregate received more than one result for viewport ${viewport.name}.`);
3822
- }
3823
- seenViewports.add(viewport.name);
3824
- return { viewport, profile: profileForSplitViewport(profile, viewport), result: result2 };
3825
- }));
3826
- const artifacts = childRuns.flatMap(splitViewportArtifactRefs);
3827
- const blocked = childRuns.filter(({ result: result2 }) => !result2.evidence || result2.status === "environment_blocked" || result2.status === "configuration_error");
3828
- if (blocked.length) {
3829
- return createRiddleProofProfileEnvironmentBlockedResult({
3830
- profile,
3831
- runner: "riddle",
3832
- error: splitViewportBlockedMessage(childRuns),
3833
- riddle: splitViewportRiddleMetadata(childRuns, "named-viewport-aggregate"),
3834
- artifacts
3835
- });
3836
- }
3837
- const evidence = aggregateSplitViewportEvidence(profile, childRuns);
3838
- const result = assessRiddleProofProfileEvidence(profile, evidence, {
3839
- runner: "riddle",
3840
- riddle: splitViewportRiddleMetadata(childRuns, "named-viewport-aggregate"),
3841
- artifacts
3842
- });
3843
- return withSplitViewportWarnings(profile, withSplitViewportChildStatusCheck(profile, result, childRuns));
3844
- }
3845
- async function recoverProfileForCli(profile, options) {
3846
- const runner = optionString(options, "runner") || "riddle";
3847
- if (runner !== "riddle") {
3848
- throw new Error(`Unsupported --runner ${runner}. The current CLI supports --runner riddle.`);
3849
- }
3850
- const jobId = optionString(options, "job") ?? optionString(options, "jobId");
3851
- if (!jobId) throw new Error("run-profile recover requires --job <job-id>.");
3852
- const client = createRiddleApiClient(riddleClientConfig(options));
3853
- let artifactPayload;
3854
- try {
3855
- artifactPayload = await client.requestJson(`/v1/jobs/${jobId}/artifacts`);
3856
- } catch (error) {
3857
- return createRiddleProofProfileEnvironmentBlockedResult({
3858
- profile,
3859
- runner,
3860
- error,
3861
- riddle: { job_id: jobId, terminal: false }
3862
- });
3863
- }
3864
- const artifacts = collectRiddleProfileArtifactRefs(artifactPayload);
3865
- const artifactStatus = riddleArtifactsPayloadStatus(artifactPayload);
3866
- const terminal = artifactStatus ? isTerminalRiddleJobStatus(artifactStatus) : artifacts.length > 0;
3867
- const recovered = await profileResultFromRiddleArtifacts(profile, artifacts, [artifactPayload]);
3868
- if (recovered) {
3869
- return withRiddleMetadata(recovered, {
3870
- job_id: jobId,
3871
- status: artifactStatus,
3872
- terminal,
3873
- artifacts,
3874
- artifactRecovery: true
3875
- });
3876
- }
3877
- return createRiddleProofProfileInsufficientResult({
3878
- profile,
3879
- runner,
3880
- error: artifacts.length ? `Riddle job ${jobId} artifacts were recovered without a proof result.` : `Riddle job ${jobId} had no recoverable artifacts.`,
3881
- riddle: {
3882
- job_id: jobId,
3883
- status: artifactStatus,
3884
- terminal,
3885
- artifact_recovery: artifacts.length > 0
3886
- },
3887
- artifacts
3888
- });
3889
- }
3890
- async function runProfileForCli(profile, options) {
3891
- const runner = optionString(options, "runner") || "riddle";
3892
- if (runner !== "riddle") {
3893
- throw new Error(`Unsupported --runner ${runner}. The current CLI supports --runner riddle.`);
3894
- }
3895
- const client = createRiddleApiClient(riddleClientConfig(options));
3896
- const balanceBlocked = await preflightRiddleProfileBalanceForCli(profile, options, { client, runner });
3897
- if (balanceBlocked) return balanceBlocked;
3898
- if (runProfileSplitViewportsOption(options) && profile.target.viewports.length > 1) {
3899
- return runSplitViewportProfileForCli(profile, options, { client, runner });
3900
- }
3901
- return runSingleRiddleProfileForCli(profile, options, { client, runner, outputDir: profileOutputDirOption(options) });
3902
- }
3903
- function requestForRun(options) {
3904
- const statePath = optionString(options, "statePath");
3905
- const withEngineModuleUrl = (request) => {
3906
- const moduleUrl = optionString(options, "riddleEngineModuleUrl");
3907
- return moduleUrl && !request.riddle_engine_module_url ? { ...request, riddle_engine_module_url: moduleUrl } : request;
3908
- };
3909
- if (optionString(options, "requestJson")) {
3910
- return withEngineModuleUrl(readJsonValue(optionString(options, "requestJson"), "--request-json"));
3911
- }
3912
- if (statePath) return withEngineModuleUrl(readRunState(statePath).request);
3913
- throw new Error("--request-json is required unless --state-path points to an existing run state.");
3914
- }
3915
- function riddleEngineModuleUrlFor(options, request) {
3916
- return optionString(options, "riddleEngineModuleUrl") || (typeof request.riddle_engine_module_url === "string" && request.riddle_engine_module_url.trim() ? request.riddle_engine_module_url.trim() : void 0);
3917
- }
3918
- function checkpointModeFor(options) {
3919
- const explicit = optionString(options, "checkpointMode");
3920
- if (explicit) return explicit;
3921
- return isLocalAgentMode(optionString(options, "agent")) ? "auto" : "yield";
3922
- }
3923
- async function main() {
3924
- const { positional, options } = parseArgs(process.argv.slice(2));
3925
- const command = positional[0];
3926
- if (!command || command === "help" || command === "--help") {
3927
- process.stdout.write(`${usage()}
3928
- `);
3929
- return;
3930
- }
3931
- validateCliOptions(options);
3932
- if (command === "doctor") {
3933
- const subject = positional[1];
3934
- if (!isLocalAgentMode(subject)) throw new Error("Only `doctor local` is supported.");
3935
- const result = await runCodexExecAgentDoctor(codexConfig(options));
3936
- process.stdout.write(`${JSON.stringify(result, null, 2)}
3937
- `);
3938
- process.exitCode = result.ok ? 0 : 1;
3939
- return;
3940
- }
3941
- if (command === "status") {
3942
- const statePath = optionString(options, "statePath");
3943
- if (!statePath) throw new Error("--state-path is required.");
3944
- const snapshot = readRiddleProofRunStatus(statePath);
3945
- if (!snapshot) throw new Error(`${statePath} is not a readable Riddle Proof run state.`);
3946
- process.stdout.write(`${JSON.stringify(snapshot, null, 2)}
3947
- `);
3948
- return;
3949
- }
3950
- if (command === "run-profile") {
3951
- const profile = profileWithSelectedViewportNamesForCli(normalizeProfileForCli(options), options);
3952
- const result = positional[1] === "recover" ? await recoverProfileForCli(profile, options) : positional[1] === "aggregate" ? await aggregateProfileResultsForCli(profile, options) : await runProfileForCli(profile, options);
3953
- writeProfileOutput(profileOutputDirOption(options), result);
3954
- const diagnosticLine = profileCliDiagnosticLine(result);
3955
- if (diagnosticLine && optionBoolean(options, "quiet") !== true) {
3956
- process.stderr.write(`${diagnosticLine}
3957
- `);
3958
- }
3959
- writeRunProfileResult(result, options);
3960
- process.exitCode = profileStatusExitCode(profile, result.status);
3961
- return;
3962
- }
3963
- if (command === "profile-http-status-preflight") {
3964
- const profile = normalizeProfileForCli(options);
3965
- const result = await preflightRiddleProofProfileHttpStatusChecks(profile);
3966
- const format = optionString(options, "format") || "json";
3967
- if (format === "summary") {
3968
- process.stdout.write(profileHttpStatusPreflightSummary(result));
3969
- } else if (format === "json") {
3970
- process.stdout.write(`${JSON.stringify(result, null, 2)}
3971
- `);
3972
- } else {
3973
- throw new Error("--format must be json or summary.");
3974
- }
3975
- process.exitCode = result.ok ? 0 : 1;
3976
- return;
3977
- }
3978
- if (command === "profile-body-assertions") {
3979
- const artifactText = await readTextValue(optionString(options, "artifact") ?? optionString(options, "input"), "--artifact");
3980
- const candidates = readOptionalJsonStringArray(optionString(options, "candidatesJson") ?? optionString(options, "candidateJson"), "--candidates-json") ?? [];
3981
- const required = readOptionalJsonStringArray(optionString(options, "requiredJson"), "--required-json");
3982
- if (!candidates.length && !required?.length) {
3983
- throw new Error("--candidates-json or --required-json must provide at least one snippet.");
3984
- }
3985
- const result = deriveRiddleProofArtifactBodyAssertions({
3986
- artifact_text: artifactText,
3987
- candidates,
3988
- required
3989
- });
3990
- const format = optionString(options, "format") || "json";
3991
- if (format === "body-contains") {
3992
- process.stdout.write(`${JSON.stringify(result.body_contains, null, 2)}
3993
- `);
3994
- } else if (format === "json") {
3995
- process.stdout.write(`${JSON.stringify(result, null, 2)}
3996
- `);
3997
- } else {
3998
- throw new Error("--format must be json or body-contains.");
3999
- }
4000
- process.exitCode = result.ok ? 0 : 1;
4001
- return;
4002
- }
4003
- if (command === "riddle-preview-deploy") {
4004
- const buildDir = positional[1];
4005
- const label = positional[2];
4006
- const result = await createRiddleApiClient(riddleClientConfig(options)).deployPreview(buildDir, label, previewFrameworkOption(options));
4007
- for (const warning of result.warnings ?? []) {
4008
- process.stderr.write(`Warning: ${warning}
4009
- `);
4010
- }
4011
- process.stdout.write(`${JSON.stringify(result, null, 2)}
4012
- `);
4013
- return;
4014
- }
4015
- if (command === "riddle-server-preview") {
4016
- const directory = positional[1];
4017
- const scriptFile = optionString(options, "scriptFile");
4018
- if (!directory || !scriptFile) throw new Error("riddle-server-preview requires <directory> and --script-file.");
4019
- const result = await createRiddleApiClient(riddleClientConfig(options)).runServerPreview({
4020
- directory,
4021
- script: readFileSync(scriptFile, "utf-8"),
4022
- image: optionString(options, "image"),
4023
- command: optionString(options, "command"),
4024
- port: optionString(options, "port") ? Number(optionString(options, "port")) : void 0,
4025
- path: optionString(options, "path"),
4026
- readinessPath: optionString(options, "readinessPath"),
4027
- readinessTimeoutSec: optionString(options, "readinessTimeout") ? Number(optionString(options, "readinessTimeout")) : void 0,
4028
- waitForSelector: optionString(options, "waitForSelector"),
4029
- navigationTimeoutSec: optionString(options, "navigationTimeout") ? Number(optionString(options, "navigationTimeout")) : void 0,
4030
- viewport: parseRiddleViewport(optionString(options, "viewport")),
4031
- timeoutSec: optionString(options, "timeout") ? Number(optionString(options, "timeout")) : void 0,
4032
- pollAttempts: optionString(options, "pollAttempts") ? Number(optionString(options, "pollAttempts")) : void 0,
4033
- pollIntervalMs: optionString(options, "pollIntervalMs") ? Number(optionString(options, "pollIntervalMs")) : void 0,
4034
- exclude: optionString(options, "exclude")?.split(",").map((item) => item.trim()).filter(Boolean)
4035
- });
4036
- process.stdout.write(`${JSON.stringify(result, null, 2)}
4037
- `);
4038
- process.exitCode = result.ok ? 0 : 1;
4039
- return;
4040
- }
4041
- if (command === "riddle-run-script") {
4042
- const url = optionString(options, "url");
4043
- const scriptFile = optionString(options, "scriptFile");
4044
- if (!url || !scriptFile) throw new Error("riddle-run-script requires --url and --script-file.");
4045
- const result = await createRiddleApiClient(riddleClientConfig(options)).runScript({
4046
- url,
4047
- script: readFileSync(scriptFile, "utf-8"),
4048
- viewport: parseRiddleViewport(optionString(options, "viewport")),
4049
- timeoutSec: optionString(options, "timeout") ? Number(optionString(options, "timeout")) : void 0,
4050
- strict: optionBoolean(options, "strict"),
4051
- sync: options.sync === true ? true : void 0
4052
- });
4053
- process.stdout.write(`${JSON.stringify(result, null, 2)}
4054
- `);
4055
- return;
4056
- }
4057
- if (command === "riddle-poll") {
4058
- const jobId = positional[1];
4059
- if (!jobId) throw new Error("riddle-poll requires <job-id>.");
4060
- const wait = options.wait === true;
4061
- const result = await createRiddleApiClient(riddleClientConfig(options)).pollJob(jobId, {
4062
- wait,
4063
- attempts: optionString(options, "attempts") ? Number(optionString(options, "attempts")) : void 0,
4064
- intervalMs: optionString(options, "intervalMs") ? Number(optionString(options, "intervalMs")) : void 0,
4065
- progressEveryMs: optionString(options, "progressEveryMs") ? Number(optionString(options, "progressEveryMs")) : void 0,
4066
- onProgress: wait && options.quiet !== true ? (snapshot) => {
4067
- process.stderr.write(`${riddlePollProgressLine(snapshot)}
4068
- `);
4069
- } : void 0
4070
- });
4071
- process.stdout.write(`${JSON.stringify(result, null, 2)}
4072
- `);
4073
- process.exitCode = result.ok ? 0 : 1;
4074
- return;
4075
- }
4076
- if (command === "checkpoint") {
4077
- const statePath = optionString(options, "statePath");
4078
- if (!statePath) throw new Error("--state-path is required.");
4079
- const state = readRunState(statePath);
4080
- const snapshot = readRiddleProofRunStatus(statePath);
4081
- if (!state.checkpoint_packet) {
4082
- throw new Error(`${statePath} has no pending checkpoint packet.`);
4083
- }
4084
- const responseTemplate = createCheckpointResponseTemplate(state.checkpoint_packet, {
4085
- decision: optionString(options, "decision"),
4086
- source_kind: optionString(options, "sourceKind") || "codex"
4087
- });
4088
- const format = optionString(options, "format") || "json";
4089
- if (format === "markdown" || format === "md") {
4090
- process.stdout.write(formatCheckpointMarkdown({
4091
- statePath,
4092
- status: snapshot?.status || state.status,
4093
- checkpointPacket: state.checkpoint_packet,
4094
- runCard: snapshot?.run_card || state.run_card || null,
4095
- responseTemplate
4096
- }));
4097
- return;
4098
- }
4099
- if (format !== "json") throw new Error("--format must be json or markdown.");
4100
- process.stdout.write(`${JSON.stringify({
4101
- checkpoint_packet: state.checkpoint_packet,
4102
- run_card: snapshot?.run_card || state.run_card || null,
4103
- response_template: responseTemplate,
4104
- next_commands: [
4105
- `riddle-proof-loop respond --state-path ${statePath} --decision ${responseTemplate.decision} --summary <summary> --payload-json <file|json|->`,
4106
- `riddle-proof-loop status --state-path ${statePath}`
4107
- ]
4108
- }, null, 2)}
4109
- `);
4110
- return;
4111
- }
4112
- if (command === "run" || command === "respond") {
4113
- const statePath = optionString(options, "statePath");
4114
- const request = requestForRun(options);
4115
- const response = command === "respond" ? optionString(options, "responseJson") ? readJsonValue(optionString(options, "responseJson"), "--response-json") : checkpointResponseForFlags(statePath || "", options) : void 0;
4116
- const result = await runRiddleProofEngineHarness({
4117
- request,
4118
- state_path: statePath,
4119
- checkpoint_response: response,
4120
- checkpoint_mode: checkpointModeFor(options),
4121
- checkpoint_visibility: optionString(options, "checkpointVisibility") || "manual",
4122
- max_iterations: optionString(options, "maxIterations") ? Number(optionString(options, "maxIterations")) : void 0,
4123
- agent: agentFor(options),
4124
- config: {
4125
- stateDir: optionString(options, "stateDir"),
4126
- riddleEngineModuleUrl: riddleEngineModuleUrlFor(options, request),
4127
- riddleProofDir: optionString(options, "riddleProofDir"),
4128
- defaultReviewer: optionString(options, "defaultReviewer"),
4129
- defaultShipMode: optionString(options, "defaultShipMode")
4130
- }
4131
- });
4132
- process.stdout.write(`${JSON.stringify(result, null, 2)}
4133
- `);
4134
- process.exitCode = result.ok || result.status === "awaiting_checkpoint" ? 0 : 1;
4135
- return;
4136
- }
4137
- throw new Error(`Unknown command: ${command}
4138
- ${usage()}`);
4139
- }
4140
- main().catch((error) => {
4141
- process.stderr.write(`${error instanceof Error ? error.message : String(error)}
4142
- `);
4143
- process.exitCode = 1;
4144
- });
13
+ import "./chunk-MLKGABMK.js";