versioncam 0.5.3 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/CHANGELOG.md +103 -0
  2. package/README.md +108 -6
  3. package/dist/cli/commands/check.js +25 -0
  4. package/dist/cli/commands/check.js.map +1 -1
  5. package/dist/cli/commands/doctor.js +54 -1
  6. package/dist/cli/commands/doctor.js.map +1 -1
  7. package/dist/cli/commands/preview.js +4 -2
  8. package/dist/cli/commands/preview.js.map +1 -1
  9. package/dist/cli/commands/record.d.ts +6 -0
  10. package/dist/cli/commands/record.js +24 -3
  11. package/dist/cli/commands/record.js.map +1 -1
  12. package/dist/cli/commands/stability.js +10 -3
  13. package/dist/cli/commands/stability.js.map +1 -1
  14. package/dist/cli/usage.d.ts +1 -1
  15. package/dist/cli/usage.js +2 -0
  16. package/dist/cli/usage.js.map +1 -1
  17. package/dist/config.d.ts +45 -4
  18. package/dist/config.js +134 -8
  19. package/dist/config.js.map +1 -1
  20. package/dist/core/cursor.d.ts +22 -0
  21. package/dist/core/cursor.js +6 -0
  22. package/dist/core/cursor.js.map +1 -1
  23. package/dist/core/motion-defaults.d.ts +8 -0
  24. package/dist/core/motion-defaults.js +8 -0
  25. package/dist/core/motion-defaults.js.map +1 -1
  26. package/dist/core/timeline.d.ts +24 -0
  27. package/dist/core/timeline.js.map +1 -1
  28. package/dist/driver/clip.d.ts +6 -0
  29. package/dist/driver/clip.js +33 -2
  30. package/dist/driver/clip.js.map +1 -1
  31. package/dist/driver/file-window.d.ts +66 -0
  32. package/dist/driver/file-window.js +245 -0
  33. package/dist/driver/file-window.js.map +1 -0
  34. package/dist/driver/page-hooks.d.ts +23 -1
  35. package/dist/driver/page-hooks.js +36 -1
  36. package/dist/driver/page-hooks.js.map +1 -1
  37. package/dist/driver/replay.d.ts +263 -0
  38. package/dist/driver/replay.js +558 -0
  39. package/dist/driver/replay.js.map +1 -0
  40. package/dist/driver/session.d.ts +70 -4
  41. package/dist/driver/session.js +267 -29
  42. package/dist/driver/session.js.map +1 -1
  43. package/dist/driver/settle.js +6 -0
  44. package/dist/driver/settle.js.map +1 -1
  45. package/dist/index.d.ts +4 -2
  46. package/dist/index.js.map +1 -1
  47. package/dist/page/assets/index-CnRDAiUz.js +2 -0
  48. package/dist/page/index.html +1 -1
  49. package/dist/publish/protocol.d.ts +12 -1
  50. package/dist/publish/protocol.js.map +1 -1
  51. package/dist/render/render.d.ts +7 -1
  52. package/dist/render/render.js +51 -17
  53. package/dist/render/render.js.map +1 -1
  54. package/dist/render/sequence.d.ts +10 -5
  55. package/dist/render/sequence.js +44 -29
  56. package/dist/render/sequence.js.map +1 -1
  57. package/dsl.md +68 -1
  58. package/package.json +1 -1
  59. package/plugin/.claude-plugin/plugin.json +1 -1
  60. package/plugin/skills/versioncam/authoring.md +15 -1
  61. package/plugin/skills/versioncam/onboarding.md +9 -3
  62. package/dist/page/assets/index-BtUbUEdN.js +0 -2
package/CHANGELOG.md CHANGED
@@ -6,6 +6,109 @@ and versions follow [semantic versioning](https://semver.org/). While the
6
6
  major version is 0, a minor version may change the config or the clip DSL,
7
7
  and its entry here says how.
8
8
 
9
+ ## 0.7.1 (2026-11-03)
10
+
11
+ A patch: a clip with its own viewport renders at its own shape, as the
12
+ README always said, and a phone clip's video is 1920 high rather than
13
+ 4155. Nothing changes for a landscape clip, and a publish sends what 0.7.0
14
+ sent, so version.cam needs nothing new to take it; it shows a phone clip
15
+ in place of its desktop clip once it is updated the same week.
16
+
17
+ ### Fixed
18
+
19
+ - A clip with its own `viewport` renders at its own shape. It rendered at
20
+ the config's: a phone clip at 390 by 844 came out as the top of its page
21
+ blown up to 1920 by 1200, and a 1600 by 900 clip in a 1440 by 900 config
22
+ lost its sides. `versioncam frame`, `sheet` and `preview` take the
23
+ recording's shape too.
24
+
25
+ ### Changed
26
+
27
+ - `output.width` is the video's longer side: a portrait clip's video is
28
+ that high, so a phone clip is 888 by 1920 rather than 1920 by 4155. This
29
+ changes nothing for a landscape or square clip, and nothing that
30
+ `versioncam publish` sends.
31
+
32
+ ### Added
33
+
34
+ - `render --sequence` refuses clips of two sizes with a message naming two
35
+ of them, before ffmpeg runs.
36
+ - The README says a clip has no sound, and how a phone clip is named: a
37
+ clip called `<id>-mobile` is shown in place of `<id>` on a narrow screen,
38
+ on its page, in its embed and through the web component, once
39
+ version.cam is updated the same week.
40
+
41
+ ## 0.7.0 (2026-11-02)
42
+
43
+ A minor version: the config gains `replay`, the clip DSL gains
44
+ `s.fileWindow`, a second form of `s.drag` and `modifiers` on `s.click`,
45
+ and `record` and `stability` take `--replay`. A config without `replay`
46
+ records as it did with 0.6.0, and the render config is unchanged, so a
47
+ publish needs nothing new of version.cam.
48
+
49
+ ### Added
50
+
51
+ - `replay` in the config records a clip's responses the first time it runs
52
+ and serves them on every run after, so a map's tiles, a model's answer or
53
+ a job's status are the same in every recording. `record` names the
54
+ requests by URL; each clip's replay is a HAR in `replay/` beside the
55
+ config, with binary bodies under `replay/bodies/` by hash, and is meant to
56
+ be committed. A request the replay covers and does not hold fails the clip
57
+ and names it. `pace` delivers a streamed response, an event stream over
58
+ `fetch` or `EventSource`, or lines of JSON, a piece at a time on the
59
+ page's clock. Authorization, cookie and API key headers are never written,
60
+ and `redact` leaves query parameters out.
61
+ - `s.fileWindow(files, options?)` draws a file window over the page, as
62
+ Finder draws one, to select files in and drag onto the app's dropzone,
63
+ which receives them as `File` objects through the events a real drag
64
+ sends: the upload a clip can film. A click selects a row, with Shift it
65
+ extends, with Meta it adds or removes.
66
+ - `s.drag(from, to, options?)`, from one locator or point to another, beside
67
+ the form in fractions of one box; and `modifiers` on `s.click`, for a
68
+ shift-click. Both strokes take Meta and Control as well as Shift and Alt.
69
+ - `versioncam record` and `stability` take `--replay auto|record|replay|live`.
70
+ `doctor` lists each clip's replay, and `check` points out one older than
71
+ ninety days.
72
+
73
+ ## 0.6.0 (2026-11-02)
74
+
75
+ A minor version: the clip DSL gains `s.scroll`, the config gains
76
+ `theme.cursor` and `motion.scrollDurationMs`, and a page's own smooth
77
+ scrolling is instant while it is recorded. A config that sets none of
78
+ the new fields renders and publishes as it did with 0.5.3, and records
79
+ the same unless its app scrolls smoothly from a script.
80
+
81
+ ### Added
82
+
83
+ - `s.scroll(target, where, options?)` scrolls a pane, or the page, on the
84
+ clip's clock: `{ by: px }`, `{ to: "top" | "bottom" | px }`, or
85
+ `{ into: locator, block? }`, one eased step a frame, so the frames inside
86
+ a scroll are the same on every run. The end is clamped to what the element
87
+ can scroll, and an element that cannot scroll at all is refused by name.
88
+ `motion.scrollDurationMs` (700) is its default length. A recording keeps
89
+ its scrolls in the timeline's new `scrolls`, which a recording without one
90
+ does not have.
91
+ - `theme.cursor: { style, ripple }` in the config. `style: "dark"` draws
92
+ the system's black arrow with a white hairline, as a screen recording of
93
+ a Mac shows it, and `ripple: false` draws no ring on a click. The default,
94
+ `{ style: "light", ripple: true }`, is the white arrow and the ring every
95
+ earlier version drew, to the byte.
96
+
97
+ ### Changed
98
+
99
+ - A page's script can no longer scroll smoothly while it is recorded:
100
+ `scrollIntoView`, `scrollTo`, `scrollBy` and `scroll` given
101
+ `{ behavior: "smooth" }` scroll at once, as a stylesheet's
102
+ `scroll-behavior: smooth` already did. The browser animated those scrolls
103
+ on its own clock, so the frames during one differed between runs. A clip
104
+ whose app scrolled itself that way now shows the scroll land in a frame;
105
+ `s.scroll` is how a clip shows one move.
106
+ - `versioncam publish` sends `theme.cursor` and `motion.scrollDurationMs`
107
+ only when the config changes them, so a config that changes neither
108
+ publishes exactly what 0.5.3 did. One that changes either needs
109
+ version.cam from cloud-v1.8.0, which knows both; before it, the publish
110
+ is refused with a message that names the key.
111
+
9
112
  ## 0.5.3 (2026-11-01)
10
113
 
11
114
  A patch version: the config and the clip DSL are as they were. The browser
package/README.md CHANGED
@@ -145,15 +145,16 @@ cannot say, that is a missing field. It is not a reason to fork.
145
145
  | `viewport` | `{ width: 1440, height: 900 }` | The page's size. The video has the same shape. |
146
146
  | `dpr` | `2` | Device pixel ratio, from 1 to 3. At 2, a zoom shows real pixels. |
147
147
  | `fps` | `60` | Frames per second, from 10 to 120. |
148
- | `output` | `{ width: 1920 }` | The video's width. Its height follows the viewport. `threads` fixes how many threads each encoder uses: an encoder's bytes depend on it, so a fixed number renders the same recording to the same file on any machine. `VERSIONCAM_FFMPEG_THREADS` sets it for one run. |
148
+ | `output` | `{ width: 1920 }` | The video's longer side: a landscape clip is this wide, a portrait clip this high, and the other side follows the viewport. `threads` fixes how many threads each encoder uses: an encoder's bytes depend on it, so a fixed number renders the same recording to the same file on any machine. `VERSIONCAM_FFMPEG_THREADS` sets it for one run. |
149
149
  | `auth` | none | How the app signs in: a saved session, `{ storageState }`, or a hook, `{ login }`. |
150
150
  | `settle` | `quietMs: 150`, `timeoutMs: 15000`, `yieldMs: 20` | When a page counts as done. `ready` adds a condition of your own. |
151
151
  | `capture` | `gate: true`, `forceCaptureEvery: 30`, `transitions: "play"` | Which frames get a screenshot (see *Speed*), and whether the app's CSS transitions play on its clock or take no time, `"zero"` (see *Determinism*). |
152
152
  | `review` | `minSeconds: 9`, `maxSeconds: 11` | How long a clip should run. `versioncam review` holds clips to it. |
153
153
  | `cursorStart` | `{ x: 0.72, y: 0.28 }` | Where the cursor rests in the first frame, as fractions of the viewport. |
154
154
  | `clock` | `time: "2026-09-01T09:00:00Z"`, `timezoneId: "UTC"`, `locale: "en-GB"` | The instant, time zone and locale the app sees. |
155
- | `theme` | `accent: "#2f6fed"`, `cursorScale: 2.1` | The colour of ripples and rings, the cursor's size, and an optional `presentation`. See *Presentation*. |
156
- | `motion` | `MOTION` | Dwells, strokes and camera timing. `MOTION` is exported, with the reason for each number beside it. |
155
+ | `theme` | `accent: "#2f6fed"`, `cursorScale: 2.1`, `cursor: { style: "light", ripple: true }` | The colour of ripples and rings, the cursor's size and look, and an optional `presentation`. `cursor: { style: "dark", ripple: false }` draws the system's black arrow and no ring on a click, as a screen recording shows them. See *Presentation*. |
156
+ | `motion` | `MOTION` | Dwells, strokes, scrolls and camera timing. `MOTION` is exported, with the reason for each number beside it. |
157
+ | `replay` | none | Responses recorded once and served on every run after: tiles, a model's answers, a job's status. See *Live data*. |
157
158
  | `outDir` | `".versioncam"` | Where everything the recorder writes goes. Gitignore it. |
158
159
  | `scenes` | none | A module whose default export is `Record<string, Scene>`, keyed by scene id: `export default { [intro.id]: intro }`. A named export is not read, and a module with no default export is refused. |
159
160
  | `sequence` | none | Clip ids, in order, for `versioncam render --sequence`. |
@@ -221,7 +222,9 @@ theme: {
221
222
 
222
223
  A caption inset is in the video's pixels. The video is `output.width` wide,
223
224
  1920 unless the config says otherwise, so with a page 1440 wide, four of the
224
- video's pixels are three of the page's.
225
+ video's pixels are three of the page's. The inset is checked against the
226
+ config's `output.width`, and a phone clip's video is narrower than that, so
227
+ give a config with phone clips an inset that fits them too.
225
228
 
226
229
  ## Write a clip
227
230
 
@@ -255,6 +258,31 @@ for a straight one, `s.lasso` for a closed loop) are written in fractions of a
255
258
  target's box for the same reason. A clip built from locators survives a layout
256
259
  change.
257
260
 
261
+ A long answer or a list is read by scrolling it, and `s.scroll` does that on
262
+ the clip's clock, one step a frame, so every frame of it is the same on every
263
+ run. Give it the pane that scrolls, or `"page"`, and where to go: `{ by: 400 }`,
264
+ `{ to: "bottom" }`, or `{ into: s.byTestId("citation-3") }` to bring one thing
265
+ into view.
266
+
267
+ ```ts
268
+ await s.moveTo(s.byTestId("answer"));
269
+ await s.scroll(s.byTestId("answer"), { into: s.byTestId("citation-3") });
270
+ ```
271
+
272
+ The cursor stays put while the pane moves, so a clip moves it over the pane
273
+ first, where a hand on a mouse wheel would be.
274
+
275
+ An upload is filmed from `s.fileWindow`, a file window drawn over the page,
276
+ since the browser's own file dialog is outside it. The clip selects files in
277
+ it and drags them onto the app's dropzone, which receives them as real files
278
+ through the events a real drag sends. The window is staged; say so where the
279
+ clip is shown.
280
+
281
+ ```ts
282
+ const files = await s.fileWindow([{ name: "cases.csv", content: csv }], { title: "Case data" });
283
+ await s.drag(files.item(0), s.byTestId("dropzone"));
284
+ ```
285
+
258
286
  `npx versioncam dsl` prints every method with its options and defaults, and a
259
287
  test holds that list to the session's code. The same reference is
260
288
  *The clip DSL*.
@@ -263,7 +291,7 @@ test holds that list to the session's code. The same reference is
263
291
  |---|---|---|
264
292
  | `title` | required | The clip's name, kept in its timeline. It is not drawn: write a caption with `s.caption`. |
265
293
  | `seed` | `1` | Seeds the jitter in cursor paths, dwells and typing. A new seed is a new take of the same script. |
266
- | `viewport`, `dpr`, `fps` | the config's | For a clip that needs a different shape. |
294
+ | `viewport`, `dpr`, `fps` | the config's | For a clip that needs a different shape. A phone clip sets `viewport: { width: 390, height: 844 }` and renders 888 by 1920 at the default output; name it `<id>-mobile` and version.cam shows it in place of `<id>` on a narrow screen (see *version.cam*). |
267
295
  | `capture` | the config's | A clip that films a canvas sets `{ forceCaptureEvery: 1 }` here, and one whose app animates in ways better left out sets `{ transitions: "zero" }`. |
268
296
 
269
297
  ### The camera
@@ -360,11 +388,13 @@ the wreckage would help nobody.
360
388
  ```
361
389
  versioncam record [id…] drive the app and capture frames
362
390
  --draft 15fps at CSS scale: cheap, for writing clips
391
+ --replay <mode> auto, record, replay or live, over the config's replay
363
392
  versioncam check [id…] record every clip; exit 1 if any breaks
364
393
  --report <file> and write each clip's result there, as JSON
365
394
  versioncam stability [id…] record each clip twice the same way; stable or not
366
395
  --runs <n> how many times (default 2)
367
396
  --full at full quality rather than draft
397
+ --replay <mode> as for record
368
398
  ```
369
399
 
370
400
  ### Review
@@ -407,6 +437,9 @@ versioncam render [id…] composite and encode recordings and scenes
407
437
  --report <file> and write what it made there, as JSON
408
438
  ```
409
439
 
440
+ A clip has no sound. The files carry a video stream only, so a player's
441
+ mute control has nothing to do. Narration is not a feature yet.
442
+
410
443
  ### Publish
411
444
 
412
445
  Send what the last run recorded to [version.cam](https://version.cam), which
@@ -483,6 +516,21 @@ and keeps each clip at a living address,
483
516
  your default branch that passed, so a page that embeds it never needs
484
517
  editing. Projects are managed on [app.version.cam](https://app.version.cam).
485
518
 
519
+ ### Phone and desktop in one link
520
+
521
+ A clip whose id is another clip's id with `-mobile` on the end is that
522
+ clip's phone version: `01-checkout-mobile` beside `01-checkout`, recorded at
523
+ a phone's viewport. The clip's page, its embed page and the `<version-cam>`
524
+ element of its script snippet show the phone clip on a screen under 768 CSS
525
+ pixels wide and the desktop clip on a wider one, so one link serves both. The element measures
526
+ its own width, not the window's, and takes the shape of the clip it will
527
+ show. The plain snippets cannot: the video snippet is the desktop clip's
528
+ file, and the iframe snippet keeps the desktop clip's shape, since an
529
+ iframe without a script keeps the box it was given, so on a phone the
530
+ phone clip plays inside that box. Use the element where a page should fit
531
+ both. Until the phone clip has a video, the desktop clip shows everywhere.
532
+ The phone clip has its own page and snippets as well, to place it by hand.
533
+
486
534
  ### Connect a repository
487
535
 
488
536
  Sign in at [app.version.cam](https://app.version.cam) with GitHub, and
@@ -691,7 +739,9 @@ your scenes are served from an in-memory route table. `versioncam render`
691
739
  needs only a recording on disk and a browser.
692
740
 
693
741
  **Output follows the viewport.** Record at 1440×900 and the video is 16:10.
694
- For 16:9, record at 1600×900. Nothing is letterboxed or cropped. A backdrop, a
742
+ For 16:9, record at 1600×900. Nothing is letterboxed or cropped. A portrait
743
+ viewport gives a portrait video, `output.width` high. A sequence stitches
744
+ clips of one size, so phone clips stay out of `sequence`. A backdrop, a
695
745
  device frame and padding are available through `theme.presentation`, and are
696
746
  off by default.
697
747
 
@@ -859,12 +909,64 @@ its CSS motion:
859
909
  up it finishes, as in a browser nobody is filming: its `finished` promise
860
910
  resolves and `animationend` fires, so a dialog that unmounts after its exit
861
911
  animation goes, and does not sit invisibly over the page.
912
+ - **Smooth scrolling is instant.** A stylesheet's `scroll-behavior: smooth`
913
+ and a script's `{ behavior: "smooth" }` both scroll at once, since the
914
+ browser would animate either on a clock the recorder does not move. A chat
915
+ that keeps its newest message in view jumps to it. To film a scroll, use
916
+ `s.scroll`.
862
917
  - **Not on the clock:** animations a script makes with `element.animate()`,
863
918
  Chromium's smooth scrolling of a mouse wheel, and transitions inside an
864
919
  iframe, which stay zeroed since nothing drives an iframe's clock. A clip
865
920
  that films one of the first two may differ between runs: `stability` says
866
921
  so.
867
922
 
923
+ ### Live data
924
+
925
+ A map's tiles, a model's answer, a job's status, a count that grows: each
926
+ comes from a server, at the server's speed and in its words of the day, so
927
+ two recordings of a clip that shows one differ wherever it reaches the page.
928
+ `replay` records those responses the first time a clip runs and serves them,
929
+ from a file, on every run after:
930
+
931
+ ```ts
932
+ replay: {
933
+ record: ["https://tiles.example.com/**", "**/api/chat/**"],
934
+ // A stream the page reads over time, one event every 300 ms of the clip.
935
+ pace: [{ url: "**/api/chat/*/stream", chunkMs: 300 }],
936
+ },
937
+ ```
938
+
939
+ | Field | Default | What it sets |
940
+ |---|---|---|
941
+ | `record` | required | The requests to record and replay: URL globs, as Playwright writes them, or regular expressions. |
942
+ | `mode` | `"auto"` | `"auto"` replays a clip whose file exists and records one whose file does not. `"record"` always records, `"replay"` fails without a file, `"live"` ignores it. `--replay <mode>` on `record` and `stability` overrides it for one run. |
943
+ | `dir` | `"replay"` | Where the files go, beside the config. Commit them: a replay is an input, like a fixture, and CI needs it to record the clip the same way. |
944
+ | `pace` | none | Responses the page reads a piece at a time, an event stream or lines of JSON: delivered one event or one line every `chunkMs` of the page's clock, so each piece lands on the same frame every run, at any frame rate. |
945
+ | `redact` | none | Query parameters left out of the file, and of the match, by name. |
946
+ | `onMissing` | `"fail"` | A request the replay covers and does not hold fails the clip, naming it, since a request that quietly went live is what this exists to stop. `"live"` sends it to the network with a warning instead. |
947
+
948
+ Each clip has its own file, `replay/<clip>.har`, a HAR that a browser's
949
+ developer tools can open. Text bodies are in it, where a diff can read them;
950
+ binary ones, tiles and images, sit beside it under `replay/bodies/`, named by
951
+ their hash, so clips that load the same tiles keep them once. The
952
+ `Authorization`, `Cookie`, `Set-Cookie` and `X-API-Key` headers are never
953
+ written. The bodies are written as the server sent them, so read a replay
954
+ before committing it if the server's answers can hold anything private.
955
+
956
+ A request the same URL answers several times, a job's status polled until it
957
+ is done, is answered in the order it was recorded, and the last answer again
958
+ after that. A request the clip answers itself, with `page.route` from
959
+ `offCamera`, never reaches the replay, so a hand-written mock still wins
960
+ where a clip has one. The frame loop waits for the replay's answers, so a
961
+ response arrives in the frame it was asked for on every run.
962
+
963
+ `doctor` lists each clip's replay, how many requests it holds and when it
964
+ was recorded, and `check` points out one older than ninety days. That is by
965
+ age alone: a clip that passes against its replay proves the app still asks
966
+ for what it asked for, not that the server still answers the same way. When
967
+ the app changes what it fetches, the clip fails and names the request; record
968
+ it again with `versioncam record <id> --replay record`.
969
+
868
970
  ### When a clip will not reproduce
869
971
 
870
972
  The recorder can only be as deterministic as the app it films. An app that is
@@ -1,6 +1,7 @@
1
1
  import { existsSync, readFileSync } from "node:fs";
2
2
  import { join, resolve } from "node:path";
3
3
  import { parseArgs } from "node:util";
4
+ import { STALE_DAYS, describeReplay } from "../../driver/replay.js";
4
5
  import { launchBrowser } from "../../driver/launch.js";
5
6
  import { RECORDER_VERSION, runClip } from "../../driver/clip.js";
6
7
  import { loadClips, loadConfig } from "../../loader.js";
@@ -51,6 +52,8 @@ async function checkAll(config, clips, reportPath) {
51
52
  await browser.close();
52
53
  }
53
54
  process.stdout.write(`\n${clips.length - failures.length}/${clips.length} clips still match the app.\n`);
55
+ for (const line of staleReplays(config, clips))
56
+ process.stdout.write(line);
54
57
  for (const { id, error } of failures) {
55
58
  process.stderr.write(`\n${id}\n ${error.message}\n`);
56
59
  }
@@ -59,6 +62,28 @@ async function checkAll(config, clips, reportPath) {
59
62
  }
60
63
  return failures.length > 0 ? 1 : 0;
61
64
  }
65
+ /**
66
+ * A line for each clip whose replay is older than `STALE_DAYS`.
67
+ *
68
+ * By age alone, and said to be: a clip that passes against its replay
69
+ * proves the app still makes the requests it made, not that the server
70
+ * still answers them that way, and nothing here can know whether it does.
71
+ * Three months is long enough that it is worth a person asking.
72
+ */
73
+ function staleReplays(config, clips) {
74
+ if (!config.replay)
75
+ return [];
76
+ const lines = [];
77
+ for (const clip of clips) {
78
+ const found = describeReplay(config.replay.dir, clip.id);
79
+ if (!found.exists || !(found.ageDays > STALE_DAYS))
80
+ continue;
81
+ lines.push(`warn ${clip.id}: its replay was recorded ${found.ageDays} days ago. ` +
82
+ "The clip shows the server's answers of that day; if they have changed, " +
83
+ `record it again with \`versioncam record ${clip.id} --replay record\`.\n`);
84
+ }
85
+ return lines;
86
+ }
62
87
  /**
63
88
  * What `--report` writes: each clip's result, the step a failure stopped at,
64
89
  * and where its picture is, for a machine to read. The Action builds its pull
@@ -1 +1 @@
1
- {"version":3,"file":"check.js","sourceRoot":"","sources":["../../../src/cli/commands/check.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"check.js","sourceRoot":"","sources":["../../../src/cli/commands/check.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,8 @@
1
1
  import { browserPaths } from "./install.js";
2
2
  import { ffmpegStatus } from "../../render/ffmpeg.js";
3
3
  import { ensureApp, probe } from "../../app-server.js";
4
- import { NO_CONFIG, findConfigFile, loadConfig, loadSceneIds, } from "../../loader.js";
4
+ import { NO_CONFIG, findConfigFile, loadClips, loadConfig, loadSceneIds, } from "../../loader.js";
5
+ import { STALE_DAYS, describeReplay } from "../../driver/replay.js";
5
6
  const NOT_SERVING = "Start the app, point `baseUrl` at where it is served, or add `webServer` to the config.";
6
7
  /**
7
8
  * Is the app the config points at serving — and if not, can it be started?
@@ -95,6 +96,55 @@ async function scenesCheck(cwd) {
95
96
  return { name: "scenes", ok: false, detail: first, fix: rest.join("\n") };
96
97
  }
97
98
  }
99
+ /**
100
+ * Each clip's replay: whether it has one, how many requests it holds, and
101
+ * how old it is. Never a failure: a clip without one records it on its first
102
+ * run. Null for a config without `replay`.
103
+ *
104
+ * The age is the only staleness anyone can tell from here. Whether the
105
+ * server's answers have changed since is not knowable without asking it, so
106
+ * an old replay is pointed out, not judged.
107
+ */
108
+ async function replayCheck(cwd) {
109
+ let config;
110
+ try {
111
+ config = await loadConfig(cwd);
112
+ }
113
+ catch {
114
+ return null;
115
+ }
116
+ const replay = config.replay;
117
+ if (!replay)
118
+ return null;
119
+ let ids;
120
+ try {
121
+ ids = (await loadClips(config, [])).map((clip) => clip.id);
122
+ }
123
+ catch (error) {
124
+ return {
125
+ name: "replay",
126
+ ok: false,
127
+ detail: `the clips did not load: ${error.message.split("\n")[0]}`,
128
+ };
129
+ }
130
+ const lines = ids.map((id) => {
131
+ const found = describeReplay(replay.dir, id);
132
+ if (!found.exists)
133
+ return `${id}: none yet; its first recording makes one`;
134
+ const age = Number.isNaN(found.ageDays)
135
+ ? "of unknown age"
136
+ : `${found.ageDays} days old`;
137
+ const stale = found.ageDays > STALE_DAYS
138
+ ? ", older than any answer should be trusted to stay"
139
+ : "";
140
+ return `${id}: ${found.requests} requests, recorded ${found.recorded.slice(0, 10)}, ${age}${stale}`;
141
+ });
142
+ return {
143
+ name: "replay",
144
+ ok: true,
145
+ detail: [`${replay.dir} (mode ${replay.mode})`, ...lines].join("\n "),
146
+ };
147
+ }
98
148
  /**
99
149
  * Can this machine record and encode?
100
150
  *
@@ -154,6 +204,9 @@ export async function doctor() {
154
204
  const scenes = await scenesCheck(process.cwd());
155
205
  if (scenes)
156
206
  checks.push(scenes);
207
+ const replay = await replayCheck(process.cwd());
208
+ if (replay)
209
+ checks.push(replay);
157
210
  checks.push(await appCheck(process.cwd()));
158
211
  }
159
212
  for (const check of checks) {
@@ -1 +1 @@
1
- {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../../src/cli/commands/doctor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../../src/cli/commands/doctor.ts"],"names":[],"mappings":"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"}
@@ -4,8 +4,8 @@ import { join } from "node:path";
4
4
  import { launchBrowser } from "../../driver/launch.js";
5
5
  import { ensureFullBrowser } from "./install.js";
6
6
  import { loadConfig } from "../../loader.js";
7
- import { renderConfigOf } from "../../config.js";
8
7
  import { bundleScenes, loadSceneIds } from "../../loader.js";
8
+ import { renderConfigFor } from "../../render/render.js";
9
9
  import { missingScenes } from "../../render/scenes.js";
10
10
  import { distPageDir, installRenderRoutes, RENDER_ORIGIN, } from "../../render/serve.js";
11
11
  /**
@@ -53,9 +53,11 @@ export async function preview(argv) {
53
53
  deviceScaleFactor: 1,
54
54
  });
55
55
  const page = await context.newPage();
56
+ // At the recording's own shape, as the encoder renders it: a phone clip
57
+ // is a portrait canvas in this window, which fits the canvas to itself.
56
58
  await installRenderRoutes(page, {
57
59
  distDir: distPageDir(),
58
- renderConfig: renderConfigOf(config),
60
+ renderConfig: await renderConfigFor(config, sceneId ? { kind: "scene", id: sceneId } : { kind: "recording", id, dir }),
59
61
  recordingDir: sceneId ? undefined : dir,
60
62
  scenesBundle: (await bundleScenes(config)) ?? undefined,
61
63
  });
@@ -1 +1 @@
1
- {"version":3,"file":"preview.js","sourceRoot":"","sources":["../../../src/cli/commands/preview.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"preview.js","sourceRoot":"","sources":["../../../src/cli/commands/preview.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import type { ReplayMode } from "../../driver/replay.js";
1
2
  /**
2
3
  * Record every clip the config points at, serially.
3
4
  *
@@ -8,3 +9,8 @@
8
9
  * error alone.
9
10
  */
10
11
  export declare function record(argv: string[]): Promise<number>;
12
+ /**
13
+ * `--replay <mode>`, checked: a mode misspelt would otherwise be read as the
14
+ * config's, and record over a replay someone meant to keep.
15
+ */
16
+ export declare function replayModeOf(value: string | boolean | undefined): ReplayMode | undefined | Error;
@@ -3,6 +3,7 @@ import { join } from "node:path";
3
3
  import { parseArgs } from "node:util";
4
4
  import { launchBrowser } from "../../driver/launch.js";
5
5
  import { runClip } from "../../driver/clip.js";
6
+ import { isReplayMode } from "../../config.js";
6
7
  import { formatTiming } from "../../core/timing.js";
7
8
  import { loadClips, loadConfig } from "../../loader.js";
8
9
  import { drivingApp } from "../app.js";
@@ -19,11 +20,19 @@ import { ensureFailure } from "../../driver/reports.js";
19
20
  export async function record(argv) {
20
21
  const { values, positionals } = parseArgs({
21
22
  args: argv,
22
- options: { draft: { type: "boolean", default: false } },
23
+ options: {
24
+ draft: { type: "boolean", default: false },
25
+ replay: { type: "string" },
26
+ },
23
27
  strict: false,
24
28
  allowPositionals: true,
25
29
  });
26
30
  const draft = values.draft === true;
31
+ const replay = replayModeOf(values.replay);
32
+ if (replay instanceof Error) {
33
+ process.stderr.write(`${replay.message}\n`);
34
+ return 1;
35
+ }
27
36
  const config = await loadConfig(process.cwd());
28
37
  const clips = await loadClips(config, positionals);
29
38
  if (clips.length === 0) {
@@ -32,9 +41,20 @@ export async function record(argv) {
32
41
  : `No clips found. The config looks for ${config.clips.join(", ")} under ${config.root}.\n`);
33
42
  return 1;
34
43
  }
35
- return drivingApp(config, () => recordAll(config, clips, draft));
44
+ return drivingApp(config, () => recordAll(config, clips, draft, replay));
45
+ }
46
+ /**
47
+ * `--replay <mode>`, checked: a mode misspelt would otherwise be read as the
48
+ * config's, and record over a replay someone meant to keep.
49
+ */
50
+ export function replayModeOf(value) {
51
+ if (value === undefined)
52
+ return undefined;
53
+ if (isReplayMode(value))
54
+ return value;
55
+ return new Error(`--replay is auto, record, replay or live, got ${JSON.stringify(value)}.`);
36
56
  }
37
- async function recordAll(config, clips, draft) {
57
+ async function recordAll(config, clips, draft, replay) {
38
58
  const browser = await launchBrowser();
39
59
  const failures = [];
40
60
  try {
@@ -43,6 +63,7 @@ async function recordAll(config, clips, draft) {
43
63
  try {
44
64
  const { timeline, cost } = await runClip(browser, config, clip, {
45
65
  draft,
66
+ replay,
46
67
  });
47
68
  // Both seconds are named. The line used to print "(7.5s) … — 2.6s" and
48
69
  // leave the reader to work out that the first is the clip and the
@@ -1 +1 @@
1
- {"version":3,"file":"record.js","sourceRoot":"","sources":["../../../src/cli/commands/record.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"record.js","sourceRoot":"","sources":["../../../src/cli/commands/record.ts"],"names":[],"mappings":"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"}