@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 +9 -0
- package/dist/cli.cjs +17 -3
- package/dist/cli.js +17 -3
- package/examples/profiles/gameplay-window-call-until.json +101 -0
- package/package.json +1 -1
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
|
-
|
|
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
|
-
|
|
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
|
+
}
|