@vosjs/cli 0.81.0 → 0.81.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.
- package/package.json +4 -4
- package/skills/VERSION +1 -1
- package/skills/launch-kit/SKILL.md +7 -0
- package/skills/product-video/SKILL.md +91 -3
- package/skills/product-video/references/how-to.md +78 -0
- package/skills/product-video/references/taste.md +4 -0
- package/skills/product-video/references/troubleshooting.md +8 -4
- package/skills/vos-cut/SKILL.md +34 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vosjs/cli",
|
|
3
|
-
"version": "0.81.
|
|
3
|
+
"version": "0.81.1",
|
|
4
4
|
"description": "The vos CLI: record the real product from a scripted browser flow, auto-zoom from the cursor track, cut as data in doc.json, render deterministic video, deliver a release's video cuts per destination spec, and sync with vos.so. One binary, every verb, MIT.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -52,13 +52,13 @@
|
|
|
52
52
|
"mediabunny": "^1.55.7",
|
|
53
53
|
"playwright": "^1.49.0",
|
|
54
54
|
"@vosjs/core": "^0.31.0",
|
|
55
|
-
"@vosjs/editor": "^1.6.0",
|
|
56
55
|
"@vosjs/elements": "^0.12.1",
|
|
56
|
+
"@vosjs/editor": "^1.6.0",
|
|
57
57
|
"@vosjs/shared": "^0.7.0",
|
|
58
58
|
"@vosjs/render-core": "^0.10.0",
|
|
59
59
|
"@vosjs/studio-core": "^0.46.0",
|
|
60
|
-
"@vosjs/
|
|
61
|
-
"@vosjs/
|
|
60
|
+
"@vosjs/timeline": "^0.5.0",
|
|
61
|
+
"@vosjs/tween": "^0.8.3"
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|
|
64
64
|
"@types/node": "^22",
|
package/skills/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.
|
|
1
|
+
0.27.0
|
|
@@ -244,3 +244,10 @@ by data. Never spread before the seed is signed off.
|
|
|
244
244
|
- A hand-typed dimension: every size comes from `channel-specs.json`.
|
|
245
245
|
- The save beat on a demo instance that disables writes: say so in
|
|
246
246
|
`skipped`, never fake the click.
|
|
247
|
+
- A zoom trusted because the track lists it: `frames --at-zooms` renders
|
|
248
|
+
each apex beside its zoom-off twin and names one that matches; read the
|
|
249
|
+
stills before `deliver`, never the list.
|
|
250
|
+
- A rehearsal that presses a step that spends or creates in the shipped
|
|
251
|
+
product: `--dry-run` CLICKS. Guard the spend (`"guard": "spend"` + `id`,
|
|
252
|
+
recorded only with `--confirm <id>`) and write the side-effect ledger
|
|
253
|
+
before the first rehearsal (the `product-video` skill's pre-flight).
|
|
@@ -52,6 +52,69 @@ failure / 3 no browser / 4 the recorder met a sign-in instead of the page
|
|
|
52
52
|
| **Quick demo** (issue, PR, chat) | 1280×720 | webm, defaults | speed over polish; drafts acceptable here ONLY |
|
|
53
53
|
|
|
54
54
|
Per-channel dimensions and byte budgets: `references/destinations.md`.
|
|
55
|
+
A **how-to** (one flow in a product, from a door to its result, for a docs
|
|
56
|
+
page or a changelog) takes the quick demo's viewport or the launch video's,
|
|
57
|
+
and its own grammar: `references/how-to.md`.
|
|
58
|
+
|
|
59
|
+
## Pre-flight: six answers before the first take
|
|
60
|
+
|
|
61
|
+
A flow in somebody's product has consequences the footage does not show:
|
|
62
|
+
two rehearsals left two untitled drafts in a founder's projects and both
|
|
63
|
+
appeared in the recorded sidebar; a rehearsal that reaches "Generate"
|
|
64
|
+
spends a credit; a result that arrives twelve minutes later is a second
|
|
65
|
+
take without a plan for it. Answer these BEFORE `vos look`, the script or a
|
|
66
|
+
rehearsal. **Each answer either changes the script or is said to the
|
|
67
|
+
person before recording**; an answer that does neither was not an answer.
|
|
68
|
+
|
|
69
|
+
1. **The door.** Which way through the product does the video walk, and
|
|
70
|
+
which others exist (a guided flow, a prompt box, an apps menu, a
|
|
71
|
+
template)? A how-to walks ONE. When there are several, list them and
|
|
72
|
+
confirm the door with the person before scripting; a door that works
|
|
73
|
+
under automation beats a recommended one that does not, and hiding the
|
|
74
|
+
automation from the site is never the answer (find another door, or
|
|
75
|
+
hand the shot list to a person: `references/sessions.md`, rung 4).
|
|
76
|
+
2. **Whose account, face and work.** What the signed-in account shows ships
|
|
77
|
+
in the video: its avatar, its name, its recent items, the titles of its
|
|
78
|
+
other projects. A demo account is the answer; when the person records
|
|
79
|
+
from their own, say what will show before the take. The rehearsal
|
|
80
|
+
reports an address, a key or a card as EXPOSED (mask those), and the
|
|
81
|
+
account's own name and its recent lists as NOTICES: those are the
|
|
82
|
+
person's call. Say they will be on screen and offer the one-line `mask`;
|
|
83
|
+
never mask a name by default, and a face is yours to notice and theirs
|
|
84
|
+
to decide.
|
|
85
|
+
3. **What the flow CREATES.** Write the side-effect ledger: for each step,
|
|
86
|
+
what it leaves in the product (a draft, a project, a message, a file, a
|
|
87
|
+
row), remembering that `--dry-run` CLICKS, so every rehearsal creates
|
|
88
|
+
them too. Say the ledger to the person before the first rehearsal when
|
|
89
|
+
the product is a real account, and report it at the end so they can
|
|
90
|
+
delete what was made. A product where creating is cheap (a sandbox, a
|
|
91
|
+
seeded local instance) needs the ledger written, not asked.
|
|
92
|
+
4. **What it SPENDS.** A step that costs something real (a generation, a
|
|
93
|
+
purchase, a message sent, a deploy) carries `"guard": "spend"` and an
|
|
94
|
+
`id`. A rehearsal hovers it and never presses it; `vos record` refuses
|
|
95
|
+
the take before a browser opens unless the command names the step
|
|
96
|
+
(`--confirm <id>`), and the done event records that it was pressed.
|
|
97
|
+
Name the spend to the person in words ("one generation") and get the
|
|
98
|
+
yes before the record; the consent then lives in the file and the
|
|
99
|
+
command line, where a reviewer can read it.
|
|
100
|
+
5. **Is the result async, and how long.** A product that finishes later (a
|
|
101
|
+
render, a generation, a deploy) is ONE take with an `await` step: the
|
|
102
|
+
capture stops, the page is polled off camera, the capture resumes when
|
|
103
|
+
the predicate holds, and the cut carries the measured time
|
|
104
|
+
(`{elapsed}` in the next caption; `references/how-to.md`). Wait for
|
|
105
|
+
what only the NEW result has (a percentage that appears, then goes;
|
|
106
|
+
never a title an older item shares), size `timeout` from what the
|
|
107
|
+
product measured last time, and `download` the output into
|
|
108
|
+
`take/outputs/` so the join can play it. On the hosted recorder the
|
|
109
|
+
waits come out of the footage cap: say how long before choosing it.
|
|
110
|
+
6. **Does sound matter.** The recorder captures frames. Sound a page plays
|
|
111
|
+
through a `<video>` or `<audio>` element is kept (`@vosjs/cli` 0.79 and
|
|
112
|
+
later: each heard source lands in `meta.media` and the plan places a
|
|
113
|
+
clip per interval); sound a page synthesizes with Web Audio is not
|
|
114
|
+
heard, and a downloaded output's own sound rides as a clip through
|
|
115
|
+
`vos join`. When the sound IS the point (a voice preview, a generated
|
|
116
|
+
clip) and the product synthesizes it, say so before recording and plan
|
|
117
|
+
the download; when it is not, say the video is silent and score it.
|
|
55
118
|
|
|
56
119
|
## The core loop (every destination)
|
|
57
120
|
|
|
@@ -81,6 +144,16 @@ Per-channel dimensions and byte budgets: `references/destinations.md`.
|
|
|
81
144
|
take directory and out of git, and record from a demo account: what the
|
|
82
145
|
account shows ships in the video.
|
|
83
146
|
|
|
147
|
+
**Never script a signed-in page blind.** `vos look <url> --session <app>`
|
|
148
|
+
(or `--storage-state`; `@vosjs/cli` 0.78 and later) opens the page
|
|
149
|
+
through the door the recorder will use and prints a screenshot plus
|
|
150
|
+
every control in view with ONE proposed selector each, counted UNIQUE
|
|
151
|
+
or AMBIGUOUS by the recorder's own engine; `--click <selector>` shows
|
|
152
|
+
what a click opens before the script relies on it, and refuses a control
|
|
153
|
+
whose words mean spend, delete or submit. Take UNIQUE selectors into
|
|
154
|
+
steps as they are. Then the side-effect ledger (pre-flight, 3), then
|
|
155
|
+
rehearse.
|
|
156
|
+
|
|
84
157
|
**Verified the feature with agent-browser already?** Keep that walk and
|
|
85
158
|
skip the second script. agent-browser's `--json` result does not say
|
|
86
159
|
what ran (`scroll` answers `{scrolled:true}`), so wrap each call so the
|
|
@@ -170,9 +243,13 @@ Per-channel dimensions and byte budgets: `references/destinations.md`.
|
|
|
170
243
|
`references/sessions.md`.
|
|
171
244
|
|
|
172
245
|
3. **Record**: `vos record --actions actions.json --out take --strict --json`
|
|
173
|
-
`--strict` always: skipped selector
|
|
174
|
-
|
|
175
|
-
|
|
246
|
+
`--strict` always: a skipped selector, a failed `expect`, a click on a
|
|
247
|
+
disabled control, a timed-out `await` or a capped take → exit 2 with
|
|
248
|
+
`skipped[]` in the done event (a first load that never goes network-idle
|
|
249
|
+
is a note, not a failure, since `@vosjs/cli` 0.78). A skip means the
|
|
250
|
+
flow is broken — fix it, never ship around it. A guarded step records
|
|
251
|
+
only with `--confirm <id>` (pre-flight, 4). The take auto-encodes and
|
|
252
|
+
auto-plans.
|
|
176
253
|
(`vos create --actions actions.json out.webm --strict` is the one-shot
|
|
177
254
|
record+render verb — fine for a quick first pass, but THIS skill's loop
|
|
178
255
|
reviews frames before rendering, so prefer the separate verbs here.)
|
|
@@ -295,3 +372,14 @@ when the ask is a release, not one video.
|
|
|
295
372
|
one per gesture): mark the payoff steps and plan `--zooms per-beat`.
|
|
296
373
|
- Trusting `--strict` for the scene: it proves the steps ran, not that the
|
|
297
374
|
app holds what the beat shows. Check with `expect` + `js` + `equals`.
|
|
375
|
+
- Trusting a zoom because the track lists it: two of a film's four zooms
|
|
376
|
+
never rendered and the list said they did. `frames --at-zooms` renders
|
|
377
|
+
each apex beside its zoom-off twin and names an apex that matches its
|
|
378
|
+
twin; read the stills, never the list.
|
|
379
|
+
- A rehearsal that presses a step that spends: `--dry-run` CLICKS. A
|
|
380
|
+
spending step carries `"guard": "spend"` and an `id`, so the rehearsal
|
|
381
|
+
hovers it and `record` refuses it without `--confirm <id>`; a step that
|
|
382
|
+
only creates goes in the side-effect ledger before the first rehearsal.
|
|
383
|
+
- Scripting a signed-in product blind: `vos look` first, then the ledger,
|
|
384
|
+
then the rehearsal. Guessing selectors from a public page costs a take
|
|
385
|
+
per guess.
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# The how-to: one flow, one door, the result first
|
|
2
|
+
|
|
3
|
+
A how-to shows a person how to reach ONE result in a product: "make a
|
|
4
|
+
cinematic shot in HeyGen", "put a video on vos.so". It is the clip a docs
|
|
5
|
+
page, a changelog entry or a support answer embeds, and it is judged by
|
|
6
|
+
whether a viewer can repeat the path. The marketing rules in `taste.md`
|
|
7
|
+
still hold (one idea, open on the money shot, end settled); these are the
|
|
8
|
+
rules that are specific to the genre. They came out of three agent-made
|
|
9
|
+
how-tos and the cuts a person had to redo on them.
|
|
10
|
+
|
|
11
|
+
## The grammar
|
|
12
|
+
|
|
13
|
+
1. **One door.** A product usually has several ways to the same result
|
|
14
|
+
(a guided flow, a prompt box, an apps menu, a template). The video walks
|
|
15
|
+
ONE, and the person named it before the script was written (the
|
|
16
|
+
pre-flight in `SKILL.md`). Two doors in one clip read as two videos;
|
|
17
|
+
a door that works under automation beats the recommended one that does
|
|
18
|
+
not (never hide the automation from a site; pick the door that works, or
|
|
19
|
+
hand the shot list to a person).
|
|
20
|
+
|
|
21
|
+
2. **One caption per step, in the product's own words for the control.**
|
|
22
|
+
The caption names the control the way the product labels it, as a verb
|
|
23
|
+
phrase: "Open Apps", "Choose Cinematic Shots", "Press Generate". Not a
|
|
24
|
+
sentence about the feature, not marketing copy, nothing the footage does
|
|
25
|
+
not show. It sits on the step whose action it describes (`caption` on
|
|
26
|
+
the step in `actions.json`; `vos plan` and `vos join --captions` land
|
|
27
|
+
each one anchored to its step, so a re-record carries it). One caption
|
|
28
|
+
is one beat; a step with no caption is part of the beat before it.
|
|
29
|
+
|
|
30
|
+
3. **The result is the payoff, and the cold open.** Open on the finished
|
|
31
|
+
result for a beat (a repeated segment at camera rest,
|
|
32
|
+
`segments[].camera: "rest"`, the `vos-cut` skill's "Assemble"), then
|
|
33
|
+
the path from the door, then the result again, settled, as the last
|
|
34
|
+
frame. The result's step is the beat marked `"zoom": true`; the path's
|
|
35
|
+
clicks stay wide unless one of them is the point. `still` sits on the
|
|
36
|
+
result, never on the door.
|
|
37
|
+
|
|
38
|
+
4. **A recap card that lists the path.** The last thing on screen is the
|
|
39
|
+
path as a list, in the captions' own words, in order ("Apps → Cinematic
|
|
40
|
+
Shots → Describe the shot → Generate"), on the plate after the card
|
|
41
|
+
fades (`frame.anim.exit: "fade"` plus layers past the footage), never
|
|
42
|
+
over a frozen frame. A viewer who looked away for the middle leaves with
|
|
43
|
+
the path.
|
|
44
|
+
|
|
45
|
+
5. **Measured times only.** When the product takes time off camera (`await`
|
|
46
|
+
in the script), the cut says how long it took in the words the
|
|
47
|
+
measurement gives: `{elapsed}` in the caption after the wait prints the
|
|
48
|
+
measured time ("8 minutes later, the shot is ready"), or write the
|
|
49
|
+
number read from `meta.skips[].ms` ("About 8 minutes later"). Never a
|
|
50
|
+
round number nobody measured, never "instantly" or "in seconds", and
|
|
51
|
+
never a speed read off a capture (the recorder loads the page too).
|
|
52
|
+
|
|
53
|
+
6. **Music lands on the result.** `vos score --track <slug> --at <result
|
|
54
|
+
step id>` puts the track's swell on the payoff; a how-to with a voice
|
|
55
|
+
or the product's own sound (a generated video playing) keeps the bed
|
|
56
|
+
under it (`--gain`). The downloaded output's own sound rides as a clip
|
|
57
|
+
through `vos join`.
|
|
58
|
+
|
|
59
|
+
7. **As long as its path.** A how-to is not held to the 30 s marketing
|
|
60
|
+
band; it is held to its beats: about 1 s of reading after a page
|
|
61
|
+
changes, 0.6 s after a control, the waits cut out, nothing padded.
|
|
62
|
+
Run 3's how-to was 36 s for seven steps and an 8-minute generation.
|
|
63
|
+
|
|
64
|
+
## The checks, in order
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
vos validate actions.json # the captions sit on the steps they describe
|
|
68
|
+
vos record --actions actions.json --out take --dry-run # the door opens, the guard hovers, the wait is timed
|
|
69
|
+
vos record --actions actions.json --out take --strict --json --confirm <spend id>
|
|
70
|
+
vos plan take --zooms per-beat --still <result output s>
|
|
71
|
+
vos frames take --at-zooms # every apex beside its zoom-off twin
|
|
72
|
+
vos frames take --times <each caption start + 1> # every caption on its own ground, in the product's words
|
|
73
|
+
vos check-video out.mp4 # one cut per 5 s at most, the first and last frames stand alone
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
A caption the footage does not show, a time that was not measured, a second
|
|
77
|
+
door, or a result that is not the first and last frame each send the cut
|
|
78
|
+
back a round, not the recording.
|
|
@@ -25,6 +25,10 @@ The rubric for judging a take before its render ships. Judge stills
|
|
|
25
25
|
Launch videos may run longer but every scene must still earn its seconds.
|
|
26
26
|
3. **End settled.** Close on a resolved state (result visible, motion parked),
|
|
27
27
|
never mid-action — the loop point should read as intentional.
|
|
28
|
+
A **how-to** (one flow to one result, for a docs page or a changelog)
|
|
29
|
+
keeps all three and adds its own: one door, one caption per step in
|
|
30
|
+
the product's words for the control, the result as the cold open and
|
|
31
|
+
the last frame, a recap card, measured times only (`how-to.md`).
|
|
28
32
|
|
|
29
33
|
## Flow authoring (actions.json)
|
|
30
34
|
|
|
@@ -49,14 +49,18 @@ selector matched no element, so whatever it was for may be showing.
|
|
|
49
49
|
|
|
50
50
|
## Strict-mode failures (exit 2)
|
|
51
51
|
|
|
52
|
-
`vos record --strict` exits 2 when a selector was skipped
|
|
53
|
-
|
|
52
|
+
`vos record --strict` exits 2 when a selector was skipped, an `expect`
|
|
53
|
+
failed, a click landed on a disabled control, an `await` timed out or the
|
|
54
|
+
take hit its cap, with `skipped[]` in the `--json` done event.
|
|
54
55
|
|
|
55
56
|
- A skipped selector means the flow is broken: the element wasn't there, the
|
|
56
57
|
selector is unstable (nth-child chains), or the page needed more settle
|
|
57
58
|
time. Fix the actions.json — never ship a take that silently skipped steps.
|
|
58
|
-
-
|
|
59
|
-
`
|
|
59
|
+
- A first load that never goes network-idle (long-polling, websockets: most
|
|
60
|
+
SaaS) is a note (`navTimeout`), never a strict failure, since `@vosjs/cli`
|
|
61
|
+
0.78, and since 0.79 a take starts once the DOM has stopped changing
|
|
62
|
+
(`ready: "dom"`, the default; `networkidle` is the opt-in). On an older
|
|
63
|
+
CLI, add explicit `wait` steps after navigation instead of relying on it.
|
|
60
64
|
- Always pass `--strict`. The lenient default exits 0 over broken flows,
|
|
61
65
|
which is how bad takes ship.
|
|
62
66
|
|
package/skills/vos-cut/SKILL.md
CHANGED
|
@@ -102,6 +102,27 @@ video PLAYING, not idle. Neither wants the planner's proposal.
|
|
|
102
102
|
If a folder is involved, read EVERY `.md` in it (own and inherited) before
|
|
103
103
|
you decide anything.
|
|
104
104
|
|
|
105
|
+
**Before the first cut, four answers from the frames** (a human's take has
|
|
106
|
+
no mask and no exposure list; the scan needs the page):
|
|
107
|
+
|
|
108
|
+
1. **Whose account, face and work is on screen.** An address, a key or a
|
|
109
|
+
card in a frame is said before anything is pushed, and the honest fix
|
|
110
|
+
is a re-record from a demo account, since a blur in `doc.json` leaves
|
|
111
|
+
the value in the footage `vos push` uploads. The person's own name,
|
|
112
|
+
face, avatar and recent items are theirs to show: say they are on
|
|
113
|
+
screen, never treat them as a defect.
|
|
114
|
+
2. **Which door the footage walks.** A how-to names ONE way to the result.
|
|
115
|
+
A recording that wanders through two (a guided flow abandoned for an
|
|
116
|
+
apps menu) is cut to the one that reached the result, and the note says
|
|
117
|
+
which.
|
|
118
|
+
3. **Where time was skipped.** A scripted take's off-camera wait is in
|
|
119
|
+
`meta.skips` and `vos info` prints it; the caption after it carries the
|
|
120
|
+
MEASURED time, never a round number nobody measured.
|
|
121
|
+
4. **What the sound is.** The take's own sound (a mic), the sound the page
|
|
122
|
+
played (`meta.media`, placed as `source: "page"` clips by the plan),
|
|
123
|
+
the sound a downloaded output brought through `vos join`. The cut keeps
|
|
124
|
+
a sound the beat is about and never speeds over it.
|
|
125
|
+
|
|
105
126
|
## 2. Narrate
|
|
106
127
|
|
|
107
128
|
Write 3-6 beats into your working notes, each with its moment ids, what it
|
|
@@ -163,6 +184,16 @@ Per beat, against `plan` and the recipe:
|
|
|
163
184
|
light (an editor's timeline is), and judge every caption at its own
|
|
164
185
|
instant. One caption per film is too sparse for a film that explains a
|
|
165
186
|
flow; zero is right only when the recipe or the ask says no text.
|
|
187
|
+
- **A how-to** (one flow to one result, for a docs page or a changelog)
|
|
188
|
+
has a grammar of its own: one caption per STEP, in the product's own
|
|
189
|
+
words for the control as a verb phrase ("Open Apps", "Press Generate"),
|
|
190
|
+
anchored to the step (`anchor: { step }`) so a re-record carries it;
|
|
191
|
+
the result as the cold open (a repeated segment at camera rest) and as
|
|
192
|
+
the last frame, with `still` on it and the one `"zoom": true` mark;
|
|
193
|
+
a recap card listing the path in the captions' words on the plate after
|
|
194
|
+
the card fades; an off-camera wait said in measured time (`{elapsed}`
|
|
195
|
+
in the caption after it); music scored `--at` the result's step. Never
|
|
196
|
+
a caption the footage does not show, never a second door.
|
|
166
197
|
- **Style.** In a series, `vos plan --style <seed>` BEFORE you cut: it copies
|
|
167
198
|
the seed's `zoomStyle`/`zoomParams`/`speedParams`/`tiltStyle`/`frame`/
|
|
168
199
|
`cursor`/`cam`/`export` and re-plans the auto spans under them. Never
|
|
@@ -254,6 +285,9 @@ never write a status line.
|
|
|
254
285
|
start, under the first caption);
|
|
255
286
|
- open a zoom before the click it frames, or aim it at a `type` verb's
|
|
256
287
|
field centre (frame the text; start the span after the click);
|
|
288
|
+
- trust a zoom because the track lists it: `frames --at-zooms` renders
|
|
289
|
+
each apex beside its zoom-off twin and names one that matches its twin;
|
|
290
|
+
a listed zoom that never rendered has shipped in a film before;
|
|
257
291
|
- leave the cold open frozen (a static page records as freeze-then-bang:
|
|
258
292
|
trim it, or speed the load);
|
|
259
293
|
- end wide on an empty page: the last frame is the poster, so the closing
|