@riddledc/riddle-proof 0.7.217 → 0.7.219

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.
@@ -1,6 +1,6 @@
1
1
  // src/riddle-client.ts
2
2
  import { execFileSync } from "child_process";
3
- import { existsSync, mkdtempSync, readFileSync, rmSync } from "fs";
3
+ import { existsSync, mkdtempSync, readdirSync, readFileSync, rmSync, statSync } from "fs";
4
4
  import { tmpdir } from "os";
5
5
  import path from "path";
6
6
  var DEFAULT_RIDDLE_API_BASE_URL = "https://api.riddledc.com";
@@ -74,6 +74,7 @@ function previewDeployResultFromRecord(input) {
74
74
  expires_at: expiresAt,
75
75
  publish_recovered: publishRecovered || void 0,
76
76
  publish_error: publishError,
77
+ warnings: input.warnings?.length ? input.warnings : void 0,
77
78
  raw: record
78
79
  };
79
80
  }
@@ -91,7 +92,8 @@ async function waitForPublishedPreview(config, input) {
91
92
  framework: input.framework,
92
93
  expiresAt: input.expiresAt,
93
94
  publishRecovered: true,
94
- publishError: input.publishError.message
95
+ publishError: input.publishError.message,
96
+ warnings: input.warnings
95
97
  });
96
98
  }
97
99
  if (attempt < PREVIEW_PUBLISH_RECOVERY_ATTEMPTS) {
@@ -104,6 +106,7 @@ async function deployRiddlePreview(config, directory, label, framework = "static
104
106
  if (!directory?.trim()) throw new Error("directory is required");
105
107
  if (!label?.trim()) throw new Error("label is required");
106
108
  if (framework !== "spa" && framework !== "static") throw new Error("framework must be spa or static");
109
+ const warnings = collectRiddlePreviewDeployWarnings(directory, framework);
107
110
  const created = await riddleRequestJson(config, "/v1/preview", {
108
111
  method: "POST",
109
112
  body: JSON.stringify({ framework, label })
@@ -131,7 +134,7 @@ async function deployRiddlePreview(config, directory, label, framework = "static
131
134
  const published = await riddleRequestJson(config, `/v1/preview/${id}/publish`, {
132
135
  method: "POST"
133
136
  });
134
- return previewDeployResultFromRecord({ record: published, id, label, framework, expiresAt });
137
+ return previewDeployResultFromRecord({ record: published, id, label, framework, expiresAt, warnings });
135
138
  } catch (error) {
136
139
  if (!canRecoverPreviewPublish(error)) throw error;
137
140
  return waitForPublishedPreview(config, {
@@ -139,10 +142,58 @@ async function deployRiddlePreview(config, directory, label, framework = "static
139
142
  label,
140
143
  framework,
141
144
  expiresAt,
142
- publishError: error
145
+ publishError: error,
146
+ warnings
143
147
  });
144
148
  }
145
149
  }
150
+ function latestMatchingMtimeMs(directory, predicate) {
151
+ let latest = 0;
152
+ const stack = [directory];
153
+ let visited = 0;
154
+ while (stack.length) {
155
+ const current = stack.pop();
156
+ for (const entry of readdirSync(current, { withFileTypes: true })) {
157
+ const fullPath = path.join(current, entry.name);
158
+ if (entry.isDirectory()) {
159
+ stack.push(fullPath);
160
+ continue;
161
+ }
162
+ if (!entry.isFile() || !predicate(fullPath)) continue;
163
+ const stat = statSync(fullPath);
164
+ latest = Math.max(latest, stat.mtimeMs);
165
+ visited += 1;
166
+ if (visited >= 1e4) return latest;
167
+ }
168
+ }
169
+ return latest;
170
+ }
171
+ function collectRiddlePreviewDeployWarnings(directory, framework = "static") {
172
+ try {
173
+ if (framework !== "static") return [];
174
+ const resolvedDirectory = path.resolve(directory);
175
+ if (path.basename(resolvedDirectory) !== "out") return [];
176
+ const repoRoot = path.dirname(resolvedDirectory);
177
+ const nextAppDir = path.join(repoRoot, ".next", "server", "app");
178
+ if (!existsSync(nextAppDir)) return [];
179
+ const nextRenderedMtimeMs = latestMatchingMtimeMs(nextAppDir, (filePath) => /\.(?:html|rsc)$/i.test(filePath));
180
+ if (!nextRenderedMtimeMs) return [];
181
+ const outRenderedMtimeMs = existsSync(resolvedDirectory) ? latestMatchingMtimeMs(resolvedDirectory, (filePath) => /\.(?:html|txt|rsc)$/i.test(filePath)) : 0;
182
+ if (!outRenderedMtimeMs) {
183
+ return [
184
+ "Riddle Preview static deploy target is an out/ directory with newer Next render output in .next/server/app, but no rendered HTML/RSC files were found in out/. Run the project static bundle/export step before deploying."
185
+ ];
186
+ }
187
+ if (nextRenderedMtimeMs > outRenderedMtimeMs + 1e3) {
188
+ return [
189
+ "Riddle Preview static deploy target out/ appears older than the Next render output in .next/server/app. Run the project static bundle/export step, such as npm run build:static-deploy or next export, before deploying to avoid a stale Preview."
190
+ ];
191
+ }
192
+ return [];
193
+ } catch {
194
+ return [];
195
+ }
196
+ }
146
197
  async function deployRiddleStaticPreview(config, directory, label) {
147
198
  return deployRiddlePreview(config, directory, label, "static");
148
199
  }
@@ -415,6 +466,7 @@ export {
415
466
  riddleRequestJson,
416
467
  getRiddleBalance,
417
468
  deployRiddlePreview,
469
+ collectRiddlePreviewDeployWarnings,
418
470
  deployRiddleStaticPreview,
419
471
  parseRiddleViewport,
420
472
  runRiddleServerPreview,
package/dist/cli.cjs CHANGED
@@ -6635,6 +6635,7 @@ function previewDeployResultFromRecord(input) {
6635
6635
  expires_at: expiresAt,
6636
6636
  publish_recovered: publishRecovered || void 0,
6637
6637
  publish_error: publishError,
6638
+ warnings: input.warnings?.length ? input.warnings : void 0,
6638
6639
  raw: record
6639
6640
  };
6640
6641
  }
@@ -6652,7 +6653,8 @@ async function waitForPublishedPreview(config, input) {
6652
6653
  framework: input.framework,
6653
6654
  expiresAt: input.expiresAt,
6654
6655
  publishRecovered: true,
6655
- publishError: input.publishError.message
6656
+ publishError: input.publishError.message,
6657
+ warnings: input.warnings
6656
6658
  });
6657
6659
  }
6658
6660
  if (attempt < PREVIEW_PUBLISH_RECOVERY_ATTEMPTS) {
@@ -6665,6 +6667,7 @@ async function deployRiddlePreview(config, directory, label, framework = "static
6665
6667
  if (!directory?.trim()) throw new Error("directory is required");
6666
6668
  if (!label?.trim()) throw new Error("label is required");
6667
6669
  if (framework !== "spa" && framework !== "static") throw new Error("framework must be spa or static");
6670
+ const warnings = collectRiddlePreviewDeployWarnings(directory, framework);
6668
6671
  const created = await riddleRequestJson(config, "/v1/preview", {
6669
6672
  method: "POST",
6670
6673
  body: JSON.stringify({ framework, label })
@@ -6692,7 +6695,7 @@ async function deployRiddlePreview(config, directory, label, framework = "static
6692
6695
  const published = await riddleRequestJson(config, `/v1/preview/${id}/publish`, {
6693
6696
  method: "POST"
6694
6697
  });
6695
- return previewDeployResultFromRecord({ record: published, id, label, framework, expiresAt });
6698
+ return previewDeployResultFromRecord({ record: published, id, label, framework, expiresAt, warnings });
6696
6699
  } catch (error) {
6697
6700
  if (!canRecoverPreviewPublish(error)) throw error;
6698
6701
  return waitForPublishedPreview(config, {
@@ -6700,10 +6703,58 @@ async function deployRiddlePreview(config, directory, label, framework = "static
6700
6703
  label,
6701
6704
  framework,
6702
6705
  expiresAt,
6703
- publishError: error
6706
+ publishError: error,
6707
+ warnings
6704
6708
  });
6705
6709
  }
6706
6710
  }
6711
+ function latestMatchingMtimeMs(directory, predicate) {
6712
+ let latest = 0;
6713
+ const stack = [directory];
6714
+ let visited = 0;
6715
+ while (stack.length) {
6716
+ const current = stack.pop();
6717
+ for (const entry of (0, import_node_fs5.readdirSync)(current, { withFileTypes: true })) {
6718
+ const fullPath = import_node_path5.default.join(current, entry.name);
6719
+ if (entry.isDirectory()) {
6720
+ stack.push(fullPath);
6721
+ continue;
6722
+ }
6723
+ if (!entry.isFile() || !predicate(fullPath)) continue;
6724
+ const stat = (0, import_node_fs5.statSync)(fullPath);
6725
+ latest = Math.max(latest, stat.mtimeMs);
6726
+ visited += 1;
6727
+ if (visited >= 1e4) return latest;
6728
+ }
6729
+ }
6730
+ return latest;
6731
+ }
6732
+ function collectRiddlePreviewDeployWarnings(directory, framework = "static") {
6733
+ try {
6734
+ if (framework !== "static") return [];
6735
+ const resolvedDirectory = import_node_path5.default.resolve(directory);
6736
+ if (import_node_path5.default.basename(resolvedDirectory) !== "out") return [];
6737
+ const repoRoot = import_node_path5.default.dirname(resolvedDirectory);
6738
+ const nextAppDir = import_node_path5.default.join(repoRoot, ".next", "server", "app");
6739
+ if (!(0, import_node_fs5.existsSync)(nextAppDir)) return [];
6740
+ const nextRenderedMtimeMs = latestMatchingMtimeMs(nextAppDir, (filePath) => /\.(?:html|rsc)$/i.test(filePath));
6741
+ if (!nextRenderedMtimeMs) return [];
6742
+ const outRenderedMtimeMs = (0, import_node_fs5.existsSync)(resolvedDirectory) ? latestMatchingMtimeMs(resolvedDirectory, (filePath) => /\.(?:html|txt|rsc)$/i.test(filePath)) : 0;
6743
+ if (!outRenderedMtimeMs) {
6744
+ return [
6745
+ "Riddle Preview static deploy target is an out/ directory with newer Next render output in .next/server/app, but no rendered HTML/RSC files were found in out/. Run the project static bundle/export step before deploying."
6746
+ ];
6747
+ }
6748
+ if (nextRenderedMtimeMs > outRenderedMtimeMs + 1e3) {
6749
+ return [
6750
+ "Riddle Preview static deploy target out/ appears older than the Next render output in .next/server/app. Run the project static bundle/export step, such as npm run build:static-deploy or next export, before deploying to avoid a stale Preview."
6751
+ ];
6752
+ }
6753
+ return [];
6754
+ } catch {
6755
+ return [];
6756
+ }
6757
+ }
6707
6758
  async function deployRiddleStaticPreview(config, directory, label) {
6708
6759
  return deployRiddlePreview(config, directory, label, "static");
6709
6760
  }
@@ -16281,6 +16332,92 @@ function extractRiddleProofProfileResult(input) {
16281
16332
 
16282
16333
  // src/cli.ts
16283
16334
  var RIDDLE_PROFILE_BALANCE_PREFLIGHT_MIN_SECONDS_PER_JOB = 30;
16335
+ var KNOWN_CLI_OPTIONS = /* @__PURE__ */ new Set([
16336
+ "agent",
16337
+ "apiBaseUrl",
16338
+ "apiKey",
16339
+ "apiKeyFile",
16340
+ "artifact",
16341
+ "attempts",
16342
+ "balancePreflight",
16343
+ "baseUrl",
16344
+ "candidateJson",
16345
+ "candidatesJson",
16346
+ "checkpointMode",
16347
+ "checkpointVisibility",
16348
+ "codexCommand",
16349
+ "codexFullAuto",
16350
+ "codexHome",
16351
+ "codexModel",
16352
+ "codexSandbox",
16353
+ "codexTimeoutMs",
16354
+ "command",
16355
+ "continueWithStage",
16356
+ "createdAt",
16357
+ "decision",
16358
+ "defaultReviewer",
16359
+ "defaultShipMode",
16360
+ "exclude",
16361
+ "format",
16362
+ "framework",
16363
+ "help",
16364
+ "image",
16365
+ "input",
16366
+ "inputDir",
16367
+ "inputFile",
16368
+ "inputFiles",
16369
+ "inputs",
16370
+ "intervalMs",
16371
+ "job",
16372
+ "jobId",
16373
+ "maxIterations",
16374
+ "navigationTimeout",
16375
+ "output",
16376
+ "outputDir",
16377
+ "path",
16378
+ "payloadJson",
16379
+ "pollAttempts",
16380
+ "pollIntervalMs",
16381
+ "port",
16382
+ "profile",
16383
+ "progressEveryMs",
16384
+ "quiet",
16385
+ "readinessPath",
16386
+ "readinessTimeout",
16387
+ "reasonsJson",
16388
+ "requestJson",
16389
+ "requiredJson",
16390
+ "responseJson",
16391
+ "resultFormat",
16392
+ "resultsDir",
16393
+ "riddleEngineModuleUrl",
16394
+ "riddleProofDir",
16395
+ "route",
16396
+ "runDir",
16397
+ "runner",
16398
+ "scriptFile",
16399
+ "sourceKind",
16400
+ "splitViewports",
16401
+ "stateDir",
16402
+ "statePath",
16403
+ "strict",
16404
+ "submitRetries",
16405
+ "submitTimeoutMs",
16406
+ "summary",
16407
+ "sync",
16408
+ "timeout",
16409
+ "url",
16410
+ "unsubmittedJobRetries",
16411
+ "unsubmittedJobTimeoutMs",
16412
+ "unsubmittedRetries",
16413
+ "unsubmittedTimeoutMs",
16414
+ "viewport",
16415
+ "viewportName",
16416
+ "viewportNames",
16417
+ "viewports",
16418
+ "wait",
16419
+ "waitForSelector"
16420
+ ]);
16284
16421
  function usage() {
16285
16422
  return [
16286
16423
  "Usage:",
@@ -16289,9 +16426,9 @@ function usage() {
16289
16426
  " riddle-proof-loop respond --state-path <path> --response-json <file|json|->",
16290
16427
  " riddle-proof-loop respond --state-path <path> --decision <decision> --summary <text> [--payload-json <file|json|->]",
16291
16428
  " riddle-proof-loop status --state-path <path>",
16292
- " riddle-proof-loop run-profile --profile <file|json|-> --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]",
16293
- " riddle-proof-loop run-profile aggregate --profile <file|json|-> --url <base-url> --input-dir <dir>|--inputs <path[,path...]> [--output <dir>|--output-dir <dir>] [--result-format json|compact-json|summary|none; default json]",
16294
- " riddle-proof-loop run-profile recover --profile <file|json|-> --url <base-url> --job <job-id> [--viewport-name <name[,name...]>] [--output <dir>|--output-dir <dir>] [--result-format json|compact-json|summary|none; default json]",
16429
+ " 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]",
16430
+ " 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]",
16431
+ " 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]",
16295
16432
  " riddle-proof-loop profile-body-assertions --artifact <file|url|-> --candidates-json <file|json|-> [--required-json <file|json|->] [--format json|body-contains]",
16296
16433
  " riddle-proof-loop profile-http-status-preflight --profile <file|json|-> --url <base-url> [--format json|summary]",
16297
16434
  " riddle-proof-loop riddle-preview-deploy <build-dir> <label> [--framework spa|static]",
@@ -16331,6 +16468,15 @@ function parseArgs(argv) {
16331
16468
  }
16332
16469
  return { positional, options };
16333
16470
  }
16471
+ function optionKeyToFlagName(key) {
16472
+ return key.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);
16473
+ }
16474
+ function validateCliOptions(options) {
16475
+ const unknown = Object.keys(options).filter((key) => !KNOWN_CLI_OPTIONS.has(key));
16476
+ if (!unknown.length) return;
16477
+ const flags = unknown.map((key) => `--${optionKeyToFlagName(key)}`).join(", ");
16478
+ throw new Error(`Unknown option${unknown.length === 1 ? "" : "s"}: ${flags}. Run riddle-proof-loop help for usage.`);
16479
+ }
16334
16480
  function optionString(options, key) {
16335
16481
  const value = options[key];
16336
16482
  return typeof value === "string" && value.trim() ? value.trim() : void 0;
@@ -16652,7 +16798,7 @@ function parseProfileViewports(value) {
16652
16798
  function normalizeProfileForCli(options) {
16653
16799
  const rawProfile = readJsonValue(optionString(options, "profile"), "--profile");
16654
16800
  return normalizeRiddleProofProfile(rawProfile, {
16655
- url: optionString(options, "url"),
16801
+ url: optionString(options, "url") ?? optionString(options, "baseUrl"),
16656
16802
  route: optionString(options, "route"),
16657
16803
  viewports: parseProfileViewports(optionString(options, "viewports") || optionString(options, "viewport"))
16658
16804
  });
@@ -19904,6 +20050,7 @@ async function main() {
19904
20050
  `);
19905
20051
  return;
19906
20052
  }
20053
+ validateCliOptions(options);
19907
20054
  if (command === "doctor") {
19908
20055
  const subject = positional[1];
19909
20056
  if (!isLocalAgentMode(subject)) throw new Error("Only `doctor local` is supported.");
@@ -19979,6 +20126,10 @@ async function main() {
19979
20126
  const buildDir = positional[1];
19980
20127
  const label = positional[2];
19981
20128
  const result = await createRiddleApiClient(riddleClientConfig(options)).deployPreview(buildDir, label, previewFrameworkOption(options));
20129
+ for (const warning of result.warnings ?? []) {
20130
+ process.stderr.write(`Warning: ${warning}
20131
+ `);
20132
+ }
19982
20133
  process.stdout.write(`${JSON.stringify(result, null, 2)}
19983
20134
  `);
19984
20135
  return;
package/dist/cli.js CHANGED
@@ -18,7 +18,7 @@ import {
18
18
  createRiddleApiClient,
19
19
  isTerminalRiddleJobStatus,
20
20
  parseRiddleViewport
21
- } from "./chunk-33XO7WFI.js";
21
+ } from "./chunk-TWTEUS7R.js";
22
22
  import {
23
23
  createDisabledRiddleProofAgentAdapter,
24
24
  readRiddleProofRunStatus,
@@ -41,6 +41,92 @@ import "./chunk-VY4Y5U57.js";
41
41
  import { existsSync, mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from "fs";
42
42
  import path from "path";
43
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
+ ]);
44
130
  function usage() {
45
131
  return [
46
132
  "Usage:",
@@ -49,9 +135,9 @@ function usage() {
49
135
  " riddle-proof-loop respond --state-path <path> --response-json <file|json|->",
50
136
  " riddle-proof-loop respond --state-path <path> --decision <decision> --summary <text> [--payload-json <file|json|->]",
51
137
  " riddle-proof-loop status --state-path <path>",
52
- " riddle-proof-loop run-profile --profile <file|json|-> --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]",
53
- " riddle-proof-loop run-profile aggregate --profile <file|json|-> --url <base-url> --input-dir <dir>|--inputs <path[,path...]> [--output <dir>|--output-dir <dir>] [--result-format json|compact-json|summary|none; default json]",
54
- " riddle-proof-loop run-profile recover --profile <file|json|-> --url <base-url> --job <job-id> [--viewport-name <name[,name...]>] [--output <dir>|--output-dir <dir>] [--result-format json|compact-json|summary|none; default json]",
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]",
55
141
  " riddle-proof-loop profile-body-assertions --artifact <file|url|-> --candidates-json <file|json|-> [--required-json <file|json|->] [--format json|body-contains]",
56
142
  " riddle-proof-loop profile-http-status-preflight --profile <file|json|-> --url <base-url> [--format json|summary]",
57
143
  " riddle-proof-loop riddle-preview-deploy <build-dir> <label> [--framework spa|static]",
@@ -91,6 +177,15 @@ function parseArgs(argv) {
91
177
  }
92
178
  return { positional, options };
93
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
+ }
94
189
  function optionString(options, key) {
95
190
  const value = options[key];
96
191
  return typeof value === "string" && value.trim() ? value.trim() : void 0;
@@ -412,7 +507,7 @@ function parseProfileViewports(value) {
412
507
  function normalizeProfileForCli(options) {
413
508
  const rawProfile = readJsonValue(optionString(options, "profile"), "--profile");
414
509
  return normalizeRiddleProofProfile(rawProfile, {
415
- url: optionString(options, "url"),
510
+ url: optionString(options, "url") ?? optionString(options, "baseUrl"),
416
511
  route: optionString(options, "route"),
417
512
  viewports: parseProfileViewports(optionString(options, "viewports") || optionString(options, "viewport"))
418
513
  });
@@ -3664,6 +3759,7 @@ async function main() {
3664
3759
  `);
3665
3760
  return;
3666
3761
  }
3762
+ validateCliOptions(options);
3667
3763
  if (command === "doctor") {
3668
3764
  const subject = positional[1];
3669
3765
  if (!isLocalAgentMode(subject)) throw new Error("Only `doctor local` is supported.");
@@ -3739,6 +3835,10 @@ async function main() {
3739
3835
  const buildDir = positional[1];
3740
3836
  const label = positional[2];
3741
3837
  const result = await createRiddleApiClient(riddleClientConfig(options)).deployPreview(buildDir, label, previewFrameworkOption(options));
3838
+ for (const warning of result.warnings ?? []) {
3839
+ process.stderr.write(`Warning: ${warning}
3840
+ `);
3841
+ }
3742
3842
  process.stdout.write(`${JSON.stringify(result, null, 2)}
3743
3843
  `);
3744
3844
  return;
package/dist/index.cjs CHANGED
@@ -2948,6 +2948,7 @@ __export(index_exports, {
2948
2948
  buildVisualProofSession: () => buildVisualProofSession,
2949
2949
  checkpointResponseIdentity: () => checkpointResponseIdentity,
2950
2950
  checkpointSummaryFromState: () => checkpointSummaryFromState,
2951
+ collectRiddlePreviewDeployWarnings: () => collectRiddlePreviewDeployWarnings,
2951
2952
  collectRiddleProfileArtifactRefs: () => collectRiddleProfileArtifactRefs,
2952
2953
  collectRiddleProofProfileWarnings: () => collectRiddleProofProfileWarnings,
2953
2954
  compactBasicGameplayText: () => compactBasicGameplayText,
@@ -18137,6 +18138,7 @@ function previewDeployResultFromRecord(input) {
18137
18138
  expires_at: expiresAt,
18138
18139
  publish_recovered: publishRecovered || void 0,
18139
18140
  publish_error: publishError,
18141
+ warnings: input.warnings?.length ? input.warnings : void 0,
18140
18142
  raw: record
18141
18143
  };
18142
18144
  }
@@ -18154,7 +18156,8 @@ async function waitForPublishedPreview(config, input) {
18154
18156
  framework: input.framework,
18155
18157
  expiresAt: input.expiresAt,
18156
18158
  publishRecovered: true,
18157
- publishError: input.publishError.message
18159
+ publishError: input.publishError.message,
18160
+ warnings: input.warnings
18158
18161
  });
18159
18162
  }
18160
18163
  if (attempt < PREVIEW_PUBLISH_RECOVERY_ATTEMPTS) {
@@ -18167,6 +18170,7 @@ async function deployRiddlePreview(config, directory, label, framework = "static
18167
18170
  if (!directory?.trim()) throw new Error("directory is required");
18168
18171
  if (!label?.trim()) throw new Error("label is required");
18169
18172
  if (framework !== "spa" && framework !== "static") throw new Error("framework must be spa or static");
18173
+ const warnings = collectRiddlePreviewDeployWarnings(directory, framework);
18170
18174
  const created = await riddleRequestJson(config, "/v1/preview", {
18171
18175
  method: "POST",
18172
18176
  body: JSON.stringify({ framework, label })
@@ -18194,7 +18198,7 @@ async function deployRiddlePreview(config, directory, label, framework = "static
18194
18198
  const published = await riddleRequestJson(config, `/v1/preview/${id}/publish`, {
18195
18199
  method: "POST"
18196
18200
  });
18197
- return previewDeployResultFromRecord({ record: published, id, label, framework, expiresAt });
18201
+ return previewDeployResultFromRecord({ record: published, id, label, framework, expiresAt, warnings });
18198
18202
  } catch (error) {
18199
18203
  if (!canRecoverPreviewPublish(error)) throw error;
18200
18204
  return waitForPublishedPreview(config, {
@@ -18202,10 +18206,58 @@ async function deployRiddlePreview(config, directory, label, framework = "static
18202
18206
  label,
18203
18207
  framework,
18204
18208
  expiresAt,
18205
- publishError: error
18209
+ publishError: error,
18210
+ warnings
18206
18211
  });
18207
18212
  }
18208
18213
  }
18214
+ function latestMatchingMtimeMs(directory, predicate) {
18215
+ let latest = 0;
18216
+ const stack = [directory];
18217
+ let visited = 0;
18218
+ while (stack.length) {
18219
+ const current = stack.pop();
18220
+ for (const entry of (0, import_node_fs5.readdirSync)(current, { withFileTypes: true })) {
18221
+ const fullPath = import_node_path5.default.join(current, entry.name);
18222
+ if (entry.isDirectory()) {
18223
+ stack.push(fullPath);
18224
+ continue;
18225
+ }
18226
+ if (!entry.isFile() || !predicate(fullPath)) continue;
18227
+ const stat = (0, import_node_fs5.statSync)(fullPath);
18228
+ latest = Math.max(latest, stat.mtimeMs);
18229
+ visited += 1;
18230
+ if (visited >= 1e4) return latest;
18231
+ }
18232
+ }
18233
+ return latest;
18234
+ }
18235
+ function collectRiddlePreviewDeployWarnings(directory, framework = "static") {
18236
+ try {
18237
+ if (framework !== "static") return [];
18238
+ const resolvedDirectory = import_node_path5.default.resolve(directory);
18239
+ if (import_node_path5.default.basename(resolvedDirectory) !== "out") return [];
18240
+ const repoRoot = import_node_path5.default.dirname(resolvedDirectory);
18241
+ const nextAppDir = import_node_path5.default.join(repoRoot, ".next", "server", "app");
18242
+ if (!(0, import_node_fs5.existsSync)(nextAppDir)) return [];
18243
+ const nextRenderedMtimeMs = latestMatchingMtimeMs(nextAppDir, (filePath) => /\.(?:html|rsc)$/i.test(filePath));
18244
+ if (!nextRenderedMtimeMs) return [];
18245
+ const outRenderedMtimeMs = (0, import_node_fs5.existsSync)(resolvedDirectory) ? latestMatchingMtimeMs(resolvedDirectory, (filePath) => /\.(?:html|txt|rsc)$/i.test(filePath)) : 0;
18246
+ if (!outRenderedMtimeMs) {
18247
+ return [
18248
+ "Riddle Preview static deploy target is an out/ directory with newer Next render output in .next/server/app, but no rendered HTML/RSC files were found in out/. Run the project static bundle/export step before deploying."
18249
+ ];
18250
+ }
18251
+ if (nextRenderedMtimeMs > outRenderedMtimeMs + 1e3) {
18252
+ return [
18253
+ "Riddle Preview static deploy target out/ appears older than the Next render output in .next/server/app. Run the project static bundle/export step, such as npm run build:static-deploy or next export, before deploying to avoid a stale Preview."
18254
+ ];
18255
+ }
18256
+ return [];
18257
+ } catch {
18258
+ return [];
18259
+ }
18260
+ }
18209
18261
  async function deployRiddleStaticPreview(config, directory, label) {
18210
18262
  return deployRiddlePreview(config, directory, label, "static");
18211
18263
  }
@@ -18519,6 +18571,7 @@ function createRiddleApiClient(config = {}) {
18519
18571
  buildVisualProofSession,
18520
18572
  checkpointResponseIdentity,
18521
18573
  checkpointSummaryFromState,
18574
+ collectRiddlePreviewDeployWarnings,
18522
18575
  collectRiddleProfileArtifactRefs,
18523
18576
  collectRiddleProofProfileWarnings,
18524
18577
  compactBasicGameplayText,
package/dist/index.d.cts CHANGED
@@ -11,4 +11,4 @@ export { BuildVisualProofSessionInput, RIDDLE_PROOF_VISUAL_SESSION_FINGERPRINT_V
11
11
  export { AssessPlayabilityOptions, RIDDLE_PROOF_PLAYABILITY_ASSESSMENT_VERSION, RIDDLE_PROOF_PLAYABILITY_VERSION, RiddleProofPlayabilityAssessment, RiddleProofPlayabilityEvidence, assessPlayabilityEvidence, extractPlayabilityEvidence, isRiddleProofPlayabilityMode } from './playability.cjs';
12
12
  export { AssessBasicGameplayOptions, AttachBasicGameplayArtifactOptions, BASIC_GAMEPLAY_ACTION_TYPES, BASIC_GAMEPLAY_PROGRESS_CHECK_TYPES, BasicGameplayActionResult, BasicGameplayActionType, BasicGameplayArtifactResolution, BasicGameplayAssessmentSummary, BasicGameplayBoundsOffender, BasicGameplayCanvasState, BasicGameplayCatchRecord, BasicGameplayChangeSummary, BasicGameplayFailureCode, BasicGameplayFixReference, BasicGameplayMetric, BasicGameplayMobileEvidence, BasicGameplayProgressCheckType, BasicGameplayProgressionCheck, BasicGameplayProofArtifact, BasicGameplayResponsiveViewportEvidence, BasicGameplayRouteReference, BasicGameplaySnapshot, BasicGameplaySuiteFailure, BasicGameplayWarningCode, CreateBasicGameplayCatchSummaryInput, RIDDLE_PROOF_BASIC_GAMEPLAY_ASSESSMENT_VERSION, RIDDLE_PROOF_BASIC_GAMEPLAY_CATCH_VERSION, RIDDLE_PROOF_BASIC_GAMEPLAY_VERSION, RiddleProofBasicGameplayAssessment, RiddleProofBasicGameplayCatchSummary, RiddleProofBasicGameplayEvidence, RiddleProofBasicGameplayRouteAssessment, RiddleProofBasicGameplayRouteEvidence, assessBasicGameplayEvidence, assessBasicGameplayProgressionCheck, assessBasicGameplayProgressionChecks, assessBasicGameplayRoute, attachBasicGameplayArtifactScreenshotHashes, augmentBasicGameplayAssessmentWithProgressionChecks, compactBasicGameplayText, createBasicGameplayCatchRecords, createBasicGameplayCatchSummary, extractBasicGameplayEvidence, resolveBasicGameplayProgressionCheckWithArtifactScreenshots, sanitizeBasicGameplayJsonString } from './basic-gameplay.cjs';
13
13
  export { NormalizeRiddleProofProfileOptions, RIDDLE_PROOF_PROFILE_CHECK_TYPES, RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION, RIDDLE_PROOF_PROFILE_NETWORK_ABORT_ERROR_CODES, RIDDLE_PROOF_PROFILE_RESULT_VERSION, RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES, RIDDLE_PROOF_PROFILE_STATUSES, RIDDLE_PROOF_PROFILE_VERSION, RiddleProofArtifactBodyAssertionInput, RiddleProofArtifactBodyAssertionResult, RiddleProofProfile, RiddleProofProfileArtifactRef, RiddleProofProfileBaselinePolicy, RiddleProofProfileBoundsOffender, RiddleProofProfileCheck, RiddleProofProfileCheckResult, RiddleProofProfileCheckType, RiddleProofProfileEvidence, RiddleProofProfileFailureAction, RiddleProofProfileHttpStatusBodyJsonAssertion, RiddleProofProfileHttpStatusBodyJsonAssertionResult, RiddleProofProfileHttpStatusPreflightCheckResult, RiddleProofProfileHttpStatusPreflightFetch, RiddleProofProfileHttpStatusPreflightFetchResponse, RiddleProofProfileHttpStatusPreflightOptions, RiddleProofProfileHttpStatusPreflightResult, RiddleProofProfileJsonValueType, RiddleProofProfileNetworkAbortErrorCode, RiddleProofProfileNetworkMock, RiddleProofProfileNetworkMockResponse, RiddleProofProfileResult, RiddleProofProfileReturnSummaryField, RiddleProofProfileRouteEvidence, RiddleProofProfileRouteInventoryRoute, RiddleProofProfileRunner, RiddleProofProfileSetupAction, RiddleProofProfileSetupActionType, RiddleProofProfileStatus, RiddleProofProfileTarget, RiddleProofProfileViewport, RiddleProofProfileViewportEvidence, assessRiddleProofProfileEvidence, buildRiddleProofProfileScript, collectRiddleProfileArtifactRefs, collectRiddleProofProfileWarnings, createRiddleProofProfileConfigurationError, createRiddleProofProfileEnvironmentBlockedResult, createRiddleProofProfileInsufficientResult, deriveRiddleProofArtifactBodyAssertions, extractRiddleProofProfileResult, normalizeRiddleProofProfile, preflightRiddleProofProfileHttpStatusChecks, profileStatusExitCode, resolveRiddleProofProfileRouteUrl, resolveRiddleProofProfileTargetUrl, resolveRiddleProofProfileTimeoutSec, slugifyRiddleProofProfileName, summarizeRiddleProofProfileResult } from './profile.cjs';
14
- export { DEFAULT_RIDDLE_API_BASE_URL, DEFAULT_RIDDLE_API_KEY_FILE, RiddleApiError, RiddleApiKeySource, RiddleBalanceResult, RiddleClientConfig, RiddleFetch, RiddlePollJobOptions, RiddlePollJobResult, RiddlePollProgressSnapshot, RiddlePollSummary, RiddlePreviewDeployResult, RiddlePreviewFramework, RiddleRunScriptInput, RiddleServerPreviewInput, RiddleServerPreviewResult, createRiddleApiClient, deployRiddlePreview, deployRiddleStaticPreview, getRiddleBalance, isTerminalRiddleJobStatus, parseRiddleViewport, pollRiddleJob, resolveRiddleApiKey, resolveRiddleApiKeySource, riddleRequestJson, runRiddleScript, runRiddleServerPreview } from './riddle-client.cjs';
14
+ export { DEFAULT_RIDDLE_API_BASE_URL, DEFAULT_RIDDLE_API_KEY_FILE, RiddleApiError, RiddleApiKeySource, RiddleBalanceResult, RiddleClientConfig, RiddleFetch, RiddlePollJobOptions, RiddlePollJobResult, RiddlePollProgressSnapshot, RiddlePollSummary, RiddlePreviewDeployResult, RiddlePreviewFramework, RiddleRunScriptInput, RiddleServerPreviewInput, RiddleServerPreviewResult, collectRiddlePreviewDeployWarnings, createRiddleApiClient, deployRiddlePreview, deployRiddleStaticPreview, getRiddleBalance, isTerminalRiddleJobStatus, parseRiddleViewport, pollRiddleJob, resolveRiddleApiKey, resolveRiddleApiKeySource, riddleRequestJson, runRiddleScript, runRiddleServerPreview } from './riddle-client.cjs';
package/dist/index.d.ts CHANGED
@@ -11,4 +11,4 @@ export { BuildVisualProofSessionInput, RIDDLE_PROOF_VISUAL_SESSION_FINGERPRINT_V
11
11
  export { AssessPlayabilityOptions, RIDDLE_PROOF_PLAYABILITY_ASSESSMENT_VERSION, RIDDLE_PROOF_PLAYABILITY_VERSION, RiddleProofPlayabilityAssessment, RiddleProofPlayabilityEvidence, assessPlayabilityEvidence, extractPlayabilityEvidence, isRiddleProofPlayabilityMode } from './playability.js';
12
12
  export { AssessBasicGameplayOptions, AttachBasicGameplayArtifactOptions, BASIC_GAMEPLAY_ACTION_TYPES, BASIC_GAMEPLAY_PROGRESS_CHECK_TYPES, BasicGameplayActionResult, BasicGameplayActionType, BasicGameplayArtifactResolution, BasicGameplayAssessmentSummary, BasicGameplayBoundsOffender, BasicGameplayCanvasState, BasicGameplayCatchRecord, BasicGameplayChangeSummary, BasicGameplayFailureCode, BasicGameplayFixReference, BasicGameplayMetric, BasicGameplayMobileEvidence, BasicGameplayProgressCheckType, BasicGameplayProgressionCheck, BasicGameplayProofArtifact, BasicGameplayResponsiveViewportEvidence, BasicGameplayRouteReference, BasicGameplaySnapshot, BasicGameplaySuiteFailure, BasicGameplayWarningCode, CreateBasicGameplayCatchSummaryInput, RIDDLE_PROOF_BASIC_GAMEPLAY_ASSESSMENT_VERSION, RIDDLE_PROOF_BASIC_GAMEPLAY_CATCH_VERSION, RIDDLE_PROOF_BASIC_GAMEPLAY_VERSION, RiddleProofBasicGameplayAssessment, RiddleProofBasicGameplayCatchSummary, RiddleProofBasicGameplayEvidence, RiddleProofBasicGameplayRouteAssessment, RiddleProofBasicGameplayRouteEvidence, assessBasicGameplayEvidence, assessBasicGameplayProgressionCheck, assessBasicGameplayProgressionChecks, assessBasicGameplayRoute, attachBasicGameplayArtifactScreenshotHashes, augmentBasicGameplayAssessmentWithProgressionChecks, compactBasicGameplayText, createBasicGameplayCatchRecords, createBasicGameplayCatchSummary, extractBasicGameplayEvidence, resolveBasicGameplayProgressionCheckWithArtifactScreenshots, sanitizeBasicGameplayJsonString } from './basic-gameplay.js';
13
13
  export { NormalizeRiddleProofProfileOptions, RIDDLE_PROOF_PROFILE_CHECK_TYPES, RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION, RIDDLE_PROOF_PROFILE_NETWORK_ABORT_ERROR_CODES, RIDDLE_PROOF_PROFILE_RESULT_VERSION, RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES, RIDDLE_PROOF_PROFILE_STATUSES, RIDDLE_PROOF_PROFILE_VERSION, RiddleProofArtifactBodyAssertionInput, RiddleProofArtifactBodyAssertionResult, RiddleProofProfile, RiddleProofProfileArtifactRef, RiddleProofProfileBaselinePolicy, RiddleProofProfileBoundsOffender, RiddleProofProfileCheck, RiddleProofProfileCheckResult, RiddleProofProfileCheckType, RiddleProofProfileEvidence, RiddleProofProfileFailureAction, RiddleProofProfileHttpStatusBodyJsonAssertion, RiddleProofProfileHttpStatusBodyJsonAssertionResult, RiddleProofProfileHttpStatusPreflightCheckResult, RiddleProofProfileHttpStatusPreflightFetch, RiddleProofProfileHttpStatusPreflightFetchResponse, RiddleProofProfileHttpStatusPreflightOptions, RiddleProofProfileHttpStatusPreflightResult, RiddleProofProfileJsonValueType, RiddleProofProfileNetworkAbortErrorCode, RiddleProofProfileNetworkMock, RiddleProofProfileNetworkMockResponse, RiddleProofProfileResult, RiddleProofProfileReturnSummaryField, RiddleProofProfileRouteEvidence, RiddleProofProfileRouteInventoryRoute, RiddleProofProfileRunner, RiddleProofProfileSetupAction, RiddleProofProfileSetupActionType, RiddleProofProfileStatus, RiddleProofProfileTarget, RiddleProofProfileViewport, RiddleProofProfileViewportEvidence, assessRiddleProofProfileEvidence, buildRiddleProofProfileScript, collectRiddleProfileArtifactRefs, collectRiddleProofProfileWarnings, createRiddleProofProfileConfigurationError, createRiddleProofProfileEnvironmentBlockedResult, createRiddleProofProfileInsufficientResult, deriveRiddleProofArtifactBodyAssertions, extractRiddleProofProfileResult, normalizeRiddleProofProfile, preflightRiddleProofProfileHttpStatusChecks, profileStatusExitCode, resolveRiddleProofProfileRouteUrl, resolveRiddleProofProfileTargetUrl, resolveRiddleProofProfileTimeoutSec, slugifyRiddleProofProfileName, summarizeRiddleProofProfileResult } from './profile.js';
14
- export { DEFAULT_RIDDLE_API_BASE_URL, DEFAULT_RIDDLE_API_KEY_FILE, RiddleApiError, RiddleApiKeySource, RiddleBalanceResult, RiddleClientConfig, RiddleFetch, RiddlePollJobOptions, RiddlePollJobResult, RiddlePollProgressSnapshot, RiddlePollSummary, RiddlePreviewDeployResult, RiddlePreviewFramework, RiddleRunScriptInput, RiddleServerPreviewInput, RiddleServerPreviewResult, createRiddleApiClient, deployRiddlePreview, deployRiddleStaticPreview, getRiddleBalance, isTerminalRiddleJobStatus, parseRiddleViewport, pollRiddleJob, resolveRiddleApiKey, resolveRiddleApiKeySource, riddleRequestJson, runRiddleScript, runRiddleServerPreview } from './riddle-client.js';
14
+ export { DEFAULT_RIDDLE_API_BASE_URL, DEFAULT_RIDDLE_API_KEY_FILE, RiddleApiError, RiddleApiKeySource, RiddleBalanceResult, RiddleClientConfig, RiddleFetch, RiddlePollJobOptions, RiddlePollJobResult, RiddlePollProgressSnapshot, RiddlePollSummary, RiddlePreviewDeployResult, RiddlePreviewFramework, RiddleRunScriptInput, RiddleServerPreviewInput, RiddleServerPreviewResult, collectRiddlePreviewDeployWarnings, createRiddleApiClient, deployRiddlePreview, deployRiddleStaticPreview, getRiddleBalance, isTerminalRiddleJobStatus, parseRiddleViewport, pollRiddleJob, resolveRiddleApiKey, resolveRiddleApiKeySource, riddleRequestJson, runRiddleScript, runRiddleServerPreview } from './riddle-client.js';
package/dist/index.js CHANGED
@@ -67,6 +67,7 @@ import {
67
67
  DEFAULT_RIDDLE_API_BASE_URL,
68
68
  DEFAULT_RIDDLE_API_KEY_FILE,
69
69
  RiddleApiError,
70
+ collectRiddlePreviewDeployWarnings,
70
71
  createRiddleApiClient,
71
72
  deployRiddlePreview,
72
73
  deployRiddleStaticPreview,
@@ -79,7 +80,7 @@ import {
79
80
  riddleRequestJson,
80
81
  runRiddleScript,
81
82
  runRiddleServerPreview
82
- } from "./chunk-33XO7WFI.js";
83
+ } from "./chunk-TWTEUS7R.js";
83
84
  import {
84
85
  DEFAULT_DIAGNOSTIC_ARRAY_LIMIT,
85
86
  DEFAULT_DIAGNOSTIC_HISTORY_LIMIT,
@@ -194,6 +195,7 @@ export {
194
195
  buildVisualProofSession,
195
196
  checkpointResponseIdentity,
196
197
  checkpointSummaryFromState,
198
+ collectRiddlePreviewDeployWarnings,
197
199
  collectRiddleProfileArtifactRefs,
198
200
  collectRiddleProofProfileWarnings,
199
201
  compactBasicGameplayText,
@@ -33,6 +33,7 @@ __export(riddle_client_exports, {
33
33
  DEFAULT_RIDDLE_API_BASE_URL: () => DEFAULT_RIDDLE_API_BASE_URL,
34
34
  DEFAULT_RIDDLE_API_KEY_FILE: () => DEFAULT_RIDDLE_API_KEY_FILE,
35
35
  RiddleApiError: () => RiddleApiError,
36
+ collectRiddlePreviewDeployWarnings: () => collectRiddlePreviewDeployWarnings,
36
37
  createRiddleApiClient: () => createRiddleApiClient,
37
38
  deployRiddlePreview: () => deployRiddlePreview,
38
39
  deployRiddleStaticPreview: () => deployRiddleStaticPreview,
@@ -122,6 +123,7 @@ function previewDeployResultFromRecord(input) {
122
123
  expires_at: expiresAt,
123
124
  publish_recovered: publishRecovered || void 0,
124
125
  publish_error: publishError,
126
+ warnings: input.warnings?.length ? input.warnings : void 0,
125
127
  raw: record
126
128
  };
127
129
  }
@@ -139,7 +141,8 @@ async function waitForPublishedPreview(config, input) {
139
141
  framework: input.framework,
140
142
  expiresAt: input.expiresAt,
141
143
  publishRecovered: true,
142
- publishError: input.publishError.message
144
+ publishError: input.publishError.message,
145
+ warnings: input.warnings
143
146
  });
144
147
  }
145
148
  if (attempt < PREVIEW_PUBLISH_RECOVERY_ATTEMPTS) {
@@ -152,6 +155,7 @@ async function deployRiddlePreview(config, directory, label, framework = "static
152
155
  if (!directory?.trim()) throw new Error("directory is required");
153
156
  if (!label?.trim()) throw new Error("label is required");
154
157
  if (framework !== "spa" && framework !== "static") throw new Error("framework must be spa or static");
158
+ const warnings = collectRiddlePreviewDeployWarnings(directory, framework);
155
159
  const created = await riddleRequestJson(config, "/v1/preview", {
156
160
  method: "POST",
157
161
  body: JSON.stringify({ framework, label })
@@ -179,7 +183,7 @@ async function deployRiddlePreview(config, directory, label, framework = "static
179
183
  const published = await riddleRequestJson(config, `/v1/preview/${id}/publish`, {
180
184
  method: "POST"
181
185
  });
182
- return previewDeployResultFromRecord({ record: published, id, label, framework, expiresAt });
186
+ return previewDeployResultFromRecord({ record: published, id, label, framework, expiresAt, warnings });
183
187
  } catch (error) {
184
188
  if (!canRecoverPreviewPublish(error)) throw error;
185
189
  return waitForPublishedPreview(config, {
@@ -187,10 +191,58 @@ async function deployRiddlePreview(config, directory, label, framework = "static
187
191
  label,
188
192
  framework,
189
193
  expiresAt,
190
- publishError: error
194
+ publishError: error,
195
+ warnings
191
196
  });
192
197
  }
193
198
  }
199
+ function latestMatchingMtimeMs(directory, predicate) {
200
+ let latest = 0;
201
+ const stack = [directory];
202
+ let visited = 0;
203
+ while (stack.length) {
204
+ const current = stack.pop();
205
+ for (const entry of (0, import_node_fs.readdirSync)(current, { withFileTypes: true })) {
206
+ const fullPath = import_node_path.default.join(current, entry.name);
207
+ if (entry.isDirectory()) {
208
+ stack.push(fullPath);
209
+ continue;
210
+ }
211
+ if (!entry.isFile() || !predicate(fullPath)) continue;
212
+ const stat = (0, import_node_fs.statSync)(fullPath);
213
+ latest = Math.max(latest, stat.mtimeMs);
214
+ visited += 1;
215
+ if (visited >= 1e4) return latest;
216
+ }
217
+ }
218
+ return latest;
219
+ }
220
+ function collectRiddlePreviewDeployWarnings(directory, framework = "static") {
221
+ try {
222
+ if (framework !== "static") return [];
223
+ const resolvedDirectory = import_node_path.default.resolve(directory);
224
+ if (import_node_path.default.basename(resolvedDirectory) !== "out") return [];
225
+ const repoRoot = import_node_path.default.dirname(resolvedDirectory);
226
+ const nextAppDir = import_node_path.default.join(repoRoot, ".next", "server", "app");
227
+ if (!(0, import_node_fs.existsSync)(nextAppDir)) return [];
228
+ const nextRenderedMtimeMs = latestMatchingMtimeMs(nextAppDir, (filePath) => /\.(?:html|rsc)$/i.test(filePath));
229
+ if (!nextRenderedMtimeMs) return [];
230
+ const outRenderedMtimeMs = (0, import_node_fs.existsSync)(resolvedDirectory) ? latestMatchingMtimeMs(resolvedDirectory, (filePath) => /\.(?:html|txt|rsc)$/i.test(filePath)) : 0;
231
+ if (!outRenderedMtimeMs) {
232
+ return [
233
+ "Riddle Preview static deploy target is an out/ directory with newer Next render output in .next/server/app, but no rendered HTML/RSC files were found in out/. Run the project static bundle/export step before deploying."
234
+ ];
235
+ }
236
+ if (nextRenderedMtimeMs > outRenderedMtimeMs + 1e3) {
237
+ return [
238
+ "Riddle Preview static deploy target out/ appears older than the Next render output in .next/server/app. Run the project static bundle/export step, such as npm run build:static-deploy or next export, before deploying to avoid a stale Preview."
239
+ ];
240
+ }
241
+ return [];
242
+ } catch {
243
+ return [];
244
+ }
245
+ }
194
246
  async function deployRiddleStaticPreview(config, directory, label) {
195
247
  return deployRiddlePreview(config, directory, label, "static");
196
248
  }
@@ -458,6 +510,7 @@ function createRiddleApiClient(config = {}) {
458
510
  DEFAULT_RIDDLE_API_BASE_URL,
459
511
  DEFAULT_RIDDLE_API_KEY_FILE,
460
512
  RiddleApiError,
513
+ collectRiddlePreviewDeployWarnings,
461
514
  createRiddleApiClient,
462
515
  deployRiddlePreview,
463
516
  deployRiddleStaticPreview,
@@ -65,6 +65,7 @@ interface RiddlePreviewDeployResult {
65
65
  expires_at?: string;
66
66
  publish_recovered?: boolean;
67
67
  publish_error?: string;
68
+ warnings?: string[];
68
69
  raw?: Record<string, unknown>;
69
70
  }
70
71
  interface RiddleRunScriptInput {
@@ -129,6 +130,7 @@ declare function resolveRiddleApiKey(config?: RiddleClientConfig): string;
129
130
  declare function riddleRequestJson<T = unknown>(config: RiddleClientConfig, pathname: string, init?: RequestInit): Promise<T>;
130
131
  declare function getRiddleBalance(config?: RiddleClientConfig): Promise<RiddleBalanceResult>;
131
132
  declare function deployRiddlePreview(config: RiddleClientConfig, directory: string, label: string, framework?: RiddlePreviewFramework): Promise<RiddlePreviewDeployResult>;
133
+ declare function collectRiddlePreviewDeployWarnings(directory: string, framework?: RiddlePreviewFramework): string[];
132
134
  declare function deployRiddleStaticPreview(config: RiddleClientConfig, directory: string, label: string): Promise<RiddlePreviewDeployResult>;
133
135
  declare function parseRiddleViewport(value?: string): {
134
136
  width: number;
@@ -149,4 +151,4 @@ declare function createRiddleApiClient(config?: RiddleClientConfig): {
149
151
  pollJob: (jobId: string, options?: RiddlePollJobOptions) => Promise<RiddlePollJobResult>;
150
152
  };
151
153
 
152
- export { DEFAULT_RIDDLE_API_BASE_URL, DEFAULT_RIDDLE_API_KEY_FILE, RiddleApiError, type RiddleApiKeySource, type RiddleBalanceResult, type RiddleClientConfig, type RiddleFetch, type RiddlePollJobOptions, type RiddlePollJobResult, type RiddlePollProgressSnapshot, type RiddlePollSummary, type RiddlePreviewDeployResult, type RiddlePreviewFramework, type RiddleRunScriptInput, type RiddleServerPreviewInput, type RiddleServerPreviewResult, createRiddleApiClient, deployRiddlePreview, deployRiddleStaticPreview, getRiddleBalance, isTerminalRiddleJobStatus, parseRiddleViewport, pollRiddleJob, resolveRiddleApiKey, resolveRiddleApiKeySource, riddleRequestJson, runRiddleScript, runRiddleServerPreview };
154
+ export { DEFAULT_RIDDLE_API_BASE_URL, DEFAULT_RIDDLE_API_KEY_FILE, RiddleApiError, type RiddleApiKeySource, type RiddleBalanceResult, type RiddleClientConfig, type RiddleFetch, type RiddlePollJobOptions, type RiddlePollJobResult, type RiddlePollProgressSnapshot, type RiddlePollSummary, type RiddlePreviewDeployResult, type RiddlePreviewFramework, type RiddleRunScriptInput, type RiddleServerPreviewInput, type RiddleServerPreviewResult, collectRiddlePreviewDeployWarnings, createRiddleApiClient, deployRiddlePreview, deployRiddleStaticPreview, getRiddleBalance, isTerminalRiddleJobStatus, parseRiddleViewport, pollRiddleJob, resolveRiddleApiKey, resolveRiddleApiKeySource, riddleRequestJson, runRiddleScript, runRiddleServerPreview };
@@ -65,6 +65,7 @@ interface RiddlePreviewDeployResult {
65
65
  expires_at?: string;
66
66
  publish_recovered?: boolean;
67
67
  publish_error?: string;
68
+ warnings?: string[];
68
69
  raw?: Record<string, unknown>;
69
70
  }
70
71
  interface RiddleRunScriptInput {
@@ -129,6 +130,7 @@ declare function resolveRiddleApiKey(config?: RiddleClientConfig): string;
129
130
  declare function riddleRequestJson<T = unknown>(config: RiddleClientConfig, pathname: string, init?: RequestInit): Promise<T>;
130
131
  declare function getRiddleBalance(config?: RiddleClientConfig): Promise<RiddleBalanceResult>;
131
132
  declare function deployRiddlePreview(config: RiddleClientConfig, directory: string, label: string, framework?: RiddlePreviewFramework): Promise<RiddlePreviewDeployResult>;
133
+ declare function collectRiddlePreviewDeployWarnings(directory: string, framework?: RiddlePreviewFramework): string[];
132
134
  declare function deployRiddleStaticPreview(config: RiddleClientConfig, directory: string, label: string): Promise<RiddlePreviewDeployResult>;
133
135
  declare function parseRiddleViewport(value?: string): {
134
136
  width: number;
@@ -149,4 +151,4 @@ declare function createRiddleApiClient(config?: RiddleClientConfig): {
149
151
  pollJob: (jobId: string, options?: RiddlePollJobOptions) => Promise<RiddlePollJobResult>;
150
152
  };
151
153
 
152
- export { DEFAULT_RIDDLE_API_BASE_URL, DEFAULT_RIDDLE_API_KEY_FILE, RiddleApiError, type RiddleApiKeySource, type RiddleBalanceResult, type RiddleClientConfig, type RiddleFetch, type RiddlePollJobOptions, type RiddlePollJobResult, type RiddlePollProgressSnapshot, type RiddlePollSummary, type RiddlePreviewDeployResult, type RiddlePreviewFramework, type RiddleRunScriptInput, type RiddleServerPreviewInput, type RiddleServerPreviewResult, createRiddleApiClient, deployRiddlePreview, deployRiddleStaticPreview, getRiddleBalance, isTerminalRiddleJobStatus, parseRiddleViewport, pollRiddleJob, resolveRiddleApiKey, resolveRiddleApiKeySource, riddleRequestJson, runRiddleScript, runRiddleServerPreview };
154
+ export { DEFAULT_RIDDLE_API_BASE_URL, DEFAULT_RIDDLE_API_KEY_FILE, RiddleApiError, type RiddleApiKeySource, type RiddleBalanceResult, type RiddleClientConfig, type RiddleFetch, type RiddlePollJobOptions, type RiddlePollJobResult, type RiddlePollProgressSnapshot, type RiddlePollSummary, type RiddlePreviewDeployResult, type RiddlePreviewFramework, type RiddleRunScriptInput, type RiddleServerPreviewInput, type RiddleServerPreviewResult, collectRiddlePreviewDeployWarnings, createRiddleApiClient, deployRiddlePreview, deployRiddleStaticPreview, getRiddleBalance, isTerminalRiddleJobStatus, parseRiddleViewport, pollRiddleJob, resolveRiddleApiKey, resolveRiddleApiKeySource, riddleRequestJson, runRiddleScript, runRiddleServerPreview };
@@ -2,6 +2,7 @@ import {
2
2
  DEFAULT_RIDDLE_API_BASE_URL,
3
3
  DEFAULT_RIDDLE_API_KEY_FILE,
4
4
  RiddleApiError,
5
+ collectRiddlePreviewDeployWarnings,
5
6
  createRiddleApiClient,
6
7
  deployRiddlePreview,
7
8
  deployRiddleStaticPreview,
@@ -14,11 +15,12 @@ import {
14
15
  riddleRequestJson,
15
16
  runRiddleScript,
16
17
  runRiddleServerPreview
17
- } from "./chunk-33XO7WFI.js";
18
+ } from "./chunk-TWTEUS7R.js";
18
19
  export {
19
20
  DEFAULT_RIDDLE_API_BASE_URL,
20
21
  DEFAULT_RIDDLE_API_KEY_FILE,
21
22
  RiddleApiError,
23
+ collectRiddlePreviewDeployWarnings,
22
24
  createRiddleApiClient,
23
25
  deployRiddlePreview,
24
26
  deployRiddleStaticPreview,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@riddledc/riddle-proof",
3
- "version": "0.7.217",
3
+ "version": "0.7.219",
4
4
  "description": "Reusable Riddle Proof contracts and helpers for evidence-backed agent changes.",
5
5
  "license": "MIT",
6
6
  "author": "RiddleDC",