@riddledc/riddle-proof 0.7.178 → 0.7.180

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -192,6 +192,10 @@ riddle-proof-loop run-profile \
192
192
  Hosted profile runs emit Riddle poll progress to stderr while waiting. Use
193
193
  `--quiet` to suppress progress lines, or `--progress-every-ms` to tune the
194
194
  heartbeat cadence for long route-inventory or workflow profiles.
195
+ By default, `run-profile` writes the full JSON result to stdout for automation.
196
+ For agent loops where the saved artifacts are the source of truth, use
197
+ `--result-format summary` to print the same compact Markdown summary that is
198
+ written to `summary.md`, or `--result-format none` to leave stdout empty.
195
199
  Hosted `run-profile` submits package-generated profile scripts with
196
200
  `strict=false` by default because the generated runner is larger than Riddle's
197
201
  generic inline-script warning threshold. Use `--strict=true` when you
@@ -240,6 +244,7 @@ The package includes generic starter profiles:
240
244
  - `examples/profiles/handled-recovery-list-load.json` for failed or malformed list-load recovery profiles.
241
245
  - `examples/profiles/handled-recovery-action-malformed-success.json` for action recovery profiles where the request succeeds at HTTP level but returns an unusable body.
242
246
  - `examples/profiles/terminal-result-partial-evidence.json` for API-console terminal error or timeout receipts that preserve partial screenshot, console, and HAR evidence.
247
+ - `examples/profiles/gameplay-window-call-until.json` for gameplay profiles that wait on a runtime state contract instead of a fixed sleep.
243
248
 
244
249
  Copy one of those shapes into a repository profile directory and replace the
245
250
  routes, selectors, mock URLs, and text checks with app-specific invariants.
@@ -487,6 +492,10 @@ progressive state until a window-state receipt is true. It accepts `path` plus
487
492
  optional `args`, `until_path`, `until_expected_value`, `max_calls` from 1 to
488
493
  100, and optional `interval_ms`; the action stops early when the predicate is
489
494
  met and records `call_count`, final `returned`, and final `until_value`.
495
+ For gameplay progression, prefer this to a fixed `wait` when frame cadence or
496
+ hosted-runner timing can vary by viewport; install a small `window` helper that
497
+ returns JSON-safe state, stores the latest receipt, and makes the pass condition
498
+ explicit. See `examples/profiles/gameplay-window-call-until.json`.
490
499
  Use `screenshot` with an optional `label` to capture durable Riddle screenshots
491
500
  at important setup milestones, such as after a route switch, terminal state, or
492
501
  reset. These labels are recorded in setup evidence and included in profile
package/dist/cli.cjs CHANGED
@@ -15765,7 +15765,7 @@ function usage() {
15765
15765
  " riddle-proof-loop respond --state-path <path> --response-json <file|json|->",
15766
15766
  " riddle-proof-loop respond --state-path <path> --decision <decision> --summary <text> [--payload-json <file|json|->]",
15767
15767
  " riddle-proof-loop status --state-path <path>",
15768
- " riddle-proof-loop run-profile --profile <file|json|-> --url <base-url> [--runner riddle] [--strict true|false; default false] [--split-viewports true|false; default false] [--poll-attempts n] [--output <dir>|--output-dir <dir>] [--quiet]",
15768
+ " riddle-proof-loop run-profile --profile <file|json|-> --url <base-url> [--runner riddle] [--strict true|false; default false] [--split-viewports true|false; default false] [--poll-attempts n] [--output <dir>|--output-dir <dir>] [--result-format json|summary|none; default json] [--quiet]",
15769
15769
  " riddle-proof-loop profile-body-assertions --artifact <file|url|-> --candidates-json <file|json|-> [--required-json <file|json|->] [--format json|body-contains]",
15770
15770
  " riddle-proof-loop profile-http-status-preflight --profile <file|json|-> --url <base-url> [--format json|summary]",
15771
15771
  " riddle-proof-loop riddle-preview-deploy <build-dir> <label> [--framework spa|static]",
@@ -15842,6 +15842,21 @@ function optionInteger(options, fallback, ...keys) {
15842
15842
  function profileOutputDirOption(options) {
15843
15843
  return optionString(options, "output") ?? optionString(options, "outputDir");
15844
15844
  }
15845
+ function runProfileResultFormatOption(options) {
15846
+ const format = optionString(options, "resultFormat") ?? "json";
15847
+ if (format === "json" || format === "summary" || format === "none") return format;
15848
+ throw new Error("--result-format must be json, summary, or none.");
15849
+ }
15850
+ function writeRunProfileResult(result, options) {
15851
+ const format = runProfileResultFormatOption(options);
15852
+ if (format === "none") return;
15853
+ if (format === "summary") {
15854
+ process.stdout.write(profileResultMarkdown(result));
15855
+ return;
15856
+ }
15857
+ process.stdout.write(`${JSON.stringify(result, null, 2)}
15858
+ `);
15859
+ }
15845
15860
  function previewFrameworkOption(options) {
15846
15861
  const framework = optionString(options, "framework") ?? "static";
15847
15862
  if (framework === "spa" || framework === "static") return framework;
@@ -17600,8 +17615,7 @@ async function main() {
17600
17615
  process.stderr.write(`${diagnosticLine}
17601
17616
  `);
17602
17617
  }
17603
- process.stdout.write(`${JSON.stringify(result, null, 2)}
17604
- `);
17618
+ writeRunProfileResult(result, options);
17605
17619
  process.exitCode = profileStatusExitCode(profile, result.status);
17606
17620
  return;
17607
17621
  }
package/dist/cli.js CHANGED
@@ -48,7 +48,7 @@ function usage() {
48
48
  " riddle-proof-loop respond --state-path <path> --response-json <file|json|->",
49
49
  " riddle-proof-loop respond --state-path <path> --decision <decision> --summary <text> [--payload-json <file|json|->]",
50
50
  " riddle-proof-loop status --state-path <path>",
51
- " riddle-proof-loop run-profile --profile <file|json|-> --url <base-url> [--runner riddle] [--strict true|false; default false] [--split-viewports true|false; default false] [--poll-attempts n] [--output <dir>|--output-dir <dir>] [--quiet]",
51
+ " riddle-proof-loop run-profile --profile <file|json|-> --url <base-url> [--runner riddle] [--strict true|false; default false] [--split-viewports true|false; default false] [--poll-attempts n] [--output <dir>|--output-dir <dir>] [--result-format json|summary|none; default json] [--quiet]",
52
52
  " riddle-proof-loop profile-body-assertions --artifact <file|url|-> --candidates-json <file|json|-> [--required-json <file|json|->] [--format json|body-contains]",
53
53
  " riddle-proof-loop profile-http-status-preflight --profile <file|json|-> --url <base-url> [--format json|summary]",
54
54
  " riddle-proof-loop riddle-preview-deploy <build-dir> <label> [--framework spa|static]",
@@ -125,6 +125,21 @@ function optionInteger(options, fallback, ...keys) {
125
125
  function profileOutputDirOption(options) {
126
126
  return optionString(options, "output") ?? optionString(options, "outputDir");
127
127
  }
128
+ function runProfileResultFormatOption(options) {
129
+ const format = optionString(options, "resultFormat") ?? "json";
130
+ if (format === "json" || format === "summary" || format === "none") return format;
131
+ throw new Error("--result-format must be json, summary, or none.");
132
+ }
133
+ function writeRunProfileResult(result, options) {
134
+ const format = runProfileResultFormatOption(options);
135
+ if (format === "none") return;
136
+ if (format === "summary") {
137
+ process.stdout.write(profileResultMarkdown(result));
138
+ return;
139
+ }
140
+ process.stdout.write(`${JSON.stringify(result, null, 2)}
141
+ `);
142
+ }
128
143
  function previewFrameworkOption(options) {
129
144
  const framework = optionString(options, "framework") ?? "static";
130
145
  if (framework === "spa" || framework === "static") return framework;
@@ -1883,8 +1898,7 @@ async function main() {
1883
1898
  process.stderr.write(`${diagnosticLine}
1884
1899
  `);
1885
1900
  }
1886
- process.stdout.write(`${JSON.stringify(result, null, 2)}
1887
- `);
1901
+ writeRunProfileResult(result, options);
1888
1902
  process.exitCode = profileStatusExitCode(profile, result.status);
1889
1903
  return;
1890
1904
  }
@@ -0,0 +1,101 @@
1
+ {
2
+ "version": "riddle-proof.profile.v1",
3
+ "name": "gameplay-window-call-until",
4
+ "target": {
5
+ "route": "/games/example",
6
+ "viewports": [
7
+ { "name": "mobile", "width": 390, "height": 844 },
8
+ { "name": "tablet", "width": 820, "height": 1180 },
9
+ { "name": "desktop", "width": 1440, "height": 1000 }
10
+ ],
11
+ "timeout_sec": 300,
12
+ "wait_for_selector": "#game-root canvas",
13
+ "screenshot_mode": "viewport",
14
+ "setup_actions": [
15
+ { "type": "clear_storage", "storage": "both", "reload": true },
16
+ { "type": "wait_for_selector", "selector": "#game-root", "timeout_ms": 20000 },
17
+ { "type": "wait_for_selector", "selector": "#game-root canvas", "timeout_ms": 20000 },
18
+ {
19
+ "type": "window_eval",
20
+ "label": "install-gameplay-proof-reader",
21
+ "timeout_ms": 10000,
22
+ "store_return_to": "__gameplayProof.ready",
23
+ "script": "window.__riddleGameplayStep=()=>{const api=window.__exampleGameProof;const state=api?.step?.()||api?.read?.()||{};const out={ready:state.ready===true,inputAccepted:state.inputAccepted===true,gameOver:state.gameOver===true,distance:Number(state.distance||0),score:Number(state.score||0),level:Number(state.level||0)};out.ok=out.ready&&out.inputAccepted&&out.gameOver===false&&out.distance>=2&&out.score>=10;window.__gameplayProof={...(window.__gameplayProof||{}),running:out};return out;};const api=window.__exampleGameProof;const initial=api?.read?.()||{};const out={ready:initial.ready===true,inputAccepted:initial.inputAccepted===true,gameOver:initial.gameOver===true,distance:Number(initial.distance||0),score:Number(initial.score||0),level:Number(initial.level||0)};window.__gameplayProof={...(window.__gameplayProof||{}),ready:out};return out;",
24
+ "return_summary_fields": [
25
+ { "path": "ready" },
26
+ { "path": "inputAccepted" },
27
+ { "path": "distance" },
28
+ { "path": "score" },
29
+ { "path": "gameOver" }
30
+ ]
31
+ },
32
+ { "type": "assert_window_value", "path": "__gameplayProof.ready.ready", "expected": true, "timeout_ms": 10000 },
33
+ {
34
+ "type": "canvas_signature",
35
+ "selector": "#game-root canvas",
36
+ "label": "ready",
37
+ "store_signature_to": "__gameplayProof.readyCanvas",
38
+ "timeout_ms": 10000
39
+ },
40
+ { "type": "screenshot", "label": "ready", "mode": "viewport" },
41
+ { "type": "press", "key": "Space", "after_ms": 120 },
42
+ { "type": "press", "key": "ArrowRight", "after_ms": 120 },
43
+ {
44
+ "type": "window_call_until",
45
+ "path": "__riddleGameplayStep",
46
+ "until_path": "__gameplayProof.running.ok",
47
+ "until_expected_value": true,
48
+ "max_calls": 36,
49
+ "interval_ms": 250,
50
+ "timeout_ms": 15000
51
+ },
52
+ {
53
+ "type": "window_eval",
54
+ "label": "capture-running-proof",
55
+ "timeout_ms": 10000,
56
+ "store_return_to": "__gameplayProof.running",
57
+ "script": "return window.__riddleGameplayStep?.()||{};",
58
+ "return_summary_fields": [
59
+ { "path": "ok" },
60
+ { "path": "distance" },
61
+ { "path": "score" },
62
+ { "path": "inputAccepted" },
63
+ { "path": "gameOver" }
64
+ ]
65
+ },
66
+ { "type": "assert_window_value", "path": "__gameplayProof.running.ok", "expected": true, "timeout_ms": 10000 },
67
+ { "type": "assert_window_value", "path": "__gameplayProof.running.gameOver", "expected": false, "timeout_ms": 10000 },
68
+ { "type": "assert_window_number", "path": "__gameplayProof.running.distance", "min_value": 2, "timeout_ms": 10000 },
69
+ { "type": "assert_window_number", "path": "__gameplayProof.running.score", "min_value": 10, "timeout_ms": 10000 },
70
+ {
71
+ "type": "canvas_signature",
72
+ "selector": "#game-root canvas",
73
+ "label": "running",
74
+ "store_signature_to": "__gameplayProof.runningCanvas",
75
+ "timeout_ms": 10000
76
+ },
77
+ { "type": "screenshot", "label": "running", "mode": "viewport" }
78
+ ]
79
+ },
80
+ "checks": [
81
+ { "type": "route_loaded", "expected_path": "/games/example" },
82
+ { "type": "selector_visible", "selector": "#game-root" },
83
+ { "type": "selector_visible", "selector": "#game-root canvas" },
84
+ { "type": "selector_count_equals", "selector": "#game-root canvas", "expected_count": 1 },
85
+ { "type": "text_absent", "pattern": "\\bNaN\\b" },
86
+ { "type": "text_absent", "pattern": "undefined", "flags": "i" },
87
+ { "type": "no_horizontal_overflow", "max_overflow_px": 1 },
88
+ { "type": "no_fatal_console_errors" },
89
+ { "type": "no_console_warnings" }
90
+ ],
91
+ "artifacts": ["screenshot", "console", "dom_summary", "proof_json"],
92
+ "baseline_policy": "invariant_only",
93
+ "failure_policy": {
94
+ "environment_blocked": "neutral",
95
+ "proof_insufficient": "fail",
96
+ "product_regression": "fail"
97
+ },
98
+ "metadata": {
99
+ "purpose": "Template for gameplay profiles where a route exposes window.__exampleGameProof.read() and optionally step(). Use window_call_until to wait for runtime state such as accepted input, distance, score, or level completion instead of relying on fixed sleeps that vary across hosted browser frame cadence."
100
+ }
101
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@riddledc/riddle-proof",
3
- "version": "0.7.178",
3
+ "version": "0.7.180",
4
4
  "description": "Reusable Riddle Proof contracts and helpers for evidence-backed agent changes.",
5
5
  "license": "MIT",
6
6
  "author": "RiddleDC",