@vosjs/cli 0.68.0 → 0.69.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.
@@ -1,30 +1,22 @@
1
1
  {
2
- "$comment": "Per-channel launch-asset specs — the data the launch-kit skill loops over (mirrored as references/channel-specs.md in vosjs/skills; update together). Verified against official platform docs 2026-08-04; platform specs drift, re-verify quarterly. Image specs carry `genre`: 'screenshot' = real UI from the take (store policy demands real UX); 'card' = a composed cover — rendered from the poster program when one is in hand. `text` is the destination's word policy: 'none' (the picture carries it alone: a tile, a store screenshot), 'allowed', 'expected' (a card that should say something). `safe` is the rect, as fractions of the frame, that every text box must sit inside (the platform's own chrome or crop covers the rest); the picture checks read both. `template` names the poster template a card destination renders from by default (the family that ships with the CLI: split-cover carries a headline, card-on-gradient carries none).",
2
+ "$comment": "Per-channel video specs, the data `vos deliver` loops over (mirrored as references/channel-specs.md in vosjs/skills; update together). Verified against official platform docs 2026-08-04; platform specs drift, re-verify quarterly. `text` is the destination word policy: 'none' (the picture carries it alone, so the beat captions drop), 'allowed', 'expected'.",
3
3
  "version": 1,
4
4
  "verified": "2026-08-04",
5
5
  "specs": [
6
6
  {
7
7
  "channel": "youtube",
8
8
  "asset": "main-demo",
9
- "kind": "video",
10
9
  "w": 1920,
11
10
  "h": 1080,
12
11
  "minSeconds": 60,
13
12
  "maxSeconds": 120,
14
13
  "format": "mp4 (H.264+AAC)",
15
14
  "notes": "Captions burned in. The same public upload serves the Chrome Web Store promo video and Product Hunt video (both take YouTube URLs only).",
16
- "text": "allowed",
17
- "safe": {
18
- "x": 0.05,
19
- "y": 0.08,
20
- "w": 0.9,
21
- "h": 0.84
22
- }
15
+ "text": "allowed"
23
16
  },
24
17
  {
25
18
  "channel": "x",
26
19
  "asset": "feed-cut",
27
- "kind": "video",
28
20
  "w": 1920,
29
21
  "h": 1080,
30
22
  "minSeconds": 30,
@@ -32,36 +24,22 @@
32
24
  "maxBytes": 536870912,
33
25
  "format": "mp4 (H.264+AAC ONLY — HEVC/VP9/AV1 rejected)",
34
26
  "notes": "30–60s plays best; 140s/512MB is the free-tier ceiling. 1:1 also allowed. Native upload, never a link post.",
35
- "text": "allowed",
36
- "safe": {
37
- "x": 0.05,
38
- "y": 0.08,
39
- "w": 0.9,
40
- "h": 0.84
41
- }
27
+ "text": "allowed"
42
28
  },
43
29
  {
44
30
  "channel": "shorts-linkedin",
45
31
  "asset": "vertical-cut",
46
- "kind": "video",
47
32
  "w": 1080,
48
33
  "h": 1920,
49
34
  "minSeconds": 30,
50
35
  "maxSeconds": 90,
51
36
  "format": "mp4 (H.264+AAC)",
52
37
  "notes": "Critical text inside a centered ~900×1160 safe zone — platform chrome covers the rest. Serves YouTube Shorts and LinkedIn native vertical.",
53
- "text": "expected",
54
- "safe": {
55
- "x": 0.0833,
56
- "y": 0.1979,
57
- "w": 0.8333,
58
- "h": 0.6042
59
- }
38
+ "text": "expected"
60
39
  },
61
40
  {
62
41
  "channel": "github",
63
42
  "asset": "readme-loop",
64
- "kind": "video",
65
43
  "w": 1920,
66
44
  "h": 1080,
67
45
  "minSeconds": 10,
@@ -69,213 +47,7 @@
69
47
  "maxBytes": 10485760,
70
48
  "format": "mp4 (H.264)",
71
49
  "notes": "≤10MB is the free-plan attachment ceiling; two-pass target bitrate from duration.",
72
- "text": "none",
73
- "safe": {
74
- "x": 0.05,
75
- "y": 0.08,
76
- "w": 0.9,
77
- "h": 0.84
78
- }
79
- },
80
- {
81
- "channel": "youtube",
82
- "asset": "thumbnail",
83
- "kind": "image",
84
- "w": 1280,
85
- "h": 720,
86
- "maxBytes": 2097152,
87
- "format": "png|jpg",
88
- "notes": "",
89
- "genre": "card",
90
- "text": "expected",
91
- "safe": {
92
- "x": 0.05,
93
- "y": 0.08,
94
- "w": 0.9,
95
- "h": 0.84
96
- },
97
- "template": "split-cover"
98
- },
99
- {
100
- "channel": "cws",
101
- "asset": "screenshot",
102
- "kind": "image",
103
- "w": 1280,
104
- "h": 800,
105
- "count": "1-5",
106
- "format": "png|jpg",
107
- "notes": "Real UX only — misleading listing images are a removal-grade violation. Full bleed, square corners.",
108
- "genre": "screenshot",
109
- "text": "none",
110
- "safe": {
111
- "x": 0,
112
- "y": 0,
113
- "w": 1,
114
- "h": 1
115
- }
116
- },
117
- {
118
- "channel": "cws",
119
- "asset": "small-promo-tile",
120
- "kind": "image",
121
- "w": 440,
122
- "h": 280,
123
- "format": "png|jpg",
124
- "notes": "Listings without one rank lower. No text; fill the region; subject centered.",
125
- "genre": "card",
126
- "text": "none",
127
- "safe": {
128
- "x": 0,
129
- "y": 0,
130
- "w": 1,
131
- "h": 1
132
- },
133
- "template": "card-on-gradient"
134
- },
135
- {
136
- "channel": "cws",
137
- "asset": "marquee",
138
- "kind": "image",
139
- "w": 1400,
140
- "h": 560,
141
- "format": "png|jpg",
142
- "notes": "Carousel eligibility.",
143
- "genre": "card",
144
- "text": "allowed",
145
- "safe": {
146
- "x": 0.05,
147
- "y": 0.08,
148
- "w": 0.9,
149
- "h": 0.84
150
- },
151
- "template": "split-cover"
152
- },
153
- {
154
- "channel": "cws",
155
- "asset": "icon",
156
- "kind": "image",
157
- "w": 128,
158
- "h": 128,
159
- "format": "png",
160
- "notes": "96×96 art + 16px transparent padding.",
161
- "text": "none",
162
- "safe": {
163
- "x": 0,
164
- "y": 0,
165
- "w": 1,
166
- "h": 1
167
- }
168
- },
169
- {
170
- "channel": "producthunt",
171
- "asset": "thumbnail",
172
- "kind": "image",
173
- "w": 240,
174
- "h": 240,
175
- "maxBytes": 3145728,
176
- "format": "gif|png",
177
- "notes": "GIF animates on hover only — the first frame must stand alone.",
178
- "genre": "card",
179
- "text": "none",
180
- "safe": {
181
- "x": 0.06,
182
- "y": 0.06,
183
- "w": 0.88,
184
- "h": 0.88
185
- },
186
- "template": "card-on-gradient"
187
- },
188
- {
189
- "channel": "producthunt",
190
- "asset": "gallery",
191
- "kind": "image",
192
- "w": 1270,
193
- "h": 760,
194
- "count": "4-8",
195
- "format": "png|jpg|gif",
196
- "notes": "First image is the hero.",
197
- "genre": "screenshot",
198
- "text": "none",
199
- "safe": {
200
- "x": 0,
201
- "y": 0,
202
- "w": 1,
203
- "h": 1
204
- }
205
- },
206
- {
207
- "channel": "x",
208
- "asset": "feed-image",
209
- "kind": "image",
210
- "w": 1200,
211
- "h": 675,
212
- "format": "png|jpg",
213
- "notes": "",
214
- "genre": "card",
215
- "text": "allowed",
216
- "safe": {
217
- "x": 0.05,
218
- "y": 0.08,
219
- "w": 0.9,
220
- "h": 0.84
221
- },
222
- "template": "split-cover"
223
- },
224
- {
225
- "channel": "linkedin",
226
- "asset": "feed-image",
227
- "kind": "image",
228
- "w": 1200,
229
- "h": 627,
230
- "format": "png|jpg",
231
- "notes": "1080×1350 vertical also performs in the mobile feed.",
232
- "genre": "card",
233
- "text": "expected",
234
- "safe": {
235
- "x": 0.05,
236
- "y": 0.08,
237
- "w": 0.9,
238
- "h": 0.84
239
- },
240
- "template": "split-cover"
241
- },
242
- {
243
- "channel": "og",
244
- "asset": "card",
245
- "kind": "image",
246
- "w": 1200,
247
- "h": 630,
248
- "maxBytes": 1048576,
249
- "format": "png|jpg",
250
- "notes": "Text in the center ~1080×600. Set twitter:card=summary_large_image explicitly — og:image alone gets the small card.",
251
- "genre": "card",
252
- "text": "expected",
253
- "safe": {
254
- "x": 0.05,
255
- "y": 0.0238,
256
- "w": 0.9,
257
- "h": 0.9524
258
- },
259
- "template": "split-cover"
260
- },
261
- {
262
- "channel": "github",
263
- "asset": "social-preview",
264
- "kind": "image",
265
- "w": 1280,
266
- "h": 640,
267
- "maxBytes": 1048576,
268
- "format": "png|jpg",
269
- "notes": "Key text ≥50px from every edge.",
270
- "genre": "card",
271
- "text": "expected",
272
- "safe": {
273
- "x": 0.0391,
274
- "y": 0.0781,
275
- "w": 0.9219,
276
- "h": 0.8438
277
- },
278
- "template": "card-on-gradient"
50
+ "text": "none"
279
51
  }
280
52
  ]
281
53
  }
@@ -526,7 +526,7 @@
526
526
  "fit": {
527
527
  "type": "string",
528
528
  "enum": ["contain", "cover"],
529
- "description": "How footage meets an off-ratio frame. contain (default) letterboxes the card onto the background; cover makes the padded area the card and fills it with footage, cropped around `focus` \u2014 what a 440x280 store tile or a 2.5:1 marquee demands"
529
+ "description": "How footage meets an off-ratio frame. contain (default) letterboxes the card onto the background; cover makes the padded area the card and fills it with footage, cropped around `focus` \u2014 what a 9:16 cut of 16:9 footage demands"
530
530
  },
531
531
  "camera": {
532
532
  "type": "string",
@@ -696,7 +696,7 @@
696
696
  "still": {
697
697
  "type": "number",
698
698
  "minimum": 0,
699
- "description": "The frame that stands for this take, in OUTPUT seconds: the cover the shelf shows, the still a kit leads with (vos plan --still <t>, LAUNCH.md still:). Absent, the take's own last freeze (a poster's rest; a template's freezes never count), else the hero moment after the card and the opening clips have entered."
699
+ "description": "The frame that stands for this take, in OUTPUT seconds: the cover the shelf shows (vos plan --still <t>, LAUNCH.md still:). Absent, the take's own last freeze (the rest a closing hold ends on; a template's freezes never count), else the hero moment after the card and the opening clips have entered."
700
700
  }
701
701
  }
702
702
  },
@@ -1613,7 +1613,7 @@
1613
1613
  },
1614
1614
  "freeze": {
1615
1615
  "type": "array",
1616
- "description": "Freezes (SOURCE moments, footage-anchored): the footage frozen on the frame just before `at` for `seconds` of output, anywhere in the take (a pause on a state while a caption reads, a beat before a cut, the rest a poster ends on). The retime primitive beside `speed`: a speed span is a source range with a rate, a freeze a source point with a length. A freeze whose frame is trimmed away has no effect and comes back when the trim does. The still every still-taking surface takes (the thumbnail, a poster's render, the stills export's first moment) is where the LAST freeze begins. Absent = none. The output ending past the footage needs no freeze: the card holds its last frame under the clips that outlast it.",
1616
+ "description": "Freezes (SOURCE moments, footage-anchored): the footage frozen on the frame just before `at` for `seconds` of output, anywhere in the take (a pause on a state while a caption reads, a beat before a cut, the rest a poster ends on). The retime primitive beside `speed`: a speed span is a source range with a rate, a freeze a source point with a length. A freeze whose frame is trimmed away has no effect and comes back when the trim does. The still every still-taking surface takes (the thumbnail, the cover) is where the LAST freeze begins. Absent = none. The output ending past the footage needs no freeze: the card holds its last frame under the clips that outlast it.",
1617
1617
  "items": {
1618
1618
  "type": "object",
1619
1619
  "required": ["id", "at", "seconds"],
package/skills/VERSION CHANGED
@@ -1 +1 @@
1
- 0.22.0
1
+ 0.23.0