jourilo 1.2.1 → 1.3.0

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.
@@ -8,7 +8,13 @@ Every command prints human-readable text, or JSON with `--json`. Errors go to st
8
8
  6 stopped early by SIGINT/SIGTERM or `--max-duration` (a partial run is still written; a second signal exits 130).
9
9
 
10
10
  Global options: `--json`, `--workspace DIR` (default `.jourilo`, or `JOURILO_WORKSPACE`), `--quiet`. With `--json`,
11
- progress lines on stderr are JSON too: `{"type":"progress","message":"…","at":"<ISO time>"}`.
11
+ progress lines on stderr are JSON too: `{"type":"progress","message":"…","at":"<ISO time>"}`. Lines from the audit
12
+ pipeline also carry `phase` (launch, discover, setup, capture, metrics, forms or report; `rules` is reserved and not
13
+ emitted yet) and, where known exactly, `done`, `total`, `url` and `viewport`. `done` counts the steps of that phase
14
+ finished before this step started, so the last line of a phase has `done` = `total` − 1; the phase is over when the
15
+ next phase's first line arrives or the run ends. `url` is redacted like the message, and the `message` text is the
16
+ same as the plain line (see docs/RUN-FORMAT.md). `--workspace` is also the output directory: every run is written
17
+ to `DIR/runs/<id>/` (there is no separate `--output-dir`).
12
18
 
13
19
  ## Understand
14
20
 
@@ -22,11 +28,31 @@ jourilo discover <path|url> [--pages 10] [--ignore-robots] [--allow-private] [--
22
28
 
23
29
  ```
24
30
  Options:
25
- --pages N Pages to read when mapping a website (default 10)
26
- --ignore-robots Ignore robots.txt (only for sites you own or are authorized to test)
27
- --allow-private Allow private-network hosts (10.x, 192.168.x, ...)
28
- --deny-local Refuse local targets (localhost, 127.0.0.1, [::1], *.localhost, *.test) (exit 3); a redirect or request to one is blocked by the network guard and listed in the limitations;
29
- JOURILO_DENY_LOCAL=1 does the same
31
+ --pages N Pages to read when mapping a website (default 10)
32
+ --ignore-robots Ignore robots.txt (only for sites you own or are authorized to test)
33
+ --allow-private Allow private-network hosts (10.x, 192.168.x, ...)
34
+ --deny-local Refuse local targets (localhost, 127.0.0.1, [::1], *.localhost, *.test) (exit 3); a redirect or request to one is blocked by the network guard and listed in the limitations;
35
+ JOURILO_DENY_LOCAL=1 does the same
36
+ --proxy URL Chain to an upstream HTTP proxy (http://[user:password@]host:port) behind the network guard;
37
+ default HTTPS_PROXY / HTTP_PROXY (either case; prefer the variable for credentials, argv shows
38
+ in ps). NO_PROXY is decided per destination host (NO_PROXY=* = no proxy). The guard resolves and
39
+ checks every destination itself, then tunnels to the checked address (CONNECT ip:443, and ip:80
40
+ for plain HTTP; a proxy that refuses port 80 fails those requests: give an https:// target);
41
+ loopback connects directly. The run records the proxy without its credentials
42
+ --allow-hosts LIST Only these hosts may be reached (comma-separated or repeated; *.example.com = its subdomains);
43
+ the target's own host is always allowed. Other hosts are refused and listed in the limitations
44
+ --block-hosts LIST Refuse these hosts (e.g. *.tracker.example); refused requests are listed in the limitations
45
+ --user-agent UA Send this User-Agent (also navigator.userAgent) instead of the browser's own; recorded in the run
46
+ --extra-header H Add a request header "Name: value" (repeatable), sent only to the target's origin, never
47
+ to other hosts: Jourilo makes those requests itself, so the headers cannot follow a redirect
48
+ elsewhere (a redirect is followed without them). The run records the names, never the values
49
+ --ignore-https-errors
50
+ Accept invalid or self-signed certificates in the browser (test environments only); the network
51
+ guard still checks every destination, and the run lists it in the limitations
52
+ --chromium-sandbox
53
+ Keep Chromium's own process sandbox (Playwright disables it by default); JOURILO_CHROMIUM_SANDBOX=1
54
+ does the same. Chromium, Chrome and Edge only (a usage error with Firefox or WebKit). Fails to launch
55
+ where the system denies the sandbox (containers, some Linux CI kernels)
30
56
  ```
31
57
 
32
58
  ## Audit
@@ -36,7 +62,7 @@ Options:
36
62
  Audit a website URL or a static build directory in a real browser (accessibility, UX, responsive, performance, reliability, conversion).
37
63
 
38
64
  ```
39
- jourilo audit <url|dir> [--pages 6] [--viewports desktop,mobile] [--url /path ...] [--repo .] [--fail-on serious]
65
+ jourilo audit <url|dir> [--pages 6] [--viewports desktop,mobile] [--url /path ...] [--repo .] [--fail-on serious] [--budget LCP=2000]
40
66
  ```
41
67
 
42
68
  ```
@@ -50,6 +76,8 @@ Options:
50
76
  --headed Show the browser window instead of running headless
51
77
  --locale TAG Browser locale for every page (e.g. tr-TR); sets Accept-Language and navigator.language
52
78
  --timeout SECS Per-page navigation timeout in seconds (default 30)
79
+ --wait-for SELECTOR Capture each page only once this element is visible (client-rendered pages); if it never appears within
80
+ --timeout the page is still audited, with a limitation. Each capture records how it loaded
53
81
  --throttle Simulate a mid-range phone network and 4x CPU slowdown (Chromium)
54
82
  --runs N Visits per page and viewport for lab metrics; reports the median and range (default 1, max 9)
55
83
  --no-keyboard Skip the keyboard-only walk
@@ -65,6 +93,26 @@ Options:
65
93
  --allow-private Allow private-network hosts (10.x, 192.168.x, ...)
66
94
  --deny-local Refuse local targets (localhost, 127.0.0.1, [::1], *.localhost, *.test) (exit 3); a redirect or request to one is blocked by the network guard and listed in the limitations;
67
95
  JOURILO_DENY_LOCAL=1 does the same. Not available with --browser webkit (exit 3). For hosted integrations; a directory target is still served
96
+ --proxy URL Chain to an upstream HTTP proxy (http://[user:password@]host:port) behind the network guard;
97
+ default HTTPS_PROXY / HTTP_PROXY (either case; prefer the variable for credentials, argv shows
98
+ in ps). NO_PROXY is decided per destination host (NO_PROXY=* = no proxy). The guard resolves and
99
+ checks every destination itself, then tunnels to the checked address (CONNECT ip:443, and ip:80
100
+ for plain HTTP; a proxy that refuses port 80 fails those requests: give an https:// target);
101
+ loopback connects directly. The run records the proxy without its credentials
102
+ --allow-hosts LIST Only these hosts may be reached (comma-separated or repeated; *.example.com = its subdomains);
103
+ the target's own host is always allowed. Other hosts are refused and listed in the limitations
104
+ --block-hosts LIST Refuse these hosts (e.g. *.tracker.example); refused requests are listed in the limitations
105
+ --user-agent UA Send this User-Agent (also navigator.userAgent) instead of the browser's own; recorded in the run
106
+ --extra-header H Add a request header "Name: value" (repeatable), sent only to the target's origin, never
107
+ to other hosts: Jourilo makes those requests itself, so the headers cannot follow a redirect
108
+ elsewhere (a redirect is followed without them). The run records the names, never the values
109
+ --ignore-https-errors
110
+ Accept invalid or self-signed certificates in the browser (test environments only); the network
111
+ guard still checks every destination, and the run lists it in the limitations
112
+ --chromium-sandbox
113
+ Keep Chromium's own process sandbox (Playwright disables it by default); JOURILO_CHROMIUM_SANDBOX=1
114
+ does the same. Chromium, Chrome and Edge only (a usage error with Firefox or WebKit). Fails to launch
115
+ where the system denies the sandbox (containers, some Linux CI kernels)
68
116
  --no-forms Skip the form validation probe
69
117
  (by default, on local hosts, an empty submission is simulated: nothing that sends data
70
118
  leaves the browser, so no database is written; server-side feedback is reported as untested)
@@ -73,6 +121,9 @@ Options:
73
121
  also lets a --setup-journey submit forms
74
122
  --sarif Also write report.sarif for code scanning
75
123
  --fail-on SEVERITY Exit 1 if a defect at or above this severity exists (CI gate)
124
+ --budget LIST Exit 1 when a lab metric exceeds its limit, e.g. LCP=2000,CLS=0.05,TBT=300 (LCP, CLS, INP, FCP,
125
+ TTFB, TBT; ms, CLS unitless). Each capture's median is compared and the worst capture decides;
126
+ a metric no page measured (INP) is reported as not measured, not as a pass. Combines with --fail-on
76
127
  --evidence MODE full (default) or minimal: keep first screens and only the full-page screenshots findings need; JPEG quality 55
77
128
  --run-id ID Use this run id instead of a generated one (1-64 of A-Z a-z 0-9 _ -); refused (exit 2) if its
78
129
  directory exists, even without a run.json (left by a crashed run)
@@ -100,6 +151,8 @@ Options:
100
151
  --headed Show the browser window instead of running headless
101
152
  --locale TAG Browser locale for every page (e.g. tr-TR); sets Accept-Language and navigator.language
102
153
  --timeout SECS Per-page navigation timeout in seconds (default 30)
154
+ --wait-for SELECTOR Capture each page only once this element is visible (client-rendered pages); if it never appears within
155
+ --timeout the page is still audited, with a limitation. Each capture records how it loaded
103
156
  --throttle Simulate a mid-range phone network and 4x CPU slowdown (Chromium)
104
157
  --runs N Visits per page and viewport for lab metrics; reports the median and range (default 1, max 9)
105
158
  --no-keyboard Skip the keyboard-only walk
@@ -115,6 +168,26 @@ Options:
115
168
  --allow-private Allow private-network hosts (10.x, 192.168.x, ...)
116
169
  --deny-local Refuse local targets (localhost, 127.0.0.1, [::1], *.localhost, *.test) (exit 3); a redirect or request to one is blocked by the network guard and listed in the limitations;
117
170
  JOURILO_DENY_LOCAL=1 does the same. Not available with --browser webkit (exit 3). For hosted integrations; a directory target is still served
171
+ --proxy URL Chain to an upstream HTTP proxy (http://[user:password@]host:port) behind the network guard;
172
+ default HTTPS_PROXY / HTTP_PROXY (either case; prefer the variable for credentials, argv shows
173
+ in ps). NO_PROXY is decided per destination host (NO_PROXY=* = no proxy). The guard resolves and
174
+ checks every destination itself, then tunnels to the checked address (CONNECT ip:443, and ip:80
175
+ for plain HTTP; a proxy that refuses port 80 fails those requests: give an https:// target);
176
+ loopback connects directly. The run records the proxy without its credentials
177
+ --allow-hosts LIST Only these hosts may be reached (comma-separated or repeated; *.example.com = its subdomains);
178
+ the target's own host is always allowed. Other hosts are refused and listed in the limitations
179
+ --block-hosts LIST Refuse these hosts (e.g. *.tracker.example); refused requests are listed in the limitations
180
+ --user-agent UA Send this User-Agent (also navigator.userAgent) instead of the browser's own; recorded in the run
181
+ --extra-header H Add a request header "Name: value" (repeatable), sent only to the target's origin, never
182
+ to other hosts: Jourilo makes those requests itself, so the headers cannot follow a redirect
183
+ elsewhere (a redirect is followed without them). The run records the names, never the values
184
+ --ignore-https-errors
185
+ Accept invalid or self-signed certificates in the browser (test environments only); the network
186
+ guard still checks every destination, and the run lists it in the limitations
187
+ --chromium-sandbox
188
+ Keep Chromium's own process sandbox (Playwright disables it by default); JOURILO_CHROMIUM_SANDBOX=1
189
+ does the same. Chromium, Chrome and Edge only (a usage error with Firefox or WebKit). Fails to launch
190
+ where the system denies the sandbox (containers, some Linux CI kernels)
118
191
  --no-forms Skip the form validation probe
119
192
  (by default, on local hosts, an empty submission is simulated: nothing that sends data
120
193
  leaves the browser, so no database is written; server-side feedback is reported as untested)
@@ -123,6 +196,9 @@ Options:
123
196
  also lets a --setup-journey submit forms
124
197
  --sarif Also write report.sarif for code scanning
125
198
  --fail-on SEVERITY Exit 1 if a defect at or above this severity exists (CI gate)
199
+ --budget LIST Exit 1 when a lab metric exceeds its limit, e.g. LCP=2000,CLS=0.05,TBT=300 (LCP, CLS, INP, FCP,
200
+ TTFB, TBT; ms, CLS unitless). Each capture's median is compared and the worst capture decides;
201
+ a metric no page measured (INP) is reported as not measured, not as a pass. Combines with --fail-on
126
202
  --evidence MODE full (default) or minimal: keep first screens and only the full-page screenshots findings need; JPEG quality 55
127
203
  --run-id ID Use this run id instead of a generated one (1-64 of A-Z a-z 0-9 _ -); refused (exit 2) if its
128
204
  directory exists, even without a run.json (left by a crashed run)
@@ -150,6 +226,8 @@ Options:
150
226
  --headed Show the browser window instead of running headless
151
227
  --locale TAG Browser locale for every page (e.g. tr-TR); sets Accept-Language and navigator.language
152
228
  --timeout SECS Per-page navigation timeout in seconds (default 30)
229
+ --wait-for SELECTOR Capture each page only once this element is visible (client-rendered pages); if it never appears within
230
+ --timeout the page is still audited, with a limitation. Each capture records how it loaded
153
231
  --throttle Simulate a mid-range phone network and 4x CPU slowdown (Chromium)
154
232
  --runs N Visits per page and viewport for lab metrics; reports the median and range (default 1, max 9)
155
233
  --no-keyboard Skip the keyboard-only walk
@@ -165,6 +243,26 @@ Options:
165
243
  --allow-private Allow private-network hosts (10.x, 192.168.x, ...)
166
244
  --deny-local Refuse local targets (localhost, 127.0.0.1, [::1], *.localhost, *.test) (exit 3); a redirect or request to one is blocked by the network guard and listed in the limitations;
167
245
  JOURILO_DENY_LOCAL=1 does the same. Not available with --browser webkit (exit 3). For hosted integrations; a directory target is still served
246
+ --proxy URL Chain to an upstream HTTP proxy (http://[user:password@]host:port) behind the network guard;
247
+ default HTTPS_PROXY / HTTP_PROXY (either case; prefer the variable for credentials, argv shows
248
+ in ps). NO_PROXY is decided per destination host (NO_PROXY=* = no proxy). The guard resolves and
249
+ checks every destination itself, then tunnels to the checked address (CONNECT ip:443, and ip:80
250
+ for plain HTTP; a proxy that refuses port 80 fails those requests: give an https:// target);
251
+ loopback connects directly. The run records the proxy without its credentials
252
+ --allow-hosts LIST Only these hosts may be reached (comma-separated or repeated; *.example.com = its subdomains);
253
+ the target's own host is always allowed. Other hosts are refused and listed in the limitations
254
+ --block-hosts LIST Refuse these hosts (e.g. *.tracker.example); refused requests are listed in the limitations
255
+ --user-agent UA Send this User-Agent (also navigator.userAgent) instead of the browser's own; recorded in the run
256
+ --extra-header H Add a request header "Name: value" (repeatable), sent only to the target's origin, never
257
+ to other hosts: Jourilo makes those requests itself, so the headers cannot follow a redirect
258
+ elsewhere (a redirect is followed without them). The run records the names, never the values
259
+ --ignore-https-errors
260
+ Accept invalid or self-signed certificates in the browser (test environments only); the network
261
+ guard still checks every destination, and the run lists it in the limitations
262
+ --chromium-sandbox
263
+ Keep Chromium's own process sandbox (Playwright disables it by default); JOURILO_CHROMIUM_SANDBOX=1
264
+ does the same. Chromium, Chrome and Edge only (a usage error with Firefox or WebKit). Fails to launch
265
+ where the system denies the sandbox (containers, some Linux CI kernels)
168
266
  --no-forms Skip the form validation probe
169
267
  (by default, on local hosts, an empty submission is simulated: nothing that sends data
170
268
  leaves the browser, so no database is written; server-side feedback is reported as untested)
@@ -173,6 +271,9 @@ Options:
173
271
  also lets a --setup-journey submit forms
174
272
  --sarif Also write report.sarif for code scanning
175
273
  --fail-on SEVERITY Exit 1 if a defect at or above this severity exists (CI gate)
274
+ --budget LIST Exit 1 when a lab metric exceeds its limit, e.g. LCP=2000,CLS=0.05,TBT=300 (LCP, CLS, INP, FCP,
275
+ TTFB, TBT; ms, CLS unitless). Each capture's median is compared and the worst capture decides;
276
+ a metric no page measured (INP) is reported as not measured, not as a pass. Combines with --fail-on
176
277
  --evidence MODE full (default) or minimal: keep first screens and only the full-page screenshots findings need; JPEG quality 55
177
278
  --run-id ID Use this run id instead of a generated one (1-64 of A-Z a-z 0-9 _ -); refused (exit 2) if its
178
279
  directory exists, even without a run.json (left by a crashed run)
@@ -204,6 +305,26 @@ Suggest options:
204
305
  --allow-private Allow private-network hosts (10.x, 192.168.x, ...)
205
306
  --deny-local Refuse local targets (localhost, 127.0.0.1, [::1], *.localhost, *.test) (exit 3); a redirect or request to one is blocked by the network guard and listed in the limitations;
206
307
  JOURILO_DENY_LOCAL=1 does the same
308
+ --proxy URL Chain to an upstream HTTP proxy (http://[user:password@]host:port) behind the network guard;
309
+ default HTTPS_PROXY / HTTP_PROXY (either case; prefer the variable for credentials, argv shows
310
+ in ps). NO_PROXY is decided per destination host (NO_PROXY=* = no proxy). The guard resolves and
311
+ checks every destination itself, then tunnels to the checked address (CONNECT ip:443, and ip:80
312
+ for plain HTTP; a proxy that refuses port 80 fails those requests: give an https:// target);
313
+ loopback connects directly. The run records the proxy without its credentials
314
+ --allow-hosts LIST Only these hosts may be reached (comma-separated or repeated; *.example.com = its subdomains);
315
+ the target's own host is always allowed. Other hosts are refused and listed in the limitations
316
+ --block-hosts LIST Refuse these hosts (e.g. *.tracker.example); refused requests are listed in the limitations
317
+ --user-agent UA Send this User-Agent (also navigator.userAgent) instead of the browser's own; recorded in the run
318
+ --extra-header H Add a request header "Name: value" (repeatable), sent only to the target's origin, never
319
+ to other hosts: Jourilo makes those requests itself, so the headers cannot follow a redirect
320
+ elsewhere (a redirect is followed without them). The run records the names, never the values
321
+ --ignore-https-errors
322
+ Accept invalid or self-signed certificates in the browser (test environments only); the network
323
+ guard still checks every destination, and the run lists it in the limitations
324
+ --chromium-sandbox
325
+ Keep Chromium's own process sandbox (Playwright disables it by default); JOURILO_CHROMIUM_SANDBOX=1
326
+ does the same. Chromium, Chrome and Edge only (a usage error with Firefox or WebKit). Fails to launch
327
+ where the system denies the sandbox (containers, some Linux CI kernels)
207
328
 
208
329
  Run options:
209
330
  --base URL|DIR The site or static build to run against (required)
@@ -216,7 +337,8 @@ Run options:
216
337
  --allow-submit Allow form submission on non-local hosts (authorized test environments only)
217
338
  --allow-destructive Allow irreversible/payment actions — local hosts with sandbox data only
218
339
  --allow-origin ORIGIN Let the page navigate to another origin you are authorized to test (e.g. a test IdP)
219
- --trace Record a Playwright trace per journey (contains typed values; keep private)
340
+ --trace Record a Playwright trace per journey (contains typed values; keep private);
341
+ refused with --extra-header, since a trace records header values
220
342
  --auth FILE Playwright storage state for signed-in journeys
221
343
  --save-auth FILE After a passing sign-in journey (exactly one), save its session for --auth (test accounts only)
222
344
  --timezone ZONE IANA time zone for the page (e.g. Europe/Istanbul)
@@ -226,6 +348,26 @@ Run options:
226
348
  --allow-private Allow private-network hosts (10.x, 192.168.x, ...)
227
349
  --deny-local Refuse local targets (localhost, 127.0.0.1, [::1], *.localhost, *.test) (exit 3); a redirect or request to one is blocked by the network guard and listed in the limitations;
228
350
  JOURILO_DENY_LOCAL=1 does the same. Not available with --browser webkit (exit 3)
351
+ --proxy URL Chain to an upstream HTTP proxy (http://[user:password@]host:port) behind the network guard;
352
+ default HTTPS_PROXY / HTTP_PROXY (either case; prefer the variable for credentials, argv shows
353
+ in ps). NO_PROXY is decided per destination host (NO_PROXY=* = no proxy). The guard resolves and
354
+ checks every destination itself, then tunnels to the checked address (CONNECT ip:443, and ip:80
355
+ for plain HTTP; a proxy that refuses port 80 fails those requests: give an https:// target);
356
+ loopback connects directly. The run records the proxy without its credentials
357
+ --allow-hosts LIST Only these hosts may be reached (comma-separated or repeated; *.example.com = its subdomains);
358
+ the target's own host is always allowed. Other hosts are refused and listed in the limitations
359
+ --block-hosts LIST Refuse these hosts (e.g. *.tracker.example); refused requests are listed in the limitations
360
+ --user-agent UA Send this User-Agent (also navigator.userAgent) instead of the browser's own; recorded in the run
361
+ --extra-header H Add a request header "Name: value" (repeatable), sent only to the target's origin, never
362
+ to other hosts: Jourilo makes those requests itself, so the headers cannot follow a redirect
363
+ elsewhere (a redirect is followed without them). The run records the names, never the values
364
+ --ignore-https-errors
365
+ Accept invalid or self-signed certificates in the browser (test environments only); the network
366
+ guard still checks every destination, and the run lists it in the limitations
367
+ --chromium-sandbox
368
+ Keep Chromium's own process sandbox (Playwright disables it by default); JOURILO_CHROMIUM_SANDBOX=1
369
+ does the same. Chromium, Chrome and Edge only (a usage error with Firefox or WebKit). Fails to launch
370
+ where the system denies the sandbox (containers, some Linux CI kernels)
229
371
  --fail-on-failure Exit 1 when a journey fails
230
372
 
231
373
  Safety: payment, purchase, delete and cancel actions are never performed on non-local hosts; form submission
@@ -293,6 +435,29 @@ Options:
293
435
  --repo PATH Repository for source mapping (default: the baseline run's repo)
294
436
  --deny-local Refuse a local target (localhost, 127.0.0.1, [::1], *.localhost, *.test) with exit 3; a redirect to one is blocked by the network guard and listed in the limitations;
295
437
  JOURILO_DENY_LOCAL=1 does the same. Not available with --browser webkit (exit 3)
438
+ --proxy URL Chain to an upstream HTTP proxy (http://[user:password@]host:port) behind the network guard;
439
+ default HTTPS_PROXY / HTTP_PROXY (either case; prefer the variable for credentials, argv shows
440
+ in ps). NO_PROXY is decided per destination host (NO_PROXY=* = no proxy). The guard resolves and
441
+ checks every destination itself, then tunnels to the checked address (CONNECT ip:443, and ip:80
442
+ for plain HTTP; a proxy that refuses port 80 fails those requests: give an https:// target);
443
+ loopback connects directly. The run records the proxy without its credentials
444
+ --allow-hosts LIST Only these hosts may be reached (comma-separated or repeated; *.example.com = its subdomains);
445
+ the target's own host is always allowed. Other hosts are refused and listed in the limitations
446
+ --block-hosts LIST Refuse these hosts (e.g. *.tracker.example); refused requests are listed in the limitations
447
+ --user-agent UA Send this User-Agent (also navigator.userAgent) instead of the browser's own; recorded in the run
448
+ --extra-header H Add a request header "Name: value" (repeatable), sent only to the target's origin, never
449
+ to other hosts: Jourilo makes those requests itself, so the headers cannot follow a redirect
450
+ elsewhere (a redirect is followed without them). The run records the names, never the values
451
+ --ignore-https-errors
452
+ Accept invalid or self-signed certificates in the browser (test environments only); the network
453
+ guard still checks every destination, and the run lists it in the limitations
454
+ --chromium-sandbox
455
+ Keep Chromium's own process sandbox (Playwright disables it by default); JOURILO_CHROMIUM_SANDBOX=1
456
+ does the same. Chromium, Chrome and Edge only (a usage error with Firefox or WebKit). Fails to launch
457
+ where the system denies the sandbox (containers, some Linux CI kernels)
458
+ Without --allow-hosts / --block-hosts, the baseline run's lists are used again; so are its
459
+ --user-agent and --ignore-https-errors. Header values are never stored: a baseline that sent
460
+ --extra-header needs the headers again (exit 2 without them)
296
461
  --fail-on-regression Exit 1 when new serious or critical defects appear
297
462
  ```
298
463
 
@@ -414,6 +579,23 @@ Benchmark detection quality on fixture sites with known defects (recall, false p
414
579
  jourilo bench [fixtures-dir=fixtures/sites] [--only name] [--record docs/evaluation/bench-history.jsonl]
415
580
  ```
416
581
 
582
+ ### `jourilo rules`
583
+
584
+ List every rule Jourilo can report, with category, severity and kind (machine-readable with --json).
585
+
586
+ ```
587
+ jourilo rules list [--json]
588
+ ```
589
+
590
+ ```
591
+ Subcommand:
592
+ list Native rules (jourilo/…, perf/…, conv/…, ux/…, a11y/…, journey/…, design/…) and the axe/<id> and
593
+ axe-review/<id> rules a run enables from axe-core 4.14.0. Severity is "varies" when it depends on
594
+ what was measured; kind is "varies" for a rule that reports a defect or, when unsure, a needs-review
595
+ item. With --json: {"jourilo": <version>, "axe": <axe-core version>, "rules": [{id, category,
596
+ severity, kind, title, standards}, …]}.
597
+ ```
598
+
417
599
  ### `jourilo serve`
418
600
 
419
601
  Serve a static build directory on 127.0.0.1 (for audits and journeys of static sites).
@@ -59,6 +59,41 @@
59
59
  },
60
60
  "axe": { "type": ["string", "null"] },
61
61
  "hostClass": { "type": "string" },
62
+ "proxy": {
63
+ "type": "string",
64
+ "description": "Upstream proxy the run chained to behind the network guard (scheme://host:port, never credentials)."
65
+ },
66
+ "allowHosts": {
67
+ "type": "array",
68
+ "items": { "type": "string" },
69
+ "description": "--allow-hosts patterns as given; the target's own host was always allowed."
70
+ },
71
+ "blockHosts": {
72
+ "type": "array",
73
+ "items": { "type": "string" },
74
+ "description": "--block-hosts patterns."
75
+ },
76
+ "userAgent": {
77
+ "type": "string",
78
+ "description": "--user-agent the browser sent instead of its own."
79
+ },
80
+ "extraHeaders": {
81
+ "type": "array",
82
+ "items": { "type": "string" },
83
+ "description": "Names of the --extra-header headers, sent only to the target's origin; their values are never stored."
84
+ },
85
+ "ignoreHttpsErrors": {
86
+ "type": "boolean",
87
+ "description": "--ignore-https-errors: the browser accepted invalid certificates; the network guard still checked every destination."
88
+ },
89
+ "waitFor": {
90
+ "type": "string",
91
+ "description": "--wait-for: each page was captured once this selector was visible (or --timeout passed; see limitations)."
92
+ },
93
+ "chromiumSandbox": {
94
+ "type": "boolean",
95
+ "description": "--chromium-sandbox: Chromium ran with its process sandbox on (Playwright disables it by default)."
96
+ },
62
97
  "scope": {
63
98
  "type": "object",
64
99
  "properties": {
@@ -123,6 +158,36 @@
123
158
  "description": "Why a partial run stopped.",
124
159
  "enum": ["signal", "max-duration"]
125
160
  },
161
+ "budgets": {
162
+ "description": "`--budget` results: per metric, the worst capture's value (the median with --runs N). `ok` is null when no capture measured the metric.",
163
+ "type": "array",
164
+ "items": {
165
+ "type": "object",
166
+ "required": ["metric", "limit", "worst", "url", "viewport", "ok"],
167
+ "properties": {
168
+ "metric": { "type": "string" },
169
+ "limit": { "type": "number" },
170
+ "worst": { "type": ["number", "null"] },
171
+ "url": { "type": ["string", "null"] },
172
+ "viewport": { "type": ["string", "null"] },
173
+ "ok": { "type": ["boolean", "null"] }
174
+ }
175
+ }
176
+ },
177
+ "sample": {
178
+ "description": "Present when discovery found more pages than were audited.",
179
+ "type": "object",
180
+ "required": ["discovered", "audited", "leftOut"],
181
+ "properties": {
182
+ "discovered": { "type": "integer" },
183
+ "audited": { "type": "integer" },
184
+ "leftOut": {
185
+ "description": "At most 20 URLs (redacted) that were discovered but not audited.",
186
+ "type": "array",
187
+ "items": { "type": "string" }
188
+ }
189
+ }
190
+ },
126
191
  "dismissed": {
127
192
  "description": "Findings a person or agent dismissed. Not counted in summary.",
128
193
  "type": "array",
@@ -180,7 +245,9 @@
180
245
  "type": "object",
181
246
  "required": ["pages", "journeys", "findings", "byCategory", "byKind"],
182
247
  "properties": {
183
- "pages": { "type": "integer" },
248
+ "pages": { "type": "integer", "description": "Page captures (URL x viewport), not distinct URLs." },
249
+ "urls": { "type": "integer", "description": "Distinct page URLs that were audited." },
250
+ "captures": { "type": "integer", "description": "Page captures; equal to `pages`." },
184
251
  "journeys": { "type": "integer" },
185
252
  "findings": { "type": "object", "additionalProperties": { "type": "integer" } },
186
253
  "byCategory": { "type": "object", "additionalProperties": { "type": "integer" } },
@@ -332,6 +399,16 @@
332
399
  "metrics": { "type": "array", "items": { "$ref": "#/$defs/metric" } },
333
400
  "consoleErrors": { "type": "integer" },
334
401
  "failedRequests": { "type": "integer" },
402
+ "load": {
403
+ "type": "object",
404
+ "description": "How the page was captured. `waitedFor` and `found` are present with --wait-for; `found` false means the element never became visible within --timeout.",
405
+ "required": ["networkIdle"],
406
+ "properties": {
407
+ "networkIdle": { "type": "boolean" },
408
+ "waitedFor": { "type": "string" },
409
+ "found": { "type": "boolean" }
410
+ }
411
+ },
335
412
  "inventory": { "$ref": "#/$defs/inventory" }
336
413
  }
337
414
  },
@@ -531,12 +608,40 @@
531
608
  }
532
609
  },
533
610
  "manifest": {
534
- "description": "manifest.json, written next to run.json: every artifact of the run with its size and sha256.",
611
+ "description": "manifest.json, written next to run.json: every artifact of the run with its size and sha256, and the versions and scope that produced them.",
535
612
  "type": "object",
536
613
  "required": ["schemaVersion", "runId", "files"],
537
614
  "properties": {
538
615
  "schemaVersion": { "const": 1 },
539
616
  "runId": { "type": "string" },
617
+ "tool": {
618
+ "description": "The Jourilo release that made the run (run.tool). Absent in manifests written before 1.3.0.",
619
+ "type": "object",
620
+ "required": ["name", "version"],
621
+ "properties": { "name": { "const": "jourilo" }, "version": { "type": "string" } }
622
+ },
623
+ "browser": {
624
+ "description": "The browser and its version (run.browser).",
625
+ "type": "object",
626
+ "required": ["name", "version"],
627
+ "properties": { "name": { "type": "string" }, "version": { "type": "string" } }
628
+ },
629
+ "axe": {
630
+ "description": "The axe-core version the pages were checked with (settings.axe), or the bundled one when no page was checked.",
631
+ "type": "object",
632
+ "required": ["version"],
633
+ "properties": { "version": { "type": "string" } }
634
+ },
635
+ "scope": {
636
+ "description": "What the run covered: the redacted target, the audited URLs (redacted; settings.scope.urls, else the captured pages) and the viewport names.",
637
+ "type": "object",
638
+ "required": ["target", "urls", "viewports"],
639
+ "properties": {
640
+ "target": { "type": "string" },
641
+ "urls": { "type": "array", "items": { "type": "string" } },
642
+ "viewports": { "type": "array", "items": { "type": "string" } }
643
+ }
644
+ },
540
645
  "files": {
541
646
  "type": "array",
542
647
  "items": {