@vosjs/cli 0.60.0 → 0.61.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/plugin/landed.ts","../src/plugin/run.ts","../src/plugin/output.ts","../src/plugin/actions.ts","../src/plugin/validateDoc.ts","../src/plugin/mediaProbe.ts","../src/plugin/framesTake.ts","../src/plugin/server.ts","../src/plugin/renderAnimation.ts","../src/plugin/backdrops.ts","../src/plugin/docOverride.ts","../src/plugin/digestTake.ts","../src/plugin/deliver.ts","../src/plugin/renderTake.ts","../src/plugin/moments.ts","../src/plugin/picture.ts","../src/plugin/motionPlan.ts","../src/plugin/posterDoc.ts","../src/plugin/markAsset.ts","../src/plugin/officialTemplates.ts","../src/plugin/music.ts","../src/plugin/judge.ts","../src/plugin/shotBake.ts","../src/plugin/fontName.ts","../src/plugin/callout.ts","../src/plugin/kitPicture.ts","../src/plugin/validateKit.ts","../src/plugin/recorder.ts","../src/plugin/wall.ts","../src/plugin/exposure.ts","../src/plugin/setup.ts","../src/plugin/session.ts","../src/plugin/recordingCap.ts","../src/plugin/encode.ts","../src/plugin/plan.ts","../src/plugin/reuse.ts","../src/plugin/sync.ts","../src/plugin/folder.ts","../src/plugin/program.ts","../src/plugin/login.ts","../src/plugin/asset.ts","../src/plugin/remove.ts","../src/plugin/trash.ts","../src/plugin/buildProgram.ts","../src/plugin/compare.ts","../src/plugin/port.ts","../src/plugin/portInventory.ts","../src/plugin/portRemotion.ts","../src/plugin/portScaffold.ts","../src/plugin/painterLib.ts","../src/plugin/recipe.ts","../src/plugin/brand.ts","../src/plugin/hostedRecord.ts","../src/plugin/agentBrowser.ts","../src/plugin/ingest.ts","../src/plugin/machineCmd.ts","../src/plugin/machine.ts"],"sourcesContent":["/**\n * `vos push --wait`: stay until what was pushed can be LOOKED at.\n *\n * A push answers as soon as the version exists, but its still and preview\n * are rendered afterwards on the fleet, so \"look at what landed\" used to\n * mean polling the API by hand. The version's own still answers 404 until\n * its render lands, which makes it the one honest signal; once it is there\n * the vos's `contentUrls` name the still and preview to open, made absolute\n * here because a relative path means nothing outside the site.\n *\n * A render that is deferred (the fleet rates media) or slow is not a failed\n * push: the wait ends in words, with the links to come back to.\n */\nimport { apiJson } from './platform'\n\nexport interface Landed {\n /** The version's still rendered before the wait ran out. */\n still: boolean\n watchUrl: string\n studioUrl: string\n thumbnailUrl: string | null\n previewUrl: string | null\n /** A private vos's links answer only to its owner's key or session. */\n private: boolean\n waitedMs: number\n}\n\nexport interface WaitOptions {\n origin: string\n key: string\n vosId: string\n versionId: string | null\n timeoutMs?: number\n intervalMs?: number\n log?: (line: string) => void\n /** Injected in tests. */\n sleep?: (ms: number) => Promise<void>\n now?: () => number\n}\n\nconst absolute = (origin: string, url: unknown): string | null =>\n typeof url === 'string' && url\n ? /^https?:/.test(url)\n ? url\n : `${origin}${url.startsWith('/') ? '' : '/'}${url}`\n : null\n\nexport async function waitForLanded(opts: WaitOptions): Promise<Landed> {\n const origin = opts.origin.replace(/\\/+$/, '')\n const sleep =\n opts.sleep ?? ((ms: number) => new Promise((r) => setTimeout(r, ms)))\n const now = opts.now ?? (() => Date.now())\n const timeoutMs = opts.timeoutMs ?? 300_000\n const intervalMs = opts.intervalMs ?? 4_000\n const started = now()\n let still = false\n if (opts.versionId) {\n opts.log?.('waiting for the still to render…')\n for (;;) {\n const res = await fetch(\n `${origin}/api/vos/${opts.vosId}/versions/${opts.versionId}/thumbnail`,\n { headers: { authorization: `Bearer ${opts.key}` } },\n )\n await res.arrayBuffer().catch(() => undefined)\n if (res.ok) {\n still = true\n break\n }\n if (now() - started >= timeoutMs) break\n await sleep(intervalMs)\n }\n }\n const meta = await apiJson(origin, `/api/vos/${opts.vosId}`, {\n key: opts.key,\n })\n // The single-vos read wraps its answer: { vos: { …, contentUrls } }.\n const vos = (meta.body.vos ?? {}) as Record<string, unknown>\n const urls = (vos.contentUrls ?? {}) as Record<string, unknown>\n return {\n still,\n watchUrl: `${origin}/vos/${opts.vosId}`,\n studioUrl: `${origin}/studio?vos=${opts.vosId}`,\n thumbnailUrl: still ? absolute(origin, urls.thumbnail) : null,\n previewUrl: still ? absolute(origin, urls.preview) : null,\n private: vos.visibility === 'private',\n waitedMs: now() - started,\n }\n}\n\n/** The lines a waited push prints under its own. */\nexport function landedLines(l: Landed): string {\n if (!l.still) {\n return ` still: not rendered yet (the fleet renders it after the push; open the watch page in a minute)`\n }\n const links = !!(l.thumbnailUrl || l.previewUrl)\n return [\n l.thumbnailUrl ? ` still: ${l.thumbnailUrl}` : null,\n l.previewUrl ? ` preview: ${l.previewUrl}` : null,\n // A bare fetch of a private vos's media answers 404 by design; say so,\n // or the still reads as missing when it is only fenced.\n links && l.private\n ? ` (private: these answer 404 without a credential; fetch with 'Authorization: Bearer <your key>' or open them signed in)`\n : null,\n ]\n .filter(Boolean)\n .join('\\n')\n}\n","import { videoFormat } from '../outputs'\nimport { landedLines, waitForLanded } from './landed'\nimport { mkdir, readFile, rm } from 'node:fs/promises'\nimport { existsSync } from 'node:fs'\nimport { join, resolve } from 'node:path'\nimport {\n END_CARD_FROM,\n docOutputDuration,\n migrateHostedDoc,\n} from '@vosjs/studio-core'\nimport { UsageError, hasFlag, numFlag, parseArgs, strFlag } from './args'\nimport {\n EXIT_ERROR,\n EXIT_NO_BROWSER,\n EXIT_OK,\n EXIT_USAGE,\n EXIT_WALL,\n createReporter,\n} from './output'\nimport { validateActions } from './actions'\nimport { lintDoc } from './validateDoc'\nimport { containerMismatch } from './container'\nimport { readMediaHead } from './media'\nimport {\n collectConfigMediaUrls,\n collectDocMediaUrls,\n mediaProbeLints,\n probeMediaUrls,\n} from './mediaProbe'\nimport { framesTake, parseTimes, writeIndexJson } from './framesTake'\nimport {\n deliverTake,\n readLaunchBesideTake,\n resolveChannels,\n resolveLook,\n readBrandBesideTake,\n} from './deliver'\nimport { fetchBrandMarks } from './markAsset'\nimport { endCardInk } from './motionPlan'\nimport type { MotionAnchor, MotionTemplate } from './motionPlan'\nimport { OFFICIAL_END_CARD_TITLE, findOfficialByRef } from './officialTemplates'\nimport type { OfficialRow } from './officialTemplates'\nimport { fetchMusicCatalog } from './music'\nimport { judgeKit, winRate } from './judge'\nimport { resolveStepTime } from './moments'\nimport {\n composeCallout,\n footageFrames,\n groundFindings,\n isCalloutShape,\n registerFrom,\n} from './callout'\nimport { formatFinding } from './kitPicture'\nimport { validateKit } from './validateKit'\nimport { digestTake, parseTranscript } from './digestTake'\nimport {\n apiJson,\n platformOrigin,\n readSyncState,\n requireCredential,\n resolveCredential,\n} from './platform'\nimport { startTakeServer } from './server'\nimport {\n PREV_DOC_NAME,\n dropScreencastFrames,\n ensureTakeDir,\n loadTake,\n prepareReRecord,\n takePaths,\n writeJson,\n} from './take'\nimport { deadLine, deadWarns } from './pace'\nimport type { TakePaths } from './take'\nimport { BrowserUnavailableError, launchBrowser } from '../browser'\nimport { recordTake } from './recorder'\nimport { WALL_PROBE, WallError, wallVerdict } from './wall'\nimport { EXPOSURE_ADVICE, exposureLine } from './exposure'\nimport { SetupEnvError, SetupError, parseHeaders } from './setup'\nimport {\n listSessions,\n openSession,\n removeSession,\n sessionDir,\n sessionNameVerdict,\n summarizeSession,\n summaryLine,\n withSession,\n} from './session'\nimport type { Arrival, WallVerdict } from './wall'\nimport type { Reporter } from './output'\nimport {\n defaultMaxDurationSeconds,\n formatDurationCap,\n hostedRecordingCap,\n} from './recordingCap'\nimport { encodeRecording } from './encode'\nimport { planTake } from './plan'\nimport { openingBackdrop } from './backdrops'\nimport { renderTake } from './renderTake'\nimport { pullTake, pushTake, takePushRefusal } from './sync'\nimport {\n cmdDuplicate,\n cmdFetch,\n cmdLogin,\n cmdPullProgram,\n cmdPushProgram,\n isTakeDir,\n preflightConfig,\n readProgramDoc,\n} from './program'\nimport { cmdFolder } from './folder'\nimport { cmdAsset } from './asset'\nimport { cmdDelete } from './remove'\nimport { cmdRestore, cmdTrash } from './trash'\nimport { cmdBuild } from './buildProgram'\nimport { cmdCompare } from './compare'\nimport { cmdPort } from './port'\nimport { cmdRecipe } from './recipe'\nimport { cmdBrand } from './brand'\nimport { hostedEnv, recordHosted } from './hostedRecord'\nimport { cmdActions } from './agentBrowser'\nimport { cmdIngest } from './ingest'\nimport { cmdDoctor, cmdLogout, cmdSetup, cmdWhoami } from './machineCmd'\nimport type { Backdrop, ProjectDoc } from '@vosjs/studio-core'\nimport type { ActionsFile } from './actions'\nimport type { ParsedArgs } from './args'\n\nconst BOOLEAN_FLAGS = new Set([\n 'json',\n 'help',\n 'wait',\n 'picture',\n 'fresh',\n 'reuse',\n 'strict',\n 'draft',\n 'at-zooms',\n 'at-moments',\n 'at-still',\n 'no-frames',\n 'media',\n 'print',\n 'yes',\n 'composed',\n 'check',\n 'motion',\n 'leader',\n 'keep-frames',\n 'dry-run',\n 'allow-wall',\n 'hosted',\n])\n/** Repeatable value flags (accumulate): --set path=value on render/frames, --override id on push, --browser-arg=<switch> on record/create. */\nexport const MULTI_FLAGS = new Set(['set', 'override', 'browser-arg', 'header'])\n\nexport const HELP = `vos — record a browser flow, plan effects, render a product video; sync with vos.so\n\nTake pipeline\n vos create --actions actions.json [--url <url>] [--out take] [out.webm] [--strict] [--allow-wall] [--keep-frames] [--max-duration <s>] [--storage-state <file>|--session <name>] [--header name=value]... [--browser-arg=<switch>]... [--background <slug|url|none>] [render flags] [--json]\n vos record --actions actions.json [--url <url>] [--out take] [--strict] [--dry-run] [--allow-wall] [--keep-frames] [--max-duration <s>] [--storage-state <file>|--session <name>] [--header name=value]... [--browser-arg=<switch>]... [--background <slug|url|none>] [--json]\n vos record --hosted --actions actions.json [--url <url>] [--out take] [--title \"…\"] [--folder <id>] [--header name=value]... [--json]\n the take recorded on vos.so's fleet (no browser here): lands as a private vos with its doc and digest, then fetched into --out with its media\n vos plan <take> [--fresh] [--reuse [--from <doc.json>]] [--style <doc.json|vosId>] [--with <doc.json|vosId>[@end|@start|@step:<id>|@<s>]]... [--background <slug|url|none>] [--motion] [--headline \"…\"] [--kicker \"…\"] [--launch LAUNCH.md] [--brand BRAND.md] [--music <slug|mood|none>] [--entrance tilt-in|pull-out|rise|fade|slide|none] [--transitions slide|fade|scale|none] [--end-card on|none|<doc.json|vosId>] [--captions none] [--clicks none] [--still <t>] [--release v2.1] [--json]\n vos render <take> [out.webm] [--width] [--height] [--fps] [--format webm|mp4] [--parallel N] [--range a..b] [--draft] [--frame <kind>] [--background <url|slug>] [--set <path=value>]... [--json]\n vos frames <take> [--times 0,25%,50%,75%,100%] [--frame <t>] [--at-zooms] [--at-moments] [--at-still] [--size WxH] [--out dir] [--background <url|slug>] [--set <path=value>]... [--json]\n vos deliver <take> --to cws,producthunt,x,linkedin,og,github,youtube (or all) [--launch LAUNCH.md] [--look plate|gradient|dark|none] [--brand BRAND.md] [--composed] [--set path=value] [--release v2.1] [--out dir] [--times a,b] [--range a..b] [--parallel N] [--json]\n vos digest <take> [--out dir] [--full 960] [--crop 640] [--no-frames] [--transcript <file.json>] [--style <doc.json|vosId>] [--json]\n vos brand <url> [--out BRAND.md] [--json]\n vos open <take> [--studio <url>] [--print]\n vos callout <take> <note|tag|code> --step <id> [--title \"…\"] [--body \"…\"] [--kicker \"…\"] [--code \"…\"|--code-file f] [--seconds 3] [--side auto|right|left|below|above] [--mark ring|underline|none] [--leader] [--color #hex (the mark and leader; the kicker is --accent)] [--brand BRAND.md] [--ground #hex] [--accent #hex] [--font \"…\"] [--body-px <n> (the body size on the delivered frame)] [--id x] [--print] [--json]\n vos validate <actions.json|take|kit.json> [--picture] [--json]\n vos judge <kit.json> --against <MANIFEST.json> [--out dir] [--json]\n vos actions from-agent-browser <steps.jsonl> [--out actions.json] [--url <url>] [--viewport WxH] [--json]\n vos ingest <video.webm|mp4> [--cursor <trace.zip|steps.jsonl|cursor.csv>] [--as footage|take] [--out take] [--offset <ms>] [--viewport WxH] [--background <slug|url|none>] [--json]\n a take from a recording someone else made (a cloud agent's PR video, a Playwright run's video, a Loom export): the file becomes recording.<container>, meta.json from its own dimensions and duration, and a trace beside it becomes cursor.json so the planner has clicks to zoom on; without one, nothing is planned and the done event says so. Without a trace the file opens as FINISHED footage (a render from HyperFrames or Remotion, a film): no card, no browser bar, no drawn cursor, its own frame rate; --as take gives a screen demo the card\n vos port inventory <page.html|project dir> [--render <their render.mp4>] [--out port] [--json]\n a finished piece (a HyperFrames composition, a Remotion project bundled with its own bundler, a hand-rolled page) read as a browser renders it: words, palette, faces (catalog or missing), media, scenes, gaps → port/inventory.json, with stills from its render\n vos port scaffold [--from port/inventory.json] [--out port/program] [--json]\n a data-first program from it: every word a bound element, every colour a key, knobs, a label and a TODO per scene, the score as a doc.json track, port/REPORT.md\n vos build <program.mjs> [--out config.json] [--json]\n real functions → config.json, refusing a module-scope read, syntax the page cannot run and non-JSON data; config.sources.json maps each function to its line\n vos compare <program dir|config.json> --against <their render.mp4> [--times a,b,50%] [--every 1] [--threshold 0.95] [--out compare] [--json]\n per-frame SSIM and source | vos | difference sheets; exit 1 when ANY frame is under the threshold (needs ffmpeg)\n vos session open <url> --name <app> a plain Chrome window on a vos-owned profile; sign in, close it\n vos session check <name> [--url <url>] headless: does the session still open the page? exit 0/4\n vos session list | rm <name> what exists and how old; delete one\n vos actions script <actions.json> [--json]\n the flow as numbered beats in words, for a person recording it by hand\n\nThis machine (no account)\n vos setup [--agent claude,cursor,codex,copilot|all] [--global] [--no-skills] [--no-rules] [--no-browser] [--url <dev server>] [--json]\n ready this computer for the loop: the vos skills into your\n agent's directories (npx skills add vosjs/skills, else the copy\n bundled in this package), a browser found or installed, one\n idempotent block in AGENTS.md (or CLAUDE.md), then doctor.\n NDJSON whenever stdout is not a TTY; done carries next_step\n vos doctor [--url <dev server>] [--json]\n what is ready, in words: node, browser, ffmpeg, the skills per\n agent, a credential (present or absent, never printed), and the\n dev server when --url names one. Exit 3 when no browser\n vos whoami [--json]\n the key's name and the account it belongs to, never the key\n vos logout [--json]\n remove ~/.config/vos/credentials (VOS_API_KEY still resolves)\n\nPlatform (vos.so) — fetch, edit, push, pull, repeat\n vos login [--key <vos_sk_…>] [--handoff <url>] [--label <name>] [--no-browser]\n sign in via the browser (approve at vos.so/cli/auth; works\n headless — print the URL, a human approves, the key stores\n itself). --key skips the browser (mint at vos.so/app/api).\n --handoff https://vos.so/h/… exchanges the setup link a\n signed-in person's line carries for a key, once, no click\n vos fetch <vosId|watch-url> [--out dir] [--media] [--json]\n writes config.json + vos.json (no auth needed for public programs);\n a take vos also gets its doc.json, and --media its footage\n vos push <config.json|take> [--vos id] [--title t] [--slug s] [--remix-of id]\n [--desc d] [--tags a,b] [--folder <folderId|slug>]\n [--note n] [--label l] [--base versionId] [--override <id>]... [--yes] [--json]\n [--claimable] [--wait] [--still <seconds>]\n a take DIRECTORY (doc.json) pushes recording + doc; a config.json\n pushes the program. No --vos: create a PRIVATE vos; with --vos:\n add a version against the tracked base — a stale push 409s WITH\n the platform's typed changelog. A TAKE pushes to the vos in its\n vos.json; --vos on a take with none ADOPTS that vos (the take\n becomes its next version, built on its head), and --vos that\n disagrees with vos.json is refused before anything uploads. --claimable (programs only, NO\n credential): creates a 72h claim link instead — hand it to the\n user and nowhere else; unclaimed work is deleted after 72h.\n --override consents to touching\n protected (human-edited) nodes, ONLY when the user asked.\n Without --folder a new vos lands unfiled, at the root of your\n shelf. A document's local files (doc.json: picture and video\n overlays, 3D props, sound; a take's mic and cam too) upload\n with the push, each once. --wait stays until the version's still has\n rendered and prints absolute still and preview links.\n --still <seconds> sets a PROGRAM's cover (doc.json \"still\", kept\n by every later push); without it the platform picks an early\n frame. A take's cover is its doc.json \"still\".\n vos delete <vosId|watch-url|dir> [--yes] [--dry-run] [--json]\n move a vos to Trash on vos.so. Nothing is erased: it stays\n restorable until the date the delete prints (vos restore <id>).\n Asks on a terminal; headless it needs --yes. --dry-run names\n what would move and changes nothing. A dir that tracked it is\n unlinked (its vos.json removed). Needs a key with the delete\n scope; no key can delete forever, only the person can, on the\n web\n vos trash [--json]\n what is in Trash on vos.so: what, moved by whom, restorable\n until when\n vos restore <id|watch-url> [...] [--json]\n bring those back from Trash, as they were\n vos trash restore --since <30m|1h|2d|ISO> [--by <key name>] [--json]\n undo everything this key (or the named one) moved to Trash\n since then\n vos pull [dir|take] [--vos <id>] [--since versionId] [--check] [--media] [--json]\n what changed on vos.so since your base; syncs config.json (backup\n kept) or the take's doc.json. ALWAYS pull before editing pushed work.\n --media also downloads the recording (+ mic/cam sidecars) beside\n the doc and re-anchors it, so digest/frames/render run locally\n auth: --key, VOS_API_KEY, or ~/.config/vos/credentials; keys can\n never publish (visibility stays private; humans publish on vos.so)\n vos folder list\n vos folder create <name> [--parent <folderId|slug>] [--desc <text>]\n vos folder move <vosId|assetId|watch-url>... --to <folderId|slug|none>\n organize the shelf: folders nest (≤5 deep, slugs stable); move\n takes vos ids AND asset ids (recipes, uploads) and files them\n into the folder (--to none unfiles). Add-only by design:\n folder rename/delete/reorder stay human gestures on vos.so\n vos asset rename <assetId> <newname.ext>\n rename one of your assets (recipes included) in place — bytes\n and fileUrl untouched; the extension must keep matching the\n asset's kind (a recipe stays .md)\n vos asset push <file...> [--folder <folderId|slug>]\n add files to your library: models, pictures and SVGs, fonts,\n HDR maps, sound, video, captions and recipes. The platform\n reads each file and answers what it is and the name it is\n stored under; the same bytes twice are the same file. Prints\n the url a doc.json key takes. GET /api/limits lists the\n kinds, their size caps and their daily rates\n vos recipe push <file.md> --folder <folderId|slug>\n vos recipe push <file.md> --asset <assetId>\n put a recipe (a plain .md) on the shelf: --folder creates it\n filed into that folder, --asset replaces one in place (same\n id, the displaced body kept as the prior version). Reading is\n vos folder pull; restore stays a gesture on the recipe page\n\ncreate = record then render in one command: drives the flow, auto-plans effects, and writes the video.\n--strict aborts before rendering on any skipped selector. For the full\nloop (inspect frames, edit doc.json, re-render) use the verbs below.\n\nThe take directory is the unit of work: recording.webm + cursor.json +\nmeta.json + actions.json + doc.json. doc.json is the editable surface —\nzoom spans, trims, speed, cursor/frame styling; edit it (or let an agent),\nthen re-run render. plan preserves manual zoom spans, regenerating only\nsource:'auto' ones. Results on stdout, logs on stderr; --json = NDJSON.\n\nThe re-render loop (re-recording the same script after the product\nchanged): record into the SAME take dir — footage/cursor/meta are\nreplaced, the cut survives as doc.prev.json — then plan --reuse re-times\nit onto the new recording. meta.json carries steps (when each actions\nstep ran); a span may carry anchor {step, at, offset} tying it to a step\nid/index for exact re-timing; unanchored human spans map piecewise\nthrough matched step edges; autos re-plan; overlays/audio keep OUTPUT\ntimes. The done event's reuse block NAMES whatever could not follow —\nfix by exception, never re-cut from scratch. Give steps ids in\nactions.json so anchors survive script edits.\n\nrecord --strict exits 2 when any selector was skipped, the page never\nreached networkidle, or the take hit --max-duration (the done event lists\nskipped[] and capped either way). --max-duration defaults to the hosted\nrecording cap, read live from GET /api/limits (30 min when the origin is\nunreachable): the capture stops there and says so in one line.\nframes captures PNG stills at OUTPUT times (seconds or % of duration);\n--at-zooms adds every zoom span's apex, --at-moments every digest moment —\nthe agent's eyes AND exact-size posters/screenshots (--size WxH). render\n--range a..b --draft spot-checks a doc edit in seconds (half res, low\nbitrate; range in OUTPUT seconds); a --range render keeps its audio.\ndeliver renders the take to a release's destinations in one pass — the\nchannel specs (schema/channel-specs.json, verified sizes for the Chrome\nWeb Store, Product Hunt, X, LinkedIn, OG, GitHub, YouTube) drive stills at\nexact pixels and video cuts, every artifact is VERIFIED against its spec\n(px, bytes, duration; misses land in skipped[] with the reason), and\nkit.json beside the assets is the manifest. Still times come from the\nSTORY: every step's end plus a 0.4 s settle (the response, not the\ntravel), then the zoom apexes, then an even spread; each candidate is\nread once as the real page, blank ones (a wallpaper, an empty canvas) are\ndropped and two of one frame collapse to one, with every drop said in\nskipped[]. --times overrides with seconds, percents or step:<id>[+offset]\n(the id from actions.json); --range cuts every video destination.\nThe LOOK presents the card: card-genre stills with no poster document\nand every video cut sit on a ground (a cream plate, the house gradient, a\ndark plate with a light streak) at ~84% of the width with headroom, a\nsoft ambient shadow plus a tight contact shadow, and a hairline when card\nand ground are both light; a wide frame runs the card off the bottom.\n--look picks a house look (or none for the pre-look crops); with no flag\nthe BRAND.md beside the take (or --brand <file>) decides from its look\nrole or its own ground, and with no brand the house gradient.\nScreenshot-genre stills never take a look.\nA POSTER is a document, never a template: a plain take whose card sits\nwhere the poster wants it (frame.inset), leans (the tilt track), carries\nthe words and the mark as clips (ids stage-title, stage-kicker,\nstage-brand, stage-mark) and ends on a trailing freeze whose start is the\nstill. Card-genre destinations (OG, LinkedIn, X, YouTube thumbnail, the\nCWS tile + marquee, GitHub social preview) render from the poster\ndocument of their aspect CLASS (landscape, square, portrait, tile), found\nbeside the take as poster/<class>/doc.json (poster/doc.json serves every\nclass) or named in LAUNCH.md (poster: <path>, poster-landscape: …), at\nthe document's rest; kit.json records source poster, the class, the file,\nthe vos it tracks, the shot rect and the text boxes read FROM the\ndocument. A class with no document is the take's own frame, said once.\ndeliver renders and verifies; it composes nothing. The composition is\nmade with plan --style <poster>, which copies a poster's layout onto a\ntake (its card placement, its stage clips with the release's words\npatched in from LAUNCH.md's headline and kicker roles or --headline and\n--kicker, its rest lean, its freeze), or by hand in doc.json.\nThe cut's MOTION is the document's too, in ONE vocabulary: every visual\nthing (the card, a text, image or video clip, a prop) carries anim.enter,\nanim.exit and anim.idle; the output lasts until the last clip ends, and\nthe card leaves with its clip (a freeze keeps it under what follows).\nThere is no end-card field and no entrance field: a\nCOMPONENT is a TEMPLATE, a plain take on a shelf whose clips carry stable\nids, laid onto the take at an anchor (LAUNCH.md with: <ref>[@end|@start|\n@step:<id>|@<s>], comma list; --with the same, repeatable; endCard: <ref>\nnames one at the end), its clips stamped with where they came from\n(from). plan proposes on a fresh plan (--motion re-proposes, replacing\nonly its own work): the card's ENTER (tilt-in by default), the templates\nnamed, the END CARD when endCard is on or absent (the official End card\ntemplate on vos.so, laid at the end with the release's words, the mark\nfrom BRAND.md logoUrl and a freeze of the last frame under it, from:\nendcard; offline, the house clips stand in), a CAPTION per\nactions.json step at the step's moment, a music BED from LAUNCH.md's music\nrole (a catalog slug or a mood) and a click sound on every press when the\ntake has no mic. LAUNCH.md's entrance, transitions, endCard, captions, music and clicks\nroles, or the flags, change or switch each off; a deleted proposal stays\ndeleted on a refresh. deliver applies each destination's MECHANICS and\nnothing more: the README loop drops the card's motion, every clip a\ntemplate placed and every sound; a channel that autoplays muted drops the\nbed; the 9:16 cut is a reframe, not a letterbox, and the crop follows\nthe camera. Screenshot-genre\ndestinations (CWS screenshots, the PH gallery) are the real page at that\nmoment, FULL BLEED: no zoom, no tilt, no browser bar, no padding (store\npolicy); --composed keeps the cut's camera and chrome instead. --set\npath=value overrides the doc in memory for every render here (the user's\nsets apply last). Store uploads stay manual: hand the human the kit\ndirectory, then vos validate <kit.json> re-measures every asset from its\nbytes against the channel specs; --picture adds what each asset LOOKS\nlike, read from its pixels: blank (a wallpaper or an empty canvas where\nthe product should be), duplicate (two stills of one frame), subject (the\ncard off the 60 to 92% band, or a crop where a card was asked for),\nseparation (a light card on a light ground with no shadow), halfsize (a\ntile that loses its edges when the store shrinks it), and, where the kit\nrecords its text boxes, sliced, safe and contrast (APCA Lc 60/75); a\nvideo's first and last frames are read through ffmpeg. Every finding\ncarries a code, a severity, a fix hint and a box; an error fails the\nverdict beside the spec problems.\njudge puts the kit beside its REFERENCES: for every still that has a\nreference of its role in the manifest (a template family, a card genre),\ntwo sheets at a common height (the asset left, then right, so order\ncannot bias the call) and the rubric in words, plus judge.json, a slot\nper pair the judge fills (win true, false or null for a tie, with the\nrule numbers). No model runs inside the verb: the skill judges the\nsheets pairwise, both orders, and the verb reports the win rate beside\nthe spec and picture counts. The reference set is the maker's own\nfixture folder with a MANIFEST.json (id, file, role, layout, facts,\nrule per asset).\nbrand writes the product's BRAND.md, witnessed: it reads /design.md when\nthe site publishes one (the convention beside /llms.txt: fonts, logo assets,\nan avoid list), /llms.txt for the name and the claim, then the page itself\nin a browser (the body ground, the surfaces, the h1 and body faces and inks,\nthe accent buttons and links agree on, theme-color, the icons, og:image).\nThe frontmatter carries the roles the poster family binds (bgA/bgB/bgC,\nink, accent, fontDisplay, logoUrl); the prose says where every value came\nfrom and quotes the site's own avoid list. Resolve the brand BEFORE any\nasset is authored; file it with vos recipe push BRAND.md --folder <slug>.\ndigest is how an agent SEES a recording before it cuts: writes digest/ with\ndigest.json (the moments the cursor track says matter — click clusters,\ntyping sessions, scroll runs, dwells, idle gaps, scene changes — each with\nsource+output extents, a normalized focus/rect you can copy into a zoom span,\nper-second motion, and the planners' proposals beside it), one FOOTAGE frame\n+ a crop around the target per moment, and sheet.png (the contact sheet).\nRead digest.json, then the sheet, then crops only where you must decide.\n--full/--crop set the long edge in px (your token budget; the done event\nestimates it). --transcript merges Whisper-shaped segments (SOURCE seconds)\nonto moments as \"said\". --style REPORTS a reference doc's style fields.\nvalidate <take> lints doc.json semantics (span overlap/bounds, normalized\n[0..1] zoom focus coords, export honesty) — schema in schema/doc.schema.json.\nactions from-agent-browser turns the walk an agent made in agent-browser\ninto actions.json, so a feature verified there becomes a take with no\nsecond script. Input: one record per command in agent-browser's own batch\nshape, {command:[…], …result} — a bare --json result does not say what ran,\nso wrap each call (the product-video skill has the one-line function) or\nkeep a batch's output. Refs (@e27) resolve through the last snapshot -i\nbefore them (-u gives links their href); what the recorder cannot follow\n(a shortcut key, a drag, a second open) is named in the output, never\ndropped. Then: vos record --actions actions.json --strict.\nopen serves the take and loads it into the studio (?take=<server>) —\ndoc.json edits arrive intact; a human can drag every zoom span. Keeps\nserving until Ctrl-C. The studio is https://vos.so by default (VOS_ORIGIN\nmoves it; --studio http://localhost:6060 for a dev server).\n\npush/pull — the hosted iteration loop (credentials: --key, VOS_API_KEY, or\n~/.config/vos/credentials via vos login; origin via VOS_ORIGIN, default\nhttps://vos.so). A take push uploads the recording ONCE (content-addressed),\nlowers doc.json, and creates a private vos (first push asks; --yes for\nheadless) or a new version against the base in vos.json — a stale base\nprints the human's typed changelog and exits 1 (run pull, re-apply, push\nagain). A protected conflict means the human touched those nodes in the\nstudio: keep their values, or --override <id> ONLY when the user asked for\nthat exact change. ALWAYS pass --label (what you did, one line) and --note\n(why: the user's ask) — the version history reads as a conversation, and an\nunlabelled push is a turn the human cannot read. pull prints what changed\nsince your base and writes the head back (doc.json for takes, config.json\nfor programs, backup kept). ALWAYS pull before editing pushed work.\n\nrender/frames doc overrides — check any presentation on the product surface\nwithout hand-editing doc.json (the disk file is untouched; the patched doc is\nlint-gated, so a bad override fails like a bad doc.json):\n --set <path=value> patch any doc field, repeatable; value is JSON when it\n parses else a string (e.g. --set tilt[0].rx=8\n --set frame.padding=120 --set frame.browserBar.kind=mac-light)\n --frame <kind> (render) browser frame: macos|mac-dark|windows|windows-dark|minimal|none\n --background <url|slug> background media: a URL (kind inferred), or a backdrop slug from GET /api/backdrops\n (.webm/.mp4 = video @10s loop, image otherwise); \"none\" clears.\n On create/record/plan it is the frame a FRESH take opens on; absent, the set's\n first ready loop (the house backdrop the studio opens on), or a flat ground offline\n`\n\nasync function loadActions(file: string): Promise<ActionsFile> {\n const raw = JSON.parse(await readFile(file, 'utf8')) as unknown\n const errors = validateActions(raw)\n if (errors.length)\n throw new UsageError(`invalid actions file:\\n ${errors.join('\\n ')}`)\n return raw as ActionsFile\n}\n\n/**\n * --max-duration <seconds>: where the capture stops. Defaults to the\n * hosted recording cap so a CLI take is never longer than vos.so will host.\n */\n/**\n * The cap a take records under: `--max-duration` when given; else the\n * hosted cap read live from `GET /api/limits` (the caller's plan when a\n * key resolves); else the built-in number, said in words, because a take\n * longer than the platform's cap is refused at push time.\n */\nasync function maxDuration(\n flags: ParsedArgs['flags'],\n r: { log: (line: string) => void },\n): Promise<number> {\n if (hasFlag(flags, 'max-duration')) {\n const v = numFlag(flags, 'max-duration', defaultMaxDurationSeconds())\n if (!(v > 0)) throw new UsageError('--max-duration expects seconds above 0')\n return v\n }\n const origin = platformOrigin({\n origin: strFlag(flags, 'origin'),\n api: strFlag(flags, 'api'),\n })\n const live = await hostedRecordingCap(\n origin,\n resolveCredential(strFlag(flags, 'key')),\n )\n if (live) return live\n r.log(\n `note: could not read the hosted cap from ${origin}/api/limits; recording up to the built-in ${formatDurationCap(defaultMaxDurationSeconds())}`,\n )\n return defaultMaxDurationSeconds()\n}\n\nfunction strictReason(rec: {\n skipped: unknown[]\n navTimeout: boolean\n capped: boolean\n masks?: { selector: string; hits: number }[]\n}): string {\n const parts = [`${rec.skipped.length} skipped step(s)`]\n if (rec.navTimeout) parts.push('networkidle timeout')\n if (rec.capped) parts.push('stopped at --max-duration')\n const missed = maskMisses(rec)\n if (missed.length)\n parts.push(\n `${missed.length} mask(s) that hid nothing (${missed.join(', ')}): whatever they were for may be showing`,\n )\n return parts.join(' + ')\n}\n\n/** A mask whose selector never reached an element hid nothing. */\nfunction maskMisses(rec: {\n masks?: { selector: string; hits: number }[]\n}): string[] {\n return (rec.masks ?? []).filter((m) => m.hits === 0).map((m) => m.selector)\n}\n\n/** What the frame shows, in words, for the end of a record or a rehearsal. */\nfunction exposureNote(rec: {\n exposures: Parameters<typeof exposureLine>[0][]\n}): string {\n if (!rec.exposures.length) return ''\n return `\\n EXPOSED in the frame (${rec.exposures.length}):\\n${rec.exposures\n .map((e) => ` - ${exposureLine(e)}`)\n .join('\\n')}\\n ${EXPOSURE_ADVICE}`\n}\n\n/**\n * The backdrop a FRESH take opens on: `--background <slug|url|none>`, or\n * absent, the set's house pick from `GET /api/backdrops`. Read once per\n * command; a set out of reach is said in words and the take opens on a\n * flat ground rather than failing.\n */\n/**\n * `--browser-arg=<switch>`, repeatable: extra Chromium switches for the\n * recording browser. Some product surfaces cannot be reached without one\n * (a fake capture device to pass a permission prompt, a loaded extension).\n *\n * Read from `multi`, never from `flags`: a flag bag holds ONE value per name,\n * so a second switch used to overwrite the first, and the pair that grants a\n * fake microphone (`--use-fake-ui-for-media-stream` beside\n * `--use-fake-device-for-media-stream`) reached Chromium as its last half.\n * A switch starts with `--`, so it is written with `=`.\n */\n/**\n * `--header name=value`, repeatable: a request header on every request the\n * recording browser makes. The way past a preview deployment that is\n * protected by a bypass header alone (rung 0 of the session ladder).\n */\nfunction takeHeaders(multi: ParsedArgs['multi']): Record<string, string> {\n try {\n return parseHeaders(multi.header as string[] | undefined)\n } catch (e) {\n throw new UsageError(e instanceof Error ? e.message : String(e))\n }\n}\n\nexport function takeBrowserArgs(multi: ParsedArgs['multi']): string[] {\n // Index access is typed present but is runtime-optional.\n const given = multi['browser-arg'] as string[] | undefined\n return (given ?? []).filter(Boolean)\n}\n\n/**\n * `--storage-state <file>`: a Playwright storage state, so the recorder\n * drives a SIGNED-IN product. Recording a demo of anything behind a login\n * needs it, and a sign-in form cannot always be scripted (an emailed code,\n * an SSO hop, a passkey). Export one from a real browser session.\n */\nfunction takeStorageState(flags: ParsedArgs['flags']): string | undefined {\n const raw = strFlag(flags, 'storage-state')\n if (!raw) return undefined\n const path = resolve(raw)\n if (!existsSync(path))\n throw new UsageError(`--storage-state: no such file: ${path}`)\n return path\n}\n\n/**\n * `--session <name>`: record on a profile the person signed in to\n * (`vos session open`). Mutually exclusive with `--storage-state`: a\n * persistent context cannot take a storage state, and a take has one door.\n */\nfunction takeSessionName(\n flags: ParsedArgs['flags'],\n storageState: string | undefined,\n): string | undefined {\n const name = strFlag(flags, 'session')\n if (!name) return undefined\n const bad = sessionNameVerdict(name)\n if (bad) throw new UsageError(bad)\n if (storageState)\n throw new UsageError(\n '--session and --storage-state are two doors to one take: a persistent profile cannot take a storage state. Pass one',\n )\n if (!existsSync(sessionDir(name)))\n throw new UsageError(\n `no session \"${name}\". Make one: vos session open <url> --name ${name} (a Chrome window opens; sign in and close it)`,\n )\n return name\n}\n\n/** Run `fn` in the named session's persistent context, or with none. */\nasync function inSession<T>(\n name: string | undefined,\n actions: { viewport?: { width: number; height: number } },\n fn: (ctx: import('playwright').BrowserContext | undefined) => Promise<T>,\n): Promise<T> {\n if (!name) return fn(undefined)\n return withSession(name, (ctx) => fn(ctx), {\n headless: true,\n viewport: {\n width: actions.viewport?.width ?? 1280,\n height: actions.viewport?.height ?? 720,\n },\n })\n}\n\nexport async function takeBackdrop(\n flags: ParsedArgs['flags'],\n r: { log: (line: string) => void },\n): Promise<Backdrop | null> {\n const { backdrop, note } = await openingBackdrop(\n strFlag(flags, 'background'),\n platformOrigin({\n origin: strFlag(flags, 'origin'),\n api: strFlag(flags, 'api'),\n }),\n )\n if (note) r.log(`note: ${note}`)\n return backdrop\n}\n\n/** After a verified encode: the screencast JPEGs go, unless `--keep-frames`. */\nasync function releaseFrames(\n paths: TakePaths,\n flags: ParsedArgs['flags'],\n log: (line: string) => void,\n): Promise<void> {\n if (flags['keep-frames'] === true) return\n const freed = await dropScreencastFrames(paths)\n // Said only when it is worth a line: a few kB of frames is not news.\n if (freed >= 1e6)\n log(\n `released ${Math.round(freed / 1e6)} MB of screencast frames (the recording holds them now; --keep-frames keeps them)`,\n )\n}\n\n/**\n * The wall gate, handed to the recorder as `onArrival`. It judges where the\n * first navigation landed and only THEN lets `prepare` touch the take\n * directory: a re-record clears the old footage, and a session that expired\n * since the last take must never cost the recording it failed to replace.\n *\n * A hard wall (a sign-in, an identity provider, a 401/403) is always refused.\n * A soft one (sent elsewhere, no sign-in in sight) is refused under\n * `--strict` and in a rehearsal, and said as a warning otherwise.\n * `--allow-wall` records either, and the take's meta says so.\n */\nfunction wallGate(\n flags: ParsedArgs['flags'],\n r: Reporter,\n opts: { strict: boolean; prepare?: () => Promise<void> },\n): (arrival: Arrival) => Promise<WallVerdict | null> {\n const allow = flags['allow-wall'] === true\n return async (arrival) => {\n const verdict = wallVerdict(arrival)\n if (verdict && !allow && (verdict.level === 'hard' || opts.strict)) {\n r.event({ event: 'wall', ...verdict, refused: true })\n throw new WallError(verdict)\n }\n if (verdict) {\n r.event({ event: 'wall', ...verdict, refused: false })\n r.log(\n allow\n ? ` note: recording past the wall (--allow-wall): landed on ${verdict.landed}`\n : ` WARNING: ${verdict.message}`,\n )\n }\n await opts.prepare?.()\n return verdict\n }\n}\n\nasync function cmdRecord(argv: string[]): Promise<number> {\n const { positionals, flags, multi } = parseArgs(\n argv,\n BOOLEAN_FLAGS,\n MULTI_FLAGS,\n )\n const actionsPath = strFlag(flags, 'actions') ?? positionals[0]\n if (!actionsPath)\n throw new UsageError(\n 'vos record --actions actions.json [--url <url>] [--out take]',\n )\n const r = createReporter(flags.json === true)\n const actions = await loadActions(actionsPath)\n const url = strFlag(flags, 'url') ?? actions.url\n if (!url)\n throw new UsageError('no URL — set \"url\" in the actions file or pass --url')\n const outDir = resolve(strFlag(flags, 'out') ?? 'take')\n const storageState = takeStorageState(flags)\n const sessionName = takeSessionName(flags, storageState)\n const browserArgs = takeBrowserArgs(multi)\n const headers = takeHeaders(multi)\n\n // ON THE FLEET: the script goes up, vos.so records, plans and lands the\n // take, and it comes home with `vos fetch --media`. No browser is opened\n // here; a session never travels; a rehearsal stays a local act.\n if (flags.hosted === true) {\n if (flags['dry-run'] === true)\n throw new UsageError(\n '--dry-run rehearses on this machine; drop --hosted to rehearse, or --dry-run to record on vos.so',\n )\n if (storageState || sessionName)\n throw new UsageError(\n 'a session never reaches vos.so: --hosted takes no --session or --storage-state. Put the sign-in in the setup steps with { \"env\": \"NAME\" }, or record here with vos record.',\n )\n const origin = platformOrigin({\n origin: strFlag(flags, 'origin'),\n api: strFlag(flags, 'api'),\n })\n const key = resolveCredential(strFlag(flags, 'key'))\n if (!key)\n throw new UsageError(\n 'recording on vos.so needs a credential: vos login, or VOS_API_KEY (mint a key at https://vos.so/app/api)',\n )\n const { env, missing } = hostedEnv(actions, process.env)\n if (missing.length)\n throw new UsageError(\n `the setup reads ${missing.map((n) => `{ \"env\": \"${n}\" }`).join(', ')} and this shell has no ${missing.length === 1 ? 'value for it' : 'values for them'}; export ${missing.join(', ')} and run again (the value rides the job, and is never stored)`,\n )\n r.log('recording on vos.so…')\n r.event({ event: 'phase', phase: 'record' })\n const started = Date.now()\n const outcome = await recordHosted({\n origin,\n key,\n url,\n actions: { ...actions, url },\n headers,\n title: strFlag(flags, 'title'),\n folderId: strFlag(flags, 'folder'),\n env,\n log: r.log,\n })\n if (!outcome.ok) {\n // The vos was made before the take, so a refusal leaves an empty one\n // on the shelf; the CLI takes it back down (its job row goes with it,\n // which is why this runs only once the refusal has been read).\n if (outcome.vosId) {\n const gone = await apiJson(origin, `/api/vos/${outcome.vosId}`, {\n method: 'DELETE',\n key,\n })\n if (gone.status === 200)\n r.log('the empty vos it would have landed on was removed')\n }\n r.done(\n {\n hosted: true,\n ok: false,\n wall: outcome.wall,\n error: outcome.error,\n vosId: outcome.vosId,\n jobId: outcome.jobId,\n },\n `${outcome.wall ? 'REFUSED' : 'FAILED'} on vos.so: ${outcome.error}`,\n )\n return outcome.wall ? EXIT_WALL : EXIT_ERROR\n }\n r.event({ event: 'phase', phase: 'fetch' })\n r.log(`landed as ${outcome.studio}; fetching the take into ${outDir}…`)\n const fetched = await cmdFetch([\n outcome.vosId,\n '--out',\n outDir,\n '--media',\n ...(strFlag(flags, 'origin')\n ? ['--origin', strFlag(flags, 'origin')!]\n : []),\n ...(strFlag(flags, 'key') ? ['--key', strFlag(flags, 'key')!] : []),\n ...(flags.json === true ? ['--json'] : []),\n ])\n if (fetched !== EXIT_OK) return fetched\n const t = outcome.job.telemetry ?? {}\n r.done(\n {\n hosted: true,\n ok: true,\n vosId: outcome.vosId,\n jobId: outcome.jobId,\n out: outDir,\n seconds: +((Date.now() - started) / 1000).toFixed(1),\n telemetry: t,\n },\n `Recorded on vos.so in ${((Date.now() - started) / 1000).toFixed(1)}s: ${outcome.studio}\\n ${outDir}/ holds doc.json, the recording and vos.json${typeof t.durationMs === 'number' ? ` (${(t.durationMs / 1000).toFixed(1)}s of footage)` : ''}${Array.isArray(t.dead) && t.dead.length ? `\\n DEAD TIME: ${t.dead.length} stretch(es) under a parked cursor; give those steps their ms` : ''}${Array.isArray(t.exposures) && t.exposures.length ? `\\n EXPOSURES: ${t.exposures.length} sensitive-looking text(s) in frame; mask them in actions.json` : ''}\\n Next: vos digest ${outDir} — look before you cut; edit doc.json; vos push ${outDir}`,\n )\n return EXIT_OK\n }\n const backdrop = await takeBackdrop(flags, r)\n const maxDurationSeconds = await maxDuration(flags, r)\n\n // A REHEARSAL: run the script against the real page and say which\n // selectors resolve, before a real-time take and its encode are spent\n // finding out. Branches HERE, before the take directory is touched: a\n // re-record moves doc.json aside, and a rehearsal must leave the take\n // exactly as it found it.\n if (flags['dry-run'] === true) {\n // The same command line with --dry-run added must rehearse cleanly, so\n // the take's own flags are read here: a rehearsal is ALWAYS strict (any\n // miss exits 2) and has no frames to keep, and neither is \"ignored\".\n void flags.strict\n void flags['keep-frames']\n const browser = await launchBrowser(browserArgs)\n try {\n r.log('rehearsing (nothing is captured or written)…')\n r.event({ event: 'phase', phase: 'rehearse' })\n const started = Date.now()\n const rec = await inSession(sessionName, actions, (context) =>\n recordTake(browser, url, actions, takePaths(outDir), r.log, {\n storageState,\n headers,\n context,\n dryRun: true,\n // A rehearsal is always strict, and it touches no directory.\n onArrival: wallGate(flags, r, { strict: true }),\n }),\n )\n const steps = rec.meta.steps ?? []\n const lines = steps.map((s) => {\n const rect = s.rect\n ? ` rect ${s.rect.x},${s.rect.y} ${s.rect.w}×${s.rect.h}`\n : ''\n const what = s.selector ? ` ${s.selector}` : ''\n return ` ${s.skipped ? '✗' : '✓'} #${s.step}${s.id ? ` (${s.id})` : ''} ${s.do}${what}${s.skipped ? ' NOT FOUND' : rect}${s.navigated ? ' → navigated' : ''}`\n })\n const failed =\n rec.skipped.length > 0 || rec.navTimeout || maskMisses(rec).length > 0\n // The next command is THIS command minus --dry-run. A hint that\n // dropped --storage-state sent a signed-in rehearsal on to record\n // the sign-in page.\n const carried = [\n ...(strFlag(flags, 'storage-state')\n ? [`--storage-state ${strFlag(flags, 'storage-state')}`]\n : []),\n ...browserArgs.map((a) => `--browser-arg=${a}`),\n ...Object.entries(headers).map(([k, v]) => `--header ${k}=${v}`),\n ...(sessionName ? [`--session ${sessionName}`] : []),\n ...(flags['allow-wall'] === true ? ['--allow-wall'] : []),\n ].join(' ')\n const nextOut = strFlag(flags, 'out') ?? 'take'\n r.done(\n {\n dryRun: true,\n ok: !failed,\n seconds: +((Date.now() - started) / 1000).toFixed(1),\n steps,\n skipped: rec.skipped,\n navTimeout: rec.navTimeout,\n exposures: rec.exposures,\n masks: rec.masks,\n },\n `${failed ? 'REHEARSAL FAILED' : 'Rehearsal passed'}: ${steps.length - rec.skipped.length}/${steps.length} steps resolved in ${((Date.now() - started) / 1000).toFixed(1)}s${rec.navTimeout ? ' (the first load never reached networkidle)' : ''}\\n${lines.join('\\n')}\\n ${maskMisses(rec).length ? `MASK hid nothing: ${maskMisses(rec).join(', ')} (the selector reached no element). ` : ''}${failed ? 'Fix the script, rehearse again, then record.' : `Rects are capture px (the step rects a pin or a callout reads). Next: vos record --actions ${actionsPath} --out ${nextOut}${carried ? ` ${carried}` : ''} --strict`}${exposureNote(rec)}`,\n )\n return failed ? EXIT_USAGE : EXIT_OK\n } finally {\n await browser.close()\n }\n }\n\n // Run by the wall gate, once the recorder has landed where it was asked.\n // A re-record replaces the FOOTAGE, never the cut. The previous doc.json\n // survives as doc.prev.json (the reuse base), actions.json and vos.json\n // stay put, and derived artifacts of the old footage clear.\n const paths = takePaths(outDir)\n const prepare = async () => {\n if (existsSync(join(outDir, 'meta.json'))) {\n const { prevDoc, kept } = await prepareReRecord(outDir)\n r.log(\n `note: re-recording ${outDir} — kept ${kept.length ? kept.join(', ') : 'nothing'}` +\n (prevDoc\n ? '; apply the previous cut to the new footage with: vos plan ' +\n outDir +\n ' --reuse'\n : ''),\n )\n }\n await mkdir(outDir, { recursive: true })\n await ensureTakeDir(outDir)\n }\n\n const browser = await launchBrowser(browserArgs)\n try {\n r.log('recording…')\n r.event({ event: 'phase', phase: 'record' })\n const rec = await inSession(sessionName, actions, (context) =>\n recordTake(browser, url, actions, paths, r.log, {\n maxDurationSeconds: maxDurationSeconds,\n storageState: storageState,\n headers,\n context,\n onArrival: wallGate(flags, r, {\n strict: flags.strict === true,\n prepare,\n }),\n }),\n )\n r.event({ event: 'phase', phase: 'encode' })\n r.log('encoding…')\n const enc = await encodeRecording(browser, outDir, (p) =>\n r.event({ event: 'progress', phase: 'encode', fraction: p }),\n )\n await releaseFrames(paths, flags, r.log)\n r.event({ event: 'phase', phase: 'plan' })\n const plan = await planTake(outDir, { backdrop })\n const clicks = rec.events.filter((e) => e.type === 'down').length\n const strict = flags.strict === true\n const strictFail =\n strict &&\n (rec.skipped.length > 0 ||\n rec.navTimeout ||\n rec.capped ||\n maskMisses(rec).length > 0)\n const skippedNote = rec.skipped.length\n ? `\\n SKIPPED ${rec.skipped.length} step(s): ${rec.skipped.map((s) => `#${s.step} ${s.do} ${s.selector}`).join(', ')}`\n : ''\n r.done(\n {\n take: outDir,\n durationMs: rec.meta.durationMs,\n frames: rec.frames.length,\n events: rec.events.length,\n clicks,\n recordingBytes: enc.bytes,\n zoomSpans: plan.doc.zoom.length,\n skipped: rec.skipped,\n navTimeout: rec.navTimeout,\n freezes: rec.freezes,\n freezePct: rec.freezePct,\n dead: rec.dead,\n capped: rec.capped,\n pace: rec.pace,\n ...(rec.wall ? { wall: rec.wall } : {}),\n exposures: rec.exposures,\n ...(rec.masks.length ? { masks: rec.masks } : {}),\n ...(strictFail ? { strictFailed: true } : {}),\n },\n strictFail\n ? `STRICT: take recorded but incomplete — ${strictReason(rec)}; fix the flow and re-record.${skippedNote}${exposureNote(rec)}`\n : `Take ready: ${outDir}\\n ${(rec.meta.durationMs / 1000).toFixed(1)}s · ${rec.frames.length} frames · ${rec.events.length} cursor events · ${clicks} clicks · ${plan.doc.zoom.length} zoom spans planned · ${rec.freezePct}% frozen · ${rec.dead.pct}% dead${deadWarns(rec.dead) ? ' ⚠ ' + deadLine(rec.dead) : ''}${skippedNote}\\n Next: edit ${join(outDir, 'doc.json')} (optional), then: vos render ${outDir}${exposureNote(rec)}`,\n )\n return strictFail ? EXIT_USAGE : EXIT_OK\n } finally {\n await browser.close()\n }\n}\n\n/**\n * The one-shot verb of the `vos <product> create` namespace: record the flow,\n * auto-plan effects, render the video — one command, one browser session.\n * The take dir still lands on disk, so the full loop (frames → doc.json edit\n * → re-render) stays available afterwards. --strict aborts BEFORE rendering\n * when the recording is incomplete (skipped selector / networkidle timeout).\n */\nasync function cmdCreate(argv: string[]): Promise<number> {\n const { positionals, flags, multi } = parseArgs(\n argv,\n BOOLEAN_FLAGS,\n MULTI_FLAGS,\n )\n const actionsPath = strFlag(flags, 'actions')\n if (!actionsPath) {\n throw new UsageError(\n 'vos create --actions actions.json [--url <url>] [--out take] [out.webm]',\n )\n }\n const r = createReporter(flags.json === true)\n const actions = await loadActions(actionsPath)\n const url = strFlag(flags, 'url') ?? actions.url\n if (!url)\n throw new UsageError('no URL — set \"url\" in the actions file or pass --url')\n const outDir = resolve(strFlag(flags, 'out') ?? 'take')\n const format = videoFormat(strFlag(flags, 'format'), positionals[0])\n const out = positionals[0] ?? join(outDir, `out.${format}`)\n const parallel = numFlag(flags, 'parallel', 1)\n if (!Number.isInteger(parallel) || parallel < 1 || parallel > 16) {\n throw new UsageError('--parallel expects an integer between 1 and 16')\n }\n const backdrop = await takeBackdrop(flags, r)\n const maxDurationSeconds = await maxDuration(flags, r)\n const storageState = takeStorageState(flags)\n const sessionName = takeSessionName(flags, storageState)\n const browserArgs = takeBrowserArgs(multi)\n const headers = takeHeaders(multi)\n\n // Run by the wall gate, once the recorder has landed where it was asked.\n // A re-record replaces the FOOTAGE, never the cut. The previous doc.json\n // survives as doc.prev.json (the reuse base), actions.json and vos.json\n // stay put, and derived artifacts of the old footage clear.\n const paths = takePaths(outDir)\n const prepare = async () => {\n if (existsSync(join(outDir, 'meta.json'))) {\n const { prevDoc, kept } = await prepareReRecord(outDir)\n r.log(\n `note: re-recording ${outDir} — kept ${kept.length ? kept.join(', ') : 'nothing'}` +\n (prevDoc\n ? '; apply the previous cut to the new footage with: vos plan ' +\n outDir +\n ' --reuse'\n : ''),\n )\n }\n await mkdir(outDir, { recursive: true })\n await ensureTakeDir(outDir)\n }\n\n const browser = await launchBrowser(browserArgs)\n try {\n r.log('recording…')\n r.event({ event: 'phase', phase: 'record' })\n const rec = await inSession(sessionName, actions, (context) =>\n recordTake(browser, url, actions, paths, r.log, {\n maxDurationSeconds: maxDurationSeconds,\n storageState: storageState,\n headers,\n context,\n onArrival: wallGate(flags, r, {\n strict: flags.strict === true,\n prepare,\n }),\n }),\n )\n r.event({ event: 'phase', phase: 'encode' })\n r.log('encoding…')\n await encodeRecording(browser, outDir, (p) =>\n r.event({ event: 'progress', phase: 'encode', fraction: p }),\n )\n await releaseFrames(paths, flags, r.log)\n r.event({ event: 'phase', phase: 'plan' })\n await planTake(outDir, { backdrop })\n\n if (\n flags.strict === true &&\n (rec.skipped.length > 0 ||\n rec.navTimeout ||\n rec.capped ||\n maskMisses(rec).length > 0)\n ) {\n r.done(\n {\n take: outDir,\n skipped: rec.skipped,\n navTimeout: rec.navTimeout,\n capped: rec.capped,\n strictFailed: true,\n rendered: false,\n },\n `STRICT: take recorded but incomplete — ${strictReason(rec)}; NOT rendering. Fix the flow and re-run, or render the partial take with: vos render ${outDir}`,\n )\n return EXIT_USAGE\n }\n\n const result = await renderTake(browser, outDir, out, {\n width: hasFlag(flags, 'width') ? numFlag(flags, 'width', 0) : undefined,\n height: hasFlag(flags, 'height')\n ? numFlag(flags, 'height', 0)\n : undefined,\n fps: hasFlag(flags, 'fps') ? numFlag(flags, 'fps', 30) : undefined,\n format,\n parallel,\n draft: flags.draft === true,\n overrides: {\n set: multi.set,\n frame: strFlag(flags, 'frame'),\n background: strFlag(flags, 'background'),\n origin: platformOrigin({\n origin: strFlag(flags, 'origin'),\n api: strFlag(flags, 'api'),\n }),\n },\n onPhase: (phase) => {\n r.log(`${phase}…`)\n r.event({ event: 'phase', phase })\n },\n onProgress: (p) =>\n r.event({ event: 'progress', phase: 'render', fraction: p }),\n })\n r.done(\n {\n take: outDir,\n ...result,\n skipped: rec.skipped,\n navTimeout: rec.navTimeout,\n freezes: rec.freezes,\n freezePct: rec.freezePct,\n dead: rec.dead,\n exposures: rec.exposures,\n ...(rec.masks.length ? { masks: rec.masks } : {}),\n ...(flags.draft === true ? { draft: true } : {}),\n },\n `Created ${result.out} (${(result.bytes / 1024).toFixed(0)} KB, ${result.width}x${result.height}@${result.fps}, ${result.duration.toFixed(1)}s, ${result.zoomSpans} zoom spans, ${result.clicks} click effects${result.audio ? ', audio' : ''}${flags.draft === true ? ', DRAFT' : ''})\\n take: ${outDir} — inspect with: vos frames ${outDir} --at-zooms; edit doc.json and re-render with: vos render ${outDir}${exposureNote(rec)}`,\n )\n return EXIT_OK\n } finally {\n await browser.close()\n }\n}\n\nasync function cmdPlan(argv: string[]): Promise<number> {\n const { positionals, flags, multi } = parseArgs(\n argv,\n BOOLEAN_FLAGS,\n new Set(['with']),\n )\n const dir = positionals[0]\n if (!dir)\n throw new UsageError(\n 'vos plan <take> [--fresh] [--reuse [--from <doc.json>]] [--style <doc.json|vosId>] [--with <doc.json|vosId>[@end|@start|@step:<id>|@<seconds>]]... [--motion] [--headline \"…\"] [--launch LAUNCH.md] [--brand BRAND.md]',\n )\n const r = createReporter(flags.json === true)\n if (flags.fresh === true) {\n await rm(join(dir, 'doc.json'), { force: true })\n r.log('note: --fresh discarded the existing doc.json')\n }\n // The re-render loop: --reuse applies a previous cut of the same\n // script to this take's new footage. Default source is the doc a\n // re-record preserved (doc.prev.json); --from names another.\n let reuse: { from: string; doc: ProjectDoc } | undefined\n if (flags.reuse === true) {\n const from = resolve(strFlag(flags, 'from') ?? join(dir, PREV_DOC_NAME))\n if (!existsSync(from)) {\n throw new UsageError(\n `--reuse: ${from} does not exist — a re-record into this take writes doc.prev.json, or pass --from <doc.json>`,\n )\n }\n reuse = {\n from,\n doc: JSON.parse(await readFile(from, 'utf8')) as ProjectDoc,\n }\n }\n const style = await resolveStyleRef(flags)\n // A refresh keeps the doc's own frame; only a FRESH doc opens on the\n // house backdrop, so the set is read only when there is no doc.json.\n const hasDoc = existsSync(join(dir, 'doc.json'))\n const backdrop = hasDoc ? null : await takeBackdrop(flags, r)\n // The release's words and roles (LAUNCH.md and BRAND.md beside the take,\n // flags over them): the words patch a layout's stage clips and name the\n // end card; the roles decide the motion proposals; the brand's mark is\n // fetched into the take's brand/ folder for the layout and the end card.\n const release = await releaseInputs(dir, flags, r, multi.with ?? [])\n const motionWanted = !hasDoc || flags.motion === true || flags.fresh === true\n // The frame that stands for the take: --still, else LAUNCH.md's still:.\n const stillRaw = strFlag(flags, 'still') ?? release.launchRoles.still\n const still = stillRaw === undefined ? null : Number(stillRaw)\n if (still !== null && !(Number.isFinite(still) && still >= 0))\n throw new UsageError(\n `--still expects output seconds ≥ 0, got \"${stillRaw}\"`,\n )\n const s = await planTake(dir, {\n ...(style ? { style } : {}),\n ...(reuse ? { reuse } : {}),\n backdrop,\n words: release.words,\n mark: release.mark,\n ...(still !== null ? { still } : {}),\n ...(motionWanted\n ? {\n motion: {\n words: release.words,\n launch: release.launchRoles,\n ink: release.ink,\n mark: release.mark,\n captions: release.captions,\n catalog: release.catalog,\n templates: release.templates,\n again: flags.motion === true,\n },\n }\n : {}),\n })\n const layoutLines = s.layout\n ? `\\n layout from ${s.styleFrom}: ${[\n s.layout.clips.length ? `${s.layout.clips.length} stage clip(s)` : '',\n s.layout.lean ? 'the rest lean' : '',\n s.layout.freeze ? 'the freeze' : '',\n ]\n .filter(Boolean)\n .join(', ')}` +\n (s.layout.notes.length ? `\\n ${s.layout.notes.join('\\n ')}` : '')\n : ''\n const motionLines = s.motion\n ? (s.motion.notes.length\n ? `\\n proposed: ${s.motion.notes.join(', ')}`\n : '') +\n (s.motion.skipped.length\n ? `\\n not proposed: ${s.motion.skipped.join('; ')}`\n : '')\n : ''\n const reuseLines = s.reuse\n ? `\\n reused ${s.reuse.from}: ${s.reuse.anchored} anchored + ${s.reuse.mapped} mapped span(s)` +\n (s.reuse.flagged.length\n ? `\\n flagged:\\n ${s.reuse.flagged.join('\\n ')}`\n : '')\n : ''\n r.done(\n {\n take: resolve(dir),\n fresh: s.fresh,\n cursorKept: s.cursorKept,\n zoomAuto: s.zoomAuto,\n zoomManual: s.zoomManual,\n duration: s.doc.source.meta.durationMs / 1000,\n ...(s.backdrop !== undefined ? { backdrop: s.backdrop } : {}),\n ...(s.styleFrom\n ? { styleFrom: s.styleFrom, styleFields: s.styleFields }\n : {}),\n ...(s.layout ? { layout: s.layout } : {}),\n ...(s.motion ? { motion: s.motion } : {}),\n ...(s.reuse ? { reuse: s.reuse } : {}),\n },\n `${s.reuse ? 'Reused' : s.fresh ? 'Planned' : 'Refreshed'} ${join(dir, 'doc.json')}: ${s.zoomAuto} auto + ${s.zoomManual} manual zoom spans${s.cursorKept ? '' : ' (cursor track dropped)'}${layoutLines}${motionLines}${reuseLines}`,\n )\n return EXIT_OK\n}\n\n/**\n * The release's inputs beside a take, for `plan`: the words (LAUNCH.md's\n * headline and kicker roles, BRAND.md's wordmark; flags override), the\n * motion roles (LAUNCH.md's music, entrance, transitions, endCard, captions, clicks;\n * flags override), the end card's ink from the brand's look, the brand's\n * mark fetched into `<take>/brand/`, the step captions from actions.json,\n * and the music catalog when a bed is asked for (one network read, only\n * then).\n */\nasync function releaseInputs(\n dir: string,\n flags: ParsedArgs['flags'],\n r: ReturnType<typeof createReporter>,\n withRefs: string[] = [],\n): Promise<{\n words: {\n headline: string | null\n kicker: string | null\n brand: string | null\n release: string | null\n }\n launchRoles: Record<string, string>\n ink: string | null\n mark: { key: string; aspect: number } | null\n captions: { step: number; id?: string; caption: string }[]\n catalog: Awaited<ReturnType<typeof fetchMusicCatalog>> | null\n templates: MotionTemplate[]\n}> {\n let lookPick: Awaited<ReturnType<typeof resolveLook>>\n try {\n lookPick = await resolveLook(dir, {\n look: strFlag(flags, 'look'),\n brand: strFlag(flags, 'brand'),\n })\n } catch (e) {\n throw new UsageError(e instanceof Error ? e.message : String(e))\n }\n const launch = await readLaunchBesideTake(dir, strFlag(flags, 'launch'))\n // A literal \\n in a frontmatter value or a flag is a line break: a headline\n // is written over its lines on purpose.\n const lines = (v: string | null | undefined) =>\n v === null || v === undefined ? null : v.replace(/\\\\n/g, '\\n')\n const words = {\n headline: lines(strFlag(flags, 'headline') ?? launch?.roles.headline),\n kicker: lines(strFlag(flags, 'kicker') ?? launch?.roles.kicker),\n brand: strFlag(flags, 'brand-name') ?? lookPick.roles?.wordmark ?? null,\n release: strFlag(flags, 'release') ?? null,\n }\n if (launch) r.log(`words: ${launch.file}`)\n const launchRoles: Record<string, string> = { ...(launch?.roles ?? {}) }\n for (const [flag, role] of [\n ['music', 'music'],\n ['entrance', 'entrance'],\n ['transitions', 'transitions'],\n ['end-card', 'endCard'],\n ['captions', 'captions'],\n ['clicks', 'clicks'],\n ] as const) {\n const v = strFlag(flags, flag)\n if (v !== undefined) launchRoles[role] = v\n }\n // The brand's mark: BRAND.md's logoUrl on a light ground, its\n // logoOnDarkUrl on a dark one; a dark ground with no on-dark mark keeps\n // the wordmark in words rather than an invisible ink mark.\n const marks = await fetchBrandMarks(dir, lookPick.roles)\n for (const n of marks.notes) r.log(`note: ${n}`)\n const mark = lookPick.look?.kind === 'dark' ? marks.dark : marks.light\n if (mark) r.log(`brand mark: ${mark.key} (${mark.aspect.toFixed(2)}:1)`)\n const off = (v: string | undefined) =>\n v !== undefined && /^(none|off|no|false)$/i.test(v)\n let catalog: Awaited<ReturnType<typeof fetchMusicCatalog>> | null = null\n if (launchRoles.music && !off(launchRoles.music)) {\n try {\n catalog = await fetchMusicCatalog(\n platformOrigin({\n origin: strFlag(flags, 'origin'),\n api: strFlag(flags, 'api'),\n }),\n )\n } catch (e) {\n r.log(\n `music catalog: ${e instanceof Error ? e.message : String(e)} — no bed`,\n )\n }\n }\n const take = await loadTake(dir)\n const captions = (take.actions?.steps ?? []).flatMap((st, i) => {\n const step = st as { id?: string; caption?: string }\n return typeof step.caption === 'string' && step.caption.trim()\n ? [{ step: i, id: step.id, caption: step.caption.trim() }]\n : []\n })\n // The templates: `--with <ref>[@anchor]` (repeatable), LAUNCH.md's\n // `with:` role (a comma list of the same), and an `endCard:` role that\n // names a document instead of on/none (anchored at the end). A ref is a\n // doc.json, a take dir, or a vos id read with the key ladder.\n const refs: { ref: string; at: MotionAnchor }[] = []\n const parseRef = (raw: string, fallback: MotionAnchor) => {\n const m = /^(.*?)(?:@(end|start|step:[^@\\s]+|\\d+(?:\\.\\d+)?))?$/.exec(\n raw.trim(),\n )\n const ref = m?.[1]?.trim() ?? raw.trim()\n const anchor = m?.[2]\n const at: MotionAnchor = !anchor\n ? fallback\n : anchor === 'end' || anchor === 'start'\n ? anchor\n : anchor.startsWith('step:')\n ? { step: anchor.slice(5) }\n : Number(anchor)\n if (ref) refs.push({ ref, at })\n }\n for (const raw of withRefs) parseRef(raw, 'end')\n for (const raw of (launchRoles.with ?? '').split(','))\n if (raw.trim()) parseRef(raw, 'end')\n const endCardRole = launchRoles.endCard\n if (\n endCardRole &&\n !/^(none|off|no|false|on|yes|true)$/i.test(endCardRole.trim())\n )\n parseRef(endCardRole, 'end')\n const templates: MotionTemplate[] = []\n for (const { ref, at } of refs) {\n const found = await resolveDocRef(ref, flags, '--with')\n templates.push({ from: found.from, doc: found.doc, at })\n r.log(`template: ${found.from}`)\n }\n // The end card the recipe leaves on (or unsaid) is the OFFICIAL one on\n // vos.so, laid at the end and stamped `from: endcard` so a loop drops it\n // and a re-plan replaces it; offline, `plan` falls back to the house\n // clips. A recipe that names its own end card took the branch above.\n if (!endCardRole || /^(on|yes|true)$/i.test(endCardRole.trim())) {\n const origin = platformOrigin({\n origin: strFlag(flags, 'origin'),\n api: strFlag(flags, 'api'),\n })\n const official = await officialTemplate(origin, OFFICIAL_END_CARD_TITLE)\n if (official) {\n try {\n const found = await resolveDocRef(official.id, flags, 'endCard')\n templates.push({ from: END_CARD_FROM, doc: found.doc, at: 'end' })\n r.log(`template: ${found.from} (the official end card)`)\n } catch {\n r.log(\n 'end card: the official template is unreadable here; the house clips stand in',\n )\n }\n }\n }\n return {\n words,\n launchRoles,\n ink: endCardInk(lookPick.look, lookPick.roles),\n mark,\n captions,\n catalog,\n templates,\n }\n}\n\nasync function cmdRender(argv: string[]): Promise<number> {\n const { positionals, flags, multi } = parseArgs(\n argv,\n BOOLEAN_FLAGS,\n MULTI_FLAGS,\n )\n const dir = positionals[0]\n if (!dir)\n throw new UsageError(\n 'vos render <take> [out] [--width] [--height] [--fps] [--format] [--parallel]',\n )\n const r = createReporter(flags.json === true)\n const format = videoFormat(strFlag(flags, 'format'), positionals[1])\n const out = positionals[1] ?? join(dir, `out.${format}`)\n const parallel = numFlag(flags, 'parallel', 1)\n if (!Number.isInteger(parallel) || parallel < 1 || parallel > 16) {\n throw new UsageError('--parallel expects an integer between 1 and 16')\n }\n let range: [number, number] | undefined\n const rangeRaw = strFlag(flags, 'range')\n if (rangeRaw !== undefined) {\n const m = /^(\\d+(?:\\.\\d+)?)\\.\\.(\\d+(?:\\.\\d+)?)$/.exec(rangeRaw)\n if (!m)\n throw new UsageError(\n '--range expects a..b in OUTPUT seconds (e.g. --range 4..8)',\n )\n range = [Number(m[1]), Number(m[2])]\n if (range[1] <= range[0])\n throw new UsageError('--range end must be > start')\n }\n\n const browser = await launchBrowser()\n try {\n const result = await renderTake(browser, dir, out, {\n width: hasFlag(flags, 'width') ? numFlag(flags, 'width', 0) : undefined,\n height: hasFlag(flags, 'height')\n ? numFlag(flags, 'height', 0)\n : undefined,\n fps: hasFlag(flags, 'fps') ? numFlag(flags, 'fps', 30) : undefined,\n format,\n parallel,\n range,\n draft: flags.draft === true,\n overrides: {\n set: multi.set,\n frame: strFlag(flags, 'frame'),\n background: strFlag(flags, 'background'),\n origin: platformOrigin({\n origin: strFlag(flags, 'origin'),\n api: strFlag(flags, 'api'),\n }),\n },\n onPhase: (phase) => {\n r.log(`${phase}…`)\n r.event({ event: 'phase', phase })\n },\n onProgress: (p) =>\n r.event({ event: 'progress', phase: 'render', fraction: p }),\n })\n r.done(\n {\n ...result,\n ...(range ? { range } : {}),\n ...(flags.draft === true ? { draft: true } : {}),\n },\n `Wrote ${result.out} (${(result.bytes / 1024).toFixed(0)} KB, ${result.width}x${result.height}@${result.fps}, ${result.duration.toFixed(1)}s, ${result.zoomSpans} zoom spans, ${result.clicks} click effects${result.audio ? ', audio' : ''}${result.chunks > 1 ? `, ${result.chunks} parallel chunks` : ''}${range ? `, range ${range[0]}..${range[1]}s` : ''}${flags.draft === true ? ', DRAFT' : ''})`,\n )\n return EXIT_OK\n } finally {\n await browser.close()\n }\n}\n\nasync function cmdFrames(argv: string[]): Promise<number> {\n const { positionals, flags, multi } = parseArgs(\n argv,\n BOOLEAN_FLAGS,\n MULTI_FLAGS,\n )\n const dir = positionals[0]\n if (!dir)\n throw new UsageError(\n 'vos frames <take> [--times 0,50%,100%] [--frame <t>] [--at-zooms] [--size WxH] [--out dir]',\n )\n const r = createReporter(flags.json === true)\n\n const take = await loadTake(dir)\n if (!take.doc) throw new UsageError(`${dir} has no doc.json — run plan first`)\n\n let size: { width: number; height: number } | undefined\n const sizeRaw = strFlag(flags, 'size')\n if (sizeRaw !== undefined) {\n const m = /^(\\d+)x(\\d+)$/.exec(sizeRaw)\n if (!m) throw new UsageError('--size expects WxH (e.g. --size 1280x800)')\n size = { width: Number(m[1]), height: Number(m[2]) }\n }\n\n // Duration for % times: the output's end (trims, speed and the clips\n // after the footage applied).\n const duration = docOutputDuration(take.doc)\n const frameRaw = strFlag(flags, 'frame')\n const timesRaw = strFlag(flags, 'times')\n const atZooms = flags['at-zooms'] === true\n const atMoments = flags['at-moments'] === true\n const atStill = flags['at-still'] === true\n let times: number[]\n try {\n times =\n frameRaw !== undefined\n ? parseTimes(frameRaw, duration)\n : timesRaw !== undefined\n ? parseTimes(timesRaw, duration)\n : atZooms || atMoments\n ? []\n : parseTimes('0,25%,50%,75%,100%', duration)\n } catch (e) {\n throw new UsageError(e instanceof Error ? e.message : String(e))\n }\n\n const browser = await launchBrowser()\n try {\n r.event({ event: 'phase', phase: 'frames' })\n const result = await framesTake(browser, dir, {\n times,\n atZooms,\n atMoments,\n atStill,\n width: size?.width,\n height: size?.height,\n outDir: strFlag(flags, 'out'),\n // NOTE: no --frame alias here — `frames --frame <t>` is the time selector.\n // Set the browser frame via --set frame.browserBar.kind=mac-light.\n overrides: {\n set: multi.set,\n background: strFlag(flags, 'background'),\n origin: platformOrigin({\n origin: strFlag(flags, 'origin'),\n api: strFlag(flags, 'api'),\n }),\n },\n })\n const index = await writeIndexJson(result)\n r.done(\n {\n outDir: result.outDir,\n index,\n width: result.width,\n height: result.height,\n duration: result.duration,\n frames: result.frames,\n },\n `Wrote ${result.frames.length} still(s) to ${result.outDir} (${result.width}x${result.height})\\n ${result.frames.map((f) => `${f.time.toFixed(2)}s${f.kind === 'zoom' ? ' [zoom apex]' : f.kind === 'moment' ? ` [${f.momentId}]` : ''} → ${f.file}`).join('\\n ')}`,\n )\n return EXIT_OK\n } finally {\n await browser.close()\n }\n}\n\nasync function cmdDeliver(argv: string[]): Promise<number> {\n const { positionals, flags, multi } = parseArgs(\n argv,\n BOOLEAN_FLAGS,\n MULTI_FLAGS,\n )\n const dir = positionals[0]\n const toRaw = strFlag(flags, 'to')\n if (!dir || !toRaw)\n throw new UsageError(\n 'vos deliver <take> --to cws,producthunt,x,linkedin,og,github,youtube (or all) [--release v2.1] [--out dir] [--times a,b] [--range a..b] [--json]\\n(hosted work: vos pull <id> --media first — deliver runs on a local take)',\n )\n const r = createReporter(flags.json === true)\n if (!isTakeDir(dir))\n throw new UsageError(\n `${dir} is not a take directory (no doc.json) — for hosted work run: vos pull <vosId> --media`,\n )\n let channels: string[]\n try {\n channels = resolveChannels(toRaw)\n } catch (e) {\n throw new UsageError(e instanceof Error ? e.message : String(e))\n }\n let range: [number, number] | undefined\n const rangeRaw = strFlag(flags, 'range')\n if (rangeRaw !== undefined) {\n const m = /^(\\d+(?:\\.\\d+)?)\\.\\.(\\d+(?:\\.\\d+)?)$/.exec(rangeRaw)\n if (!m)\n throw new UsageError(\n '--range expects a..b in OUTPUT seconds (e.g. --range 4..24)',\n )\n range = [Number(m[1]), Number(m[2])]\n if (range[1] <= range[0])\n throw new UsageError('--range end must be > start')\n }\n const take = await loadTake(dir)\n if (!take.doc) throw new UsageError(`${dir} has no doc.json — run plan first`)\n const duration = docOutputDuration(take.doc)\n const timesRaw = strFlag(flags, 'times')\n let times: number[] | undefined\n if (timesRaw !== undefined) {\n // Entries are seconds, percents, or `step:<id>[+offset]` against the\n // take's step timeline (the still is the step's response, settled).\n try {\n const doc = take.doc\n times = timesRaw\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean)\n .map((s) => resolveStepTime(doc, s) ?? parseTimes(s, duration)[0])\n } catch (e) {\n throw new UsageError(e instanceof Error ? e.message : String(e))\n }\n }\n const parallel = numFlag(flags, 'parallel', 1)\n if (!Number.isInteger(parallel) || parallel < 1 || parallel > 16) {\n throw new UsageError('--parallel expects an integer between 1 and 16')\n }\n\n let lookPick: Awaited<ReturnType<typeof resolveLook>>\n try {\n lookPick = await resolveLook(dir, {\n look: strFlag(flags, 'look'),\n brand: strFlag(flags, 'brand'),\n })\n } catch (e) {\n throw new UsageError(e instanceof Error ? e.message : String(e))\n }\n r.log(`look: ${lookPick.from}`)\n // LAUNCH.md beside the take: its poster roles name the documents the\n // card destinations render from. The words and the motion are the\n // document's own since `vos plan` wrote them.\n const launch = await readLaunchBesideTake(dir, strFlag(flags, 'launch'))\n if (launch) r.log(`launch: ${launch.file}`)\n\n const browser = await launchBrowser()\n try {\n const result = await deliverTake(browser, dir, {\n look: lookPick.look,\n launchRoles: launch?.roles ?? null,\n channels,\n outDir: strFlag(flags, 'out'),\n release: strFlag(flags, 'release'),\n times,\n range,\n parallel,\n composed: hasFlag(flags, 'composed'),\n overrides: {\n set: multi.set,\n background: strFlag(flags, 'background'),\n origin: platformOrigin({\n origin: strFlag(flags, 'origin'),\n api: strFlag(flags, 'api'),\n }),\n },\n onPhase: (phase) => {\n r.log(`${phase}…`)\n r.event({ event: 'phase', phase })\n },\n onProgress: (p) =>\n r.event({ event: 'progress', phase: 'deliver', fraction: p }),\n })\n const { kit } = result\n const assetLines = kit.assets.map(\n (a) =>\n `${a.destination} → ${a.path} (${a.w}x${a.h}, ${(a.bytes / 1024).toFixed(0)} KB${a.seconds !== null ? `, ${a.seconds.toFixed(1)}s` : ''}${a.frameTime !== null ? `, frame ${a.frameTime.toFixed(2)}s` : ''}${a.poster ? `, poster ${a.poster.class}` : ''})`,\n )\n const skippedLines = kit.skipped.map((s) => `skipped: ${s}`)\n r.done(\n {\n outDir: result.outDir,\n kit: result.kitFile,\n assets: kit.assets,\n skipped: kit.skipped,\n },\n `Wrote ${kit.assets.length} asset(s) + kit.json to ${result.outDir}` +\n (assetLines.length ? `\\n ${assetLines.join('\\n ')}` : '') +\n (skippedLines.length ? `\\n ${skippedLines.join('\\n ')}` : '') +\n `\\nStore uploads stay manual: hand the human this directory and the manifest.`,\n )\n return kit.assets.length > 0 ? EXIT_OK : EXIT_ERROR\n } finally {\n await browser.close()\n }\n}\n\n/**\n * `--style <doc.json|take dir|vosId>`: the reference doc whose style fields\n * `vos plan` copies and `vos digest` reports. A file or take dir on\n * disk, else a hosted take's head doc read with the key ladder.\n */\nasync function resolveStyleRef(\n flags: ParsedArgs['flags'],\n): Promise<{ from: string; doc: ProjectDoc } | null> {\n const styleRef = strFlag(flags, 'style')\n if (!styleRef) return null\n return resolveDocRef(styleRef, flags, '--style')\n}\n\n/**\n * A document reference: a doc.json or a take dir on disk, else a hosted\n * take's head doc read with the key ladder. What a template, a style seed\n * and a digest's reference all are. A local file is read into the current\n * vocabulary too.\n */\nasync function resolveDocRef(\n ref: string,\n flags: ParsedArgs['flags'],\n what: string,\n): Promise<{ from: string; doc: ProjectDoc }> {\n const styleRef = ref\n const file = existsSync(styleRef)\n ? resolve(\n styleRef,\n existsSync(join(styleRef, 'doc.json')) ? 'doc.json' : '',\n )\n : null\n if (file && existsSync(file)) {\n return {\n from: file,\n doc: migrateHostedDoc(\n JSON.parse(await readFile(file, 'utf8')) as Record<string, unknown>,\n ) as unknown as ProjectDoc,\n }\n }\n const origin = platformOrigin({\n origin: strFlag(flags, 'origin'),\n api: strFlag(flags, 'api'),\n })\n const key = resolveCredential(strFlag(flags, 'key'))\n const meta = await apiJson(origin, `/api/vos/${styleRef}`, { key })\n const head = (meta.body.vos as { currentVersionId?: string } | undefined)\n ?.currentVersionId\n if (meta.status !== 200 || !head) {\n // Not an id or a slug: a TITLE on the official shelf (\"End card\",\n // \"Split cover, landscape\"), the platform's registry of templates.\n const official = await officialTemplate(origin, styleRef)\n if (official && official.id !== styleRef)\n return resolveDocRef(official.id, flags, what)\n throw new UsageError(\n `${what}: ${styleRef} is neither a doc.json, a vos I can read, nor an official template's title`,\n )\n }\n const doc = await apiJson(\n origin,\n `/api/vos/${styleRef}/versions/${head}/doc`,\n { key },\n )\n if (doc.status !== 200)\n throw new UsageError(`${what}: ${styleRef} carries no doc (is it a take?)`)\n return {\n from: `${origin}/vos/${styleRef}`,\n doc: migrateHostedDoc(doc.body) as unknown as ProjectDoc,\n }\n}\n\n/** The official vos a ref names by title or slug, or null (offline = null). */\nasync function officialTemplate(\n origin: string,\n ref: string,\n): Promise<OfficialRow | null> {\n try {\n const list = await apiJson(origin, '/api/vos/official', {})\n if (list.status !== 200) return null\n const rows = (list.body as { voses?: OfficialRow[] }).voses ?? []\n return findOfficialByRef(rows, ref)\n } catch {\n return null\n }\n}\n\nasync function cmdDigest(argv: string[]): Promise<number> {\n const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS)\n const dir = positionals[0]\n if (!dir)\n throw new UsageError(\n 'vos digest <take> [--out dir] [--full 960] [--crop 640] [--no-frames] [--transcript <file>] [--style <doc.json|vosId>]',\n )\n const r = createReporter(flags.json === true)\n const take = await loadTake(dir)\n if (!take.doc) throw new UsageError(`${dir} has no doc.json — run plan first`)\n\n const transcriptPath = strFlag(flags, 'transcript')\n const transcript = transcriptPath\n ? parseTranscript(JSON.parse(await readFile(transcriptPath, 'utf8')))\n : null\n\n const style = await resolveStyleRef(flags)\n\n const noFrames = flags['no-frames'] === true\n let browser = null\n if (!noFrames) browser = await launchBrowser()\n try {\n r.event({ event: 'phase', phase: 'digest' })\n const result = await digestTake(browser, dir, {\n outDir: strFlag(flags, 'out'),\n full: strFlag(flags, 'full') ? numFlag(flags, 'full', 0) : undefined,\n crop: strFlag(flags, 'crop') ? numFlag(flags, 'crop', 0) : undefined,\n frames: !noFrames,\n transcript,\n style,\n })\n const d = result.digest\n const kinds = d.moments.reduce<Partial<Record<string, number>>>(\n (acc, m) => {\n acc[m.kind] = (acc[m.kind] ?? 0) + 1\n return acc\n },\n {},\n )\n r.done(\n {\n file: result.file,\n outDir: result.outDir,\n moments: d.moments.length,\n kinds,\n frames: d.images.full,\n crops: d.images.crop,\n sheet: d.images.sheet ? join(result.outDir, d.images.sheet) : null,\n scenes: kinds.scene ?? 0,\n sourceDuration: d.take.sourceDuration,\n outputDuration: d.take.outputDuration,\n hasCursor: d.take.hasCursor,\n ...(d.take.wall ? { wall: d.take.wall } : {}),\n ...(d.take.exposures.length ? { exposures: d.take.exposures } : {}),\n tokensEstimate: d.images.tokensEstimate,\n bytes: result.bytes,\n },\n `Wrote ${result.file} — ${d.moments.length} moments (${Object.entries(\n kinds,\n )\n .map(([k, n]) => `${n} ${k}`)\n .join(', ')}), ${d.images.full} frames + ${d.images.crop} crops` +\n (d.images.sheet ? `, sheet.png` : '') +\n ` — ~${d.images.tokensEstimate} image tokens to read them all` +\n (d.take.hasCursor\n ? ''\n : '\\n no cursor track: moments are head/tail/scenes only — pace by activity, zoom only where the ask names a place') +\n (d.take.exposures.length\n ? `\\n EXPOSED in the footage: ${d.take.exposures.map((e) => `${e.kind} in ${e.selector}`).join('; ')} — look at those frames before this take goes anywhere`\n : '') +\n (d.take.wall\n ? `\\n WALL: asked for ${d.take.wall.asked}, recorded ${d.take.wall.landed} — this footage may be the wrong page; re-record with a session before cutting it`\n : '') +\n `\\n Read digest.json, then the sheet, then a crop only where you must decide.`,\n )\n return EXIT_OK\n } finally {\n if (browser) await browser.close()\n }\n}\n\nasync function cmdOpen(argv: string[]): Promise<number> {\n const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS)\n const dir = positionals[0]\n if (!dir) throw new UsageError('vos open <take> [--studio <url>]')\n const r = createReporter(flags.json === true)\n const take = await loadTake(dir) // validates it IS a take (meta.json)\n if (!existsSync(take.paths.recording)) {\n throw new UsageError(`${dir} has no recording — re-run record`)\n }\n\n // The studio at vos.so by default (AN1): the one line an agent is handed\n // ends with the person's own product open there, on a clean machine with\n // no repo of ours around. VOS_ORIGIN (the platform origin) moves it for\n // this repo's dev server; --studio overrides both.\n const studio = (strFlag(flags, 'studio') ?? platformOrigin()).replace(\n /\\/+$/,\n '',\n )\n const server = await startTakeServer(resolve(dir), {})\n // /studio is the one editor route (older CLIs that open\n // /voila/studio ride a query-preserving 301 forever).\n const url = `${studio}/studio?take=${encodeURIComponent(server.base)}`\n r.event({ event: 'open', server: server.base, url })\n r.log(`take served at ${server.base}`)\n process.stdout.write(flags.json === true ? '' : `${url}\\n`)\n if (flags.print !== true) {\n r.log('opening the studio… (Ctrl-C to stop serving)')\n // Best-effort browser launch; the printed URL is the contract.\n const opener =\n process.platform === 'darwin'\n ? 'open'\n : process.platform === 'win32'\n ? 'start'\n : 'xdg-open'\n const { exec } = await import('node:child_process')\n exec(`${opener} ${JSON.stringify(url)}`, () => {})\n } else {\n r.log('serving (— --print: not launching a browser; Ctrl-C to stop)')\n }\n\n // Serve until interrupted — the studio streams the recording from us.\n await new Promise<void>((resolvePromise) => {\n const stop = () => {\n server.close()\n resolvePromise()\n }\n process.once('SIGINT', stop)\n process.once('SIGTERM', stop)\n })\n return EXIT_OK\n}\n\nasync function cmdJudge(argv: string[]): Promise<number> {\n const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS)\n const target = positionals[0]\n const against = strFlag(flags, 'against')\n if (!target || !against)\n throw new UsageError(\n 'vos judge <kit.json> --against <MANIFEST.json> [--out dir] [--json]\\n(the manifest names the reference set: id, file, role, layout, facts, rule per asset)',\n )\n const r = createReporter(flags.json === true)\n const kitFile = target.endsWith('kit.json')\n ? target\n : join(target, 'kit.json')\n if (!existsSync(kitFile)) throw new UsageError(`${kitFile}: no kit manifest`)\n if (!existsSync(against))\n throw new UsageError(`${against}: no reference manifest`)\n const result = await judgeKit(kitFile, against, strFlag(flags, 'out'))\n const verdicts = (\n JSON.parse(await readFile(result.verdictFile, 'utf8')) as {\n verdicts: { win: boolean | null; reasons?: number[] }[]\n }\n ).verdicts\n const rate = winRate(verdicts)\n const lines = result.sheets.map(\n (s) =>\n `${s.asset} vs ${s.reference}: ${s.sheetA}, ${s.sheetB}, ${s.rubric}`,\n )\n r.done(\n { ...result, winRate: rate },\n `Wrote ${result.sheets.length} sheet pair(s) to ${result.outDir}` +\n (lines.length ? `\\n ${lines.join('\\n ')}` : '') +\n (result.skipped.length\n ? `\\n skipped: ${result.skipped.join('\\n skipped: ')}`\n : '') +\n `\\nJudge each pair both ways (the rubric is beside it) and fill ${result.verdictFile}` +\n (rate.judged\n ? `\\nWin rate so far: ${rate.wins} win(s), ${rate.ties} tie(s) of ${rate.judged} judged (${(rate.rate! * 100).toFixed(0)}%; a tie counts a half); parity with the references is 50%, the marketability bar is 40%`\n : ''),\n )\n return EXIT_OK\n}\n\nasync function cmdCallout(argv: string[]): Promise<number> {\n const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS)\n const dir = positionals[0]\n const shape = positionals[1]\n if (!dir || !shape || !isCalloutShape(shape))\n throw new UsageError(\n 'vos callout <take> <note|tag|code> --step <id> [--title \"…\"] [--body \"…\"] [--kicker \"…\"] [--code \"…\"|--code-file f] [--seconds 3] [--side …] [--mark ring|underline|none] [--leader] [--color #hex (the mark and leader; the kicker is --accent)] [--brand BRAND.md] [--ground #hex --accent #hex] [--font \"…\"] [--body-px <n> (the body size on the delivered frame)] [--id x] [--print] [--json]',\n )\n const r = createReporter(flags.json === true)\n const take = await loadTake(dir)\n if (!take.doc) throw new UsageError(`${dir} has no doc.json — run plan first`)\n const brand = await readBrandBesideTake(dir, strFlag(flags, 'brand'))\n const bodyPx = strFlag(flags, 'body-px')\n const register = registerFrom(brand?.roles ?? null, {\n ground: strFlag(flags, 'ground'),\n accent: strFlag(flags, 'accent'),\n face: strFlag(flags, 'font'),\n mono: strFlag(flags, 'mono'),\n body: bodyPx !== undefined ? Number(bodyPx) : undefined,\n })\n if (!register)\n throw new UsageError(\n `no register: put a BRAND.md beside the take (vos brand <url> --out BRAND.md; its bgA and accent are the ground and the accent), or pass --ground #hex --accent #hex`,\n )\n const codeFile = strFlag(flags, 'code-file')\n const code = codeFile\n ? await readFile(codeFile, 'utf8')\n : strFlag(flags, 'code')\n const words = {\n kicker: strFlag(flags, 'kicker'),\n title: strFlag(flags, 'title'),\n body: strFlag(flags, 'body'),\n code: code?.replace(/\\\\n/g, '\\n'),\n }\n if (shape === 'code' && !words.code)\n throw new UsageError(\n 'a code callout needs --code \"…\" or --code-file <file>',\n )\n if (shape === 'note' && !words.title)\n throw new UsageError('a note needs --title \"…\"')\n if (shape === 'tag' && !words.kicker && !words.title)\n throw new UsageError('a tag needs --kicker \"…\"')\n const stepRaw = strFlag(flags, 'step')\n const atRaw = strFlag(flags, 'at')\n const secondsRaw = strFlag(flags, 'seconds')\n const side = strFlag(flags, 'side')\n const mark = strFlag(flags, 'mark')\n let composed\n try {\n composed = composeCallout(take.doc, register, {\n shape,\n words,\n id: strFlag(flags, 'id'),\n step:\n stepRaw !== undefined\n ? /^\\d+$/.test(stepRaw)\n ? Number(stepRaw)\n : stepRaw\n : undefined,\n at: atRaw !== undefined ? Number(atRaw) : undefined,\n seconds: secondsRaw !== undefined ? Number(secondsRaw) : undefined,\n side: side as never,\n mark: mark as never,\n leader: flags.leader === true,\n color: strFlag(flags, 'color'),\n bodyPxGiven: bodyPx !== undefined,\n })\n } catch (e) {\n throw new UsageError(e instanceof Error ? e.message : String(e))\n }\n const { clip, window, sizes } = composed\n if (flags.print === true) {\n r.done(\n { clip, window, sizes, register, brand: brand?.file ?? null },\n JSON.stringify(clip, null, 2),\n )\n return EXIT_OK\n }\n const doc = take.doc\n const overlays = (doc.overlays ?? []).filter((o) => o.id !== clip.id)\n const next = { ...doc, overlays: [...overlays, clip] }\n const lint = lintDoc(next)\n if (lint.problems.length) {\n r.done(\n { valid: false, problems: lint.problems, warnings: lint.warnings, clip },\n `the callout would not validate:\\n ${lint.problems.join('\\n ')}`,\n )\n return EXIT_ERROR\n }\n await writeJson(take.paths.doc, next, true)\n r.done(\n {\n clip,\n window,\n sizes,\n register,\n brand: brand?.file ?? null,\n warnings: lint.warnings,\n },\n `${shape} \"${clip.id}\" at ${window.start.toFixed(2)}s for ${window.duration.toFixed(2)}s${clip.pin ? `, pinned to ${clip.pin.step !== undefined ? `step ${String(clip.pin.step)}` : `the press at ${String(clip.pin.press)}s`}` : ''}, ground ${register.ground} → card in the product's hue, type ${sizes.kickerPx} / ${sizes.titlePx} / ${sizes.bodyPx} px (kicker / title / body; ${bodyPx !== undefined ? `--body-px ${bodyPx} as delivered` : `the app's body as seen, footage scale ${sizes.scale}; --body-px <n> sets the delivered size`}), written to ${take.paths.doc}${lint.warnings.length ? `\\n warnings:\\n ${lint.warnings.join('\\n ')}` : ''}`,\n )\n return EXIT_OK\n}\n\nasync function cmdValidate(argv: string[]): Promise<number> {\n const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS)\n const target = positionals[0]\n if (!target) throw new UsageError('vos validate <actions.json|take>')\n const r = createReporter(flags.json === true)\n // A kit manifest (deliver's output, or a hand-assembled PR kit): every\n // asset re-measured from its bytes against the channel specs.\n const kitTarget = target.endsWith('kit.json')\n ? target\n : existsSync(join(target, 'kit.json')) && !isTakeDir(target)\n ? join(target, 'kit.json')\n : null\n if (kitTarget) {\n const picture = flags.picture === true\n const verdict = await validateKit(kitTarget, { picture })\n const pictureLines = (verdict.picture ?? []).map(formatFinding)\n const pictureErrors = (verdict.picture ?? []).filter(\n (f) => f.severity === 'error',\n ).length\n const tail =\n (verdict.warnings.length\n ? `\\n warnings:\\n ${verdict.warnings.join('\\n ')}`\n : '') +\n (picture\n ? `\\n picture: ${pictureErrors} problem(s), ${(verdict.picture ?? []).length - pictureErrors} note(s)` +\n (pictureLines.length ? `\\n ${pictureLines.join('\\n ')}` : '')\n : '')\n if (!verdict.valid) {\n r.done(\n { ...verdict, target: kitTarget },\n `${kitTarget}:${verdict.problems.length ? `\\n ${verdict.problems.join('\\n ')}` : ''}${tail}`,\n )\n return EXIT_ERROR\n }\n r.done(\n { ...verdict, target: kitTarget },\n `${kitTarget}: ${verdict.measured.length} asset(s) match their bytes and their specs${tail}`,\n )\n return EXIT_OK\n }\n if (target.endsWith('.json')) {\n await loadActions(target)\n r.done({ valid: true, target }, `${target}: valid actions file`)\n return EXIT_OK\n }\n // A PROGRAM directory: config.json plus, optionally, a program\n // document — lint the document's shared layers against the program.\n if (!isTakeDir(target) && existsSync(join(target, 'config.json'))) {\n const parsed = JSON.parse(\n await readFile(join(target, 'config.json'), 'utf8'),\n ) as unknown\n const pre = preflightConfig(parsed)\n const problems = pre.ok ? [] : pre.issues.map((i) => `config.json: ${i}`)\n const warnings: string[] = []\n const doc = pre.config ? await readProgramDoc(target, pre.config) : null\n if (doc) {\n const lint = lintDoc(doc as never)\n problems.push(...lint.problems.map((p) => `doc.json: ${p}`))\n warnings.push(...lint.warnings.map((w) => `doc.json: ${w}`))\n }\n {\n const urls = [\n ...collectConfigMediaUrls(pre.config ?? parsed),\n ...collectDocMediaUrls(doc),\n ]\n const probe = mediaProbeLints(await probeMediaUrls([...new Set(urls)]))\n problems.push(...probe.problems)\n warnings.push(...probe.warnings)\n }\n if (problems.length) {\n r.done(\n { valid: false, target, problems, warnings },\n `${target}:\\n ${problems.join('\\n ')}${warnings.length ? `\\n warnings:\\n ${warnings.join('\\n ')}` : ''}`,\n )\n return EXIT_ERROR\n }\n r.done(\n { valid: true, target, warnings, doc: !!doc },\n `${target}: program${doc ? ' + document' : ''} is valid${warnings.length ? `\\n warnings:\\n ${warnings.join('\\n ')}` : ''}`,\n )\n return EXIT_OK\n }\n const take = await loadTake(target)\n const problems: string[] = []\n const warnings: string[] = []\n if (!existsSync(take.paths.recording)) {\n problems.push('missing recording (re-run record)')\n } else {\n const mismatch = containerMismatch(\n take.paths.recordingName,\n await readMediaHead(take.paths.recording),\n )\n if (mismatch) warnings.push(mismatch)\n }\n // What the recorder saw in the frame, and masks that hid nothing. The take\n // is valid either way (the doc is fine); these are what to look at before\n // the footage goes anywhere.\n for (const e of take.meta.exposures ?? [])\n warnings.push(`the recording shows ${exposureLine(e)}`)\n if (take.meta.exposures?.length) warnings.push(EXPOSURE_ADVICE)\n for (const m of take.meta.masks ?? [])\n if (m.hits === 0)\n warnings.push(\n `mask \"${m.selector}\" reached no element, so it hid nothing: whatever it was for may be showing`,\n )\n if (take.meta.wall)\n warnings.push(\n `recorded past a wall: asked for ${take.meta.wall.asked}, landed on ${take.meta.wall.landed}. This footage may be the wrong page`,\n )\n if (!take.doc) problems.push('missing doc.json (run plan)')\n if (take.doc) {\n const lint = lintDoc(take.doc)\n problems.push(...lint.problems.map((p) => `doc.json: ${p}`))\n warnings.push(...lint.warnings.map((w) => `doc.json: ${w}`))\n const probe = mediaProbeLints(\n await probeMediaUrls(collectDocMediaUrls(take.doc)),\n )\n problems.push(...probe.problems)\n warnings.push(...probe.warnings)\n // --picture: each html layer's ground against the footage it covers, as\n // the camera shows it at the layer's start (one browser session, the\n // footage rendered without layers).\n if (\n flags.picture === true &&\n (take.doc.overlays ?? []).some((o) => o.kind === 'html')\n ) {\n const doc = take.doc\n const times = [\n ...new Set(\n (doc.overlays ?? [])\n .filter((o) => o.kind === 'html')\n .map((o) => +(o.start + Math.min(0.35, o.duration / 2)).toFixed(3)),\n ),\n ]\n const browser = await launchBrowser()\n try {\n const frames = await footageFrames(\n browser,\n target,\n doc,\n times,\n framesTake,\n )\n const findings = await groundFindings(\n doc,\n async (t) => frames.get(+t.toFixed(3)) ?? null,\n )\n for (const f of findings) {\n if (f.level === 'problem') problems.push(`doc.json: ${f.message}`)\n else if (f.level === 'warning')\n warnings.push(`doc.json: ${f.message}`)\n else r.event({ event: 'ground', ...f })\n }\n } finally {\n await browser.close()\n }\n }\n }\n if (problems.length) {\n r.done(\n { valid: false, target, problems, warnings },\n `${target}:\\n ${problems.join('\\n ')}${warnings.length ? `\\n warnings:\\n ${warnings.join('\\n ')}` : ''}`,\n )\n return EXIT_ERROR\n }\n r.done(\n { valid: true, target, warnings },\n `${target}: take is complete and renderable${warnings.length ? `\\n warnings:\\n ${warnings.join('\\n ')}` : ''}`,\n )\n return EXIT_OK\n}\n\nasync function cmdPush(argv: string[]): Promise<number> {\n const { positionals, flags, multi } = parseArgs(\n argv,\n BOOLEAN_FLAGS,\n MULTI_FLAGS,\n )\n const dir = positionals[0]\n if (!dir)\n throw new UsageError(\n 'vos push <take> [--vos|--title|--label|--note|--folder|--override|--yes|--key|--api]',\n )\n const refusal = takePushRefusal({\n vos: strFlag(flags, 'vos'),\n trackedVosId: readSyncState(resolve(dir))?.vosId ?? null,\n programOnly: ['slug', 'desc', 'tags', 'base', 'remix-of', 'still'].filter(\n (name) => hasFlag(flags, name),\n ),\n })\n if (refusal) throw new UsageError(refusal)\n const r = createReporter(flags.json === true)\n // Index access is typed present but is runtime-optional — pushTake guards.\n const overrides = multi.override\n const result = await pushTake(\n resolve(dir),\n {\n key: strFlag(flags, 'key'),\n api: strFlag(flags, 'api'),\n origin: strFlag(flags, 'origin'),\n yes: flags.yes === true,\n vos: strFlag(flags, 'vos'),\n title: strFlag(flags, 'title'),\n label: strFlag(flags, 'label'),\n note: strFlag(flags, 'note'),\n folder: strFlag(flags, 'folder'),\n overrides,\n },\n r,\n )\n // The links name the origin the push went to, so a local dev push does\n // not point at the public site.\n const pushedTo = platformOrigin({\n origin: strFlag(flags, 'origin'),\n api: strFlag(flags, 'api'),\n }).replace(/\\/+$/, '')\n const landed =\n flags.wait === true\n ? await waitForLanded({\n origin: pushedTo,\n key: requireCredential(strFlag(flags, 'key')),\n vosId: result.vosId,\n versionId: result.versionId ?? null,\n log: (l) => r.log(l),\n })\n : null\n const filed =\n result.versionNumber === 1\n ? `\\n shelf: ${strFlag(flags, 'folder') ? `in ${strFlag(flags, 'folder')}` : `unfiled, at the root of your shelf (file it: vos folder move ${result.vosId} --to <slug>)`}`\n : ''\n r.done(\n {\n ...result,\n ...(landed\n ? {\n still: landed.still,\n thumbnailUrl: landed.thumbnailUrl,\n previewUrl: landed.previewUrl,\n }\n : {}),\n },\n `pushed v${result.versionNumber} → vos ${result.vosId}\\n review: ${pushedTo}/vos/${result.vosId}\\n studio: ${pushedTo}/studio?vos=${result.vosId}` +\n filed +\n (landed ? `\\n${landedLines(landed)}` : ''),\n )\n return EXIT_OK\n}\n\nasync function cmdPull(argv: string[]): Promise<number> {\n const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS, MULTI_FLAGS)\n const dir = positionals[0] ?? '.'\n const r = createReporter(flags.json === true)\n const result = await pullTake(\n resolve(dir),\n {\n key: strFlag(flags, 'key'),\n api: strFlag(flags, 'api'),\n origin: strFlag(flags, 'origin'),\n vos: strFlag(flags, 'vos'),\n media: flags.media === true,\n since: strFlag(flags, 'since'),\n check: flags.check === true,\n },\n r,\n )\n if (result.checked) {\n r.done(\n { ...result },\n result.behind === null\n ? `${result.vosId}: head is ${result.versionId.slice(0, 8)}… — no base to count from; run without --check to sync`\n : result.behind === 0\n ? `${result.vosId}: up to date`\n : `${result.behind} version${result.behind === 1 ? '' : 's'} behind — run without --check to sync`,\n )\n return EXIT_OK\n }\n const mediaLine = result.media\n ? result.media.downloaded.length\n ? ` + ${result.media.downloaded.map((m) => m.file).join(', ')} (footage home — digest/frames/render run here now)`\n : result.media.kept.length\n ? ` (footage already here: ${result.media.kept.join(', ')})`\n : ' (no hosted media on this doc)'\n : ''\n r.done(\n { ...result },\n (result.changed\n ? `pulled v${result.versionNumber ?? '?'} into doc.json — your edit loop continues from the human's version`\n : 'up to date') + mediaLine,\n )\n return EXIT_OK\n}\n\n/**\n * One verb's lines out of HELP: its usage line(s) and whatever is indented\n * under them. HELP stays the one text, so a verb's help cannot drift from it.\n */\nexport function verbHelp(verb: string): string {\n const lines = HELP.split('\\n')\n const out: string[] = []\n let taking = false\n for (const line of lines) {\n if (/^ {2}vos /.test(line)) taking = line.startsWith(` vos ${verb} `)\n else if (taking && !/^ {3,}\\S/.test(line)) taking = false\n if (taking) out.push(line)\n }\n if (out.length === 0) return `vos ${verb}: no such verb here. Run: vos help\\n`\n return `${out.join('\\n')}\\n\\nThe whole reference, with every flag explained: https://vos.so/llms-full.txt\\nExit codes: 0 ok, 1 error, 2 usage or --strict failure, 3 no browser, 4 the recorder met a sign-in instead of the page.\\n`\n}\n\n/** Entry point — the delegation contract for @vosjs/cli: the host forwards\n every non-engine verb here (`vos <verb>`; `vos voila <verb>` stays a\n hidden alias until public launch). The exported `manifest` (index.ts)\n tells the host which verbs exist and how to summarize them in help. */\nexport async function run(argv: string[]): Promise<number> {\n const [cmd, ...rest] = argv\n try {\n if (!cmd || cmd === 'help' || cmd === '--help' || cmd === '-h') {\n process.stdout.write(HELP)\n return cmd ? EXIT_OK : EXIT_USAGE\n }\n // `vos <verb> --help` is a question, never a usage error: an agent that\n // asks a verb for its flags used to get one line and exit 2, and went\n // grepping the package for the answer.\n if (rest.includes('--help') || rest.includes('-h')) {\n process.stdout.write(verbHelp(cmd))\n return EXIT_OK\n }\n switch (cmd) {\n case 'create':\n return await cmdCreate(rest)\n case 'record':\n return await cmdRecord(rest)\n case 'plan':\n return await cmdPlan(rest)\n case 'render':\n return await cmdRender(rest)\n case 'frames':\n return await cmdFrames(rest)\n case 'deliver':\n return await cmdDeliver(rest)\n case 'digest':\n return await cmdDigest(rest)\n case 'open':\n return await cmdOpen(rest)\n case 'validate':\n return await cmdValidate(rest)\n case 'callout':\n return await cmdCallout(rest)\n case 'judge':\n return await cmdJudge(rest)\n case 'fetch':\n return await cmdFetch(rest)\n case 'duplicate':\n return await cmdDuplicate(rest)\n case 'login':\n return await cmdLogin(rest)\n case 'setup':\n return await cmdSetup(rest)\n case 'doctor':\n return await cmdDoctor(rest)\n case 'whoami':\n return await cmdWhoami(rest)\n case 'logout':\n return cmdLogout(rest)\n case 'push': {\n // Polymorphic by the deterministic sniff: a take DIRECTORY (doc.json)\n // pushes recording + doc; anything else is a program config push.\n const target = rest.find((a) => !a.startsWith('-'))\n if (target && isTakeDir(target)) {\n if (rest.includes('--claimable')) {\n throw new UsageError(\n '--claimable pushes are PROGRAMS only (a config.json) — takes carry recordings, which need an account: vos login, then vos push',\n )\n }\n return await cmdPush(rest)\n }\n return await cmdPushProgram(rest)\n }\n case 'pull': {\n const target = rest.find((a) => !a.startsWith('-')) ?? '.'\n return isTakeDir(target)\n ? await cmdPull(rest)\n : await cmdPullProgram(rest)\n }\n case 'delete':\n return await cmdDelete(rest)\n case 'trash':\n return await cmdTrash(rest)\n case 'restore':\n return await cmdRestore(rest)\n case 'build':\n return await cmdBuild(rest)\n case 'compare':\n return await cmdCompare(rest)\n case 'port':\n return await cmdPort(rest)\n case 'folder':\n return await cmdFolder(rest)\n case 'asset':\n return await cmdAsset(rest)\n case 'recipe':\n return await cmdRecipe(rest)\n case 'brand':\n return await cmdBrand(rest)\n case 'session':\n return await cmdSession(rest)\n case 'actions':\n return await cmdActions(rest)\n case 'ingest':\n return await cmdIngest(rest)\n default:\n throw new UsageError(`unknown command \"${cmd}\" — run: vos help`)\n }\n } catch (e) {\n if (e instanceof UsageError) {\n process.stderr.write(`usage error: ${e.message}\\n`)\n return EXIT_USAGE\n }\n if (e instanceof SetupError || e instanceof SetupEnvError) {\n process.stderr.write(`${e.message}\\n`)\n return EXIT_USAGE\n }\n if (e instanceof WallError) {\n process.stderr.write(`wall: ${e.message}\\n`)\n return EXIT_WALL\n }\n if (e instanceof BrowserUnavailableError) {\n process.stderr.write(`${e.message}\\n`)\n return EXIT_NO_BROWSER\n }\n process.stderr.write(\n `error: ${e instanceof Error ? e.message : String(e)}\\n`,\n )\n return EXIT_ERROR\n }\n}\n\n/**\n * `vos session`: takeover mode, local. open / check / list / rm. Counts,\n * origins and expiry only; no verb prints a cookie value, --json included.\n */\nasync function cmdSession(argv: string[]): Promise<number> {\n const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS)\n const [sub, arg] = positionals\n const r = createReporter(flags.json === true)\n const usage =\n 'vos session open <url> --name <app> | check <name> [--url <url>] | list | rm <name>'\n switch (sub) {\n case 'open': {\n if (!arg) throw new UsageError(usage)\n const name = strFlag(flags, 'name')\n const bad = sessionNameVerdict(name)\n if (bad) throw new UsageError(bad)\n let url: URL\n try {\n url = new URL(arg)\n } catch {\n throw new UsageError(`vos session open wants a URL, got \"${arg}\"`)\n }\n if (!/^https?:$/.test(url.protocol))\n throw new UsageError('vos session open wants an http(s) URL')\n await openSession(name!, url.href, { log: r.log })\n const summary = await summarizeSession(name!)\n r.done(\n {\n name: summary.name,\n origins: summary.origins,\n newestExpires: summary.newestExpires,\n sessionOnly: summary.sessionOnly,\n },\n `${summaryLine(summary)}\\n Record on it: vos record --actions actions.json --out take --session ${name} --strict`,\n )\n return summary.origins.length ? EXIT_OK : EXIT_ERROR\n }\n case 'check': {\n if (!arg) throw new UsageError(usage)\n const bad = sessionNameVerdict(arg)\n if (bad) throw new UsageError(bad)\n if (!existsSync(sessionDir(arg)))\n throw new UsageError(`no session \"${arg}\" (vos session list)`)\n const summary = await summarizeSession(arg)\n const url = strFlag(flags, 'url')\n if (!url) {\n r.done(\n {\n name: arg,\n origins: summary.origins,\n newestExpires: summary.newestExpires,\n sessionOnly: summary.sessionOnly,\n },\n summaryLine(summary),\n )\n return summary.origins.length ? EXIT_OK : EXIT_WALL\n }\n // Does the session still open the page it was made for? The wall\n // check's own verdict, on this profile.\n const verdict = await withSession(arg, async (ctx) => {\n const page = await ctx.newPage()\n const response = await page\n .goto(url, { waitUntil: 'networkidle', timeout: 30000 })\n .catch(() => null)\n const seen = (await page.evaluate(WALL_PROBE).catch(() => null)) as {\n passwordFields: number\n newPasswordField: boolean\n oneTimeCodeField: boolean\n } | null\n return wallVerdict({\n askedUrl: url,\n landedUrl: page.url(),\n ...(response ? { status: response.status() } : {}),\n passwordFields: seen?.passwordFields ?? 0,\n newPasswordField: seen?.newPasswordField ?? false,\n oneTimeCodeField: seen?.oneTimeCodeField ?? false,\n })\n })\n if (verdict) {\n r.done(\n {\n name: arg,\n ok: false,\n wall: verdict,\n origins: summary.origins,\n newestExpires: summary.newestExpires,\n },\n `session \"${arg}\" no longer opens ${url}: ${verdict.message.split('. ')[0]}. It expired, or the sign-in never landed. Sign in again: vos session open ${url} --name ${arg}`,\n )\n return EXIT_WALL\n }\n r.done(\n {\n name: arg,\n ok: true,\n origins: summary.origins,\n newestExpires: summary.newestExpires,\n },\n `session \"${arg}\" opens ${url} signed in. ${summaryLine(summary)}`,\n )\n return EXIT_OK\n }\n case 'list': {\n const rows = listSessions()\n r.done(\n { sessions: rows },\n rows.length\n ? rows\n .map(\n (x) =>\n ` ${x.name} ${x.ageDays} day${x.ageDays === 1 ? '' : 's'} old`,\n )\n .join('\\n')\n : 'no sessions. Make one: vos session open <url> --name <app>',\n )\n return EXIT_OK\n }\n case 'rm': {\n if (!arg) throw new UsageError(usage)\n const bad = sessionNameVerdict(arg)\n if (bad) throw new UsageError(bad)\n const gone = removeSession(arg)\n r.done(\n { name: arg, removed: gone },\n gone ? `removed session \"${arg}\"` : `no session \"${arg}\"`,\n )\n return gone ? EXIT_OK : EXIT_ERROR\n }\n default:\n throw new UsageError(usage)\n }\n}\n","/** Output conventions — logs on stderr, results on stdout, --json NDJSON. */\nexport const EXIT_OK = 0\nexport const EXIT_ERROR = 1\nexport const EXIT_USAGE = 2\nexport const EXIT_NO_BROWSER = 3\n/** The recorder met a sign-in instead of the page it was asked for. */\nexport const EXIT_WALL = 4\n\nexport interface Reporter {\n json: boolean\n log: (msg: string) => void\n event: (obj: Record<string, unknown>) => void\n done: (obj: Record<string, unknown>, humanLine: string) => void\n}\n\nexport function createReporter(json: boolean): Reporter {\n return {\n json,\n log: (msg) => {\n if (!json) process.stderr.write(`${msg}\\n`)\n },\n event: (obj) => {\n if (json) process.stdout.write(`${JSON.stringify(obj)}\\n`)\n },\n done: (obj, humanLine) => {\n if (json)\n process.stdout.write(`${JSON.stringify({ event: 'done', ...obj })}\\n`)\n else process.stdout.write(`${humanLine}\\n`)\n },\n }\n}\n","/**\n * actions.json: the module moved to `@vosjs/render-core/record` (AN4), so\n * vosso's hosted recorder validates a request through the same\n * `validateActions` the CLI runs. This file keeps every name the CLI and\n * its tests import.\n */\nexport { validateActions } from '@vosjs/render-core/record'\nexport type { ActionStep, ActionsFile } from '@vosjs/render-core/record'\n","/**\n * Semantic lints for a take's doc.json — the agent-editable ProjectDoc surface.\n * Mirrors schema/doc.schema.json (keep the two in sync): the schema documents\n * the shape for agents/editors; these lints enforce the semantic contracts a\n * schema can't (overlap, footage bounds, the normalized-coords trap).\n *\n * The input is UNTRUSTED JSON an agent may have hand-edited — every access is\n * guarded, hence the `unknown`-based reads despite the ProjectDoc signature.\n *\n * `problems` break or visibly corrupt a render; `warnings` are honesty/taste\n * notes (footage upscaling, sub-minimum spans) that still render fine.\n */\nimport {\n CAM_SIZE_MAX,\n CAM_SIZE_MIN,\n CAM_SPAN_MIN,\n CARD_ENTER_KINDS,\n SEGMENT_ENTER_KINDS,\n SEGMENT_EXIT_KINDS,\n enterOf,\n exitOf,\n htmlLayerProblems,\n segmentOutputExtents,\n transitionSeconds,\n CARD_EXIT_KINDS,\n EXPORT_RESOLUTION_OPTIONS,\n FREEZE_SECONDS_MAX,\n FREEZE_SECONDS_MIN,\n IDLE_KINDS,\n MEDIA_ENTER_KINDS,\n MEDIA_EXIT_KINDS,\n MEDIA_FRAME_KEYS,\n SPEED_RATE_MAX,\n SPEED_RATE_MIN,\n TEXT_ENTER_KINDS,\n TEXT_EXIT_KINDS,\n TILT_DEG_MAX,\n RETIRED_ZOOM_STYLES,\n TILT_SPAN_MIN,\n ZOOM_LEVEL_MAX,\n ZOOM_LEVEL_MIN,\n ZOOM_SPAN_MIN,\n docCardLayout,\n docZoomTrack,\n findStep,\n outputEnd,\n pinBox,\n pinCandidates,\n pinRectOnScreen,\n pinReferent,\n parseEmphasis,\n ratedSegments,\n recommendedExportResolution,\n resolvePins,\n spanOutputExtent,\n zoomCoversRect,\n cameraModel,\n unionFitLevel,\n} from '@vosjs/studio-core'\nimport { TYPEFACE_CATALOG, findFontFamily, findTypeface } from '@vosjs/shared'\nimport type {\n ExportResolution,\n ProjectDoc,\n StudioDoc,\n OverlayClip,\n OverlayPin,\n} from '@vosjs/studio-core'\n\n/** How close (a fraction of the frame's height) a layer's box may sit to a\n * step's element, as the camera shows it, before it reads as ABOUT it. */\nconst PIN_NEAR_FRACTION = 0.08\n\n/** A step's element larger than this share of the frame is a SURFACE, which\n * every layer on it sits beside. */\nconst PIN_SURFACE_AREA = 0.25\n\nconst LABEL_STOPWORDS = new Set([\n 'the',\n 'and',\n 'for',\n 'with',\n 'your',\n 'you',\n 'this',\n 'that',\n 'from',\n 'into',\n 'button',\n 'link',\n])\n\nfunction wordsOf(text: string): string[] {\n return text\n .toLowerCase()\n .split(/[^a-z0-9]+/)\n .filter((x) => x.length >= 3 && !LABEL_STOPWORDS.has(x))\n}\n\n/** The words a person reads on a layer: an html layer's markup without its\n * tags, a text layer's string. A media layer has none. */\nfunction layerWords(o: Record<string, unknown>): Set<string> {\n const src =\n typeof o.html === 'string'\n ? o.html.replace(/<[^>]*>/g, ' ')\n : typeof o.text === 'string'\n ? o.text\n : ''\n return new Set(wordsOf(src))\n}\n\n/** The words a selector says the element READS as: the text and accessible\n * names it quotes (`has-text('OHLC Bars')`, `[aria-label='Save']`), never a\n * test id or a class, which name the element for code rather than people. */\nfunction selectorLabelWords(selector: string): string[] {\n const out: string[] = []\n const re =\n /(?:has-text\\(|text=|(?:aria-label|title|alt|placeholder|name)\\s*[*^$~|]?=\\s*)['\"]([^'\"]+)['\"]/g\n for (let m = re.exec(selector); m; m = re.exec(selector)) {\n out.push(...wordsOf(m[1]))\n }\n return [...new Set(out)]\n}\n\nconst STEP_KINDS_ALL = [\n 'none',\n 'fade',\n 'rise',\n 'pop',\n 'blur',\n 'typewriter',\n 'tilt-in',\n 'pull-out',\n 'recede',\n 'slide',\n 'scale',\n]\nconst STEP_SIDES = ['left', 'right', 'up', 'down']\nconst STEP_UNITS = ['block', 'line', 'word', 'char']\nconst STEP_DIRS = ['forward', 'reverse', 'center']\n\n/**\n * The one vocabulary, checked per primitive: which kinds a thing accepts\n * is its own (the card cannot typewrite, a word cannot tilt in), the\n * per-unit grammar belongs to words, and idle belongs to props.\n */\nfunction lintAnim(\n name: string,\n anim: unknown,\n kinds: {\n enter: readonly string[]\n exit: readonly string[]\n idle: readonly string[] | null\n words: boolean\n /** The card's own anim: its enter may wait (`at`). */\n card?: boolean\n },\n problems: string[],\n): void {\n if (anim === undefined) return\n if (typeof anim !== 'object' || anim === null || Array.isArray(anim)) {\n problems.push(`${name}.anim must be { enter?, exit?, idle? }`)\n return\n }\n const a = anim as Record<string, unknown>\n for (const side of ['enter', 'exit'] as const) {\n const step = a[side]\n if (step === undefined) continue\n const allowed = kinds[side]\n const spelled = typeof step === 'string' ? step : null\n const obj =\n typeof step === 'object' && step !== null && !Array.isArray(step)\n ? (step as Record<string, unknown>)\n : null\n const kind = spelled ?? (obj ? obj.kind : undefined)\n if (typeof kind !== 'string' || !STEP_KINDS_ALL.includes(kind)) {\n problems.push(\n `${name}.anim.${side} must be a kind or { kind, seconds?${kinds.words ? ', unit?, direction?, stagger?' : ''} } (got ${JSON.stringify(step)})`,\n )\n continue\n }\n if (!allowed.includes(kind)) {\n problems.push(\n `${name}.anim.${side} cannot be \"${kind}\" here; one of ${allowed.join(' | ')}`,\n )\n }\n if (!obj) continue\n const secs = obj.seconds\n if (\n secs !== undefined &&\n (typeof secs !== 'number' ||\n !Number.isFinite(secs) ||\n secs < 0.05 ||\n secs > 3)\n ) {\n problems.push(`${name}.anim.${side}.seconds must be 0.05..3`)\n }\n for (const key of ['unit', 'direction', 'stagger'] as const) {\n if (obj[key] === undefined) continue\n if (!kinds.words) {\n problems.push(`${name}.anim.${side}.${key} is for words only`)\n continue\n }\n if (\n key === 'unit' &&\n (typeof obj.unit !== 'string' || !STEP_UNITS.includes(obj.unit))\n )\n problems.push(\n `${name}.anim.${side}.unit must be ${STEP_UNITS.join('|')}`,\n )\n if (\n key === 'direction' &&\n (typeof obj.direction !== 'string' ||\n !STEP_DIRS.includes(obj.direction))\n )\n problems.push(\n `${name}.anim.${side}.direction must be ${STEP_DIRS.join('|')}`,\n )\n if (\n key === 'stagger' &&\n (typeof obj.stagger !== 'number' || obj.stagger < 0 || obj.stagger > 2)\n )\n problems.push(`${name}.anim.${side}.stagger must be seconds in 0..2`)\n }\n if (obj.at !== undefined) {\n if (!kinds.card || side !== 'enter')\n problems.push(\n `${name}.anim.${side}.at is the card's own: frame.anim.enter.at delays the card's entrance; a clip already starts at its own start`,\n )\n else if (\n typeof obj.at !== 'number' ||\n !Number.isFinite(obj.at) ||\n obj.at < 0 ||\n obj.at > 30\n )\n problems.push(\n `${name}.anim.enter.at must be OUTPUT seconds in 0..30 (when the card arrives; the ground plays alone until then)`,\n )\n else if (kind === 'none')\n problems.push(\n `${name}.anim.enter.at has nothing to delay: the enter is \"none\", so the card is on screen from the first frame`,\n )\n }\n if (obj.side !== undefined) {\n if (kind !== 'slide')\n problems.push(`${name}.anim.${side}.side is for a slide`)\n else if (typeof obj.side !== 'string' || !STEP_SIDES.includes(obj.side))\n problems.push(\n `${name}.anim.${side}.side must be ${STEP_SIDES.join(' | ')}`,\n )\n }\n }\n if (a.idle !== undefined && a.idle !== null) {\n if (!kinds.idle) problems.push(`${name}.anim.idle is for props only`)\n else if (typeof a.idle !== 'string' || !kinds.idle.includes(a.idle))\n problems.push(\n `${name}.anim.idle must be ${kinds.idle.join(' | ')} | null`,\n )\n }\n}\n\nfunction lintFrom(name: string, from: unknown, problems: string[]): void {\n if (from !== undefined && (typeof from !== 'string' || !from.length))\n problems.push(`${name}.from must be the id of the template that placed it`)\n}\n\nexport interface DocLintResult {\n problems: string[]\n warnings: string[]\n}\n\nconst EPS = 1e-3\n\ntype Json = Record<string, unknown>\n\nconst isNum = (v: unknown): v is number =>\n typeof v === 'number' && Number.isFinite(v)\nconst isObj = (v: unknown): v is Json => typeof v === 'object' && v !== null\n\n/** Array field → object entries (non-arrays/non-objects handled by callers). */\nconst entries = (v: unknown): Json[] =>\n Array.isArray(v) ? v.filter(isObj) : []\n\nconst spanName = (label: string, s: Json): string =>\n `${label} ${typeof s.id === 'string' ? s.id : `@${String(s.in)}`}`\n\n/** Per-span transition speed (zoom/tilt/camMotion). */\nconst TRANSITION_SPEEDS = ['instant', 'fast', 'smooth', 'slow']\nfunction checkTransition(s: Json, name: string, problems: string[]): void {\n if (\n s.transition !== undefined &&\n !TRANSITION_SPEEDS.includes(s.transition as string)\n ) {\n problems.push(\n `${name}: transition must be ${TRANSITION_SPEEDS.join('|')} (got ${String(s.transition)})`,\n )\n }\n}\n\n/**\n * A step anchor is metadata for `vos plan --reuse` — never read by\n * lowering — but a malformed one silently loses the re-record tie, so it\n * lints like everything else: in words, at the span that carries it.\n */\nfunction checkAnchor(s: Json, name: string, problems: string[]): void {\n if (s.anchor === undefined) return\n if (!isObj(s.anchor)) {\n problems.push(`${name}: anchor must be { step, at?, offset? }`)\n return\n }\n const a = s.anchor\n if (\n typeof a.step !== 'string' &&\n !(isNum(a.step) && Number.isInteger(a.step) && a.step >= 0)\n ) {\n problems.push(\n `${name}: anchor.step must be a step id (string) or index (integer ≥ 0)`,\n )\n }\n if (a.at !== undefined && a.at !== 'start' && a.at !== 'end') {\n problems.push(`${name}: anchor.at must be \"start\" or \"end\"`)\n }\n if (a.offset !== undefined && !isNum(a.offset)) {\n problems.push(`${name}: anchor.offset must be a number (seconds)`)\n }\n}\n\nfunction checkSpanList(\n list: Json[],\n label: string,\n duration: number,\n problems: string[],\n): void {\n const sorted = [...list].sort(\n (a, b) => (isNum(a.in) ? a.in : 0) - (isNum(b.in) ? b.in : 0),\n )\n for (const s of sorted) {\n const name = spanName(label, s)\n checkAnchor(s, name, problems)\n if (!isNum(s.in) || !isNum(s.out)) {\n problems.push(`${name}: in/out must be finite numbers (SOURCE seconds)`)\n continue\n }\n if (s.out - s.in <= 0)\n problems.push(`${name}: out (${s.out}) must be > in (${s.in})`)\n if (s.in < -EPS || (duration > 0 && s.in > duration + EPS)) {\n problems.push(\n `${name}: in=${s.in}s is outside the footage (0..${duration.toFixed(2)}s)`,\n )\n }\n if (duration > 0 && s.out > duration + EPS) {\n problems.push(\n `${name}: out=${s.out}s exceeds the footage (${duration.toFixed(2)}s)`,\n )\n }\n }\n for (let i = 1; i < sorted.length; i++) {\n const prev = sorted[i - 1]\n const curr = sorted[i]\n if (isNum(prev.out) && isNum(curr.in) && curr.in < prev.out - EPS) {\n problems.push(\n `${spanName(label, curr)} overlaps ${spanName(label, prev)} (spans must not overlap)`,\n )\n }\n }\n}\n\nexport function lintDoc(docIn: StudioDoc): DocLintResult {\n const doc = docIn as unknown as Json\n const problems: string[] = []\n const warnings: string[] = []\n // The anchor: a recording document carries `source` and lints its\n // footage-anchored tracks against the footage's length; a program\n // document lints the shared layers against the program's length.\n const recording = isObj(doc.source)\n const source = isObj(doc.source) ? doc.source : {}\n const meta = isObj(source.meta) ? source.meta : {}\n const program = isObj(doc.program) ? doc.program : undefined\n const programConfig =\n program && isObj(program.config) ? program.config : undefined\n const duration = recording\n ? (isNum(meta.durationMs) ? meta.durationMs : 0) / 1000\n : program && isNum(program.duration)\n ? program.duration\n : programConfig && isNum(programConfig.duration)\n ? programConfig.duration\n : 0\n // The take's other media (concat): a span that names one is measured\n // against THAT media's length, never the primary's.\n const mediaLen = new Map<string, number>()\n if (recording && doc.media !== undefined) {\n if (!Array.isArray(doc.media)) problems.push('media must be an array')\n for (const [i, raw] of (Array.isArray(doc.media)\n ? (doc.media as unknown[])\n : []\n ).entries()) {\n const m = isObj(raw) ? raw : {}\n const id = typeof m.id === 'string' ? m.id : ''\n if (!id) problems.push(`media[${i}]: id must be a string`)\n else if (mediaLen.has(id))\n problems.push(`media[${i}] (${id}): duplicate id`)\n // A media's own card: card-owned fields only (the frame-wide ones,\n // the aspect, the padding, the ground, the backdrop, the card's\n // animation, are the take's and read wrong on a media).\n const mf = (m as { frame?: unknown }).frame\n if (mf !== undefined) {\n if (!isObj(mf)) {\n problems.push(\n `media[${i}]${id ? ` (${id})` : ''}: frame must be an object`,\n )\n } else {\n for (const k of Object.keys(mf)) {\n if (!(MEDIA_FRAME_KEYS as readonly string[]).includes(k))\n problems.push(\n `media[${i}]${id ? ` (${id})` : ''}.frame.${k}: not a card field (a media's frame carries ${MEDIA_FRAME_KEYS.join(', ')}; the rest is the take's frame)`,\n )\n }\n }\n }\n if (typeof m.videoKey !== 'string')\n problems.push(\n `media[${i}]${id ? ` (${id})` : ''}: videoKey must be a string`,\n )\n const mm = isObj(m.meta) ? m.meta : {}\n const ms = isNum(mm.durationMs) ? mm.durationMs : 0\n if (id) mediaLen.set(id, ms / 1000)\n }\n }\n /** Check a span list media by media: each against its own footage. */\n const checkByMedia = (list: Json[], label: string): void => {\n const groups = new Map<string, Json[]>()\n for (const s of list) {\n const m = typeof s.media === 'string' ? s.media : ''\n if (m && !mediaLen.has(m)) {\n problems.push(\n `${spanName(label, s)}: media \"${m}\" is not one of media[].id`,\n )\n continue\n }\n groups.set(m, [...(groups.get(m) ?? []), s])\n }\n for (const [m, group] of groups)\n checkSpanList(\n group,\n label,\n m ? (mediaLen.get(m) ?? 0) : duration,\n problems,\n )\n }\n if (!recording) {\n if (!program)\n problems.push(\n 'doc must carry `source` (a recording) or `program` (a program)',\n )\n else if (!programConfig)\n problems.push(\n 'program.config must be the config object (functions as strings)',\n )\n if (\n program &&\n program.tweenEdits !== undefined &&\n !isObj(program.tweenEdits)\n )\n problems.push('program.tweenEdits must be an object keyed by spec index')\n }\n\n // --- zoom spans (the highest-traffic agent surface) ---\n if (recording && !Array.isArray(doc.zoom))\n problems.push('zoom must be an array of spans')\n const zoom = recording ? entries(doc.zoom) : []\n if (recording) {\n checkByMedia(zoom, 'zoom')\n for (const z of zoom) {\n const name = spanName('zoom', z)\n if (\n !isNum(z.level) ||\n z.level < ZOOM_LEVEL_MIN - EPS ||\n z.level > ZOOM_LEVEL_MAX + EPS\n ) {\n problems.push(\n `${name}: level=${String(z.level)} out of range (${ZOOM_LEVEL_MIN}..${ZOOM_LEVEL_MAX})`,\n )\n }\n for (const axis of ['cx', 'cy'] as const) {\n const v = z[axis]\n if (!isNum(v) || v < 0 || v > 1) {\n problems.push(\n `${name}: ${axis}=${String(v)} — focus coords are NORMALIZED [0..1] video-frame fractions (0.5 = center), not pixels`,\n )\n }\n }\n checkTransition(z, name, problems)\n if (\n z.focusMode !== undefined &&\n z.focusMode !== 'manual' &&\n z.focusMode !== 'auto'\n ) {\n problems.push(`${name}: focusMode must be 'manual' or 'auto'`)\n }\n if (z.screen !== undefined) {\n const sp = z.screen as Record<string, unknown> | null\n const ok =\n !!sp &&\n typeof sp === 'object' &&\n isNum(sp.x) &&\n isNum(sp.y) &&\n (sp.x as number) >= 0 &&\n (sp.x as number) <= 1 &&\n (sp.y as number) >= 0 &&\n (sp.y as number) <= 1\n if (!ok) {\n problems.push(\n `${name}: screen must be { x, y } in 0..1 — where the target lands as FRACTIONS of the frame (0.35, 0.5 = a third across, centred), not pixels`,\n )\n } else if (z.focusMode === 'auto') {\n warnings.push(\n `${name}: screen is ignored on a span that follows the cursor (focusMode 'auto'); drop one or the other`,\n )\n } else if (cameraModel(doc.frame as never) !== 'stage') {\n warnings.push(\n `${name}: screen places the target under the stage camera only (frame.camera: 'stage'); the magnifier keeps the target where it is`,\n )\n }\n }\n if (\n z.source !== undefined &&\n z.source !== 'manual' &&\n z.source !== 'auto'\n ) {\n problems.push(`${name}: source must be 'manual' or 'auto'`)\n }\n if (\n isNum(z.in) &&\n isNum(z.out) &&\n z.out - z.in > 0 &&\n z.out - z.in < ZOOM_SPAN_MIN\n ) {\n warnings.push(\n `${name}: span ${(z.out - z.in).toFixed(2)}s is under the ${ZOOM_SPAN_MIN}s minimum the studio enforces`,\n )\n }\n }\n\n // --- the still: the frame that stands for the take, output seconds ---\n if (recording && doc.still !== undefined) {\n const st = doc.still\n if (!isNum(st) || st < 0) {\n problems.push('still must be a number ≥ 0 (OUTPUT seconds)')\n } else {\n const rated = ratedSegments(doc as unknown as ProjectDoc)\n const end = outputEnd(\n doc as unknown as ProjectDoc,\n rated.reduce((a, s) => a + (s.out - s.in) / (s.rate ?? 1), 0),\n )\n if (st > end + 1e-6)\n problems.push(\n `still=${String(st)} is past the output's end (${end.toFixed(2)}s)`,\n )\n }\n }\n // --- freezes and the end card: a freeze is output seconds, never long ---\n for (const [i, seg] of (Array.isArray(doc.segments)\n ? (doc.segments as unknown[])\n : []\n ).entries()) {\n const hold = (seg as { hold?: unknown }).hold\n if (hold === undefined) continue\n if (!isNum(hold) || hold < 0 || hold > FREEZE_SECONDS_MAX) {\n problems.push(\n `segments[${i}].hold must be 0..${FREEZE_SECONDS_MAX} output seconds (got ${String(hold)})`,\n )\n } else if (hold > 0) {\n warnings.push(\n `segments[${i}].hold is a legacy spelling, read as a freeze at ${String((seg as { out?: unknown }).out)}s (doc.freeze); vos plan writes that shape`,\n )\n }\n }\n if (doc.freeze !== undefined && !Array.isArray(doc.freeze)) {\n problems.push('freeze must be an array of {id, at, seconds}')\n }\n const freezes = Array.isArray(doc.freeze) ? (doc.freeze as unknown[]) : []\n const freezeIds = new Set<string>()\n for (const [i, raw] of freezes.entries()) {\n const f = raw as { id?: unknown; at?: unknown; seconds?: unknown }\n const name = `freeze[${i}]${typeof f.id === 'string' ? ` (${f.id})` : ''}`\n if (typeof f.id !== 'string' || !f.id)\n problems.push(`${name}: id must be a string`)\n else if (freezeIds.has(f.id)) problems.push(`${name}: duplicate id`)\n else freezeIds.add(f.id)\n const fm =\n typeof (f as { media?: unknown }).media === 'string'\n ? ((f as { media?: string }).media as string)\n : ''\n const fLen = fm ? mediaLen.get(fm) : duration\n if (fm && fLen === undefined) {\n problems.push(`${name}: media \"${fm}\" is not one of media[].id`)\n } else if (!isNum(f.at) || f.at < 0 || f.at > (fLen ?? duration) + EPS) {\n problems.push(\n `${name}: at must be a SOURCE moment inside the recording (0..${(fLen ?? duration).toFixed(2)}s, got ${String(f.at)})`,\n )\n }\n if (\n !isNum(f.seconds) ||\n f.seconds < FREEZE_SECONDS_MIN - EPS ||\n f.seconds > FREEZE_SECONDS_MAX + EPS\n ) {\n problems.push(\n `${name}: seconds must be ${FREEZE_SECONDS_MIN}..${FREEZE_SECONDS_MAX} output seconds (got ${String(f.seconds)})`,\n )\n }\n }\n const endCard = (doc as { endCard?: unknown }).endCard\n if (endCard !== undefined) {\n warnings.push(\n 'endCard is a legacy spelling, read as clips after the footage plus a card exit (frame.anim.exit); vos plan writes that shape',\n )\n if (typeof endCard !== 'object' || endCard === null) {\n problems.push(\n 'endCard must be an object: {seconds?, headline?, sub?, wordmark?}',\n )\n } else {\n const ec = endCard as {\n seconds?: unknown\n headline?: unknown\n sub?: unknown\n wordmark?: unknown\n }\n if (\n ec.seconds !== undefined &&\n (!isNum(ec.seconds) || ec.seconds < 1 || ec.seconds > 8)\n ) {\n problems.push(\n `endCard.seconds must be 1..8 (got ${String(ec.seconds)}); absent = 2.5`,\n )\n }\n for (const k of ['headline', 'sub', 'wordmark'] as const) {\n if (ec[k] !== undefined && typeof ec[k] !== 'string') {\n problems.push(`endCard.${k} must be a string`)\n }\n }\n if (\n !['headline', 'sub', 'wordmark'].some(\n (k) =>\n typeof ec[k as keyof typeof ec] === 'string' &&\n (ec[k as keyof typeof ec] as string).trim(),\n )\n ) {\n warnings.push(\n 'endCard carries no words: it holds the last frame and recedes the card over nothing',\n )\n }\n }\n }\n // --- segments (kept footage) ---\n if (doc.segments !== undefined && !Array.isArray(doc.segments)) {\n problems.push('segments must be an array of {in, out} spans')\n }\n checkByMedia(entries(doc.segments), 'segment')\n // A clip's transitions: the vocabulary a footage clip accepts, never\n // longer than half the shorter clip at its boundary (the clip must be\n // seen still before it moves), and the outer edges are the card's.\n const segs = Array.isArray(doc.segments)\n ? (doc.segments as Record<string, unknown>[]).filter(isObj)\n : []\n segs.forEach((seg, i) => {\n lintAnim(\n `segments[${i}]`,\n seg.anim,\n {\n enter: SEGMENT_ENTER_KINDS,\n exit: SEGMENT_EXIT_KINDS,\n idle: null,\n words: false,\n },\n problems,\n )\n })\n if (segs.length && segs.every((s) => isNum(s.in) && isNum(s.out))) {\n const anims = segs.map(\n (s) => s.anim as ProjectDoc['segments'][number]['anim'],\n )\n if (enterOf(anims[0]) && enterOf(anims[0])!.kind !== 'none')\n warnings.push(\n 'segments[0].anim.enter is ignored: the first clip arrives with the card (frame.anim.enter)',\n )\n const last = segs.length - 1\n if (\n last > 0 &&\n exitOf(anims[last]) &&\n exitOf(anims[last])!.kind !== 'none'\n )\n warnings.push(\n `segments[${last}].anim.exit is ignored: the last clip leaves with the card (frame.anim.exit)`,\n )\n let extents: { start: number; end: number }[] = []\n try {\n extents = segmentOutputExtents(doc as unknown as ProjectDoc)\n } catch {\n extents = []\n }\n for (\n let i = 0;\n i + 1 < segs.length && extents.length === segs.length;\n i++\n ) {\n const cap =\n Math.min(\n extents[i].end - extents[i].start,\n extents[i + 1].end - extents[i + 1].start,\n ) / 2\n const exitS = transitionSeconds(exitOf(anims[i]))\n const enterS = transitionSeconds(enterOf(anims[i + 1]))\n if (exitS > cap + EPS)\n problems.push(\n `segments[${i}].anim.exit: ${exitS}s is longer than half the shorter clip at that boundary (${cap.toFixed(2)}s); the clip must be seen still before it moves`,\n )\n if (enterS > cap + EPS)\n problems.push(\n `segments[${i + 1}].anim.enter: ${enterS}s is longer than half the shorter clip at that boundary (${cap.toFixed(2)}s); the clip must be seen still before it moves`,\n )\n }\n }\n }\n\n // --- speed spans ---\n const speed = entries(doc.speed)\n checkByMedia(speed, 'speed')\n for (const s of speed) {\n if (\n !isNum(s.rate) ||\n s.rate < SPEED_RATE_MIN - EPS ||\n s.rate > SPEED_RATE_MAX + EPS\n ) {\n problems.push(\n `${spanName('speed', s)}: rate=${String(s.rate)} out of range (${SPEED_RATE_MIN}..${SPEED_RATE_MAX})`,\n )\n }\n }\n\n if (recording) {\n // --- tilt spans (card pose regions — DEGREES, footage-anchored) ---\n if (doc.tilt !== undefined && !Array.isArray(doc.tilt)) {\n problems.push('tilt must be an array of spans')\n }\n const tilt = entries(doc.tilt)\n checkByMedia(tilt, 'tilt')\n const dramatic: string[] = []\n for (const t of tilt) {\n const name = spanName('tilt', t)\n for (const ax of ['rx', 'ry'] as const) {\n const v = t[ax]\n if (!isNum(v) || v < -TILT_DEG_MAX || v > TILT_DEG_MAX) {\n problems.push(\n `${name}: ${ax}=${String(v)} — pose angles are DEGREES in -${TILT_DEG_MAX}..${TILT_DEG_MAX} (not radians, not fractions)`,\n )\n }\n }\n checkTransition(t, name, problems)\n if (isNum(t.rx) && isNum(t.ry) && Math.abs(t.rx) + Math.abs(t.ry) > 25) {\n dramatic.push(\n `${name} ${(Math.abs(t.rx) + Math.abs(t.ry)).toFixed(0)}°`,\n )\n }\n if (\n t.source !== undefined &&\n t.source !== 'manual' &&\n t.source !== 'auto'\n ) {\n problems.push(`${name}: source must be 'manual' or 'auto'`)\n }\n if (\n isNum(t.in) &&\n isNum(t.out) &&\n t.out - t.in > 0 &&\n t.out - t.in < TILT_SPAN_MIN\n ) {\n warnings.push(\n `${name}: span ${(t.out - t.in).toFixed(2)}s is under the ${TILT_SPAN_MIN}s minimum the studio enforces (a pose needs ~0.9s ramps to settle)`,\n )\n }\n }\n // Said ONCE: a strong lean is usually a choice made for the whole piece,\n // and a line per span teaches the reader to skim the list.\n if (dramatic.length) {\n warnings.push(\n `tilt: ${dramatic.length === 1 ? 'a span leans' : `${dramatic.length} spans lean`} past 25° combined (${dramatic.join(', ')}) and read${dramatic.length === 1 ? 's' : ''} dramatic — the premium band is ±5..18° per axis; keep it if the piece means it`,\n )\n }\n // A retired camera style name still reads (its live style plus the tilt\n // intensity the name carried); say so rather than refuse an old take.\n if (\n typeof doc.zoomStyle === 'string' &&\n doc.zoomStyle in RETIRED_ZOOM_STYLES\n ) {\n const r = RETIRED_ZOOM_STYLES[doc.zoomStyle]\n warnings.push(\n `zoomStyle \"${doc.zoomStyle}\" is retired: it reads as \"${r.style}\" with tiltStyle \"${r.tilt}\" (write those instead)`,\n )\n }\n if (\n doc.tiltStyle !== undefined &&\n !['off', 'subtle', 'medium', 'strong'].includes(doc.tiltStyle as string)\n ) {\n problems.push(\n `tiltStyle must be \"off\" | \"subtle\" | \"medium\" | \"strong\" (got ${String(doc.tiltStyle)})`,\n )\n }\n\n // --- rejected proposals (\"not this one\": a deleted auto span, kept) ---\n if (doc.rejected !== undefined && !Array.isArray(doc.rejected)) {\n problems.push('rejected must be an array of {id, lane, in, out}')\n }\n for (const r of entries(doc.rejected)) {\n const name = spanName('rejected', r)\n if (!['zoom', 'tilt', 'speed'].includes(r.lane as string)) {\n problems.push(\n `${name}: lane must be \"zoom\" | \"tilt\" | \"speed\" (got ${String(r.lane)})`,\n )\n }\n if (!isNum(r.in) || !isNum(r.out) || r.out <= r.in) {\n problems.push(`${name}: needs SOURCE seconds in < out`)\n } else if (r.in >= duration) {\n problems.push(\n `${name}: starts at ${r.in}s, past the footage (${duration.toFixed(2)}s) — nothing to reject there`,\n )\n }\n }\n\n // --- cam pose spans (MO: animated cam layouts — fractions, footage-anchored) ---\n if (doc.camMotion !== undefined && !Array.isArray(doc.camMotion)) {\n problems.push('camMotion must be an array of spans')\n }\n const camMotion = entries(doc.camMotion)\n checkByMedia(camMotion, 'camMotion')\n if (camMotion.length && typeof source.camKey !== 'string') {\n warnings.push(\n 'camMotion has spans but the take has no cam track (source.camKey) — nothing renders them',\n )\n }\n for (const m of camMotion) {\n const name = spanName('camMotion', m)\n for (const axis of ['x', 'y'] as const) {\n const v = m[axis]\n if (v !== undefined && (!isNum(v) || v < 0 || v > 1)) {\n problems.push(\n `${name}: ${axis}=${String(v)} — the bubble center is FRACTIONS of the frame [0..1] (the zoom cx/cy convention), not pixels`,\n )\n }\n }\n if (\n m.size !== undefined &&\n (!isNum(m.size) ||\n m.size < CAM_SIZE_MIN - EPS ||\n m.size > CAM_SIZE_MAX + EPS)\n ) {\n problems.push(\n `${name}: size=${String(m.size)} must be a fraction of the frame height in ${CAM_SIZE_MIN}..${CAM_SIZE_MAX}`,\n )\n }\n checkTransition(m, name, problems)\n if (m.x === undefined && m.y === undefined && m.size === undefined) {\n warnings.push(\n `${name}: no pose fields (x/y/size) — the span inherits the rest pose and changes nothing`,\n )\n }\n if (\n m.source !== undefined &&\n m.source !== 'manual' &&\n m.source !== 'auto'\n ) {\n problems.push(`${name}: source must be 'manual' or 'auto'`)\n }\n if (\n isNum(m.in) &&\n isNum(m.out) &&\n m.out - m.in > 0 &&\n m.out - m.in < CAM_SPAN_MIN\n ) {\n warnings.push(\n `${name}: span ${(m.out - m.in).toFixed(2)}s is under the ${CAM_SPAN_MIN}s minimum the studio enforces (a move needs its ~0.65s ramp to settle)`,\n )\n }\n }\n }\n\n // --- audio clips (OUTPUT-anchored) ---\n for (const a of entries(doc.audio)) {\n const name = `audio ${typeof a.id === 'string' ? a.id : `@${String(a.start)}`}`\n if (!isNum(a.start) || a.start < -EPS)\n problems.push(`${name}: start must be ≥ 0 (OUTPUT seconds)`)\n if (!isNum(a.in) || !isNum(a.out) || a.out - a.in <= 0) {\n problems.push(\n `${name}: in/out must be a positive span within the source file`,\n )\n }\n if (a.gain !== undefined && (!isNum(a.gain) || a.gain < 0 || a.gain > 1)) {\n problems.push(`${name}: gain must be 0..1`)\n }\n }\n\n if (recording) {\n // --- background media (frame.backgroundMedia) ---\n const frame = isObj(doc.frame) ? doc.frame : undefined\n const bgm =\n frame && isObj(frame.backgroundMedia) ? frame.backgroundMedia : undefined\n if (bgm) {\n if (bgm.kind !== 'video' && bgm.kind !== 'image') {\n problems.push(\n `frame.backgroundMedia.kind must be \"video\" or \"image\" (got ${String(bgm.kind)})`,\n )\n }\n if (typeof bgm.key !== 'string' || bgm.key.length === 0) {\n problems.push(\n 'frame.backgroundMedia.key must be a non-empty URL or take-dir file (e.g. \"/bg.webm\")',\n )\n }\n if (\n bgm.dim !== undefined &&\n (!isNum(bgm.dim) || bgm.dim < 0 || bgm.dim > 1)\n ) {\n problems.push(\n `frame.backgroundMedia.dim must be 0..1 (got ${String(bgm.dim)})`,\n )\n }\n if (bgm.kind === 'video') {\n if (bgm.duration === undefined) {\n // A video background with no duration can't compute its modulo loop —\n // it would freeze on the first frame.\n warnings.push(\n 'frame.backgroundMedia: a video background has no `duration` — the loop needs it (bgT = t % duration), else it freezes',\n )\n } else if (!isNum(bgm.duration) || bgm.duration <= 0) {\n problems.push(\n `frame.backgroundMedia.duration must be > 0 for a video background (got ${String(bgm.duration)})`,\n )\n }\n }\n }\n\n // --- frame depth dials (V2) ---\n if (frame) {\n for (const k of ['parallax'] as const) {\n const v = frame[k]\n if (v !== undefined && (!isNum(v) || v < 0 || v > 1)) {\n problems.push(`frame.${k} must be 0..1 (got ${String(v)})`)\n }\n }\n const cam = frame.camera\n if (cam !== undefined && cam !== 'card' && cam !== 'stage') {\n problems.push(\n `frame.camera must be \"card\" or \"stage\" (got ${String(cam)}); absent = card, the clamped magnifier every older take was cut with`,\n )\n }\n }\n\n // --- cover fit: fit is a closed pair, focus normalized fractions ---\n if (frame) {\n const fit = frame.fit\n if (fit !== undefined && fit !== 'contain' && fit !== 'cover') {\n problems.push(\n `frame.fit must be \"contain\" or \"cover\" (got ${String(fit)})`,\n )\n }\n const focus = frame.focus\n if (focus !== undefined) {\n if (!isObj(focus)) {\n problems.push('frame.focus must be { cx, cy } in 0..1')\n } else {\n for (const k of ['cx', 'cy'] as const) {\n const v = focus[k]\n if (v !== undefined && (!isNum(v) || v < 0 || v > 1)) {\n problems.push(\n `frame.focus.${k} must be a normalized video fraction 0..1 (got ${String(v)}) — the zoom cx/cy convention, never pixels`,\n )\n }\n }\n }\n if (fit !== 'cover') {\n warnings.push(\n 'frame.focus only acts under frame.fit: \"cover\" (contain ignores it)',\n )\n }\n }\n }\n\n // --- the card stroke: a switch (alpha) with a width and a colour ---\n // ON_FRAME falls back to the 1.5px white hairline for a width it cannot\n // use, so an out-of-range number would render as the default and read as\n // \"the field was ignored\". Say so here instead.\n if (frame) {\n const bw = frame.borderWidth\n if (bw !== undefined && (!isNum(bw) || bw <= 0 || bw > 24)) {\n problems.push(\n `frame.borderWidth must be 0..24 design px (got ${String(bw)}); absent = the 1.5px hairline`,\n )\n }\n const bc = frame.borderColor\n if (bc !== undefined && (typeof bc !== 'string' || !bc.trim())) {\n problems.push(\n `frame.borderColor must be a CSS colour string (got ${String(bc)}); absent = #ffffff`,\n )\n }\n if ((bw !== undefined || bc !== undefined) && !frame.border) {\n problems.push(\n 'frame.borderWidth/borderColor are set but frame.border is 0 — border is the switch AND the alpha, so nothing is drawn',\n )\n }\n // The border grows OUTWARD from the card's edge, into the padding ring,\n // and the frame crops whatever reaches past its own edge — so a border\n // wider than the padding renders cropped flat where the card meets the\n // frame (at padding 0, not at all on that axis). The doc still renders,\n // so this is honesty, not breakage.\n // --- the second shadow layer and its colour ---\n const sc = frame.shadowContact\n if (sc !== undefined && (!isNum(sc) || sc < 0 || sc > 1)) {\n problems.push(\n `frame.shadowContact must be 0..1 (got ${String(sc)}); absent = no contact layer`,\n )\n }\n const shc = frame.shadowColor\n if (shc !== undefined && !/^#[0-9a-fA-F]{6}$/.test(String(shc))) {\n problems.push(\n `frame.shadowColor must be a #rrggbb hex (got ${String(shc)}); absent = black`,\n )\n }\n // --- the entrance and the crop that follows the camera ---\n const ent = frame.entrance\n if (ent !== undefined) {\n warnings.push(\n 'frame.entrance is a legacy spelling; write frame.anim.enter',\n )\n const kinds = ['tilt-in', 'pull-out', 'rise', 'none']\n if (\n typeof ent !== 'object' ||\n ent === null ||\n !kinds.includes(String((ent as { kind?: unknown }).kind))\n ) {\n problems.push(\n `frame.entrance.kind must be one of ${kinds.join(' | ')} (got ${JSON.stringify(ent)})`,\n )\n } else {\n const secs = (ent as { seconds?: unknown }).seconds\n if (secs !== undefined && (!isNum(secs) || secs < 0.2 || secs > 3)) {\n problems.push(\n `frame.entrance.seconds must be 0.2..3 (got ${String(secs)}); absent = 1.2`,\n )\n }\n }\n }\n lintAnim(\n 'frame',\n frame.anim,\n {\n enter: CARD_ENTER_KINDS,\n exit: CARD_EXIT_KINDS,\n idle: null,\n words: false,\n card: true,\n },\n problems,\n )\n if (frame.focusFollow !== undefined && frame.focusFollow !== 'camera') {\n problems.push(\n `frame.focusFollow must be \"camera\" (got ${String(frame.focusFollow)}); it reads under fit: cover only`,\n )\n }\n // --- per-side placement: fractions, a negative side bleeds ---\n const ins = frame.inset\n if (ins !== undefined) {\n if (typeof ins !== 'object' || ins === null || Array.isArray(ins)) {\n problems.push(\n 'frame.inset must be an object of {top, right, bottom, left} fractions',\n )\n } else {\n const sides = ins as Record<string, unknown>\n for (const side of ['top', 'right', 'bottom', 'left']) {\n const v = sides[side]\n if (v !== undefined && (!isNum(v) || v < -2 || v > 0.9)) {\n problems.push(\n `frame.inset.${side} must be a fraction of the frame in -2..0.9 (got ${String(v)}); negative bleeds the card past the edge`,\n )\n }\n }\n const l = isNum(sides.left) ? sides.left : 0\n const r = isNum(sides.right) ? sides.right : 0\n const t = isNum(sides.top) ? sides.top : 0\n const b = isNum(sides.bottom) ? sides.bottom : 0\n if (l + r >= 1 || t + b >= 1) {\n problems.push(\n `frame.inset leaves no room for the card (left+right ${l + r}, top+bottom ${t + b}; each pair must stay under 1)`,\n )\n }\n }\n }\n const ebw = isNum(bw) && bw > 0 && bw <= 24 ? bw : 1.5\n const pad = isNum(frame.padding) ? frame.padding : 0\n if (frame.border && ebw > pad && ins === undefined) {\n warnings.push(\n `frame.borderWidth (${ebw}) is wider than frame.padding (${pad}) — the border grows outward from the card, so the frame edge crops it; raise the padding to at least the width to show the whole stroke`,\n )\n }\n }\n if (\n bgm &&\n bgm.blur !== undefined &&\n (!isNum(bgm.blur) || bgm.blur < 0 || bgm.blur > 100)\n ) {\n problems.push(\n `frame.backgroundMedia.blur must be 0..100 design px (got ${String(bgm.blur)})`,\n )\n }\n\n // --- removed fields (decided 2026-08-03) ---\n // The card's static pose and its V2 effects are gone: a lean is a tilt SPAN\n // on the timeline, nothing else poses the card. Say so instead of ignoring\n // the field, or a doc written against the old schema renders silently\n // without what it asked for.\n if (doc.card !== undefined) {\n problems.push(\n 'card was removed — lean the card with tilt spans (doc.tilt); entrance/exit/float/effect are gone',\n )\n }\n if (frame && frame.vignette !== undefined) {\n problems.push('frame.vignette was removed')\n }\n }\n\n // --- overlays (compositor v2 V1: text clips, OUTPUT-anchored) ---\n const overlays = Array.isArray(doc.overlays) ? doc.overlays : undefined\n if (doc.overlays !== undefined && !overlays) {\n problems.push('overlays must be an array of clips')\n }\n const TRANSITIONS = ['none', 'fade', 'rise']\n const PRESETS = ['title', 'caption', 'label']\n // Where the FOOTAGE ends in output seconds, freezes included (a freeze is a\n // rated piece). A recording's output runs to the end of its last visual\n // clip, on purpose, so words can play after the footage; the same rule means\n // a layer left behind by a trim silently LENGTHENS the render, and the clip\n // ends on bare backdrop with a note floating on nothing. Never a problem\n // (that would refuse every legacy end card); always said.\n let footageEnd: number | null = null\n if (recording && Array.isArray(doc.segments)) {\n try {\n footageEnd = ratedSegments(doc as unknown as ProjectDoc).reduce(\n (a, s) => a + (s.out - s.in) / (s.rate ?? 1),\n 0,\n )\n } catch {\n footageEnd = null\n }\n }\n for (let i = 0; i < (overlays?.length ?? 0); i++) {\n const o = overlays![i]\n const name = `overlays[${i}]`\n if (!isObj(o)) {\n problems.push(`${name} must be an object`)\n continue\n }\n if (\n o.kind !== 'text' &&\n o.kind !== 'image' &&\n o.kind !== 'video' &&\n o.kind !== 'html'\n ) {\n problems.push(\n `${name}.kind must be \"text\" | \"image\" | \"video\" | \"html\" (got ${String(o.kind)})`,\n )\n }\n if (!isNum(o.start) || o.start < 0)\n problems.push(`${name}.start must be ≥ 0 (OUTPUT seconds)`)\n if (!isNum(o.duration) || o.duration <= 0) {\n problems.push(`${name}.duration must be > 0 (seconds)`)\n }\n if (\n footageEnd !== null &&\n footageEnd > 0 &&\n isNum(o.start) &&\n isNum(o.duration)\n ) {\n const over = o.start + o.duration - footageEnd\n // A card that LEAVES when its footage ends is an ending on the ground,\n // made on purpose: a layer past the footage is that ending's words.\n const frameAnim =\n isObj(docIn) && isObj(docIn.frame) && isObj(docIn.frame.anim)\n ? docIn.frame.anim\n : null\n const exit = frameAnim\n ? isObj(frameAnim.exit)\n ? frameAnim.exit.kind\n : frameAnim.exit\n : undefined\n const cardLeaves = exit !== undefined && exit !== 'none'\n if (over > 0.05 && !cardLeaves) {\n warnings.push(\n o.start >= footageEnd\n ? `${name} starts at ${o.start.toFixed(2)}s, after the footage ends (${footageEnd.toFixed(2)}s): it plays over the card's held last frame and lengthens the output by ${over.toFixed(2)}s. A trim moves the footage, never an OUTPUT-anchored layer: re-place it (vos callout with the same --id), put a freeze under it, or, for a closing card on the ground, let the card leave (frame.anim.exit: 'fade')`\n : `${name} ends ${over.toFixed(2)}s after the footage (${footageEnd.toFixed(2)}s): the card holds its last frame under it. Shorten it, put a freeze under it, or, for a closing card on the ground, let the card leave (frame.anim.exit: 'fade')`,\n )\n }\n }\n checkPin(o, name, docIn, recording, problems, warnings)\n if (o.kind === 'text') {\n if (typeof o.text !== 'string')\n problems.push(`${name}.text must be a string`)\n if (typeof o.preset === 'string' && !PRESETS.includes(o.preset)) {\n warnings.push(\n `${name}.preset \"${String(o.preset)}\" is not a known preset (${PRESETS.join('|')}) — falls back to \"title\"`,\n )\n }\n // Emphasis is OPT-IN: asterisks are markers only on a clip carrying\n // `emphasis`. A pair on a clip without it shows as typed, which is\n // right for a literal `*`, so say it rather than refuse it.\n if (o.emphasis !== undefined) {\n const em = o.emphasis as Record<string, unknown> | null\n if (!em || typeof em !== 'object' || Array.isArray(em)) {\n problems.push(\n `${name}.emphasis must be { weight?, color? } ({} turns *markers* on)`,\n )\n } else {\n if (\n em.weight !== undefined &&\n (!isNum(em.weight) || em.weight < 100 || em.weight > 900)\n )\n problems.push(`${name}.emphasis.weight must be 100..900`)\n if (em.color !== undefined && typeof em.color !== 'string')\n problems.push(`${name}.emphasis.color must be a CSS colour`)\n }\n } else if (typeof o.text === 'string' && parseEmphasis(o.text) !== null) {\n warnings.push(\n `${name}.text has *marked* words but no emphasis, so the asterisks show as typed; add emphasis: {} to set them bold (\\\\* keeps one literal)`,\n )\n }\n if (\n o.size !== undefined &&\n (!isNum(o.size) || o.size < 12 || o.size > 200)\n ) {\n problems.push(`${name}.size must be design px in 12..200`)\n }\n if (o.family !== undefined) {\n if (typeof o.family !== 'string' || o.family.length === 0) {\n problems.push(`${name}.family must be a font family name`)\n } else if (!findFontFamily(o.family)) {\n warnings.push(\n `${name}.family \"${String(o.family)}\" is not in the hosted catalog (GET https://vos.so/api/fonts) — the render fleet falls back to the preset font`,\n )\n }\n }\n if (\n o.weight !== undefined &&\n (!isNum(o.weight) || o.weight < 100 || o.weight > 900)\n ) {\n problems.push(`${name}.weight must be a CSS weight in 100..900`)\n }\n if (\n o.align !== undefined &&\n !['left', 'center', 'right'].includes(o.align as string)\n ) {\n problems.push(`${name}.align must be left|center|right`)\n }\n if (\n o.letterSpacing !== undefined &&\n (!isNum(o.letterSpacing) ||\n o.letterSpacing < -10 ||\n o.letterSpacing > 60)\n ) {\n problems.push(`${name}.letterSpacing must be design px in -10..60`)\n }\n if (\n o.lineHeight !== undefined &&\n (!isNum(o.lineHeight) || o.lineHeight < 0.8 || o.lineHeight > 3)\n ) {\n problems.push(`${name}.lineHeight must be a multiplier in 0.8..3`)\n }\n if (o.stroke !== undefined) {\n const rawStroke: unknown = o.stroke\n if (\n typeof rawStroke !== 'object' ||\n rawStroke === null ||\n Array.isArray(rawStroke)\n ) {\n problems.push(`${name}.stroke must be an object { color, width }`)\n } else {\n const sk = rawStroke as Record<string, unknown>\n if (typeof sk.color !== 'string' || sk.color.length === 0) {\n problems.push(`${name}.stroke.color must be a CSS color string`)\n }\n if (!isNum(sk.width) || sk.width < 0.5 || sk.width > 40) {\n problems.push(`${name}.stroke.width must be design px in 0.5..40`)\n }\n }\n }\n if (o.box !== undefined) {\n const raw: unknown = o.box\n if (typeof raw !== 'object' || raw === null || Array.isArray(raw)) {\n problems.push(`${name}.box must be an object { color, … }`)\n } else {\n const bx = raw as Record<string, unknown>\n if (typeof bx.color !== 'string' || bx.color.length === 0) {\n problems.push(`${name}.box.color must be a CSS color string`)\n }\n if (\n bx.opacity !== undefined &&\n (!isNum(bx.opacity) || bx.opacity < 0 || bx.opacity > 1)\n ) {\n problems.push(`${name}.box.opacity must be in 0..1`)\n }\n for (const k of ['paddingX', 'paddingY', 'radius'] as const) {\n const v = bx[k]\n if (v !== undefined && (!isNum(v) || v < 0 || v > 4)) {\n problems.push(\n `${name}.box.${k} must be EMs of the font size in 0..4`,\n )\n }\n }\n }\n }\n if (\n o.maxWidth !== undefined &&\n (!isNum(o.maxWidth) || o.maxWidth < 0.1 || o.maxWidth > 1)\n ) {\n problems.push(\n `${name}.maxWidth must be a FRACTION of the frame width in 0.1..1 (wrap budget; absent = no wrapping)`,\n )\n }\n // TX6 entrance animation: fx owns the entrance when present (`enter`\n // is ignored); exit stays clip-level. Pure f(t) — segmentation and\n // timing are baked at lowering.\n if (o.fx !== undefined) {\n if (!isObj(o.fx)) {\n problems.push(\n `${name}.fx must be { fx, unit?, direction?, stagger?, duration? }`,\n )\n } else {\n const fx = o.fx\n const FX_KINDS = ['fade', 'rise', 'pop', 'blur', 'typewriter']\n const FX_UNITS = ['block', 'line', 'word', 'char']\n const FX_DIRS = ['forward', 'reverse', 'center']\n if (typeof fx.fx !== 'string' || !FX_KINDS.includes(fx.fx)) {\n problems.push(\n `${name}.fx.fx must be ${FX_KINDS.join('|')} (got ${String(fx.fx)})`,\n )\n }\n if (\n fx.unit !== undefined &&\n (typeof fx.unit !== 'string' || !FX_UNITS.includes(fx.unit))\n ) {\n problems.push(`${name}.fx.unit must be ${FX_UNITS.join('|')}`)\n }\n if (\n fx.direction !== undefined &&\n (typeof fx.direction !== 'string' ||\n !FX_DIRS.includes(fx.direction))\n ) {\n problems.push(`${name}.fx.direction must be ${FX_DIRS.join('|')}`)\n }\n if (\n fx.stagger !== undefined &&\n (!isNum(fx.stagger) || fx.stagger < 0 || fx.stagger > 2)\n ) {\n problems.push(\n `${name}.fx.stagger must be seconds between unit starts in 0..2`,\n )\n }\n if (\n fx.duration !== undefined &&\n (!isNum(fx.duration) || fx.duration < 0.05 || fx.duration > 2)\n ) {\n problems.push(`${name}.fx.duration must be seconds in 0.05..2`)\n }\n if (\n fx.fx === 'typewriter' &&\n (fx.unit === undefined || fx.unit === 'block')\n ) {\n warnings.push(\n `${name}.fx: typewriter with unit \"block\" reveals everything at once — unit \"char\" or \"word\" is its nature`,\n )\n }\n if (o.enter !== undefined && o.enter !== 'none') {\n warnings.push(\n `${name}: fx owns the entrance — the \"enter\" transition is ignored while fx is set`,\n )\n }\n }\n }\n }\n if (o.kind === 'image' || o.kind === 'video') {\n if (o.fx !== undefined) {\n problems.push(`${name}.fx is text-only (media clips have enter/exit)`)\n }\n // A layer that shows a document media: the reference must name one\n // (`media:` alone is the primary), and its card carries card fields.\n if (typeof o.key === 'string' && o.key.startsWith('media:')) {\n const ref = o.key.slice('media:'.length)\n const ids = new Set(\n (Array.isArray((doc as { media?: unknown }).media)\n ? ((doc as { media: unknown[] }).media as { id?: unknown }[])\n : []\n ).map((m) => (typeof m.id === 'string' ? m.id : '')),\n )\n if (ref !== '' && !ids.has(ref))\n problems.push(\n `${name}.key names media \"${ref}\", which is not one of media[].id (media: alone is the primary)`,\n )\n }\n const lcf = (o as { frame?: unknown }).frame\n if (lcf !== undefined) {\n if (!isObj(lcf)) {\n problems.push(`${name}.frame must be an object (the layer's card)`)\n } else {\n const LCF = [\n 'browserBar',\n 'lean',\n 'shadow',\n 'shadowContact',\n 'shadowColor',\n 'cursor',\n ]\n for (const k of Object.keys(lcf))\n if (!LCF.includes(k))\n problems.push(\n `${name}.frame.${k}: not a layer card field (${LCF.join(', ')})`,\n )\n const lean = (lcf as { lean?: unknown }).lean\n if (\n lean !== undefined &&\n (!isObj(lean) ||\n !isNum((lean as { rx?: unknown }).rx) ||\n !isNum((lean as { ry?: unknown }).ry))\n )\n problems.push(`${name}.frame.lean must be { rx, ry } in degrees`)\n }\n }\n if (typeof o.key !== 'string' || o.key.length === 0) {\n problems.push(\n `${name}.key must be a non-empty media URL or take-dir file (e.g. \"/logo.png\")`,\n )\n }\n if (\n o.width !== undefined &&\n (!isNum(o.width) || o.width <= 0 || o.width > 1)\n ) {\n problems.push(\n `${name}.width must be a fraction of the frame width in (0..1] (got ${String(o.width)})`,\n )\n }\n if (o.radius !== undefined && (!isNum(o.radius) || o.radius < 0)) {\n problems.push(`${name}.radius must be ≥ 0 design px`)\n }\n if (\n o.opacity !== undefined &&\n (!isNum(o.opacity) || o.opacity < 0 || o.opacity > 1)\n ) {\n problems.push(`${name}.opacity must be 0..1`)\n }\n }\n if (o.kind === 'html') {\n // An HTML layer keeps its SOURCE: markup and CSS laid out in a design\n // box, rasterized in the page. The XML rules, the wall clock, the\n // faces and the media fields it refuses are the pure gate's\n // (`htmlLayerProblems`), the same words the studio panel shows.\n if (typeof o.html !== 'string') {\n problems.push(`${name}.html must be the layer's markup (a string)`)\n }\n if (o.css !== undefined && typeof o.css !== 'string') {\n problems.push(`${name}.css must be a string of CSS`)\n }\n const box = isObj(o.box) ? o.box : undefined\n if (\n !box ||\n !isNum(box.width) ||\n !isNum(box.height) ||\n box.width <= 0 ||\n box.height <= 0\n ) {\n problems.push(\n `${name}.box must be { width, height } in design px, both > 0 (the 1080p frame is 1920 wide)`,\n )\n }\n if (o.bleed !== undefined && (!isNum(o.bleed) || o.bleed < 0)) {\n problems.push(\n `${name}.bleed must be ≥ 0 design px (absent = derived from the CSS's shadows)`,\n )\n }\n if (o.fonts !== undefined) {\n if (!Array.isArray(o.fonts)) {\n problems.push(\n `${name}.fonts must be an array of { family, url, weight?, style? }`,\n )\n } else {\n o.fonts.forEach((f, fi) => {\n if (\n !isObj(f) ||\n typeof f.family !== 'string' ||\n typeof f.url !== 'string' ||\n !/^https?:\\/\\//.test(f.url)\n )\n problems.push(\n `${name}.fonts[${fi}] must be { family, url (https), weight?, style? }: a face the catalog does not host. A hosted family needs no entry; name it in the CSS`,\n )\n })\n }\n }\n if (\n o.width !== undefined &&\n (!isNum(o.width) || o.width <= 0 || o.width > 1)\n ) {\n problems.push(\n `${name}.width must be a fraction of the frame width in (0..1] (got ${String(o.width)}; absent = the design size)`,\n )\n }\n if (o.live !== undefined && typeof o.live !== 'boolean') {\n problems.push(\n `${name}.live must be true or absent: a live layer is re-rasterized per frame at clip-local t (its @keyframes scrubbed, its {{t}} and {{data.…}} filled)`,\n )\n }\n if (o.data !== undefined) {\n const bad =\n !isObj(o.data) ||\n Object.values(o.data).some(\n (v) => !['string', 'number', 'boolean'].includes(typeof v),\n )\n if (bad)\n problems.push(\n `${name}.data must be a map of strings, numbers or booleans: the values a live layer's {{data.<name>}} placeholders read`,\n )\n }\n if (\n o.opacity !== undefined &&\n (!isNum(o.opacity) || o.opacity < 0 || o.opacity > 1)\n ) {\n problems.push(`${name}.opacity must be 0..1`)\n }\n if (typeof o.html === 'string') {\n for (const p of htmlLayerProblems(o as never)) {\n ;(p.level === 'problem' ? problems : warnings).push(\n `${name}: ${p.message}`,\n )\n }\n }\n }\n const tf = isObj(o.transform) ? o.transform : undefined\n if (!tf) {\n problems.push(\n `${name}.transform must be { x, y, scale, rotation } — x/y are FRACTIONS of the frame [0..1] (0.5/0.5 = center; the zoom cx/cy convention), aspect-stable`,\n )\n } else {\n if (!isNum(tf.x) || !isNum(tf.y)) {\n problems.push(\n `${name}.transform.x/y must be numbers (frame fractions [0..1])`,\n )\n } else {\n // The cx/cy pixel trap: coords are FRACTIONS, not pixels.\n if (Math.abs(tf.x) > 2 || Math.abs(tf.y) > 2) {\n problems.push(\n `${name}.transform.x/y look like PIXELS (${String(tf.x)}, ${String(tf.y)}) — they are FRACTIONS of the frame [0..1] (center = 0.5/0.5, lower-third y ≈ 0.82)`,\n )\n } else if (tf.x < -0.1 || tf.x > 1.1 || tf.y < -0.1 || tf.y > 1.1) {\n warnings.push(\n `${name}.transform.x/y (${String(tf.x)}, ${String(tf.y)}) sit outside the frame [0..1] — the clip may be partly or fully invisible`,\n )\n }\n }\n if (tf.scale !== undefined && (!isNum(tf.scale) || tf.scale <= 0)) {\n problems.push(`${name}.transform.scale must be > 0`)\n }\n if (tf.rotation !== undefined && !isNum(tf.rotation)) {\n problems.push(`${name}.transform.rotation must be degrees (number)`)\n }\n }\n for (const key of ['enter', 'exit'] as const) {\n const v = o[key]\n if (\n v !== undefined &&\n (typeof v !== 'string' || !TRANSITIONS.includes(v))\n ) {\n problems.push(`${name}.${key} must be one of ${TRANSITIONS.join('|')}`)\n }\n }\n if (o.enter !== undefined || o.exit !== undefined || o.fx !== undefined)\n warnings.push(\n `${name}: enter, exit and fx are legacy spellings; write anim.enter / anim.exit`,\n )\n lintAnim(\n name,\n o.anim,\n o.kind === 'text'\n ? {\n enter: TEXT_ENTER_KINDS,\n exit: TEXT_EXIT_KINDS,\n idle: null,\n words: true,\n }\n : {\n enter: MEDIA_ENTER_KINDS,\n exit: MEDIA_EXIT_KINDS,\n idle: null,\n words: false,\n },\n problems,\n )\n lintFrom(name, o.from, problems)\n // Pose keyframes: clip-local, fractions, opacity as a multiplier.\n if (o.motion !== undefined) {\n if (!Array.isArray(o.motion)) {\n problems.push(`${name}.motion must be an array of poses`)\n } else {\n const clipDur = isNum(o.duration) ? o.duration : 0\n o.motion.filter(isObj).forEach((p, pi) => {\n const pn = `${name}.motion[${pi}]`\n if (!isNum(p.at) || p.at < -EPS) {\n problems.push(\n `${pn}.at must be ≥ 0 CLIP-LOCAL seconds (0 = the clip's start; poses ride along when the clip moves)`,\n )\n } else if (clipDur > 0 && p.at > clipDur + EPS) {\n warnings.push(\n `${pn}.at=${String(p.at)}s is past the clip's ${clipDur.toFixed(2)}s duration (clamped to the end)`,\n )\n }\n for (const axis of ['x', 'y'] as const) {\n const v = p[axis]\n if (v === undefined) continue\n if (!isNum(v)) {\n problems.push(`${pn}.${axis} must be a number (frame fraction)`)\n } else if (Math.abs(v) > 2) {\n problems.push(\n `${pn}.${axis} looks like PIXELS (${String(v)}) — pose coords are FRACTIONS of the frame [0..1], the transform.x/y convention`,\n )\n }\n }\n if (p.scale !== undefined && (!isNum(p.scale) || p.scale <= 0)) {\n problems.push(`${pn}.scale must be > 0`)\n }\n if (p.rotation !== undefined && !isNum(p.rotation)) {\n problems.push(`${pn}.rotation must be degrees (number)`)\n }\n if (\n p.opacity !== undefined &&\n (!isNum(p.opacity) || p.opacity < 0 || p.opacity > 1)\n ) {\n problems.push(\n `${pn}.opacity must be 0..1 (a multiplier on the clip's alpha)`,\n )\n }\n })\n }\n }\n }\n\n // --- object clips (V3 — the drafted V4 spec) ---\n const objects = Array.isArray(doc.objects) ? doc.objects : undefined\n if (doc.objects !== undefined && !objects)\n problems.push('objects must be an array of clips')\n const SHAPES = ['cube', 'sphere', 'torus', 'knot']\n const T3_MATERIALS = ['standard', 'metal', 'glass', 'neon']\n for (let i = 0; i < (objects?.length ?? 0); i++) {\n const o = objects![i]\n const name = `objects[${i}]`\n if (!isObj(o)) {\n problems.push(`${name} must be an object`)\n continue\n }\n const asset = isObj(o.asset) ? o.asset : undefined\n if (!asset)\n problems.push(\n `${name}.asset must be { kind: \"primitive\", shape } | { kind: \"gltf\", key } | { kind: \"text3d\", text }`,\n )\n else if (asset.kind === 'primitive') {\n if (typeof asset.shape !== 'string' || !SHAPES.includes(asset.shape)) {\n problems.push(`${name}.asset.shape must be one of ${SHAPES.join('|')}`)\n }\n } else if (asset.kind === 'gltf') {\n if (typeof asset.key !== 'string' || !asset.key)\n problems.push(\n `${name}.asset.key must be a non-empty URL/file (e.g. \"/model.glb\")`,\n )\n } else if (asset.kind === 'text3d') {\n // TX7: extruded text from the hosted typeface catalog. Materials are\n // preset names only — the fleet-audited set (single-sided, no\n // dispersion); depth is a fraction of the glyph height.\n if (typeof asset.text !== 'string' || !asset.text.trim())\n problems.push(`${name}.asset.text must be a non-empty string`)\n if (asset.typeface !== undefined) {\n if (typeof asset.typeface !== 'string')\n problems.push(`${name}.asset.typeface must be a string`)\n else if (!findTypeface(asset.typeface))\n warnings.push(\n `${name}.asset.typeface \"${asset.typeface}\" is not in the 3D typeface catalog — falls back to the house face (${TYPEFACE_CATALOG.map((t) => t.family).join(', ')})`,\n )\n }\n if (\n asset.material !== undefined &&\n !T3_MATERIALS.includes(asset.material as string)\n ) {\n problems.push(\n `${name}.asset.material must be ${T3_MATERIALS.join('|')}`,\n )\n }\n if (\n asset.depth !== undefined &&\n (!isNum(asset.depth) || asset.depth < 0.02 || asset.depth > 1)\n ) {\n problems.push(\n `${name}.asset.depth must be a fraction of the glyph height in 0.02..1`,\n )\n }\n if (asset.bevel !== undefined && typeof asset.bevel !== 'boolean')\n problems.push(`${name}.asset.bevel must be a boolean`)\n } else\n problems.push(\n `${name}.asset.kind must be \"primitive\" | \"gltf\" | \"text3d\"`,\n )\n const tf = isObj(o.transform3d) ? o.transform3d : undefined\n if (!tf)\n problems.push(\n `${name}.transform3d must be { x, y, z, rx, ry, rz, scale } — x/y are FRACTIONS of the frame [0..1], z = world units toward the camera, scale = fraction of frame height`,\n )\n else {\n if (!isNum(tf.x) || !isNum(tf.y))\n problems.push(\n `${name}.transform3d.x/y must be numbers (frame fractions [0..1])`,\n )\n else if (Math.abs(tf.x) > 2 || Math.abs(tf.y) > 2) {\n problems.push(\n `${name}.transform3d.x/y look like PIXELS (${String(tf.x)}, ${String(tf.y)}) — they are FRACTIONS of the frame (center = 0.5/0.5)`,\n )\n }\n if (tf.z !== undefined && (!isNum(tf.z) || tf.z < -2 || tf.z > 2.5))\n problems.push(\n `${name}.transform3d.z must be -2..2.5 world units (0 = the card plane; + toward camera)`,\n )\n if (\n tf.scale !== undefined &&\n (!isNum(tf.scale) || tf.scale <= 0 || tf.scale > 1)\n )\n problems.push(\n `${name}.transform3d.scale must be a fraction of the frame height in (0..1]`,\n )\n }\n const span = o.span\n if (span !== undefined) {\n if (\n !isObj(span) ||\n !isNum(span.start) ||\n span.start < 0 ||\n !isNum(span.duration) ||\n span.duration <= 0\n ) {\n problems.push(\n `${name}.span must be { start ≥ 0, duration > 0 } (OUTPUT seconds)`,\n )\n }\n }\n if (\n o.animation !== undefined &&\n o.animation !== null &&\n o.animation !== 'spin' &&\n o.animation !== 'float'\n ) {\n problems.push(`${name}.animation must be \"spin\" | \"float\" | null`)\n }\n if (o.animation !== undefined)\n warnings.push(`${name}.animation is a legacy spelling; write anim.idle`)\n lintAnim(\n name,\n o.anim,\n {\n enter: MEDIA_ENTER_KINDS,\n exit: MEDIA_EXIT_KINDS,\n idle: IDLE_KINDS,\n words: false,\n },\n problems,\n )\n lintFrom(name, o.from, problems)\n // Pose keyframes: clip-local over transform3d; presets compose.\n if (o.motion !== undefined) {\n if (!Array.isArray(o.motion)) {\n problems.push(`${name}.motion must be an array of poses`)\n } else {\n o.motion.filter(isObj).forEach((p, pi) => {\n const pn = `${name}.motion[${pi}]`\n if (!isNum(p.at) || p.at < -EPS) {\n problems.push(\n `${pn}.at must be ≥ 0 CLIP-LOCAL seconds (from the clip's span start)`,\n )\n }\n for (const axis of ['x', 'y'] as const) {\n const v = p[axis]\n if (v === undefined) continue\n if (!isNum(v)) {\n problems.push(`${pn}.${axis} must be a number (frame fraction)`)\n } else if (Math.abs(v) > 2) {\n problems.push(\n `${pn}.${axis} looks like PIXELS (${String(v)}) — pose coords are FRACTIONS of the frame [0..1]`,\n )\n }\n }\n if (p.z !== undefined && (!isNum(p.z) || p.z < -2 || p.z > 2.5)) {\n problems.push(`${pn}.z must be -2..2.5 world units`)\n }\n for (const ax of ['rx', 'ry', 'rz'] as const) {\n if (p[ax] !== undefined && !isNum(p[ax])) {\n problems.push(`${pn}.${ax} must be degrees (number)`)\n }\n }\n if (\n p.scale !== undefined &&\n (!isNum(p.scale) || p.scale <= 0 || p.scale > 1)\n ) {\n problems.push(\n `${pn}.scale must be a fraction of the frame height in (0..1]`,\n )\n }\n })\n }\n }\n }\n\n // --- export block ---\n if (isObj(doc.export)) {\n const resolution = doc.export.resolution as ExportResolution\n const validResolution = EXPORT_RESOLUTION_OPTIONS.includes(resolution)\n if (!validResolution) {\n problems.push(\n `export.resolution \"${String(doc.export.resolution)}\" invalid — one of: ${EXPORT_RESOLUTION_OPTIONS.join(' | ')}`,\n )\n }\n if (doc.export.fps !== 30 && doc.export.fps !== 60) {\n problems.push(\n `export.fps must be 30 or 60 (got ${String(doc.export.fps)})`,\n )\n }\n if (validResolution && isNum(meta.durationMs)) {\n const recommended = recommendedExportResolution(docIn as ProjectDoc)\n const want = EXPORT_RESOLUTION_OPTIONS.indexOf(resolution)\n const rec = EXPORT_RESOLUTION_OPTIONS.indexOf(recommended)\n if (want > rec) {\n const capW = isNum(meta.captureWidth) ? meta.captureWidth : meta.width\n warnings.push(\n `export.resolution \"${resolution}\" upscales the footage (capture is ${String(capW)}px wide — \"${recommended}\" matches the recording)`,\n )\n }\n }\n }\n\n if (recording)\n framingWarnings(docIn as ProjectDoc, doc, zoom, overlays ?? [], warnings)\n return { problems, warnings }\n}\n\ninterface DownEvent {\n t: number\n rect: { x: number; y: number; w: number; h: number }\n}\n\n/** `down` events carrying a target rect, in seconds — the evidence. */\nfunction clicksWithRects(source: Json): DownEvent[] {\n const cursor = Array.isArray(source.cursor) ? source.cursor : []\n const out: DownEvent[] = []\n for (const e of cursor) {\n if (!isObj(e) || e.type !== 'down' || !isNum(e.t) || !isObj(e.rect))\n continue\n const r = e.rect\n if (!isNum(r.x) || !isNum(r.y) || !isNum(r.w) || !isNum(r.h)) continue\n out.push({ t: e.t / 1000, rect: { x: r.x, y: r.y, w: r.w, h: r.h } })\n }\n return out\n}\n\n/**\n * The framing checks — advisory, never a problem, never a\n * throw: a zoom must contain what was clicked under it (the planner solves\n * this from the rect; a hand- or agent-written span is re-checked against\n * the same evidence), and a caption must not sit over the thing being\n * clicked. Both need a cursor track with rects; a browser-recorder take\n * has none and warns nothing.\n */\nconst PIN_SIDES = ['auto', 'right', 'left', 'below', 'above']\nconst PIN_MARKS = ['none', 'ring', 'underline']\n\n/**\n * A layer's pin names its referent, and a pin that names nothing is a\n * problem said in words (a silently ignored pin is a layer that claims to\n * be a callout and is placed like a caption). A pin whose referent may\n * have moved under the layer (a later scroll or navigation inside the\n * layer's window) is a warning.\n */\nfunction checkPin(\n o: Json,\n name: string,\n docIn: StudioDoc,\n recording: boolean,\n problems: string[],\n warnings: string[],\n): void {\n if (o.pin === undefined) return\n if (!isObj(o.pin)) {\n problems.push(\n `${name}.pin must be { step | press | rect, side?, gap?, mark?, leader?, color? }`,\n )\n return\n }\n const p = o.pin\n const named = ['step', 'press', 'rect'].filter((k) => p[k] !== undefined)\n if (named.length !== 1) {\n problems.push(\n `${name}.pin names its referent by exactly one of step (a recorder step id or index), press (a source second) or rect (video fractions)${named.length ? ` — got ${named.join(' and ')}` : ''}`,\n )\n return\n }\n if (\n p.step !== undefined &&\n typeof p.step !== 'string' &&\n !(isNum(p.step) && Number.isInteger(p.step) && p.step >= 0)\n ) {\n problems.push(\n `${name}.pin.step must be a step id (string) or index (integer ≥ 0)`,\n )\n }\n if (p.press !== undefined && !isNum(p.press))\n problems.push(`${name}.pin.press must be a source second (number)`)\n if (p.rect !== undefined) {\n const r = isObj(p.rect) ? p.rect : null\n if (!r || !isNum(r.x) || !isNum(r.y) || !isNum(r.w) || !isNum(r.h)) {\n problems.push(`${name}.pin.rect must be { x, y, w, h }`)\n } else if (Math.abs(r.x) > 2 || Math.abs(r.y) > 2 || r.w > 2 || r.h > 2) {\n problems.push(\n `${name}.pin.rect looks like PIXELS (${String(r.x)}, ${String(r.y)}, ${String(r.w)}×${String(r.h)}) — it is FRACTIONS of the video frame [0..1] (the zoom cx/cy convention)`,\n )\n } else if (r.w <= 0 || r.h <= 0) {\n problems.push(`${name}.pin.rect must have w > 0 and h > 0`)\n }\n }\n if (p.side !== undefined && !PIN_SIDES.includes(p.side as string))\n problems.push(`${name}.pin.side must be one of ${PIN_SIDES.join(' | ')}`)\n if (p.gap !== undefined && (!isNum(p.gap) || p.gap < 0))\n problems.push(`${name}.pin.gap must be design px ≥ 0`)\n if (p.mark !== undefined && !PIN_MARKS.includes(p.mark as string))\n problems.push(`${name}.pin.mark must be one of ${PIN_MARKS.join(' | ')}`)\n if (p.leader !== undefined && typeof p.leader !== 'boolean')\n problems.push(`${name}.pin.leader must be true or false`)\n if (p.color !== undefined && typeof p.color !== 'string')\n problems.push(`${name}.pin.color must be a CSS colour string`)\n if (problems.some((m) => m.startsWith(`${name}.pin`))) return\n if (!recording) {\n problems.push(\n `${name}.pin names something on a recording's page; a program has no referents — place the layer with transform`,\n )\n return\n }\n const doc = docIn as ProjectDoc\n const steps = doc.source.meta.steps ?? []\n if (p.step !== undefined) {\n const step = findStep(steps, p.step as string | number)\n if (!step) {\n const known = steps\n .filter((s) => s.selector)\n .map((s) => (s.id !== undefined ? s.id : String(s.step)))\n problems.push(\n `${name}.pin.step \"${String(p.step)}\" is not a step of this take${known.length ? ` — steps with an element: ${known.join(', ')}` : ' — the take has no step timeline (a human recording); pin by press or rect'}`,\n )\n return\n }\n if (step.skipped) {\n problems.push(\n `${name}.pin.step \"${String(p.step)}\" was skipped at record time (its selector never became visible), so it has no element to point at`,\n )\n return\n }\n }\n let ref\n try {\n ref = pinReferent(doc, p as unknown as OverlayPin)\n } catch {\n ref = null\n }\n if (!ref) {\n problems.push(\n p.step !== undefined\n ? `${name}.pin.step \"${String(p.step)}\" has no element rect and no press inside its window (a wait, scroll or move step touches nothing) — pin a hover, click, type or drag step, or a press`\n : p.press !== undefined\n ? `${name}.pin.press ${String(p.press)}s has no press with an element rect within half a second — the presses are the cursor track's down events`\n : `${name}.pin.rect could not be read`,\n )\n return\n }\n // The referent was measured at one moment; a later scroll or navigation\n // inside the layer's window moves what was under it.\n if (ref.at !== null && isNum(o.start) && isNum(o.duration)) {\n const rated = ratedSegments(doc)\n for (const s of steps) {\n if (s.tStart <= ref.at) continue\n if (s.do !== 'scroll' && !s.navigated) continue\n const out = spanOutputExtent(rated, s.tStart, s.tEnd)\n if (!out) continue\n if (out.start < o.start + o.duration && out.end > o.start) {\n warnings.push(\n `${name} is pinned to something measured at ${ref.at.toFixed(1)}s, but ${s.do === 'scroll' ? 'a scroll' : 'a navigation'} at ${s.tStart.toFixed(1)}s (output ${out.start.toFixed(1)}s) falls inside the layer's window — the referent may have moved; end the layer before it`,\n )\n break\n }\n }\n }\n}\n\nfunction framingWarnings(\n docIn: ProjectDoc,\n doc: Json,\n zoom: Json[],\n overlays: unknown[],\n warnings: string[],\n): void {\n try {\n const source = isObj(doc.source) ? doc.source : {}\n const meta = isObj(source.meta) ? source.meta : {}\n const w = isNum(meta.width) ? meta.width : 0\n const h = isNum(meta.height) ? meta.height : 0\n if (!(w > 0) || !(h > 0)) return\n const clicks = clicksWithRects(source)\n if (!clicks.length) return\n const layout = docCardLayout(docIn)\n\n for (const z of zoom) {\n if (\n !isNum(z.in) ||\n !isNum(z.out) ||\n !isNum(z.level) ||\n !isNum(z.cx) ||\n !isNum(z.cy) ||\n z.level <= 1.001\n )\n continue\n const zin = z.in\n const zout = z.out\n const under = clicks.filter((c) => c.t >= zin && c.t <= zout)\n if (!under.length) continue\n let x0 = Infinity\n let y0 = Infinity\n let x1 = -Infinity\n let y1 = -Infinity\n for (const c of under) {\n x0 = Math.min(x0, c.rect.x / w)\n y0 = Math.min(y0, c.rect.y / h)\n x1 = Math.max(x1, (c.rect.x + c.rect.w) / w)\n y1 = Math.max(y1, (c.rect.y + c.rect.h) / h)\n }\n const rect = { x: x0, y: y0, w: x1 - x0, h: y1 - y0 }\n if (\n !zoomCoversRect(\n {\n level: z.level,\n cx: z.cx,\n cy: z.cy,\n screen: z.screen as { x: number; y: number } | undefined,\n focusMode: z.focusMode as string | undefined,\n },\n rect,\n layout,\n 0.02,\n cameraModel(docIn.frame),\n )\n ) {\n // The presses under a span must share its window. When they cannot\n // at any level worth zooming to, no cx/cy helps: the span is two\n // beats, and the advice is the split (the planner now makes it).\n const together = unionFitLevel(\n { x: x0 * w, y: y0 * h, w: rect.w * w, h: rect.h * h },\n w,\n h,\n )\n const fix =\n together < 1.2\n ? `the ${under.length} presses under it do not share one window at any zoom, so split it, one span per press (vos plan replans auto spans)`\n : together < z.level\n ? `lower the level to ${together.toFixed(2)}× or below, or split the span`\n : `move cx/cy toward it`\n warnings.push(\n `${spanName('zoom', z)}: points beside what was clicked at ${under[0].t.toFixed(1)}s — the target (center ${((x0 + x1) / 2).toFixed(2)}, ${((y0 + y1) / 2).toFixed(2)}) sits outside the visible window; ${fix}`,\n )\n }\n }\n\n // A layer's BOX against the clicked element as the CAMERA shows it at\n // the click's output moment, for every kind: the old check read a\n // caption's anchor point against the rect at rest, so a card beside its\n // anchor point covered the target under a zoom and warned nothing.\n // A pinned layer sits beside its referent by construction; it reports\n // only when the frame had no room for it there.\n const rated = ratedSegments(docIn)\n const camera = cameraModel(docIn.frame)\n const zoomTrack = docZoomTrack(docIn)\n const pins = resolvePins(docIn, layout, camera, zoomTrack)\n overlays.forEach((o, i) => {\n if (!isObj(o) || !isNum(o.start) || !isNum(o.duration)) return\n const tf = isObj(o.transform) ? o.transform : null\n if (!tf || !isNum(tf.x) || !isNum(tf.y)) return\n const pinned = pins.get(String(o.id))\n // An unpinned callout-shaped layer (html or media) that is ABOUT a\n // step: its words name the step's element, or its box sits beside the\n // element as the camera shows it then. Sharing the step's window is not\n // enough: every caption in a product video shares one with something.\n if (\n !pinned &&\n o.pin === undefined &&\n (o.kind === 'html' || o.kind === 'image' || o.kind === 'video')\n ) {\n const words = layerWords(o)\n let layerBox: { x: number; y: number; w: number; h: number } | null =\n null\n try {\n const b = pinBox(o as unknown as OverlayClip, layout)\n layerBox = {\n x: tf.x * layout.W - b.w / 2,\n y: tf.y * layout.H - b.h / 2,\n w: b.w,\n h: b.h,\n }\n } catch {\n layerBox = null\n }\n const about: { step: string; why: string }[] = []\n for (const c of pinCandidates(docIn, {\n start: o.start,\n duration: o.duration,\n })) {\n const named = c.selector\n ? selectorLabelWords(c.selector).filter((x) => words.has(x))\n : []\n if (named.length) {\n about.push({\n step: String(c.step),\n why: `its words name ${c.step}'s element (\"${named.join(' ')}\")`,\n })\n continue\n }\n if (!layerBox) continue\n let ref\n try {\n ref = pinReferent(docIn, { step: c.step } as OverlayPin)\n } catch {\n ref = null\n }\n // A SURFACE (a chart, a canvas, a panel) is beside everything on\n // it, so nearness says nothing about what a layer is about; only\n // its words can.\n if (!ref || ref.rect.w * ref.rect.h > PIN_SURFACE_AREA) continue\n const target = pinRectOnScreen(\n ref.rect,\n c.output.start,\n layout,\n camera,\n zoomTrack,\n )\n const dx = Math.max(\n 0,\n target.x - (layerBox.x + layerBox.w),\n layerBox.x - (target.x + target.w),\n )\n const dy = Math.max(\n 0,\n target.y - (layerBox.y + layerBox.h),\n layerBox.y - (target.y + target.h),\n )\n if (Math.hypot(dx, dy) <= PIN_NEAR_FRACTION * layout.H) {\n about.push({\n step: String(c.step),\n why: `it sits beside ${c.step}'s element`,\n })\n }\n }\n if (about.length) {\n warnings.push(\n `overlays[${i}] is not pinned, but ${about[0].why} — a callout about it says so, and follows it through the camera: pin: { step: \"${about[0].step}\" }`,\n )\n }\n }\n if (pinned) {\n if (pinned.clamped > 4) {\n warnings.push(\n `overlays[${i}] is pinned ${pinned.side} of its referent but the frame has no room there — it sits ${Math.round(pinned.clamped)} design px off; a smaller box, another side, or a lower zoom level keeps it beside what it names. A pin resolves THROUGH the camera, so author the zoom first: a callout composed before it is measured against a frame the viewer never sees`,\n )\n }\n return\n }\n let box: { w: number; h: number }\n try {\n box = pinBox(o as unknown as OverlayClip, layout)\n } catch {\n return\n }\n for (const c of clicks) {\n const out = spanOutputExtent(rated, c.t, c.t + 0.001)\n if (!out || out.start < o.start || out.start > o.start + o.duration)\n continue\n const target = pinRectOnScreen(\n {\n x: c.rect.x / w,\n y: c.rect.y / h,\n w: c.rect.w / w,\n h: c.rect.h / h,\n },\n out.start,\n layout,\n camera,\n zoomTrack,\n )\n const L = {\n x: tf.x * layout.W - box.w / 2,\n y: tf.y * layout.H - box.h / 2,\n w: box.w,\n h: box.h,\n }\n const overlaps =\n L.x < target.x + target.w &&\n L.x + L.w > target.x &&\n L.y < target.y + target.h &&\n L.y + L.h > target.y\n if (overlaps) {\n warnings.push(\n `overlays[${i}] sits over the thing being clicked at ${c.t.toFixed(1)}s (output ${out.start.toFixed(1)}s) — pin it to that step (pin: { step }) so it sits beside the target and follows it, or move it off`,\n )\n break\n }\n }\n })\n } catch {\n // Framing is advisory: a malformed doc is reported by the checks above.\n }\n}\n","/**\n * Remote-media probing for `vos validate` — the loud-failure sibling of the\n * dangling-reference ladder. A doc or config that references a\n * hosted file (a poster's shot, a backdrop loop, an audio bed) can go\n * quietly broken when that file is deleted: the render carries on without\n * it and nothing says so. Validate is the next touch, so validate probes.\n *\n * The COLLECTOR is pure and unit-tested; the PROBE is best-effort network:\n * an unreachable URL (>=400) is a PROBLEM in words, a failed probe (offline,\n * DNS, timeout) is a WARNING — validation must still work on a plane.\n */\n\nconst MEDIA_EXT =\n /\\.(png|jpe?g|webp|gif|webm|mp4|mov|mp3|wav|m4a|ogg|glb|gltf|hdr|exr|woff2?)($|\\?)/i\n\nconst isRemote = (v: unknown): v is string =>\n typeof v === 'string' && /^https?:\\/\\//i.test(v)\n\n/** A remote URL that plausibly names media bytes (an asset route or a media\n * extension) — never a page, a docs link, or an API endpoint. */\nconst isRemoteMedia = (v: unknown): v is string =>\n isRemote(v) && (/\\/api\\/assets\\/[^/]+\\/file/i.test(v) || MEDIA_EXT.test(v))\n\nconst isObj = (v: unknown): v is Record<string, unknown> =>\n typeof v === 'object' && v !== null && !Array.isArray(v)\n\n/**\n * Every remote media URL a doc references: the backdrop loop, image/video\n * overlay keys, audio clip keys. Local take-dir keys (\"/music.mp3\") and\n * blob/data URLs are not probeable and not collected.\n */\nexport function collectDocMediaUrls(doc: unknown): string[] {\n if (!isObj(doc)) return []\n const urls: string[] = []\n const frame = doc.frame\n if (isObj(frame) && isObj(frame.backgroundMedia)) {\n const key = frame.backgroundMedia.key\n if (isRemoteMedia(key)) urls.push(key)\n }\n for (const list of [doc.overlays, doc.audio]) {\n if (!Array.isArray(list)) continue\n for (const clip of list) {\n if (isObj(clip) && isRemoteMedia(clip.key)) urls.push(clip.key)\n if (isObj(clip) && isRemoteMedia(clip.src)) urls.push(clip.src)\n }\n }\n return [...new Set(urls)]\n}\n\n/**\n * Every remote media URL a CONFIG references: element srcs (image/video/svg\n * by URL), font files, and any data value that names hosted media (the\n * poster family's shotUrl, a model URL knob).\n */\nexport function collectConfigMediaUrls(config: unknown): string[] {\n if (!isObj(config)) return []\n const urls: string[] = []\n if (Array.isArray(config.elements)) {\n for (const el of config.elements) {\n if (isObj(el) && isRemoteMedia(el.src)) urls.push(el.src)\n }\n }\n if (Array.isArray(config.fonts)) {\n for (const f of config.fonts) {\n if (isObj(f) && isRemote(f.url)) urls.push(f.url)\n }\n }\n if (isObj(config.data)) {\n for (const v of Object.values(config.data)) {\n if (isRemoteMedia(v)) urls.push(v)\n }\n }\n return [...new Set(urls)]\n}\n\nexport interface MediaProbeResult {\n url: string\n /** true = reachable · false = the server answered >=400 · null = probe failed (offline, timeout) */\n ok: boolean | null\n status?: number\n error?: string\n}\n\nconst PROBE_CAP = 16\nconst PROBE_TIMEOUT_MS = 5000\n\nasync function probeOne(url: string): Promise<MediaProbeResult> {\n const attempt = async (method: 'HEAD' | 'GET') => {\n const ctl = new AbortController()\n const timer = setTimeout(() => ctl.abort(), PROBE_TIMEOUT_MS)\n try {\n return await fetch(url, {\n method,\n signal: ctl.signal,\n headers: method === 'GET' ? { range: 'bytes=0-0' } : undefined,\n })\n } finally {\n clearTimeout(timer)\n }\n }\n try {\n let res = await attempt('HEAD')\n // Some hosts refuse HEAD; one ranged GET settles it without the bytes.\n if (res.status === 405 || res.status === 501) res = await attempt('GET')\n return { url, ok: res.status < 400, status: res.status }\n } catch (e) {\n return { url, ok: null, error: e instanceof Error ? e.message : String(e) }\n }\n}\n\n/** Probe up to PROBE_CAP urls in parallel. */\nexport async function probeMediaUrls(\n urls: string[],\n): Promise<MediaProbeResult[]> {\n return Promise.all(urls.slice(0, PROBE_CAP).map(probeOne))\n}\n\n/** Fold probe results into validate's problems/warnings, in words. */\nexport function mediaProbeLints(results: MediaProbeResult[]): {\n problems: string[]\n warnings: string[]\n} {\n const problems: string[] = []\n const warnings: string[] = []\n for (const r of results) {\n if (r.ok === false) {\n problems.push(\n `media unreachable: ${r.url} answers ${String(r.status)} — a render will quietly carry on without it`,\n )\n } else if (r.ok === null) {\n warnings.push(`could not probe ${r.url} (${r.error ?? 'network error'})`)\n }\n }\n return { problems, warnings }\n}\n","/**\n * Stills from a take — the agent's eyes AND a first-class asset output\n * (posters, OG cards, store screenshots). Lowers + compiles exactly like\n * render, then seeks each requested time in ONE page and captures the canvas\n * as PNG at the exact output resolution. No encoder, no chunks.\n *\n * Times are OUTPUT seconds (what the rendered video shows). `--at-zooms`\n * samples the apex (output-time midpoint) of every zoom span — where quality\n * lives.\n */\nimport { mkdir, readFile, rename, writeFile } from 'node:fs/promises'\nimport { existsSync } from 'node:fs'\nimport { join, resolve } from 'node:path'\nimport { compileVosConfig } from '@vosjs/core'\nimport {\n docStillTime,\n lowerToComposition,\n momentsFromDoc,\n planForDigest,\n ratedSegments,\n resolveExportSize,\n spanOutputExtent,\n} from '@vosjs/studio-core'\nimport { loadTake } from './take'\nimport { startTakeServer, waitForPageDone } from './server'\nimport { renderPageHtml } from './renderAnimation'\nimport {\n applyAndValidate,\n hasOverrides,\n resolveBackdropSlug,\n} from './docOverride'\nimport { DIGEST_DIR } from './digestTake'\nimport type { DocOverrides } from './docOverride'\nimport type { Moment, ProjectDoc } from '@vosjs/studio-core'\nimport type { Browser } from 'playwright'\n\nconst VIDEO_TOKEN = '__VOILA_CLI_VIDEO__'\n\n/**\n * The supersample factor a still renders at: small destinations (a 440\n * px store tile, a 240 px thumbnail) render at two or three times their\n * pixels and downscale once with the browser's high-quality resampler,\n * so footage recorded at 1920 px is not one bilinear tap away from a\n * 270 px card. A still already past 1800 px on its long side renders 1:1.\n */\nexport function stillSupersample(w: number, h: number): number {\n return Math.min(3, Math.max(1, Math.ceil(1800 / Math.max(1, w, h))))\n}\n\nexport interface FramesTakeOptions {\n /** OUTPUT-time seconds; each may also be given as a percent of duration upstream. */\n times: number[]\n /** Also sample every zoom span's output-time apex. */\n atZooms?: boolean\n /**\n * Also sample every digest moment that survives into the output (reads\n * digest/digest.json when present, else derives the moments — no frames).\n */\n atMoments?: boolean\n /** Also sample the frame that stands for the take (docStillTime). */\n atStill?: boolean\n width?: number\n height?: number\n outDir?: string\n /** In-memory doc overrides (--set / --frame / --background); lint-gated. */\n overrides?: DocOverrides\n /**\n * Render THIS document over the take's footage instead of its doc.json\n * (a poster document beside the take). Cloned before any override.\n */\n doc?: ProjectDoc\n}\n\nexport interface CapturedFrame {\n file: string\n time: number\n /** 'time' = requested instant, 'zoom' = a zoom-span apex, 'moment' = a digest moment. */\n kind: 'time' | 'zoom' | 'moment' | 'still'\n momentId?: string\n}\n\nexport interface FramesTakeResult {\n frames: CapturedFrame[]\n width: number\n height: number\n duration: number\n outDir: string\n}\n\n/** Runs inside the render page: seek each time, settle, capture PNG, POST it. */\nasync function stillsInPage(opts: {\n animationCode: string\n token: string\n videoUrl: string\n W: number\n H: number\n /** Render at W*ss × H*ss, downscale to W × H for the PNG. */\n ss: number\n shots: { time: number; name: string }[]\n}) {\n const w = window as unknown as Record<string, any>\n const RW = opts.W * opts.ss\n const RH = opts.H * opts.ss\n try {\n const vblob = await (await fetch(opts.videoUrl)).blob()\n const vurl = URL.createObjectURL(vblob)\n const code = opts.animationCode.split(opts.token).join(vurl)\n const mod = await import(\n /* @vite-ignore */ URL.createObjectURL(\n new Blob([code], { type: 'text/javascript' }),\n )\n )\n\n w.__vos__ = w.__vos__ || {}\n w.__vos__.isPaused = true\n\n const deps = {\n THREE: w.__THREE__,\n gsap: w.__gsap__,\n resolution: {\n width: RW,\n height: RH,\n pixelRatio: 1,\n drawingBufferWidth: RW,\n drawingBufferHeight: RH,\n },\n preserveDrawingBuffer: true,\n }\n const result = await mod.initVos(document.body, deps)\n if (result.assetsReady) await result.assetsReady\n const { timeline } = result\n timeline.pause()\n timeline.seek(0, false)\n\n const canvas = document.querySelector('canvas') as HTMLCanvasElement\n canvas.width = RW\n canvas.height = RH\n canvas.style.width = RW + 'px'\n canvas.style.height = RH + 'px'\n // The downscale target, when supersampled.\n const out = document.createElement('canvas')\n out.width = opts.W\n out.height = opts.H\n\n const raf = () => new Promise((r) => requestAnimationFrame(r))\n const wvr = () =>\n w.__vos__?.waitForVideosReady ? w.__vos__.waitForVideosReady() : null\n const pending = () => w.__vos__?.pendingDecodes?.size ?? 0\n const toPng = () =>\n new Promise<Blob>((res, rej) => {\n let src = canvas\n if (opts.ss > 1) {\n const g = out.getContext('2d')!\n g.imageSmoothingEnabled = true\n g.imageSmoothingQuality = 'high'\n g.clearRect(0, 0, opts.W, opts.H)\n g.drawImage(canvas, 0, 0, opts.W, opts.H)\n src = out\n }\n src.toBlob(\n (b) => (b ? res(b) : rej(new Error('toBlob failed'))),\n 'image/png',\n )\n })\n\n // Every still is a COLD seek — html5-path videos update currentTime\n // asynchronously, so wait for a completed, stable seek before capturing\n // (mirrors renderInPage's chunk-start guard; see renderAnimation.ts).\n const collectVideos = (): HTMLVideoElement[] => {\n const out = new Set<HTMLVideoElement>()\n const cache = w.__vos__?.videoCache\n if (cache) {\n const vals =\n cache instanceof Map ? [...cache.values()] : Object.values(cache)\n for (const v of vals) {\n if (v?.tagName === 'VIDEO') out.add(v)\n else if (v?.el?.tagName === 'VIDEO') out.add(v.el)\n else if (v?.video?.tagName === 'VIDEO') out.add(v.video)\n }\n }\n document.querySelectorAll('video').forEach((v) => out.add(v))\n return [...out]\n }\n const videosSettled = () =>\n collectVideos().every((v) => !v.seeking && v.readyState >= 2)\n const waitVideosSettled = async (maxMs: number) => {\n const t0 = performance.now()\n let stableTimes = ''\n while (performance.now() - t0 < maxMs) {\n await raf()\n if (videosSettled()) {\n const times = collectVideos()\n .map((v) => v.currentTime.toFixed(3))\n .join(',')\n if (times === stableTimes) return\n stableTimes = times\n } else {\n stableTimes = ''\n }\n }\n }\n\n for (let i = 0; i < opts.shots.length; i++) {\n const shot = opts.shots[i]\n timeline.seek(shot.time, false)\n await wvr()\n await raf()\n if (pending() > 0) {\n await wvr()\n await raf()\n }\n await waitVideosSettled(8000)\n const png = await toPng()\n await fetch('/save?name=' + shot.name, { method: 'POST', body: png })\n w.__progress = (i + 1) / opts.shots.length\n }\n w.__done = { ok: true, count: opts.shots.length }\n } catch (e) {\n w.__error = String((e instanceof Error && e.stack) || e)\n }\n}\n\nexport async function framesTake(\n browser: Browser,\n dir: string,\n opts: FramesTakeOptions,\n): Promise<FramesTakeResult> {\n const take = await loadTake(dir)\n const doc = opts.doc ? structuredClone(opts.doc) : take.doc\n if (!doc) throw new Error(`${dir} has no doc.json — run plan first`)\n\n // Product-surface overrides (--set/--frame/--background): patch + lint the doc\n // in memory (doc.json untouched) so a still can preview any presentation.\n if (opts.overrides && hasOverrides(opts.overrides)) {\n await resolveBackdropSlug(opts.overrides)\n applyAndValidate(doc, opts.overrides)\n }\n\n const res = resolveExportSize(doc)\n const width = opts.width ?? res.width\n const height = opts.height ?? res.height\n\n doc.source.videoKey = VIDEO_TOKEN\n const lowered = lowerToComposition(doc)\n const animationCode = compileVosConfig(lowered.config as never, {\n tweenEngine: 'vos',\n })\n const duration = lowered.duration\n\n const clamp = (t: number) =>\n Math.min(Math.max(0, t), Math.max(0, duration - 1 / 30))\n const shots: {\n time: number\n kind: 'time' | 'zoom' | 'moment' | 'still'\n momentId?: string\n }[] = opts.times.map((t) => ({\n time: clamp(t),\n kind: 'time',\n }))\n if (opts.atZooms) {\n const rated = ratedSegments(doc)\n for (const z of doc.zoom) {\n const ext = spanOutputExtent(rated, z.in, z.out)\n if (ext)\n shots.push({ time: clamp((ext.start + ext.end) / 2), kind: 'zoom' })\n }\n }\n if (opts.atMoments) {\n for (const m of await momentsFor(dir, doc)) {\n if (m.outputAt === null) continue\n shots.push({ time: clamp(m.outputAt), kind: 'moment', momentId: m.id })\n }\n }\n if (opts.atStill)\n shots.push({ time: clamp(docStillTime(doc)), kind: 'still' })\n shots.sort((a, b) => a.time - b.time)\n if (!shots.length)\n throw new Error(\n 'no frame times — pass --times/--frame, --at-zooms, --at-moments or --at-still',\n )\n\n const outDir = resolve(opts.outDir ?? join(dir, 'stills'))\n await mkdir(outDir, { recursive: true })\n const named = shots.map((s, i) => ({\n ...s,\n name:\n s.kind === 'moment'\n ? `moment-${s.momentId}-${s.time.toFixed(2)}s.png`\n : `${s.kind === 'zoom' ? 'zoom' : 'frame'}-${String(i).padStart(2, '0')}-${s.time.toFixed(2)}s.png`,\n }))\n\n const server = await startTakeServer(dir, {\n '/render.html': renderPageHtml(),\n })\n const ss = stillSupersample(width, height)\n const context = await browser.newContext({\n viewport: { width: width * ss, height: height * ss },\n })\n try {\n const page = await context.newPage()\n page.on('console', (m) => {\n if (m.type() === 'error')\n process.stderr.write(` [stills page] ${m.text()}\\n`)\n })\n await page.addInitScript(() => {\n ;(globalThis as unknown as Record<string, unknown>).__name = (\n f: unknown,\n ) => f\n })\n await page.goto(`${server.base}/render.html`)\n await page.waitForFunction('window.__pageReady__ === true')\n void page\n .evaluate(stillsInPage, {\n animationCode,\n token: VIDEO_TOKEN,\n videoUrl: `/${take.paths.recordingName}`,\n W: width,\n H: height,\n ss,\n shots: named.map(({ time, name }) => ({ time, name })),\n })\n .catch(() => {})\n await waitForPageDone(\n page,\n 'stills',\n () => {},\n 120_000 + named.length * 4_000,\n )\n\n // The take server saves into its root (the take dir) — move into outDir.\n const frames: CapturedFrame[] = []\n for (const n of named) {\n const from = join(dir, n.name)\n const to = join(outDir, n.name)\n if (from !== to) await rename(from, to)\n frames.push({\n file: to,\n time: n.time,\n kind: n.kind,\n ...(n.momentId ? { momentId: n.momentId } : {}),\n })\n }\n return { frames, width, height, duration, outDir }\n } finally {\n await context.close()\n server.close()\n }\n}\n\n/**\n * The moments to frame: the digest on disk when there is one (its scenes and\n * activity came from a real decode), else derived from the track alone.\n */\nasync function momentsFor(dir: string, doc: ProjectDoc): Promise<Moment[]> {\n const file = join(dir, DIGEST_DIR, 'digest.json')\n if (existsSync(file)) {\n try {\n const d = JSON.parse(await readFile(file, 'utf8')) as {\n moments?: Moment[]\n }\n if (Array.isArray(d.moments)) return d.moments\n } catch {\n // fall through to a fresh derivation\n }\n }\n return momentsFromDoc(doc, planForDigest(doc))\n}\n\n/** Parse a --times list: seconds (\"2.5\") and percents of duration (\"50%\"). */\nexport function parseTimes(spec: string, duration: number): number[] {\n return spec\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean)\n .map((s) => {\n if (s.endsWith('%')) {\n const p = Number(s.slice(0, -1))\n if (!Number.isFinite(p)) throw new Error(`bad time \"${s}\"`)\n return (p / 100) * duration\n }\n const t = Number(s)\n if (!Number.isFinite(t)) throw new Error(`bad time \"${s}\"`)\n return t\n })\n}\n\n/** Contact-sheet composite via PNGs written by framesTake (no deps; caller may skip). */\nexport async function writeIndexJson(\n result: FramesTakeResult,\n): Promise<string> {\n const index = join(result.outDir, 'stills.json')\n await writeFile(\n index,\n JSON.stringify(\n {\n width: result.width,\n height: result.height,\n duration: result.duration,\n frames: result.frames,\n },\n null,\n 2,\n ),\n )\n return index\n}\n","import { createServer } from 'node:http'\nimport { existsSync, readFileSync, statSync } from 'node:fs'\nimport { writeFile } from 'node:fs/promises'\nimport { extname, join } from 'node:path'\nimport { MEDIA_HEAD_BYTES, sniffMediaType } from './container'\nimport type { Page } from 'playwright'\n\nconst MIME: Record<string, string> = {\n '.html': 'text/html',\n '.js': 'text/javascript',\n '.json': 'application/json',\n '.jpg': 'image/jpeg',\n '.png': 'image/png',\n // A brand mark or an image overlay: an <img> refuses an SVG served as an\n // octet stream, so the kinds a doc can key are named.\n '.svg': 'image/svg+xml',\n '.webp': 'image/webp',\n '.gif': 'image/gif',\n '.webm': 'video/webm',\n '.mp4': 'video/mp4',\n // Take-dir audio (doc.audio keys like \"/music.mp3\") — decode goes through\n // fetch → arrayBuffer so the type is informational, but an <audio> element\n // would care; never serve these as octet-stream.\n '.mp3': 'audio/mpeg',\n '.wav': 'audio/wav',\n '.m4a': 'audio/mp4',\n '.ogg': 'audio/ogg',\n}\n\nexport interface TakeServer {\n base: string\n close: () => void\n}\n\n/**\n * Static server over the take dir + generated pages + a POST /save endpoint\n * the in-page encoder/renderer uses to hand bytes back to node. The recording\n * is fetched → blob URL (seekable), but a take-dir VIDEO BACKGROUND\n * (frame.backgroundMedia.key = \"/bg.webm\") is loaded directly by ON_FRAME and\n * seeked during export — so this serves Range/206 (an HTMLVideoElement hangs\n * forever seeking a naive 200-only static server).\n */\nexport function startTakeServer(\n rootDir: string,\n pages: Record<string, string>,\n): Promise<TakeServer> {\n const server = createServer((req, res) => {\n const url = new URL(req.url ?? '/', 'http://x')\n // The studio (a different origin, https://vos.so) fetches take files for\n // `vos open`. Two doors a public page must pass to reach localhost:\n // CORS, answered on every response, and Chrome's private-network\n // check. Chrome 104 to 141 asked it as a preflight carrying\n // Access-Control-Request-Private-Network and wanted the Allow-\n // Private-Network answer; Chrome 142 and later (Local Network Access)\n // asks the PERSON instead, a prompt by the address bar, which no header\n // can answer (measured 2026-09-25 on Chrome 153: the fetch fails with\n // \"Permission was denied for this request to access the loopback\n // address space\" until it is allowed once per site). Both answered\n // here; the studio's reader says what to allow.\n res.setHeader('access-control-allow-origin', '*')\n res.setHeader('access-control-allow-private-network', 'true')\n if (req.method === 'OPTIONS') {\n res.writeHead(204, {\n 'access-control-allow-methods': 'GET, POST, OPTIONS',\n 'access-control-allow-headers': '*',\n 'access-control-max-age': '600',\n })\n res.end()\n return\n }\n if (req.method === 'POST' && url.pathname === '/save') {\n const name = (url.searchParams.get('name') ?? 'out.bin').replace(\n /[^\\w.-]/g,\n '',\n )\n const chunks: Buffer[] = []\n req.on('data', (c: Buffer) => chunks.push(c))\n req.on('end', () => {\n void writeFile(join(rootDir, name), Buffer.concat(chunks)).then(\n () => res.writeHead(200).end('ok'),\n (e) => res.writeHead(500).end(String(e)),\n )\n })\n return\n }\n if (pages[url.pathname]) {\n res.writeHead(200, { 'content-type': 'text/html' })\n res.end(pages[url.pathname])\n return\n }\n const file = join(rootDir, decodeURIComponent(url.pathname))\n if (existsSync(file) && statSync(file).isFile()) {\n const size = statSync(file).size\n const buf = readFileSync(file)\n // The BYTES outrank the extension for anything carrying a container\n // signature: a take pulled as mp4 under a `.webm` name would otherwise be\n // served as webm, and the page's video element would refuse to decode it.\n // Everything without one (html, js, json, svg) keeps the table's answer.\n const type =\n sniffMediaType(buf.subarray(0, MEDIA_HEAD_BYTES)) ??\n MIME[extname(file)] ??\n 'application/octet-stream'\n const range = req.headers.range\n // Range/206 so an HTMLVideoElement can seek a take-dir video background.\n const m = range && /^bytes=(\\d*)-(\\d*)$/.exec(range)\n if (m) {\n const start = m[1] ? parseInt(m[1], 10) : 0\n const end = m[2] ? Math.min(parseInt(m[2], 10), size - 1) : size - 1\n if (start > end || start >= size) {\n res.writeHead(416, { 'content-range': `bytes */${size}` }).end()\n return\n }\n res.writeHead(206, {\n 'content-type': type,\n 'accept-ranges': 'bytes',\n 'content-range': `bytes ${start}-${end}/${size}`,\n 'content-length': end - start + 1,\n })\n res.end(buf.subarray(start, end + 1))\n return\n }\n res.writeHead(200, {\n 'content-type': type,\n 'accept-ranges': 'bytes',\n 'content-length': size,\n })\n res.end(buf)\n return\n }\n res.writeHead(404).end()\n })\n return new Promise((resolve) =>\n server.listen(0, () => {\n const addr = server.address()\n const port = typeof addr === 'object' && addr ? addr.port : 0\n resolve({ base: `http://localhost:${port}`, close: () => server.close() })\n }),\n )\n}\n\n/** Poll a capture/encode page for window.__done / __error / __progress. */\nexport async function waitForPageDone(\n page: Page,\n label: string,\n onProgress: (fraction: number) => void,\n timeoutMs: number,\n): Promise<Record<string, unknown>> {\n const start = Date.now()\n let last = -1\n for (;;) {\n const state: {\n done: Record<string, unknown> | null\n progress: number | null\n error: string | null\n } = await page.evaluate(\n '({ done: window.__done ?? null, progress: window.__progress ?? null, error: window.__error ?? null })',\n )\n if (state.error) throw new Error(`${label} failed: ${state.error}`)\n if (state.done) return state.done\n if (typeof state.progress === 'number') {\n const pct = Math.floor(state.progress * 10) * 10\n if (pct !== last) {\n onProgress(state.progress)\n last = pct\n }\n }\n if (Date.now() - start > timeoutMs) {\n throw new Error(\n `${label} timed out after ${Math.round(timeoutMs / 1000)}s`,\n )\n }\n await new Promise((r) => setTimeout(r, 400))\n }\n}\n","/**\n * Generic deterministic render harness — runs compiled vos animation code in\n * headless page(s) and returns encoded video bytes.\n *\n * Chunk-parallel (R1 of the rendering plan): because vos evaluation is a pure\n * function of time, the timeline shards into independent frame ranges. Each\n * chunk renders in its own page with chunk-LOCAL timestamps and byte-identical\n * encoder params; the finalize step stream-copies the chunks into one file\n * (@vosjs/render-core concat — no re-encode, keyframe per chunk by\n * construction). parallel=1 renders exactly like the historical single-flight\n * path (one chunk, no concat).\n *\n * Take-flavored details (video token, recording file) are optional so the\n * same harness renders studio takes and plain compositions (films, verify\n * fixtures) alike.\n */\nimport { readFile, rm } from 'node:fs/promises'\nimport { tweenRuntimeCode } from '@vosjs/tween/bundle'\nimport { elementsBundleCode } from '@vosjs/elements/bundle'\nimport { concatEncodedVideo, planChunks } from '@vosjs/render-core'\nimport { startTakeServer, waitForPageDone } from './server'\nimport type { RenderChunk } from '@vosjs/render-core'\nimport type { Browser } from 'playwright'\n\nconst MEDIABUNNY_URL = 'https://esm.sh/mediabunny@1.55.7?target=es2022'\nconst THREE_URL = 'https://esm.sh/three@0.183.0?target=es2022'\nconst THREE_ADDONS = 'https://esm.sh/three@0.183.0&target=es2022/examples/jsm/'\n\nexport interface RenderAnimationOptions {\n /** Compiled vos animation code (module exporting initVos). */\n animationCode: string\n /** Directory the page server roots at; chunk artifacts land here too. */\n workDir: string\n /** Source video file name inside workDir (studio takes), served → blob URL. */\n videoFile?: string\n /** Token inside animationCode replaced with the video blob URL. */\n videoToken?: string\n width: number\n height: number\n fps: number\n duration: number\n format: 'webm' | 'mp4'\n /** Max simultaneous chunk pages; 1 = single-flight (no concat). */\n parallel?: number\n /**\n * First GLOBAL frame to render (a range render: seek time starts here while\n * output timestamps stay zero-based). duration then covers the range only.\n */\n frameOffset?: number\n /** Encoder bitrate override (draft renders); default 10 Mbps. */\n bitrate?: number\n /**\n * Mix + mux an audio track in the SAME render (single-flight only — audio\n * stays out of chunks by design, mirroring the cloud single-flight path).\n * `producerCode` defines window.__vosAudioProducer__ (render-core);\n * `data` is the lowered composition data (videoToken replaced in-page).\n * `duration` is the FULL timeline — the producer builds the whole mix and\n * the page slices its own frame window, so a range render keeps audio.\n */\n audio?: { producerCode: string; data: unknown; duration: number }\n onProgress?: (fraction: number) => void\n}\n\nexport interface RenderAnimationResult {\n bytes: Uint8Array\n totalFrames: number\n /** Number of chunks actually rendered (1 = single-flight). */\n chunks: number\n}\n\nexport function renderPageHtml(): string {\n const importmap = JSON.stringify({\n imports: { three: THREE_URL, 'three/addons/': THREE_ADDONS },\n })\n return `<!doctype html><html><head><meta charset=\"utf-8\"><link rel=\"icon\" href=\"data:,\">\n<style>html,body{margin:0;padding:0;background:#000;overflow:hidden}canvas{display:block}</style>\n<script type=\"importmap\">${importmap}</script>\n</head><body>\n<script type=\"module\">\n import * as THREE from 'three'\n ${tweenRuntimeCode}\n // Vos Element System (bundled IIFE) — the same injection the engine's\n // render template performs. Take configs never touch ctx.elements, but a\n // POSTER program (the deliver --poster leg) is element text + an image\n // over the ground, and without this the elements silently never draw.\n ${elementsBundleCode}\n window.__vos__ = window.__vos__ || {}\n window.__vos__.elements = __vosElementsFactory.createVosElements(THREE)\n window.__gsap__ = globalThis.__vosTween.createTweenRecorder()\n window.__THREE__ = THREE\n window.__pageReady__ = true\n</script></body></html>`\n}\n\n/**\n * Runs inside the render page (serialized by Playwright). Renders frames\n * [startFrame, endFrame) — seeks GLOBAL time, captures CHUNK-LOCAL\n * timestamps — so every chunk is an independent, concat-ready file.\n */\nasync function renderInPage(opts: {\n animationCode: string\n token?: string\n videoUrl?: string\n W: number\n H: number\n fps: number\n startFrame: number\n endFrame: number\n format: 'webm' | 'mp4'\n bitrate: number\n mediabunnyUrl: string\n outName: string\n debug?: boolean\n audioProducerCode?: string\n audioDataJson?: string\n audioDuration?: number\n}) {\n const w = window as unknown as Record<string, any>\n try {\n const MB = await import(/* @vite-ignore */ opts.mediabunnyUrl)\n let code = opts.animationCode\n let vurl: string | null = null\n if (opts.videoUrl && opts.token) {\n // Blob URL: HTMLVideoElement seeking needs HTTP range support the take\n // server doesn't provide — a local blob is fully seekable.\n const vblob = await (await fetch(opts.videoUrl)).blob()\n vurl = URL.createObjectURL(vblob)\n code = code.split(opts.token).join(vurl)\n }\n\n // Audio first: a producer failure aborts before any frame work.\n let audioBuffer: AudioBuffer | null = null\n if (opts.audioProducerCode && opts.audioDataJson) {\n ;(0, eval)(opts.audioProducerCode)\n const dataJson =\n vurl && opts.token\n ? opts.audioDataJson.split(opts.token).join(vurl)\n : opts.audioDataJson\n audioBuffer = await w.__vosAudioProducer__({\n data: JSON.parse(dataJson),\n duration: opts.audioDuration,\n sampleRate: 48000,\n })\n }\n // The producer mixes the WHOLE timeline; mux only this page's own frame\n // window. On a full render the slice is a no-op cap (the RF D1 overlong\n // guard); on a --range render it is what keeps the clip's audio synced.\n if (audioBuffer) {\n const sr = audioBuffer.sampleRate\n const sliceStart = Math.round((opts.startFrame / opts.fps) * sr)\n const wanted = Math.ceil(\n ((opts.endFrame - opts.startFrame) / opts.fps) * sr,\n )\n if (sliceStart > 0 || audioBuffer.length > wanted) {\n const len = Math.max(\n 0,\n Math.min(wanted, audioBuffer.length - sliceStart),\n )\n if (len === 0) {\n audioBuffer = null\n } else {\n const sliced = new AudioBuffer({\n length: len,\n numberOfChannels: audioBuffer.numberOfChannels,\n sampleRate: sr,\n })\n for (let ch = 0; ch < audioBuffer.numberOfChannels; ch++) {\n sliced.copyToChannel(\n audioBuffer\n .getChannelData(ch)\n .subarray(sliceStart, sliceStart + len),\n ch,\n )\n }\n audioBuffer = sliced\n }\n }\n }\n const mod = await import(\n /* @vite-ignore */ URL.createObjectURL(\n new Blob([code], { type: 'text/javascript' }),\n )\n )\n\n // Deterministic export: compositions must seek (not play) their videos.\n w.__vos__ = w.__vos__ || {}\n w.__vos__.isPaused = true\n\n const deps = {\n THREE: w.__THREE__,\n gsap: w.__gsap__,\n resolution: {\n width: opts.W,\n height: opts.H,\n pixelRatio: 1,\n drawingBufferWidth: opts.W,\n drawingBufferHeight: opts.H,\n },\n preserveDrawingBuffer: true,\n }\n const result = await mod.initVos(document.body, deps)\n if (result.assetsReady) await result.assetsReady\n const { timeline } = result\n timeline.pause()\n timeline.seek(0, false)\n\n const canvas = document.querySelector('canvas') as HTMLCanvasElement\n canvas.width = opts.W\n canvas.height = opts.H\n canvas.style.width = opts.W + 'px'\n canvas.style.height = opts.H + 'px'\n\n // Encoder params are PINNED (codec/bitrate identical for every chunk of\n // a render) — stream-copy concat at finalize depends on it.\n const output = new MB.Output({\n format:\n opts.format === 'mp4'\n ? new MB.Mp4OutputFormat()\n : new MB.WebMOutputFormat(),\n target: new MB.BufferTarget(),\n })\n const videoSource = new MB.CanvasSource(canvas, {\n codec: opts.format === 'mp4' ? 'avc' : 'vp9',\n bitrate: opts.bitrate,\n })\n output.addVideoTrack(videoSource, { frameRate: opts.fps })\n let audioSource: any = null\n if (audioBuffer) {\n // AAC first for mp4 (compatibility), Opus fallback — mirrors finalizePage.\n const preferred = opts.format === 'mp4' ? 'aac' : 'opus'\n const audioCodec =\n preferred === 'aac' && !(await MB.canEncodeAudio('aac'))\n ? 'opus'\n : preferred\n audioSource = new MB.AudioBufferSource({\n codec: audioCodec,\n bitrate: MB.QUALITY_HIGH,\n })\n output.addAudioTrack(audioSource)\n }\n await output.start()\n if (audioSource && audioBuffer) {\n await audioSource.add(audioBuffer)\n audioSource.close()\n }\n\n const frames = opts.endFrame - opts.startFrame\n const raf = () => new Promise((r) => requestAnimationFrame(r))\n const wvr = () =>\n w.__vos__?.waitForVideosReady ? w.__vos__.waitForVideosReady() : null\n const pending = () => w.__vos__?.pendingDecodes?.size ?? 0\n\n // html5-path videos seek currentTime ASYNCHRONOUSLY — a cold seek into the\n // middle of the timeline (every chunk start) displays the element's stale\n // initial frame until the seek lands, and the readiness hooks above only\n // cover the webcodecs path. Wait until every video element reports a\n // completed, stable seek before capturing. (The per-frame 33ms steps after\n // warm-up keep up on their own — this guards the COLD seeks.)\n const collectVideos = (): HTMLVideoElement[] => {\n const out = new Set<HTMLVideoElement>()\n const cache = w.__vos__?.videoCache\n if (cache) {\n const vals =\n cache instanceof Map ? [...cache.values()] : Object.values(cache)\n for (const v of vals) {\n if (v?.tagName === 'VIDEO') out.add(v)\n else if (v?.el?.tagName === 'VIDEO') out.add(v.el)\n else if (v?.video?.tagName === 'VIDEO') out.add(v.video)\n }\n }\n document.querySelectorAll('video').forEach((v) => out.add(v))\n return [...out]\n }\n const videosSettled = () =>\n collectVideos().every((v) => !v.seeking && v.readyState >= 2)\n const waitVideosSettled = async (maxMs: number) => {\n const t0 = performance.now()\n // Two consecutive settled reads with stable currentTime — a seek that\n // hasn't dispatched yet can read \"settled\" for one tick.\n let stableTimes = ''\n while (performance.now() - t0 < maxMs) {\n await raf()\n if (videosSettled()) {\n const times = collectVideos()\n .map((v) => v.currentTime.toFixed(3))\n .join(',')\n if (times === stableTimes) return\n stableTimes = times\n } else {\n stableTimes = ''\n }\n }\n }\n\n for (let frame = opts.startFrame; frame < opts.endFrame; frame++) {\n const time = frame / opts.fps\n timeline.seek(time, false)\n await wvr()\n await raf()\n if (pending() > 0) {\n await wvr()\n await raf()\n }\n if (frame === opts.startFrame) await waitVideosSettled(8000)\n if (opts.debug && frame === opts.startFrame) {\n const png: Blob = await new Promise((res, rej) =>\n canvas.toBlob(\n (b) => (b ? res(b) : rej(new Error('toBlob'))),\n 'image/png',\n ),\n )\n await fetch(\n '/save?name=' + opts.outName.replace('.tmp', '-first.png'),\n {\n method: 'POST',\n body: png,\n },\n )\n }\n // Chunk-local timestamp: this chunk's file starts at t=0.\n await videoSource.add((frame - opts.startFrame) / opts.fps, 1 / opts.fps)\n w.__progress = (frame - opts.startFrame) / frames\n }\n\n await output.finalize()\n const buf = output.target.buffer\n await fetch('/save?name=' + opts.outName, { method: 'POST', body: buf })\n w.__done = { ok: true, bytes: buf.byteLength }\n } catch (e) {\n w.__error = String((e instanceof Error && e.stack) || e)\n }\n}\n\nasync function renderChunk(\n context: Awaited<ReturnType<Browser['newContext']>>,\n serverBase: string,\n chunk: RenderChunk,\n opts: RenderAnimationOptions,\n onChunkProgress: (fraction: number) => void,\n): Promise<string> {\n const outName = `render-chunk-${chunk.index}.tmp`\n const page = await context.newPage()\n try {\n page.on('console', (m) => {\n if (m.type() === 'error' || process.env.VOS_RENDER_DEBUG)\n process.stderr.write(\n ` [render page ${chunk.index} ${m.type()}] ${m.text()}\\n`,\n )\n })\n if (process.env.VOS_RENDER_DEBUG)\n page.on('pageerror', (e) =>\n process.stderr.write(\n ` [render pageerror ${chunk.index}] ${String(e)}\\n`,\n ),\n )\n await page.addInitScript(() => {\n ;(globalThis as unknown as Record<string, unknown>).__name = (\n f: unknown,\n ) => f\n })\n await page.goto(`${serverBase}/render.html`)\n await page.waitForFunction('window.__pageReady__ === true')\n const frameOffset = opts.frameOffset ?? 0\n const audio = opts.audio\n void page\n .evaluate(renderInPage, {\n animationCode: opts.animationCode,\n token: opts.videoToken,\n videoUrl: opts.videoFile ? `/${opts.videoFile}` : undefined,\n W: opts.width,\n H: opts.height,\n fps: opts.fps,\n startFrame: chunk.startFrame + frameOffset,\n endFrame: chunk.endFrame + frameOffset,\n format: opts.format,\n bitrate: opts.bitrate ?? 10_000_000,\n mediabunnyUrl: MEDIABUNNY_URL,\n outName,\n debug: process.env.VOILA_DEBUG_CHUNKS === '1',\n audioProducerCode: audio?.producerCode,\n audioDataJson: audio ? JSON.stringify(audio.data) : undefined,\n audioDuration: audio?.duration,\n })\n .catch(() => {})\n const timeoutMs = 120_000 + chunk.frameCount * 500\n await waitForPageDone(\n page,\n `render chunk ${chunk.index}`,\n onChunkProgress,\n timeoutMs,\n )\n return outName\n } finally {\n await page.close()\n }\n}\n\nexport async function renderAnimation(\n browser: Browser,\n opts: RenderAnimationOptions,\n): Promise<RenderAnimationResult> {\n const totalFrames = Math.ceil(opts.duration * opts.fps)\n const chunks = planChunks(totalFrames, opts.fps, {\n maxParallel: Math.max(1, opts.parallel ?? 1),\n })\n\n // Audio stays out of chunks by design: only a single-flight render muxes\n // it (renderTake forces parallel=1 when audio is wanted). A range render\n // keeps audio — the page slices its frame window from the full mix.\n const effOpts: RenderAnimationOptions =\n opts.audio && chunks.length > 1 ? { ...opts, audio: undefined } : opts\n\n const server = await startTakeServer(opts.workDir, {\n '/render.html': renderPageHtml(),\n })\n // One context for all chunk pages: they share the HTTP cache, so CDN\n // module imports (three, mediabunny) are fetched once, not per chunk.\n const context = await browser.newContext({\n viewport: { width: opts.width, height: opts.height },\n })\n try {\n const progress = new Array<number>(chunks.length).fill(0)\n const reportProgress = () => {\n const done = chunks.reduce(\n (sum, c, i) => sum + c.frameCount * progress[i],\n 0,\n )\n opts.onProgress?.(done / totalFrames)\n }\n\n const outNames = await Promise.all(\n chunks.map((chunk) =>\n renderChunk(context, server.base, chunk, effOpts, (fraction) => {\n progress[chunk.index] = fraction\n reportProgress()\n }),\n ),\n )\n\n const files = await Promise.all(\n outNames.map((name) => readFile(`${opts.workDir}/${name}`)),\n )\n await Promise.all(\n outNames.map((name) => rm(`${opts.workDir}/${name}`, { force: true })),\n )\n\n if (chunks.length === 1) {\n return { bytes: new Uint8Array(files[0]), totalFrames, chunks: 1 }\n }\n\n const { bytes } = await concatEncodedVideo(\n chunks.map((chunk, i) => ({\n data: new Uint8Array(files[i]),\n duration: chunk.duration,\n })),\n { format: opts.format, frameRate: opts.fps },\n )\n return { bytes, totalFrames, chunks: chunks.length }\n } finally {\n await context.close()\n server.close()\n }\n}\n","/**\n * The backdrop SET: the loops the platform publishes at `GET /api/backdrops`\n * (public, no credential, each with its 1080p loop, poster, period and\n * ground). Two readers: `--background <slug>` on the verification verbs, and\n * the frame a FRESH take opens on, which is the set's first ready loop, the\n * house pick, so a take made here opens on what a take made in the studio\n * opens on. The pick is the platform's ordering of its set, never a\n * constant in this package: the studio names its own, the CLI reads it.\n */\nimport { UsageError } from './args'\nimport type { Backdrop } from '@vosjs/studio-core'\n\nexport interface BackdropRow {\n slug: string\n title?: string\n duration: number\n ground?: string\n urls: {\n '1080p': string | null\n '2k'?: string | null\n poster?: string | null\n }\n}\n\n/** A backdrop from the set, with the slug it was picked by. */\nexport interface NamedBackdrop extends Backdrop {\n slug: string\n}\n\n/** Reads the set. Throws when the origin cannot be reached or answers badly. */\nexport async function fetchBackdropSet(origin: string): Promise<BackdropRow[]> {\n const base = origin.replace(/\\/+$/, '')\n const res = await fetch(`${base}/api/backdrops`)\n if (!res.ok)\n throw new Error(`GET ${base}/api/backdrops answered ${res.status}`)\n const body = (await res.json()) as { backdrops?: unknown }\n return Array.isArray(body.backdrops) ? (body.backdrops as BackdropRow[]) : []\n}\n\nfunction rowBackdrop(row: BackdropRow): NamedBackdrop | null {\n const key = row.urls['1080p']\n if (!key) return null\n return {\n slug: row.slug,\n key,\n kind: 'video',\n duration: row.duration,\n ...(row.urls.poster ? { poster: row.urls.poster } : {}),\n ...(row.ground ? { ground: row.ground } : {}),\n }\n}\n\n/** The house backdrop: the first row of the set with a loop, or null. */\nexport function houseBackdrop(\n rows: readonly BackdropRow[],\n): NamedBackdrop | null {\n for (const row of rows) {\n const b = rowBackdrop(row)\n if (b) return b\n }\n return null\n}\n\n/** One row of the set by slug; null when it is absent or has no loop yet. */\nexport function backdropBySlug(\n rows: readonly BackdropRow[],\n slug: string,\n): NamedBackdrop | null {\n const row = rows.find((r) => r.slug === slug)\n return row ? rowBackdrop(row) : null\n}\n\n/** A bare slug (`soft-beams`), never a URL, a path or `none`. */\nexport function isBackdropSlug(value: string): boolean {\n return /^[a-z0-9][a-z0-9-]{0,49}$/.test(value) && value !== 'none'\n}\n\nconst VIDEO_EXT = /\\.(webm|mp4|mov|m4v)(\\?|#|$)/i\nconst IMAGE_EXT = /\\.(jpe?g|png|webp|gif|avif)(\\?|#|$)/i\n\n/**\n * The media kind a URL or take-dir path implies. Video when the extension\n * says nothing (the flagship case is a loop); `--set` gives precise control\n * when the URL is opaque.\n */\nexport function inferBackgroundKind(url: string): 'video' | 'image' {\n if (IMAGE_EXT.test(url)) return 'image'\n if (VIDEO_EXT.test(url)) return 'video'\n return 'video'\n}\n\n/** Default loop length assumed for a --background video with no explicit duration. */\nexport const BACKGROUND_DEFAULT_DURATION = 10\n\n/** A backdrop for a URL or take-dir path handed to `--background`. */\nexport function backdropFromKey(key: string, duration?: number): Backdrop {\n const kind = inferBackgroundKind(key)\n return kind === 'video'\n ? { key, kind, duration: duration ?? BACKGROUND_DEFAULT_DURATION }\n : { key, kind }\n}\n\n/**\n * The backdrop a fresh take opens on, from `--background`: `none` is the\n * bare frame, a slug is that loop (refused in words when the set lacks it),\n * a URL or path is taken as given, and ABSENT is the set's house pick. When\n * the set cannot be read and nothing was asked, the take opens on the bare\n * frame and `note` says so; an asked slug that cannot be read is an error.\n */\nexport async function openingBackdrop(\n background: string | undefined,\n origin: string,\n): Promise<{ backdrop: Backdrop | null; note?: string }> {\n if (background === 'none' || background === '') return { backdrop: null }\n if (background !== undefined && !isBackdropSlug(background)) {\n return { backdrop: backdropFromKey(background) }\n }\n let rows: BackdropRow[]\n try {\n rows = await fetchBackdropSet(origin)\n } catch (err) {\n if (background !== undefined) {\n throw new UsageError(\n `--background \"${background}\" — could not read the backdrop set from ${origin}/api/backdrops (${(err as Error).message}); pass a URL instead`,\n )\n }\n return {\n backdrop: null,\n note: `could not read the backdrop set from ${origin}/api/backdrops; the take opens on a flat ground (--background <slug|url> picks one later)`,\n }\n }\n if (background !== undefined) {\n const hit = backdropBySlug(rows, background)\n if (!hit) {\n throw new UsageError(\n `--background \"${background}\" is not in the set (${rows.map((b) => b.slug).join(' | ') || 'empty'}); GET ${origin}/api/backdrops lists it, or pass a URL`,\n )\n }\n return { backdrop: hit }\n }\n const house = houseBackdrop(rows)\n return house\n ? { backdrop: house }\n : {\n backdrop: null,\n note: `the backdrop set at ${origin}/api/backdrops has no ready loop; the take opens on a flat ground`,\n }\n}\n","/**\n * Doc-override flags for `render` / `frames` — the product-surface verification\n * seam (verification is how customers use it). The CLI and the studio are\n * producer AND consumer: when we want to CHECK a doc field\n * (a browser frame, a background, a tilt span), the right move is not a bespoke\n * harness but a flag that expresses it on the product surface — so the check and\n * the customer feature are the same thing. Every doc field is reachable via a\n * generic `--set <path>=<value>` (agents have the schema); the marquee\n * presentation knobs get named aliases (`--frame`, `--background`).\n *\n * Overrides patch the take's doc IN MEMORY only (doc.json on disk stays the\n * source of truth) and are LINT-GATED before rendering — a bad override fails\n * exactly like a bad doc.json, so the override path can't ship an invalid doc.\n */\nimport { lintDoc } from './validateDoc'\nimport { UsageError } from './args'\nimport {\n BACKGROUND_DEFAULT_DURATION,\n backdropBySlug,\n fetchBackdropSet,\n inferBackgroundKind,\n isBackdropSlug,\n} from './backdrops'\nimport type { ProjectDoc } from '@vosjs/studio-core'\n\nexport { BACKGROUND_DEFAULT_DURATION, isBackdropSlug } from './backdrops'\n\nexport interface DocOverrides {\n /** raw `path=value` expressions from repeated --set. */\n set?: string[]\n /** Top-level or nested paths to REMOVE after the sets (a destination's mechanics drop a field a null could not express). */\n unset?: string[]\n /** --frame alias → frame.browserBar.kind. */\n frame?: string\n /** --background alias → frame.backgroundMedia (kind inferred from the URL,\n * or a backdrop SLUG from GET /api/backdrops, resolved by\n * resolveBackdropSlug before the sync apply). */\n background?: string\n /** The loop length a resolved backdrop slug brought with it. */\n backgroundDuration?: number\n /** Platform origin for slug resolution (platformOrigin(flags)). */\n origin?: string\n}\n\n/**\n * `--background <slug>` names a backdrop from the set. The set is\n * public (`GET /api/backdrops`), so this needs no credential; it rewrites\n * the override IN PLACE to the loop's 1080p URL and its own period, and\n * refuses in words when the slug is not in the set. URLs pass untouched.\n */\nexport async function resolveBackdropSlug(o: DocOverrides): Promise<void> {\n if (!o.background || !isBackdropSlug(o.background)) return\n const origin = (o.origin ?? 'https://vos.so').replace(/\\/+$/, '')\n let list: Awaited<ReturnType<typeof fetchBackdropSet>>\n try {\n list = await fetchBackdropSet(origin)\n } catch {\n throw new UsageError(\n `--background \"${o.background}\" — could not read the backdrop set from ${origin}/api/backdrops; pass a URL instead`,\n )\n }\n const hit = backdropBySlug(list, o.background)\n if (!hit) {\n throw new UsageError(\n `--background \"${o.background}\" is not in the set (${list.map((b) => b.slug).join(' | ') || 'empty'}); GET ${origin}/api/backdrops lists it, or pass a URL`,\n )\n }\n o.background = hit.key\n o.backgroundDuration = hit.duration\n}\n\nexport function hasOverrides(o: DocOverrides): boolean {\n return !!(\n o.set?.length ||\n o.unset?.length ||\n o.frame !== undefined ||\n o.background !== undefined\n )\n}\n\n/** Friendly --frame values → BrowserBarStyle.kind. */\nconst FRAME_KINDS: Record<string, string> = {\n macos: 'mac-light',\n mac: 'mac-light',\n 'mac-light': 'mac-light',\n 'mac-dark': 'mac-dark',\n windows: 'windows-light',\n 'windows-light': 'windows-light',\n 'windows-dark': 'windows-dark',\n minimal: 'minimal',\n none: 'none',\n hidden: 'none',\n}\n\n/**\n * Coerce a `--set` value: JSON when it parses (numbers, booleans, null, objects,\n * arrays), else the raw string — so `tilt[0].rx=8` is a number, `tilt=null`\n * clears it, `frame.background=#000` stays a string, and\n * `frame.backgroundMedia={\"kind\":\"video\",\"key\":\"…\",\"duration\":10,\"dim\":0.2}`\n * is an object.\n */\nexport function coerceValue(raw: string): unknown {\n try {\n return JSON.parse(raw)\n } catch {\n return raw\n }\n}\n\ninterface PathSeg {\n key: string | number\n}\n\n/**\n * Tokenize `frame.browserBar.kind` / `zoom[0].level` into path segments, strictly\n * (contiguous — no empty segments, no `a..b`, no leading/trailing dot).\n */\nfunction parsePath(path: string): PathSeg[] {\n const bad = (): never => {\n throw new UsageError(`--set: invalid path \"${path}\"`)\n }\n const segs: PathSeg[] = []\n let i = 0\n let expectKey = true // start of the path, or just after a '.'\n while (i < path.length) {\n const c = path[i]\n if (c === '.') {\n if (expectKey) bad() // leading '.' or '..'\n expectKey = true\n i++\n } else if (c === '[') {\n if (expectKey) bad() // '[' can only follow a name/index\n const j = path.indexOf(']', i)\n if (j < 0) bad()\n const num = path.slice(i + 1, j)\n if (!/^\\d+$/.test(num)) bad()\n segs.push({ key: Number(num) })\n i = j + 1\n } else {\n let j = i\n while (j < path.length && path[j] !== '.' && path[j] !== '[') j++\n segs.push({ key: path.slice(i, j) })\n expectKey = false\n i = j\n }\n }\n if (expectKey || !segs.length) bad() // trailing '.' or empty\n return segs\n}\n\n/** Set a nested path on an object, creating intermediate objects/arrays. */\nexport function setPath(\n root: Record<string, unknown>,\n path: string,\n value: unknown,\n): void {\n const segs = parsePath(path)\n let node: unknown = root\n for (let i = 0; i < segs.length - 1; i++) {\n const key = segs[i].key\n const nextIsIndex = typeof segs[i + 1].key === 'number'\n const container = node as Record<string | number, unknown>\n if (container[key] === undefined || container[key] === null) {\n container[key] = nextIsIndex ? [] : {}\n }\n node = container[key]\n if (typeof node !== 'object' || node === null) {\n throw new UsageError(\n `--set: \"${path}\" traverses a non-object at \"${String(key)}\"`,\n )\n }\n }\n ;(node as Record<string | number, unknown>)[segs[segs.length - 1].key] = value\n}\n\n/**\n * Apply overrides to `doc` IN PLACE. Named aliases first (so an explicit --set\n * can still override them), then --set expressions in order. Returns a\n * human-readable summary of what was applied. Throws UsageError on a malformed\n * expression; SEMANTIC validity is the caller's lint pass.\n */\nexport function applyDocOverrides(doc: ProjectDoc, o: DocOverrides): string[] {\n const applied: string[] = []\n const d = doc as unknown as Record<string, unknown>\n\n if (o.frame !== undefined) {\n const kind = FRAME_KINDS[o.frame.toLowerCase()]\n if (!kind) {\n throw new UsageError(\n `--frame \"${o.frame}\" — one of: ${Object.keys(FRAME_KINDS).join(' | ')}`,\n )\n }\n setPath(d, 'frame.browserBar.kind', kind)\n applied.push(`frame.browserBar.kind = ${kind}`)\n }\n\n if (o.background !== undefined) {\n if (o.background === 'none' || o.background === '') {\n setPath(d, 'frame.backgroundMedia', null)\n applied.push('frame.backgroundMedia = null')\n } else {\n const kind = inferBackgroundKind(o.background)\n const media: Record<string, unknown> = { kind, key: o.background, dim: 0 }\n if (kind === 'video')\n media.duration = o.backgroundDuration ?? BACKGROUND_DEFAULT_DURATION\n setPath(d, 'frame.backgroundMedia', media)\n applied.push(`frame.backgroundMedia = ${kind} ${o.background}`)\n }\n }\n\n for (const expr of o.set ?? []) {\n const eq = expr.indexOf('=')\n if (eq < 1) throw new UsageError(`--set expects path=value (got \"${expr}\")`)\n const path = expr.slice(0, eq)\n const value = coerceValue(expr.slice(eq + 1))\n setPath(d, path, value)\n applied.push(`${path} = ${JSON.stringify(value)}`)\n }\n\n for (const path of o.unset ?? []) {\n const segs = parsePath(path)\n let node: unknown = d\n for (\n let i = 0;\n i < segs.length - 1 && node && typeof node === 'object';\n i++\n )\n node = (node as Record<string | number, unknown>)[segs[i].key]\n if (node && typeof node === 'object') {\n delete (node as Record<string | number, unknown>)[\n segs[segs.length - 1].key\n ]\n applied.push(`${path} removed`)\n }\n }\n\n return applied\n}\n\n/**\n * Apply overrides then LINT — the gate that makes the override path as safe as\n * editing doc.json. Throws UsageError (bad expression or resulting doc invalid)\n * so `render`/`frames` refuse an override that would produce a broken video.\n */\nexport function applyAndValidate(doc: ProjectDoc, o: DocOverrides): string[] {\n const applied = applyDocOverrides(doc, o)\n const lint = lintDoc(doc)\n if (lint.problems.length) {\n throw new UsageError(\n `override produced an invalid doc:\\n ${lint.problems.join('\\n ')}`,\n )\n }\n return applied\n}\n","/**\n * The take digest — the agent's eyes. Slices the FOOTAGE\n * (never the composed render) at the moments the cursor telemetry says\n * matter: one full frame + a crop around the target rect per moment, per-\n * second motion bins, the scene changes those bins reveal, the planners'\n * proposals beside each moment, all in the doc's own normalized units.\n *\n * Two page passes on one bare page over the take server: (1) motion bins by\n * seeking every source second and diffing a 64×36 luma thumbnail — cheap,\n * and the second witness for \"nothing happened here\"; (2) the moment frames.\n * CLI takes reuse their screencast JPEGs (nearest tMs) instead of decoding.\n * Everything the agent reads lands in `digest/` beside the take; `vos push`\n * never uploads it.\n */\nimport { mkdir, readFile, rename, writeFile } from 'node:fs/promises'\nimport { existsSync } from 'node:fs'\nimport { join, resolve } from 'node:path'\nimport {\n DIGEST_CROP_MAX,\n DIGEST_FULL_MAX,\n DIGEST_VERSION,\n MOTION_DELTA,\n buildDigest,\n cropBox,\n frameGeometry,\n momentsFromDoc,\n outputDurationOf,\n planForDigest,\n sceneChanges,\n} from '@vosjs/studio-core'\nimport { loadTake, readJson } from './take'\nimport { startTakeServer, waitForPageDone } from './server'\nimport type {\n Digest,\n DigestImageRef,\n Moment,\n ProjectDoc,\n PxRect,\n TranscriptSegment,\n} from '@vosjs/studio-core'\nimport type { Browser } from 'playwright'\n\nexport const DIGEST_DIR = 'digest'\n// Geometry, thresholds and the document shape are studio-core's (shared\n// with the fleet's digest job): one crop geometry, one builder.\nexport {\n DIGEST_CROP_MAX,\n DIGEST_FULL_MAX,\n DIGEST_VERSION,\n} from '@vosjs/studio-core'\n\nexport interface DigestOptions {\n outDir?: string\n full?: number\n crop?: number\n /** Skip the browser passes (moments only; activity null). */\n frames?: boolean\n transcript?: readonly TranscriptSegment[] | null\n /** A reference doc whose style fields are REPORTED (never applied here). */\n style?: { from: string; doc: ProjectDoc } | null\n}\n\nexport type { Digest } from '@vosjs/studio-core'\n\nexport interface DigestResult {\n file: string\n outDir: string\n digest: Digest\n bytes: number\n}\n\ninterface FrameSource {\n kind: 'video' | 'frames'\n url?: string\n frames?: { t: number; url: string }[]\n}\n\n/** Pass 1 (in page): frame size + per-second motion bins. */\nasync function binsInPage(opts: {\n source: FrameSource\n durationS: number\n delta: number\n}) {\n const w = window as unknown as Record<string, any>\n try {\n const getFrame = await (window as any).__digestSource(opts.source)\n // The INTRINSIC size (videoWidth / naturalWidth), stamped on the source\n // by the page — a <video> element's own .width is its CSS box (0 here).\n const size = { width: getFrame.width, height: getFrame.height }\n await getFrame(0)\n const cw = 64\n const ch = 36\n const c = document.createElement('canvas')\n c.width = cw\n c.height = ch\n const ctx = c.getContext('2d', { willReadFrequently: true })!\n let prev: Uint8ClampedArray | null = null\n const bins: number[] = []\n const n = Math.max(1, Math.ceil(opts.durationS))\n for (let i = 0; i < n; i++) {\n const el = await getFrame(Math.min(opts.durationS, i + 0.5))\n ctx.drawImage(el, 0, 0, cw, ch)\n const d = ctx.getImageData(0, 0, cw, ch).data\n const luma = new Uint8ClampedArray(cw * ch)\n for (let p = 0; p < luma.length; p++) {\n const o = p * 4\n luma[p] = (d[o] * 299 + d[o + 1] * 587 + d[o + 2] * 114) / 1000\n }\n if (!prev) bins.push(0)\n else {\n let changed = 0\n for (let p = 0; p < luma.length; p++)\n if (Math.abs(luma[p] - prev[p]) > opts.delta) changed++\n bins.push(Math.round((changed / luma.length) * 1000) / 1000)\n }\n prev = luma\n w.__progress = (i + 1) / n\n }\n w.__done = { ok: true, bins, width: size.width, height: size.height }\n } catch (e) {\n w.__error = String((e instanceof Error && e.stack) || e)\n }\n}\n\n/** Pass 2 (in page): the moment frames, crops and the contact sheet. */\nasync function framesInPage(opts: {\n source: FrameSource\n shots: {\n id: string\n label: string\n t: number\n full: string\n crop: string | null\n region: { x: number; y: number; w: number; h: number }\n box: { x: number; y: number; w: number; h: number } | null\n }[]\n fullMax: number\n cropMax: number\n sheet: string\n}) {\n const w = window as unknown as Record<string, any>\n try {\n const getFrame = await (window as any).__digestSource(opts.source)\n const sizes: Record<string, { width: number; height: number }> = {}\n const toPng = (c: HTMLCanvasElement) =>\n new Promise<Blob>((res, rej) =>\n c.toBlob(\n (b) => (b ? res(b) : rej(new Error('toBlob failed'))),\n 'image/png',\n ),\n )\n const save = async (name: string, c: HTMLCanvasElement) => {\n await fetch('/save?name=' + name, {\n method: 'POST',\n body: await toPng(c),\n })\n sizes[name] = { width: c.width, height: c.height }\n }\n const fit = (bw: number, bh: number, max: number) => {\n const s = Math.min(1, max / Math.max(bw, bh))\n return {\n w: Math.max(1, Math.round(bw * s)),\n h: Math.max(1, Math.round(bh * s)),\n }\n }\n const tiles: { label: string; c: HTMLCanvasElement }[] = []\n for (let i = 0; i < opts.shots.length; i++) {\n const s = opts.shots[i]\n const el = await getFrame(s.t)\n const full = document.createElement('canvas')\n const f = fit(s.region.w, s.region.h, opts.fullMax)\n full.width = f.w\n full.height = f.h\n full\n .getContext('2d')!\n .drawImage(\n el,\n s.region.x,\n s.region.y,\n s.region.w,\n s.region.h,\n 0,\n 0,\n f.w,\n f.h,\n )\n await save(s.full, full)\n let tileSrc = full\n if (s.crop && s.box) {\n const crop = document.createElement('canvas')\n const k = fit(s.box.w, s.box.h, opts.cropMax)\n crop.width = k.w\n crop.height = k.h\n crop\n .getContext('2d')!\n .drawImage(el, s.box.x, s.box.y, s.box.w, s.box.h, 0, 0, k.w, k.h)\n await save(s.crop, crop)\n tileSrc = crop\n }\n const tile = document.createElement('canvas')\n const tw = 240\n const th = Math.max(1, Math.round((tw * tileSrc.height) / tileSrc.width))\n tile.width = tw\n tile.height = th\n tile.getContext('2d')!.drawImage(tileSrc, 0, 0, tw, th)\n tiles.push({ label: s.label, c: tile })\n w.__progress = (i + 1) / opts.shots.length\n }\n // The contact sheet: crops (or fulls) in time order, ids burned in.\n if (tiles.length) {\n const cols = Math.min(6, tiles.length)\n const tw = 240\n const th = Math.max(...tiles.map((t) => t.c.height))\n const rows = Math.ceil(tiles.length / cols)\n const sheet = document.createElement('canvas')\n sheet.width = cols * (tw + 8) + 8\n sheet.height = rows * (th + 26) + 8\n const ctx = sheet.getContext('2d')!\n ctx.fillStyle = '#111'\n ctx.fillRect(0, 0, sheet.width, sheet.height)\n ctx.font = '12px ui-monospace, Menlo, monospace'\n tiles.forEach((t, i) => {\n const x = 8 + (i % cols) * (tw + 8)\n const y = 8 + Math.floor(i / cols) * (th + 26)\n ctx.drawImage(t.c, x, y)\n ctx.fillStyle = '#eee'\n ctx.fillText(t.label, x, y + th + 16)\n })\n await save(opts.sheet, sheet)\n }\n w.__done = { ok: true, sizes }\n } catch (e) {\n w.__error = String((e instanceof Error && e.stack) || e)\n }\n}\n\n/** The bare page: a frame source over a <video> (seek + settle) or JPEGs. */\nexport function digestPageHtml(): string {\n return `<!doctype html><html><head><meta charset=\"utf-8\"><link rel=\"icon\" href=\"data:,\">\n<style>html,body{margin:0;background:#000}video,img{position:absolute;left:-99999px}</style>\n</head><body><script>\nwindow.__digestSource = async (source) => {\n const raf = () => new Promise((r) => requestAnimationFrame(r))\n if (source.kind === 'video') {\n const blob = await (await fetch(source.url)).blob()\n const v = document.createElement('video')\n v.muted = true\n v.preload = 'auto'\n v.src = URL.createObjectURL(blob)\n document.body.appendChild(v)\n await new Promise((res, rej) => {\n v.addEventListener('loadeddata', () => res(), { once: true })\n v.addEventListener('error', () => rej(new Error('video failed to load')), { once: true })\n })\n const settle = async () => {\n const t0 = performance.now()\n let last = ''\n while (performance.now() - t0 < 4000) {\n await raf()\n if (!v.seeking && v.readyState >= 2) {\n const now = v.currentTime.toFixed(3)\n if (now === last) return\n last = now\n } else last = ''\n }\n }\n const getFrame = async (t) => {\n const target = Math.max(0, Math.min(t, Math.max(0, (v.duration || t) - 0.02)))\n if (Math.abs(v.currentTime - target) > 0.0005 || v.readyState < 2) {\n await new Promise((res) => {\n const on = () => { v.removeEventListener('seeked', on); res() }\n v.addEventListener('seeked', on)\n v.currentTime = target\n })\n }\n await settle()\n return v\n }\n const first = await getFrame(0)\n getFrame.width = first.videoWidth\n return Object.assign(getFrame, { width: v.videoWidth, height: v.videoHeight })\n }\n const frames = source.frames\n const img = new Image()\n document.body.appendChild(img)\n const load = (url) => new Promise((res, rej) => {\n if (img.src.endsWith(url) && img.complete) return res(img)\n img.onload = () => res(img)\n img.onerror = () => rej(new Error('frame failed to load: ' + url))\n img.src = url\n })\n const getFrame = async (t) => {\n let best = frames[0]\n for (const f of frames) if (Math.abs(f.t - t) < Math.abs(best.t - t)) best = f\n await load(best.url)\n return img\n }\n const first = await getFrame(0)\n return Object.assign(getFrame, { width: first.naturalWidth, height: first.naturalHeight })\n}\nwindow.__pageReady__ = true\n</script></body></html>`\n}\n\nexport async function digestTake(\n browser: Browser | null,\n dir: string,\n opts: DigestOptions = {},\n): Promise<DigestResult> {\n const take = await loadTake(dir)\n if (!take.doc) throw new Error(`${dir} has no doc.json — run plan first`)\n const doc = take.doc\n const meta = doc.source.meta\n // Re-planned once the bins exist: the speed planner tells playback from\n // idle only with the activity witness.\n let plan = planForDigest(doc)\n // A transcript.json beside the take (Whisper's shape) is picked up\n // unasked; --transcript names another file.\n const transcript = opts.transcript ?? (await discoverTranscript(dir))\n const outDir = resolve(opts.outDir ?? join(dir, DIGEST_DIR))\n await mkdir(outDir, { recursive: true })\n const fullMax = opts.full ?? DIGEST_FULL_MAX\n const cropMax = opts.crop ?? DIGEST_CROP_MAX\n const wantFrames = opts.frames !== false && browser !== null\n const durS = meta.durationMs / 1000\n\n let bins: number[] | null = null\n let frameW: number | null = null\n let frameH: number | null = null\n let sizes: Partial<Record<string, { width: number; height: number }>> = {}\n let sheet: string | null = null\n let moments: Moment[]\n const boxes = new Map<string, PxRect>()\n\n // The frame source: screencast JPEGs when the take has them, else the video.\n let source: FrameSource = {\n kind: 'video',\n url: `/${take.paths.recordingName}`,\n }\n if (existsSync(take.paths.framesIndex) && existsSync(take.paths.framesDir)) {\n const index = await readJson<{ file: string; tMs: number }[]>(\n take.paths.framesIndex,\n )\n if (Array.isArray(index) && index.length) {\n source = {\n kind: 'frames',\n frames: index.map((f) => ({\n t: f.tMs / 1000,\n url: `/frames/${f.file}`,\n })),\n }\n }\n }\n\n if (wantFrames) {\n if (source.kind === 'video' && !existsSync(take.paths.recording))\n throw new Error(\n `${dir} has no recording — pull it with \\`vos pull --media\\` first`,\n )\n const server = await startTakeServer(dir, {\n '/digest.html': digestPageHtml(),\n })\n const context = await browser.newContext({\n viewport: { width: 640, height: 360 },\n })\n try {\n const page = await context.newPage()\n page.on('console', (m) => {\n if (m.type() === 'error')\n process.stderr.write(` [digest page] ${m.text()}\\n`)\n })\n await page.addInitScript(() => {\n ;(globalThis as unknown as Record<string, unknown>).__name = (\n f: unknown,\n ) => f\n })\n await page.goto(`${server.base}/digest.html`)\n await page.waitForFunction('window.__pageReady__ === true')\n\n // Pass 1: bins.\n void page\n .evaluate(binsInPage, { source, durationS: durS, delta: MOTION_DELTA })\n .catch(() => {})\n const b = await waitForPageDone(\n page,\n 'digest bins',\n () => {},\n 60_000 + durS * 400,\n )\n bins = b.bins as number[]\n plan = planForDigest(doc, bins)\n frameW = b.width as number\n frameH = b.height as number\n\n moments = momentsFromDoc(doc, plan, {\n bins,\n scenes: sceneChanges(bins),\n transcript,\n })\n\n // Pass 2: frames.\n const geo = frameGeometry(doc, frameW, frameH)\n const shots = moments\n .filter((m) => m.at !== null)\n .map((m) => {\n const box = cropBox(m, geo, meta)\n if (box) boxes.set(m.id, box)\n return {\n id: m.id,\n label: `${m.id} ${m.kind} ${m.source.in.toFixed(1)}s`,\n t: m.at!,\n full: `${m.id}.full.png`,\n crop: box ? `${m.id}.crop.png` : null,\n region: geo.region,\n box,\n }\n })\n await page.evaluate('window.__done = null; window.__progress = null')\n void page\n .evaluate(framesInPage, {\n source,\n shots,\n fullMax,\n cropMax,\n sheet: 'sheet.png',\n })\n .catch(() => {})\n const f = await waitForPageDone(\n page,\n 'digest frames',\n () => {},\n 60_000 + shots.length * 4_000,\n )\n sizes = f.sizes as Record<string, { width: number; height: number }>\n for (const name of Object.keys(sizes)) {\n const from = join(dir, name)\n const to = join(outDir, name)\n if (from !== to && existsSync(from)) await rename(from, to)\n }\n if (sizes['sheet.png']) sheet = 'sheet.png'\n } finally {\n await context.close()\n server.close()\n }\n } else {\n // --no-frames after a real pass (the skill re-digests after retiming to\n // read fresh OUTPUT times): the prior digest's bins, scenes and images\n // are measurements of the FOOTAGE, which retiming does not change —\n // carry them forward instead of dropping them.\n const prior = await readPriorDigest(outDir)\n bins = prior?.activity ?? null\n if (bins) plan = planForDigest(doc, bins)\n frameW = prior?.take.frameWidth ?? null\n frameH = prior?.take.frameHeight ?? null\n moments = momentsFromDoc(doc, plan, {\n bins,\n scenes: bins ? sceneChanges(bins) : [],\n transcript,\n })\n if (prior) {\n for (const m of moments) {\n const p = prior.moments.find(\n (x) =>\n x.id === m.id && x.kind === m.kind && x.source.in === m.source.in,\n )\n if (!p) continue\n for (const f of [p.full, p.crop]) {\n if (!f) continue\n const size = await pngSize(join(outDir, f))\n if (size) sizes[f] = size\n }\n if (p.box) boxes.set(m.id, p.box)\n }\n if (prior.images.sheet && existsSync(join(outDir, prior.images.sheet)))\n sheet = prior.images.sheet\n }\n }\n\n const images = new Map<string, DigestImageRef>()\n for (const m of moments) {\n const full = sizes[`${m.id}.full.png`] ? `${m.id}.full.png` : null\n const crop = sizes[`${m.id}.crop.png`] ? `${m.id}.crop.png` : null\n if (!full && !crop) continue\n images.set(m.id, {\n full,\n crop,\n box: crop ? (boxes.get(m.id) ?? null) : null,\n fullSize: full ? (sizes[full] ?? null) : null,\n cropSize: crop ? (sizes[crop] ?? null) : null,\n })\n }\n const digest = buildDigest({\n doc,\n plan,\n moments,\n outputDuration: outputDurationOf(doc),\n bins,\n frame:\n frameW !== null && frameH !== null\n ? { width: frameW, height: frameH }\n : null,\n images,\n sheet,\n style: opts.style ?? null,\n transcript,\n })\n const file = join(outDir, 'digest.json')\n const body = JSON.stringify(digest, null, 2)\n await writeFile(file, body)\n return { file, outDir, digest, bytes: Buffer.byteLength(body) }\n}\n\n/** `<take>/transcript.json` when present and well-formed; never throws. */\nasync function discoverTranscript(\n dir: string,\n): Promise<TranscriptSegment[] | null> {\n const file = join(dir, 'transcript.json')\n if (!existsSync(file)) return null\n try {\n return parseTranscript(JSON.parse(await readFile(file, 'utf8')))\n } catch {\n return null\n }\n}\n\n/** The digest already in outDir, when it parses; never throws. */\nasync function readPriorDigest(outDir: string): Promise<Digest | null> {\n try {\n const raw = JSON.parse(\n await readFile(join(outDir, 'digest.json'), 'utf8'),\n ) as Digest\n return raw.digestVersion === DIGEST_VERSION && Array.isArray(raw.moments)\n ? raw\n : null\n } catch {\n return null\n }\n}\n\n/** Width/height from a PNG header (IHDR), or null when the file is not one. */\nasync function pngSize(\n file: string,\n): Promise<{ width: number; height: number } | null> {\n try {\n const buf = await readFile(file)\n if (buf.length < 24 || buf.readUInt32BE(0) !== 0x89504e47) return null\n return { width: buf.readUInt32BE(16), height: buf.readUInt32BE(20) }\n } catch {\n return null\n }\n}\n\n/** Accept Whisper's `{segments:[…]}` or a bare `[{start,end,text}]`. */\nexport function parseTranscript(raw: unknown): TranscriptSegment[] {\n const list = Array.isArray(raw)\n ? raw\n : raw && typeof raw === 'object' && Array.isArray((raw as any).segments)\n ? (raw as any).segments\n : null\n if (!list)\n throw new Error('transcript must be [{start,end,text}] or {segments:[…]}')\n return (list as Record<string, unknown>[])\n .filter(\n (s) =>\n typeof s.start === 'number' &&\n typeof s.end === 'number' &&\n typeof s.text === 'string',\n )\n .map((s) => ({\n start: s.start as number,\n end: s.end as number,\n text: s.text as string,\n }))\n}\n","/**\n * Deliver — render one take to a release's destinations and write the kit\n * manifest. Loops the DESTINATIONS table (studio-core, generated from\n * schema/channel-specs.json): stills through framesTake at each spec's exact\n * pixels, videos through renderTake, then VERIFIES every artifact against\n * its spec (px, bytes, duration) and writes kit.json beside the assets —\n * the manifest the launch-kit skill describes, made real as a verb.\n *\n * Verification reports, it never guesses: an asset that misses its spec\n * (or a spec floor the take cannot fill — a 60 s minimum against a 35 s\n * take) lands in `skipped` with the reason in words. Store uploads stay\n * manual by policy — the verb hands the human a kit directory, it never\n * pushes to a store.\n */\nimport { mkdir, mkdtemp, rename, rm, stat, writeFile } from 'node:fs/promises'\nimport { tmpdir } from 'node:os'\nimport { join, relative, resolve } from 'node:path'\nimport { existsSync } from 'node:fs'\nimport { readFile } from 'node:fs/promises'\nimport { parseFrontmatter } from '@vosjs/shared/frontmatter'\nimport {\n CHANNEL_SPECS_VERIFIED,\n DESTINATIONS,\n cardInset,\n destinationsForChannel,\n houseLook,\n isLookKind,\n lookFromBrand,\n docOutputDuration,\n} from '@vosjs/studio-core'\nimport { loadTake } from './take'\nimport { framesTake } from './framesTake'\nimport { renderTake } from './renderTake'\nimport { momentCandidates, pickMoments } from './moments'\nimport { decodePng, differenceHash, inkCoverage } from './picture'\nimport { LOOP_DESTINATIONS, destinationMechanics } from './motionPlan'\nimport {\n findPosterDocs,\n posterClassFor,\n posterShotRect,\n posterStillTime,\n posterTextBoxes,\n} from './posterDoc'\nimport type { PosterClass } from './posterDoc'\nimport type { MomentCandidate } from './moments'\nimport type { TextBox } from './kitPicture'\nimport type { Destination, Look, LookPlacement } from '@vosjs/studio-core'\nimport type { DocOverrides } from './docOverride'\nimport type { Browser } from 'playwright'\n\n/** `--to` shorthand → channel ids (the spec's own channel slugs also work). */\nexport const CHANNEL_ALIASES: Record<string, string> = {\n ph: 'producthunt',\n yt: 'youtube',\n gh: 'github',\n li: 'linkedin',\n shorts: 'shorts-linkedin',\n}\n\n/**\n * Destinations a take cannot honestly produce: brand art, not footage.\n * They are reported in `skipped`, never silently absent from the kit.\n */\nconst NOT_FROM_FOOTAGE: Record<string, string> = {\n 'cws-icon': 'an icon is brand art, not footage — supply it from the kit',\n}\n\nexport interface DeliverOptions {\n /** Resolved channel ids (aliases already applied). */\n channels: string[]\n /** Kit directory; default `<take>/kit`. */\n outDir?: string\n /** Stamped into kit.json (`--release v2.1`). */\n release?: string\n /** Still times override (OUTPUT seconds, already parsed). */\n times?: number[]\n /** OUTPUT-time cut window applied to every video destination. */\n range?: [number, number]\n /** Concurrent chunk renders for video destinations. */\n parallel?: number\n /** In-memory doc overrides (--set / --background); lint-gated. */\n overrides?: DocOverrides\n /**\n * LAUNCH.md's roles beside the take. The POSTER roles name the document a\n * card destination renders from (`poster: <path>`, `poster-landscape`,\n * `poster-square`, `poster-portrait`, `poster-tile`); the folder\n * convention `poster/<class>/doc.json` needs no role.\n */\n launchRoles?: Record<string, string> | null\n /**\n * Keep the cut's camera and the frame chrome on SCREENSHOT-genre stills.\n * By default a store screenshot is the real page at that moment, full\n * bleed: no zoom, no tilt, no browser bar, no padding (store policy says\n * real UX, full bleed, square corners; a zoomed crop under a mac bar on a\n * gradient reads as a marketing frame, and a text-heavy page zoomed to a\n * corner reads as an empty page).\n */\n composed?: boolean\n /**\n * The card's presentation, resolved before the run (`resolveLook`): a\n * house look, the maker's BRAND.md, or null for the pre-look behaviour\n * (cards as cover crops, videos as the doc frames them). Card-genre\n * stills without a poster and every video destination ride it; the\n * screenshot genre never does (store policy: the real page, full bleed).\n */\n look?: Look | null\n onPhase?: (phase: string) => void\n onProgress?: (fraction: number) => void\n}\n\n/** One produced asset, the launch-kit skill's kit.json entry shape. */\nexport interface KitAsset {\n channel: string\n asset: string\n /** The destination id (`cws-screenshot`) the entry was rendered for. */\n destination: string\n path: string\n w: number\n h: number\n bytes: number\n seconds: number | null\n frameTime: number | null\n /** Where the pixels came from: the take (absent = take), or a poster DOCUMENT beside it. */\n source?: 'poster'\n /** The poster document a card rendered from: its class, its file (relative to the take), the vos it tracks. */\n poster?: { class: PosterClass; file: string; vosId?: string }\n /** Where the words landed, as fractions of the asset (the picture checks read them). */\n text?: TextBox[]\n /** Where the card sits on a poster, fractions of the asset (a bleed runs past the edge). */\n shot?: { x: number; y: number; w: number; h: number }\n /** The card runs past both edges: a close crop of the subject (a tile), so the picture checks skip the card band. */\n crop?: boolean\n /**\n * A screenshot-genre still rendered with the cut's camera and chrome\n * (`--composed`), which store policy refuses; the picture checks read it.\n */\n composed?: boolean\n}\n\nexport interface KitManifest {\n release: string | null\n /** The look the cards and cuts were presented in (null = none). */\n look: string | null\n take: string\n produced: string\n /** channel-specs.json's own verified date — the spec sheet's freshness. */\n specsVerified: string\n /** The still moments, in order, and where each came from. */\n moments: MomentCandidate[]\n skipped: string[]\n assets: KitAsset[]\n}\n\nexport interface DeliverResult {\n kit: KitManifest\n kitFile: string\n outDir: string\n}\n\n/** Resolve `--to` entries to channel ids; UsageError-shaped message on junk. */\nexport function resolveChannels(raw: string): string[] {\n const known = [...new Set(DESTINATIONS.map((d) => d.channel))]\n const wanted = raw\n .split(',')\n .map((s) => s.trim().toLowerCase())\n .filter(Boolean)\n if (!wanted.length) throw new Error('--to expects a channel list')\n if (wanted.includes('all')) return known\n const out: string[] = []\n for (const w of wanted) {\n const id = CHANNEL_ALIASES[w] ?? w\n if (!known.includes(id))\n throw new Error(\n `unknown channel \"${w}\" — channels: ${known.join(', ')} (or all)`,\n )\n if (!out.includes(id)) out.push(id)\n }\n return out\n}\n\n/**\n * Read the brand kit's frontmatter beside a take: `BRAND.md` in the take\n * directory, else in its parent (a release's `media/` folder holds the\n * takes under it), else an explicit path. Null when there is none.\n */\nexport async function readBrandBesideTake(\n dir: string,\n explicit?: string,\n): Promise<{ file: string; roles: Record<string, string> } | null> {\n const candidates = explicit\n ? [explicit]\n : [join(dir, 'BRAND.md'), join(dir, '..', 'BRAND.md')]\n for (const file of candidates) {\n if (!existsSync(file)) continue\n const roles = parseFrontmatter(await readFile(file, 'utf8'))\n return { file, roles }\n }\n return null\n}\n\n/** LAUNCH.md beside a take (or its parent, or an explicit path): the release's roles. */\nexport async function readLaunchBesideTake(\n dir: string,\n explicit?: string,\n): Promise<{ file: string; roles: Record<string, string> } | null> {\n const candidates = explicit\n ? [explicit]\n : [join(dir, 'LAUNCH.md'), join(dir, '..', 'LAUNCH.md')]\n for (const file of candidates) {\n if (!existsSync(file)) continue\n return { file, roles: parseFrontmatter(await readFile(file, 'utf8')) }\n }\n return null\n}\n\n/**\n * The look a run presents its cards and cuts in, in precedence: `--look\n * none` (the pre-look behaviour), `--look <kind>` (a house look), the\n * brand kit beside the take (its `look` role, else its own ground decides),\n * then the house gradient. Says where it came from, for the phase note.\n */\nexport async function resolveLook(\n dir: string,\n opts: { look?: string; brand?: string },\n): Promise<{\n look: Look | null\n from: string\n roles: Record<string, string> | null\n}> {\n const brand = await readBrandBesideTake(dir, opts.brand)\n const roles = brand?.roles ?? null\n if (opts.look === 'none') return { look: null, from: '--look none', roles }\n if (opts.look !== undefined) {\n if (!isLookKind(opts.look))\n throw new Error(\n `--look \"${opts.look}\" — one of plate | gradient | dark | none`,\n )\n return { look: houseLook(opts.look), from: `--look ${opts.look}`, roles }\n }\n if (brand) {\n const look = lookFromBrand(brand.roles)\n return { look, from: `${brand.file} (${look.kind})`, roles }\n }\n return {\n look: houseLook('gradient'),\n from: 'the house gradient (no BRAND.md beside the take)',\n roles,\n }\n}\n\n/**\n * The overrides that present the card in a look at one destination size:\n * the ground, the placement (inset from the footage's aspect), the radius,\n * both shadow layers and the hairline; a still also releases the camera\n * and hides the cursor (a card shows the whole window at rest, and a\n * zoomed crop inside a small card reads as a broken screenshot). The\n * document's bar kind stays. Pure, so the policy is testable.\n */\nexport function lookOverrides(\n look: Look,\n placement: LookPlacement,\n size: { w: number; h: number },\n video: { w: number; h: number },\n opts: { still: boolean; keepMedia?: boolean },\n): string[] {\n const inset = cardInset(look, size, video, placement)\n const set = [\n 'frame.fit=contain',\n `frame.background=${JSON.stringify(look.ground)}`,\n `frame.inset=${JSON.stringify(inset)}`,\n `frame.radius=${look.radius}`,\n `frame.shadow=${look.shadow}`,\n `frame.shadowContact=${look.shadowContact}`,\n `frame.border=${look.border}`,\n ]\n if (look.shadowColor) set.push(`frame.shadowColor=${look.shadowColor}`)\n if (look.border > 0) {\n set.push('frame.borderWidth=1')\n set.push(`frame.borderColor=${look.borderColor ?? '#000000'}`)\n }\n if (!opts.keepMedia) set.push('frame.backgroundMedia=null')\n if (opts.still) {\n set.push(\n 'zoom=[]',\n 'tilt=[]',\n 'cursor.visible=false',\n 'cursor.clickFx.style=none',\n )\n }\n return set\n}\n\n/** The probe's width: enough to read ink and a hash, cheap to capture. */\nconst PROBE_WIDTH = 640\n\n/**\n * The still moments of a take: candidates from the step timeline, the\n * zoom apexes and the spread (moments.ts), captured ONCE at probe size as\n * the real page (camera released, no chrome), then kept only when\n * populated and distinct. What is dropped is said in `skipped`.\n */\nasync function pickStillTimes(\n browser: Browser,\n dir: string,\n doc: NonNullable<Awaited<ReturnType<typeof loadTake>>['doc']>,\n duration: number,\n opts: DeliverOptions,\n): Promise<{ times: number[]; moments: MomentCandidate[]; notes: string[] }> {\n const { candidates, dropped } = momentCandidates(doc, duration)\n const notes: string[] = []\n if (dropped > 0)\n notes.push(\n `${dropped} of ${doc.zoom.length} zoom apex(es) fall outside the cut`,\n )\n if (!candidates.length) return { times: [], moments: [], notes }\n const meta = doc.source.meta\n const vw = meta.captureWidth ?? meta.width\n const vh = meta.captureHeight ?? meta.height\n const probeDir = await mkdtemp(join(tmpdir(), 'vos-moments-'))\n try {\n const probe = await framesTake(browser, dir, {\n times: candidates.map((c) => c.time),\n width: PROBE_WIDTH,\n height: Math.max(2, Math.round((PROBE_WIDTH * vh) / vw / 2) * 2),\n outDir: probeDir,\n overrides: {\n ...opts.overrides,\n set: [...SCREENSHOT_DEFAULTS, ...(opts.overrides?.set ?? [])],\n },\n })\n // The probe writes its frames in time order; the candidates are in\n // rung order (steps first), which is the order the pick must keep, so\n // measures are joined by TIME, never by index.\n const byTime = new Map<number, { ink: number; hash: string }>()\n for (const frame of probe.frames) {\n const img = decodePng(new Uint8Array(await readFile(frame.file)))\n if (!img) continue\n const whole = { x: 0, y: 0, w: img.w, h: img.h }\n byTime.set(+frame.time.toFixed(3), {\n ink: inkCoverage(img, whole),\n hash: differenceHash(img, whole),\n })\n }\n const measured = []\n for (const c of candidates) {\n const m = byTime.get(+c.time.toFixed(3))\n if (m) measured.push({ time: c.time, ...m })\n }\n const pick = pickMoments(measured)\n const kept = candidates.filter((c) => pick.times.includes(c.time))\n const bySource = (s: MomentCandidate['source']) =>\n candidates.filter((c) => c.source === s).length\n notes.push(\n `${candidates.length} candidate(s): ${bySource('step')} from steps, ${bySource('zoom')} from zoom apexes, ${bySource('spread')} from the spread; ${kept.length} kept`,\n )\n return {\n times: pick.times,\n moments: kept,\n notes: [...notes, ...pick.dropped.map((d) => `moment: ${d}`)],\n }\n } finally {\n await rm(probeDir, { recursive: true, force: true })\n }\n}\n\n/**\n * A byte-ceiling miss in words that survive a 1% overshoot: ceil the size,\n * floor the ceiling, so the two figures can never round to the same number\n * (the dogfood printed \"1.0MB exceeds the 1.0MB ceiling\").\n */\nconst overCeiling = (bytes: number, maxBytes: number) =>\n `${Math.ceil(bytes / 1024)} KB exceeds the ${Math.floor(maxBytes / 1024)} KB ceiling`\n\nconst specWords = (d: Destination) => {\n const parts = [`${d.px.w}x${d.px.h}`]\n if (d.minSeconds !== undefined || d.maxSeconds !== undefined)\n parts.push(`${d.minSeconds ?? 0}-${d.maxSeconds ?? '∞'}s`)\n if (d.maxBytes !== undefined)\n parts.push(`≤${(d.maxBytes / 1024 / 1024).toFixed(0)}MB`)\n return parts.join(' ')\n}\n\n/**\n * The in-memory overrides a still destination rides, in apply order (the\n * user's own --set entries come LAST, so they win): the channel's fit, then\n * the screenshot genre's full-bleed defaults unless `composed` keeps the\n * cut's camera and chrome. Pure, so the policy is testable without a\n * browser.\n */\n/** The real page, edge to edge: no chrome, no cursor dot, no click ring. */\nexport const FULL_BLEED = [\n 'frame.padding=0',\n 'frame.radius=0',\n 'frame.shadow=0',\n 'frame.border=0',\n 'frame.browserBar.kind=none',\n 'cursor.visible=false',\n 'cursor.clickFx.style=none',\n]\n/** A store screenshot: the real page at that moment, the camera released. */\nexport const SCREENSHOT_DEFAULTS = [...FULL_BLEED, 'zoom=[]', 'tilt=[]']\n\nexport function stillOverridesFor(\n d: Pick<Destination, 'fit' | 'genre'> & { px?: Destination['px'] },\n opts: Pick<DeliverOptions, 'overrides' | 'composed' | 'look'>,\n video?: { w: number; h: number },\n): DocOverrides | undefined {\n const set: string[] = []\n if (d.genre === 'screenshot' && !opts.composed) {\n if (d.fit === 'cover') set.push('frame.fit=cover')\n set.push(...SCREENSHOT_DEFAULTS)\n } else if (\n d.genre === 'card' &&\n !opts.composed &&\n opts.look &&\n video &&\n d.px\n ) {\n // A card with no poster program is the whole window on the look's\n // ground: centred with room around it, or, on a frame too wide to hold\n // it, given headroom and run off the bottom (the feature-clip grammar).\n set.push(\n ...lookOverrides(opts.look, 'card', d.px, video, {\n still: true,\n keepMedia: opts.overrides?.background !== undefined,\n }),\n )\n } else {\n if (d.fit === 'cover') set.push('frame.fit=cover')\n // No look: a card with no poster program is a cover crop of the real\n // page (the cut's camera kept): never the card chrome and the padding\n // band, which a 2.5:1 marquee turns into a browser bar over a gradient.\n if (d.genre === 'card' && !opts.composed) set.push(...FULL_BLEED)\n }\n set.push(...(opts.overrides?.set ?? []))\n if (!set.length) return opts.overrides\n return { ...opts.overrides, set }\n}\n\nexport async function deliverTake(\n browser: Browser,\n dir: string,\n opts: DeliverOptions,\n): Promise<DeliverResult> {\n const take = await loadTake(dir)\n if (!take.doc) throw new Error(`${dir} has no doc.json — run plan first`)\n const doc = take.doc\n\n // The output's end: the clips after the footage count, so an end card\n // is inside every cut and the loop's cap reads the whole picture.\n const duration = docOutputDuration(doc)\n const videoSeconds = opts.range\n ? Math.min(opts.range[1], duration) - Math.min(opts.range[0], duration)\n : duration\n const outDir = resolve(opts.outDir ?? join(dir, 'kit'))\n await mkdir(outDir, { recursive: true })\n\n const destinations = opts.channels.flatMap((c) => destinationsForChannel(c))\n const assets: KitAsset[] = []\n const skipped: string[] = []\n\n let stillTimes: number[]\n let moments: MomentCandidate[]\n if (opts.times?.length) {\n stillTimes = opts.times\n moments = opts.times.map((time) => ({ time, source: 'times' as const }))\n } else {\n opts.onPhase?.('moments (the step timeline, the zoom apexes, the spread)')\n const picked = await pickStillTimes(browser, dir, doc, duration, opts)\n stillTimes = picked.times\n moments = picked.moments\n for (const n of picked.notes) {\n if (n.startsWith('moment: ')) skipped.push(n)\n else opts.onPhase?.(`note: ${n}`)\n }\n }\n const meta0 = doc.source.meta\n const video = {\n w: meta0.captureWidth ?? meta0.width,\n h: meta0.captureHeight ?? meta0.height,\n }\n /**\n * A video destination rides the look in the hero placement, camera kept,\n * then the destination's MECHANICS (a loop plays no entrance, end card\n * or sound; a silent channel mutes the bed; a 9:16 destination reframes\n * the card), then the user's own sets, which win. The cut's motion\n * (entrance, end card, captions, bed, clicks) is the DOCUMENT's, written\n * by `vos plan`; nothing is composed here.\n */\n const videoOverrides = (d: Destination): DocOverrides | undefined => {\n const set: string[] = []\n if (opts.look) {\n set.push(\n ...lookOverrides(opts.look, 'hero', d.px, video, {\n still: false,\n keepMedia: opts.overrides?.background !== undefined,\n }),\n )\n }\n const mech = destinationMechanics(d, doc)\n set.push(...mech.set)\n if (mech.notes.length) opts.onPhase?.(`${d.id}: ${mech.notes.join(', ')}`)\n set.push(...(opts.overrides?.set ?? []))\n if (!set.length && !mech.unset.length) return opts.overrides\n return { ...opts.overrides, set, unset: mech.unset }\n }\n\n // The poster leg: a CARD destination renders from the POSTER DOCUMENT of\n // its aspect class, found beside the take (poster/<class>/doc.json, or\n // named in LAUNCH.md), at the document's REST (the trailing hold's\n // start), so the still is a frame of the poster's own video by\n // construction. Deliver renders and verifies; the composition is the\n // document's, written by an agent or the studio. A class with no\n // document falls to the take's own frame, said once in words.\n const posters = await findPosterDocs(dir, opts.launchRoles)\n const posterCardIds = new Set<string>()\n const missing = new Set<PosterClass>()\n for (const d of destinations) {\n if (d.kind === 'video' || d.genre !== 'card' || NOT_FROM_FOOTAGE[d.id])\n continue\n const cls = posterClassFor(d.px)\n const ref = posters[cls]\n if (!ref) {\n missing.add(cls)\n continue\n }\n posterCardIds.add(d.id)\n const label = `${d.channel} ${d.asset}`\n const posterDuration = docOutputDuration(ref.doc)\n const time = posterStillTime(ref.doc, posterDuration)\n opts.onPhase?.(\n `${label} (${specWords(d)}) from ${ref.from}${ref.vosId ? ` ${ref.vosId}` : ''}, the rest at ${time.toFixed(2)}s`,\n )\n const shotDir = await mkdtemp(join(tmpdir(), 'vos-poster-'))\n try {\n const captured = await framesTake(browser, ref.takeDir, {\n times: [time],\n width: d.px.w,\n height: d.px.h,\n outDir: shotDir,\n doc: ref.doc,\n overrides: opts.overrides,\n })\n const to = join(outDir, `${d.id}.png`)\n await rename(captured.frames[0].file, to)\n const bytes = (await stat(to)).size\n if (d.maxBytes !== undefined && bytes > d.maxBytes) {\n skipped.push(\n `${label}: ${overCeiling(bytes, d.maxBytes)} (kept at ${to})`,\n )\n continue\n }\n const shot = posterShotRect(ref.doc, d.px)\n assets.push({\n channel: d.channel,\n asset: d.asset,\n destination: d.id,\n path: relative(outDir, to),\n w: d.px.w,\n h: d.px.h,\n bytes,\n seconds: null,\n frameTime: time,\n source: 'poster',\n poster: {\n class: cls,\n file: relative(dir, ref.file),\n ...(ref.vosId ? { vosId: ref.vosId } : {}),\n },\n text: posterTextBoxes(ref.doc, d.px, time),\n shot,\n ...(shot.x < 0 && shot.x + shot.w > 1 ? { crop: true } : {}),\n })\n } finally {\n await rm(shotDir, { recursive: true, force: true })\n }\n }\n if (missing.size) {\n const classes = [...missing].sort().join(', ')\n skipped.push(\n `note: no poster document for the ${classes} class${missing.size > 1 ? 'es' : ''} beside the take (poster/<class>/doc.json, or LAUNCH.md poster:), so those cards are the take's own frame`,\n )\n }\n\n for (const d of destinations) {\n const label = `${d.channel} ${d.asset}`\n const excuse = NOT_FROM_FOOTAGE[d.id]\n if (excuse) {\n skipped.push(`${label}: ${excuse}`)\n continue\n }\n if (posterCardIds.has(d.id)) continue // rendered from the poster above\n\n if (d.kind === 'video') {\n // A spec floor the take cannot fill is a SKIP with the reason in\n // words, never padding — and never minutes of render first.\n if (d.minSeconds !== undefined && videoSeconds < d.minSeconds) {\n skipped.push(\n `${label}: spec wants ${d.minSeconds}-${d.maxSeconds ?? '∞'}s, the ${opts.range ? 'range' : 'take'} is ${videoSeconds.toFixed(0)}s`,\n )\n continue\n }\n // A LOOP destination the take outruns takes the take's FIRST seconds\n // up to its cap (a loop is a texture, not a story); a story\n // destination is skipped with the reason, never cut blind.\n let range = opts.range\n let seconds = videoSeconds\n if (d.maxSeconds !== undefined && videoSeconds > d.maxSeconds) {\n if (LOOP_DESTINATIONS.has(d.id) && !opts.range) {\n range = [0, d.maxSeconds]\n seconds = d.maxSeconds\n opts.onPhase?.(\n `note: ${label} takes the first ${d.maxSeconds}s of the ${videoSeconds.toFixed(0)}s take (a loop's cap)`,\n )\n } else {\n skipped.push(\n `${label}: spec caps at ${d.maxSeconds}s, the take is ${videoSeconds.toFixed(0)}s — cut it (--range, or trim segments in doc.json)`,\n )\n continue\n }\n }\n opts.onPhase?.(`${label} (${specWords(d)})`)\n const outFile = join(outDir, `${d.id}.${d.format}`)\n // A byte ceiling becomes a bitrate budget (leave 15% for container +\n // audio); never raise the default for ceilings that don't bind.\n const bitrate =\n d.maxBytes !== undefined\n ? Math.min(\n 10_000_000,\n Math.floor(((d.maxBytes * 8) / seconds) * 0.85),\n )\n : undefined\n const result = await renderTake(browser, dir, outFile, {\n width: d.px.w,\n height: d.px.h,\n format: 'mp4',\n parallel: opts.parallel,\n range,\n bitrate,\n overrides: videoOverrides(d),\n onProgress: opts.onProgress,\n })\n if (d.maxBytes !== undefined && result.bytes > d.maxBytes) {\n skipped.push(\n `${label}: ${overCeiling(result.bytes, d.maxBytes)} (kept at ${outFile})`,\n )\n continue\n }\n assets.push({\n channel: d.channel,\n asset: d.asset,\n destination: d.id,\n path: relative(outDir, outFile),\n w: result.width,\n h: result.height,\n bytes: result.bytes,\n seconds: result.duration,\n frameTime: null,\n })\n continue\n }\n\n // Stills: capture at the spec's exact pixels; a set takes up to its\n // count ceiling of the hero times, a single still takes the first.\n const wanted =\n d.kind === 'still-set'\n ? stillTimes.slice(0, d.count?.max ?? stillTimes.length)\n : stillTimes.slice(0, 1)\n opts.onPhase?.(`${label} (${specWords(d)}, ${wanted.length} still(s))`)\n // The destination's fit is the channel's demand (\"fill the region\"): a\n // cover still rides an in-memory frame.fit override (cover fit), so\n // a 16:9 take fills a 440x280 tile instead of striping the background.\n // The doc on disk is untouched; an explicit --set frame.fit wins (later\n // entries apply last in docOverride).\n const overrides = stillOverridesFor(d, opts, video)\n const captured = await framesTake(browser, dir, {\n times: wanted,\n width: d.px.w,\n height: d.px.h,\n outDir,\n overrides,\n })\n for (let i = 0; i < captured.frames.length; i++) {\n const frame = captured.frames[i]\n const name =\n captured.frames.length > 1 ? `${d.id}-${i + 1}.png` : `${d.id}.png`\n const to = join(outDir, name)\n await rename(frame.file, to)\n const bytes = (await stat(to)).size\n if (d.maxBytes !== undefined && bytes > d.maxBytes) {\n skipped.push(\n `${label}: ${overCeiling(bytes, d.maxBytes)} (kept at ${to})`,\n )\n continue\n }\n assets.push({\n channel: d.channel,\n asset: d.asset,\n destination: d.id,\n path: relative(outDir, to),\n w: captured.width,\n h: captured.height,\n bytes,\n seconds: null,\n frameTime: frame.time,\n ...(d.genre === 'screenshot' && opts.composed\n ? { composed: true }\n : {}),\n })\n }\n if (d.count && captured.frames.length < d.count.min) {\n skipped.push(\n `${label}: spec wants ${d.count.min}-${d.count.max}, only ${captured.frames.length} still time(s) available — pass --times`,\n )\n }\n }\n\n const kit: KitManifest = {\n release: opts.release ?? null,\n look: opts.look?.kind ?? null,\n take: dir,\n produced: new Date().toISOString(),\n specsVerified: CHANNEL_SPECS_VERIFIED,\n moments,\n skipped,\n assets,\n }\n const kitFile = join(outDir, 'kit.json')\n await writeFile(kitFile, JSON.stringify(kit, null, 2))\n return { kit, kitFile, outDir }\n}\n","/**\n * Render — lower the take's ProjectDoc to the studio composition, compile it,\n * and run the deterministic export frame-loop (seek → settle → capture →\n * mediabunny mux) through the shared renderAnimation harness. Same pipeline\n * as the studio's export; --parallel N shards the timeline into concurrent\n * chunk pages (see renderAnimation.ts).\n */\nimport { writeFile } from 'node:fs/promises'\nimport { compileVosConfig } from '@vosjs/core'\nimport {\n audioProducerCode,\n dataHasAudio,\n studioEntryData,\n} from '@vosjs/render-core'\nimport {\n lowerToComposition,\n resolveExportSize,\n studioAudioPlan,\n} from '@vosjs/studio-core'\nimport { loadTake } from './take'\nimport { renderAnimation } from './renderAnimation'\nimport {\n applyAndValidate,\n hasOverrides,\n resolveBackdropSlug,\n} from './docOverride'\nimport type { EnvelopePoint, LoweredAudioClip } from '@vosjs/studio-core'\nimport type { DocOverrides } from './docOverride'\nimport type { Browser } from 'playwright'\n\nconst VIDEO_TOKEN = '__VOILA_CLI_VIDEO__'\n\nexport interface RenderTakeOptions {\n width?: number\n height?: number\n fps?: number\n format?: 'webm' | 'mp4'\n /** Concurrent chunk renders (timeline sharding); 1 = single-flight. */\n parallel?: number\n /** OUTPUT-time subrange [start, end) seconds — spot-check a doc edit cheaply. */\n range?: [number, number]\n /** Draft mode: half resolution + low bitrate, for iteration only. */\n draft?: boolean\n /** Encoder bitrate override (a destination's byte ceiling as a budget). */\n bitrate?: number\n /** In-memory doc overrides (--set / --frame / --background); lint-gated. */\n overrides?: DocOverrides\n onPhase?: (phase: string) => void\n onProgress?: (fraction: number) => void\n}\n\nexport interface RenderTakeResult {\n out: string\n bytes: number\n width: number\n height: number\n fps: number\n duration: number\n zoomSpans: number\n clicks: number\n /** Number of chunks rendered (1 unless --parallel raised it). */\n chunks: number\n /** An audio track was mixed + muxed (doc.audio clips / mic). */\n audio: boolean\n}\n\nexport async function renderTake(\n browser: Browser,\n dir: string,\n outFile: string,\n opts: RenderTakeOptions,\n): Promise<RenderTakeResult> {\n const take = await loadTake(dir)\n if (!take.doc) throw new Error(`${dir} has no doc.json — run plan first`)\n const doc = take.doc\n\n // Product-surface overrides (--set/--frame/--background): patch the doc in\n // memory + lint before anything renders (doc.json on disk is untouched).\n if (opts.overrides && hasOverrides(opts.overrides)) {\n await resolveBackdropSlug(opts.overrides)\n applyAndValidate(doc, opts.overrides)\n }\n\n // Same short-edge × aspect sizing as the studio's Export button (a preset\n // alone would letterbox portrait/native docs into a fixed 16:9 canvas).\n const res = resolveExportSize(doc)\n // Draft: half resolution (even), low bitrate — iteration speed over quality.\n const half = (n: number) => Math.max(2, Math.round(n / 2 / 2) * 2)\n const width = opts.width ?? (opts.draft ? half(res.width) : res.width)\n const height = opts.height ?? (opts.draft ? half(res.height) : res.height)\n const fps = opts.fps ?? doc.export.fps\n const format = opts.format ?? 'webm'\n\n opts.onPhase?.('compile')\n doc.source.videoKey = VIDEO_TOKEN\n const lowered = lowerToComposition(doc)\n // Render-page modes, never stored in the doc: the recording's frames come\n // from the WebCodecs sequential decoder by PTS instead of an element seek\n // and a settle wait per frame, and the page keeps the recording as a Blob\n // so the decoder reads the bytes the element already holds. The lowering\n // fails open at every rung (no VideoDecoder, an undecodable track, a\n // dimension mismatch), so a browser without the path keeps the old one.\n const captureData = {\n ...lowered.data,\n videoDecodeMode: 'webcodecs',\n videoFetchMode: 'blob',\n }\n const animationCode = compileVosConfig(\n { ...lowered.config, data: captureData } as never,\n { tweenEngine: 'vos' },\n )\n const duration = lowered.duration\n const clicks = Array.isArray(lowered.data.clicks)\n ? (lowered.data.clicks as unknown[]).length\n : 0\n\n // Range render: clamp to the timeline, shift the frame clock, keep output\n // timestamps zero-based (the clip plays standalone).\n let frameOffset = 0\n let renderDuration = duration\n if (opts.range) {\n const start = Math.max(0, Math.min(opts.range[0], duration))\n const end = Math.max(start, Math.min(opts.range[1], duration))\n if (end - start <= 0)\n throw new Error(\n `--range ${opts.range[0]}..${opts.range[1]} is empty for a ${duration.toFixed(1)}s timeline`,\n )\n frameOffset = Math.round(start * fps)\n renderDuration = end - start\n }\n\n // Audio (doc.audio clips / mic) muxes in the SAME render — single-flight\n // only: chunks stay silent by design. A --range clip keeps its audio: the\n // producer mixes the whole timeline and the page slices the range window\n // (a cut-down is a deliverable, not just a spot check).\n let parallel = opts.parallel\n // The clips ride the studio stack entry, rendered as ONE engine\n // audio plan (studio-core builds it, the page's producer mixes it).\n const studioEntry = studioEntryData(lowered.stack)\n const studioClips = Array.isArray(studioEntry?.audio)\n ? (studioEntry.audio as LoweredAudioClip[])\n : []\n const audioPlan = studioClips.length\n ? studioAudioPlan(\n studioClips,\n Array.isArray(studioEntry?.duckEnv)\n ? (studioEntry.duckEnv as EnvelopePoint[])\n : [],\n duration,\n )\n : null\n const audioWanted = dataHasAudio(lowered.data, undefined, audioPlan)\n if (audioWanted && (parallel ?? 1) > 1) {\n parallel = 1\n opts.onPhase?.(\n 'note: audio present — forcing single-flight (--parallel ignored)',\n )\n }\n\n opts.onPhase?.('render')\n const result = await renderAnimation(browser, {\n animationCode,\n workDir: dir,\n videoFile: take.paths.recordingName,\n videoToken: VIDEO_TOKEN,\n width,\n height,\n fps,\n duration: renderDuration,\n format,\n parallel,\n frameOffset,\n bitrate: opts.bitrate ?? (opts.draft ? 3_000_000 : undefined),\n audio: audioWanted\n ? {\n producerCode: audioProducerCode({ plan: audioPlan }),\n data: lowered.data,\n duration,\n }\n : undefined,\n onProgress: opts.onProgress,\n })\n await writeFile(outFile, result.bytes)\n\n return {\n out: outFile,\n bytes: result.bytes.length,\n width,\n height,\n fps,\n duration: renderDuration,\n zoomSpans: doc.zoom.length,\n clicks,\n chunks: result.chunks,\n audio: audioWanted,\n }\n}\n","/**\n * The moment: which instants of a take become its stills. Three rungs, in\n * order, each pure: the STEP timeline (every gesture's end plus a settle,\n * so the frame shows the response and not the travel), the zoom apexes\n * (the camera's own picks), an even spread. Then two guards over what was\n * actually captured: candidates that hash alike collapse to one (a kit of\n * eight crops of one frame is the failure this exists for), and a blank\n * candidate (a wallpaper, an empty canvas, a flat panel) is dropped with\n * the reason in words. No model; the numbers come from the pixels.\n */\nimport { ratedSegments, spanOutputExtent } from '@vosjs/studio-core'\nimport { hammingDistance } from './picture'\nimport type { ProjectDoc, StepSpan } from '@vosjs/studio-core'\n\n/** Seconds after a gesture's end before the frame is read: the response has landed. */\nexport const STEP_SETTLE_SECONDS = 0.4\n\n/** Steps that are not gestures: nothing happened on screen at their end. */\nconst NOT_A_GESTURE = new Set(['wait', 'goto', 'sleep'])\n\nexport interface MomentCandidate {\n /** OUTPUT seconds. */\n time: number\n /** Where it came from. */\n source: 'step' | 'zoom' | 'spread' | 'times'\n /** The step's id (or index) when source is 'step'. */\n step?: string | number\n}\n\n/**\n * Candidate still times for a take, in rung order. Steps first (skipped\n * steps and waits excluded, and a step whose settled instant falls outside\n * the cut drops silently), then zoom apexes, then the spread; duplicates\n * within 0.25 s are merged. `dropped` counts zoom apexes the cut trimmed\n * out, for the phase note.\n */\nexport function momentCandidates(\n doc: ProjectDoc,\n duration: number,\n): { candidates: MomentCandidate[]; dropped: number } {\n const rated = ratedSegments(doc)\n const out: MomentCandidate[] = []\n const push = (c: MomentCandidate) => {\n if (c.time < 0 || c.time > duration) return\n if (out.some((o) => Math.abs(o.time - c.time) < 0.25)) return\n out.push(c)\n }\n const steps = doc.source.meta.steps ?? []\n for (let i = 0; i < steps.length; i++) {\n const s = steps[i]\n if (s.skipped || NOT_A_GESTURE.has(s.do)) continue\n const t = stepOutputTime(rated, s, settleAfter(steps, i))\n if (t === null) continue\n push({ time: t, source: 'step', step: s.id ?? s.step })\n }\n let dropped = 0\n const apexes: number[] = []\n for (const z of doc.zoom) {\n const ext = spanOutputExtent(rated, z.in, z.out)\n if (ext) apexes.push((ext.start + ext.end) / 2)\n else dropped++\n }\n for (const t of apexes.sort((a, b) => a - b))\n push({ time: t, source: 'zoom' })\n if (!out.length) {\n for (const p of [0.1, 0.3, 0.5, 0.7, 0.9])\n push({ time: p * duration, source: 'spread' })\n }\n return { candidates: out, dropped }\n}\n\n/**\n * How long after a gesture's end its frame is read. The script's author\n * says it when a `wait` follows the step (a click that navigates, a hover\n * that opens a menu: the wait IS the response landing), so the moment is\n * that wait's end; otherwise the default settle.\n */\nexport function settleAfter(steps: StepSpan[], i: number): number {\n const next = steps[i + 1]\n if (next && next.do === 'wait' && !next.skipped)\n return Math.max(0, next.tEnd - steps[i].tEnd)\n return STEP_SETTLE_SECONDS\n}\n\n/**\n * A step's settled instant in OUTPUT seconds (its gesture end plus the\n * settle, mapped through the cut), or null when the cut trimmed it out.\n */\nexport function stepOutputTime(\n rated: ReturnType<typeof ratedSegments>,\n step: Pick<StepSpan, 'tStart' | 'tEnd'>,\n settle: number,\n): number | null {\n const src = step.tEnd + settle\n const ext = spanOutputExtent(rated, src, src + 0.001)\n if (!ext) return null\n return ext.start\n}\n\n/**\n * Resolve a `--times` entry of the form `step:<id>[+offset|-offset]` (the\n * id from actions.json, or the step's index) against the take's step\n * timeline, in OUTPUT seconds. Null when the entry is not a step form;\n * throws when the step is unknown or trimmed out.\n */\nexport function resolveStepTime(doc: ProjectDoc, entry: string): number | null {\n const m = /^step:([^+-]+)([+-]\\d+(?:\\.\\d+)?)?$/.exec(entry.trim())\n if (!m) return null\n const key = m[1]\n const offset = m[2] ? Number(m[2]) : STEP_SETTLE_SECONDS\n const steps = doc.source.meta.steps ?? []\n const step =\n steps.find((s) => s.id === key) ??\n (/^\\d+$/.test(key) ? steps.find((s) => s.step === Number(key)) : undefined)\n if (!step) {\n const known = steps\n .map((s) => s.id ?? String(s.step))\n .filter((s) => s.length)\n throw new Error(\n `--times ${entry}: no step \"${key}\" in the take's step timeline${known.length ? ` (steps: ${known.join(', ')})` : ' (the take carries none: record it with the current CLI)'}`,\n )\n }\n const t = stepOutputTime(ratedSegments(doc), step, offset)\n if (t === null)\n throw new Error(\n `--times ${entry}: step \"${key}\" (${step.tEnd.toFixed(2)}s in the recording) falls outside the cut`,\n )\n return t\n}\n\nexport interface CandidateMeasure {\n time: number\n /** Ink coverage inside the frame's subject, 0..1. */\n ink: number\n /** Difference hash of the subject. */\n hash: string\n}\n\nexport interface MomentPick {\n /** Times that survive, in candidate order. */\n times: number[]\n /** What was dropped, in words. */\n dropped: string[]\n}\n\n/** Hamming bits under which two candidates are one frame. */\nexport const DUPLICATE_BITS = 6\n\n/**\n * The relative floor's cap: a frame with this much ink is populated no\n * matter how dense the take's other pages are (a gallery grid reads 90%+\n * and must not make a watch page at 30% read as blank).\n */\nexport const POPULATED_INK = 0.12\n\n/**\n * Keep the candidates that are populated and distinct. The blank floor is\n * relative to the take (a fraction of the median ink across candidates,\n * with an absolute floor), so a dense page and a sparse app are each held\n * to their own norm; duplicates collapse to the FIRST of a pair, since\n * candidates arrive in rung order (a step beats an apex beats the spread).\n */\nexport function pickMoments(\n measured: CandidateMeasure[],\n opts: { minInk?: number; relativeInk?: number; duplicateBits?: number } = {},\n): MomentPick {\n const minInk = opts.minInk ?? 0.06\n const relative = opts.relativeInk ?? 0.4\n const bits = opts.duplicateBits ?? DUPLICATE_BITS\n const inks = measured.map((m) => m.ink).sort((a, b) => a - b)\n const median = inks[inks.length >> 1] ?? 0\n const floor = Math.max(minInk, Math.min(POPULATED_INK, median * relative))\n const kept: CandidateMeasure[] = []\n const dropped: string[] = []\n for (const m of measured) {\n if (m.ink < floor) {\n dropped.push(\n `blank at ${m.time.toFixed(2)}s: ${Math.round(m.ink * 100)}% ink (the floor is ${Math.round(floor * 100)}%; the take's median is ${Math.round(median * 100)}%)`,\n )\n continue\n }\n const twin = kept.find((k) => hammingDistance(k.hash, m.hash) <= bits)\n if (twin) {\n dropped.push(\n `${m.time.toFixed(2)}s is the same frame as ${twin.time.toFixed(2)}s`,\n )\n continue\n }\n kept.push(m)\n }\n // Every candidate blank: keep the best one rather than nothing, said.\n if (!kept.length && measured.length) {\n const best = [...measured].sort((a, b) => b.ink - a.ink)[0]\n kept.push(best)\n dropped.push(\n `every candidate is under the blank floor; kept ${best.time.toFixed(2)}s (${Math.round(best.ink * 100)}% ink) as the least empty`,\n )\n }\n return { times: kept.map((k) => k.time), dropped }\n}\n","/**\n * Picture primitives for the kit: what a still LOOKS like, measured from\n * its bytes, no browser and no model. A PNG decoder for the captures this\n * CLI writes (8-bit RGB/RGBA, non-interlaced; anything else reads as\n * unreadable rather than wrong), then the measurements the reference\n * assets were read with: the ground (the median of a border ring), the\n * card (the bounding box of what differs from the ground), the shadow (a\n * gradient band outside the card's bottom edge), ink coverage inside a\n * rect (how much of the card is content), and a difference hash so two\n * stills of one frame can be told apart from two frames.\n */\nimport { inflateSync } from 'node:zlib'\n\nexport interface Rgba {\n w: number\n h: number\n /** RGBA, row-major, 4 bytes per pixel. */\n data: Uint8Array\n}\n\nconst PNG_SIG = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]\n\n/**\n * Decode an 8-bit truecolor (with or without alpha) or greyscale\n * non-interlaced PNG. Returns null for anything else (palette, 16-bit,\n * interlaced): the picture checks then say \"unreadable\", never a wrong\n * number.\n */\nexport function decodePng(bytes: Uint8Array): Rgba | null {\n if (bytes.length < 33) return null\n for (let i = 0; i < 8; i++) if (bytes[i] !== PNG_SIG[i]) return null\n const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength)\n let pos = 8\n let w = 0\n let h = 0\n let depth = 0\n let colorType = 0\n let interlace = 0\n const idat: Uint8Array[] = []\n while (pos + 8 <= bytes.length) {\n const len = view.getUint32(pos)\n const type = String.fromCharCode(\n bytes[pos + 4],\n bytes[pos + 5],\n bytes[pos + 6],\n bytes[pos + 7],\n )\n const start = pos + 8\n if (type === 'IHDR') {\n w = view.getUint32(start)\n h = view.getUint32(start + 4)\n depth = bytes[start + 8]\n colorType = bytes[start + 9]\n interlace = bytes[start + 12]\n } else if (type === 'IDAT') {\n idat.push(bytes.subarray(start, start + len))\n } else if (type === 'IEND') break\n pos = start + len + 4\n }\n if (!w || !h || depth !== 8 || interlace !== 0) return null\n const channels =\n colorType === 6\n ? 4\n : colorType === 2\n ? 3\n : colorType === 4\n ? 2\n : colorType === 0\n ? 1\n : 0\n if (!channels) return null\n const total = idat.reduce((n, c) => n + c.length, 0)\n const joined = new Uint8Array(total)\n let off = 0\n for (const c of idat) {\n joined.set(c, off)\n off += c.length\n }\n let raw: Uint8Array\n try {\n raw = new Uint8Array(inflateSync(joined))\n } catch {\n return null\n }\n const stride = w * channels\n if (raw.length < (stride + 1) * h) return null\n const out = new Uint8Array(w * h * 4)\n const prev = new Uint8Array(stride)\n const cur = new Uint8Array(stride)\n for (let y = 0; y < h; y++) {\n const filter = raw[y * (stride + 1)]\n const rowStart = y * (stride + 1) + 1\n for (let i = 0; i < stride; i++) {\n const x = raw[rowStart + i]\n const a = i >= channels ? cur[i - channels] : 0\n const b = prev[i]\n const c = i >= channels ? prev[i - channels] : 0\n let v: number\n switch (filter) {\n case 0:\n v = x\n break\n case 1:\n v = x + a\n break\n case 2:\n v = x + b\n break\n case 3:\n v = x + ((a + b) >> 1)\n break\n case 4: {\n const p = a + b - c\n const pa = Math.abs(p - a)\n const pb = Math.abs(p - b)\n const pc = Math.abs(p - c)\n v = x + (pa <= pb && pa <= pc ? a : pb <= pc ? b : c)\n break\n }\n default:\n return null\n }\n cur[i] = v & 255\n }\n for (let px = 0; px < w; px++) {\n const o = (y * w + px) * 4\n const s = px * channels\n if (channels >= 3) {\n out[o] = cur[s]\n out[o + 1] = cur[s + 1]\n out[o + 2] = cur[s + 2]\n out[o + 3] = channels === 4 ? cur[s + 3] : 255\n } else {\n out[o] = out[o + 1] = out[o + 2] = cur[s]\n out[o + 3] = channels === 2 ? cur[s + 1] : 255\n }\n }\n prev.set(cur)\n }\n return { w, h, data: out }\n}\n\nexport interface Rect {\n x: number\n y: number\n w: number\n h: number\n}\n\nconst at = (img: Rgba, x: number, y: number): [number, number, number] => {\n const o = (y * img.w + x) * 4\n return [img.data[o], img.data[o + 1], img.data[o + 2]]\n}\n\nconst median = (a: number[]) => {\n const s = [...a].sort((x, y) => x - y)\n return s[s.length >> 1] ?? 0\n}\n\n/** The ground: the per-channel median of a 1% border ring, as `#rrggbb`. */\nexport function groundColour(img: Rgba): [number, number, number] {\n const ring = Math.max(1, Math.round(Math.min(img.w, img.h) * 0.01))\n const r: number[] = []\n const g: number[] = []\n const b: number[] = []\n const step = Math.max(1, Math.round(Math.max(img.w, img.h) / 400))\n for (let y = 0; y < img.h; y += step) {\n for (let x = 0; x < img.w; x += step) {\n if (x < ring || y < ring || x >= img.w - ring || y >= img.h - ring) {\n const p = at(img, x, y)\n r.push(p[0])\n g.push(p[1])\n b.push(p[2])\n }\n }\n }\n return [median(r), median(g), median(b)]\n}\n\nexport const hex = (c: [number, number, number]) =>\n '#' + c.map((v) => v.toString(16).padStart(2, '0')).join('')\n\nconst delta = (p: [number, number, number], q: [number, number, number]) =>\n Math.abs(p[0] - q[0]) + Math.abs(p[1] - q[1]) + Math.abs(p[2] - q[2])\n\n/**\n * The card: the bounding box of pixels whose channel-sum delta from the\n * ground exceeds `threshold` (60, the reference measurement). Null when\n * nothing differs (a flat image). Sampled every other pixel.\n */\nexport function cardBounds(\n img: Rgba,\n ground: [number, number, number],\n threshold = 60,\n): Rect | null {\n let x0 = img.w\n let y0 = img.h\n let x1 = -1\n let y1 = -1\n const step = Math.max(1, Math.round(Math.max(img.w, img.h) / 700))\n for (let y = 0; y < img.h; y += step) {\n for (let x = 0; x < img.w; x += step) {\n if (delta(at(img, x, y), ground) > threshold) {\n if (x < x0) x0 = x\n if (y < y0) y0 = y\n if (x > x1) x1 = x\n if (y > y1) y1 = y\n }\n }\n }\n if (x1 < 0) return null\n return { x: x0, y: y0, w: x1 - x0 + 1, h: y1 - y0 + 1 }\n}\n\n/**\n * Shadow presence, read INWARD from the object's faint edge: a soft shadow\n * is a halo whose delta from the ground grows toward the card, so the band\n * nearer the card must read darker than the outer band (a card fill, a\n * hard edge or a flat plate read flat). Sides read are left, right and\n * bottom, wherever the object clears the frame; the reading is the nearer\n * band's delta, else 0. Null when no side has room.\n */\nexport function haloReading(\n img: Rgba,\n ground: [number, number, number],\n card: Rect,\n): number | null {\n const band = Math.max(2, Math.round(Math.min(img.w, img.h) * 0.012))\n const meanRect = (x0: number, y0: number, x1: number, y1: number) => {\n let sum = 0\n let n = 0\n const sx = Math.max(1, Math.round((x1 - x0) / 60))\n const sy = Math.max(1, Math.round((y1 - y0) / 60))\n for (let y = Math.max(0, y0); y < Math.min(img.h, y1); y += sy) {\n for (let x = Math.max(0, x0); x < Math.min(img.w, x1); x += sx) {\n sum += delta(at(img, x, y), ground)\n n++\n }\n }\n return n ? sum / n : 0\n }\n // Two bands, not three: the innermost band would reach the card's own\n // fill, which on a light card is LIGHTER than the halo and breaks the\n // rise. A halo is present when the band nearer the card is darker than\n // the outer one by a clear step and the outer one is not the ground.\n const rise = (bands: [number, number, number]) => {\n const [outer, mid] = bands\n return outer >= 3 && mid - outer >= 1.5 ? mid : 0\n }\n const readings: number[] = []\n const yA = card.y + card.h * 0.2\n const yB = card.y + card.h * 0.8\n if (card.x >= 1 && card.w > band * 4) {\n const x0 = card.x\n readings.push(\n rise([\n meanRect(x0, yA, x0 + band, yB),\n meanRect(x0 + band, yA, x0 + band * 2, yB),\n meanRect(x0 + band * 2, yA, x0 + band * 3, yB),\n ]),\n )\n }\n if (card.x + card.w <= img.w - 1 && card.w > band * 4) {\n const x1 = card.x + card.w\n readings.push(\n rise([\n meanRect(x1 - band, yA, x1, yB),\n meanRect(x1 - band * 2, yA, x1 - band, yB),\n meanRect(x1 - band * 3, yA, x1 - band * 2, yB),\n ]),\n )\n }\n if (card.y + card.h <= img.h - 1 && card.h > band * 4) {\n const y1 = card.y + card.h\n const xA = card.x + card.w * 0.2\n const xB = card.x + card.w * 0.8\n readings.push(\n rise([\n meanRect(xA, y1 - band, xB, y1),\n meanRect(xA, y1 - band * 2, xB, y1 - band),\n meanRect(xA, y1 - band * 3, xB, y1 - band * 2),\n ]),\n )\n }\n return readings.length ? Math.max(...readings) : null\n}\n\n/**\n * A drawn edge at the object's boundary: the strongest single column\n * within the first 24 px inside the faint edge (the halo lies between the\n * faint edge and the card, so the hairline sits a few px in), as the\n * median delta from the ground along its height. A hairline, a browser bar or a dark card reads\n * high; a light fill against a light plate reads its own small tone step.\n */\nexport function edgeContrast(\n img: Rgba,\n ground: [number, number, number],\n card: Rect,\n): number {\n const yA = Math.max(0, Math.round(card.y + card.h * 0.2))\n const yB = Math.min(img.h, Math.round(card.y + card.h * 0.8))\n // The MEDIAN of a column, not its mean: a drawn edge is dark along its\n // whole height, while a column through page content is mostly fill with\n // a few dark rows, which a mean would mistake for an edge.\n const col = (x: number) => {\n if (x < 0 || x >= img.w) return 0\n const ds: number[] = []\n const step = Math.max(1, Math.round((yB - yA) / 80))\n for (let y = yA; y < yB; y += step) ds.push(delta(at(img, x, y), ground))\n return median(ds)\n }\n const depth = Math.min(24, Math.floor(card.w / 8))\n let best = 0\n for (let d = 0; d < depth; d++) {\n best = Math.max(best, col(card.x + d), col(card.x + card.w - 1 - d))\n }\n return best\n}\n\n/**\n * Ink coverage inside a rect: the share of sampled pixels that differ from\n * the rect's own median colour by more than `threshold`. A populated page\n * reads 0.2 and up; a blank canvas, a wallpaper or a flat panel reads\n * under 0.1.\n */\nexport function inkCoverage(img: Rgba, rect: Rect, threshold = 48): number {\n const x0 = Math.max(0, Math.floor(rect.x))\n const y0 = Math.max(0, Math.floor(rect.y))\n const x1 = Math.min(img.w, Math.ceil(rect.x + rect.w))\n const y1 = Math.min(img.h, Math.ceil(rect.y + rect.h))\n if (x1 - x0 < 2 || y1 - y0 < 2) return 0\n const step = Math.max(1, Math.round(Math.max(x1 - x0, y1 - y0) / 300))\n const r: number[] = []\n const g: number[] = []\n const b: number[] = []\n const pts: [number, number, number][] = []\n for (let y = y0; y < y1; y += step) {\n for (let x = x0; x < x1; x += step) {\n const p = at(img, x, y)\n pts.push(p)\n r.push(p[0])\n g.push(p[1])\n b.push(p[2])\n }\n }\n const base: [number, number, number] = [median(r), median(g), median(b)]\n let ink = 0\n for (const p of pts) if (delta(p, base) > threshold) ink++\n return pts.length ? ink / pts.length : 0\n}\n\n/**\n * A 64-bit difference hash: the image reduced to 9x8 luma, each bit \"is\n * this cell brighter than its right neighbour\". Two crops of ONE frame at\n * different aspects still hash within a few bits of each other; two\n * frames of a moving page do not. Returned as a 16-hex string.\n */\nexport function differenceHash(img: Rgba, rect?: Rect): string {\n const r = rect ?? { x: 0, y: 0, w: img.w, h: img.h }\n const cols = 9\n const rows = 8\n const cell: number[] = []\n for (let cy = 0; cy < rows; cy++) {\n for (let cx = 0; cx < cols; cx++) {\n const x0 = Math.floor(r.x + (cx * r.w) / cols)\n const x1 = Math.max(x0 + 1, Math.floor(r.x + ((cx + 1) * r.w) / cols))\n const y0 = Math.floor(r.y + (cy * r.h) / rows)\n const y1 = Math.max(y0 + 1, Math.floor(r.y + ((cy + 1) * r.h) / rows))\n let sum = 0\n let n = 0\n const sx = Math.max(1, Math.floor((x1 - x0) / 8))\n const sy = Math.max(1, Math.floor((y1 - y0) / 8))\n for (let y = y0; y < y1 && y < img.h; y += sy) {\n for (let x = x0; x < x1 && x < img.w; x += sx) {\n const p = at(img, Math.max(0, x), Math.max(0, y))\n sum += 0.299 * p[0] + 0.587 * p[1] + 0.114 * p[2]\n n++\n }\n }\n cell.push(n ? sum / n : 0)\n }\n }\n let bits = ''\n for (let cy = 0; cy < rows; cy++) {\n let byte = 0\n for (let cx = 0; cx < cols - 1; cx++) {\n const l = cell[cy * cols + cx]\n const rr = cell[cy * cols + cx + 1]\n byte = (byte << 1) | (l > rr ? 1 : 0)\n }\n bits += byte.toString(16).padStart(2, '0')\n }\n return bits\n}\n\n/** Bits that differ between two hashes of equal length. */\nexport function hammingDistance(a: string, b: string): number {\n let d = 0\n for (let i = 0; i < Math.min(a.length, b.length); i++) {\n let x = parseInt(a[i], 16) ^ parseInt(b[i], 16)\n while (x) {\n d += x & 1\n x >>= 1\n }\n }\n return d + Math.abs(a.length - b.length) * 4\n}\n\n/** Relative luminance 0..1 of an sRGB triple. */\nexport function luminance(c: [number, number, number]): number {\n const lin = (v: number) => {\n const s = v / 255\n return s <= 0.04045 ? s / 12.92 : Math.pow((s + 0.055) / 1.055, 2.4)\n }\n return 0.2126 * lin(c[0]) + 0.7152 * lin(c[1]) + 0.0722 * lin(c[2])\n}\n\n/** CIE L* (0..100) of an sRGB triple, for a card-vs-ground separation. */\nexport function lightness(c: [number, number, number]): number {\n const y = luminance(c)\n return y > 0.008856 ? 116 * Math.cbrt(y) - 16 : 903.3 * y\n}\n\n/** The median colour inside a rect (sampled). */\nexport function medianColour(img: Rgba, rect: Rect): [number, number, number] {\n const r: number[] = []\n const g: number[] = []\n const b: number[] = []\n const x0 = Math.max(0, Math.floor(rect.x))\n const y0 = Math.max(0, Math.floor(rect.y))\n const x1 = Math.min(img.w, Math.ceil(rect.x + rect.w))\n const y1 = Math.min(img.h, Math.ceil(rect.y + rect.h))\n const step = Math.max(1, Math.round(Math.max(x1 - x0, y1 - y0) / 200))\n for (let y = y0; y < y1; y += step) {\n for (let x = x0; x < x1; x += step) {\n const p = at(img, x, y)\n r.push(p[0])\n g.push(p[1])\n b.push(p[2])\n }\n }\n return [median(r), median(g), median(b)]\n}\n\n/**\n * Edge energy at a scale: the mean absolute luma step between horizontal\n * neighbours after downscaling the image so its width is `width` cells.\n * The half-size legibility rule compares the energy at full and at half\n * size: a tile that keeps most of its edges when shrunk still reads.\n */\nexport function edgeEnergy(img: Rgba, width: number): number {\n const cols = Math.max(2, Math.min(width, img.w))\n const rows = Math.max(2, Math.round((cols * img.h) / img.w))\n const lum: number[] = []\n for (let cy = 0; cy < rows; cy++) {\n for (let cx = 0; cx < cols; cx++) {\n const x = Math.min(img.w - 1, Math.floor(((cx + 0.5) * img.w) / cols))\n const y = Math.min(img.h - 1, Math.floor(((cy + 0.5) * img.h) / rows))\n const p = at(img, x, y)\n lum.push(0.299 * p[0] + 0.587 * p[1] + 0.114 * p[2])\n }\n }\n let sum = 0\n let n = 0\n for (let cy = 0; cy < rows; cy++) {\n for (let cx = 1; cx < cols; cx++) {\n sum += Math.abs(lum[cy * cols + cx] - lum[cy * cols + cx - 1])\n n++\n }\n }\n return n ? sum / n : 0\n}\n\n/** Measure a still the way the reference assets were measured. */\nexport interface StillMeasure {\n w: number\n h: number\n ground: string\n card: Rect | null\n /** The card's width as a fraction of the frame. */\n widthPct: number | null\n /** Padding on each side as fractions of the frame. */\n pad: { left: number; right: number; top: number; bottom: number } | null\n /** Sides where the card runs to (or past) the frame edge (< 0.5% room). */\n bleed: ('left' | 'right' | 'top' | 'bottom')[]\n /** The shadow halo reading inward from the object's edge; null when no side clears the frame. */\n shadow: number | null\n /** The strongest drawn edge at the boundary (a hairline, a bar, a dark card). */\n edge: number\n /** Ink coverage inside the card (or the whole frame when no card). */\n ink: number\n /** L* difference between the card's median and the ground. */\n separation: number | null\n hash: string\n}\n\nexport function measureStill(img: Rgba): StillMeasure {\n const g = groundColour(img)\n // Two thresholds: the STRONG box is the content (60, the reference\n // measurement); the FAINT box (12) is the object, halo and hairline\n // included, which is what a light card on a light plate needs to be\n // found by at all.\n const strong = cardBounds(img, g, 60)\n const faint = cardBounds(img, g, 12) ?? strong\n const card = faint\n const bleed: StillMeasure['bleed'] = []\n let pad: StillMeasure['pad'] = null\n let widthPct: number | null = null\n let shadow: number | null = null\n let edge = 0\n let separation: number | null = null\n if (card) {\n pad = {\n left: card.x / img.w,\n right: (img.w - card.x - card.w) / img.w,\n top: card.y / img.h,\n bottom: (img.h - card.y - card.h) / img.h,\n }\n for (const side of ['left', 'right', 'top', 'bottom'] as const)\n if (pad[side] < 0.005) bleed.push(side)\n widthPct = card.w / img.w\n shadow = haloReading(img, g, card)\n edge = edgeContrast(img, g, card)\n const body = strong ?? card\n const inner = {\n x: body.x + body.w * 0.1,\n y: body.y + body.h * 0.1,\n w: body.w * 0.8,\n h: body.h * 0.8,\n }\n separation = Math.abs(lightness(medianColour(img, inner)) - lightness(g))\n }\n const inkRect = strong ?? card ?? { x: 0, y: 0, w: img.w, h: img.h }\n return {\n w: img.w,\n h: img.h,\n ground: hex(g),\n card,\n widthPct,\n pad,\n bleed,\n shadow,\n edge,\n ink: inkCoverage(img, inkRect),\n separation,\n hash: differenceHash(img, inkRect),\n }\n}\n","/**\n * The cut's presenting MOTION as planner proposals on the document, and the\n * spec MECHANICS a destination applies at render time. Two halves, drawn\n * once:\n *\n * TASTE lives in the document, in the one vocabulary. `proposeMotion`\n * writes the card's `anim.enter`, lays the templates the recipe names at\n * their anchors (a template is a vos; its clips come stamped `from`), the\n * house end card as clips after the footage plus a card exit, a caption\n * per beat, a music bed and click sounds onto the cut's doc.json (`vos\n * plan`), keyed on the recipe's roles (LAUNCH.md) and never on measured\n * audio, so the studio shows exactly what the kit will render and a\n * human's deletion stays deleted (a re-plan never re-proposes onto a\n * document that already carries a cut).\n *\n * MECHANICS live in the spec. `destinationMechanics` is what a VIDEO\n * destination does to a document at render time and nothing more: a loop\n * drops the card's motion, every clip a template placed and every sound\n * (it must be seamless); a silent channel mutes the bed; a 9:16\n * destination reframes the card (a cover crop that follows the camera,\n * not a letterbox). Pure; the catalog and the words come in as data.\n */\nimport {\n END_CARD_FROM,\n END_CARD_SECONDS,\n applyTemplate,\n docOutputDuration,\n dropTemplate,\n endCardClips,\n migrateMotion,\n ratedSegments,\n sameMedia,\n spanOutputExtent,\n} from '@vosjs/studio-core'\nimport { STEP_SETTLE_SECONDS, stepOutputTime } from './moments'\nimport type {\n Anim,\n AnimKind,\n Destination,\n EndCard,\n Look,\n ProjectDoc,\n TemplateAnchor,\n} from '@vosjs/studio-core'\nimport type { ReleaseWords } from './posterValues'\n\n/** Destinations that play sound (a feed autoplays muted; a demo has a speaker). */\nexport const SOUND_DESTINATIONS = new Set([\n 'x-feed-cut',\n 'youtube-main-demo',\n 'shorts-linkedin-vertical-cut',\n])\n\n/** Destinations that must loop seamlessly: no entrance, no end card, no sound. */\nexport const LOOP_DESTINATIONS = new Set(['github-readme-loop'])\n\nexport interface MusicCatalog {\n tracks: {\n slug: string\n title: string\n mood?: string\n duration: number\n url: string\n }[]\n sfx: { slug: string; title: string; duration: number; url: string }[]\n}\n\n/** The ids the proposals write, so a re-proposal replaces its own work and nothing else. */\nexport const BED_ID = 'bed'\nexport const CLICK_ID_PREFIX = 'click-'\nexport const CAPTION_ID_PREFIX = 'caption-'\n\nexport interface MotionProposalInput {\n words: ReleaseWords\n /** LAUNCH.md roles: music (a slug or mood), entrance, endCard, captions, clicks. */\n launch: Record<string, string>\n /** The end card's ink: the brand's ink over a light ground, white over a dark one. */\n ink?: string | null\n /** The brand's mark for the end card (a take-dir key and its aspect), or none. */\n mark?: { key: string; aspect: number } | null\n /** actions.json steps with their optional captions, by index. */\n captions: { step: number; id?: string; caption: string }[]\n catalog: MusicCatalog | null\n /** The templates the recipe or the flags named, resolved, in order. */\n templates?: MotionTemplate[]\n}\n\nexport interface MotionProposals {\n doc: ProjectDoc\n /** What was proposed, for the phase note. */\n notes: string[]\n /** What could not be proposed, in words. */\n skipped: string[]\n}\n\nconst off = (v: string | undefined) =>\n v !== undefined && /^(none|off|false|no)$/i.test(v.trim())\n\n/** The kinds a boundary moves by. */\nexport type TransitionKind = 'slide' | 'fade' | 'scale'\n\nconst round3 = (v: number): number => Math.round(v * 1000) / 1000\n\n/** A clip on either side of a page change keeps at least this much footage. */\nconst TRANSITION_CLIP_MIN = 1\n\n/**\n * A transition at every page change: a recorded step that navigated (a\n * click, or the wait that let the load land) splits its clip, the outgoing\n * ending on the frame BEFORE the change and the incoming beginning once\n * the page has settled (the load between them is dropped), and the two\n * meet by the kind. A boundary that already sits there is left as it is\n * (a re-plan never doubles a cut); a change too close to a clip's edge is\n * named and skipped. Pure; the primary's steps only.\n */\nexport function proposeTransitions(\n input: ProjectDoc,\n kind: TransitionKind,\n): { doc: ProjectDoc; count: number; skipped: string[] } {\n const doc = structuredClone(input)\n const skipped: string[] = []\n let count = 0\n const steps = doc.source.meta.steps ?? []\n for (const step of steps) {\n if (!step.navigated || step.skipped) continue\n const name = step.id ?? String(step.step)\n const wait = step.do === 'wait'\n const outEnd = round3(wait ? step.tStart : step.tEnd)\n const inStart = round3(wait ? step.tEnd : step.tEnd + STEP_SETTLE_SECONDS)\n const segs = doc.segments\n if (\n segs.some(\n (s) => !s.media && Math.abs(s.out - outEnd) < 0.05 && s !== segs.at(-1),\n )\n )\n continue\n const i = segs.findIndex(\n (s) =>\n !s.media &&\n outEnd >= s.in + TRANSITION_CLIP_MIN &&\n inStart <= s.out - TRANSITION_CLIP_MIN,\n )\n if (i < 0) {\n skipped.push(\n `no transition at step ${name}: the page change sits too close to a clip's edge`,\n )\n continue\n }\n const seg = segs[i]\n const before = { ...seg, out: outEnd, anim: { exit: kind } as Anim }\n const after = { ...seg, in: inStart, anim: { enter: kind } as Anim }\n if (seg.anim?.enter !== undefined) before.anim.enter = seg.anim.enter\n if (seg.anim?.exit !== undefined) after.anim.exit = seg.anim.exit\n doc.segments = [...segs.slice(0, i), before, after, ...segs.slice(i + 1)]\n count++\n }\n return { doc, count, skipped }\n}\n\n/**\n * The bed: LAUNCH.md names a track slug or a mood; a mood picks the first\n * track of that mood. Null when nothing was asked or nothing matched.\n */\nexport function pickTrack(\n catalog: MusicCatalog | null,\n ask: string | undefined,\n): MusicCatalog['tracks'][number] | null {\n if (!catalog || !ask || off(ask)) return null\n const want = ask.trim().toLowerCase()\n return (\n catalog.tracks.find((t) => t.slug.toLowerCase() === want) ??\n catalog.tracks.find((t) => (t.mood ?? '').toLowerCase() === want) ??\n null\n )\n}\n\n/** Click instants of the take in OUTPUT seconds, inside the range. */\nexport function clickTimes(doc: ProjectDoc, range: [number, number]): number[] {\n const rated = ratedSegments(doc)\n const out: number[] = []\n for (const e of doc.source.cursor) {\n if (e.type !== 'down') continue\n const src = e.t / 1000\n const ext = spanOutputExtent(rated, src, src + 0.001)\n if (!ext) continue\n const t = ext.start\n if (t < range[0] || t > range[1]) continue\n if (out.length && t - out[out.length - 1] < 0.12) continue\n out.push(+(t - range[0]).toFixed(3))\n }\n return out\n}\n\nconst outputLength = (doc: ProjectDoc) =>\n ratedSegments(doc).reduce((acc, s) => {\n const rate = s.rate && s.rate > 0 ? s.rate : 1\n return acc + (s.out - s.in) / rate\n }, 0)\n\n/** Where a template lands: the studio-core anchor, or a recorded step's settle. */\nexport type MotionAnchor = TemplateAnchor | { step: string }\n\n/** A template the recipe or a flag named, resolved to its document. */\nexport interface MotionTemplate {\n /** What its clips say they came from (the vos id or the path it was read from). */\n from: string\n doc: ProjectDoc\n at: MotionAnchor\n}\n\n/**\n * The words a template's clips take, by the ids the house templates use:\n * a poster's `stage-*` clips and an end card's `endcard-*` clips. A\n * template with other ids keeps its own words.\n */\nexport function templateWords(words: ReleaseWords): Record<string, string> {\n const headline = (words.headline ?? '').trim()\n const kicker = (words.kicker ?? '').trim()\n const brand = (words.brand ?? '').trim()\n const sub = [brand, (words.release ?? '').trim()].filter(Boolean).join(' ')\n const out: Record<string, string> = {}\n if (headline) {\n out['stage-title'] = headline\n out['endcard-title'] = headline\n }\n if (kicker) out['stage-kicker'] = kicker\n if (brand) {\n out['stage-brand'] = brand\n out['endcard-mark'] = brand\n }\n if (sub && sub !== headline) out['endcard-sub'] = sub\n return out\n}\n\nfunction resolveAnchor(\n doc: ProjectDoc,\n at: MotionAnchor,\n): TemplateAnchor | null {\n if (typeof at !== 'object') return at\n const steps = doc.source.meta.steps ?? []\n const step = steps.find((s) => s.id === at.step || String(s.step) === at.step)\n if (!step || step.skipped) return null\n const t = stepOutputTime(ratedSegments(doc), step, 0.2)\n return t === null ? null : +t.toFixed(3)\n}\n\nconst anchorWord = (at: MotionAnchor): string =>\n typeof at === 'object'\n ? `step ${at.step}`\n : typeof at === 'number'\n ? `${at}s`\n : `the ${at}`\n\nconst onWord = (v: string | undefined) =>\n v === undefined || /^(on|yes|true)$/i.test(v.trim())\n\n/**\n * Propose the cut's motion onto a copy of the document, in the one\n * vocabulary: the card's `anim.enter`, the templates the recipe names\n * laid at their anchors (stamped `from`), the house end card as clips\n * after the footage plus a card exit (`from: 'endcard'`, the migration's\n * shape, until a shelf template replaces it), a caption per beat, a bed\n * and click sounds. Every proposal writes a STABLE id or a `from`, and\n * replaces only its own earlier work, so a maker's clips survive a second\n * pass. A legacy document is read into the vocabulary first.\n */\nexport function proposeMotion(\n input: ProjectDoc,\n opts: MotionProposalInput,\n): MotionProposals {\n let doc = migrateMotion(structuredClone(input))\n const { words, launch, catalog } = opts\n const notes: string[] = []\n const skipped: string[] = []\n const footage = outputLength(doc)\n const range: [number, number] = [0, footage]\n\n // The card's enter: the clip opens on a move.\n const entrance = launch.entrance\n delete doc.frame.entrance\n if (!off(entrance)) {\n const kind =\n entrance && /^(tilt-in|pull-out|rise|fade)$/.test(entrance.trim())\n ? (entrance.trim() as AnimKind)\n : 'tilt-in'\n doc.frame.anim = { ...(doc.frame.anim ?? {}), enter: kind }\n notes.push(`enter ${kind}`)\n } else if (doc.frame.anim?.enter !== undefined) {\n const { enter: _enter, ...rest } = doc.frame.anim\n if (Object.keys(rest).length) doc.frame.anim = rest\n else delete doc.frame.anim\n }\n\n // Page changes: a recorded step that navigated is a cut with a\n // transition at the boundary. LAUNCH.md's `transitions` role picks the\n // kind (slide, the house default; fade; scale; none switches it off).\n const trRole = launch.transitions\n if (!off(trRole)) {\n const trKind =\n trRole && /^(slide|fade|scale)$/.test(trRole.trim())\n ? (trRole.trim() as TransitionKind)\n : 'slide'\n const made = proposeTransitions(doc, trKind)\n doc = made.doc\n if (made.count) notes.push(`${made.count} transition(s) ${trKind}`)\n for (const n of made.skipped) skipped.push(n)\n }\n\n // The end card the recipe names, or the official one the platform holds,\n // arrives as a template stamped `from: 'endcard'` (the house clips below\n // are the offline fallback); a re-plan replaces its earlier work first,\n // and `endCard: none` drops it with the rest.\n const endCardRole = launch.endCard\n doc = dropTemplate(doc, END_CARD_FROM)\n const templates = (opts.templates ?? []).filter(\n (t) => !(t.from === END_CARD_FROM && off(endCardRole)),\n )\n const namedEndCard = templates.some((t) => t.from === END_CARD_FROM)\n\n // The templates the recipe or the flags named, at their anchors: a\n // template is a vos, its clips come stamped with where they came from.\n const tWords = templateWords(words)\n const keys = opts.mark\n ? { 'stage-mark': opts.mark.key, 'endcard-markimg': opts.mark.key }\n : undefined\n for (const t of templates) {\n const at = resolveAnchor(doc, t.at)\n if (at === null) {\n skipped.push(`${t.from}: ${anchorWord(t.at)} was not recorded`)\n continue\n }\n const applied = applyTemplate(t.doc, doc, {\n at,\n from: t.from,\n words: tWords,\n keys,\n })\n doc = applied.doc\n notes.push(`${t.from} at ${anchorWord(t.at)}`)\n for (const n of applied.notes) skipped.push(`${t.from}: ${n}`)\n }\n\n // The end card: on (or absent) with no template in hand is the house\n // shape, a freeze under clips and a card exit; a named or official\n // template took its place above; off drops it.\n if (off(endCardRole)) {\n if (doc.frame.anim?.exit !== undefined) {\n const { exit: _exit, ...rest } = doc.frame.anim\n if (Object.keys(rest).length) doc.frame.anim = rest\n else delete doc.frame.anim\n }\n } else if (onWord(endCardRole) && !namedEndCard) {\n const headline = (words.headline ?? '').trim()\n const brand = (words.brand ?? '').trim()\n const sub = [brand, (words.release ?? '').trim()].filter(Boolean).join(' ')\n if (headline || brand) {\n const card: EndCard = { seconds: END_CARD_SECONDS }\n // Over a light plate the presets' white would vanish: the brand's ink.\n if (opts.ink) card.ink = opts.ink\n if (headline) card.headline = headline\n if (sub && sub !== headline) card.sub = sub\n if (brand) card.wordmark = brand\n if (opts.mark) card.mark = opts.mark\n // The words start where the moving footage ends; the card stays\n // under them as a freeze of its last frame (past its clip the card\n // is gone), receding over the card's seconds.\n const endStart = outputLength(doc)\n const lastSeg = doc.segments.at(-1)\n if (lastSeg) {\n // The last clip may play another media (concat): the freeze\n // names it, or its seconds would land on the primary's footage.\n const atEnd = (f: { at: number; media?: string }) =>\n Math.abs(f.at - lastSeg.out) <= 1e-9 &&\n sameMedia(f.media, lastSeg.media)\n // A freeze the take OWNS at its end survives (its rest, the frame\n // that stands for it) and grows to the card's seconds; only a\n // take with none gets the house freeze, stamped from.\n const kept = (doc.freeze ?? []).find((f) => atEnd(f) && !f.from)\n const own = (doc.freeze ?? []).filter((f) => !atEnd(f))\n const taken = new Set(own.map((f) => f.id))\n let n = 0\n while (taken.has(`f${n}`)) n++\n doc.freeze = [\n ...own,\n kept\n ? { ...kept, seconds: Math.max(kept.seconds, END_CARD_SECONDS) }\n : {\n id: `f${n}`,\n at: lastSeg.out,\n seconds: END_CARD_SECONDS,\n from: END_CARD_FROM,\n ...(lastSeg.media ? { media: lastSeg.media } : {}),\n },\n ].sort((a, b) => a.at - b.at)\n }\n doc.overlays = [\n ...(doc.overlays ?? []),\n ...endCardClips(card, doc, endStart),\n ]\n doc.frame.anim = {\n ...(doc.frame.anim ?? {}),\n exit: { kind: 'recede', seconds: END_CARD_SECONDS },\n }\n notes.push('end card')\n } else {\n skipped.push(\n 'no end card (no headline or wordmark in LAUNCH.md, BRAND.md or the flags)',\n )\n }\n }\n\n // Captions per beat: a step's caption lands at the step's settled moment\n // as a lower-third.\n const kept = (doc.overlays ?? []).filter(\n (o) => !o.id.startsWith(CAPTION_ID_PREFIX),\n )\n const captionClips: NonNullable<ProjectDoc['overlays']> = []\n if (opts.captions.length && !off(launch.captions)) {\n const rated = ratedSegments(doc)\n const steps = doc.source.meta.steps ?? []\n for (const c of opts.captions) {\n const step = steps.find(\n (s) => (c.id !== undefined && s.id === c.id) || s.step === c.step,\n )\n if (!step || step.skipped) continue\n const t = stepOutputTime(rated, step, 0.2)\n if (t === null || t < 0 || t > footage - 1) continue\n captionClips.push({\n id: `${CAPTION_ID_PREFIX}${c.step}`,\n kind: 'text',\n text: c.caption,\n preset: 'caption',\n start: +t.toFixed(3),\n duration: Math.min(3.5, Math.max(2.5, footage - t - 0.2)),\n transform: { x: 0.5, y: 0.86, scale: 1, rotation: 0 },\n anim: { enter: 'rise', exit: 'fade' },\n align: 'center',\n box: { color: 'rgba(17,17,17,0.72)' },\n })\n }\n if (captionClips.length) notes.push(`${captionClips.length} caption(s)`)\n }\n const overlays = [...kept, ...captionClips]\n if (overlays.length) doc.overlays = overlays\n else delete doc.overlays\n\n // Sound: a bed and click sounds. A destination that plays no sound mutes\n // them at render time (`destinationMechanics`); the document carries\n // them, so the studio plays what the demo will. The bed fills the whole\n // OUTPUT, the clips after the footage included.\n const length = docOutputDuration(doc)\n const clips = (doc.audio ?? []).filter(\n (a) => a.id !== BED_ID && !a.id.startsWith(CLICK_ID_PREFIX),\n )\n const track = pickTrack(catalog, launch.music)\n if (track) {\n const hasMic = !!doc.source.micKey\n const fadeOut = Math.min(2.5, length * 0.15)\n clips.push({\n id: BED_ID,\n key: track.url,\n name: track.title,\n start: 0,\n in: 0,\n out: Math.min(track.duration, length),\n duration: track.duration,\n gain: hasMic ? 0.35 : 0.5,\n fadeIn: 0.6,\n fadeOut,\n loop: track.duration < length,\n loopLen:\n track.duration < length ? Math.round(length * 1000) / 1000 : undefined,\n duck: hasMic,\n })\n notes.push(`bed ${track.slug}`)\n } else if (launch.music && !off(launch.music)) {\n skipped.push(\n `music \"${launch.music}\" is not a catalog track or mood${catalog ? '' : ' (the catalog could not be read)'}`,\n )\n }\n const click = catalog?.sfx.find((s) => s.slug === 'sfx-click')\n if (click && !doc.source.micKey && !off(launch.clicks)) {\n const times = clickTimes(doc, range)\n for (const [i, t] of times.entries()) {\n clips.push({\n id: `${CLICK_ID_PREFIX}${i}`,\n key: click.url,\n name: click.title,\n start: t,\n in: 0,\n out: click.duration,\n duration: click.duration,\n gain: 0.4,\n fadeIn: 0,\n fadeOut: 0,\n })\n }\n if (times.length) notes.push(`${times.length} click sound(s)`)\n }\n doc.audio = clips\n\n return { doc, notes, skipped }\n}\n\n/**\n * What a VIDEO destination does to the document at render time, as doc\n * overrides for that one render: the spec's mechanics, never taste.\n */\nexport function destinationMechanics(\n d: Pick<Destination, 'id' | 'kind' | 'px' | 'text'>,\n doc: Pick<ProjectDoc, 'overlays' | 'freeze'>,\n): { set: string[]; unset: string[]; notes: string[] } {\n const set: string[] = []\n const unset: string[] = []\n const notes: string[] = []\n if (d.kind !== 'video') return { set, unset, notes }\n const loop = LOOP_DESTINATIONS.has(d.id)\n const sound = SOUND_DESTINATIONS.has(d.id)\n const portrait = d.px.w / d.px.h < 0.9\n\n if (loop) {\n // Seamless by contract: the card neither arrives nor leaves, nothing a\n // template placed plays, nothing sounds. The two legacy spellings go\n // with it for a document read unmigrated.\n unset.push('frame.anim', 'frame.entrance', 'endCard')\n notes.push('loop: no card motion')\n }\n if (loop || !sound) {\n set.push('audio=[]')\n if (!loop) notes.push('silent channel')\n }\n if (loop || d.text === 'none') {\n // A destination that takes no words drops the beat captions; a loop\n // drops every clip a template placed too. A maker's own titles stay.\n const kept = (doc.overlays ?? []).filter(\n (o) => !o.id.startsWith(CAPTION_ID_PREFIX) && !(loop && o.from),\n )\n if (kept.length !== (doc.overlays ?? []).length) {\n set.push(`overlays=${JSON.stringify(kept)}`)\n notes.push(loop ? 'no template clips, no captions' : 'no captions')\n }\n }\n if (loop) {\n // The freeze a template placed under its clips goes with the clips.\n const keptFreezes = (doc.freeze ?? []).filter((f) => !f.from)\n if (keptFreezes.length !== (doc.freeze ?? []).length)\n set.push(`freeze=${JSON.stringify(keptFreezes)}`)\n }\n if (portrait) {\n // The vertical cut is a reframe, not a letterbox: the card is the tall\n // inset area, the footage cover-fills it, and the crop follows the camera.\n set.push('frame.fit=cover')\n set.push('frame.inset={\"left\":0.06,\"right\":0.06,\"top\":0.17,\"bottom\":0.17}')\n set.push('frame.focusFollow=camera')\n notes.push('vertical reframe follows the camera')\n }\n return { set, unset, notes }\n}\n\n/**\n * The end card's ink: the brand's ink (or near-black) over a light ground,\n * white over a dark one, decided from the look's ground.\n */\nexport function endCardInk(\n look: Look | null | undefined,\n brand: Record<string, string> | null | undefined,\n): string | null {\n if (!look) return null\n const ground = look.ground\n const m = /#([0-9a-f]{6})/i.exec(ground)\n const hex = m ? m[0] : null\n const light =\n look.kind === 'plate' ||\n (hex ? isLightHexGround(hex) : look.kind === 'gradient')\n if (!light) return '#ffffff'\n const ink = brand?.ink\n return ink && /^#[0-9a-f]{6}$/i.test(ink) ? ink : '#111111'\n}\n\nfunction isLightHexGround(hex: string): boolean {\n const n = parseInt(hex.slice(1), 16)\n const r = (n >> 16) & 255\n const g = (n >> 8) & 255\n const b = n & 255\n return (0.2126 * r + 0.7152 * g + 0.0722 * b) / 255 >= 0.6\n}\n","/**\n * POSTER DOCUMENTS beside a take. A poster is a plain take document (the\n * card placed by `frame.inset`, leaned by the tilt track, the words and the\n * mark as overlay clips, a trailing hold whose start is the still) that an\n * agent or the studio wrote and pushed; `vos deliver` RENDERS the ones it\n * finds and composes nothing. Found by aspect CLASS beside the take\n * (`poster/<class>/doc.json`, or `poster/doc.json` for every class), or\n * named in LAUNCH.md (`poster: <path>`, `poster-landscape: <path>`, …). A\n * path names a doc.json, or a take directory holding one (a pulled poster\n * take renders over its own footage; a bare doc.json renders over this\n * take's).\n *\n * The picture checks read the text boxes and the shot rect FROM THE\n * DOCUMENT, by the same layout the studio and the render use: the card\n * rect from `computeCardLayout`, the text boxes from `overlayRect` with an\n * estimating measure (no canvas here; the boxes are a fraction wide at\n * worst, which the checks tolerate). Pure except `findPosterDocs`.\n */\nimport { existsSync } from 'node:fs'\nimport { readFile } from 'node:fs/promises'\nimport { isAbsolute, join, resolve } from 'node:path'\nimport {\n computeCardLayout,\n docStillTime,\n migrateHostedDoc,\n overlayRect,\n resolveOverlayStyle,\n} from '@vosjs/studio-core'\nimport { readSyncState } from './platform'\nimport type { TextBox } from './kitPicture'\nimport type { ProjectDoc } from '@vosjs/studio-core'\n\nexport type PosterClass = 'landscape' | 'square' | 'portrait' | 'tile'\nexport const POSTER_CLASSES: PosterClass[] = [\n 'landscape',\n 'square',\n 'portrait',\n 'tile',\n]\n\n/** A destination under this long side is a tile: the subject large, few words. */\nexport const TILE_MAX_PX = 700\n\n/** The aspect class a destination's pixels ask for. */\nexport function posterClassFor(px: { w: number; h: number }): PosterClass {\n if (Math.max(px.w, px.h) < TILE_MAX_PX) return 'tile'\n const r = px.w / Math.max(1, px.h)\n if (r < 0.87) return 'portrait'\n if (r <= 1.15) return 'square'\n return 'landscape'\n}\n\nexport interface PosterRef {\n /** The class it serves. */\n cls: PosterClass\n /** The doc.json read. */\n file: string\n /** The take directory whose footage it renders over. */\n takeDir: string\n /** True when the poster is its own take directory (pulled with its footage). */\n ownFootage: boolean\n doc: ProjectDoc\n /** The hosted vos the poster tracks (its vos.json), when it does. */\n vosId?: string\n /** Where the reference came from, for the phase note. */\n from: string\n}\n\nconst ROLE_ALL = 'poster'\nconst roleFor = (cls: PosterClass) => `poster-${cls}`\n\nasync function readPosterAt(\n cls: PosterClass,\n path: string,\n takeDir: string,\n from: string,\n): Promise<PosterRef | null> {\n let file = path\n let docDir = path\n if (existsSync(join(path, 'doc.json'))) {\n file = join(path, 'doc.json')\n } else if (!/\\.json$/i.test(path) || !existsSync(path)) {\n return null\n } else {\n docDir = resolve(path, '..')\n }\n let raw: unknown\n try {\n raw = JSON.parse(await readFile(file, 'utf8'))\n } catch {\n return null\n }\n if (!raw || typeof raw !== 'object') return null\n const source = (raw as { source?: { videoKey?: unknown } }).source\n if (!source || typeof source.videoKey !== 'string') return null\n const doc = migrateHostedDoc(\n raw as Record<string, unknown>,\n ) as unknown as ProjectDoc\n const ownFootage =\n existsSync(join(docDir, 'meta.json')) &&\n existsSync(join(docDir, source.videoKey))\n const sync = readSyncState(docDir)\n return {\n cls,\n file,\n takeDir: ownFootage ? docDir : takeDir,\n ownFootage,\n doc,\n ...(sync?.vosId ? { vosId: sync.vosId } : {}),\n from,\n }\n}\n\n/**\n * The poster document per class, from LAUNCH.md's roles first (a class\n * role over the all-classes role), then the folder convention beside the\n * take. A class with none is absent; the caller says so in words.\n */\nexport async function findPosterDocs(\n takeDir: string,\n launchRoles: Record<string, string> | null | undefined,\n): Promise<Partial<Record<PosterClass, PosterRef>>> {\n const out: Partial<Record<PosterClass, PosterRef>> = {}\n const at = (p: string) => (isAbsolute(p) ? p : resolve(takeDir, p))\n for (const cls of POSTER_CLASSES) {\n const named = launchRoles?.[roleFor(cls)] ?? launchRoles?.[ROLE_ALL]\n const candidates: { path: string; from: string }[] = []\n if (named && !/^(none|off|no|false)$/i.test(named.trim())) {\n const role = launchRoles?.[roleFor(cls)] ? roleFor(cls) : ROLE_ALL\n candidates.push({ path: at(named.trim()), from: `LAUNCH.md ${role}` })\n }\n candidates.push({\n path: join(takeDir, 'poster', cls),\n from: `poster/${cls}`,\n })\n candidates.push({ path: join(takeDir, 'poster'), from: 'poster' })\n for (const c of candidates) {\n const ref = await readPosterAt(cls, c.path, takeDir, c.from)\n if (ref) {\n out[cls] = ref\n break\n }\n }\n }\n return out\n}\n\n/**\n * The still's OUTPUT time: the rest (where the last freeze begins), else\n * the footage's last frame (the last frame the card is on; past its clip\n * the card is gone, so the output's last frame may hold no card at all).\n */\nexport function posterStillTime(doc: ProjectDoc, duration: number): number {\n // One derivation with the shelf's cover and the stills export: the\n // author's still, else the document's own last freeze (the rest), else\n // the hero after the opening has entered.\n return Math.max(0, Math.min(duration, docStillTime(doc)))\n}\n\nconst DESIGN_H = 1080\n\n/** The design frame the document lays out on at the destination's aspect. */\nfunction designFrame(px: { w: number; h: number }) {\n return {\n W: Math.max(2, Math.round((DESIGN_H * px.w) / Math.max(1, px.h))),\n H: DESIGN_H,\n }\n}\n\n/** Where the card sits, as fractions of the asset (a bleed runs past 1 or below 0). */\nexport function posterShotRect(\n doc: ProjectDoc,\n px: { w: number; h: number },\n): { x: number; y: number; w: number; h: number } {\n const { W, H } = designFrame(px)\n const meta = doc.source.meta\n const layout = computeCardLayout(\n doc.frame,\n {\n width: meta.captureWidth ?? meta.width,\n height: meta.captureHeight ?? meta.height,\n },\n W,\n H,\n )\n const r3 = (v: number) => Math.round(v * 1000) / 1000\n return {\n x: r3(layout.cardX / W),\n y: r3(layout.cardY / H),\n w: r3(layout.cardW / W),\n h: r3(layout.cardH / H),\n }\n}\n\n/** An estimating text measure: no canvas here, so a glyph is ~0.55 em. */\nfunction estimateWidth(text: string, font: string, letterSpacingPx = 0) {\n const m = /(\\d+(?:\\.\\d+)?)px/.exec(font)\n const px = m ? Number(m[1]) : 32\n return text.length * (px * 0.55 + letterSpacingPx)\n}\n\n/**\n * The text boxes of the clips on screen at `time`, as fractions of the\n * asset, with the role and colour the contrast check reads.\n */\nexport function posterTextBoxes(\n doc: ProjectDoc,\n px: { w: number; h: number },\n time: number,\n): TextBox[] {\n const { W, H } = designFrame(px)\n const out: TextBox[] = []\n for (const clip of doc.overlays ?? []) {\n if (clip.kind !== 'text') continue\n if (time < clip.start || time > clip.start + clip.duration) continue\n const rect = overlayRect(clip, estimateWidth, W, H)\n const style = resolveOverlayStyle(clip)\n const r3 = (v: number) => Math.round(v * 1000) / 1000\n out.push({\n x: r3((rect.cx - rect.w / 2) / W),\n y: r3((rect.cy - rect.h / 2) / H),\n w: r3(rect.w / W),\n h: r3(rect.h / H),\n role: clip.preset === 'title' ? 'headline' : 'body',\n label: clip.text.split('\\n')[0].slice(0, 40),\n ...(/^#[0-9a-f]{6}$/i.test(style.color) ? { color: style.color } : {}),\n })\n }\n return out\n}\n","/**\n * The brand's MARK as a file: what `vos brand` recorded as `logoUrl` (and\n * its on-dark twin), fetched once into the take's `brand/` folder so the\n * render page can load it from the take server (the site's own URL rarely\n * carries a CORS header, and a cross-origin image taints the canvas), with\n * its aspect read from the bytes. The parsers are pure.\n */\nimport { mkdir, readFile, writeFile } from 'node:fs/promises'\nimport { existsSync } from 'node:fs'\nimport { isAbsolute, join, resolve } from 'node:path'\n\nexport type MarkExt = 'svg' | 'png' | 'webp' | 'jpg'\n\nexport interface BrandMark {\n /** The key the render page loads: a take-dir path like `/brand/mark.svg`. */\n key: string\n /** Width over height. */\n aspect: number\n}\n\nexport interface BrandMarks {\n /** The mark for light grounds (BRAND.md `logoUrl`). */\n light: BrandMark | null\n /** The mark for dark grounds (BRAND.md `logoOnDarkUrl`). */\n dark: BrandMark | null\n /** What could not be fetched or read, in words. */\n notes: string[]\n}\n\n/** The file kind a mark URL or path names; null for anything else (an .ico, a data URL). */\nexport function markExtension(url: string): MarkExt | null {\n const m = /\\.(svg|png|webp|jpe?g)(?:[?#]|$)/i.exec(url)\n if (!m) return null\n const e = m[1].toLowerCase()\n return e === 'jpeg' ? 'jpg' : (e as MarkExt)\n}\n\n/** Width over height from the bytes: an SVG's viewBox or width/height, a PNG's IHDR, a WebP's VP8/VP8L/VP8X header, a JPEG's SOF. Null when unreadable. */\nexport function imageAspect(bytes: Uint8Array, ext: MarkExt): number | null {\n if (ext === 'svg') {\n const head = new TextDecoder().decode(bytes.subarray(0, 4096))\n const vb =\n /viewBox\\s*=\\s*[\"']\\s*[-\\d.]+[\\s,]+[-\\d.]+[\\s,]+([\\d.]+)[\\s,]+([\\d.]+)/i.exec(\n head,\n )\n if (vb) return ratio(+vb[1], +vb[2])\n const w = /<svg[^>]*\\swidth\\s*=\\s*[\"']([\\d.]+)/i.exec(head)\n const h = /<svg[^>]*\\sheight\\s*=\\s*[\"']([\\d.]+)/i.exec(head)\n if (w && h) return ratio(+w[1], +h[1])\n return null\n }\n const dv = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength)\n if (ext === 'png') {\n if (bytes.length < 24 || bytes[0] !== 0x89 || bytes[1] !== 0x50) return null\n return ratio(dv.getUint32(16), dv.getUint32(20))\n }\n if (ext === 'webp') {\n if (bytes.length < 30) return null\n const tag = String.fromCharCode(...bytes.subarray(12, 16))\n if (tag === 'VP8X')\n return ratio(\n 1 + (dv.getUint32(24, true) & 0xffffff),\n 1 + (dv.getUint32(27, true) & 0xffffff),\n )\n if (tag === 'VP8L') {\n const b = dv.getUint32(21, true)\n return ratio(1 + (b & 0x3fff), 1 + ((b >> 14) & 0x3fff))\n }\n if (tag === 'VP8 ')\n return ratio(\n dv.getUint16(26, true) & 0x3fff,\n dv.getUint16(28, true) & 0x3fff,\n )\n return null\n }\n if (ext === 'jpg') {\n let i = 2\n while (i + 9 < bytes.length) {\n if (bytes[i] !== 0xff) return null\n const marker = bytes[i + 1]\n const len = dv.getUint16(i + 2)\n if (\n marker >= 0xc0 &&\n marker <= 0xcf &&\n marker !== 0xc4 &&\n marker !== 0xc8 &&\n marker !== 0xcc\n ) {\n return ratio(dv.getUint16(i + 7), dv.getUint16(i + 5))\n }\n i += 2 + len\n }\n return null\n }\n return null\n}\n\nfunction ratio(w: number, h: number): number | null {\n return w > 0 && h > 0 ? w / h : null\n}\n\n/**\n * Fetch the brand's marks into `<takeDir>/brand/` and read their aspects.\n * A role may be a URL or a path (relative to the take). Absent roles are\n * absent marks; a failed fetch or an unreadable file is a note, never an\n * error: the kit falls back to the wordmark in words.\n */\nexport async function fetchBrandMarks(\n takeDir: string,\n roles: Record<string, string> | null | undefined,\n): Promise<BrandMarks> {\n const out: BrandMarks = { light: null, dark: null, notes: [] }\n if (!roles) return out\n const one = async (\n role: 'logoUrl' | 'logoOnDarkUrl',\n name: string,\n ): Promise<BrandMark | null> => {\n const src = (roles[role] ?? '').trim()\n if (!src) return null\n const ext = markExtension(src)\n if (!ext) {\n out.notes.push(\n `${role}: ${src} is not an svg, png, webp or jpg; the wordmark stands in`,\n )\n return null\n }\n let bytes: Uint8Array\n try {\n if (/^https?:/i.test(src)) {\n const res = await fetch(src)\n if (!res.ok) throw new Error(`HTTP ${res.status}`)\n bytes = new Uint8Array(await res.arrayBuffer())\n } else {\n const file = isAbsolute(src) ? src : resolve(takeDir, src)\n if (!existsSync(file)) throw new Error('no such file')\n bytes = new Uint8Array(await readFile(file))\n }\n } catch (e) {\n out.notes.push(\n `${role}: ${src} could not be read (${e instanceof Error ? e.message : String(e)}); the wordmark stands in`,\n )\n return null\n }\n const aspect = imageAspect(bytes, ext)\n if (!aspect) {\n out.notes.push(\n `${role}: ${src} has no readable size; the wordmark stands in`,\n )\n return null\n }\n await mkdir(join(takeDir, 'brand'), { recursive: true })\n await writeFile(join(takeDir, 'brand', `${name}.${ext}`), bytes)\n return { key: `/brand/${name}.${ext}`, aspect }\n }\n out.light = await one('logoUrl', 'mark')\n out.dark = await one('logoOnDarkUrl', 'mark-on-dark')\n return out\n}\n","/**\n * The official templates on vos.so, found by TITLE on the official shelf\n * (`GET /api/vos/official`): the platform's `Templates` project, promoted,\n * is the registry, so a template is a document anyone can read and the\n * CLI carries no numbers of its own. A ref that is neither a file nor a\n * vos id resolves here (`--with \"End card\"`, `--style \"Split cover,\n * landscape\"`, `--style split-cover-square`: the match ignores case,\n * spaces and punctuation), and the end card `plan` proposes when the\n * recipe says `on` (or nothing) is the official `End card`; the house\n * clips in `motionPlan.ts` survive as the offline fallback only.\n */\n\n/** The official end card's title. */\nexport const OFFICIAL_END_CARD_TITLE = 'End card'\n\n/** The official split cover's title per aspect class. */\nexport const OFFICIAL_POSTER_TITLES = {\n landscape: 'Split cover, landscape',\n square: 'Split cover, square',\n portrait: 'Split cover, portrait',\n tile: 'Split cover, tile',\n} as const\n\n/** A title or a ref reduced to what identifies it: lowercase, letters and digits only. */\nexport function templateKey(s: string): string {\n return s.toLowerCase().replace(/[^a-z0-9]+/g, '')\n}\n\nexport interface OfficialRow {\n id: string\n title: string\n slug?: string\n}\n\n/**\n * The official vos a ref names, by its title (or its slug), or null. The\n * first match in the shelf's own order wins, so a duplicate title on the\n * gallery resolves to the one the founder sorted first.\n */\nexport function findOfficialByRef(\n rows: readonly OfficialRow[],\n ref: string,\n): OfficialRow | null {\n const key = templateKey(ref)\n if (!key) return null\n for (const row of rows) {\n if (templateKey(row.title) === key) return row\n if (row.slug && templateKey(row.slug) === key) return row\n }\n return null\n}\n","/**\n * The music catalog the platform publishes at `GET /api/music`: the\n * curated CC0 tracks (slug, mood, duration, an absolute URL on the assets\n * host) and the built-in sound effects. Read once per run when a\n * destination plays sound; a failed read is said and the cut stays silent.\n */\nimport type { MusicCatalog } from './motionPlan'\n\nexport async function fetchMusicCatalog(origin: string): Promise<MusicCatalog> {\n const base = origin.replace(/\\/+$/, '')\n const res = await fetch(`${base}/api/music`)\n if (!res.ok) throw new Error(`GET ${base}/api/music answered ${res.status}`)\n const body = (await res.json()) as Partial<MusicCatalog>\n return {\n tracks: Array.isArray(body.tracks) ? body.tracks : [],\n sfx: Array.isArray(body.sfx) ? body.sfx : [],\n }\n}\n","/**\n * `vos judge <kit.json> --against <manifest.json>`: the kit beside its\n * references, composed as sheets an agent (or a person) judges pairwise.\n * No model runs here: for every kit asset that has a reference of its\n * role, the verb writes two sheets (the asset left and right, so order\n * cannot bias the call), a rubric in words, and a verdict slot the judge\n * fills; a summary counts the wins. The reference set is the maker's own\n * (a private fixture folder with a manifest), never redistributed.\n */\nimport { existsSync } from 'node:fs'\nimport { mkdir, readFile, writeFile } from 'node:fs/promises'\nimport { dirname, isAbsolute, join, resolve } from 'node:path'\nimport { DESTINATIONS } from '@vosjs/studio-core'\nimport { decodePng } from './picture'\nimport { encodePng } from './shotBake'\nimport type { Rgba } from './picture'\nimport type { KitRecord } from './validateKit'\n\nexport interface ReferenceAsset {\n id: string\n file: string\n /** What a kit asset matches on: a template family, a card genre, a video's first frame. */\n role: string\n genre: 'card' | 'video' | 'context' | 'screenshot'\n layout: string\n facts?: Record<string, unknown>\n rule: string\n}\n\nexport interface ReferenceManifest {\n assets: ReferenceAsset[]\n}\n\n/** The rubric every sheet carries: the eight clip rules and the poster layout facts. */\nexport const RUBRIC = [\n 'A plate, and room on it: the subject sits at 74 to 89% of the width with headroom; nobody bleeds a window on all four sides.',\n 'The window is an object: rounded corners and a shadow with weight (a soft wide one on a light plate, a tight glow on a dark one).',\n 'It enters: the first frame is not a static, centred, flat window (a tilt-in, a pull-out, a rise).',\n 'The camera zooms to the affordance, holds through the response, and pulls out to show the consequence.',\n 'Beats are cut at stillness; no wipes.',\n 'Content is staged: real data, a populated state, never an empty canvas or a wallpaper.',\n 'The cursor is a character: visible, smoothed, a press on click, never drifting through dead space.',\n 'The last frame is a poster: a resolved state you could ship as the still.',\n 'The message has its own column or its own frame; the headline is two to six words over up to three lines at about 40% of the height; the wordmark is anchored.',\n 'The poster test: would you post this frame as a still, alone?',\n 'The thumbnail test: does it read at half size?',\n 'Name three ways this asset acknowledges THIS product (its data, its state, its brand), not a generic window.',\n]\n\n/** Which reference roles a kit asset can be judged against. */\nexport function rolesFor(asset: {\n destination?: string\n source?: string\n template?: string\n path: string\n}): string[] {\n if ((asset.source === 'poster' || asset.source === 'stage') && asset.template)\n return [asset.template.replace(/-stage$/, '')]\n const spec = DESTINATIONS.find((d) => d.id === asset.destination)\n if (spec?.kind === 'video') {\n const portrait = spec.px.w < spec.px.h\n return portrait\n ? ['feature-clip', 'site-walkthrough']\n : ['feature-clip', 'site-walkthrough', 'feature-clip-dark']\n }\n if (spec?.genre === 'card')\n return ['window-in-scene', 'card-on-gradient', 'framed-screenshot']\n if (spec?.genre === 'screenshot') return ['framed-screenshot', 'app-session']\n return []\n}\n\n/** Box-filter resample to `w`×`h` (a clean downscale; upscales bilinearly enough for a sheet). */\nexport function resample(img: Rgba, w: number, h: number): Rgba {\n const out = new Uint8Array(w * h * 4)\n const sx = img.w / w\n const sy = img.h / h\n for (let y = 0; y < h; y++) {\n const y0 = Math.floor(y * sy)\n const y1 = Math.max(y0 + 1, Math.floor((y + 1) * sy))\n for (let x = 0; x < w; x++) {\n const x0 = Math.floor(x * sx)\n const x1 = Math.max(x0 + 1, Math.floor((x + 1) * sx))\n let r = 0\n let g = 0\n let b = 0\n let a = 0\n let n = 0\n for (let yy = y0; yy < y1 && yy < img.h; yy++) {\n for (let xx = x0; xx < x1 && xx < img.w; xx++) {\n const o = (yy * img.w + xx) * 4\n r += img.data[o]\n g += img.data[o + 1]\n b += img.data[o + 2]\n a += img.data[o + 3]\n n++\n }\n }\n const o = (y * w + x) * 4\n out[o] = n ? r / n : 0\n out[o + 1] = n ? g / n : 0\n out[o + 2] = n ? b / n : 0\n out[o + 3] = n ? a / n : 0\n }\n }\n return { w, h, data: out }\n}\n\n/**\n * Two pictures on one sheet at a common height with a gutter, on the\n * plate ground; `left` first. A thin band under each marks its side (a\n * dark band left, a light band right) so the order can be read back\n * without type.\n */\nexport function composeSheet(\n left: Rgba,\n right: Rgba,\n height = 540,\n gutter = 32,\n): Rgba {\n const lw = Math.max(1, Math.round((left.w * height) / left.h))\n const rw = Math.max(1, Math.round((right.w * height) / right.h))\n const L = resample(left, lw, height)\n const R = resample(right, rw, height)\n const margin = 24\n const band = 8\n const w = margin * 2 + lw + gutter + rw\n const h = margin * 2 + height + band + 6\n const out = new Uint8Array(w * h * 4)\n for (let i = 0; i < w * h; i++) {\n out[i * 4] = 240\n out[i * 4 + 1] = 242\n out[i * 4 + 2] = 244\n out[i * 4 + 3] = 255\n }\n const blit = (src: Rgba, x0: number, y0: number) => {\n for (let y = 0; y < src.h; y++) {\n for (let x = 0; x < src.w; x++) {\n const si = (y * src.w + x) * 4\n const a = src.data[si + 3] / 255\n const o = ((y0 + y) * w + x0 + x) * 4\n for (let c = 0; c < 3; c++)\n out[o + c] = Math.round(src.data[si + c] * a + out[o + c] * (1 - a))\n }\n }\n }\n blit(L, margin, margin)\n blit(R, margin + lw + gutter, margin)\n const fill = (x0: number, x1: number, y0: number, y1: number, v: number) => {\n for (let y = y0; y < y1; y++)\n for (let x = x0; x < x1; x++) {\n const o = (y * w + x) * 4\n out[o] = v\n out[o + 1] = v\n out[o + 2] = v\n }\n }\n fill(margin, margin + lw, margin + height + 6, margin + height + 6 + band, 40)\n fill(\n margin + lw + gutter,\n margin + lw + gutter + rw,\n margin + height + 6,\n margin + height + 6 + band,\n 200,\n )\n return { w, h, data: out }\n}\n\nexport interface JudgeSheet {\n asset: string\n reference: string\n /** The two sheets: A = asset left, B = reference left. */\n sheetA: string\n sheetB: string\n rubric: string\n}\n\nexport interface JudgeResult {\n sheets: JudgeSheet[]\n skipped: string[]\n outDir: string\n verdictFile: string\n}\n\n/**\n * Compose the sheets for a kit against a manifest. For each still asset\n * with a reference of its role, the two orders and the rubric; the verdict\n * file is a JSON skeleton the judge fills (`win: true|false|null` per\n * sheet, with a reason) and `count.mjs` reads.\n */\nexport async function judgeKit(\n kitPath: string,\n manifestPath: string,\n outDir?: string,\n): Promise<JudgeResult> {\n const kit = JSON.parse(await readFile(kitPath, 'utf8')) as KitRecord & {\n assets: (KitRecord['assets'][number] & { template?: string })[]\n }\n const manifest = JSON.parse(\n await readFile(manifestPath, 'utf8'),\n ) as ReferenceManifest\n const manifestDir = dirname(resolve(manifestPath))\n const kitDir = dirname(resolve(kitPath))\n const out = resolve(outDir ?? join(kitDir, 'judge'))\n await mkdir(out, { recursive: true })\n const sheets: JudgeSheet[] = []\n const skipped: string[] = []\n const refCache = new Map<string, Rgba | null>()\n const loadRef = async (file: string) => {\n if (refCache.has(file)) return refCache.get(file) ?? null\n const p = join(manifestDir, file)\n const img = existsSync(p)\n ? decodePng(new Uint8Array(await readFile(p)))\n : null\n refCache.set(file, img)\n return img\n }\n for (const a of kit.assets) {\n if (!/\\.png$/i.test(a.path)) continue\n const file =\n isAbsolute(a.path) && existsSync(a.path)\n ? a.path\n : join(kitDir, a.path.split('/').pop() ?? a.path)\n const img = existsSync(file)\n ? decodePng(new Uint8Array(await readFile(file)))\n : null\n if (!img) {\n skipped.push(`${a.destination ?? a.path}: unreadable`)\n continue\n }\n const roles = rolesFor({\n destination: a.destination,\n source: a.source,\n template: a.template,\n path: a.path,\n })\n const ref = manifest.assets.find(\n (r) => roles.includes(r.role) && r.genre !== 'context',\n )\n if (!ref) {\n skipped.push(\n `${a.destination ?? a.path}: no reference of role ${roles.join('|') || '(none)'}`,\n )\n continue\n }\n const refImg = await loadRef(ref.file)\n if (!refImg) {\n skipped.push(\n `${a.destination ?? a.path}: reference ${ref.file} unreadable`,\n )\n continue\n }\n // A still set's members share a destination: the file's own stem is the id.\n const stem = (a.path.split('/').pop() ?? a.path).replace(/\\.png$/i, '')\n const id = stem.replace(/[^A-Za-z0-9_-]+/g, '-') || a.destination || 'asset'\n const nameA = `${id}--A.png`\n const nameB = `${id}--B.png`\n await writeFile(join(out, nameA), encodePng(composeSheet(img, refImg)))\n await writeFile(join(out, nameB), encodePng(composeSheet(refImg, img)))\n const rubric = [\n `# ${id} against ${ref.id} (${ref.file})`,\n '',\n `Sheet A: the kit asset LEFT (dark band), the reference RIGHT (light band). Sheet B: the reverse.`,\n `Judge each sheet on its own, both orders, and write the verdict where the two agree; a disagreement is a tie.`,\n '',\n `## The reference`,\n ref.layout,\n ...(ref.facts\n ? ['', '```json', JSON.stringify(ref.facts, null, 2), '```']\n : []),\n '',\n `Rule: ${ref.rule}`,\n '',\n '## The rubric',\n ...RUBRIC.map((r, i) => `${i + 1}. ${r}`),\n '',\n '## Verdict',\n 'In judge.json: `win` true when the kit asset is at least as good as the reference on the rules that apply to its genre, false when it is worse, null for a tie; `reasons` names the rules by number.',\n '',\n ].join('\\n')\n await writeFile(join(out, `${id}.md`), rubric)\n sheets.push({\n asset: id,\n reference: ref.id,\n sheetA: nameA,\n sheetB: nameB,\n rubric: `${id}.md`,\n })\n }\n const verdictFile = join(out, 'judge.json')\n if (!existsSync(verdictFile)) {\n await writeFile(\n verdictFile,\n JSON.stringify(\n {\n kit: kitPath,\n manifest: manifestPath,\n verdicts: sheets.map((s) => ({\n asset: s.asset,\n reference: s.reference,\n A: null,\n B: null,\n win: null,\n reasons: [],\n })),\n },\n null,\n 2,\n ),\n )\n }\n return { sheets, skipped, outDir: out, verdictFile }\n}\n\n/**\n * The win rate: a win counts one, a tie (`win: null` with reasons) counts a\n * half, the pairwise convention; a pair with no reasons was not judged and\n * does not count. Parity with the references is 0.5.\n */\nexport function winRate(\n verdicts: { win: boolean | null; reasons?: number[] }[],\n): { wins: number; ties: number; judged: number; rate: number | null } {\n const judgedList = verdicts.filter(\n (v) => v.win !== null || (v.reasons?.length ?? 0) > 0,\n )\n const wins = judgedList.filter((v) => v.win === true).length\n const ties = judgedList.filter((v) => v.win === null).length\n const judged = judgedList.length\n return {\n wins,\n ties,\n judged,\n rate: judged ? (wins + ties / 2) / judged : null,\n }\n}\n","/**\n * The shot as an OBJECT: a full-bleed page capture padded with a\n * transparent margin, its corners rounded, a soft shadow under it, encoded\n * back to PNG. The image element the poster family binds carries none of\n * these (an engine ask), so the shot arrives already sitting on whatever\n * ground the template paints. Pure over decoded pixels; the blur is a\n * three-pass box blur (a gaussian to the eye) on the alpha mask.\n */\nimport { deflateSync } from 'node:zlib'\nimport type { Rgba } from './picture'\n\nexport interface BakeOptions {\n /** Transparent margin around the shot, as a fraction of its width (0.06). */\n margin?: number\n /** Corner radius as a fraction of the shot's width (0.014). */\n radius?: number\n /**\n * Shadow strength 0..1 (0.3); 0 = no shadow. Two layers share it: a\n * tight one at the edge and a wide one below, each at a low alpha, so\n * the shot reads as lifted rather than sitting in a dark pool.\n */\n shadow?: number\n /** The wide layer's blur radius as a fraction of the shot's width (0.05). */\n blur?: number\n /** The wide layer's offset downward as a fraction of the shot's width (0.02). */\n offsetY?: number\n /** A hairline around the shot, alpha 0..1 (0 = none), for light shots on light grounds. */\n hairline?: number\n}\n\n/** Box blur one channel of a w×h float plane, radius r, in place; three passes. */\nfunction blurPlane(\n src: Float32Array,\n w: number,\n h: number,\n r: number,\n passes = 3,\n) {\n if (r < 1) return\n const tmp = new Float32Array(src.length)\n for (let p = 0; p < passes; p++) {\n // horizontal\n for (let y = 0; y < h; y++) {\n let acc = 0\n const row = y * w\n for (let x = -r; x <= r; x++)\n acc += src[row + Math.min(w - 1, Math.max(0, x))]\n for (let x = 0; x < w; x++) {\n tmp[row + x] = acc / (2 * r + 1)\n const add = src[row + Math.min(w - 1, x + r + 1)]\n const sub = src[row + Math.max(0, x - r)]\n acc += add - sub\n }\n }\n // vertical\n for (let x = 0; x < w; x++) {\n let acc = 0\n for (let y = -r; y <= r; y++)\n acc += tmp[Math.min(h - 1, Math.max(0, y)) * w + x]\n for (let y = 0; y < h; y++) {\n src[y * w + x] = acc / (2 * r + 1)\n const add = tmp[Math.min(h - 1, y + r + 1) * w + x]\n const sub = tmp[Math.max(0, y - r) * w + x]\n acc += add - sub\n }\n }\n }\n}\n\n/** Coverage of a rounded rect at pixel (x, y) with 2x2 supersampling, 0..1. */\nfunction roundedCoverage(\n x: number,\n y: number,\n rect: { x: number; y: number; w: number; h: number },\n r: number,\n): number {\n let inside = 0\n for (const dy of [0.25, 0.75]) {\n for (const dx of [0.25, 0.75]) {\n const px = x + dx\n const py = y + dy\n if (\n px < rect.x ||\n py < rect.y ||\n px > rect.x + rect.w ||\n py > rect.y + rect.h\n )\n continue\n const cx = Math.min(Math.max(px, rect.x + r), rect.x + rect.w - r)\n const cy = Math.min(Math.max(py, rect.y + r), rect.y + rect.h - r)\n if ((px - cx) ** 2 + (py - cy) ** 2 <= r * r) inside++\n }\n }\n return inside / 4\n}\n\n/** Pad, round and shadow a shot. The output is RGBA with a transparent margin. */\nexport function bakeShot(shot: Rgba, opts: BakeOptions = {}): Rgba {\n const margin = Math.round(shot.w * (opts.margin ?? 0.06))\n const radius = shot.w * (opts.radius ?? 0.014)\n const shadowA = opts.shadow ?? 0.3\n const blur = Math.round(shot.w * (opts.blur ?? 0.05))\n const offsetY = Math.round(shot.w * (opts.offsetY ?? 0.02))\n const hair = opts.hairline ?? 0\n const w = shot.w + margin * 2\n const h = shot.h + margin * 2\n const out = new Uint8Array(w * h * 4)\n const rect = { x: margin, y: margin, w: shot.w, h: shot.h }\n\n if (shadowA > 0) {\n // Two layers: tight at the edge (a quarter of the blur, a fifth of the\n // offset, 0.4 of the strength) and wide below (0.6 of the strength).\n const layers: [number, number, number][] = [\n [Math.max(1, Math.round(blur / 4)), Math.round(offsetY / 5), 0.4],\n [blur, offsetY, 0.6],\n ]\n const acc = new Float32Array(w * h)\n for (const [lb, lo, share] of layers) {\n const mask = new Float32Array(w * h)\n for (let y = 0; y < h; y++)\n for (let x = 0; x < w; x++) {\n const c = roundedCoverage(x, y - lo, rect, radius)\n if (c > 0) mask[y * w + x] = c\n }\n blurPlane(mask, w, h, Math.max(1, Math.round(lb / 2)))\n const a = shadowA * share\n // Layers composite over each other: 1 - (1-a1)(1-a2).\n for (let i = 0; i < w * h; i++)\n acc[i] = 1 - (1 - acc[i]) * (1 - mask[i] * a)\n }\n for (let i = 0; i < w * h; i++) {\n const a = acc[i]\n if (a <= 0.002) continue\n out[i * 4] = 0\n out[i * 4 + 1] = 0\n out[i * 4 + 2] = 0\n out[i * 4 + 3] = Math.round(a * 255)\n }\n }\n\n for (let y = 0; y < h; y++) {\n for (let x = 0; x < w; x++) {\n const cov = roundedCoverage(x, y, rect, radius)\n if (cov <= 0) continue\n const sx = Math.min(shot.w - 1, Math.max(0, x - margin))\n const sy = Math.min(shot.h - 1, Math.max(0, y - margin))\n const si = (sy * shot.w + sx) * 4\n const o = (y * w + x) * 4\n let r = shot.data[si]\n let g = shot.data[si + 1]\n let b = shot.data[si + 2]\n // A hairline at the edge: the outer 1.5 px darkened.\n if (hair > 0) {\n const edge = Math.min(\n x - rect.x,\n rect.x + rect.w - x,\n y - rect.y,\n rect.y + rect.h - y,\n )\n if (edge < 1.5) {\n r = Math.round(r * (1 - hair))\n g = Math.round(g * (1 - hair))\n b = Math.round(b * (1 - hair))\n }\n }\n // Composite the shot over whatever shadow lies under this pixel.\n const a = cov\n const ba = out[o + 3] / 255\n const outA = a + ba * (1 - a)\n const mix = (fg: number, bg: number) =>\n outA > 0 ? Math.round((fg * a + bg * ba * (1 - a)) / outA) : 0\n out[o] = mix(r, out[o])\n out[o + 1] = mix(g, out[o + 1])\n out[o + 2] = mix(b, out[o + 2])\n out[o + 3] = Math.round(outA * 255)\n }\n }\n return { w, h, data: out }\n}\n\nconst crcTable = (() => {\n const t = new Uint32Array(256)\n for (let n = 0; n < 256; n++) {\n let c = n\n for (let k = 0; k < 8; k++) c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1\n t[n] = c >>> 0\n }\n return t\n})()\n\nfunction crc32(buf: Uint8Array): number {\n let c = 0xffffffff\n for (const b of buf) c = crcTable[(c ^ b) & 255] ^ (c >>> 8)\n return (c ^ 0xffffffff) >>> 0\n}\n\nfunction chunk(type: string, body: Uint8Array): Uint8Array {\n const out = new Uint8Array(12 + body.length)\n const dv = new DataView(out.buffer)\n dv.setUint32(0, body.length)\n for (let i = 0; i < 4; i++) out[4 + i] = type.charCodeAt(i)\n out.set(body, 8)\n dv.setUint32(8 + body.length, crc32(out.subarray(4, 8 + body.length)))\n return out\n}\n\n/** Encode RGBA as an 8-bit truecolor-with-alpha PNG (the \"up\" filter per row). */\nexport function encodePng(img: Rgba): Uint8Array {\n const stride = img.w * 4\n const raw = new Uint8Array((stride + 1) * img.h)\n for (let y = 0; y < img.h; y++) {\n raw[y * (stride + 1)] = 2\n for (let i = 0; i < stride; i++) {\n const cur = img.data[y * stride + i]\n const up = y ? img.data[(y - 1) * stride + i] : 0\n raw[y * (stride + 1) + 1 + i] = (cur - up) & 255\n }\n }\n const ihdr = new Uint8Array(13)\n const dv = new DataView(ihdr.buffer)\n dv.setUint32(0, img.w)\n dv.setUint32(4, img.h)\n ihdr[8] = 8\n ihdr[9] = 6\n const parts = [\n new Uint8Array([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]),\n chunk('IHDR', ihdr),\n chunk('IDAT', new Uint8Array(deflateSync(raw))),\n chunk('IEND', new Uint8Array(0)),\n ]\n const out = new Uint8Array(parts.reduce((n, p) => n + p.length, 0))\n let o = 0\n for (const p of parts) {\n out.set(p, o)\n o += p.length\n }\n return out\n}\n","import { findFontFamily } from '@vosjs/shared'\n\n/**\n * The name a family goes by in the hosted catalog, when a site's own CSS\n * name for it differs only by the `Variable` suffix.\n *\n * A site ships `Inter Variable` or `Lexend Variable` (the fontsource names),\n * and that is what a page's computed style reports. The catalog hosts the\n * same family as `Inter` or `Lexend`, and a render page registers the face\n * under THAT name, so CSS written with the site's name matches nothing and\n * falls back to a system stack, silently on the fleet. The name is corrected\n * where it is WRITTEN (the brand kit, the composed callout), never at the\n * lookup: a lookup that forgave the suffix would find the face and still\n * leave the CSS asking for a family nobody registered.\n *\n * A family the catalog does not host is returned untouched.\n */\nexport function catalogFamily(family: string): string {\n const name = family.trim()\n if (findFontFamily(name)) return name\n const base = name.replace(/\\s+Variable$/i, '')\n if (base !== name) {\n const hit = findFontFamily(base)\n if (hit) return hit.family\n }\n return family\n}\n","/**\n * `vos callout` — a callout in the grammar, from the take's register.\n *\n * The agent names the shape, the words and the step the layer is about;\n * the verb reads the product's register from `BRAND.md` beside the take\n * (or the flags), takes the type scale from the camera at the layer's\n * start (the app's body as it appears on screen), places the window from\n * the step's output extent, writes the clip pinned to that step and lints\n * the document. What a hand would have to get right in CSS is a computation\n * here, so the card is the video's and the product's at once.\n *\n * `validate <take> --picture` has its eyes here too: each html layer's\n * ground against the footage it covers, as the camera shows it at the\n * layer's start, in CIE76 ΔE — a card within a few ΔE of what it covers\n * reads as one more panel.\n */\nimport { catalogFamily } from './fontName'\nimport { existsSync } from 'node:fs'\nimport { readFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport { lerpArray, sample } from '@vosjs/timeline'\nimport {\n CALLOUT_DEFAULT_BODY_PX,\n CALLOUT_SHAPES,\n calloutClip,\n calloutLook,\n calloutGroundOf,\n cameraModel,\n deltaE,\n docCardLayout,\n docZoomTrack,\n hexToRgb,\n parseCssColour,\n pinBox,\n ratedSegments,\n resolvePins,\n spanOutputExtent,\n} from '@vosjs/studio-core'\nimport { decodePng, medianColour } from './picture'\nimport type { Browser } from 'playwright'\nimport type {\n CalloutRegister,\n CalloutShape,\n CalloutWords,\n HtmlOverlayClip,\n OverlayClip,\n OverlayPin,\n PinMark,\n PinSide,\n ProjectDoc,\n} from '@vosjs/studio-core'\nimport type { Rgba } from './picture'\n\n/** How long a callout stays up when nothing says otherwise. */\nexport const CALLOUT_DEFAULT_SECONDS = 3\n/** The card opens this long after the step's press lands on screen. */\nexport const CALLOUT_LEAD_SECONDS = 0.2\n/** ΔE under which the card's ground is the footage's: a problem. */\nexport const CALLOUT_DELTA_E_PROBLEM = 8\n/** ΔE under which the card only just separates: a warning. */\nexport const CALLOUT_DELTA_E_WARNING = 16\n\n/**\n * The register from BRAND.md's roles (`bgA`, `accent`, `fontBody`) and the\n * flags that override them. Null when neither names a ground and an\n * accent.\n *\n * A kit may name a `callout` role, and it wins over `accent`: some brands\n * RESERVE their accent. A recorder's red marks time and nothing else, so a\n * note kicker in it breaks the brand's own rule, twice over when the\n * product's playhead is in the same frame. The composer cannot know what a\n * brand reserves; a role is how the kit says it.\n */\nexport function registerFrom(\n roles: Record<string, string> | null,\n flags: {\n ground?: string\n accent?: string\n face?: string\n mono?: string\n body?: number\n },\n): CalloutRegister | null {\n const ground = flags.ground ?? roles?.bgA\n const accent = flags.accent ?? roles?.callout ?? roles?.accent\n if (!ground || !accent) return null\n if (!hexToRgb(ground) || !hexToRgb(accent)) return null\n // The catalog's name for the face, or the CSS asks for a family no\n // render page registers (fontName.ts).\n const named = flags.face ?? roles?.fontBody\n const face = named ? catalogFamily(named) : named\n return {\n ground,\n accent,\n ...(face && !/^ui-sans-serif$|^system-ui$/.test(face) ? { face } : {}),\n ...(flags.mono ? { mono: flags.mono } : {}),\n body: flags.body ?? CALLOUT_DEFAULT_BODY_PX,\n }\n}\n\n/**\n * Design px per CSS px of the app on screen at OUTPUT time t: the card's\n * footage scale times the camera's level.\n */\nexport function appScaleAt(doc: ProjectDoc, t: number): number {\n const layout = docCardLayout(doc)\n const meta = doc.source.meta\n const base = layout.dw / Math.max(1, meta.width)\n const track = docZoomTrack(doc)\n if (!track || !track.keyframes.length) return base\n const z = sample(track, t, lerpArray)\n return base * Math.max(1, z[0])\n}\n\nexport interface CalloutWindow {\n start: number\n duration: number\n}\n\n/**\n * The layer's window from the step it is about: it opens a beat after the\n * step's press lands on screen and stays CALLOUT_DEFAULT_SECONDS, cut short\n * by the next scroll or navigation so the referent is still there.\n */\nexport function windowForStep(\n doc: ProjectDoc,\n step: string | number,\n seconds = CALLOUT_DEFAULT_SECONDS,\n): CalloutWindow | null {\n const steps = doc.source.meta.steps ?? []\n const s =\n steps.find((x) => x.id !== undefined && x.id === step) ??\n steps.find((x) => String(x.step) === String(step))\n if (!s || s.skipped) return null\n const rated = ratedSegments(doc)\n const ext = spanOutputExtent(rated, s.tStart, s.tEnd)\n if (!ext) return null\n // The press is at the step's start for a click, the gesture's end for a\n // hover or a type; the card opens once the press has landed.\n const at = s.do === 'click' || s.do === 'drag' ? ext.start : ext.end\n const start = +(at + CALLOUT_LEAD_SECONDS).toFixed(3)\n let end = start + seconds\n for (const n of steps) {\n if (n.tStart <= s.tStart) continue\n if (n.do !== 'scroll' && !n.navigated) continue\n const ne = spanOutputExtent(rated, n.tStart, n.tEnd)\n if (ne && ne.start > start && ne.start < end) end = ne.start - 0.05\n }\n return { start, duration: +Math.max(0.5, end - start).toFixed(3) }\n}\n\nexport interface CalloutAsk {\n shape: CalloutShape\n words: CalloutWords\n id?: string\n step?: string | number\n press?: number\n at?: number\n seconds?: number\n side?: PinSide\n mark?: PinMark\n leader?: boolean\n color?: string\n /**\n * `--body-px` was GIVEN: the register's body is then the size on the\n * delivered frame and is not rescaled. Without it the grammar's default\n * stands, a note that matches the app's body AS SEEN, which multiplies by\n * the footage scale. A rich capture on a padded frame sits near 0.6, and\n * at that scale both 14 and 21 land under the grammar's floors, so an\n * explicit size used to print the same 11 / 20 / 15 as no size at all.\n */\n bodyPxGiven?: boolean\n}\n\n/** What the composer chose, so the verb can say it instead of hiding a floor. */\nexport interface CalloutSizes {\n scale: number\n kickerPx: number\n titlePx: number\n bodyPx: number\n}\n\n/** The clip `vos callout` writes: grammar, register, window and pin composed. */\nexport function composeCallout(\n doc: ProjectDoc,\n register: CalloutRegister,\n ask: CalloutAsk,\n): { clip: HtmlOverlayClip; window: CalloutWindow; sizes: CalloutSizes } {\n let window: CalloutWindow | null = null\n if (ask.step !== undefined) {\n window = windowForStep(doc, ask.step, ask.seconds)\n if (!window)\n throw new Error(\n `step \"${String(ask.step)}\" is not in the take's step timeline, was skipped, or falls outside the cut`,\n )\n } else if (ask.at !== undefined) {\n window = {\n start: ask.at,\n duration: ask.seconds ?? CALLOUT_DEFAULT_SECONDS,\n }\n } else {\n throw new Error(\n 'name the step the callout is about (--step <id>), or --at <output seconds>',\n )\n }\n const pin: OverlayPin | undefined =\n ask.step !== undefined\n ? { step: ask.step }\n : ask.press !== undefined\n ? { press: ask.press }\n : undefined\n if (pin) {\n if (ask.side && ask.side !== 'auto') pin.side = ask.side\n if (ask.mark && ask.mark !== 'none') pin.mark = ask.mark\n if (ask.leader) pin.leader = true\n if (ask.color) pin.color = ask.color\n }\n const taken = new Set((doc.overlays ?? []).map((o) => o.id))\n let id = ask.id ?? `${ask.shape}-${ask.step ?? Math.round(window.start * 10)}`\n let n = 2\n while (taken.has(id) && !ask.id)\n id = `${ask.shape}-${ask.step ?? Math.round(window.start * 10)}-${n++}`\n const seen = appScaleAt(doc, window.start + 0.35)\n const scale = ask.bodyPxGiven ? 1 : seen\n const look = calloutLook(register, scale)\n const clip = calloutClip(ask.shape, register, ask.words, {\n id,\n start: window.start,\n duration: window.duration,\n scale,\n pin,\n // The fallback place, in the margin: the lower third.\n at: { x: 0.5, y: 0.82 },\n })\n return {\n clip,\n window,\n sizes: {\n scale: +seen.toFixed(3),\n kickerPx: look.kickerPx,\n titlePx: look.titlePx,\n bodyPx: look.bodyPx,\n },\n }\n}\n\nexport function isCalloutShape(s: string): s is CalloutShape {\n return (CALLOUT_SHAPES as readonly string[]).includes(s)\n}\n\n// --- the picture check -----------------------------------------------------\n\nexport interface GroundFinding {\n index: number\n id: string\n level: 'problem' | 'warning' | 'note'\n deltaE: number | null\n card: string | null\n footage: string | null\n message: string\n}\n\n/**\n * ΔE between a card's declared ground and the footage under its box, as\n * the camera shows it at the layer's start plus its entrance. `frameAt`\n * renders the footage WITHOUT layers at an output time; the layer's box is\n * its on-screen rect (a pinned layer's from its placement).\n */\nexport async function groundFindings(\n doc: ProjectDoc,\n frameAt: (t: number) => Promise<Rgba | null>,\n): Promise<GroundFinding[]> {\n const out: GroundFinding[] = []\n const overlays = doc.overlays ?? []\n const layout = docCardLayout(doc)\n const camera = cameraModel(doc.frame)\n const track = docZoomTrack(doc)\n const pins = resolvePins(doc, layout, camera, track)\n for (let i = 0; i < overlays.length; i++) {\n const o = overlays[i]\n if (o.kind !== 'html') continue\n const card = calloutGroundOf(o.css ?? '')\n if (!card) {\n out.push({\n index: i,\n id: o.id,\n level: 'note',\n deltaE: null,\n card: null,\n footage: null,\n message: `overlays[${i}] declares no readable background on its root rule — the ground check cannot read it`,\n })\n continue\n }\n const t = o.start + Math.min(0.35, o.duration / 2)\n const img = await frameAt(t)\n if (!img) {\n out.push({\n index: i,\n id: o.id,\n level: 'note',\n deltaE: null,\n card,\n footage: null,\n message: `overlays[${i}]: the frame at ${t.toFixed(2)}s could not be read`,\n })\n continue\n }\n const box = pinBox(o as OverlayClip, layout)\n const pinned = pins.get(o.id)\n let cx = o.transform.x * layout.W\n let cy = o.transform.y * layout.H\n if (pinned) {\n const v = sample(pinned.track, t - o.start, lerpArray)\n cx = v[0] * layout.W\n cy = v[1] * layout.H\n }\n const sx = img.w / layout.W\n const sy = img.h / layout.H\n const rect = {\n x: (cx - box.w / 2) * sx,\n y: (cy - box.h / 2) * sy,\n w: box.w * sx,\n h: box.h * sy,\n }\n const footage = medianColour(img, rect)\n const cardRgb = parseCssColour(card)\n if (!cardRgb) continue\n const d = deltaE(cardRgb, footage)\n const fh = `#${footage.map((c) => c.toString(16).padStart(2, '0')).join('')}`\n const level =\n d < CALLOUT_DELTA_E_PROBLEM\n ? 'problem'\n : d < CALLOUT_DELTA_E_WARNING\n ? 'warning'\n : 'note'\n out.push({\n index: i,\n id: o.id,\n level,\n deltaE: +d.toFixed(1),\n card,\n footage: fh,\n message:\n level === 'note'\n ? `overlays[${i}] ground ${card} over footage ${fh}: ΔE ${d.toFixed(1)}, reads as lifted`\n : `overlays[${i}] ground ${card} is within ΔE ${d.toFixed(1)} of the footage it covers (${fh}) at ${t.toFixed(2)}s — it reads as one more panel of the app; invert its value (vos callout does) or move it to the margin`,\n })\n }\n return out\n}\n\n/** Render the take's footage without layers at output times, one browser session. */\nexport async function footageFrames(\n browser: Browser,\n dir: string,\n doc: ProjectDoc,\n times: number[],\n framesTake: (\n browser: Browser,\n dir: string,\n opts: {\n times: number[]\n outDir?: string\n doc?: ProjectDoc\n },\n ) => Promise<{ frames: { file: string; time: number }[] }>,\n): Promise<Map<number, Rgba | null>> {\n const out = new Map<number, Rgba | null>()\n if (!times.length) return out\n const bare: ProjectDoc = { ...doc, overlays: [] }\n const outDir = join(dir, '.ground-check')\n const res = await framesTake(browser, dir, { times, outDir, doc: bare })\n for (const f of res.frames) {\n if (!existsSync(f.file)) continue\n out.set(\n +f.time.toFixed(3),\n decodePng(new Uint8Array(await readFile(f.file))),\n )\n }\n return out\n}\n","/**\n * `vos validate <kit.json> --picture`: what each asset LOOKS like, read\n * from its bytes the way the spec pass reads its size. Every finding\n * carries a code, a severity, a message written from the failure it was\n * built on, a fix hint and (where it has one) a box, so an agent can\n * self-check by name before it renders and a reader can find the spot.\n *\n * Checks, and the failure each was written from:\n * blank a card whose subject is under the ink floor (a wallpaper,\n * an empty canvas)\n * duplicate two stills of one frame (a kit of eight crops of one frame)\n * subject the card's width off the band, or a card bled on all four\n * sides where a card was asked for; a screenshot not full bleed\n * separation a light card on a light ground with no shadow and no edge\n * halfsize a tile that loses its edges at half size (the store rule)\n * sliced a text box crossing the frame edge (a headline cut mid-word)\n * safe a text box outside the destination's safe rect\n * contrast a text box under APCA Lc 60 (headline) / 75 (body)\n * firstlast a video whose first or last frame is blank or bled\n *\n * Text boxes come from the manifest (the poster leg records the element\n * layout it rendered), never from OCR: a take frame's page text is\n * unknown, so those three checks run only where the kit says where words\n * are. Pure over decoded pixels; the video frames come through ffmpeg\n * when it is on PATH and are skipped, said, when it is not.\n */\nimport { execFile } from 'node:child_process'\nimport { promisify } from 'node:util'\nimport { readFile } from 'node:fs/promises'\nimport {\n decodePng,\n edgeEnergy,\n hammingDistance,\n inkCoverage,\n measureStill,\n medianColour,\n} from './picture'\nimport type { Rect, Rgba, StillMeasure } from './picture'\nimport type { Destination } from '@vosjs/studio-core'\n\nconst execFileP = promisify(execFile)\n\nexport type PictureCode =\n | 'blank'\n | 'duplicate'\n | 'subject'\n | 'separation'\n | 'halfsize'\n | 'sliced'\n | 'safe'\n | 'contrast'\n | 'firstlast'\n | 'unreadable'\n\nexport interface PictureFinding {\n code: PictureCode\n severity: 'error' | 'warning' | 'info'\n /** The asset's destination id (or ids, for a duplicate group). */\n asset: string\n message: string\n fixHint: string\n /** Where, in pixels of the asset, when the finding has a place. */\n bbox?: Rect\n}\n\n/** A text box the manifest records, as fractions of the asset. */\nexport interface TextBox {\n x: number\n y: number\n w: number\n h: number\n /** `#rrggbb` of the type, for the contrast check. */\n color?: string\n /** 'headline' (Lc 60) or 'body' (Lc 75); absent = headline. */\n role?: 'headline' | 'body'\n /** For the message. */\n label?: string\n}\n\nexport interface PictureAsset {\n destination: string\n path: string\n file: string\n spec?: Pick<Destination, 'genre' | 'kind' | 'text' | 'safe' | 'px'>\n text?: TextBox[]\n seconds?: number | null\n /** The manifest says this screenshot kept the cut's camera and chrome. */\n composed?: boolean\n /**\n * A poster card's shot placement (fractions; a bleed runs past 1): the\n * composition is the template's, so the subject is the SHOT, and the\n * ground is designed rather than a plate to find a card on.\n */\n shot?: { x: number; y: number; w: number; h: number }\n /**\n * A tile: the shot is a close CROP of the page's hero, wider than the\n * frame by design (the subject band does not apply) and mostly the\n * page's own plate (a hero region is half as inky as a populated card).\n */\n crop?: boolean\n}\n\n/** The band the reference assets were measured to. */\nexport const SUBJECT_BAND = { min: 0.6, max: 0.92 }\n/** Ink coverage under which a card's subject is blank. */\nexport const BLANK_INK = 0.12\n/** L* difference under which a card needs a shadow to sit. */\nexport const SEPARATION_L = 8\n/** Shadow halo reading above which a shadow is present. */\nexport const SHADOW_PRESENT = 6\n/** Edge contrast above which a drawn edge (a hairline, a bar) separates the card. */\nexport const EDGE_PRESENT = 40\n/** Hamming bits under which two stills are one frame. */\nexport const DUPLICATE_BITS = 6\n/** Edge energy kept at half size, below which a tile stops reading. */\nexport const HALFSIZE_KEEP = 0.45\n\n/** APCA (W3 0.1.9) lightness contrast of text on a background, |Lc|. */\nexport function apcaContrast(\n text: [number, number, number],\n bg: [number, number, number],\n): number {\n const lum = (c: [number, number, number]) => {\n const ch = (v: number) => Math.pow(v / 255, 2.4)\n let y = 0.2126729 * ch(c[0]) + 0.7151522 * ch(c[1]) + 0.072175 * ch(c[2])\n if (y < 0.022) y += Math.pow(0.022 - y, 1.414)\n return y\n }\n const yt = lum(text)\n const yb = lum(bg)\n if (Math.abs(yb - yt) < 0.0005) return 0\n let sapc: number\n if (yb > yt) {\n sapc = (Math.pow(yb, 0.56) - Math.pow(yt, 0.57)) * 1.14\n return sapc < 0.1 ? 0 : (sapc - 0.027) * 100\n }\n sapc = (Math.pow(yb, 0.65) - Math.pow(yt, 0.62)) * 1.14\n return sapc > -0.1 ? 0 : -(sapc + 0.027) * 100\n}\n\nconst pct = (v: number) => `${Math.round(v * 100)}%`\n\nconst hexToRgb = (h: string): [number, number, number] | null => {\n const m = /^#([0-9a-f]{6})$/i.exec(h.trim())\n if (!m) return null\n const n = parseInt(m[1], 16)\n return [(n >> 16) & 255, (n >> 8) & 255, n & 255]\n}\n\n/** The checks on one still's measurement; pure. */\nexport function stillFindings(\n a: PictureAsset,\n img: Rgba,\n m: StillMeasure,\n): PictureFinding[] {\n const out: PictureFinding[] = []\n const genre = a.spec?.genre\n const bledAll = m.bleed.length === 4\n\n // A poster card: the subject is the shot the template placed. Its width\n // sits in the band (a bleed past the frame is a layout, so the ceiling\n // is loose), and the visible part of it carries ink.\n if (a.shot) {\n const sx = Math.max(0, a.shot.x) * img.w\n const sy = Math.max(0, a.shot.y) * img.h\n const sw = Math.min(1, a.shot.x + a.shot.w) * img.w - sx\n const sh = Math.min(1, a.shot.y + a.shot.h) * img.h - sy\n const rect = { x: sx, y: sy, w: Math.max(1, sw), h: Math.max(1, sh) }\n const ink = inkCoverage(img, rect)\n if (ink < (a.crop ? BLANK_INK / 2 : BLANK_INK)) {\n out.push({\n code: 'blank',\n severity: 'error',\n asset: a.destination,\n message: `${pct(ink)} ink inside the shot: the moment shows a wallpaper, an empty canvas or a flat panel`,\n fixHint:\n 'pick a moment after a gesture landed (--shot-time, or --times step:<id>) and stage the set before recording',\n bbox: rect,\n })\n }\n if (!a.crop && (a.shot.w < 0.5 || a.shot.w > 1.2)) {\n out.push({\n code: 'subject',\n severity: 'error',\n asset: a.destination,\n message: `the shot is ${pct(a.shot.w)} of the width; a card sits at 60 to 92%, a bleed a little past the edge`,\n fixHint:\n 'the template layout places the slot; fix its place for this aspect',\n bbox: rect,\n })\n }\n for (const f of textFindings(a, img)) out.push(f)\n return out\n }\n\n const subject = m.card ?? { x: 0, y: 0, w: img.w, h: img.h }\n if (m.ink < BLANK_INK) {\n out.push({\n code: 'blank',\n severity: 'error',\n asset: a.destination,\n message: `${pct(m.ink)} ink inside the ${m.card ? 'card' : 'frame'}: a wallpaper, an empty canvas or a flat panel, not the product doing something`,\n fixHint:\n 'pick a moment after a gesture landed (--times step:<id>) and stage the set before recording: real data, a populated state',\n bbox: subject,\n })\n }\n\n if (genre === 'card') {\n if (bledAll || m.widthPct === null) {\n out.push({\n code: 'subject',\n severity: 'error',\n asset: a.destination,\n message: bledAll\n ? 'the picture fills the frame on all four sides: a crop, not a card on a ground'\n : 'no card found: the frame is one flat tone',\n fixHint:\n 'present the card in a look (vos deliver reads BRAND.md or --look) or render this destination from a poster template',\n })\n } else if (m.widthPct < SUBJECT_BAND.min || m.widthPct > SUBJECT_BAND.max) {\n out.push({\n code: 'subject',\n severity: 'error',\n asset: a.destination,\n message: `the card is ${pct(m.widthPct)} of the width; the references sit at ${pct(SUBJECT_BAND.min)} to ${pct(SUBJECT_BAND.max)}`,\n fixHint:\n 'the look places the card at 84% (frame.inset); a poster template sets its own placement',\n bbox: m.card ?? undefined,\n })\n }\n if (m.card && !bledAll) {\n const sep = m.separation ?? 0\n const shadow = m.shadow ?? 0\n if (\n sep < SEPARATION_L &&\n shadow < SHADOW_PRESENT &&\n m.edge < EDGE_PRESENT\n ) {\n out.push({\n code: 'separation',\n severity: 'error',\n asset: a.destination,\n message: `the card and the ground are ${sep.toFixed(1)} L* apart with no shadow halo (${shadow.toFixed(1)}) and no drawn edge (${m.edge.toFixed(0)}): the card dissolves into the plate`,\n fixHint:\n 'a contact shadow (frame.shadowContact) plus a hairline (frame.border with borderColor) makes a light card sit on a light ground; the plate look sets both',\n bbox: m.card,\n })\n }\n }\n }\n\n // A page whose own margins are flat reads its content block as the\n // \"card\", and a page's tiles cast halos of their own, so the picture\n // alone cannot prove a screenshot was composed. The manifest can: the\n // deliver verb records `composed` on a screenshot it rendered with the\n // cut's camera and chrome, and that is what this reads.\n if (\n genre === 'screenshot' &&\n a.composed &&\n m.card &&\n (m.widthPct ?? 0) < 0.98\n ) {\n out.push({\n code: 'subject',\n severity: 'error',\n asset: a.destination,\n message: `a store screenshot must be the real page full bleed; this one shows a ${pct(m.widthPct ?? 0)} card on a ground`,\n fixHint:\n 'drop --composed: the screenshot genre renders the page with no chrome and no padding',\n bbox: m.card,\n })\n }\n\n if (img.w <= 500 && (a.spec?.text === 'none' || genre === 'card')) {\n const full = edgeEnergy(img, Math.min(img.w, 400))\n const half = edgeEnergy(img, Math.min(img.w, 400) >> 1)\n const keep = full > 0 ? half / full : 1\n if (keep < HALFSIZE_KEEP) {\n out.push({\n code: 'halfsize',\n severity: 'warning',\n asset: a.destination,\n message: `at half size the tile keeps ${pct(keep)} of its edges: fine text and thin lines vanish where the store shows it small`,\n fixHint:\n 'a tile is the subject large and saturated with no text (the store rule); render it from the card-on-gradient template',\n })\n }\n }\n\n for (const f of textFindings(a, img)) out.push(f)\n return out\n}\n\n/** The word checks: sliced, safe, contrast, and words where none are wanted. */\nfunction textFindings(a: PictureAsset, img: Rgba): PictureFinding[] {\n const out: PictureFinding[] = []\n for (const t of a.text ?? []) {\n const box: Rect = {\n x: t.x * img.w,\n y: t.y * img.h,\n w: t.w * img.w,\n h: t.h * img.h,\n }\n const name = t.label ? `\"${t.label}\"` : 'a text box'\n if (\n box.x < 0 ||\n box.y < 0 ||\n box.x + box.w > img.w + 0.5 ||\n box.y + box.h > img.h + 0.5\n ) {\n out.push({\n code: 'sliced',\n severity: 'error',\n asset: a.destination,\n message: `${name} crosses the frame edge: cut mid-word`,\n fixHint:\n 'shorten the line, or let the template recompose (headline lines at 12 to 14% of the height, inside the safe rect)',\n bbox: box,\n })\n }\n const s = a.spec?.safe\n if (s) {\n const sx = s.x * img.w\n const sy = s.y * img.h\n const sw = s.w * img.w\n const sh = s.h * img.h\n if (\n box.x < sx - 0.5 ||\n box.y < sy - 0.5 ||\n box.x + box.w > sx + sw + 0.5 ||\n box.y + box.h > sy + sh + 0.5\n ) {\n out.push({\n code: 'safe',\n severity: 'warning',\n asset: a.destination,\n message: `${name} sits outside the destination's safe rect (${pct(s.w)}x${pct(s.h)} at ${pct(s.x)},${pct(s.y)}): the platform's chrome or crop covers it`,\n fixHint:\n 'move the text inside the safe rect; the template reads channel-specs safe',\n bbox: box,\n })\n }\n }\n const rgb = t.color ? hexToRgb(t.color) : null\n if (rgb) {\n const ground = medianColour(img, box)\n const lc = apcaContrast(rgb, ground)\n const floor = t.role === 'body' ? 75 : 60\n if (lc < floor) {\n out.push({\n code: 'contrast',\n severity: 'warning',\n asset: a.destination,\n message: `${name} reads APCA Lc ${lc.toFixed(0)} on its ground; ${t.role === 'body' ? 'body' : 'a headline'} wants ${floor}`,\n fixHint:\n 'darken the ink or lighten the ground under the text (BRAND.md ink on bgA/bgB, never on the shot)',\n bbox: box,\n })\n }\n }\n }\n if (a.spec?.text === 'none' && (a.text?.length ?? 0) > 0) {\n out.push({\n code: 'safe',\n severity: 'warning',\n asset: a.destination,\n message:\n 'this destination wants no text (the picture carries it alone) and the kit put words on it',\n fixHint:\n 'render the tile from the card-on-gradient template with no headline',\n })\n }\n return out\n}\n\n/**\n * Duplicate groups across a kit's stills, by difference hash of the\n * subject. Cards are compared with cards (eight covers of one frame is\n * the failure); a screenshot set is compared within its own destination\n * only, because two store galleries of one story legitimately share\n * frames. Two cards on one frame is a warning (X and LinkedIn often take\n * one image); three or more is an error.\n */\nexport function duplicateFindings(\n stills: {\n destination: string\n hash: string\n time: number | null\n genre?: 'screenshot' | 'card'\n /** A poster or stage card: a composition, not a crop. */\n composed?: boolean\n }[],\n): PictureFinding[] {\n const groups: { destination: string; time: number | null }[][] = []\n const seen = new Set<number>()\n const comparable = (\n a: (typeof stills)[number],\n b: (typeof stills)[number],\n ) =>\n a.genre === 'screenshot' || b.genre === 'screenshot'\n ? a.destination === b.destination\n : true\n for (let i = 0; i < stills.length; i++) {\n if (seen.has(i)) continue\n const g = [stills[i]]\n for (let j = i + 1; j < stills.length; j++) {\n if (seen.has(j)) continue\n if (!comparable(stills[i], stills[j])) continue\n if (hammingDistance(stills[i].hash, stills[j].hash) <= DUPLICATE_BITS) {\n g.push(stills[j])\n seen.add(j)\n }\n }\n if (g.length > 1) groups.push(g)\n }\n return groups.map((g) => {\n // Every member composed: one cover on several channels, which a release\n // does on purpose; the failure this check exists for is the CROP of one\n // frame at eight aspects.\n const composed = g.every(\n (s) => stills.find((x) => x.destination === s.destination)?.composed,\n )\n return {\n code: 'duplicate' as const,\n severity: composed\n ? ('info' as const)\n : g.length >= 3\n ? ('error' as const)\n : ('warning' as const),\n asset: g.map((s) => s.destination).join(', '),\n message: composed\n ? `${g.length} channels share one cover: ${g.map((s) => s.destination).join(', ')}`\n : `${g.length} assets share one frame${g[0].time !== null ? ` (${g[0].time.toFixed(2)}s)` : ''}: ${g.map((s) => s.destination).join(', ')}`,\n fixHint:\n 'a kit is many moments: let deliver pick from the step timeline, or pass --times with one step per still; a poster document per class (poster/<class>/doc.json) or per destination (LAUNCH.md poster roles) gives each channel its own cover',\n }\n })\n}\n\n/** One frame of a video through ffmpeg, as decoded pixels; null when unavailable. */\nasync function videoFrame(\n file: string,\n at: number,\n ffmpeg: string,\n): Promise<Rgba | null> {\n try {\n const { stdout } = await execFileP(\n ffmpeg,\n [\n '-v',\n 'error',\n '-ss',\n at.toFixed(3),\n '-i',\n file,\n '-frames:v',\n '1',\n '-f',\n 'image2pipe',\n '-vcodec',\n 'png',\n '-',\n ],\n { encoding: 'buffer', maxBuffer: 64 * 1024 * 1024 },\n )\n return decodePng(new Uint8Array(stdout))\n } catch {\n return null\n }\n}\n\n/** Is a binary on PATH? */\nasync function onPath(bin: string): Promise<boolean> {\n try {\n await execFileP(bin, ['-version'])\n return true\n } catch {\n return false\n }\n}\n\n/**\n * Run the picture checks over a kit's assets. Stills decode from their\n * PNGs; videos read their first and last frame through ffmpeg. Returns the\n * findings and, per asset, what was measured.\n */\nexport async function pictureChecks(assets: PictureAsset[]): Promise<{\n findings: PictureFinding[]\n measured: { destination: string; measure: StillMeasure | null }[]\n}> {\n const findings: PictureFinding[] = []\n const measured: { destination: string; measure: StillMeasure | null }[] = []\n const stills: {\n destination: string\n hash: string\n time: number | null\n genre?: 'screenshot' | 'card'\n composed?: boolean\n }[] = []\n let ffmpeg: boolean | null = null\n\n for (const a of assets) {\n if (/\\.png$/i.test(a.file)) {\n const img = decodePng(new Uint8Array(await readFile(a.file)))\n if (!img) {\n findings.push({\n code: 'unreadable',\n severity: 'info',\n asset: a.destination,\n message: `${a.path} is not an 8-bit non-interlaced PNG; the picture checks cannot read it`,\n fixHint:\n 'render stills through vos deliver or vos frames, which write readable PNGs',\n })\n measured.push({ destination: a.destination, measure: null })\n continue\n }\n const m = measureStill(img)\n measured.push({ destination: a.destination, measure: m })\n findings.push(...stillFindings(a, img, m))\n if (a.spec?.kind !== 'video')\n stills.push({\n destination: a.destination,\n hash: m.hash,\n time: null,\n genre: a.spec?.genre,\n composed: !!a.shot,\n })\n continue\n }\n if (/\\.(mp4|webm|mov)$/i.test(a.file)) {\n if (ffmpeg === null) ffmpeg = await onPath('ffmpeg')\n if (!ffmpeg) {\n findings.push({\n code: 'firstlast',\n severity: 'info',\n asset: a.destination,\n message:\n 'ffmpeg is not on PATH, so the first and last frames were not read',\n fixHint: 'install ffmpeg to have the video checks run',\n })\n measured.push({ destination: a.destination, measure: null })\n continue\n }\n const seconds = a.seconds ?? 0\n const first = await videoFrame(a.file, 0, 'ffmpeg')\n const last = await videoFrame(\n a.file,\n Math.max(0, seconds - 0.1),\n 'ffmpeg',\n )\n for (const [name, img] of [\n ['first', first],\n ['last', last],\n ] as const) {\n if (!img) continue\n const m = measureStill(img)\n if (name === 'first')\n measured.push({ destination: a.destination, measure: m })\n const subject = m.card ?? { x: 0, y: 0, w: img.w, h: img.h }\n const ink = inkCoverage(img, subject)\n if (ink < BLANK_INK) {\n findings.push({\n code: 'firstlast',\n severity: 'error',\n asset: a.destination,\n message: `the ${name} frame is ${pct(ink)} ink: a ${name === 'first' ? 'cold open on nothing' : 'clip that ends on nothing'}`,\n fixHint:\n name === 'first'\n ? 'open on the product (trim the head, or an entrance over a populated frame)'\n : 'end on a resolved state or an end card (the last frame is the poster)',\n })\n }\n if (m.bleed.length === 4 && a.spec?.genre !== 'screenshot') {\n findings.push({\n code: 'firstlast',\n severity: 'warning',\n asset: a.destination,\n message: `the ${name} frame fills the frame on all four sides: no ground, no room`,\n fixHint:\n 'present the cut in a look (vos deliver reads BRAND.md or --look)',\n })\n }\n }\n continue\n }\n }\n findings.push(...duplicateFindings(stills))\n const order: Record<PictureFinding['severity'], number> = {\n error: 0,\n warning: 1,\n info: 2,\n }\n findings.sort((a, b) => order[a.severity] - order[b.severity])\n return { findings, measured }\n}\n\n/** One line per finding, the way the verb prints them. */\nexport function formatFinding(f: PictureFinding): string {\n const where = f.bbox\n ? ` @ ${Math.round(f.bbox.x)},${Math.round(f.bbox.y)} ${Math.round(f.bbox.w)}x${Math.round(f.bbox.h)}`\n : ''\n return `${f.severity} ${f.code} ${f.asset}${where}: ${f.message}\\n fix: ${f.fixHint}`\n}\n","/**\n * `vos validate <kit.json>` — the kit's own verifier, run AFTER deliver (or\n * after a hand-assembled kit): every asset in the manifest must exist, be\n * what its name says (a `.png` that is really WebP is the classic miss),\n * measure what the manifest claims, and meet its destination's spec (px,\n * bytes, duration, count). Reads dims and durations from the FILES, never\n * from intent, so a manifest that lies is caught the way a still that lies\n * is. Pure over a directory: no browser, no network.\n */\nimport { existsSync } from 'node:fs'\nimport { readFile, stat } from 'node:fs/promises'\nimport { dirname, isAbsolute, join } from 'node:path'\nimport { DESTINATIONS } from '@vosjs/studio-core'\nimport { pictureChecks } from './kitPicture'\nimport type { PictureAsset, PictureFinding, TextBox } from './kitPicture'\nimport type { StillMeasure } from './picture'\nimport type { Destination } from '@vosjs/studio-core'\n\nexport interface KitAssetRecord {\n channel: string\n asset: string\n destination?: string\n path: string\n w: number\n h: number\n bytes: number\n seconds: number | null\n frameTime?: number | null\n source?: string\n /**\n * Where the words are, as fractions of the asset (the poster leg records\n * the element layout it rendered): what the sliced, safe and contrast\n * checks read. Absent on a take frame, whose page text is unknown.\n */\n text?: TextBox[]\n /** A screenshot rendered with the cut's camera and chrome (--composed). */\n composed?: boolean\n /** A poster card's shot placement, fractions of the asset. */\n shot?: { x: number; y: number; w: number; h: number }\n /** A tile: the shot is a close CROP of the page's hero, past the frame by design. */\n crop?: boolean\n /** The poster document a card rendered from: its class, its file, the vos it tracks. */\n poster?: { class: string; file: string; vosId?: string }\n}\n\nexport interface KitRecord {\n release?: string | null\n take?: string\n produced?: string\n skipped?: string[]\n assets: KitAssetRecord[]\n}\n\nexport interface KitVerdict {\n valid: boolean\n problems: string[]\n warnings: string[]\n /**\n * The picture checks (`--picture`): every finding with a code, a\n * severity, a message, a fix hint and a box. An `error` finding fails\n * the verdict beside the spec problems; absent when the pass did not run.\n */\n picture?: PictureFinding[]\n /** Per asset, what the picture pass measured (null = unreadable). */\n pictureMeasured?: { destination: string; measure: StillMeasure | null }[]\n /** Per asset: what the file measured. */\n measured: {\n destination: string\n path: string\n w: number | null\n h: number | null\n bytes: number\n seconds: number | null\n }[]\n}\n\nconst PNG_SIG = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a])\n\n/** PNG dims from the IHDR chunk, or null when the bytes are not a PNG. */\nexport function pngDimensions(bytes: Buffer): { w: number; h: number } | null {\n if (bytes.length < 24 || !bytes.subarray(0, 8).equals(PNG_SIG)) return null\n if (bytes.toString('ascii', 12, 16) !== 'IHDR') return null\n return { w: bytes.readUInt32BE(16), h: bytes.readUInt32BE(20) }\n}\n\n/** What a file's leading bytes say it is, for the \"named .png, is WebP\" miss. */\nexport function sniffImage(bytes: Buffer): 'png' | 'webp' | 'jpeg' | 'unknown' {\n if (bytes.subarray(0, 8).equals(PNG_SIG)) return 'png'\n if (\n bytes.length >= 12 &&\n bytes.toString('ascii', 0, 4) === 'RIFF' &&\n bytes.toString('ascii', 8, 12) === 'WEBP'\n )\n return 'webp'\n if (bytes.length >= 3 && bytes[0] === 0xff && bytes[1] === 0xd8) return 'jpeg'\n return 'unknown'\n}\n\n/**\n * Video dims + duration through mediabunny (the render harness's own\n * demuxer), so a kit's mp4 is measured by the same library that wrote it.\n * Loaded lazily: a stills-only kit never pays for it.\n */\nasync function probeVideo(\n path: string,\n): Promise<{ w: number; h: number; seconds: number } | null> {\n const MB = await import('mediabunny')\n const input = new MB.Input({\n formats: MB.ALL_FORMATS,\n source: new MB.BufferSource(new Uint8Array(await readFile(path))),\n })\n try {\n const track = await input.getPrimaryVideoTrack()\n if (!track) return null\n const seconds = await input.computeDuration()\n return { w: track.displayWidth, h: track.displayHeight, seconds }\n } finally {\n input.dispose()\n }\n}\n\nconst specById = new Map<string, Destination>(\n DESTINATIONS.map((d) => [d.id, d]),\n)\n\nconst near = (a: number, b: number, tol: number) => Math.abs(a - b) <= tol\n\n/**\n * Verify a kit manifest against the files beside it and the channel specs.\n * `kitPath` is the manifest's path; relative asset paths resolve against\n * its directory (the deliver output layout) or against `take`-relative\n * `media/kit/…` paths a hand-assembled PR kit uses.\n */\nexport async function validateKit(\n kitPath: string,\n opts: { picture?: boolean } = {},\n): Promise<KitVerdict> {\n const problems: string[] = []\n const warnings: string[] = []\n const measured: KitVerdict['measured'] = []\n let kit: KitRecord\n try {\n kit = JSON.parse(await readFile(kitPath, 'utf8')) as KitRecord\n } catch (e) {\n return {\n valid: false,\n problems: [`${kitPath}: ${e instanceof Error ? e.message : String(e)}`],\n warnings,\n measured,\n }\n }\n if (!Array.isArray(kit.assets)) {\n return {\n valid: false,\n problems: [`${kitPath}: no assets[] in the manifest`],\n warnings,\n measured,\n }\n }\n const base = dirname(kitPath)\n const resolvePath = (p: string) => {\n // An absolute path from the machine that made the kit (a CI runner) is\n // honoured while it exists; a moved kit resolves beside its manifest.\n if (isAbsolute(p) && existsSync(p)) return p\n // A PR kit records paths as `media/kit/<name>`; the file sits beside the\n // manifest, so the last segment is what resolves.\n const beside = join(base, p.split('/').pop() ?? p)\n return beside\n }\n const perDestination = new Map<string, number>()\n const pictureAssets: PictureAsset[] = []\n\n for (const a of kit.assets) {\n const id = a.destination ?? `${a.channel}-${a.asset}`\n const label = `${a.channel} ${a.asset}`\n const file = resolvePath(a.path)\n let bytes: number\n try {\n bytes = (await stat(file)).size\n } catch {\n problems.push(`${label}: ${a.path} is missing`)\n continue\n }\n perDestination.set(id, (perDestination.get(id) ?? 0) + 1)\n if (bytes !== a.bytes)\n problems.push(\n `${label}: manifest says ${a.bytes} bytes, the file is ${bytes}`,\n )\n const spec = specById.get(id)\n let w: number | null = null\n let h: number | null = null\n let seconds: number | null = null\n if (/\\.(png|jpe?g|webp)$/i.test(file)) {\n const head = Buffer.from(await readFile(file))\n const kind = sniffImage(head)\n if (file.toLowerCase().endsWith('.png') && kind !== 'png')\n problems.push(\n `${label}: ${a.path} is named .png but its bytes are ${kind} — stores refuse a mislabelled image`,\n )\n const dims = kind === 'png' ? pngDimensions(head) : null\n if (dims) {\n w = dims.w\n h = dims.h\n if (w !== a.w || h !== a.h)\n problems.push(\n `${label}: manifest says ${a.w}x${a.h}, the file is ${w}x${h}`,\n )\n } else if (kind === 'png') {\n problems.push(`${label}: ${a.path} has no readable IHDR`)\n }\n } else if (/\\.(mp4|webm|mov)$/i.test(file)) {\n try {\n const v = await probeVideo(file)\n if (!v) problems.push(`${label}: ${a.path} has no video track`)\n else {\n w = v.w\n h = v.h\n seconds = v.seconds\n if (w !== a.w || h !== a.h)\n problems.push(\n `${label}: manifest says ${a.w}x${a.h}, the file is ${w}x${h}`,\n )\n if (a.seconds === null || !near(seconds, a.seconds, 0.25))\n problems.push(\n `${label}: manifest says ${a.seconds ?? 'no'} s, the file is ${seconds.toFixed(2)} s`,\n )\n }\n } catch (e) {\n problems.push(\n `${label}: could not read ${a.path} (${e instanceof Error ? e.message : String(e)})`,\n )\n }\n } else {\n warnings.push(\n `${label}: ${a.path} is not an image or video the kit verifies`,\n )\n }\n measured.push({ destination: id, path: a.path, w, h, bytes, seconds })\n pictureAssets.push({\n destination: id,\n path: a.path,\n file,\n spec,\n text: a.text,\n seconds,\n composed: a.composed,\n shot: a.source === 'poster' || a.source === 'stage' ? a.shot : undefined,\n crop: a.crop,\n })\n\n if (!spec) {\n if (a.channel !== 'demo')\n warnings.push(\n `${label}: no channel spec for \"${id}\" — not verified against one`,\n )\n continue\n }\n if (w !== null && h !== null && (w !== spec.px.w || h !== spec.px.h))\n problems.push(\n `${label}: spec wants ${spec.px.w}x${spec.px.h}, the file is ${w}x${h}`,\n )\n if (spec.maxBytes !== undefined && bytes > spec.maxBytes)\n problems.push(\n `${label}: ${Math.ceil(bytes / 1024)} KB exceeds the ${Math.floor(spec.maxBytes / 1024)} KB ceiling`,\n )\n if (seconds !== null) {\n if (spec.minSeconds !== undefined && seconds < spec.minSeconds - 0.25)\n problems.push(\n `${label}: spec wants at least ${spec.minSeconds} s, the file is ${seconds.toFixed(1)} s`,\n )\n if (spec.maxSeconds !== undefined && seconds > spec.maxSeconds + 0.25)\n problems.push(\n `${label}: spec caps at ${spec.maxSeconds} s, the file is ${seconds.toFixed(1)} s`,\n )\n }\n if (spec.format === 'png' && !file.toLowerCase().endsWith('.png'))\n warnings.push(\n `${label}: spec renders png, the file is ${file.split('.').pop()}`,\n )\n }\n\n for (const [id, n] of perDestination) {\n const spec = specById.get(id)\n if (spec?.count && (n < spec.count.min || n > spec.count.max))\n problems.push(\n `${spec.channel} ${spec.asset}: spec wants ${spec.count.min}-${spec.count.max}, the kit has ${n}`,\n )\n }\n\n if (!opts.picture) {\n return { valid: problems.length === 0, problems, warnings, measured }\n }\n const picture = await pictureChecks(pictureAssets)\n const pictureErrors = picture.findings.filter((f) => f.severity === 'error')\n return {\n valid: problems.length === 0 && pictureErrors.length === 0,\n problems,\n warnings,\n measured,\n picture: picture.findings,\n pictureMeasured: picture.measured,\n }\n}\n","/**\n * The recorder, as the CLI runs it: the mechanism lives in\n * `@vosjs/render-core/record` (AN4, host-free: a structural driver, a frame\n * sink, no filesystem); this wraps it with a take DIRECTORY, the shell's\n * env for a setup's `{ env }` texts, and this machine's platform, and\n * writes the same four files it always wrote (cursor.json, meta.json,\n * frames.json, actions.json), byte for byte.\n */\nimport { writeFileSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { recordTake as recordTakeCore } from '@vosjs/render-core/record'\nimport type { RecordOpts as CoreRecordOpts } from '@vosjs/render-core/record'\nimport type { Browser, BrowserContext } from 'playwright'\nimport { writeJson } from './take'\nimport type { ActionsFile } from './actions'\nimport type { TakePaths } from './take'\n\nexport type {\n FrameRec,\n FreezeSpan,\n RecordResult,\n SkippedStep,\n} from '@vosjs/render-core/record'\n\nexport type RecordOpts = Omit<\n CoreRecordOpts,\n 'context' | 'env' | 'platform'\n> & {\n /**\n * A ready-made context to record IN, instead of one made from `browser`:\n * `--session <name>`, a persistent profile the person signed in to.\n */\n context?: BrowserContext\n}\n\nexport async function recordTake(\n browser: Browser,\n url: string,\n actions: ActionsFile,\n paths: TakePaths,\n log: (msg: string) => void,\n opts: RecordOpts = {},\n): Promise<import('@vosjs/render-core/record').RecordResult> {\n const dry = opts.dryRun === true\n const result = await recordTakeCore(\n browser,\n url,\n actions,\n {\n frame: (file, bytes) => {\n writeFileSync(join(paths.framesDir, file), bytes)\n },\n },\n log,\n {\n ...opts,\n env: process.env,\n platform:\n process.platform === 'darwin'\n ? 'mac'\n : process.platform === 'win32'\n ? 'windows'\n : 'linux',\n },\n )\n // A rehearsal writes nothing: the take beside it keeps its footage, its\n // cut and its script exactly as they were.\n if (!dry) {\n await writeJson(paths.cursor, result.events)\n await writeJson(paths.meta, result.meta, true)\n await writeJson(paths.framesIndex, result.frames)\n await writeJson(paths.actions, result.actions, true)\n }\n return result\n}\n","/**\n * The wall: the module moved to `@vosjs/render-core/record` (AN4). This\n * file keeps every name the CLI and its tests import.\n */\nexport {\n WALL_PROBE,\n WallError,\n isIdpHost,\n isSignInPath,\n redirectedAway,\n wallVerdict,\n} from '@vosjs/render-core/record'\nexport type { Arrival, WallKind, WallVerdict } from '@vosjs/render-core/record'\n","/**\n * Exposure scanning and masks: the module moved to\n * `@vosjs/render-core/record` (AN4). This file keeps every name the CLI\n * and its tests import.\n */\nexport {\n EXPOSURE_ADVICE,\n EXPOSURE_MATCHERS_SRC,\n EXPOSURE_PROBE,\n ExposureLog,\n exposureLine,\n maskInitScript,\n} from '@vosjs/render-core/record'\nexport type {\n Exposure,\n ExposureKind,\n MaskReport,\n MaskRule,\n} from '@vosjs/render-core/record'\n","/**\n * `setup` steps: the module moved to `@vosjs/render-core/record` (AN4).\n * This file keeps every name the CLI and its tests import. The CLI's\n * recorder hands `process.env` in for a `{ env }` text; the fleet hands the\n * job's own map.\n */\nexport {\n SetupEnvError,\n SetupError,\n parseHeaders,\n resolveSetupText,\n runSetup,\n setupEnvNames,\n validateSetup,\n} from '@vosjs/render-core/record'\nexport type {\n SetupResult,\n SetupStep,\n SetupText,\n} from '@vosjs/render-core/record'\n","/**\n * `vos session`: takeover mode, local. A SESSION is a browser profile the\n * person signed in to once, in a plain Chrome window that no automation\n * touched, and the recorder reuses afterwards. Not `auth` and not `login`:\n * `login` is the vos.so account, and an agent that confuses the two pastes\n * the wrong credential into the wrong place.\n *\n * What was measured before this was written (SI0 b): a profile written by\n * plain Chrome reopens signed in under Playwright ONLY as the SYSTEM Chrome\n * with the real keychain. Playwright's bundled Chromium keeps its own\n * keychain entry and can never decrypt Chrome's cookies, and Playwright\n * adds `--use-mock-keychain` by default. So every reader of a session here\n * launches `channel: 'chrome'` with that switch removed, and nothing else.\n *\n * Rules that bind (the SI doc's §7): a session lives under\n * ~/.config/vos/sessions/<name>, beside the credentials file, never in a\n * take directory and never on vos.so; no verb prints a cookie value, and\n * --json does not either; expiry is said in words.\n */\nimport { spawn } from 'node:child_process'\nimport { existsSync, mkdirSync, readdirSync, rmSync, statSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\nimport { chromium } from 'playwright'\nimport type { BrowserContext } from 'playwright'\n\nexport const SESSIONS_DIR = join(homedir(), '.config', 'vos', 'sessions')\n\nconst NAME = /^[a-z0-9][a-z0-9._-]{0,63}$/i\n\n/** A session's name is a directory name: short, no separators, no dots to walk up. */\nexport function sessionNameVerdict(name: string | undefined): string | null {\n if (!name) return 'a session needs a name: --name <app>'\n if (!NAME.test(name) || name.includes('..'))\n return `\"${name}\" is not a session name: letters, digits, . _ - only, up to 64`\n return null\n}\n\nexport function sessionDir(name: string): string {\n return join(SESSIONS_DIR, name)\n}\n\n/**\n * The system Chrome's executable, the one binary a session is ever opened\n * with. VOS_BROWSER_PATH first, then the install locations Playwright's\n * `channel: 'chrome'` itself resolves to, so `open` and the readers agree.\n */\nexport function systemChromePath(): string {\n const explicit = process.env.VOS_BROWSER_PATH\n if (explicit) return explicit\n const candidates =\n process.platform === 'darwin'\n ? ['/Applications/Google Chrome.app/Contents/MacOS/Google Chrome']\n : process.platform === 'win32'\n ? [\n join(\n process.env['PROGRAMFILES'] ?? 'C:\\\\Program Files',\n 'Google',\n 'Chrome',\n 'Application',\n 'chrome.exe',\n ),\n join(\n process.env['LOCALAPPDATA'] ?? '',\n 'Google',\n 'Chrome',\n 'Application',\n 'chrome.exe',\n ),\n ]\n : [\n '/usr/bin/google-chrome',\n '/usr/bin/google-chrome-stable',\n '/opt/google/chrome/chrome',\n ]\n const found = candidates.find((c) => existsSync(c))\n if (!found)\n throw new Error(\n 'no Google Chrome found: a session needs the system Chrome (the bundled Chromium cannot read a profile Chrome wrote). Install Chrome, or set VOS_BROWSER_PATH',\n )\n return found\n}\n\n/**\n * Open a plain Chrome window on the session's profile and wait for it to\n * EXIT. A child process with no debugging pipe and no automation switch, so\n * a sign-in that refuses automated browsers (Google's) goes through, and\n * the person signs in however the app demands. The cookie store is flushed\n * when Chrome quits, not before: a killed Chrome writes nothing, which is\n * why this waits rather than polls.\n */\nexport async function openSession(\n name: string,\n url: string,\n opts: { log: (line: string) => void } = { log: () => {} },\n): Promise<{ code: number | null }> {\n const dir = sessionDir(name)\n mkdirSync(dir, { recursive: true, mode: 0o700 })\n const exe = systemChromePath()\n const args = [\n `--user-data-dir=${dir}`,\n '--no-first-run',\n '--no-default-browser-check',\n '--window-size=1100,800',\n url,\n ]\n // On a Mac, closing the last window leaves Chrome running, and this waits\n // on the PROCESS: a person who closed the window and reported \"done\" left\n // the command hanging and nothing saved (measured on the first real run).\n const leave =\n process.platform === 'darwin'\n ? 'then quit Chrome with ⌘Q (closing the window alone leaves it running, and this waiting)'\n : 'then close the window'\n opts.log(\n `a Chrome window opened on session \"${name}\": sign in to ${new URL(url).host}, ${leave}`,\n )\n return new Promise((resolve, reject) => {\n const child = spawn(exe, args, { stdio: 'ignore' })\n child.on('error', reject)\n child.on('exit', (code) => resolve({ code }))\n })\n}\n\n/** What a session holds, said in counts and dates. Never a value. */\nexport interface SessionSummary {\n name: string\n origins: { host: string; cookies: number }[]\n /** the newest expiry among persistent cookies, ISO; null when every cookie dies with the window */\n newestExpires: string | null\n /** cookies with no expiry: they die when the window closes, so they cannot be reused */\n sessionOnly: number\n ageDays: number\n}\n\n/**\n * Read a session's cookies THROUGH the browser that can decrypt them\n * (headless system Chrome, real keychain) and summarize. The values pass\n * through memory here and nowhere else.\n */\nexport async function withSession<T>(\n name: string,\n fn: (ctx: BrowserContext) => Promise<T>,\n opts: {\n headless?: boolean\n viewport?: { width: number; height: number }\n } = {},\n): Promise<T> {\n const dir = sessionDir(name)\n if (!existsSync(dir))\n throw new Error(`no session \"${name}\" (vos session list)`)\n const explicit = process.env.VOS_BROWSER_PATH\n const ctx = await chromium.launchPersistentContext(dir, {\n headless: opts.headless ?? true,\n ...(explicit ? { executablePath: explicit } : { channel: 'chrome' }),\n // The real keychain: the whole reason a profile Chrome wrote can be read.\n ignoreDefaultArgs: ['--use-mock-keychain'],\n ...(opts.viewport ? { viewport: opts.viewport, deviceScaleFactor: 1 } : {}),\n })\n try {\n return await fn(ctx)\n } finally {\n await ctx.close().catch(() => {})\n }\n}\n\nexport async function summarizeSession(name: string): Promise<SessionSummary> {\n const dir = sessionDir(name)\n const created = statSync(dir).birthtimeMs || statSync(dir).mtimeMs\n return withSession(name, async (ctx) => {\n const cookies = await ctx.cookies()\n const byHost = new Map<string, number>()\n let newest = 0\n let sessionOnly = 0\n for (const c of cookies) {\n const host = c.domain.replace(/^\\./, '')\n byHost.set(host, (byHost.get(host) ?? 0) + 1)\n if (c.expires && c.expires > 0) newest = Math.max(newest, c.expires)\n else sessionOnly++\n }\n return {\n name,\n origins: [...byHost.entries()]\n .map(([host, n]) => ({ host, cookies: n }))\n .sort((a, b) => b.cookies - a.cookies),\n newestExpires: newest ? new Date(newest * 1000).toISOString() : null,\n sessionOnly,\n ageDays: Math.floor((Date.now() - created) / 86400000),\n }\n })\n}\n\nexport function summaryLine(s: SessionSummary): string {\n if (!s.origins.length)\n return `session \"${s.name}\" holds no cookies: the window closed before a sign-in landed, or the sign-in never happened`\n const hosts = s.origins\n .slice(0, 4)\n .map((o) => `${o.host} (${o.cookies})`)\n .join(', ')\n const more = s.origins.length > 4 ? ` and ${s.origins.length - 4} more` : ''\n const exp = s.newestExpires\n ? `newest expires in ${Math.max(0, Math.round((new Date(s.newestExpires).getTime() - Date.now()) / 86400000))} days`\n : 'every cookie dies with the window (the app set no expiry), so this session cannot be reused'\n return `session \"${s.name}\" holds cookies for ${hosts}${more}; ${exp}`\n}\n\nexport function listSessions(): { name: string; ageDays: number }[] {\n if (!existsSync(SESSIONS_DIR)) return []\n return readdirSync(SESSIONS_DIR, { withFileTypes: true })\n .filter((d) => d.isDirectory() && NAME.test(d.name))\n .map((d) => {\n const st = statSync(join(SESSIONS_DIR, d.name))\n return {\n name: d.name,\n ageDays: Math.floor(\n (Date.now() - (st.birthtimeMs || st.mtimeMs)) / 86400000,\n ),\n }\n })\n .sort((a, b) => a.name.localeCompare(b.name))\n}\n\nexport function removeSession(name: string): boolean {\n const dir = sessionDir(name)\n if (!existsSync(dir)) return false\n rmSync(dir, { recursive: true, force: true })\n return true\n}\n\n/**\n * Is this JSON a Playwright storage state? The push guard's test: a take\n * directory holding one would upload live credentials with the take.\n */\nexport function looksLikeStorageState(value: unknown): boolean {\n if (typeof value !== 'object' || value === null) return false\n const v = value as { cookies?: unknown; origins?: unknown }\n return Array.isArray(v.cookies) && Array.isArray(v.origins)\n}\n","/**\n * The hosted recording cap as `vos record` applies it: the default for\n * `--max-duration`. A CLI take that runs past it is stopped at the cap so\n * what lands is what vos.so hosts.\n *\n * The number's home is the platform's plan table, served public at\n * `GET /api/limits`; `hostedRecordingCap` reads it before a take (with the\n * caller's key when one resolves, so a plan with a longer cap gets it).\n * The constant below is the offline fallback, stated here because this is\n * the platform client. `--max-duration` overrides either for a take that\n * never leaves the machine.\n *\n * How the recorder APPLIES a cap (reached, clamp, the words) is mechanism\n * and lives in `@vosjs/render-core/record` (AN4); re-exported here.\n */\nexport {\n capReached,\n cappedLine,\n clampWait,\n formatDurationCap,\n} from '@vosjs/render-core/record'\n\nexport const HOSTED_RECORDING_CAP_SECONDS = 30 * 60\n\n/**\n * The cap in a limits payload, or null when the payload is not one: an\n * integer number of seconds above zero under `limits.recordingMaxSeconds`.\n */\nexport function parseHostedCap(body: unknown): number | null {\n const limits =\n body && typeof body === 'object'\n ? (body as { limits?: { recordingMaxSeconds?: unknown } }).limits\n : undefined\n const cap = limits?.recordingMaxSeconds\n return typeof cap === 'number' && Number.isInteger(cap) && cap > 0\n ? cap\n : null\n}\n\n/**\n * The hosted cap read live from `GET /api/limits`. Bounded and fail-open:\n * null within ~2 s or on any refusal, and the caller uses the constant.\n * A key, when given, asks for the caller's own plan.\n */\nexport async function hostedRecordingCap(\n origin: string,\n key?: string | null,\n fetchImpl: typeof fetch = fetch,\n): Promise<number | null> {\n const ctl = new AbortController()\n const timer = setTimeout(() => ctl.abort(), 2000)\n try {\n const res = await fetchImpl(`${origin.replace(/\\/+$/, '')}/api/limits`, {\n signal: ctl.signal,\n ...(key ? { headers: { authorization: `Bearer ${key}` } } : {}),\n })\n if (!res.ok) return null\n return parseHostedCap(await res.json())\n } catch {\n return null\n } finally {\n clearTimeout(timer)\n }\n}\n\nexport function defaultMaxDurationSeconds(): number {\n return HOSTED_RECORDING_CAP_SECONDS\n}\n","/**\n * Frames → CFR WebM, as the CLI runs it: the page is render-core's\n * (`buildEncodePage`, shared with the fleet); this serves the take\n * directory to it and takes the bytes back through the take server's\n * `/save`, so the recording lands beside the frames it was made from. The\n * page is served FROM the take server, so its fetches are same-origin and\n * relative.\n */\nimport { buildEncodePage } from '@vosjs/render-core/record'\nimport { startTakeServer, waitForPageDone } from './server'\nimport { RECORDING_NAME } from './take'\nimport type { Browser } from 'playwright'\n\nconst ENCODE_HTML = buildEncodePage({\n framesIndexUrl: '/frames.json',\n metaUrl: '/meta.json',\n framesBaseUrl: '/frames/',\n save: { method: 'POST', url: `/save?name=${RECORDING_NAME}` },\n})\n\nexport async function encodeRecording(\n browser: Browser,\n takeDir: string,\n onProgress: (fraction: number) => void,\n): Promise<{ bytes: number }> {\n const server = await startTakeServer(takeDir, { '/encode.html': ENCODE_HTML })\n const page = await browser.newPage()\n try {\n await page.goto(`${server.base}/encode.html`)\n const done = await waitForPageDone(page, 'encode', onProgress, 600_000)\n return { bytes: Number(done.bytes ?? 0) }\n } finally {\n await page.close()\n server.close()\n }\n}\n","/**\n * Plan — build or refresh the take's ProjectDoc (doc.json), the agent-editable\n * surface. Fresh takes run the real studio ingest + auto-zoom planner. Reruns\n * honor the wand contract: `source:'manual'` zoom spans (and every other doc\n * edit) are preserved; only `source:'auto'` spans are regenerated, and new\n * suggestions overlapping a manual span are dropped.\n *\n * Two more things a plan writes, both DATA on the document so the studio\n * shows what the kit will render: a LAYOUT copied from a poster document\n * (`--style` carries the seed's card placement, its stage clips by id, its\n * rest lean and its trailing hold, with the release's words patched into\n * the stage clips), and the cut's MOTION as planner proposals (the card's\n * entrance, the end card, a caption per beat, a music bed and click\n * sounds, from LAUNCH.md's roles). Motion is proposed on a FRESH plan and\n * on `--motion`, never on a refresh: a document that carries a cut is the\n * maker's, and a deleted end card stays deleted.\n */\nimport { existsSync } from 'node:fs'\nimport { readFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport {\n DEFAULT_FRAME_STYLE,\n STYLE_FIELDS,\n copyLayout,\n copyStyle,\n isRejected,\n isStageClip,\n layoutOf,\n planAutoSpeed,\n planAutoZoom,\n projectFromArtifact,\n withBackdrop,\n migrateMotion,\n} from '@vosjs/studio-core'\nimport { loadTake, writeJson } from './take'\nimport { retimeCut } from './reuse'\nimport { proposeMotion } from './motionPlan'\nimport type { MotionProposalInput } from './motionPlan'\nimport type { ReuseReport } from './reuse'\nimport type { ReleaseWords } from './posterValues'\nimport type {\n Backdrop,\n LayoutParts,\n ProjectDoc,\n RecordingArtifact,\n SpeedSpan,\n ZoomSpan,\n} from '@vosjs/studio-core'\n\nexport interface PlanSummary {\n doc: ProjectDoc\n zoomAuto: number\n zoomManual: number\n cursorKept: boolean\n fresh: boolean\n /** The loop the fresh doc opened on when one was handed in (`none` if a reference's frame won without one). */\n backdrop?: string\n /** The style fields copied from `--style`'s reference, when given. */\n styleFrom?: string\n styleFields?: readonly string[]\n /** The layout the reference carried and what the copy left alone. */\n layout?: LayoutParts & { notes: string[] }\n /** The motion proposed onto the document, and what could not be. */\n motion?: { notes: string[]; skipped: string[] }\n /** `--reuse`: what the re-anchor did and what it could not. */\n reuse?: ReuseReport & { from: string }\n}\n\nexport interface PlanOptions {\n /**\n * Style transfer at the data layer: a signed-off take whose\n * zoomStyle/zoomParams/speedParams/tiltStyle/frame/cursor/cam/export are\n * copied onto this take BEFORE the planners run, so the auto spans are\n * proposed under the series' camera. The cut (spans, overlays, audio) is\n * never touched; a field absent on the reference is removed here too.\n * A reference that is a POSTER carries its layout too: the stage clips\n * by id, the rest lean where this take has no spans, the trailing hold.\n */\n style?: { from: string; doc: ProjectDoc }\n /**\n * The re-render loop: a PREVIOUS cut of the same script (a\n * re-record's doc.prev.json) applied to this take's NEW footage. Style\n * fields copy over like --style; the human's camera spans and trims\n * re-time through the step map / explicit anchors; output-anchored work\n * (overlays, audio, objects) carries at its output times; auto spans\n * re-plan on the new cursor. The report NAMES whatever could not follow.\n */\n reuse?: { from: string; doc: ProjectDoc }\n /**\n * The backdrop a FRESH doc opens on (the set's house pick, or what\n * `--background` named), written under a `--style`/`--reuse` reference's\n * frame, which still wins. Null or absent: the bare frame.\n */\n backdrop?: Backdrop | null\n /**\n * The take is FINISHED footage (a render from another tool): a fresh doc\n * opens bare, with no drawn cursor or webcam, at the footage's own rate.\n * `backdrop` is ignored for it.\n */\n footage?: boolean\n /**\n * The release's words, patched into the stage clips a layout carries\n * (`stage-title` ← headline, `stage-kicker` ← kicker, `stage-brand` ←\n * the wordmark) and read by the end card.\n */\n words?: ReleaseWords\n /** The brand's mark (a take-dir key + aspect): the layout's `stage-mark` and the end card's mark. */\n mark?: { key: string; aspect: number } | null\n /**\n * Propose the cut's motion (the card's enter, the templates the recipe\n * names, the end card, captions, bed, clicks) from these roles. Applied\n * on a fresh plan; `again` re-proposes onto an existing document\n * (replacing only the proposals' own ids and `from`s).\n */\n motion?: MotionProposalInput & { again?: boolean }\n /** The frame that stands for the take (output seconds): --still, LAUNCH.md still:. */\n still?: number | null\n}\n\nconst overlaps = (a: ZoomSpan, b: ZoomSpan) => a.in < b.out && b.in < a.out\n\n/** `<take>/digest/digest.json`'s activity bins, when a digest exists. */\nasync function readDigestActivity(\n dir: string,\n): Promise<readonly number[] | null> {\n const file = join(dir, 'digest', 'digest.json')\n if (!existsSync(file)) return null\n try {\n const d = JSON.parse(await readFile(file, 'utf8')) as {\n activity?: unknown\n }\n return Array.isArray(d.activity) &&\n d.activity.every((v) => typeof v === 'number')\n ? d.activity\n : null\n } catch {\n return null\n }\n}\n\n/**\n * The release's words into the stage clips a layout carries: a headline\n * into `stage-title`, a kicker into `stage-kicker`, the wordmark into\n * `stage-brand`. A word that is absent leaves the clip's own words (the\n * exemplar's placeholder, or what the maker typed). In place.\n */\nexport function patchStageWords(doc: ProjectDoc, words: ReleaseWords): void {\n const map: Record<string, string | null | undefined> = {\n 'stage-title': words.headline,\n 'stage-kicker': words.kicker,\n 'stage-brand': words.brand,\n }\n for (const clip of doc.overlays ?? []) {\n if (clip.kind !== 'text' || !isStageClip(clip)) continue\n const v = map[clip.id]\n if (typeof v === 'string' && v.trim()) clip.text = v.trim()\n }\n}\n\n/** `copyStyle` with the layout, the words and the mark applied. */\nfunction applyStyle(\n seed: ProjectDoc,\n doc: ProjectDoc,\n opts: PlanOptions,\n): { doc: ProjectDoc; layout: PlanSummary['layout'] } {\n const parts = layoutOf(seed)\n const carries = parts.clips.length > 0 || parts.lean || parts.freeze\n if (!carries) return { doc: copyStyle(seed, doc), layout: undefined }\n const keys = opts.mark ? { 'stage-mark': opts.mark.key } : undefined\n const { doc: next, notes } = copyLayout(seed, copyStyle(seed, doc), { keys })\n if (opts.words) patchStageWords(next, opts.words)\n return { doc: next, layout: { ...parts, notes } }\n}\n\n/**\n * The planners over the take's OTHER media (concat): each media's own\n * cursor track, in its own capture space, proposes zoom and speed spans\n * stamped with its id; the manual spans and the rejections of that media\n * hold them off exactly as the primary's do.\n */\nfunction planOtherMedia(\n doc: ProjectDoc,\n activity: Awaited<ReturnType<typeof readDigestActivity>>,\n): { zoom: ZoomSpan[]; speed: SpeedSpan[] } {\n const zoom: ZoomSpan[] = []\n const speed: SpeedSpan[] = []\n for (const m of doc.media ?? []) {\n const manualZoom = doc.zoom.filter(\n (z) => z.media === m.id && z.source === 'manual',\n )\n const rejected = (doc.rejected ?? []).filter((r) => r.media === m.id)\n zoom.push(\n ...planAutoZoom(m.cursor, {\n width: m.meta.width,\n height: m.meta.height,\n duration: m.meta.durationMs / 1000,\n style: doc.zoomStyle,\n params: doc.zoomParams,\n })\n .filter((z) => !manualZoom.some((x) => overlaps(z, x)))\n .filter((z) => !isRejected('zoom', z, rejected))\n .map((z) => ({ ...z, id: `${z.id}-${m.id}`, media: m.id })),\n )\n const manualSpeed = (doc.speed ?? []).filter(\n (x) => x.media === m.id && x.source !== 'auto',\n )\n speed.push(\n ...planAutoSpeed(m.cursor, {\n durationMs: m.meta.durationMs,\n params: doc.speedParams,\n activity,\n })\n .filter((x) => !manualSpeed.some((y) => x.in < y.out && x.out > y.in))\n .filter((x) => !isRejected('speed', x, rejected))\n .map((x) => ({ ...x, id: `${x.id}-${m.id}`, media: m.id })),\n )\n }\n return { zoom, speed }\n}\n\nexport async function planTake(\n dir: string,\n opts: PlanOptions = {},\n): Promise<PlanSummary> {\n const take = await loadTake(dir)\n const { meta, cursor } = take\n // A digest's activity bins, when one exists: the speed planner then tells\n // playback from idle (the studio's ingest has no such witness).\n const activity = await readDigestActivity(dir)\n // The frame a fresh doc opens on: the house backdrop on the bare frame\n // when one was handed in. The ingest still derives the browser bar from\n // the footage on top of it.\n const ingest = opts.footage\n ? { footage: true }\n : opts.backdrop\n ? { frame: withBackdrop(DEFAULT_FRAME_STYLE, opts.backdrop) }\n : {}\n\n let doc: ProjectDoc\n let fresh: boolean\n let layout: PlanSummary['layout']\n if (opts.reuse) {\n // The re-render loop: fresh ingest of the NEW footage, the\n // previous cut's style + human work re-timed onto it, autos re-planned.\n // The previous cut in the one vocabulary (a legacy end card becomes\n // clips and a card exit, which ride along like the other overlays).\n const prev = migrateMotion(opts.reuse.doc)\n const artifact: RecordingArtifact = {\n videoKey: take.paths.recordingName,\n cursor,\n meta,\n }\n doc = projectFromArtifact(artifact, take.paths.recordingName, ingest).doc\n doc = copyStyle(prev, doc)\n const rt = retimeCut(prev, meta.steps ?? [], meta.durationMs)\n doc.segments = rt.segments\n // The previous cut's freezes survive the re-record, re-timed onto the\n // new footage (the trailing one is the poster's still).\n if (rt.freeze.length) doc.freeze = rt.freeze\n // The previous cut's deletions come along too: a proposal the human\n // rejected stays rejected on the new footage.\n if (rt.rejected.length) doc.rejected = rt.rejected\n const manualZoom = rt.zoom\n const autoZoom = planAutoZoom(doc.source.cursor, {\n width: doc.source.meta.width,\n height: doc.source.meta.height,\n duration: doc.source.meta.durationMs / 1000,\n style: doc.zoomStyle,\n params: doc.zoomParams,\n })\n .filter((z) => !manualZoom.some((m) => overlaps(z, m)))\n .filter((z) => !isRejected('zoom', z, doc.rejected))\n doc.zoom = [...manualZoom, ...autoZoom].sort((a, b) => a.in - b.in)\n const manualSpeed = rt.speed\n const autoSpeed = planAutoSpeed(doc.source.cursor, {\n durationMs: doc.source.meta.durationMs,\n params: doc.speedParams,\n activity,\n })\n .filter((s) => !manualSpeed.some((m) => s.in < m.out && s.out > m.in))\n .filter((s) => !isRejected('speed', s, doc.rejected))\n doc.speed = [...manualSpeed, ...autoSpeed].sort((a, b) => a.in - b.in)\n {\n const others = planOtherMedia(doc, activity)\n doc.zoom = [\n ...doc.zoom.filter((z) => !z.media || z.source === 'manual'),\n ...others.zoom,\n ].sort((a, b) => a.in - b.in)\n doc.speed = [\n ...(doc.speed ?? []).filter((x) => !x.media || x.source !== 'auto'),\n ...others.speed,\n ].sort((a, b) => a.in - b.in)\n }\n if (rt.tilt.length) doc.tilt = rt.tilt\n // Output-anchored work carries at its output times — a title at 1s is\n // still a title at 1s (the constant-perceived-position contract).\n if (prev.overlays?.length) doc.overlays = prev.overlays\n if (prev.objects?.length) doc.objects = prev.objects\n if (prev.audio.length) doc.audio = prev.audio\n if (prev.camMotion?.length) doc.camMotion = prev.camMotion\n // The frame that stands for the take is an output moment too, and the\n // author's choice: it carries as it is.\n if (prev.still !== undefined) doc.still = prev.still\n if (opts.still != null) doc.still = opts.still\n await writeJson(take.paths.doc, doc, true)\n return {\n doc,\n zoomAuto: doc.zoom.filter((z) => z.source !== 'manual').length,\n zoomManual: doc.zoom.filter((z) => z.source === 'manual').length,\n cursorKept: doc.source.cursor.length > 0,\n fresh: false,\n reuse: { ...rt.report, from: opts.reuse.from },\n }\n }\n if (take.doc) {\n if (opts.style) {\n const applied = applyStyle(opts.style.doc, take.doc, opts)\n doc = applied.doc\n layout = applied.layout\n } else {\n doc = take.doc\n }\n fresh = false\n const manual = doc.zoom.filter((z) => z.source === 'manual' && !z.media)\n const auto = planAutoZoom(doc.source.cursor, {\n width: doc.source.meta.width,\n height: doc.source.meta.height,\n duration: doc.source.meta.durationMs / 1000,\n style: doc.zoomStyle,\n params: doc.zoomParams,\n })\n .filter((z) => !manual.some((m) => overlaps(z, m)))\n .filter((z) => !isRejected('zoom', z, doc.rejected))\n doc.zoom = [...manual, ...auto].sort((a, b) => a.in - b.in)\n // The speed wand: absent `source` counts as manual — spans from before\n // the wand are user work and always survive a re-plan.\n const manualSpeed = (doc.speed ?? []).filter(\n (s) => s.source !== 'auto' && !s.media,\n )\n const autoSpeed = planAutoSpeed(doc.source.cursor, {\n durationMs: doc.source.meta.durationMs,\n params: doc.speedParams,\n activity,\n })\n .filter((s) => !manualSpeed.some((m) => s.in < m.out && s.out > m.in))\n .filter((s) => !isRejected('speed', s, doc.rejected))\n doc.speed = [...manualSpeed, ...autoSpeed].sort((a, b) => a.in - b.in)\n {\n const others = planOtherMedia(doc, activity)\n doc.zoom = [\n ...doc.zoom.filter((z) => !z.media || z.source === 'manual'),\n ...others.zoom,\n ].sort((a, b) => a.in - b.in)\n doc.speed = [\n ...(doc.speed ?? []).filter((x) => !x.media || x.source !== 'auto'),\n ...others.speed,\n ].sort((a, b) => a.in - b.in)\n }\n } else {\n const artifact: RecordingArtifact = {\n videoKey: take.paths.recordingName,\n cursor,\n meta,\n }\n doc = projectFromArtifact(artifact, take.paths.recordingName, ingest).doc\n if (opts.style) {\n const applied = applyStyle(opts.style.doc, doc, opts)\n doc = applied.doc\n layout = applied.layout\n }\n doc.zoom = planAutoZoom(doc.source.cursor, {\n width: doc.source.meta.width,\n height: doc.source.meta.height,\n duration: doc.source.meta.durationMs / 1000,\n style: doc.zoomStyle,\n params: doc.zoomParams,\n })\n doc.speed = planAutoSpeed(doc.source.cursor, {\n durationMs: doc.source.meta.durationMs,\n params: doc.speedParams,\n activity,\n })\n fresh = true\n }\n\n // The motion proposals ride a fresh document, or an explicit re-ask.\n let motion: PlanSummary['motion']\n if (opts.motion && (fresh || opts.motion.again)) {\n const proposed = proposeMotion(doc, opts.motion)\n doc = proposed.doc\n motion = { notes: proposed.notes, skipped: proposed.skipped }\n }\n\n // The frame that stands for the take: named, never proposed. A plan\n // never moves a still the author set.\n if (opts.still != null) doc.still = opts.still\n await writeJson(take.paths.doc, doc, true)\n return {\n doc,\n zoomAuto: doc.zoom.filter((z) => z.source !== 'manual').length,\n zoomManual: doc.zoom.filter((z) => z.source === 'manual').length,\n cursorKept: doc.source.cursor.length > 0,\n fresh,\n ...(opts.backdrop\n ? { backdrop: doc.frame.backgroundMedia?.key ?? 'none' }\n : {}),\n ...(opts.style\n ? {\n styleFrom: opts.style.from,\n styleFields: STYLE_FIELDS.filter(\n (k) => opts.style!.doc[k] !== undefined,\n ),\n }\n : {}),\n ...(layout ? { layout } : {}),\n ...(motion ? { motion } : {}),\n }\n}\n","/**\n * Reuse: re-time a previous cut onto a NEW recording of the same\n * script. The recorder's `meta.steps` say when each actions.json step ran\n * in BOTH takes, so the old timeline maps onto the new one piecewise —\n * matched step edges are the control points, and any source time in\n * between interpolates. Explicit `anchor`s on camera spans resolve\n * directly against the new steps and win over the map.\n *\n * Report, never guess: every span that\n * could not re-anchor cleanly is NAMED in `flagged` with the reason in\n * words — a vanished step, a skipped selector, a span clamped or dropped\n * at the new take's edge. The agent fixes actions.json and re-runs; the\n * verb never silently invents a cut.\n *\n * Pure functions, no I/O — reuse.test.ts drives them with synthetic\n * step timelines; the browser gate is smoke-recut.ts.\n */\nimport { docFreezes } from '@vosjs/studio-core'\nimport type {\n FreezeSpan,\n ProjectDoc,\n RejectedSpan,\n SpeedSpan,\n StepAnchor,\n StepSpan,\n TiltSpan,\n ZoomSpan,\n} from '@vosjs/studio-core'\n\n/** Minimum surviving span length (seconds) — anything shorter drops. */\nconst MIN_SPAN = 0.15\n\nexport interface StepMap {\n /** old SOURCE seconds → new SOURCE seconds (piecewise linear, clamped). */\n map: (t: number) => number\n /** old steps with no usable match in the new recording. */\n unmatched: StepSpan[]\n matched: number\n}\n\n/**\n * Match an old step to a new one: by `id` when both carry one; else the\n * same index when the verb + selector still agree there; else a UNIQUE\n * (do, selector) match anywhere. A new step that was skipped (selector\n * never appeared) is no match — its gesture did not happen.\n */\nfunction matchStep(old: StepSpan, newSteps: StepSpan[]): StepSpan | null {\n const usable = (s: StepSpan | undefined): s is StepSpan =>\n !!s && s.skipped !== true\n if (old.id) {\n const byId = newSteps.find((s) => s.id === old.id)\n return usable(byId) ? byId : null\n }\n const atIndex = newSteps.find((s) => s.step === old.step)\n if (\n usable(atIndex) &&\n atIndex.do === old.do &&\n atIndex.selector === old.selector\n ) {\n return atIndex\n }\n const bySignature = newSteps.filter(\n (s) => s.do === old.do && s.selector === old.selector && !s.skipped,\n )\n return old.selector !== undefined && bySignature.length === 1\n ? bySignature[0]\n : usable(atIndex) && old.selector === undefined && atIndex.do === old.do\n ? atIndex\n : null\n}\n\nexport function buildStepMap(\n oldSteps: StepSpan[],\n newSteps: StepSpan[],\n oldDuration: number,\n newDuration: number,\n): StepMap {\n const points: { from: number; to: number }[] = [\n { from: 0, to: 0 },\n { from: oldDuration, to: newDuration },\n ]\n const unmatched: StepSpan[] = []\n let matched = 0\n for (const old of oldSteps) {\n if (old.skipped) continue // never ran in the old take; nothing anchored to it\n const hit = matchStep(old, newSteps)\n if (!hit) {\n unmatched.push(old)\n continue\n }\n matched++\n points.push({ from: old.tStart, to: hit.tStart })\n points.push({ from: old.tEnd, to: hit.tEnd })\n }\n // Sort and keep the mapping monotonic: a control point that would send\n // time backwards (steps reordered between takes) is dropped — the\n // interpolation through its neighbours is the honest fallback.\n points.sort((a, b) => a.from - b.from || a.to - b.to)\n const clean: { from: number; to: number }[] = []\n for (const p of points) {\n const last = clean.at(-1)\n if (!last) {\n clean.push(p)\n continue\n }\n if (p.from <= last.from + 1e-9) continue\n if (p.to < last.to) continue\n clean.push(p)\n }\n const map = (t: number): number => {\n const x = Math.max(0, Math.min(t, oldDuration))\n let i = 1\n while (i < clean.length - 1 && clean[i].from < x) i++\n const a = clean[i - 1] ?? clean[0]\n const b = clean[i] ?? a\n const span = b.from - a.from\n const u = span > 1e-9 ? (x - a.from) / span : 0\n return Math.max(0, Math.min(a.to + (b.to - a.to) * u, newDuration))\n }\n return { map, unmatched, matched }\n}\n\n/** Resolve an explicit anchor against the NEW steps; null when it cannot. */\nexport function resolveAnchor(\n anchor: StepAnchor,\n newSteps: StepSpan[],\n): number | null {\n const step =\n typeof anchor.step === 'string'\n ? newSteps.find((s) => s.id === anchor.step)\n : newSteps.find((s) => s.step === anchor.step)\n if (!step || step.skipped) return null\n const base = anchor.at === 'end' ? step.tEnd : step.tStart\n return base + (anchor.offset ?? 0)\n}\n\ninterface SourceSpan {\n id: string\n in: number\n out: number\n anchor?: StepAnchor\n}\n\nexport interface ReuseReport {\n /** spans re-timed through an explicit anchor. */\n anchored: number\n /** spans re-timed through the step map (approximate by nature). */\n mapped: number\n /** everything that needs a human/agent look, in words. */\n flagged: string[]\n}\n\nfunction retimeSpans<T extends SourceSpan>(\n kind: string,\n spans: T[],\n stepMap: StepMap,\n newSteps: StepSpan[],\n newDuration: number,\n report: ReuseReport,\n): T[] {\n const out: T[] = []\n for (const span of spans) {\n const length = span.out - span.in\n let nextIn: number | null = null\n if (span.anchor) {\n nextIn = resolveAnchor(span.anchor, newSteps)\n if (nextIn === null) {\n report.flagged.push(\n `${kind} ${span.id}: its anchored step (${String(span.anchor.step)}) is missing or skipped in the new recording — fell back to the step map`,\n )\n } else {\n report.anchored++\n }\n }\n if (nextIn === null) {\n nextIn = stepMap.map(span.in)\n report.mapped++\n }\n const nextOut = Math.min(nextIn + length, newDuration)\n const clampedIn = Math.max(0, Math.min(nextIn, newDuration))\n if (nextOut - clampedIn < MIN_SPAN) {\n report.flagged.push(\n `${kind} ${span.id}: lands outside the new recording (${clampedIn.toFixed(2)}s) — dropped`,\n )\n continue\n }\n out.push({ ...span, in: +clampedIn.toFixed(3), out: +nextOut.toFixed(3) })\n }\n // Source spans must not overlap: sort, then trim a later span's head to\n // its neighbour's tail (a shifted step can squeeze two spans together).\n out.sort((a, b) => a.in - b.in)\n const kept: T[] = []\n for (const span of out) {\n const prev = kept.at(-1)\n if (prev && span.in < prev.out) {\n const trimmed = { ...span, in: +prev.out.toFixed(3) }\n if (trimmed.out - trimmed.in < MIN_SPAN) {\n report.flagged.push(\n `${kind} ${span.id}: fully overlapped ${prev.id} after re-timing — dropped`,\n )\n continue\n }\n report.flagged.push(\n `${kind} ${span.id}: overlapped ${prev.id} after re-timing — trimmed to ${trimmed.in.toFixed(2)}s`,\n )\n kept.push(trimmed)\n continue\n }\n kept.push(span)\n }\n return kept\n}\n\nexport interface ReusedCut {\n segments: { in: number; out: number }[]\n zoom: ZoomSpan[]\n speed: SpeedSpan[]\n /** The previous cut's freezes, re-timed like its manual spans (a legacy hold included). */\n freeze: FreezeSpan[]\n tilt: TiltSpan[]\n /** The previous cut's rejected proposals, re-timed like its manual spans. */\n rejected: RejectedSpan[]\n report: ReuseReport\n}\n\n/**\n * The previous cut's HUMAN work, re-timed onto the new recording. Auto\n * spans are deliberately absent — the planners re-propose them on the new\n * cursor track, exactly as a refresh does. Output-anchored work (overlays,\n * audio, objects) is not retimed here: a title at 1s stays a title at 1s,\n * the constant-perceived-position contract those clips already keep\n * through trims and speed changes.\n */\nexport function retimeCut(\n prev: ProjectDoc,\n newSteps: StepSpan[],\n newDurationMs: number,\n): ReusedCut {\n const report: ReuseReport = { anchored: 0, mapped: 0, flagged: [] }\n const oldSteps = prev.source.meta.steps ?? []\n const oldDuration = prev.source.meta.durationMs / 1000\n const newDuration = newDurationMs / 1000\n const stepMap = buildStepMap(oldSteps, newSteps, oldDuration, newDuration)\n for (const miss of stepMap.unmatched) {\n // An unmatched wait is dead time nothing anchors to — reporting it is\n // noise (the smoke's v1 tail wait \"vanished\" on every reindex).\n if (miss.do === 'wait') continue\n report.flagged.push(\n `step ${miss.id ?? miss.step} (${miss.do}${miss.selector ? ` ${miss.selector}` : ''}) has no match in the new recording — times near it interpolate`,\n )\n }\n\n // Segments: an untrimmed take stays untrimmed at the new length; a real\n // trim re-times edge-wise through the map.\n const untrimmed =\n prev.segments.length === 0 ||\n (prev.segments.length === 1 &&\n prev.segments[0].in <= 0.05 &&\n prev.segments[0].out >= oldDuration - 0.05)\n const segments = untrimmed\n ? [{ in: 0, out: +newDuration.toFixed(3) }]\n : prev.segments\n .map((s) => ({\n in: +stepMap.map(s.in).toFixed(3),\n out: +stepMap.map(s.out).toFixed(3),\n }))\n .filter((s) => s.out - s.in >= MIN_SPAN)\n if (!untrimmed && segments.length < prev.segments.length) {\n report.flagged.push(\n `${prev.segments.length - segments.length} trimmed segment(s) collapsed to nothing in the new recording — dropped`,\n )\n }\n\n const zoom = retimeSpans(\n 'zoom',\n prev.zoom.filter((z) => z.source === 'manual'),\n stepMap,\n newSteps,\n newDuration,\n report,\n )\n // The speed wand's contract: absent source = manual, always kept.\n const speed = retimeSpans(\n 'speed',\n (prev.speed ?? []).filter((s) => s.source !== 'auto'),\n stepMap,\n newSteps,\n newDuration,\n report,\n )\n const tilt = retimeSpans(\n 'tilt',\n (prev.tilt ?? []).filter((t) => t.source !== 'auto'),\n stepMap,\n newSteps,\n newDuration,\n report,\n )\n // A freeze is a source MOMENT: its anchor or the map re-times the\n // moment, its seconds come along untouched, and one that lands past the\n // new recording is dropped and named.\n const freeze: FreezeSpan[] = []\n for (const f of docFreezes(prev)) {\n let at: number | null = null\n if (f.anchor) {\n at = resolveAnchor(f.anchor, newSteps)\n if (at === null) {\n report.flagged.push(\n `freeze ${f.id}: its anchored step (${String(f.anchor.step)}) is missing or skipped in the new recording — fell back to the step map`,\n )\n } else report.anchored++\n }\n if (at === null) {\n at = stepMap.map(f.at)\n report.mapped++\n }\n if (at < 0 || at > newDuration) {\n report.flagged.push(\n `freeze ${f.id}: lands outside the new recording (${at.toFixed(2)}s) — dropped`,\n )\n continue\n }\n freeze.push({ ...f, at: +at.toFixed(3) })\n }\n freeze.sort((a, b) => a.at - b.at)\n // A rejected proposal is a deletion the human made; it follows the\n // footage the way the spans it stands beside do, one lane at a time\n // (two lanes may legitimately reject the same seconds).\n const rejected: RejectedSpan[] = []\n for (const lane of ['zoom', 'tilt', 'speed'] as const) {\n rejected.push(\n ...retimeSpans(\n `rejected ${lane}`,\n (prev.rejected ?? []).filter((r) => r.lane === lane),\n stepMap,\n newSteps,\n newDuration,\n report,\n ),\n )\n }\n\n return { segments, zoom, speed, freeze, tilt, rejected, report }\n}\n","/**\n * Push/pull — the take side of the versioned human↔agent loop.\n *\n * `vos push <take>` uploads the recording (content-addressed: same bytes\n * upload once), lowers doc.json through the real studio pipeline, and\n * creates a hosted vos/version carrying BOTH the compiled program and the\n * doc — always against the base recorded in vos.json, so a stale push\n * 409s with the human's typed changelog instead of clobbering it.\n *\n * `vos pull <take>` fetches what the human changed (the semantic diff per\n * intervening version) and writes the head's doc.json back into the take\n * dir — the local edit loop continues exactly where the human left off.\n *\n * Local-first doctrine: the first push of a take asks (TTY) or\n * requires --yes (headless). vos.json records the consent, the vos id and\n * the base version (legacy push.json still reads); delete it to unlink.\n *\n * All HTTP + credentials + state ride the ONE platform client (platform.ts).\n */\nimport { createHash } from 'node:crypto'\nimport { existsSync, readFileSync, readdirSync } from 'node:fs'\nimport { readFile } from 'node:fs/promises'\nimport { createInterface } from 'node:readline/promises'\nimport { basename, join } from 'node:path'\nimport { lowerToComposition, migrateHostedDoc } from '@vosjs/studio-core'\nimport { RECORDING_NAME, loadTake, takeMediaFile, writeJson } from './take'\nimport { lintDoc } from './validateDoc'\nimport {\n docMediaRefs,\n isTakeRelativeKey,\n pullMedia,\n sourceSidecarRefs,\n uploadDocRefs,\n} from './media'\nimport { MEDIA_HEAD_BYTES, nameForType, resolveMediaType } from './container'\nimport { listFolders, resolveFolder } from './folder'\nimport { uploadAsset } from './uploadAsset'\nimport { looksLikeStorageState } from './session'\nimport {\n apiJson,\n clientId,\n platformOrigin,\n readSyncState,\n requireCredential,\n serverWarnings,\n writeSyncState,\n} from './platform'\nimport type { UploadedAsset } from './uploadAsset'\nimport type { MediaPullResult } from './media'\nimport type { ProjectDoc } from '@vosjs/studio-core'\nimport type { Reporter } from './output'\n\nexport interface ApiContext {\n origin: string\n key: string\n}\n\n/** Auth + origin: flags win, then the documented ladder (platform.ts). */\nexport function apiContext(flags: {\n key?: string\n api?: string\n origin?: string\n}): ApiContext {\n return {\n origin: platformOrigin(flags),\n key: requireCredential(flags.key),\n }\n}\n\nasync function api(\n ctx: ApiContext,\n path: string,\n init?: {\n method?: string\n body?: unknown\n raw?: Uint8Array\n headers?: Record<string, string>\n },\n): Promise<{ status: number; json: Record<string, unknown> }> {\n const r = await apiJson(ctx.origin, `/api${path}`, { ...init, key: ctx.key })\n return { status: r.status, json: r.body }\n}\n\n/**\n * A 400's zod issues, in words an agent can act on (`label: String must\n * contain at most 60 character(s)`). A bare \"Invalid input\" cost a real push\n * a round trip (DF1, 2026-08-25).\n */\nfunction detailLine(body: Record<string, unknown>): string {\n const details = body.details\n if (!Array.isArray(details) || !details.length) return ''\n const lines = (details as Record<string, unknown>[]).map((d) => {\n const path = Array.isArray(d.path) ? d.path.join('.') : ''\n return `${path ? `${path}: ` : ''}${String(d.message ?? JSON.stringify(d))}`\n })\n return `\\n ${lines.join('\\n ')}`\n}\n\n/** Print a /changes payload's summaries — the human's half of the loop. */\nfunction printChanges(\n r: Reporter,\n changes: unknown,\n protectedIds: unknown,\n): void {\n if (Array.isArray(changes)) {\n for (const entry of changes as Record<string, unknown>[]) {\n const who = entry.origin === 'studio' ? 'human' : String(entry.origin)\n r.log(` v${entry.versionNumber} (${who}): ${entry.summary}`)\n if (entry.note) r.log(` note: ${String(entry.note)}`)\n r.event({ event: 'change', ...entry })\n }\n }\n if (Array.isArray(protectedIds) && protectedIds.length) {\n r.log(\n ` protected (human-touched, keep their values): ${(protectedIds as string[]).join(', ')}`,\n )\n r.event({ event: 'protected', nodes: protectedIds })\n }\n}\n\n/**\n * Why a take push must not start, or null. Asked BEFORE any upload: a push\n * is not something to report on afterwards.\n *\n * `--vos <id>` on a directory with no `vos.json` is ADOPTION, not a refusal\n * (see `pushTake`): the only other way to tie a directory to a vos is\n * `vos pull`, which writes the hosted doc over the local one, and the take\n * that needs `--vos` is exactly the one re-recorded from scratch.\n */\nexport function takePushRefusal(ask: {\n /** `--vos`, when given. */\n vos?: string\n /** The vos this directory tracks (vos.json), or null. */\n trackedVosId: string | null\n /** Flags given that only a PROGRAM push reads. */\n programOnly: string[]\n}): string | null {\n if (ask.programOnly.length) {\n const list = ask.programOnly.map((f) => `--${f}`).join(', ')\n return `${list} ${ask.programOnly.length > 1 ? 'belong' : 'belongs'} to a PROGRAM push (a config.json); a take push reads --vos, --title, --label, --note, --folder, --override and --yes`\n }\n if (\n ask.vos !== undefined &&\n ask.trackedVosId !== null &&\n ask.trackedVosId !== ask.vos\n )\n return `this take tracks vos ${ask.trackedVosId} (its vos.json), not ${ask.vos}. Drop --vos to push there, or remove vos.json to adopt ${ask.vos} instead`\n return null\n}\n\n/** Where a program push lands, or why it must not start. */\nexport type ProgramPushTarget =\n | { kind: 'version'; vosId: string; tracked: boolean }\n | { kind: 'create'; remixOfId?: string }\n | { kind: 'refuse'; why: string }\n\n/**\n * Where `vos push <config.json>` lands.\n *\n * A directory that TRACKS a vos ITERATES it. That is the contract's loop —\n * fetch, edit, check, push, pull, with no flags — and `vos.json` is what\n * makes the flags unnecessary. Making something NEW from the same config is\n * the explicit `--remix-of` door, which is also the one the README names for\n * remixing someone else's work.\n *\n * Reading the tracked id as LINEAGE instead is what made a bare re-push\n * create a fresh vos remixed from the last one: pushing twice in a directory\n * left a chain of \"... remix remix\" siblings on the shelf and edited none of\n * them.\n */\nexport function programPushTarget(ask: {\n /** `--vos`, when given (already parsed to an id). */\n vos?: string | null\n /** `--remix-of`, when given. */\n remixOf?: string | null\n /** The vos this directory tracks (vos.json), or null. */\n trackedVosId: string | null\n /** Create-only flags given, by name (`title`, `slug`, ...). */\n createOnly?: string[]\n}): ProgramPushTarget {\n if (ask.vos) return { kind: 'version', vosId: ask.vos, tracked: false }\n // An explicit remix always creates, even in a tracked directory: saying\n // --remix-of IS the ask for a new vos.\n if (ask.remixOf) return { kind: 'create', remixOfId: ask.remixOf }\n const tracked = ask.trackedVosId\n if (!tracked) return { kind: 'create' }\n // Create-only flags against a tracked directory are ambiguous: they read\n // as \"make a new one\" while the directory says \"iterate this one\". Name\n // both doors rather than silently dropping the flag or the edit.\n const extra = ask.createOnly ?? []\n if (extra.length) {\n const list = extra.map((f) => `--${f}`).join(', ')\n return {\n kind: 'refuse',\n why:\n `this directory tracks vos ${tracked} (vos.json), so a bare push adds a VERSION to it, ` +\n `and ${list} ${extra.length > 1 ? 'apply' : 'applies'} only when creating. ` +\n `To make a separate vos from this config: vos push <config.json> --remix-of ${tracked} ${list}. ` +\n `To change the tracked vos's title or slug, edit it on vos.so`,\n }\n }\n return { kind: 'version', vosId: tracked, tracked: true }\n}\n\n/** The first top-level JSON in `dir` shaped like a Playwright storage state, or null. */\nexport function storageStateInDir(dir: string): string | null {\n for (const f of readdirSync(dir)) {\n if (\n !f.endsWith('.json') ||\n f === 'doc.json' ||\n f === 'meta.json' ||\n f === 'actions.json' ||\n f === 'cursor.json' ||\n f === 'vos.json' ||\n f === 'doc.prev.json'\n )\n continue\n try {\n const v = JSON.parse(readFileSync(join(dir, f), 'utf8')) as unknown\n if (looksLikeStorageState(v)) return join(dir, f)\n } catch {\n /* not JSON, not a state */\n }\n }\n return null\n}\n\nexport async function pushTake(\n dir: string,\n flags: {\n key?: string\n api?: string\n origin?: string\n yes?: boolean\n /** `--vos`: on an untracked take, the vos to ADOPT. */\n vos?: string\n title?: string\n label?: string\n note?: string\n folder?: string\n overrides?: string[]\n },\n r: Reporter,\n): Promise<{ vosId: string; versionId: string; versionNumber: number }> {\n // A storage-state-shaped JSON in the take would upload live credentials\n // with it. Refused by path, before anything is read for the push.\n const stateFile = storageStateInDir(dir)\n if (stateFile)\n throw new Error(\n `${stateFile} looks like a Playwright storage state (cookies + origins): a live session in the take directory would be uploaded with it. Move it out of the take (a session belongs under ~/.config/vos/sessions or a temp dir) and push again`,\n )\n const take = await loadTake(dir)\n if (!take.doc) {\n throw new Error('no doc.json in this take — run `vos plan` first')\n }\n const lint = lintDoc(take.doc)\n if (lint.problems.length) {\n throw new Error(`doc.json fails lint:\\n ${lint.problems.join('\\n ')}`)\n }\n if (!existsSync(take.paths.recording)) {\n throw new Error(\n 'no recording in this take — record it, or `vos pull --media` to bring it home',\n )\n }\n\n const ctx = apiContext(flags)\n const tracked = readSyncState(dir)\n // The first push of this DIRECTORY uploads its recording either way, so\n // consent is asked of the directory, not of the vos it lands on.\n const firstPush = tracked === null\n\n // ADOPTION: `--vos <id>` on a directory with no vos.json. It used to be\n // ignored, and a second vos appeared on the shelf every time a take was\n // re-recorded from scratch. Now the take becomes the NEXT VERSION of that\n // vos: its head is read here and named as the base, which is the person\n // saying \"I know what is there\". The platform's own guards still hold: a\n // key push touching studio-modified nodes 409s unless --override names them.\n let state = tracked\n if (!state && flags.vos) {\n const meta = await api(ctx, `/vos/${flags.vos}`)\n const head = (meta.json.vos as { currentVersionId?: string } | undefined)\n ?.currentVersionId\n if (meta.status !== 200 || !head) {\n throw new Error(\n `--vos ${flags.vos}: cannot adopt it (${meta.status}${meta.json.error ? `: ${String(meta.json.error)}` : ''}) — it must be a vos this credential can read, with a version to build on`,\n )\n }\n r.log(\n `adopting vos ${flags.vos}: this take becomes the next version after its head (${head})`,\n )\n state = { vosId: flags.vos, versionId: head }\n }\n\n // --folder files the CREATED vos into a project (keys add\n // organization). Refused in words on an already-pushed take, and resolved\n // BEFORE any upload so a bad slug costs nothing — the flag used to parse\n // and silently drop, which is worse than either.\n let folderId: string | undefined\n if (flags.folder) {\n if (state) {\n throw new Error(\n '--folder applies when CREATING a vos — this take is already pushed; file it with: vos folder move <vosId> --to <folder>',\n )\n }\n folderId = resolveFolder(\n await listFolders(ctx.origin, ctx.key),\n flags.folder,\n ).id\n }\n\n // Never upload unprompted: explicit consent on the first push.\n if (firstPush && !flags.yes) {\n if (!process.stdin.isTTY) {\n throw new Error(\n 'first push of this take uploads its recording — pass --yes to consent headlessly',\n )\n }\n const rl = createInterface({ input: process.stdin, output: process.stderr })\n const answer = await rl.question(\n `Push this take (recording + doc.json) to ${ctx.origin}? [y/N] `,\n )\n rl.close()\n if (!/^y(es)?$/i.test(answer.trim())) {\n throw new Error('push cancelled')\n }\n }\n\n // 1. The recording, content-addressed — re-pushes reuse the same asset.\n // A take of any real length is past the single-request ceiling, so\n // this goes in parts; `uploadAsset` picks the transport by size.\n const bytes = await readFile(take.paths.recording)\n const hash = createHash('sha256').update(bytes).digest('hex')\n // What the file IS, never what it is called. A take remuxed to mp4 keeps the\n // name `recording.webm`, and an asset declared `video/webm` holding mp4 bytes\n // fails every render of that version inside the video element — a format\n // error a day and a machine away from the mislabelling that caused it.\n const { type: contentType } = resolveMediaType({\n head: bytes.subarray(0, MEDIA_HEAD_BYTES),\n filename: take.paths.recordingName,\n })\n const filename = nameForType(take.paths.recordingName, contentType)\n if (filename !== take.paths.recordingName) {\n r.log(\n ` ${take.paths.recordingName} holds ${contentType} — uploading it as ${filename}`,\n )\n }\n r.log(`uploading recording (${Math.round(bytes.length / 1024)} kB)…`)\n let upload: UploadedAsset\n try {\n upload = await uploadAsset(ctx, new Uint8Array(bytes), {\n filename,\n contentType,\n contentHash: hash,\n // The take's length so the server holds it to the plan's cap.\n ...(take.meta.durationMs > 0\n ? { durationSeconds: take.meta.durationMs / 1000 }\n : {}),\n onPart: (done, total) => r.log(` part ${done}/${total}`),\n })\n } catch (e) {\n throw new Error(\n `recording upload failed: ${e instanceof Error ? e.message : String(e)}`,\n )\n }\n for (const note of upload.notes) r.log(` note: ${note}`)\n const assetId = upload.id\n const assetUrl = upload.url\n r.event({ event: 'recording', assetId, reused: upload.reused })\n if (upload.reused) r.log(' recording already hosted — reused')\n\n // 2. The doc, keys rewritten to hosted URLs; lower through the real\n // pipeline so the hosted program is exactly what renders locally.\n const docForPush: ProjectDoc = structuredClone(take.doc)\n docForPush.source.videoKey = assetUrl\n // The voice and the webcam ride the same content-addressed door as the\n // recording. They used to be dropped here as \"local-only\", which made\n // fetch-then-push lose them from the hosted take without a word a person\n // would notice. A sidecar whose FILE is missing is the one case left to\n // drop, and it is said.\n await uploadDocRefs(sourceSidecarRefs(docForPush), dir, ctx, (l) => r.log(l))\n for (const field of ['micKey', 'camKey'] as const) {\n const key = docForPush.source[field]\n if (key && isTakeRelativeKey(key)) {\n r.log(\n ` ${field === 'micKey' ? 'mic' : 'cam'} track ${key} is not beside the take — left out of the push`,\n )\n delete docForPush.source[field]\n }\n }\n // The document's other media, keyed beside the recording (a poster's\n // mark in brand/, a pasted ground, an added score): each file rides the\n // same content-addressed door, and the hosted document keys the asset.\n await uploadDocRefs(docMediaRefs(docForPush), dir, ctx, (l) => r.log(l))\n const lowered = lowerToComposition(docForPush)\n const config = { ...lowered.config, data: lowered.data }\n\n // 3. Create or iterate — always against the recorded base.\n if (!state) {\n const title =\n flags.title ??\n `Take ${basename(dir)} ${new Date().toISOString().slice(0, 10)}`\n const slug = `${\n title\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .slice(0, 40) || 'take'\n }-${Date.now().toString(36)}`\n const created = await api(ctx, '/vos', {\n method: 'POST',\n body: {\n title,\n slug,\n visibility: 'private',\n config,\n doc: docForPush,\n assetIds: [assetId],\n client: clientId(),\n ...(folderId ? { folderId } : {}),\n ...(flags.label ? { label: flags.label } : {}),\n ...(flags.note ? { note: flags.note } : {}),\n },\n })\n if (created.status !== 201) {\n throw new Error(\n `push failed (${created.status}): ${String(created.json.error ?? '')}${detailLine(created.json)}`,\n )\n }\n serverWarnings(created.json, (l) => r.log(l))\n const vos = created.json.vos as { id: string; currentVersionId?: string }\n const meta = await api(ctx, `/vos/${vos.id}`)\n const versionId = String(\n (meta.json.vos as { currentVersionId?: string } | undefined)\n ?.currentVersionId ?? '',\n )\n writeSyncState(dir, {\n vosId: vos.id,\n versionId,\n pushedAt: new Date().toISOString(),\n title,\n slug,\n })\n return { vosId: vos.id, versionId, versionNumber: 1 }\n }\n\n const pushed = await api(ctx, `/vos/${state.vosId}/versions`, {\n method: 'POST',\n body: {\n config,\n doc: docForPush,\n client: clientId(),\n ...(state.versionId ? { baseVersionId: state.versionId } : {}),\n ...(flags.label ? { label: flags.label } : {}),\n ...(flags.note ? { note: flags.note } : {}),\n ...(flags.overrides?.length ? { overrides: flags.overrides } : {}),\n },\n })\n if (pushed.status === 409) {\n r.log(\n pushed.json.error === 'stale_base'\n ? 'HEAD moved while you worked — what changed:'\n : `protected nodes (${String((pushed.json.nodes as string[] | undefined)?.join(', '))}) — the human touched these since your last push:`,\n )\n printChanges(r, pushed.json.changes, pushed.json.protected)\n r.event({ event: 'conflict', ...pushed.json })\n throw new Error(\n pushed.json.error === 'stale_base'\n ? 'stale base — run `vos pull` to take the human’s changes, re-apply yours on top, then push again'\n : 'protected conflict — keep the human’s values, or push with --override <id> ONLY if the user asked for that exact change',\n )\n }\n if (pushed.status !== 201) {\n throw new Error(\n `push failed (${pushed.status}): ${String(pushed.json.error ?? '')}${detailLine(pushed.json)}`,\n )\n }\n serverWarnings(pushed.json, (l) => r.log(l))\n const version = pushed.json.version as { id: string; versionNumber: number }\n writeSyncState(dir, {\n vosId: state.vosId,\n versionId: version.id,\n pushedAt: new Date().toISOString(),\n })\n return {\n vosId: state.vosId,\n versionId: version.id,\n versionNumber: version.versionNumber,\n }\n}\n\nexport async function pullTake(\n dir: string,\n flags: {\n key?: string\n api?: string\n origin?: string\n vos?: string\n /** Also download the recording + sidecars and re-anchor the doc. */\n media?: boolean\n /** The base to walk the changelog from; default the tracked version. */\n since?: string\n /** Report what changed and stop: no doc.json, no media, no repoint. */\n check?: boolean\n },\n r: Reporter,\n): Promise<{\n vosId: string\n versionId: string\n versionNumber: number | null\n changed: boolean\n media?: MediaPullResult\n /** --check: the report, nothing written. */\n checked?: boolean\n /** --check: versions between the base and head (null when there is no base to walk from). */\n behind?: number | null\n changes?: unknown[]\n protected?: string[]\n}> {\n const ctx = apiContext(flags)\n const state = readSyncState(dir)\n const vosId = flags.vos ?? state?.vosId\n if (!vosId) {\n throw new Error('this take was never pushed — pass --vos <id> to link it')\n }\n const base = flags.since ?? state?.versionId ?? null\n\n const meta = await api(ctx, `/vos/${vosId}`)\n if (meta.status !== 200) {\n throw new Error(\n `fetch failed (${meta.status}): ${String(meta.json.error ?? '')}`,\n )\n }\n const head = String(\n (meta.json.vos as { currentVersionId?: string } | undefined)\n ?.currentVersionId ?? '',\n )\n if (!head) throw new Error('this vos has no versions')\n\n if (base === head) {\n r.log(\n flags.since\n ? 'up to date — --since names the head'\n : 'up to date — HEAD is your last push',\n )\n if (flags.check) {\n return {\n vosId,\n versionId: head,\n versionNumber: null,\n changed: false,\n checked: true,\n behind: 0,\n changes: [],\n protected: [],\n }\n }\n let media: MediaPullResult | undefined\n if (flags.media && existsSync(join(dir, 'doc.json'))) {\n const local = JSON.parse(\n await readFile(join(dir, 'doc.json'), 'utf8'),\n ) as ProjectDoc\n media = await pullMedia(ctx, dir, local, r.log)\n }\n return {\n vosId,\n versionId: head,\n versionNumber: null,\n changed: false,\n media,\n }\n }\n\n // The typed changelog: what the human did since this take's base (the\n // tracked version, or --since).\n let walked: { changes: unknown[]; protected: string[] } | null = null\n if (base) {\n const changes = await api(\n ctx,\n `/vos/${vosId}/changes?since=${encodeURIComponent(base)}`,\n )\n if (changes.status === 200) {\n r.log(\n flags.since\n ? `changes since ${base.slice(0, 8)}…:`\n : 'changes since your last push:',\n )\n printChanges(r, changes.json.changes, changes.json.protected)\n walked = {\n changes: Array.isArray(changes.json.changes)\n ? (changes.json.changes as unknown[])\n : [],\n protected: Array.isArray(changes.json.protected)\n ? (changes.json.protected as string[])\n : [],\n }\n if (changes.json.truncated === true) {\n r.log('walk truncated — more versions exist; pull again after syncing')\n }\n } else {\n r.log(\n `changelog unavailable (${changes.status}) — the head is v?; pass --since <versionId> you can read, or pull to sync`,\n )\n }\n } else {\n r.log(\n 'no base to compare from (this take was linked with --vos) — pass --since <versionId> for the changelog',\n )\n }\n\n // --check: the report is the result. Nothing on disk moves.\n if (flags.check) {\n return {\n vosId,\n versionId: head,\n versionNumber: null,\n changed: false,\n checked: true,\n behind: walked ? walked.changes.length : null,\n changes: walked?.changes ?? [],\n protected: walked?.protected ?? [],\n }\n }\n\n // The head doc, migrated on read, re-anchored to the local recording —\n // same bytes by construction (content-addressed upload).\n const docRes = await api(ctx, `/vos/${vosId}/versions/${head}/doc`)\n if (docRes.status !== 200) {\n throw new Error(\n docRes.status === 404\n ? 'the head version carries no doc — is this a take vos?'\n : `doc fetch failed (${docRes.status})`,\n )\n }\n const hostedDoc = migrateHostedDoc(docRes.json)\n const doc = hostedDoc as unknown as ProjectDoc\n const localRecording = takeMediaFile(dir, 'recording', RECORDING_NAME)\n if (existsSync(localRecording)) {\n doc.source.videoKey = basename(localRecording)\n }\n await writeJson(join(dir, 'doc.json'), doc, true)\n // --media: the footage (and sidecars) come home beside the doc, so digest,\n // frames and render work on this directory as on a local take.\n const media = flags.media ? await pullMedia(ctx, dir, doc, r.log) : undefined\n\n const versions = await api(ctx, `/vos/${vosId}/versions`)\n const headRow = (\n (versions.json.versions ?? []) as { id: string; versionNumber: number }[]\n ).find((v) => v.id === head)\n\n writeSyncState(dir, {\n vosId,\n versionId: head,\n pushedAt: state?.pushedAt ?? new Date().toISOString(),\n })\n return {\n vosId,\n versionId: head,\n versionNumber: headRow?.versionNumber ?? null,\n changed: true,\n media,\n }\n}\n","/**\n * `vos folder` — the shelf verbs: list your folders, create one, move\n * work into one, PULL one (the folder contract on disk). The additive half\n * of the shelf rule: an agent may ADD organization\n * (create a folder, file voses and assets into it) but never reshape or\n * destroy what the human made — rename/delete/reorder have no CLI verb on\n * purpose; those stay session gestures on vos.so.\n *\n * vos folder list [--json]\n * vos folder create <name> [--parent <folderId|slug>] [--desc <text>] [--json]\n * vos folder move <vosId|assetId|watch-url>... --to <folderId|slug|none> [--json]\n * vos folder pull <folderId|slug> [--out dir] [--media] [--json]\n *\n * pull writes the folder's whole context package to disk — the one step of\n * the \"create in my style\" flow the CLI could not do: recipes (own and\n * inherited, bodies inline) and every member's config.json (+ doc.json for\n * takes) each in a directory that TRACKS its vos, so `vos push` from any of\n * them lands as a version. One line per recipe prints what it governs and\n * where it says to start, read from the optional hints.\n *\n * move accepts vos ids AND asset ids (recipes, uploads): it tries the vos\n * first and falls back to the asset route on 404, so the caller never has\n * to say which kind an id is.\n */\nimport { mkdir, writeFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport { recipeHints } from '@vosjs/shared/frontmatter'\nimport { migrateHostedDoc } from '@vosjs/studio-core'\nimport { UsageError, parseArgs, strFlag } from './args'\nimport { pullMedia } from './media'\nimport { EXIT_ERROR, EXIT_OK, createReporter } from './output'\nimport {\n apiError,\n apiJson,\n parseVosId,\n platformOrigin,\n requireCredential,\n writeSyncState,\n} from './platform'\nimport type { ProjectDoc } from '@vosjs/studio-core'\n\nconst BOOLEAN_FLAGS = new Set(['json', 'help', 'media'])\n\nexport interface FolderRow {\n id: string\n name: string\n slug: string\n parentId: string | null\n counts?: { voses?: number; recipes?: number; assets?: number }\n}\n\nexport async function listFolders(\n origin: string,\n key: string,\n): Promise<FolderRow[]> {\n const r = await apiJson(origin, '/api/folders', { key })\n if (r.status !== 200) throw new Error(apiError('list folders', r))\n return (r.body.folders ?? []) as FolderRow[]\n}\n\n/** Resolve a folder reference (id or slug) against the caller's own shelf. */\nexport function resolveFolder(rows: FolderRow[], ref: string): FolderRow {\n const hit = rows.find((f) => f.id === ref) ?? rows.find((f) => f.slug === ref)\n if (!hit) {\n const shelf = rows.map((f) => f.slug).join(', ') || '(no folders yet)'\n throw new UsageError(`no folder \"${ref}\" on your shelf — have: ${shelf}`)\n }\n return hit\n}\n\nfunction printTree(rows: FolderRow[]): void {\n const children = new Map<string | null, FolderRow[]>()\n for (const f of rows) {\n const list = children.get(f.parentId) ?? []\n list.push(f)\n children.set(f.parentId, list)\n }\n const walk = (parentId: string | null, depth: number) => {\n for (const f of children.get(parentId) ?? []) {\n const c = f.counts ?? {}\n const held = [\n c.voses ? `${c.voses} vos${c.voses === 1 ? '' : 'es'}` : '',\n c.recipes ? `${c.recipes} recipe${c.recipes === 1 ? '' : 's'}` : '',\n c.assets ? `${c.assets} asset${c.assets === 1 ? '' : 's'}` : '',\n ]\n .filter(Boolean)\n .join(', ')\n process.stdout.write(\n `${' '.repeat(depth)}${f.name} (${f.slug})${held ? ` — ${held}` : ''}\\n`,\n )\n walk(f.id, depth + 1)\n }\n }\n walk(null, 0)\n}\n\nasync function cmdList(argv: string[]): Promise<number> {\n const { flags } = parseArgs(argv, BOOLEAN_FLAGS)\n const r = createReporter(flags.json === true)\n const origin = platformOrigin({\n origin: strFlag(flags, 'origin'),\n api: strFlag(flags, 'api'),\n })\n const key = requireCredential(strFlag(flags, 'key'))\n const rows = await listFolders(origin, key)\n if (r.json) {\n r.done({ folders: rows }, '')\n return EXIT_OK\n }\n if (rows.length === 0) {\n r.done({}, 'no folders yet — vos folder create <name>')\n return EXIT_OK\n }\n printTree(rows)\n return EXIT_OK\n}\n\nasync function cmdCreate(argv: string[]): Promise<number> {\n const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS)\n const name = positionals.join(' ').trim()\n if (!name)\n throw new UsageError(\n 'vos folder create <name> [--parent <folderId|slug>] [--desc <text>]',\n )\n const r = createReporter(flags.json === true)\n const origin = platformOrigin({\n origin: strFlag(flags, 'origin'),\n api: strFlag(flags, 'api'),\n })\n const key = requireCredential(strFlag(flags, 'key'))\n\n const parentRef = strFlag(flags, 'parent')\n let parentId: string | undefined\n if (parentRef) {\n parentId = resolveFolder(await listFolders(origin, key), parentRef).id\n }\n\n const res = await apiJson(origin, '/api/folders', {\n method: 'POST',\n key,\n body: {\n name,\n ...(strFlag(flags, 'desc')\n ? { description: strFlag(flags, 'desc') }\n : {}),\n ...(parentId ? { parentId } : {}),\n },\n })\n if (res.status !== 201) throw new Error(apiError('create folder', res))\n const created = res.body.folder as FolderRow\n r.done(\n { id: created.id, slug: created.slug, parentId: created.parentId },\n `created ${created.name} (${created.slug}, ${created.id})${parentRef ? ` inside ${parentRef}` : ''}`,\n )\n return EXIT_OK\n}\n\nasync function cmdMove(argv: string[]): Promise<number> {\n const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS)\n const toRef = strFlag(flags, 'to')\n if (positionals.length === 0 || !toRef)\n throw new UsageError(\n 'vos folder move <vosId|assetId|watch-url>... --to <folderId|slug|none>',\n )\n const r = createReporter(flags.json === true)\n const origin = platformOrigin({\n origin: strFlag(flags, 'origin'),\n api: strFlag(flags, 'api'),\n })\n const key = requireCredential(strFlag(flags, 'key'))\n\n const folderId =\n toRef === 'none'\n ? null\n : resolveFolder(await listFolders(origin, key), toRef).id\n\n let failed = 0\n const moved: { id: string; kind: string }[] = []\n for (const raw of positionals) {\n const id = parseVosId(raw)\n // A move target is a vos or an asset; ids don't say which, so try the\n // vos first and fall back to the asset route on its 404.\n const asVos = await apiJson(origin, `/api/vos/${id}`, {\n method: 'PATCH',\n key,\n body: { folderId },\n })\n if (asVos.status === 200) {\n moved.push({ id, kind: 'vos' })\n r.log(`moved vos ${id}`)\n continue\n }\n if (asVos.status === 404) {\n const asAsset = await apiJson(origin, `/api/assets/${id}`, {\n method: 'PATCH',\n key,\n body: { folderId },\n })\n if (asAsset.status === 200) {\n moved.push({ id, kind: 'asset' })\n r.log(`moved asset ${id}`)\n continue\n }\n failed++\n r.log(apiError(`move ${id}`, asAsset))\n continue\n }\n failed++\n r.log(apiError(`move ${id}`, asVos))\n }\n r.done(\n { moved, failed, folderId },\n `moved ${moved.length}/${positionals.length} into ${toRef === 'none' ? 'the top level' : toRef}${failed ? ` — ${failed} failed` : ''}`,\n )\n return failed ? EXIT_ERROR : EXIT_OK\n}\n\ninterface PullPayload {\n folder: { id: string; name: string; slug: string; description?: string }\n subfolders: { id: string; name: string; slug: string }[]\n recipes: { id: string; filename: string; body?: string }[]\n inheritedRecipes: {\n id: string\n filename: string\n body?: string\n folderSlug?: string\n folderName?: string\n }[]\n voses: {\n id: string\n title: string\n slug?: string | null\n currentVersionId?: string | null\n hasDoc?: boolean\n contentUrls?: { config?: string }\n }[]\n assets: { id: string; filename: string; category: string; fileUrl: string }[]\n}\n\n/** The one line a recipe earns in the pull summary, from its hints. */\nexport function recipeLine(filename: string, body: string): string {\n const h = recipeHints(body)\n const facts = [\n h.applies\n ? `applies to ${h.applies === 'any' ? 'everything' : `${h.applies}s`}`\n : '',\n h.seed ? `starts from ${h.seed}` : '',\n ].filter(Boolean)\n return `${filename}${facts.length ? ` (${facts.join(' · ')})` : ''}`\n}\n\nconst safeName = (v: string) =>\n v\n .toLowerCase()\n .replace(/[^a-z0-9._-]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .slice(0, 60) || 'file'\n\nasync function cmdPull(argv: string[]): Promise<number> {\n const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS)\n const ref = positionals[0]\n if (!ref)\n throw new UsageError(\n 'vos folder pull <folderId|slug> [--out dir] [--media]',\n )\n const r = createReporter(flags.json === true)\n const origin = platformOrigin({\n origin: strFlag(flags, 'origin'),\n api: strFlag(flags, 'api'),\n })\n const key = requireCredential(strFlag(flags, 'key'))\n const folder = resolveFolder(await listFolders(origin, key), ref)\n const res = await apiJson(origin, `/api/folders/${folder.id}`, { key })\n if (res.status !== 200)\n throw new Error(apiError(`pull folder ${folder.slug}`, res))\n const payload = res.body as unknown as PullPayload\n const out = strFlag(flags, 'out') ?? folder.slug\n await mkdir(join(out, 'recipes'), { recursive: true })\n\n const lines: string[] = []\n const recipes: { path: string; line: string }[] = []\n for (const rec of payload.recipes) {\n const path = join(out, 'recipes', safeName(rec.filename))\n await writeFile(path, rec.body ?? '')\n recipes.push({ path, line: recipeLine(rec.filename, rec.body ?? '') })\n }\n for (const rec of payload.inheritedRecipes) {\n const from = safeName(rec.folderSlug ?? 'inherited')\n await mkdir(join(out, 'recipes', '_inherited', from), { recursive: true })\n const path = join(\n out,\n 'recipes',\n '_inherited',\n from,\n safeName(rec.filename),\n )\n await writeFile(path, rec.body ?? '')\n recipes.push({\n path,\n line: `${recipeLine(rec.filename, rec.body ?? '')} [inherited from ${rec.folderName ?? from}]`,\n })\n }\n\n const members: { dir: string; id: string; title: string; take: boolean }[] =\n []\n for (const v of payload.voses) {\n const dir = join(out, 'members', safeName(v.slug || v.title || v.id))\n await mkdir(dir, { recursive: true })\n const cfg = await apiJson(origin, `/api/vos/${v.id}/config`, { key })\n if (cfg.status !== 200) {\n lines.push(`skipped ${v.title}: ${apiError('fetch config', cfg)}`)\n continue\n }\n await writeFile(\n join(dir, 'config.json'),\n JSON.stringify(cfg.body.config, null, 2),\n )\n let take = false\n if (v.hasDoc && v.currentVersionId) {\n const doc = await apiJson(\n origin,\n `/api/vos/${v.id}/versions/${v.currentVersionId}/doc`,\n { key },\n )\n if (doc.status === 200) {\n await writeFile(\n join(dir, 'doc.json'),\n JSON.stringify(doc.body, null, 2),\n )\n take = true\n // --media: the footage comes home beside the doc.\n if (flags.media === true) {\n const hosted = migrateHostedDoc(doc.body) as unknown as ProjectDoc\n await pullMedia({ origin, key }, dir, hosted, r.log)\n }\n }\n }\n writeSyncState(dir, {\n vosId: v.id,\n versionId: v.currentVersionId ?? null,\n title: v.title,\n ...(v.slug ? { slug: v.slug } : {}),\n })\n members.push({ dir, id: v.id, title: v.title, take })\n }\n\n const assets = payload.assets.filter((a) => a.category !== 'recipe')\n const summary = [\n `Pulled ${folder.name} (${folder.slug}) → ${out}/`,\n ...(folder.id && payload.folder.description\n ? [` ${payload.folder.description}`]\n : []),\n ` recipes (${recipes.length}) — read EVERY one:`,\n ...recipes.map((x) => ` ${x.line}`),\n ` members (${members.length}):`,\n ...members.map(\n (m) => ` ${m.title}${m.take ? ' [take]' : ''} → ${m.dir}/`,\n ),\n ...(assets.length\n ? [\n ` assets (${assets.length}): ${assets.map((a) => a.filename).join(', ')}`,\n ]\n : []),\n ...(payload.subfolders.length\n ? [\n ` subfolders (not inlined): ${payload.subfolders.map((s) => s.slug).join(', ')}`,\n ]\n : []),\n ...lines,\n `Then: vos push <file> --folder ${folder.slug} --label \"…\" --note \"…\"`,\n ].join('\\n')\n r.done(\n {\n out,\n folder: payload.folder,\n recipes: recipes.map((x) => x.path),\n members,\n assets,\n subfolders: payload.subfolders,\n },\n summary,\n )\n return EXIT_OK\n}\n\nexport async function cmdFolder(argv: string[]): Promise<number> {\n const sub = argv[0]\n const rest = argv.slice(1)\n switch (sub) {\n case 'list':\n case 'ls':\n return cmdList(rest)\n case 'create':\n return cmdCreate(rest)\n case 'move':\n return cmdMove(rest)\n case 'pull':\n return cmdPull(rest)\n default:\n throw new UsageError(\n 'vos folder <list|create|move|pull> — list your shelf, create a folder, move voses/assets into one, pull a folder to disk',\n )\n }\n}\n","/**\n * Program-path platform verbs — fetch / push / pull for config.json programs,\n * plus `vos login`. Moved here from @vosjs/cli under the CLI boundary (the MIT\n * host owns engine verbs only; every vos.so verb lives in this package).\n *\n * Full local validation stays the host's `vos check` (the one home of the\n * check pipeline); push runs a preflight (migrate → schema → function syntax,\n * all MIT @vosjs/core) so an obviously broken config never burns a request.\n */\nimport { existsSync } from 'node:fs'\nimport { mkdir, readFile, writeFile } from 'node:fs/promises'\nimport { createInterface } from 'node:readline/promises'\nimport { basename, dirname, join } from 'node:path'\nimport {\n CURRENT_CONFIG_VERSION,\n migrateConfig,\n vosConfigJsonSchema,\n} from '@vosjs/core'\nimport { lowerProgramDoc, migrateHostedDoc } from '@vosjs/studio-core'\nimport { UsageError, parseArgs, strFlag } from './args'\nimport { directoryKind } from '../loadConfig'\nimport { EXIT_OK, createReporter } from './output'\nimport { LoginUnsupportedError, browserLogin, handoffLogin } from './login'\nimport {\n apiError,\n apiJson,\n clientId,\n deriveSlug,\n formatChanges,\n parseVosId,\n platformOrigin,\n readSyncState,\n requireCredential,\n resolveCredential,\n serverWarnings,\n writeCredential,\n writeSyncState,\n} from './platform'\nimport { programPushTarget } from './sync'\nimport { hostedAssetId, manifestRefs } from '../programAssets'\nimport { listFolders, resolveFolder } from './folder'\nimport { docAudioRefs, docLayerRefs, pullMedia, uploadDocRefs } from './media'\nimport {\n hostedLiteralWarnings,\n localManifestRefs,\n pullManifest,\n uploadManifest,\n} from './assetManifest'\nimport { lintDoc } from './validateDoc'\nimport { landedLines, waitForLanded } from './landed'\nimport type {\n AudioClip,\n ObjectClip,\n OverlayClip,\n ProjectDoc,\n} from '@vosjs/studio-core'\nimport type { VersionChange } from './platform'\nimport type { Reporter } from './output'\n\nconst BOOLEAN_FLAGS = new Set([\n 'json',\n 'help',\n 'media',\n 'check',\n 'yes',\n 'claimable',\n 'no-browser',\n 'wait',\n])\nconst MULTI_FLAGS = new Set(['override'])\n\ninterface Preflight {\n ok: boolean\n issues: string[]\n /** The migrated config (params/presets untouched) — what a push sends. */\n config: Record<string, unknown> | null\n}\n\n/** Envelope unwrap → migrate → schema → function-string syntax. */\nexport function preflightConfig(parsed: unknown): Preflight {\n const issues: string[] = []\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {\n return { ok: false, issues: ['not a JSON object'], config: null }\n }\n let obj = parsed as Record<string, unknown>\n if (\n typeof obj.config === 'object' &&\n obj.config !== null &&\n !('createTimeline' in obj)\n ) {\n obj = obj.config as Record<string, unknown>\n }\n // A push makes a config DURABLE, so it must say which schema era it was\n // written against. Migrating an absent version would stamp a guess about\n // WHEN the file was authored: a config.json can sit in a repository for\n // years, and reading it as the current schema is silent and unrecoverable.\n // Refuse here rather than send a config the server would refuse anyway.\n if (obj.version === undefined) {\n return {\n ok: false,\n issues: [\n `missing \"version\": a config that is pushed must say which schema it was written against. Add \"version\": ${CURRENT_CONFIG_VERSION}.`,\n ],\n config: null,\n }\n }\n let migrated: Record<string, unknown>\n try {\n migrated = migrateConfig(obj as never) as unknown as Record<string, unknown>\n } catch (e) {\n return {\n ok: false,\n issues: [\n `migration failed: ${e instanceof Error ? e.message : String(e)}`,\n ],\n config: null,\n }\n }\n const schema = vosConfigJsonSchema.safeParse(migrated)\n if (!schema.success) {\n for (const i of schema.error.issues.slice(0, 10)) {\n issues.push(`schema ${i.path.join('.') || '(root)'}: ${i.message}`)\n }\n return { ok: false, issues, config: null }\n }\n for (const key of [\n 'setup',\n 'createContent',\n 'createTimeline',\n 'onFrame',\n ] as const) {\n const src = migrated[key]\n if (typeof src !== 'string' || !src.length) continue\n try {\n new Function(`\"use strict\"; return (${src}\\n)`)\n } catch (e) {\n issues.push(\n `syntax ${key}: ${e instanceof Error ? e.message : String(e)}`,\n )\n }\n }\n return {\n ok: issues.length === 0,\n issues,\n config: issues.length ? null : migrated,\n }\n}\n\n/** `vos push <target>`: a .json file, or a dir holding config.json. */\nexport function resolveConfigPath(target: string): string {\n if (target.endsWith('.json')) return target\n const inDir = join(target, 'config.json')\n if (existsSync(inDir)) return inDir\n throw new UsageError(\n `${target} has no config.json (and is not a take — no doc.json)`,\n )\n}\n\nexport async function cmdFetch(argv: string[]): Promise<number> {\n const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS)\n const source = positionals[0]\n if (!source)\n throw new UsageError('vos fetch <vosId|watch-url> [--out dir] [--media]')\n const r = createReporter(flags.json === true)\n const origin = platformOrigin({\n origin: strFlag(flags, 'origin'),\n api: strFlag(flags, 'api'),\n })\n const id = parseVosId(source)\n // Attached when present so your own private programs fetch too; public and\n // unlisted programs need no credential at all.\n const key = resolveCredential(strFlag(flags, 'key'))\n\n const meta = await apiJson(origin, `/api/vos/${id}`, { key })\n if (meta.status !== 200) throw new Error(apiError(`fetch vos ${id}`, meta))\n const vosMeta = (meta.body.vos ?? {}) as Record<string, unknown>\n // The metadata route resolves slugs; byte routes want the canonical id.\n const vosId = typeof vosMeta.id === 'string' && vosMeta.id ? vosMeta.id : id\n const cfg = await apiJson(origin, `/api/vos/${vosId}/config`, { key })\n if (cfg.status !== 200)\n throw new Error(apiError(`fetch config for ${vosId}`, cfg))\n\n const slug =\n typeof vosMeta.slug === 'string' && vosMeta.slug ? vosMeta.slug : vosId\n const out = strFlag(flags, 'out') ?? slug\n await mkdir(out, { recursive: true })\n // The config is written EXACTLY as stored (params/presets included) — this\n // file round-trips back through `vos push`.\n await writeFile(\n join(out, 'config.json'),\n JSON.stringify(cfg.body.config, null, 2),\n )\n const title = typeof vosMeta.title === 'string' ? vosMeta.title : ''\n const head =\n typeof vosMeta.currentVersionId === 'string'\n ? vosMeta.currentVersionId\n : null\n writeSyncState(out, {\n vosId,\n versionId: head,\n ...(title ? { title } : {}),\n slug,\n })\n\n // A TAKE vos carries a doc beside its program: write it (and, with\n // --media, bring the footage home) so the directory is a take directory.\n let take = false\n let mediaLine = ''\n if (head) {\n const doc = await apiJson(\n origin,\n `/api/vos/${vosId}/versions/${head}/doc`,\n {\n key,\n },\n )\n if (doc.status === 200 && !('source' in doc.body)) {\n // A PROGRAM document: the user's config is the doc's own; the\n // stored config is the composed one (what plays), so config.json is\n // written from the doc and doc.json omits it.\n const hosted = migrateHostedDoc(doc.body)\n const { config: own } = await writeProgramDoc(out, hosted)\n if (own) {\n await writeFile(join(out, 'config.json'), JSON.stringify(own, null, 2))\n }\n } else if (doc.status === 200) {\n take = true\n const hosted = migrateHostedDoc(doc.body) as unknown as ProjectDoc\n await writeFile(join(out, 'doc.json'), JSON.stringify(hosted, null, 2))\n if (flags.media === true) {\n const media = await pullMedia({ origin, key }, out, hosted, r.log)\n mediaLine = media.downloaded.length\n ? ` + ${media.downloaded.map((m) => m.file).join(', ')}`\n : ''\n }\n }\n }\n\n // A program's declared files: with --media they come home beside the\n // config and its manifest names them by path; without, the manifest keeps\n // the hosted refs, which a local render reads with your key.\n let assetsLine = ''\n if (!take) {\n const configPath = join(out, 'config.json')\n const written = JSON.parse(await readFile(configPath, 'utf8')) as Record<\n string,\n unknown\n >\n const hostedCount = manifestRefs(written).filter(({ ref }) =>\n hostedAssetId(ref, [origin, 'https://vos.so', 'https://www.vos.so']),\n ).length\n if (hostedCount && flags.media === true) {\n const pulled = await pullManifest({ origin, key }, out, written, r.log)\n if (pulled) {\n await writeFile(\n configPath,\n JSON.stringify({ ...written, assets: pulled.assets }, null, 2),\n )\n assetsLine = `\\n${pulled.files.length} declared file${pulled.files.length === 1 ? '' : 's'} in ${out}/assets`\n }\n } else if (hostedCount) {\n assetsLine = `\\n${hostedCount} declared file${hostedCount === 1 ? ' is' : 's are'} hosted (a render reads ${hostedCount === 1 ? 'it' : 'them'} with your key). Add --media to bring ${hostedCount === 1 ? 'it' : 'them'} home`\n }\n }\n\n r.done(\n {\n out,\n id: vosId,\n slug,\n title,\n currentVersionId: head,\n take,\n },\n take\n ? `Wrote ${out}/doc.json + config.json + vos.json${mediaLine} (${title || id}, a take)\\n` +\n (flags.media === true\n ? `Then: vos digest ${out} — look before you cut; edit doc.json; vos validate ${out}; vos push ${out}`\n : `Add --media to bring the recording home (digest/frames/render need it); then edit doc.json and vos push ${out}`)\n : `Wrote ${out}/config.json + vos.json (${title || id})${assetsLine}\\n` +\n `Edit config.json, then: vos check ${out}/config.json && vos push ${out}/config.json`,\n )\n return EXIT_OK\n}\n\n/**\n * `vos duplicate <vosId|watch-url>` — a private sibling of YOUR OWN vos.\n * Head only, same folder, named \"Copy of <title>\" by the SERVER so\n * the shelf and the CLI can never disagree about what a copy is called.\n *\n * Someone else's work is REMIXED, not duplicated: fetch it and push with\n * `--remix-of`. The route answers 403 saying exactly that.\n */\nexport async function cmdDuplicate(argv: string[]): Promise<number> {\n const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS)\n const source = positionals[0]\n if (!source) throw new UsageError('vos duplicate <vosId|watch-url> [--json]')\n const r = createReporter(flags.json === true)\n const origin = platformOrigin({\n origin: strFlag(flags, 'origin'),\n api: strFlag(flags, 'api'),\n })\n const id = parseVosId(source)\n const key = resolveCredential(strFlag(flags, 'key'))\n\n const res = await apiJson(origin, `/api/vos/${id}/duplicate`, {\n method: 'POST',\n key,\n })\n if (res.status !== 201) throw new Error(apiError(`duplicate ${id}`, res))\n const created = (res.body.vos ?? {}) as Record<string, unknown>\n const newId = String(created.id ?? '')\n const title = typeof created.title === 'string' ? created.title : ''\n const slug = typeof created.slug === 'string' ? created.slug : newId\n\n r.done(\n {\n id: newId,\n title,\n slug,\n remixedFromId: id,\n currentVersionId: created.currentVersionId ?? null,\n },\n `Duplicated as \"${title}\" (private, beside the original)\\n` +\n ` edit ${origin}/studio?vos=${newId}\\n` +\n ` fetch vos fetch ${newId}`,\n )\n return EXIT_OK\n}\n\n/**\n * THE program-create call — the one implementation behind `vos push` for a\n * new vos (and any in-repo script that creates programs). Creates a PRIVATE\n * vos, retrying the slug on collision (unless the caller chose it). No\n * sync-state side effects: tracking is the CLI verb's concern, not the\n * create's.\n */\nexport interface CreateProgramOptions {\n origin: string\n key: string\n config: Record<string, unknown>\n title: string\n /** Caller-chosen slug (no retry on collision); absent = derived + retried. */\n slug?: string\n description?: string\n tags?: string[]\n folderId?: string\n remixOfId?: string\n /** Attribution on v1: what you did and why — the first turn. */\n label?: string\n note?: string\n /** The program document riding along (overlays, objects, audio, speed, tween edits). */\n doc?: Record<string, unknown>\n log?: (msg: string) => void\n}\n\nexport interface CreateProgramResult {\n id: string\n slug: string\n currentVersionId: string | null\n}\n\nexport async function createProgramVos(\n opts: CreateProgramOptions,\n): Promise<CreateProgramResult> {\n const title = opts.title.slice(0, 100)\n const slugGiven = opts.slug !== undefined\n const baseSlug = opts.slug ?? deriveSlug(title)\n for (let attempt = 0; ; attempt++) {\n const slug =\n attempt === 0 ? baseSlug : `${baseSlug}-${attempt + 1}`.slice(0, 50)\n const body: Record<string, unknown> = {\n title,\n slug,\n visibility: 'private',\n config: opts.config,\n client: clientId(),\n }\n if (opts.description) body.description = opts.description\n if (opts.tags?.length) body.tags = opts.tags\n if (opts.folderId) body.folderId = opts.folderId\n if (opts.remixOfId) body.remixOfId = opts.remixOfId\n if (opts.label) body.label = opts.label\n if (opts.note) body.note = opts.note\n if (opts.doc) body.doc = opts.doc\n const res = await apiJson(opts.origin, '/api/vos', {\n method: 'POST',\n key: opts.key,\n body,\n })\n if (res.status === 409 && !slugGiven && attempt < 3) {\n opts.log?.(`slug \"${slug}\" is taken — retrying`)\n continue\n }\n if (res.status !== 201) throw new Error(apiError('push vos', res))\n if (opts.log) serverWarnings(res.body, opts.log)\n const created = (res.body.vos ?? {}) as Record<string, unknown>\n return {\n id: String(created.id ?? ''),\n slug: typeof created.slug === 'string' ? created.slug : slug,\n currentVersionId:\n typeof created.currentVersionId === 'string'\n ? created.currentVersionId\n : null,\n }\n }\n}\n\nexport async function cmdPushProgram(argv: string[]): Promise<number> {\n const { positionals, flags, multi } = parseArgs(\n argv,\n BOOLEAN_FLAGS,\n MULTI_FLAGS,\n )\n const target = positionals[0]\n if (!target) {\n throw new UsageError(\n 'vos push <config.json|take> [--vos id] [--title t] [--slug s] [--desc d] [--tags a,b] [--folder <id|slug>] [--remix-of id] [--note n] [--label l] [--base versionId] [--override id]...',\n )\n }\n const source = resolveConfigPath(target)\n const r = createReporter(flags.json === true)\n const origin = platformOrigin({\n origin: strFlag(flags, 'origin'),\n api: strFlag(flags, 'api'),\n })\n const dir = dirname(source)\n\n const parsed = JSON.parse(await readFile(source, 'utf8')) as unknown\n const pre = preflightConfig(parsed)\n if (!pre.ok || !pre.config) {\n for (const issue of pre.issues) r.log(`error ${issue}`)\n throw new Error(\n `config does not validate — full report: vos check ${source}`,\n )\n }\n const config = pre.config\n const state = readSyncState(dir)\n const vosFlag = strFlag(flags, 'vos')\n const explicitVosId = vosFlag ? parseVosId(vosFlag) : null\n // --still <t>: the program's cover, in output seconds. It is intent the\n // config cannot hold, so it lives in doc.json (minted when there is none)\n // and every later push keeps it.\n const stillFlag = strFlag(flags, 'still')\n if (stillFlag !== undefined) {\n const t = Number(stillFlag)\n if (!Number.isFinite(t) || t < 0)\n throw new UsageError('--still expects seconds, like --still 2.5')\n await setProgramStill(dir, t)\n r.log(`cover: ${t}s (doc.json \"still\")`)\n }\n // A program document beside the config: the shared layers, the tween\n // overlay, the anchor's own length. Lint-gated like a take's doc.\n for (const w of hostedLiteralWarnings(config)) r.log(`warning ${w}`)\n const programDoc = await readProgramDoc(dir, config)\n if (programDoc) {\n const lint = lintDoc(programDoc as never)\n if (lint.problems.length) {\n throw new Error(`doc.json fails lint:\\n ${lint.problems.join('\\n ')}`)\n }\n for (const w of lint.warnings) r.log(`warning doc.json: ${w}`)\n }\n\n // --claimable: the credential-free rung. Creates a NEW claimable vos (72h\n // claim link, programs only) — no key resolved, no vos.json written (the\n // agent cannot iterate an unclaimed vos; after the human claims it, the\n // loop rides THEIR key). One-shot by design.\n if (flags.claimable === true) {\n if (explicitVosId) {\n throw new UsageError(\n '--claimable creates a NEW claimable vos and cannot iterate (--vos). After the human claims it, iterate with their key: vos push --vos <id>',\n )\n }\n const fallback = state?.title\n ? `${state.title} remix`\n : basename(source).replace(/\\.json$/i, '') || 'vos program'\n const title = (strFlag(flags, 'title') ?? fallback).slice(0, 100)\n // The COMPOSED config, like every other push, so the document's layers\n // ride the claim. A claim carries no files, so a sound that is still a\n // local file cannot come along: it is left out, and said.\n let claimDoc = programDoc\n if (programDoc) {\n const sound = soundOf(programDoc)\n const local = docAudioRefs(sound)\n if (local.length) {\n const dropped = new Set(local.map((ref) => ref.key))\n claimDoc = {\n ...programDoc,\n audio: (sound.audio ?? []).filter((a) => !dropped.has(a.key)),\n }\n r.log(\n `warning a claimable push carries no files, so ${local.length} local sound${local.length === 1 ? '' : 's'} (${[...dropped].join(', ')}) ${local.length === 1 ? 'was' : 'were'} left out. After the claim, push again with a key to add ${local.length === 1 ? 'it' : 'them'}`,\n )\n }\n }\n // A sound can be left out; a file the program reads cannot. Without it\n // the claim link would show a program that fails to draw.\n const stay = localManifestRefs(config)\n if (stay.length) {\n throw new UsageError(\n `a claimable push carries no files, and this program declares ${stay.length} local file${stay.length === 1 ? '' : 's'} (${stay.join(', ')}). Push with a key instead (vos login, then vos push ${source}), which uploads ${stay.length === 1 ? 'it' : 'them'}`,\n )\n }\n const body: Record<string, unknown> = {\n title,\n config: storedProgramConfig(config, claimDoc),\n }\n const slug = strFlag(flags, 'slug')\n if (slug) body.slug = slug\n const res = await apiJson(origin, '/api/claim', { method: 'POST', body })\n if (res.status !== 201) throw new Error(apiError('claimable push', res))\n serverWarnings(res.body, (l) => r.log(l))\n const claimUrl = String(res.body.claimUrl ?? '')\n const expiresAt = String(res.body.expiresAt ?? '')\n const created = (res.body.vos ?? {}) as Record<string, unknown>\n r.done(\n { id: created.id ?? null, title, claimUrl, expiresAt },\n `Claimable push created (${title})\\n` +\n ` claim: ${claimUrl}\\n` +\n ` expires: ${expiresAt} — unclaimed work is deleted after 72h\\n` +\n `Hand the claim link to the user and NOWHERE else — it is the only\\n` +\n `reference and the only credential. After they claim it, iterate\\n` +\n `with their key: vos push ${source} --vos ${String(created.id ?? '<id>')}`,\n )\n return EXIT_OK\n }\n\n const key = requireCredential(strFlag(flags, 'key'))\n // A take's first push asks; a program's never does (it holds no\n // recording), so --yes is accepted and has nothing to answer.\n void flags.yes\n // The files the document's layers name, still local: its picture and\n // video overlays, its 3D props and its sound. Upload them first, so the\n // stored config and the document both key hosted assets. Only the sound\n // used to go; a program with a logo overlay or a prop pushed a document\n // that keyed files only the pusher's disk held.\n if (programDoc) {\n await uploadDocRefs(\n docLayerRefs(layersOf(programDoc)),\n dir,\n { origin, key },\n (l) => r.log(l),\n )\n }\n // The files the program itself declares (config.assets): uploaded the\n // same way, and named on the platform as asset:<id>. The config object is\n // the one the document carries, so both leave with the hosted refs; the\n // file on disk keeps its paths.\n await uploadManifest(config, dir, { origin, key }, (l) => r.log(l))\n // Accept both the repeatable --override id and the legacy --overrides id,id.\n // multi's index access is typed present but runtime-optional — hence the cast.\n const overrides = [\n ...((multi.override as string[] | undefined) ?? []),\n ...(strFlag(flags, 'overrides')?.split(',') ?? []),\n ]\n .map((s) => s.trim())\n .filter(Boolean)\n\n const desc = strFlag(flags, 'desc')\n const tagsFlag = strFlag(flags, 'tags')\n const folderRef = strFlag(flags, 'folder')\n const remixOfFlag = strFlag(flags, 'remix-of')\n\n const pushTarget = programPushTarget({\n vos: explicitVosId,\n remixOf: remixOfFlag,\n trackedVosId: state?.vosId ?? null,\n createOnly: (['title', 'slug'] as const).filter((f) => strFlag(flags, f)),\n })\n if (pushTarget.kind === 'refuse') throw new UsageError(pushTarget.why)\n const vosId = pushTarget.kind === 'version' ? pushTarget.vosId : null\n\n if (vosId && (desc || tagsFlag || folderRef)) {\n throw new UsageError(\n '--desc/--tags/--folder apply when CREATING a vos. On an existing one: vos folder move <id> --to <folder> for filing; edit title/description/tags on vos.so',\n )\n }\n\n if (vosId) {\n // Iterate an existing vos: add a version. --base names the version this\n // edit was made FROM (defaulting to the tracked base in vos.json, so a\n // fetch→edit→push loop gets stale detection for free); --overrides\n // consents to touching protected (human-edited) nodes — ONLY when the\n // user asked for that change.\n const trackedBase =\n state && state.vosId === vosId && state.versionId\n ? state.versionId\n : undefined\n const body: Record<string, unknown> = {\n config: storedProgramConfig(config, programDoc),\n client: clientId(),\n }\n if (programDoc) body.doc = programDoc\n const base = strFlag(flags, 'base') ?? trackedBase\n if (base) body.baseVersionId = base\n const note = strFlag(flags, 'note')\n if (note) body.note = note\n const label = strFlag(flags, 'label')\n if (label) body.label = label\n if (overrides.length) body.overrides = overrides\n const res = await apiJson(origin, `/api/vos/${vosId}/versions`, {\n method: 'POST',\n key,\n body,\n })\n if (res.status === 409) {\n // The correction path is the data path: both 409 shapes carry what to\n // read. stale_base embeds the changes made on the platform since your\n // base; protected_conflict lists the human-touched nodes you'd clobber.\n const changes = Array.isArray(res.body.changes)\n ? (res.body.changes as VersionChange[])\n : []\n for (const line of formatChanges(changes)) r.log(`platform: ${line}`)\n const protectedIds = Array.isArray(res.body.protected)\n ? res.body.protected\n : []\n const nodes = Array.isArray(res.body.nodes) ? res.body.nodes : []\n r.event({\n event: 'conflict',\n reason: res.body.error ?? 'conflict',\n changes,\n protected: protectedIds,\n nodes,\n })\n if (res.body.error === 'protected_conflict') {\n throw new Error(\n `push touches human-edited nodes: ${nodes.join(', ')} — keep the human's values, ` +\n `or re-push with --overrides ${nodes.join(',')} ONLY if the user asked for this change`,\n )\n }\n throw new Error(\n `version base is stale — the platform copy changed (${changes.length} edit${changes.length === 1 ? 's' : ''} above). ` +\n `Run: vos pull ${dir} — then re-apply your edit and push again`,\n )\n }\n if (res.status !== 201)\n throw new Error(apiError(`push version to ${vosId}`, res))\n serverWarnings(res.body, (l) => r.log(l))\n const version = (res.body.version ?? {}) as Record<string, unknown>\n // Track what we just made: the new version is the next push's base.\n if (typeof version.id === 'string') {\n writeSyncState(dir, { vosId, versionId: version.id })\n }\n const watchUrl = `${origin}/vos/${vosId}`\n const studioUrl = `${origin}/studio?vos=${vosId}`\n const landed =\n flags.wait === true\n ? await waitForLanded({\n origin,\n key,\n vosId,\n versionId: typeof version.id === 'string' ? version.id : null,\n log: (l) => r.log(l),\n })\n : null\n r.done(\n {\n id: vosId,\n versionId: version.id ?? null,\n versionNumber: version.versionNumber ?? null,\n base: base ?? null,\n watchUrl,\n studioUrl,\n ...(landed\n ? {\n still: landed.still,\n thumbnailUrl: landed.thumbnailUrl,\n previewUrl: landed.previewUrl,\n }\n : {}),\n },\n `Pushed version ${String(version.versionNumber ?? '?')} of ${vosId}\\n` +\n ` watch: ${watchUrl}\\n studio: ${studioUrl}` +\n (landed ? `\\n${landedLines(landed)}` : ''),\n )\n return EXIT_OK\n }\n\n // Create a new PRIVATE vos. Reached only when this directory tracks\n // nothing, or when --remix-of says so outright — a tracked directory\n // iterates above. Lineage is that flag; the platform validates it.\n const remixOfId =\n pushTarget.kind === 'create' ? pushTarget.remixOfId : undefined\n const fallbackTitle = state?.title\n ? `${state.title} remix`\n : basename(source).replace(/\\.json$/i, '') || 'vos remix'\n const title = (strFlag(flags, 'title') ?? fallbackTitle).slice(0, 100)\n const folderId = folderRef\n ? resolveFolder(await listFolders(origin, key), folderRef).id\n : undefined\n\n const created = await createProgramVos({\n origin,\n key,\n config: storedProgramConfig(config, programDoc),\n // The document rode the version path and not the create path, so a\n // fresh push of a program directory silently dropped its doc.json\n // (found seeding one-layer members: `--with` then said the vos carried\n // no doc).\n doc: programDoc ?? undefined,\n title,\n slug: strFlag(flags, 'slug'),\n description: desc,\n tags: tagsFlag\n ?.split(',')\n .map((t) => t.trim())\n .filter(Boolean),\n folderId,\n remixOfId,\n label: strFlag(flags, 'label'),\n note: strFlag(flags, 'note'),\n log: (msg) => r.log(msg),\n })\n // The directory now TRACKS the created vos (its source stays as\n // remixOfId) — the next push/pull needs no flags.\n writeSyncState(dir, {\n vosId: created.id,\n versionId: created.currentVersionId,\n title,\n slug: created.slug,\n ...(remixOfId ? { remixOfId } : {}),\n })\n const watchUrl = `${origin}/vos/${created.id}`\n const studioUrl = `${origin}/studio?vos=${created.id}`\n const landed =\n flags.wait === true\n ? await waitForLanded({\n origin,\n key,\n vosId: created.id,\n versionId: created.currentVersionId,\n log: (l) => r.log(l),\n })\n : null\n r.done(\n {\n id: created.id,\n slug: created.slug,\n title,\n visibility: 'private',\n folder: folderRef ?? null,\n remixOfId: remixOfId ?? null,\n currentVersionId: created.currentVersionId,\n watchUrl,\n studioUrl,\n ...(landed\n ? {\n still: landed.still,\n thumbnailUrl: landed.thumbnailUrl,\n previewUrl: landed.previewUrl,\n }\n : {}),\n },\n `Created private vos ${created.id} (${title})\\n` +\n ` watch: ${watchUrl}\\n studio: ${studioUrl}\\n` +\n (landed ? `${landedLines(landed)}\\n` : '') +\n ` shelf: ${folderRef ? `in ${folderRef}` : `unfiled, at the root of your shelf (file it: vos folder move ${created.id} --to <slug>)`}\\n` +\n ` cover: ${typeof programDoc?.still === 'number' ? `${String(programDoc.still)}s` : 'the platform picks an early frame; choose one with --still <seconds>'}\\n` +\n `Iterate with: vos push ${source} --vos ${created.id}`,\n )\n return EXIT_OK\n}\n\nexport async function cmdPullProgram(argv: string[]): Promise<number> {\n const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS)\n // Positional: the tracked directory or its config.json (default cwd).\n const target = positionals[0] ?? '.'\n const dir = target.endsWith('.json') ? dirname(target) : target\n const r = createReporter(flags.json === true)\n const origin = platformOrigin({\n origin: strFlag(flags, 'origin'),\n api: strFlag(flags, 'api'),\n })\n\n const state = readSyncState(dir)\n const vosFlag = strFlag(flags, 'vos')\n const vosId = vosFlag ? parseVosId(vosFlag) : (state?.vosId ?? null)\n if (!vosId) {\n throw new UsageError(\n `no tracked vos in ${dir}/vos.json — pass --vos <id>, or fetch/push first`,\n )\n }\n const since = strFlag(flags, 'since') ?? state?.versionId ?? null\n if (!since) {\n throw new UsageError(\n `no base version in ${dir}/vos.json — pass --since <versionId>`,\n )\n }\n // The changelog walk is owner-only (edits on private work).\n const key = requireCredential(strFlag(flags, 'key'))\n\n const res = await apiJson(\n origin,\n `/api/vos/${vosId}/changes?since=${encodeURIComponent(since)}`,\n { key },\n )\n if (res.status !== 200)\n throw new Error(apiError(`pull changes for ${vosId}`, res))\n\n const head = (res.body.head ?? {}) as Record<string, unknown>\n const changes = Array.isArray(res.body.changes)\n ? (res.body.changes as VersionChange[])\n : []\n const protectedIds = Array.isArray(res.body.protected)\n ? (res.body.protected as string[])\n : []\n\n if (changes.length === 0) {\n r.done(\n { id: vosId, upToDate: true, head: head.id ?? since },\n `${vosId}: up to date (base ${since.slice(0, 8)}… is the head)`,\n )\n return EXIT_OK\n }\n\n for (const line of formatChanges(changes)) r.log(line)\n if (protectedIds.length) {\n r.log(\n `protected (human-edited — keep their values unless asked): ${protectedIds.join(', ')}`,\n )\n }\n if (res.body.truncated === true) {\n r.log('walk truncated — more versions exist; pull again after syncing')\n }\n\n if (flags.check === true) {\n r.done(\n {\n id: vosId,\n upToDate: false,\n versions: changes.length,\n head: head.id ?? null,\n protected: protectedIds,\n changes,\n },\n `${changes.length} version${changes.length === 1 ? '' : 's'} behind — run without --check to sync`,\n )\n return EXIT_OK\n }\n\n // Sync: the head config replaces config.json (the old file is kept as\n // config.backup.json), and vos.json repoints so the next push has the fresh\n // base. Your uncommitted local edits live in the backup — re-apply on top.\n const cfg = await apiJson(origin, `/api/vos/${vosId}/config`, { key })\n if (cfg.status !== 200)\n throw new Error(apiError(`fetch head config for ${vosId}`, cfg))\n const configPath = join(dir, 'config.json')\n let backedUp = false\n if (existsSync(configPath)) {\n await writeFile(join(dir, 'config.backup.json'), await readFile(configPath))\n backedUp = true\n }\n // A program DOCUMENT on the head: the user's config is the doc's\n // own (the stored config is the composed one), and doc.json comes home\n // beside it without that config.\n let headConfig = cfg.body.config as Record<string, unknown>\n const headId = typeof head.id === 'string' ? head.id : null\n if (headId) {\n const docRes = await apiJson(\n origin,\n `/api/vos/${vosId}/versions/${headId}/doc`,\n { key },\n )\n if (docRes.status === 200 && !('source' in docRes.body)) {\n const { config: own } = await writeProgramDoc(\n dir,\n migrateHostedDoc(docRes.body),\n )\n if (own) headConfig = own\n }\n }\n await writeFile(configPath, JSON.stringify(headConfig, null, 2))\n writeSyncState(dir, {\n vosId,\n versionId: typeof head.id === 'string' ? head.id : since,\n })\n\n r.done(\n {\n id: vosId,\n upToDate: false,\n versions: changes.length,\n head: head.id ?? null,\n protected: protectedIds,\n changes,\n out: configPath,\n backup: backedUp ? join(dir, 'config.backup.json') : null,\n },\n `Pulled ${changes.length} version${changes.length === 1 ? '' : 's'} → ${configPath}` +\n (backedUp ? ` (previous copy: config.backup.json)` : '') +\n `\\nRe-apply your edit on the new head, then: vos push ${configPath} --vos ${vosId}`,\n )\n return EXIT_OK\n}\n\nexport async function cmdLogin(argv: string[]): Promise<number> {\n const { flags } = parseArgs(argv, BOOLEAN_FLAGS)\n const r = createReporter(flags.json === true)\n const origin = platformOrigin({\n origin: strFlag(flags, 'origin'),\n api: strFlag(flags, 'api'),\n })\n\n // AN2: a setup link from a signed-in person's line exchanges itself for\n // a key, once, with no click. Its origin is the link's own.\n const handoffUrl = strFlag(flags, 'handoff')\n if (handoffUrl) {\n const done = await handoffLogin(handoffUrl, r)\n r.done(\n {\n path: done.path,\n origin: done.origin,\n user: done.user,\n keyName: done.keyName,\n next_step: 'the link is spent; vos push when you want the work hosted',\n },\n `Signed in${done.user ? ` as ${done.user}` : ''} — key \"${done.keyName}\" stored at ${done.path} (used by every vos platform verb). The link is spent.`,\n )\n return EXIT_OK\n }\n\n // The paste ladder keeps its lanes: an explicit --key (or a VOS_API_KEY\n // already in the env) validates and stores without any browser.\n const explicit = strFlag(flags, 'key') ?? process.env.VOS_API_KEY?.trim()\n if (explicit) return storeKey(explicit, origin, r)\n\n // Default: the browser device flow. Works TTY-less by design — that is\n // the agent path (print URL + code, the human approves, the poll lands).\n try {\n const openBrowser =\n process.stdout.isTTY === true &&\n !process.env.SSH_CONNECTION &&\n !process.env.SSH_TTY &&\n flags.json !== true &&\n flags['no-browser'] !== true\n const { path, user } = await browserLogin(origin, r, {\n label: strFlag(flags, 'label'),\n openBrowser,\n })\n r.done(\n { path, origin, user },\n `Signed in${user ? ` as ${user}` : ''} — key stored at ${path} (used by every vos platform verb)`,\n )\n return EXIT_OK\n } catch (e) {\n if (!(e instanceof LoginUnsupportedError)) throw e\n }\n\n // Older origin without the device flow — the pre-device-flow paste prompt.\n if (!process.stdin.isTTY) {\n throw new UsageError(\n 'vos login --key <vos_sk_…> (headless), or run interactively — mint a key at https://vos.so/app/api',\n )\n }\n const rl = createInterface({ input: process.stdin, output: process.stderr })\n const key = (\n await rl.question(`Paste a content key from ${origin}/app/api: `)\n ).trim()\n rl.close()\n if (!key) throw new UsageError('no key given')\n return storeKey(key, origin, r)\n}\n\n/** Validate (cheapest key-readable read) and store a pasted/env key. */\nasync function storeKey(\n key: string,\n origin: string,\n r: Reporter,\n): Promise<number> {\n const probe = await apiJson(origin, '/api/folders', { key })\n if (probe.status === 401 || probe.status === 403) {\n throw new Error(apiError('validate key', probe))\n }\n const path = writeCredential(key)\n r.done(\n { path, origin },\n `Signed in — key stored at ${path} (used by every vos platform verb)`,\n )\n return EXIT_OK\n}\n\n/**\n * A directory is a TAKE when its doc.json is a RECORDING document (it carries\n * `source`) — the deterministic sniff. A program directory may carry a\n * doc.json too (a program document, `program` + the shared layers,\n * with config.json as its config); that is a program push.\n */\nexport function isTakeDir(target: string): boolean {\n return directoryKind(target) === 'take'\n}\n\n/**\n * The program document beside a config.json, if any: doc.json without\n * `source`. On disk it omits `program.config` (config.json IS the config);\n * on the wire it carries it. Returns the doc as pushed (config attached) or\n * null when the directory has none.\n */\n/**\n * What the platform STORES for a layered program: the COMPOSED config (the\n * studio's own save shape, `lowerProgramDoc(doc).config`), never the user's\n * config alone, which lives in the document's `program.config`. A push that\n * sent the raw config stored a program whose layers the fleet never saw:\n * its still and preview rendered the ground and nothing on it, while the\n * studio (which composes on open) showed the layers. `fetch` and `pull`\n * already write `config.json` from the document's own config, so the round\n * trip is unchanged.\n */\n/** A program document's added sound, typed (the document itself is read loosely). */\nfunction soundOf(doc: Record<string, unknown>): { audio?: AudioClip[] } {\n return { audio: Array.isArray(doc.audio) ? (doc.audio as AudioClip[]) : [] }\n}\n\n/** The shared layers of a program document, as the file walker reads them. */\nfunction layersOf(doc: Record<string, unknown>): {\n overlays?: OverlayClip[]\n objects?: ObjectClip[]\n audio?: AudioClip[]\n} {\n return {\n ...soundOf(doc),\n overlays: Array.isArray(doc.overlays)\n ? (doc.overlays as OverlayClip[])\n : [],\n objects: Array.isArray(doc.objects) ? (doc.objects as ObjectClip[]) : [],\n }\n}\n\nexport function storedProgramConfig(\n config: Record<string, unknown>,\n programDoc: Record<string, unknown> | null,\n): Record<string, unknown> {\n if (!programDoc) return config\n const doc = { audio: [], ...programDoc } as never\n return lowerProgramDoc(doc).config as Record<string, unknown>\n}\n\nexport async function readProgramDoc(\n dir: string,\n config: Record<string, unknown>,\n): Promise<Record<string, unknown> | null> {\n const docPath = join(dir, 'doc.json')\n if (!existsSync(docPath)) return null\n const parsed: unknown = JSON.parse(await readFile(docPath, 'utf8'))\n if (typeof parsed !== 'object' || parsed === null || 'source' in parsed)\n return null\n const raw = parsed as Record<string, unknown>\n const program =\n raw.program && typeof raw.program === 'object'\n ? (raw.program as Record<string, unknown>)\n : {}\n return { ...raw, program: { ...program, config } }\n}\n\n/** Write a hosted program document to disk: config.json + doc.json sans config. */\n/**\n * Write a program's cover into doc.json beside its config: the existing\n * document with `still` set, or a minimal program document when there is\n * none (no `program.config` on disk; the push composes it).\n */\nexport async function setProgramStill(dir: string, t: number): Promise<void> {\n const docPath = join(dir, 'doc.json')\n let doc: Record<string, unknown> = { program: {}, audio: [] }\n if (existsSync(docPath)) {\n const parsed: unknown = JSON.parse(await readFile(docPath, 'utf8'))\n if (!parsed || typeof parsed !== 'object' || 'source' in parsed)\n throw new UsageError(\n `${docPath} is a take's document; a take's cover is its own \"still\" field`,\n )\n doc = parsed as Record<string, unknown>\n }\n await writeFile(docPath, JSON.stringify({ ...doc, still: t }, null, 2) + '\\n')\n}\n\nexport async function writeProgramDoc(\n dir: string,\n hosted: Record<string, unknown>,\n): Promise<{ config: Record<string, unknown> | null }> {\n const program =\n hosted.program && typeof hosted.program === 'object'\n ? (hosted.program as Record<string, unknown>)\n : {}\n const { config, ...rest } = program\n const onDisk = { ...hosted, program: rest }\n await writeFile(join(dir, 'doc.json'), JSON.stringify(onDisk, null, 2))\n return {\n config:\n config && typeof config === 'object'\n ? (config as Record<string, unknown>)\n : null,\n }\n}\n","/**\n * `vos login` browser flow — the RFC-8628-shaped device flow behind\n * the AgentDoor promise (\"run `vos login` and let me finish the browser\n * sign-in\"). The CLI asks the platform for a short user code + a vos_dc_\n * poll secret, shows the approval URL (the printed URL is the contract;\n * the browser launch is best-effort), and polls until a signed-in human\n * approves at /cli/auth. The key arrives exactly once and goes STRAIGHT to\n * ~/.config/vos/credentials — never into stdout, NDJSON, or logs (the\n * attribution doctrine: never print a credential).\n */\nimport { hostname } from 'node:os'\nimport { apiError, apiJson, writeCredential } from './platform'\nimport type { Reporter } from './output'\n\n/** The origin has no device-flow endpoints (older server) — caller falls\n back to the paste-a-key ladder. */\nexport class LoginUnsupportedError extends Error {\n constructor() {\n super('this origin does not support browser login')\n }\n}\n\n/** Consecutive network failures tolerated before the loop gives up. */\nconst MAX_TRANSIENT_FAILURES = 5\n/** Backoff ceiling when the server answers 429. */\nconst MAX_INTERVAL_MS = 30_000\n\nexport interface BrowserLoginOptions {\n /** Optional requester label shown on the approval page (--label). */\n label?: string\n /** Attempt the OS browser launch (TTY, local, not --json/--no-browser). */\n openBrowser: boolean\n /** Injected for tests. */\n sleep?: (ms: number) => Promise<void>\n /** Injected for tests — defaults to the real credentials file. */\n store?: (key: string) => string\n}\n\n/** Best-effort OS launch — the printed URL stays the contract (vos open). */\nasync function launchDefaultBrowser(url: string): Promise<void> {\n const opener =\n process.platform === 'darwin'\n ? 'open'\n : process.platform === 'win32'\n ? 'start'\n : 'xdg-open'\n const { exec } = await import('node:child_process')\n exec(`${opener} ${JSON.stringify(url)}`, () => {})\n}\n\n/**\n * Run the device flow to completion. Returns the credential path and the\n * signed-in display name; throws on deny/expiry/timeout with the next step\n * in words.\n */\nexport async function browserLogin(\n origin: string,\n r: Reporter,\n opts: BrowserLoginOptions,\n): Promise<{ path: string; user: string }> {\n const create = await apiJson(origin, '/api/cli/login', {\n method: 'POST',\n body: {\n hostname: hostname().slice(0, 64),\n ...(opts.label ? { label: opts.label.slice(0, 64) } : {}),\n },\n })\n if (create.status === 404) throw new LoginUnsupportedError()\n if (create.status !== 201) throw new Error(apiError('start login', create))\n const code = create.body.code as string\n const secret = create.body.secret as string\n const verifyUrl = create.body.verifyUrl as string\n const expiresAt = Date.parse(String(create.body.expiresAt ?? ''))\n const baseIntervalMs =\n (typeof create.body.interval === 'number' ? create.body.interval : 3) * 1000\n if (!code || !secret || !verifyUrl || Number.isNaN(expiresAt)) {\n throw new Error('start login → malformed response from the platform')\n }\n\n // The agent relay: everything the human needs, nothing secret.\n r.event({ event: 'login_await', url: verifyUrl, code, expiresAt })\n r.log(`Confirm this code in the browser: ${code}`)\n r.log(`Sign in at ${verifyUrl}`)\n if (opts.openBrowser) void launchDefaultBrowser(verifyUrl)\n r.log('Waiting for approval… (Ctrl-C to cancel)')\n\n const sleep =\n opts.sleep ?? ((ms: number) => new Promise((res) => setTimeout(res, ms)))\n let intervalMs = baseIntervalMs\n let failures = 0\n let capNoted = false\n while (Date.now() < expiresAt) {\n await sleep(intervalMs)\n let res\n try {\n res = await apiJson(origin, '/api/cli/login/poll', {\n method: 'POST',\n body: { secret },\n })\n failures = 0\n } catch (e) {\n if (++failures >= MAX_TRANSIENT_FAILURES) {\n throw new Error(\n `lost the connection while waiting (${e instanceof Error ? e.message : String(e)}) — run \\`vos login\\` again`,\n )\n }\n continue\n }\n const status = res.body.status as string | undefined\n if (res.status === 200 && status === 'pending') {\n intervalMs = baseIntervalMs\n continue\n }\n if (res.status === 200 && status === 'ok') {\n // The one delivery — straight to disk, never through any output path.\n const path = (opts.store ?? writeCredential)(res.body.key as string)\n const user =\n typeof res.body.user === 'object' && res.body.user !== null\n ? ((res.body.user as { name?: string }).name ?? '')\n : ''\n return { path, user }\n }\n if (res.status === 429) {\n // key_limit carries the fix in words and keeps the approval alive —\n // say it once, keep polling so a revoke over on /app/api resumes us.\n if (status === 'key_limit' && !capNoted) {\n capNoted = true\n r.log(`${res.body.error as string} — ${res.body.hint as string}`)\n }\n intervalMs = Math.min(intervalMs * 2, MAX_INTERVAL_MS)\n continue\n }\n if (res.status === 403 && status === 'denied') {\n throw new Error('the sign-in was denied in the browser')\n }\n throw new Error(\n typeof res.body.error === 'string'\n ? res.body.error\n : apiError('poll login', res),\n )\n }\n throw new Error(\n 'no approval within 15 minutes — run `vos login` again, or mint a key at https://vos.so/app/api and pass --key',\n )\n}\n\n/** The handoff URL's shape: the platform origin, `/h/`, a vos_ho_ token. */\nconst HANDOFF_URL = /^(https?:\\/\\/[^/]+)\\/h\\/(vos_ho_[A-Za-z0-9_-]+)$/\n\n/**\n * Parse `vos login --handoff <url>`'s argument: the origin is the link's\n * own (the platform that minted it), the token its last segment. Pure.\n */\nexport function parseHandoffUrl(\n url: string,\n): { origin: string; token: string } | null {\n const m = HANDOFF_URL.exec(url.trim())\n return m ? { origin: m[1], token: m[2] } : null\n}\n\n/**\n * `vos login --handoff <url>` (AN2): a signed-in person's line carries a\n * SETUP GRANT, and this exchanges it, once, for a content key named for\n * this machine, with no click from the person. The token is the link's\n * last segment; it goes to the exchange route and nowhere else, and the\n * key it answers goes straight to disk. A spent, expired or unknown link\n * fails in words with the next step, which is the ordinary `vos login`.\n */\nexport async function handoffLogin(\n url: string,\n r: Reporter,\n opts: { store?: (key: string) => string } = {},\n): Promise<{ path: string; user: string; keyName: string; origin: string }> {\n const parsed = parseHandoffUrl(url)\n if (!parsed)\n throw new Error(\n '--handoff wants the link a person copied from vos.so, https://vos.so/h/vos_ho_…',\n )\n r.log(`exchanging the setup link at ${parsed.origin}…`)\n const res = await apiJson(parsed.origin, '/api/cli/login/exchange', {\n method: 'POST',\n body: { token: parsed.token, hostname: hostname().slice(0, 64) },\n })\n if (res.status === 200 && res.body.status === 'ok') {\n const path = (opts.store ?? writeCredential)(res.body.key as string)\n const user =\n typeof res.body.user === 'object' && res.body.user !== null\n ? ((res.body.user as { name?: string }).name ?? '')\n : ''\n return {\n path,\n user,\n keyName: String(res.body.keyName ?? ''),\n origin: parsed.origin,\n }\n }\n if (res.status === 404 && !res.body.status) {\n // An origin from before the route.\n throw new Error(\n `${parsed.origin} does not support setup links yet — run \\`vos login\\` instead`,\n )\n }\n const said =\n typeof res.body.error === 'string'\n ? res.body.error\n : apiError('exchange', res)\n const hint = typeof res.body.hint === 'string' ? ` ${res.body.hint}` : ''\n throw new Error(`${said}${hint}`)\n}\n","/**\n * `vos asset` — the work verbs on individual assets. Deliberately\n * NOT a folder verb: folders are shelf structure (the human's, add-only),\n * assets are WORK — and renaming your own work is an ordinary edit.\n *\n * vos asset rename <assetId> <newname.ext> [--json]\n * vos asset push <file...> [--folder <folderId|slug>] [--json]\n *\n * rename is the CLI face of `PATCH /assets/:id { filename }`: a\n * one-column update, bytes and fileUrl untouched. The server holds the\n * extension to the asset's category (a recipe stays .md).\n *\n * push sends each file through the platform's one upload door (declare,\n * parts, seal), filed as a library file: models, pictures and SVGs, fonts,\n * HDR maps, sound, video, captions and recipes (though `vos recipe push`\n * is the recipe verb, with replace-in-place). The platform reads what it\n * stores, so the kind and the stored name come back from it, and a file it\n * has no use for is refused in words before anything is sent\n * (`GET /api/limits` lists the kinds and their caps). The same bytes pushed\n * twice are the same file. Files upload one by one and a refusal names the\n * file it stopped on, so a partial push is legible, never silent.\n */\nimport { createHash } from 'node:crypto'\nimport { readFileSync } from 'node:fs'\nimport { basename } from 'node:path'\nimport { MEDIA_HEAD_BYTES, nameForType, resolveMediaType } from './container'\nimport { uploadAsset } from './uploadAsset'\nimport { UsageError, parseArgs, strFlag } from './args'\nimport { listFolders, resolveFolder } from './folder'\nimport { EXIT_OK, createReporter } from './output'\nimport {\n apiError,\n apiJson,\n platformOrigin,\n requireCredential,\n} from './platform'\n\nconst BOOLEAN_FLAGS = new Set(['json', 'help'])\n\nasync function cmdRename(argv: string[]): Promise<number> {\n const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS)\n const [assetId, filename] = positionals\n if (!assetId || !filename) {\n throw new UsageError('vos asset rename <assetId> <newname.ext>')\n }\n const r = createReporter(flags.json === true)\n const origin = platformOrigin({\n origin: strFlag(flags, 'origin'),\n api: strFlag(flags, 'api'),\n })\n const key = requireCredential(strFlag(flags, 'key'))\n\n const res = await apiJson(origin, `/api/assets/${assetId}`, {\n method: 'PATCH',\n key,\n body: { filename },\n })\n if (res.status !== 200) throw new Error(apiError(`rename ${assetId}`, res))\n r.done(\n { id: assetId, filename: res.body.filename },\n `renamed asset ${assetId} → ${String(res.body.filename)}`,\n )\n return EXIT_OK\n}\n\nasync function cmdPush(argv: string[]): Promise<number> {\n const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS)\n if (positionals.length === 0) {\n throw new UsageError('vos asset push <file...> [--folder <folderId|slug>]')\n }\n const r = createReporter(flags.json === true)\n const origin = platformOrigin({\n origin: strFlag(flags, 'origin'),\n api: strFlag(flags, 'api'),\n })\n const key = requireCredential(strFlag(flags, 'key'))\n const folderRef = strFlag(flags, 'folder')\n const folder = folderRef\n ? resolveFolder(await listFolders(origin, key), folderRef)\n : null\n\n // What the platform answered per file, in the result as well as the log:\n // a caller reading JSON (an agent) must not lose the note that an SVG's\n // scripts were removed, or that the file was already there.\n const uploaded: {\n id: string\n filename: string\n kind: string\n url: string\n reused?: true\n notes?: string[]\n }[] = []\n for (const file of positionals) {\n const name = basename(file)\n const body = readFileSync(file)\n // Sound and video are typed by their bytes here too, so a clip is sent\n // under the name its container earns. Everything else goes as it is\n // named, and the platform answers what it turned out to be.\n const media = resolveMediaType({\n head: body.subarray(0, MEDIA_HEAD_BYTES),\n filename: name,\n })\n const isMedia = /^(audio|video)\\//.test(media.type)\n const sent = isMedia ? nameForType(name, media.type) : name\n let put\n try {\n put = await uploadAsset({ origin, key }, new Uint8Array(body), {\n filename: sent,\n ...(isMedia ? { contentType: media.type } : {}),\n contentHash: createHash('sha256').update(body).digest('hex'),\n intent: 'library',\n ...(folder ? { folderId: folder.id } : {}),\n })\n } catch (e) {\n const landed = uploaded.length\n ? ` (${uploaded.length} of ${positionals.length} landed before it)`\n : ''\n throw new Error(\n `push ${name}${landed}: ${e instanceof Error ? e.message : String(e)}`,\n )\n }\n const stored = put.filename || sent\n uploaded.push({\n id: put.id,\n filename: stored,\n kind: put.kind,\n url: put.url,\n ...(put.reused ? { reused: true as const } : {}),\n ...(put.notes.length ? { notes: put.notes } : {}),\n })\n r.log(\n `uploaded ${stored} (${put.id})${put.reused ? ' — already on your shelf' : ''} ${put.url}`,\n )\n for (const note of put.notes) r.log(` note: ${note}`)\n }\n r.done(\n {\n uploaded,\n count: uploaded.length,\n folder: folder?.slug ?? null,\n },\n `pushed ${uploaded.length} asset${uploaded.length === 1 ? '' : 's'}${\n folder ? ` into ${folder.slug}` : ''\n }`,\n )\n return EXIT_OK\n}\n\nexport async function cmdAsset(argv: string[]): Promise<number> {\n const sub = argv[0]\n const rest = argv.slice(1)\n switch (sub) {\n case 'rename':\n return cmdRename(rest)\n case 'push':\n return cmdPush(rest)\n default:\n throw new UsageError(\n 'vos asset <rename|push> — rename one of your assets, or push files onto the shelf (vos asset push <file...> [--folder <slug>])',\n )\n }\n}\n","/**\n * `vos delete <vosId|watch-url|dir> [--yes] [--dry-run]`: move a vos to\n * Trash on vos.so.\n *\n * Deleting used to be the one push that could not be undone, and the verb\n * said so. It no longer is: vos.so moves a deleted vos to Trash, where it\n * stays restorable until the date the delete prints (`vos restore <id>`\n * brings it back as it was). Nothing a key can do is final; only the person\n * can empty Trash, on the web.\n *\n * It still asks, because consent is not the same thing as an undo: on a\n * terminal it names the vos and waits for a yes, and headless it needs\n * `--yes` said out loud. `--dry-run` names what would move and moves\n * nothing, so an agent asked to clean up can show the list first. A\n * directory that tracked the vos is unlinked (its vos.json removed), or the\n * next push would iterate a vos that is in Trash.\n */\nimport { existsSync, rmSync, statSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { createInterface } from 'node:readline/promises'\nimport { UsageError, parseArgs, strFlag } from './args'\nimport { EXIT_OK, createReporter } from './output'\nimport {\n SYNC_STATE_NAME,\n apiError,\n apiJson,\n clientId,\n parseVosId,\n platformOrigin,\n readSyncState,\n requireCredential,\n} from './platform'\nimport { restoreDate } from './trash'\n\nconst BOOLEAN_FLAGS = new Set(['json', 'help', 'yes', 'dry-run'])\n\nexport async function cmdDelete(argv: string[]): Promise<number> {\n const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS)\n const target = positionals[0]\n if (!target)\n throw new UsageError(\n 'vos delete <vosId|watch-url|dir> [--yes] [--dry-run] [--json]',\n )\n const r = createReporter(flags.json === true)\n const origin = platformOrigin({\n origin: strFlag(flags, 'origin'),\n api: strFlag(flags, 'api'),\n }).replace(/\\/+$/, '')\n const key = requireCredential(strFlag(flags, 'key'))\n\n const dir =\n existsSync(target) && statSync(target).isDirectory() ? target : null\n const vosId = dir ? readSyncState(dir)?.vosId : parseVosId(target)\n if (!vosId)\n throw new UsageError(\n `${target} tracks no vos (no ${SYNC_STATE_NAME}): pass the vos id or its watch URL`,\n )\n\n const meta = await apiJson(origin, `/api/vos/${vosId}`, { key })\n if (meta.status !== 200) throw new Error(apiError(`read ${vosId}`, meta))\n const vos = (meta.body.vos ?? {}) as Record<string, unknown>\n const title = typeof vos.title === 'string' ? vos.title : vosId\n\n if (flags['dry-run'] === true) {\n r.done(\n { id: vosId, title, deleted: false, dryRun: true },\n `would move \"${title}\" (${vosId}) to Trash; nothing was changed`,\n )\n return EXIT_OK\n }\n\n if (flags.yes !== true) {\n if (!process.stdin.isTTY)\n throw new UsageError(\n `\"${title}\" (${vosId}) would move to Trash: re-run with --yes to confirm, or --dry-run to only look`,\n )\n const rl = createInterface({ input: process.stdin, output: process.stderr })\n const answer = await rl.question(\n `Move \"${title}\" (${vosId}) to Trash? It stays restorable there for a while (vos restore ${vosId}). [y/N] `,\n )\n rl.close()\n if (!/^y(es)?$/i.test(answer.trim())) {\n r.done({ id: vosId, deleted: false }, 'kept: nothing was deleted')\n return EXIT_OK\n }\n }\n\n const res = await apiJson(origin, `/api/vos/${vosId}`, {\n method: 'DELETE',\n key,\n // Who did it, for the person reading Trash later (display only).\n headers: { 'x-vos-client': clientId() },\n })\n if (res.status !== 200 && res.status !== 204)\n throw new Error(apiError(`delete ${vosId}`, res))\n let unlinked = false\n if (dir) {\n rmSync(join(dir, SYNC_STATE_NAME), { force: true })\n unlinked = true\n }\n const trashed = res.body.trashed === true\n const restoreUntil =\n typeof res.body.restoreUntil === 'string' ? res.body.restoreUntil : null\n const tail = unlinked ? `; ${dir} no longer tracks it` : ''\n r.done(\n {\n id: vosId,\n title,\n deleted: true,\n trashed,\n ...(restoreUntil ? { restoreUntil } : {}),\n unlinked,\n },\n trashed\n ? `moved \"${title}\" (${vosId}) to Trash${\n restoreUntil ? `, restorable until ${restoreDate(restoreUntil)}` : ''\n }: vos restore ${vosId}${tail}`\n : // A vos with no version (a refused hosted take's empty shell) has\n // nothing to restore, so the platform erases it.\n `deleted \"${title}\" (${vosId})${tail}`,\n )\n return EXIT_OK\n}\n","/**\n * Trash on vos.so, from the command line.\n *\n * vos trash what is in Trash, by whom, until when\n * vos restore <id|watch-url> [...] bring those back, as they were\n * vos trash restore --since <1h|ISO> undo everything a key trashed\n *\n * Deleting on vos.so moves a thing to Trash; these are the verbs that see\n * it and undo it. There is deliberately no `vos trash empty`: making a\n * delete final is the person's act, on the web, and no key, flag or verb\n * here can do it.\n */\nimport { UsageError, parseArgs, strFlag } from './args'\nimport { EXIT_OK, createReporter } from './output'\nimport {\n apiError,\n apiJson,\n parseVosId,\n platformOrigin,\n requireCredential,\n} from './platform'\n\nconst BOOLEAN_FLAGS = new Set(['json', 'help'])\n\nexport interface TrashEntry {\n kind: 'vos' | 'folder' | 'asset'\n id: string\n title: string\n deletedAt: string\n restoreUntil: string\n deletedVia: string | null\n deletedKeyId: string | null\n deletedKeyName: string | null\n deletedClient: string | null\n members: { voses: number; assets: number; folders: number } | null\n}\n\nconst MONTHS = [\n 'Jan',\n 'Feb',\n 'Mar',\n 'Apr',\n 'May',\n 'Jun',\n 'Jul',\n 'Aug',\n 'Sep',\n 'Oct',\n 'Nov',\n 'Dec',\n]\n\n/** `14 Oct`, with the year when it is not this one. A date, never a duration. */\nexport function restoreDate(iso: string, now = new Date()): string {\n const d = new Date(iso)\n if (Number.isNaN(d.getTime())) return iso\n const day = `${d.getUTCDate()} ${MONTHS[d.getUTCMonth()]}`\n return d.getUTCFullYear() === now.getUTCFullYear()\n ? day\n : `${day} ${d.getUTCFullYear()}`\n}\n\n/** Who moved it, in words: a tool, a key by name, or the person. */\nexport function trashedBy(entry: {\n deletedVia: string | null\n deletedKeyName: string | null\n deletedClient: string | null\n}): string {\n if (entry.deletedVia === 'key') {\n return entry.deletedClient ?? entry.deletedKeyName ?? 'a key'\n }\n if (entry.deletedVia === 'admin') return 'an admin'\n if (entry.deletedVia === 'service') return 'vos.so'\n return 'you'\n}\n\n/**\n * `--since` as a moment: `90s`, `30m`, `1h`, `2d`, or an ISO timestamp.\n * Null when it is none of those.\n */\nexport function sinceMoment(value: string, now = new Date()): Date | null {\n const rel = /^(\\d+(?:\\.\\d+)?)(s|m|h|d)$/.exec(value.trim())\n if (rel) {\n const unit = { s: 1e3, m: 60e3, h: 3600e3, d: 86400e3 }[\n rel[2] as 's' | 'm' | 'h' | 'd'\n ]\n return new Date(now.getTime() - Number(rel[1]) * unit)\n }\n const at = new Date(value)\n return Number.isNaN(at.getTime()) ? null : at\n}\n\nfunction words(kind: TrashEntry['kind']): string {\n return kind === 'vos' ? 'vos' : kind === 'folder' ? 'project' : 'file'\n}\n\nfunction context(flags: Record<string, string | true>) {\n const origin = platformOrigin({\n origin: strFlag(flags, 'origin'),\n api: strFlag(flags, 'api'),\n }).replace(/\\/+$/, '')\n return { origin, key: requireCredential(strFlag(flags, 'key')) }\n}\n\nasync function readTrash(ctx: {\n origin: string\n key: string\n}): Promise<TrashEntry[]> {\n const res = await apiJson(ctx.origin, '/api/trash', { key: ctx.key })\n if (res.status !== 200) throw new Error(apiError('read Trash', res))\n return (res.body.entries ?? []) as TrashEntry[]\n}\n\n/** POST a restore until the platform says it is done (bounded). */\nasync function restore(\n ctx: { origin: string; key: string },\n body: Record<string, unknown>,\n): Promise<{ restored: { kind: string; id: string }[]; missing: unknown[] }> {\n let restored: { kind: string; id: string }[] = []\n let missing: unknown[] = []\n for (let pass = 0; pass < 100; pass++) {\n const res = await apiJson(ctx.origin, '/api/trash/restore', {\n method: 'POST',\n key: ctx.key,\n body,\n })\n if (res.status !== 200) throw new Error(apiError('restore', res))\n if (pass === 0) {\n restored = (res.body.restored ?? []) as { kind: string; id: string }[]\n missing = (res.body.missing ?? []) as unknown[]\n }\n if (res.body.done !== false) break\n }\n return { restored, missing }\n}\n\n/** `vos trash` and `vos trash restore --since …`. */\nexport async function cmdTrash(argv: string[]): Promise<number> {\n const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS)\n const r = createReporter(flags.json === true)\n const ctx = context(flags)\n\n if (positionals[0] === 'restore') {\n const raw = strFlag(flags, 'since')\n const since = raw ? sinceMoment(raw) : null\n if (!since)\n throw new UsageError(\n 'vos trash restore --since <30m|1h|2d|ISO time> [--by <key name>] [--json]',\n )\n const by = strFlag(flags, 'by')\n let keyId: string | null = null\n if (by) {\n const match = (await readTrash(ctx)).find(\n (e) => e.deletedKeyName === by || e.deletedKeyId?.startsWith(by),\n )\n keyId = match?.deletedKeyId ?? null\n if (!keyId)\n throw new Error(`nothing in Trash was moved there by a key named ${by}`)\n } else {\n // The key this CLI is signed in with: undoing your own deletes.\n const me = await apiJson(ctx.origin, '/api/user/whoami', {\n key: ctx.key,\n })\n keyId = ((me.body.key ?? null) as { id?: string } | null)?.id ?? null\n if (me.status !== 200 || !keyId)\n throw new Error(\n 'could not tell which key this is: pass --by <key name> (vos trash lists them)',\n )\n }\n const done = await restore(ctx, { keyId, since: since.toISOString() })\n r.done(\n { restored: done.restored, count: done.restored.length },\n done.restored.length\n ? `restored ${done.restored.length} item${done.restored.length === 1 ? '' : 's'} moved to Trash since ${since.toISOString()}`\n : `nothing was moved to Trash by that key since ${since.toISOString()}`,\n )\n return EXIT_OK\n }\n if (positionals[0])\n throw new UsageError(\n `vos trash has no \"${positionals[0]}\": vos trash, or vos trash restore --since <time>. Trash is emptied by a person, at vos.so/app/trash`,\n )\n\n const entries = await readTrash(ctx)\n if (flags.json === true) {\n r.done({ entries, count: entries.length }, '')\n return EXIT_OK\n }\n if (entries.length === 0) {\n r.done({ entries, count: 0 }, 'Trash is empty')\n return EXIT_OK\n }\n const lines = entries.map((e) => {\n const inside = e.members\n ? ` (${e.members.voses} vos, ${e.members.assets} files)`\n : ''\n return ` ${words(e.kind).padEnd(7)} ${e.id} \"${e.title}\"${inside}: moved by ${trashedBy(e)}, restorable until ${restoreDate(e.restoreUntil)}`\n })\n r.done(\n { entries, count: entries.length },\n `${entries.length} in Trash\\n${lines.join('\\n')}\\nrestore one: vos restore <id> (emptying Trash is the person's act, at vos.so/app/trash)`,\n )\n return EXIT_OK\n}\n\n/** `vos restore <id|watch-url> […]`. */\nexport async function cmdRestore(argv: string[]): Promise<number> {\n const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS)\n if (positionals.length === 0)\n throw new UsageError('vos restore <id|watch-url> [...] [--json]')\n const r = createReporter(flags.json === true)\n const ctx = context(flags)\n\n // An id says nothing about its kind: Trash does.\n const entries = await readTrash(ctx)\n const wanted = positionals.map((p) => parseVosId(p) ?? p)\n const units = wanted.map((id) => {\n const entry = entries.find((e) => e.id === id)\n if (!entry)\n throw new Error(\n `${id} is not in Trash (vos trash lists what is; something inside a trashed project comes back with the project)`,\n )\n return { kind: entry.kind, id: entry.id, title: entry.title }\n })\n const done = await restore(ctx, {\n ids: units.map(({ kind, id }) => ({ kind, id })),\n })\n const names = units.map((u) => `\"${u.title}\"`).join(', ')\n r.done(\n { restored: done.restored, count: done.restored.length },\n `restored ${names}`,\n )\n return EXIT_OK\n}\n","/**\n * `vos build <program.mjs> [--out config.json]` — author a program as real\n * module code and get the wire's config.\n *\n * A VosConfigJson carries its functions as STRINGS, so every port wrote a\n * build script that stringified them, and each one learned the same traps\n * by hand: a function that reads a constant from module scope works in Node\n * and throws in the page (the string travels without its closure), method\n * shorthand does not survive `toString()` as an expression, TypeScript\n * syntax passes the editor and dies in the browser. This verb is that build\n * script, once: it imports the module, stringifies each function, refuses\n * what cannot run on its own, and records where each function lives so an\n * error the engine reports as `createContent:12` can be found in the file.\n */\nimport { readFileSync, writeFileSync } from 'node:fs'\nimport { basename, dirname, join, resolve } from 'node:path'\nimport { pathToFileURL } from 'node:url'\nimport { parse } from 'acorn'\nimport { fullAncestor } from 'acorn-walk'\nimport { UsageError, parseArgs, strFlag } from './args'\nimport { EXIT_ERROR, EXIT_OK, createReporter } from './output'\n\n/** The config keys whose values are functions on the wire. */\nexport const FUNCTION_KEYS = [\n 'setup',\n 'createContent',\n 'createTimeline',\n 'onFrame',\n 'retime',\n] as const\n\n/** Names a program may read without declaring them: the page's globals. */\nconst PAGE_GLOBALS = new Set([\n 'window',\n 'document',\n 'navigator',\n 'location',\n 'performance',\n 'requestAnimationFrame',\n 'cancelAnimationFrame',\n 'devicePixelRatio',\n 'Image',\n 'ImageData',\n 'ImageBitmap',\n 'createImageBitmap',\n 'OffscreenCanvas',\n 'HTMLCanvasElement',\n 'CanvasRenderingContext2D',\n 'Path2D',\n 'DOMMatrix',\n 'FontFace',\n 'Blob',\n 'URL',\n 'fetch',\n 'Response',\n 'TextEncoder',\n 'TextDecoder',\n 'AudioContext',\n 'OfflineAudioContext',\n 'getComputedStyle',\n 'matchMedia',\n 'atob',\n 'btoa',\n])\nconst JS_GLOBALS = new Set(Object.getOwnPropertyNames(globalThis))\nJS_GLOBALS.add('undefined')\nJS_GLOBALS.add('arguments')\n\nexport interface BuildProblem {\n fn: string\n message: string\n}\n\n/**\n * A function's own source as an EXPRESSION: arrow functions and `function`\n * expressions are already one; method shorthand (`createContent(ctx) {…}`,\n * `async setup(ctx) {…}`) is rewritten to a `function` expression.\n */\nexport function functionSource(fn: (...args: never[]) => unknown): string {\n const src = fn.toString()\n if (parsesAsExpression(src)) return src\n const asyncMethod = /^async\\s+/.test(src)\n const body = asyncMethod ? src.replace(/^async\\s+/, '') : src\n const candidate = `${asyncMethod ? 'async ' : ''}function ${body}`\n if (parsesAsExpression(candidate)) return candidate\n return src\n}\n\nfunction parsesAsExpression(src: string): boolean {\n try {\n parse(`(${src})`, { ecmaVersion: 'latest' })\n return true\n } catch {\n return false\n }\n}\n\n/**\n * The names a function reads that it neither declares nor gets from the\n * page (pure). Declarations count anywhere in the function (a deliberate\n * over-approximation: a name declared in any inner scope is not reported),\n * so what is left is what the string would carry no value for: module\n * constants, imports, helpers defined beside it.\n */\nexport function freeIdentifiers(src: string): string[] {\n const ast = parse(`(${src})`, { ecmaVersion: 'latest' })\n const declared = new Set<string>()\n const read = new Set<string>()\n const addPattern = (p: any): void => {\n if (!p) return\n if (p.type === 'Identifier') declared.add(p.name)\n else if (p.type === 'ObjectPattern')\n for (const prop of p.properties)\n addPattern(prop.type === 'RestElement' ? prop.argument : prop.value)\n else if (p.type === 'ArrayPattern')\n for (const el of p.elements) addPattern(el)\n else if (p.type === 'RestElement') addPattern(p.argument)\n else if (p.type === 'AssignmentPattern') addPattern(p.left)\n }\n fullAncestor(ast, (node: any, _state: unknown, ancestors: any[]) => {\n if (\n node.type === 'FunctionDeclaration' ||\n node.type === 'FunctionExpression' ||\n node.type === 'ArrowFunctionExpression'\n ) {\n if (node.id) declared.add(node.id.name)\n for (const p of node.params) addPattern(p)\n } else if (node.type === 'VariableDeclarator') addPattern(node.id)\n else if (node.type === 'ClassDeclaration' && node.id)\n declared.add(node.id.name)\n else if (node.type === 'CatchClause') addPattern(node.param)\n else if (node.type === 'Identifier') {\n const parent = ancestors[ancestors.length - 2]\n if (!parent) return\n if (\n parent.type === 'MemberExpression' &&\n parent.property === node &&\n !parent.computed\n )\n return\n if (\n (parent.type === 'Property' ||\n parent.type === 'MethodDefinition' ||\n parent.type === 'PropertyDefinition') &&\n parent.key === node &&\n !parent.computed &&\n !(parent.type === 'Property' && parent.shorthand)\n )\n return\n if (\n parent.type === 'LabeledStatement' ||\n parent.type === 'BreakStatement' ||\n parent.type === 'ContinueStatement'\n )\n return\n if (parent.type === 'MetaProperty') return\n read.add(node.name)\n }\n })\n return [...read]\n .filter(\n (n) => !declared.has(n) && !JS_GLOBALS.has(n) && !PAGE_GLOBALS.has(n),\n )\n .sort()\n}\n\nexport interface BuiltProgram {\n config: Record<string, unknown>\n /** Each function's place in the module, 1-based, or absent if not found. */\n sources: Record<string, { file: string; line: number } | null>\n problems: BuildProblem[]\n}\n\n/**\n * Turn a program module's export into the wire's config (pure apart from\n * `toString`). `file` and `text` locate each function in the source.\n */\nexport function buildProgram(\n program: Record<string, unknown>,\n file: string,\n text: string,\n): BuiltProgram {\n const problems: BuildProblem[] = []\n const sources: BuiltProgram['sources'] = {}\n\n const stringify = (fn: unknown, name: string): string | undefined => {\n if (fn === undefined) return undefined\n if (typeof fn === 'string') return fn\n if (typeof fn !== 'function') {\n problems.push({\n fn: name,\n message: `must be a function, got ${typeof fn}`,\n })\n return undefined\n }\n const raw = fn.toString()\n const src = functionSource(fn as (...a: never[]) => unknown)\n const at = text.indexOf(raw)\n sources[name] =\n at >= 0 ? { file, line: text.slice(0, at).split('\\n').length } : null\n let free: string[]\n try {\n free = freeIdentifiers(src)\n } catch (e) {\n problems.push({\n fn: name,\n message: `does not parse as JavaScript the page can run: ${(e as Error).message}`,\n })\n return src\n }\n for (const n of free) {\n problems.push({\n fn: name,\n message: `reads \\`${n}\\` from outside the function; the string travels without it. Move it inside the function, or put its value in data and read ctx.data.`,\n })\n }\n return src\n }\n\n const out: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(program)) {\n if ((FUNCTION_KEYS as readonly string[]).includes(key)) {\n const s = stringify(value, key)\n if (s !== undefined) out[key] = s\n } else if (key === 'stack' && Array.isArray(value)) {\n out.stack = value.map((entry: Record<string, unknown>, i: number) => {\n const e: Record<string, unknown> = { ...entry }\n for (const k of FUNCTION_KEYS) {\n if (k in e) {\n const s = stringify(e[k], `stack[${String(entry.id ?? i)}].${k}`)\n if (s !== undefined) e[k] = s\n }\n }\n return e\n })\n } else {\n out[key] = value\n }\n }\n\n // Data, params and the rest ride as JSON: a function or a class instance\n // in them would vanish on the way.\n for (const key of Object.keys(out)) {\n if ((FUNCTION_KEYS as readonly string[]).includes(key) || key === 'stack')\n continue\n const bad = nonJson(out[key], key)\n if (bad) problems.push({ fn: key, message: bad })\n }\n return { config: out, sources, problems }\n}\n\nfunction nonJson(value: unknown, path: string): string | null {\n if (value === null) return null\n const t = typeof value\n if (t === 'function')\n return `${path} is a function; only the hooks (${FUNCTION_KEYS.join(', ')}) may be`\n if (t === 'number' && !Number.isFinite(value as number))\n return `${path} is ${String(value)}, which JSON cannot carry`\n if (t === 'undefined' || t === 'symbol' || t === 'bigint')\n return `${path} is ${t}, which JSON cannot carry`\n if (Array.isArray(value)) {\n for (let i = 0; i < value.length; i++) {\n const r = nonJson(value[i], `${path}[${i}]`)\n if (r) return r\n }\n return null\n }\n if (t === 'object') {\n const proto = Object.getPrototypeOf(value)\n if (proto !== Object.prototype && proto !== null)\n return `${path} is a ${proto?.constructor?.name ?? 'class'} instance; use plain objects and arrays`\n for (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n const r = nonJson(v, `${path}.${k}`)\n if (r) return r\n }\n }\n return null\n}\n\nconst BOOLEAN_FLAGS = new Set(['json', 'help'])\n\nexport async function cmdBuild(argv: string[]): Promise<number> {\n const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS)\n const source = positionals[0]\n if (!source)\n throw new UsageError('vos build <program.mjs> [--out config.json] [--json]')\n const r = createReporter(flags.json === true)\n const file = resolve(source)\n const text = readFileSync(file, 'utf8')\n // A query busts the module cache, so a second build in one process reads\n // the edited file.\n const mod = (await import(`${pathToFileURL(file).href}?t=${Date.now()}`)) as {\n default?: unknown\n program?: unknown\n }\n const program = (mod.default ?? mod.program) as Record<string, unknown>\n if (!program || typeof program !== 'object')\n throw new UsageError(\n `${source} exports no program: \\`export default { version: 2, duration, camera, createContent, createTimeline, … }\\``,\n )\n\n const built = buildProgram(program, basename(file), text)\n for (const p of built.problems) r.log(`error ${p.fn}: ${p.message}`)\n if (built.problems.length) {\n r.done(\n { ok: false, problems: built.problems },\n `${source}: ${built.problems.length} problem${built.problems.length === 1 ? '' : 's'}, nothing written`,\n )\n return EXIT_ERROR\n }\n\n const out = resolve(\n strFlag(flags, 'out') ?? join(dirname(file), 'config.json'),\n )\n writeFileSync(out, JSON.stringify(built.config, null, 2) + '\\n')\n const sidecar = out.replace(/\\.json$/, '') + '.sources.json'\n writeFileSync(sidecar, JSON.stringify(built.sources, null, 2) + '\\n')\n for (const [fn, at] of Object.entries(built.sources)) {\n if (at) r.log(` ${fn} → ${at.file}:${at.line}`)\n }\n r.done(\n { ok: true, out, sources: sidecar, functions: Object.keys(built.sources) },\n `Wrote ${out} (${Object.keys(built.sources).length} functions; an engine error at fn:N is that function's line N, from the line above)`,\n )\n return EXIT_OK\n}\n","/**\n * `vos compare <program> --against <their render>` — the port's eyes.\n *\n * Every port compared its frames against the source's render by hand: an\n * ffmpeg line per time, an SSIM loop, a side-by-side to look at. This verb is\n * that loop. At each sampled time it takes the source frame from the render,\n * captures the program's frame through the engine's own still, scores the\n * pair (SSIM, ffmpeg's filter) and writes a sheet: source | vos | difference.\n * It exits non-zero when ANY frame falls under the threshold, because a\n * missing element is one frame's failure that an average would hide.\n */\nimport { spawnSync } from 'node:child_process'\nimport { existsSync, mkdirSync, statSync, writeFileSync } from 'node:fs'\nimport { dirname, join, resolve } from 'node:path'\nimport { UsageError, parseArgs, strFlag } from './args'\nimport { EXIT_ERROR, EXIT_OK, createReporter } from './output'\nimport { launchBrowser } from '../browser'\nimport { configDuration, loadVosConfig } from '../loadConfig'\nimport { parseTimes } from '../outputs'\nimport { programAssets } from '../programAssets'\nimport { reencodeStill, renderStill } from '../render'\nimport { platformOrigin, resolveCredential } from './platform'\n\nconst BOOLEAN_FLAGS = new Set(['json', 'help'])\n\nexport interface FrameScore {\n t: number\n ssim: number\n sheet: string\n}\n\n/** Default sample times: every `every` seconds, centred in each step (pure). */\nexport function sampleTimes(duration: number, every: number): number[] {\n const step = every > 0 ? every : 1\n const out: number[] = []\n for (let t = step / 2; t < duration; t += step) out.push(Number(t.toFixed(3)))\n return out.length ? out : [Number((duration / 2).toFixed(3))]\n}\n\n/** Parse ffmpeg's ssim summary line (pure). */\nexport function parseSsim(stderr: string): number | null {\n const m = /All:([0-9.]+)/.exec(stderr)\n return m ? Number(m[1]) : null\n}\n\n/** The verdict over a run (pure): every frame must clear the threshold. */\nexport function compareVerdict(scores: FrameScore[], threshold: number) {\n const values = scores.map((s) => s.ssim)\n const min = values.length ? Math.min(...values) : 0\n const mean = values.length\n ? values.reduce((a, b) => a + b, 0) / values.length\n : 0\n const failing = scores.filter((s) => s.ssim < threshold).map((s) => s.t)\n return { min, mean, failing, pass: failing.length === 0 && values.length > 0 }\n}\n\nfunction ffmpeg(args: string[]): { ok: boolean; stderr: string } {\n const res = spawnSync('ffmpeg', ['-hide_banner', ...args], {\n encoding: 'utf8',\n })\n return { ok: res.status === 0, stderr: res.stderr ?? '' }\n}\n\nfunction requireFfmpeg(): void {\n const res = spawnSync('ffmpeg', ['-version'], { encoding: 'utf8' })\n if (res.status !== 0)\n throw new UsageError(\n 'vos compare reads frames with ffmpeg, and none is on PATH: install it (brew install ffmpeg, apt install ffmpeg) and run again',\n )\n}\n\nfunction probeSize(video: string): { width: number; height: number } | null {\n const res = spawnSync(\n 'ffprobe',\n [\n '-v',\n 'error',\n '-select_streams',\n 'v:0',\n '-show_entries',\n 'stream=width,height',\n '-of',\n 'csv=p=0',\n video,\n ],\n { encoding: 'utf8' },\n )\n const m = /(\\d+),(\\d+)/.exec(res.stdout ?? '')\n return m ? { width: Number(m[1]), height: Number(m[2]) } : null\n}\n\nexport async function cmdCompare(argv: string[]): Promise<number> {\n const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS)\n const source = positionals[0]\n const against = strFlag(flags, 'against')\n if (!source || !against)\n throw new UsageError(\n 'vos compare <program dir|config.json> --against <their render.mp4> [--times a,b,50%] [--every 1] [--width W --height H] [--threshold 0.95] [--out compare] [--json]',\n )\n requireFfmpeg()\n const r = createReporter(flags.json === true)\n const ref = resolve(against)\n\n const loaded = await loadVosConfig(source)\n for (const w of loaded.warnings) r.log(`note: ${w}`)\n const config = loaded.config as Record<string, unknown>\n const duration = configDuration(config) ?? 5\n const assets = await programAssets(config, {\n baseDir: /^https?:\\/\\//.test(source)\n ? null\n : existsSync(source) && statSync(source).isDirectory()\n ? source\n : dirname(source),\n origin: platformOrigin({}),\n key: resolveCredential(),\n log: (line) => r.log(line),\n })\n\n // Compare at the render's own size unless told otherwise, halved past\n // 1280 wide: the sheet is for looking at, and SSIM is stable at half size.\n const probed = probeSize(ref)\n const half = probed && probed.width > 1280 ? 2 : 1\n const width = Number(\n strFlag(flags, 'width') ?? (probed ? probed.width / half : 960),\n )\n const height = Number(\n strFlag(flags, 'height') ?? (probed ? probed.height / half : 540),\n )\n const threshold = Number(strFlag(flags, 'threshold') ?? 0.95)\n const timesRaw = strFlag(flags, 'times')\n const times = timesRaw\n ? parseTimes(timesRaw, duration)\n : sampleTimes(duration, Number(strFlag(flags, 'every') ?? 1))\n const outDir = resolve(strFlag(flags, 'out') ?? 'compare')\n mkdirSync(outDir, { recursive: true })\n\n const browser = await launchBrowser()\n const scores: FrameScore[] = []\n try {\n for (const t of times) {\n const tag = t.toFixed(2)\n const refPng = join(outDir, `src-${tag}.png`)\n const vosPng = join(outDir, `vos-${tag}.png`)\n const sheet = join(outDir, `sheet-${tag}.png`)\n const grab = ffmpeg([\n '-v',\n 'error',\n '-y',\n '-ss',\n String(t),\n '-i',\n ref,\n '-frames:v',\n '1',\n '-vf',\n `scale=${width}:${height}`,\n refPng,\n ])\n if (!grab.ok)\n throw new Error(\n `could not read ${against} at ${tag}s: ${grab.stderr.trim()}`,\n )\n const still = await renderStill(browser, {\n config,\n assets,\n width,\n height,\n time: t,\n })\n writeFileSync(vosPng, await reencodeStill(browser, still.bytes, 'png'))\n const pair = ['-i', refPng, '-i', vosPng]\n const ssim = parseSsim(\n ffmpeg([\n ...pair,\n '-lavfi',\n '[0:v]format=rgb24[x];[1:v]format=rgb24[y];[x][y]ssim',\n '-f',\n 'null',\n '-',\n ]).stderr,\n )\n ffmpeg([\n '-v',\n 'error',\n '-y',\n ...pair,\n '-filter_complex',\n '[0:v]format=gbrp[x];[1:v]format=gbrp[y];[x]split[x1][x2];[y]split[y1][y2];[x1][y1]blend=all_mode=difference[d];[x2][y2][d]hstack=inputs=3,format=rgb24',\n sheet,\n ])\n const score = { t, ssim: ssim ?? 0, sheet }\n scores.push(score)\n const mark = score.ssim < threshold ? ' ← under' : ''\n r.log(`t=${tag}s SSIM ${score.ssim.toFixed(3)} ${sheet}${mark}`)\n for (const w of still.pageErrors)\n r.log(`warn: t=${tag}s the page threw: ${w}`)\n }\n } finally {\n await browser.close()\n }\n\n // One picture of the whole run: the sheets stacked at a third of their size.\n const overview = join(outDir, 'overview.png')\n if (scores.length) {\n const inputs = scores.flatMap((s) => ['-i', s.sheet])\n const scaled = scores\n .map((_, i) => `[${i}:v]scale=iw/3:-2[s${i}]`)\n .join(';')\n const stack = scores.map((_, i) => `[s${i}]`).join('')\n ffmpeg([\n '-v',\n 'error',\n '-y',\n ...inputs,\n '-filter_complex',\n scores.length > 1\n ? `${scaled};${stack}vstack=inputs=${scores.length}`\n : `${scaled}`.replace('[s0]', ''),\n overview,\n ])\n }\n\n const verdict = compareVerdict(scores, threshold)\n const report = {\n against: ref,\n width,\n height,\n threshold,\n ...verdict,\n frames: scores,\n overview,\n }\n writeFileSync(\n join(outDir, 'report.json'),\n JSON.stringify(report, null, 2) + '\\n',\n )\n r.done(\n report,\n `${scores.length} frames: mean SSIM ${verdict.mean.toFixed(3)}, lowest ${verdict.min.toFixed(3)}${\n verdict.failing.length\n ? `; under ${threshold} at ${verdict.failing.map((t) => `${t}s`).join(', ')}: look at those sheets`\n : `; every frame at or above ${threshold}`\n }. Sheets (source | vos | difference) and overview.png in ${outDir}`,\n )\n return verdict.pass ? EXIT_OK : EXIT_ERROR\n}\n","/**\n * `vos port inventory <source>` and `vos port scaffold` — the mechanical half\n * of bringing a finished piece into vos. The inventory reads the source; the\n * scaffold writes a program that already keeps the port grammar, built into\n * config.json, so the agent starts from data and translates only the motion.\n * The tools are engine-agnostic: a plain page, a HyperFrames composition (its\n * root's data attributes, its audio) and a Remotion project's render.\n */\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { dirname, join, resolve } from 'node:path'\nimport { pathToFileURL } from 'node:url'\nimport { UsageError, parseArgs, strFlag } from './args'\nimport { EXIT_ERROR, EXIT_OK, createReporter } from './output'\nimport { buildProgram } from './buildProgram'\nimport { readInventory } from './portInventory'\nimport type { Inventory } from './portInventory'\nimport { planScaffold, probeAudioDuration, writeScaffold } from './portScaffold'\n\nconst BOOLEAN_FLAGS = new Set(['json', 'help'])\n\nexport async function cmdPort(argv: string[]): Promise<number> {\n const [sub, ...rest] = argv\n if (sub === 'inventory') return await inventory(rest)\n if (sub === 'scaffold') return await scaffold(rest)\n throw new UsageError(\n 'vos port inventory <page.html|project dir> [--render <their render.mp4>] [--out port] [--json]\\n' +\n 'vos port scaffold [--from port/inventory.json] [--out port/program] [--json]',\n )\n}\n\nasync function inventory(argv: string[]): Promise<number> {\n const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS)\n const source = positionals[0] ?? '.'\n const r = createReporter(flags.json === true)\n const outDir = resolve(strFlag(flags, 'out') ?? 'port')\n mkdirSync(outDir, { recursive: true })\n const renderFlag = strFlag(flags, 'render')\n const inv = await readInventory(source, {\n render: renderFlag === undefined ? undefined : resolve(renderFlag),\n outDir,\n log: (l) => r.log(`note: ${l}`),\n })\n const file = join(outDir, 'inventory.json')\n writeFileSync(file, JSON.stringify(inv, null, 2) + '\\n')\n const missing = inv.fonts.filter((f) => !f.catalog).map((f) => f.family)\n r.log(\n `${inv.engine}, ${inv.width}×${inv.height}${inv.fps ? `@${inv.fps}` : ''}, ${inv.duration ?? '?'}s: ` +\n `${inv.texts.length} words, ${Object.keys(inv.palette).length} palette colours, ${inv.fonts.length} faces` +\n `${missing.length ? ` (not in the catalog: ${missing.join(', ')})` : ''}, ` +\n `${inv.media.length} media, ${inv.scenes.length} scenes, ${inv.canvases.length} canvases` +\n `${inv.gaps.length ? `; needs a painter or an approximation: ${inv.gaps.join(', ')}` : ''}`,\n )\n r.done(\n { inventory: file, ...summary(inv) },\n `Wrote ${file}${inv.stills.length ? ` and ${inv.stills.length} reference stills` : ''}. Next: npx vos port scaffold`,\n )\n return EXIT_OK\n}\n\nfunction summary(inv: Inventory) {\n return {\n engine: inv.engine,\n width: inv.width,\n height: inv.height,\n fps: inv.fps,\n duration: inv.duration,\n words: inv.texts.length,\n palette: Object.keys(inv.palette).length,\n faces: inv.fonts.map((f) => ({ family: f.family, catalog: f.catalog })),\n media: inv.media.length,\n scenes: inv.scenes.length,\n canvases: inv.canvases.length,\n gaps: inv.gaps,\n render: inv.render,\n }\n}\n\nasync function scaffold(argv: string[]): Promise<number> {\n const { flags } = parseArgs(argv, BOOLEAN_FLAGS)\n const r = createReporter(flags.json === true)\n const from = resolve(strFlag(flags, 'from') ?? join('port', 'inventory.json'))\n if (!existsSync(from))\n throw new UsageError(\n `no inventory at ${from}: run npx vos port inventory <source> first`,\n )\n const inv = JSON.parse(readFileSync(from, 'utf8')) as Inventory\n const outDir = resolve(\n strFlag(flags, 'out') ?? join(dirname(from), 'program'),\n )\n const plan = planScaffold(inv, {\n sourceDir: scaffoldSourceDir(inv),\n probeDuration: probeAudioDuration,\n })\n writeScaffold(plan, outDir)\n\n // Build config.json from the program, as `vos build` does.\n const programFile = join(outDir, 'program.mjs')\n const mod = (await import(\n `${pathToFileURL(programFile).href}?t=${Date.now()}`\n )) as { default: Record<string, unknown> }\n const built = buildProgram(mod.default, 'program.mjs', plan.program)\n for (const p of built.problems) r.log(`error ${p.fn}: ${p.message}`)\n if (built.problems.length) return EXIT_ERROR\n writeFileSync(\n join(outDir, 'config.json'),\n JSON.stringify(built.config, null, 2) + '\\n',\n )\n r.done(\n { program: outDir, report: join(dirname(outDir), 'REPORT.md') },\n `Wrote ${outDir}/program.mjs, config.json and doc.json, and ${join(dirname(outDir), 'REPORT.md')}. ` +\n 'Translate the motion where it says TODO, then: npx vos build program.mjs && npx vos compare . --against <their render>',\n )\n return EXIT_OK\n}\n\n/**\n * The folder the scaffold resolves the source's media against: the absolute\n * root the inventory recorded, else (an older inventory) its source label\n * read from where the scaffold runs.\n */\nexport function scaffoldSourceDir(\n inv: Pick<Inventory, 'source' | 'root'>,\n): string {\n if (inv.root) return inv.root\n return inv.source.endsWith('.html')\n ? dirname(resolve(inv.source))\n : resolve(inv.source)\n}\n","/**\n * `vos port inventory` — what a source piece holds, read from the piece as a\n * browser renders it, before any animation code is written.\n *\n * Every port started by reading the source by hand for its words, colours,\n * faces, media and scenes, and a port that missed one shipped a literal in a\n * function string or a face from a third-party host. The inventory is that\n * reading, done by the browser that renders the page: computed styles, not\n * guesses from CSS text. It writes nothing but `port/inventory.json` (and\n * reference stills when the source's own render sits beside it); the\n * scaffold turns it into a program.\n */\nimport { spawnSync } from 'node:child_process'\nimport {\n existsSync,\n mkdirSync,\n readFileSync,\n readdirSync,\n statSync,\n} from 'node:fs'\nimport { dirname, join, relative, resolve } from 'node:path'\nimport { pathToFileURL } from 'node:url'\nimport { findFontFamily } from '@vosjs/shared'\nimport { launchBrowser } from '../browser'\nimport { readRemotion } from './portRemotion'\n\nexport type SourceEngine = 'hyperframes' | 'remotion' | 'page'\n\nexport interface InventoryText {\n id: string\n text: string\n tag: string\n /** Box in composition pixels, top-left origin; null when not laid out at the first frame. */\n box: { x: number; y: number; width: number; height: number } | null\n /** The scene element it sits in, when the piece has scenes. */\n scene?: string | null\n /** 'chars' when the source animates the word one span per letter: one split element. */\n split?: 'chars' | null\n font: {\n family: string\n size: number\n weight: number\n style: string\n color: string\n letterSpacing: number\n transform: string\n }\n}\n\nexport interface InventoryFont {\n family: string\n weights: number[]\n italic: boolean\n /** The catalog family that serves it, or null when the catalog lacks it. */\n catalog: string | null\n}\n\nexport interface InventoryMedia {\n kind: 'image' | 'svg' | 'video' | 'audio'\n src: string | null\n start: number | null\n duration: number | null\n volume: number | null\n mediaStart: number | null\n}\n\nexport interface Inventory {\n /** The source as given, relative to where the inventory ran ('.' for there). */\n source: string\n /** The folder holding the source page or project, absolute: what the scaffold resolves media against. */\n root?: string\n engine: SourceEngine\n width: number\n height: number\n fps: number | null\n duration: number | null\n /** `ground`: the full-frame colour behind the scene, when it was measured. */\n scenes: {\n name: string\n start: number\n duration: number | null\n ground?: string | null\n }[]\n texts: InventoryText[]\n /** CSS custom properties that hold a colour, by name, first. */\n palette: Record<string, string>\n /** Every other colour the page paints text or a background with. */\n colors: string[]\n fonts: InventoryFont[]\n media: InventoryMedia[]\n canvases: { width: number; height: number }[]\n /** CSS no element can say (blend, clip, mask, filter, 3D): a painter or an approximation. */\n gaps: string[]\n /** Proposed knobs from the source's own declared variables. */\n variables: Record<string, unknown>\n /** Quoted strings in the page's scripts, for a piece that paints its words. */\n scriptStrings: string[]\n /** Maths the source reaches for that the painter starter provides: 'spring', 'noise', 'interpolate', 'bezier', 'random'. */\n uses?: string[]\n /** The source's own render, when one sits beside it. */\n render: string | null\n /** Stills from that render, at each scene's middle or each second. */\n stills: { t: number; file: string }[]\n}\n\n/** What kind of project a path holds (pure over the files it lists). */\nexport function detectEngine(dir: string): SourceEngine {\n if (existsSync(join(dir, 'hyperframes.json'))) return 'hyperframes'\n const pkg = join(dir, 'package.json')\n if (existsSync(pkg)) {\n try {\n const p = JSON.parse(readFileSync(pkg, 'utf8')) as Record<string, any>\n const deps = { ...(p.dependencies ?? {}), ...(p.devDependencies ?? {}) }\n if ('remotion' in deps) return 'remotion'\n if ('hyperframes' in deps) return 'hyperframes'\n if (/hyperframes/.test(JSON.stringify(p.scripts ?? {})))\n return 'hyperframes'\n } catch {\n /* not JSON: a plain page */\n }\n }\n return 'page'\n}\n\n/** The page a source path renders (pure over the file system). */\nexport function sourcePage(source: string): string | null {\n if (!existsSync(source)) return null\n if (statSync(source).isFile()) return /\\.html?$/i.test(source) ? source : null\n const index = join(source, 'index.html')\n return existsSync(index) ? index : null\n}\n\n/** A render beside the source: renders/, out/, or a video at the root. */\nexport function findRender(dir: string): string | null {\n const videos = (d: string) =>\n existsSync(d)\n ? readdirSync(d)\n .filter((f) => /\\.(mp4|webm|mov)$/i.test(f))\n .map((f) => join(d, f))\n : []\n for (const d of [join(dir, 'renders'), join(dir, 'out'), dir]) {\n const found = videos(d)\n if (found.length) return found[0]\n }\n return null\n}\n\n/** Quoted strings a person would read, from script text (pure). */\nexport function scriptStringsOf(code: string): string[] {\n const out = new Set<string>()\n for (const m of code.matchAll(/(['\"`])((?:(?!\\1)[^\\\\\\n]|\\\\.){2,60})\\1/g)) {\n const s = m[2]\n if (!/[A-Za-z]{2}/.test(s)) continue\n if (/[\"'`]/.test(s)) continue // a font stack or a stretch of code between two literals\n if (/\\b[a-zA-Z_$][\\w$]*\\s*:\\s*[\\w$.]+\\s*,/.test(s)) continue // an object literal\n if (/^-?[\\d.]+(px|%|ms|s|deg|em|rem|vh|vw)?$/.test(s)) continue // a CSS length\n if (/^[a-z]+\\/[a-z0-9.+-]+$/.test(s)) continue // a MIME type\n if (\n /^(source|destination)-(over|in|out|atop)$|^(lighter|copy|xor|multiply|screen|overlay|darken|lighten|difference|exclusion)$/.test(\n s,\n )\n )\n continue // a composite op\n if (/^[A-Za-z ]{4}$/.test(s) && /^(RIFF|WAVE|fmt |data|LIST)$/.test(s))\n continue // a file chunk id\n if (\n /[(){};=<>]|\\$\\{|^\\.?\\/|https?:|\\.(js|css|png|jpe?g|mp[34]|wav|woff2?)$/i.test(\n s,\n )\n )\n continue\n if (/^[a-z][a-zA-Z0-9]*$/.test(s) && !/[A-Z]{2}/.test(s)) continue // an identifier or a key\n if (/^(rgba?|hsla?)\\(|^#[0-9a-f]{3,8}$/i.test(s)) continue\n out.add(s)\n }\n return [...out].slice(0, 80)\n}\n\n/**\n * Scenes a GSAP timeline reveals (pure): each scene element's start is the\n * first time a `tl.set|to|fromTo` on its id makes it visible, and every\n * `addLabel('name', t)` is a scene too. Ordered by start; each lasts until\n * the next one.\n */\nexport function scriptScenes(\n ids: string[],\n code: string,\n duration: number | null,\n): { name: string; start: number; duration: number | null }[] {\n const found = new Map<string, number>()\n for (const id of ids) {\n const re = new RegExp(\n `\\\\.(?:set|to|fromTo)\\\\(\\\\s*[\"'\\`]#${id.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}[\"'\\`][^)]*?(?:opacity|autoAlpha)\\\\s*:\\\\s*1[^)]*?,\\\\s*([\\\\d.]+)\\\\s*\\\\)`,\n )\n const m = re.exec(code)\n if (m) found.set(id, Number(m[1]))\n else if (!found.size && ids[0] === id) found.set(id, 0) // the first scene shows from the start\n }\n for (const m of code.matchAll(\n /addLabel\\(\\s*[\"'`]([^\"'`]+)[\"'`]\\s*,\\s*([\\d.]+)/g,\n )) {\n if (!found.has(m[1])) found.set(m[1], Number(m[2]))\n }\n const sorted = [...found.entries()].sort((a, b) => a[1] - b[1])\n return sorted.map(([name, start], i) => {\n const next = sorted[i + 1]?.[1] ?? duration\n return {\n name,\n start,\n duration: next == null ? null : Math.round((next - start) * 1000) / 1000,\n }\n })\n}\n\n/**\n * The faces a script paints with (pure): the first family of every font\n * stack written as a string (`'\"Inter Tight\", Helvetica, sans-serif'`), the\n * way a canvas page names its type.\n */\nexport function scriptFontFamilies(code: string): string[] {\n const out = new Set<string>()\n const generic = /,\\s*(?:sans-serif|serif|monospace|cursive|system-ui)\\b/\n // A canvas `font` shorthand leads with style, weight and size: drop them.\n const shorthand =\n /^(?:(?:italic|oblique|normal|bold|bolder|lighter|small-caps|\\d{3})\\s+)*[\\d.]+(?:px|pt|em|rem|%)(?:\\/[\\d.]+\\w*)?\\s+/\n for (const m of code.matchAll(/(['\"`])((?:\\\\.|(?!\\1).)*?)\\1/g)) {\n const s = m[2]\n if (!generic.test(s)) continue\n const first = s\n .replace(shorthand, '')\n .split(',')[0]\n .trim()\n .replace(/^[\"']|[\"']$/g, '')\n if (\n first &&\n !/^(sans-serif|serif|monospace|cursive|system-ui)$/.test(first)\n )\n out.add(first)\n }\n return [...out]\n}\n\n/**\n * What the source's code reaches for that the painter starter provides\n * (pure): a Remotion \\`spring(\\` or \\`measureSpring(\\`, \\`@remotion/noise\\`\n * or a \\`noise2D/3D(\\` call, \\`interpolate(\\`, \\`Easing.bezier(\\`, a seeded\n * \\`random(\\`.\n */\nexport function sourceUses(code: string): string[] {\n const out: string[] = []\n if (/\\bspring\\s*\\(|\\bmeasureSpring\\s*\\(/.test(code)) out.push('spring')\n if (/@remotion\\/noise|\\bnoise[234]D\\s*\\(/.test(code)) out.push('noise')\n if (/\\binterpolate\\s*\\(/.test(code)) out.push('interpolate')\n if (/Easing\\.bezier\\s*\\(|cubic-bezier\\(/.test(code)) out.push('bezier')\n if (/\\brandom\\s*\\(\\s*['\"\\w]/.test(code)) out.push('random')\n return out\n}\n\n/** The catalog family for a source family, or null (pure over the catalog). */\nexport function catalogFamily(family: string): string | null {\n const clean = family.trim().replace(/^['\"]|['\"]$/g, '')\n return findFontFamily(clean)?.family ?? null\n}\n\nfunction probe(video: string): { fps: number | null; duration: number | null } {\n const res = spawnSync(\n 'ffprobe',\n [\n '-v',\n 'error',\n '-select_streams',\n 'v:0',\n '-show_entries',\n 'stream=r_frame_rate:format=duration',\n '-of',\n 'json',\n video,\n ],\n { encoding: 'utf8' },\n )\n try {\n const j = JSON.parse(res.stdout ?? '{}')\n const [n, d] = String(j.streams?.[0]?.r_frame_rate ?? '')\n .split('/')\n .map(Number)\n const fps = n && d ? Math.round((n / d) * 100) / 100 : null\n const duration = Number(j.format?.duration)\n return { fps, duration: Number.isFinite(duration) ? duration : null }\n } catch {\n return { fps: null, duration: null }\n }\n}\n\n// The page-side reader, as a string: a serialized function would carry the\n// bundler's helpers into a page that has none.\nexport const READ_PAGE = `(() => {\n const root = document.querySelector('[data-composition-id], [data-width][data-height]') || document.body\n const num = (v) => { const n = Number(v); return Number.isFinite(n) ? n : null }\n const canvases = [...document.querySelectorAll('canvas')].map((c) => ({ width: c.width, height: c.height }))\n const biggest = canvases.slice().sort((a, b) => b.width * b.height - a.width * a.height)[0]\n const width = num(root.dataset && root.dataset.width) || (biggest && biggest.width) || window.innerWidth\n const height = num(root.dataset && root.dataset.height) || (biggest && biggest.height) || window.innerHeight\n const rootRect = root.getBoundingClientRect()\n const sx = rootRect.width ? width / rootRect.width : 1\n const sy = rootRect.height ? height / rootRect.height : 1\n\n // The faces that actually render: a family loaded only italic, or only at\n // one weight, draws that face whatever the CSS asked for.\n const loaded = {}\n if (document.fonts) for (const f of document.fonts) {\n if (f.status !== 'loaded') continue\n const fam = f.family.replace(/^[\"']|[\"']$/g, '')\n const e = loaded[fam] || (loaded[fam] = { styles: new Set(), weights: new Set() })\n e.styles.add(f.style)\n const w = Number(f.weight)\n if (Number.isFinite(w)) e.weights.add(w)\n }\n const renderedFace = (fam, style, weight) => {\n const e = loaded[fam]\n if (!e) return { style, weight }\n const st = e.styles.has(style) ? style : style === 'normal' && e.styles.has('italic') ? 'italic' : style\n const ws = [...e.weights]\n const wt = !ws.length || ws.includes(weight) ? weight : ws.reduce((a, b) => (Math.abs(b - weight) < Math.abs(a - weight) ? b : a))\n return { style: st, weight: wt }\n }\n const texts = []\n const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT)\n const seen = new Set()\n let n = 0\n while (walker.nextNode()) {\n const node = walker.currentNode\n let el = node.parentElement\n if (!el || !(node.textContent || '').trim() || el.closest('script, style, noscript, title')) continue\n // A word animated letter by letter is one span per glyph: read the word,\n // once, as a split word, never as its letters.\n let split = null\n const glyphs = (a) => a && a.children.length >= 3 && [...a.childNodes].every((c) => c.nodeType === 1 ? (c.textContent || '').trim().length <= 2 : !(c.textContent || '').trim())\n for (let a = el.parentElement, up = 0; a && up < 3; a = a.parentElement, up++) {\n if (glyphs(a)) { el = a; split = 'chars'; break }\n }\n // A line with a styled word inside it (\"TYPE <span>that</span> MOVES\")\n // is read run by run, each with its own box, or the runs after the\n // first are lost.\n const mixed = !split && [...el.children].some((c) => (c.textContent || '').trim())\n const unit = mixed ? node : el\n if (seen.has(unit)) continue\n seen.add(unit)\n const text = ((mixed ? node.textContent : el.textContent) || '').replace(/\\\\s+/g, ' ').trim()\n if (!text) continue\n // A split word wears its letters' face, never its container's.\n const cs = getComputedStyle(split ? node.parentElement : el)\n let r\n if (mixed) { const range = document.createRange(); range.selectNodeContents(node); r = range.getBoundingClientRect() }\n else r = el.getBoundingClientRect()\n const box = r.width && r.height ? {\n x: Math.round((r.left - rootRect.left) * sx), y: Math.round((r.top - rootRect.top) * sy),\n width: Math.round(r.width * sx), height: Math.round(r.height * sy) } : null\n const ls = parseFloat(cs.letterSpacing)\n if (!mixed) el.setAttribute('data-vos-inv', String(texts.length))\n const sceneEl = el.closest('.scene, [data-scene], section[id]')\n const fam = cs.fontFamily.split(',')[0].trim().replace(/^[\"']|[\"']$/g, '')\n const face = renderedFace(fam, cs.fontStyle, Number(cs.fontWeight) || 400)\n texts.push({\n id: (mixed ? '' : el.id || (el.className && typeof el.className === 'string' ? el.className.split(' ')[0] : '')) || el.tagName.toLowerCase() + '-' + (n++),\n text, tag: el.tagName.toLowerCase(), box, scene: sceneEl && sceneEl.id ? sceneEl.id : null, split,\n font: { family: fam,\n size: Math.round(parseFloat(cs.fontSize) * sy), weight: face.weight,\n style: face.style, color: cs.color, letterSpacing: Number.isFinite(ls) ? Math.round(ls * sy * 100) / 100 : 0,\n transform: cs.textTransform },\n })\n }\n\n const palette = {}\n const isColor = (v) => /^(#[0-9a-f]{3,8}|rgba?\\\\(|hsla?\\\\(|oklch\\\\()/i.test(v)\n const scan = (style) => { for (let i = 0; i < style.length; i++) { const p = style[i]; if (p.startsWith('--')) { const v = style.getPropertyValue(p).trim(); if (isColor(v)) palette[p.slice(2)] = v } } }\n for (const sheet of document.styleSheets) {\n let rules\n try { rules = sheet.cssRules } catch (e) { continue }\n for (const rule of rules) if (rule.style) scan(rule.style)\n }\n scan(root.style)\n\n const colors = new Set()\n const gaps = new Set()\n for (const el of document.querySelectorAll('body *')) {\n const cs = getComputedStyle(el)\n if (cs.backgroundColor && cs.backgroundColor !== 'rgba(0, 0, 0, 0)') colors.add(cs.backgroundColor)\n if (cs.mixBlendMode && cs.mixBlendMode !== 'normal') gaps.add('mix-blend-mode: ' + cs.mixBlendMode)\n if (cs.clipPath && cs.clipPath !== 'none') gaps.add('clip-path')\n if (cs.maskImage && cs.maskImage !== 'none') gaps.add('mask')\n if (cs.overflow === 'hidden' && el.children.length && el.textContent.trim()) gaps.add('overflow: hidden (a text mask)')\n if (cs.filter && cs.filter !== 'none') gaps.add('filter: ' + cs.filter.split('(')[0])\n if (cs.backdropFilter && cs.backdropFilter !== 'none') gaps.add('backdrop-filter')\n if (cs.perspective && cs.perspective !== 'none') gaps.add('3D perspective')\n if (cs.webkitTextStrokeWidth && parseFloat(cs.webkitTextStrokeWidth) > 0) gaps.add('-webkit-text-stroke (a stroke: see the reference for its width)')\n }\n for (const t of texts) colors.add(t.font.color)\n\n const media = []\n const attrs = (el) => ({ start: num(el.dataset.start), duration: num(el.dataset.duration), volume: num(el.dataset.volume), mediaStart: num(el.dataset.mediaStart) })\n for (const el of document.querySelectorAll('img')) media.push({ kind: 'image', src: el.getAttribute('src'), ...attrs(el) })\n for (const el of document.querySelectorAll('svg')) if (!el.closest('svg svg')) media.push({ kind: 'svg', src: null, ...attrs(el) })\n for (const el of document.querySelectorAll('video')) media.push({ kind: 'video', src: el.getAttribute('src') || (el.querySelector('source') && el.querySelector('source').getAttribute('src')), ...attrs(el) })\n for (const el of document.querySelectorAll('audio')) media.push({ kind: 'audio', src: el.getAttribute('src') || (el.querySelector('source') && el.querySelector('source').getAttribute('src')), ...attrs(el) })\n\n const scenes = []\n for (const el of document.querySelectorAll('[data-start]')) {\n if (['AUDIO', 'VIDEO', 'IMG'].includes(el.tagName)) continue\n scenes.push({ name: el.id || el.dataset.compositionId || (typeof el.className === 'string' ? el.className.split(' ')[0] : '') || el.tagName.toLowerCase(), start: num(el.dataset.start) || 0, duration: num(el.dataset.duration) })\n }\n const sceneEls = [...document.querySelectorAll('.scene, [data-scene], section[id]')]\n .filter((el) => el.id)\n .map((el) => el.id)\n let variables = {}\n try { variables = JSON.parse(root.dataset.compositionVariables || '{}') } catch (e) {}\n const scriptText = [...document.querySelectorAll('script:not([src])')].map((s) => s.textContent).join('\\\\n')\n return {\n width, height, fps: num(root.dataset && root.dataset.fps), duration: num(root.dataset && root.dataset.duration),\n texts, palette, colors: [...colors], gaps: [...gaps], media, canvases, scenes, sceneEls, variables, scriptText,\n }\n})()`\n\n/**\n * The scene's ground: the colour of the opaque, frame-filling element on top\n * at the centre and the four corners, by majority (a circle in the middle or\n * a card is not the ground).\n */\nexport const READ_GROUND = `(() => {\n const W = innerWidth, H = innerHeight\n const counts = {}\n for (const [px, py] of [[0.5, 0.5], [0.06, 0.06], [0.94, 0.94], [0.06, 0.94], [0.94, 0.06]]) {\n for (const el of document.elementsFromPoint(px * W, py * H)) {\n const cs = getComputedStyle(el)\n const bg = cs.backgroundColor\n if (!bg || bg === 'transparent' || /rgba\\\\([^)]*,\\\\s*0\\\\)$/.test(bg)) continue\n const r = el.getBoundingClientRect()\n if (r.width < W * 0.9 || r.height < H * 0.9 || Number(cs.opacity) < 0.99) continue\n counts[bg] = (counts[bg] || 0) + 1\n break\n }\n }\n let best = null\n for (const k in counts) if (!best || counts[k] > counts[best]) best = k\n return best\n})()`\n\n/**\n * Re-read the boxes of the texts in one scene with the piece's registered\n * timelines (HyperFrames' `window.__timelines`) seeked to that time: an\n * animated word is laid out where it SETTLES, not where it starts. Returns\n * null when the page registers no timeline.\n */\nconst SEEK_AND_READ = `((args) => {\n const tls = window.__timelines ? Object.values(window.__timelines) : []\n if (!tls.length) return null\n for (const tl of tls) { try { tl.pause(); tl.seek(args.t, false) } catch (e) {} }\n const root = document.querySelector('[data-composition-id], [data-width][data-height]') || document.body\n const rr = root.getBoundingClientRect()\n const sx = rr.width ? args.width / rr.width : 1\n const sy = rr.height ? args.height / rr.height : 1\n const out = {}\n for (const i of args.indices) {\n const el = document.querySelector('[data-vos-inv=\"' + i + '\"]')\n if (!el) continue\n const r = el.getBoundingClientRect()\n if (r.width && r.height) out[i] = { x: Math.round((r.left - rr.left) * sx), y: Math.round((r.top - rr.top) * sy), width: Math.round(r.width * sx), height: Math.round(r.height * sy) }\n }\n return out\n})`\n\n/** Read a source into an inventory, with stills from its render when ffmpeg can. */\nexport async function readInventory(\n source: string,\n opts: { render?: string | null; outDir: string; log?: (l: string) => void },\n): Promise<Inventory> {\n const abs = resolve(source)\n const dir =\n existsSync(abs) && statSync(abs).isDirectory() ? abs : dirname(abs)\n const engine = detectEngine(dir)\n const page = sourcePage(abs)\n const render = opts.render === undefined ? findRender(dir) : opts.render\n\n let read: any = {\n width: 1920,\n height: 1080,\n fps: null,\n duration: null,\n texts: [],\n palette: {},\n colors: [],\n gaps: [],\n media: [],\n canvases: [],\n scenes: [],\n variables: {},\n scriptText: '',\n }\n const fromRender = render ? probe(render) : { fps: null, duration: null }\n let fps: number | null = fromRender.fps\n let duration: number | null = fromRender.duration\n let settled = 0\n if (page) {\n const browser = await launchBrowser()\n try {\n const ctx = await browser.newContext({\n viewport: { width: 1920, height: 1080 },\n })\n const p = await ctx.newPage()\n // HyperFrames' runtime provides the registry a composition writes its\n // timeline into; outside it the page's own `window.__timelines[id] = tl`\n // would throw, so the registry is created first, as the runtime does.\n await p.addInitScript('window.__timelines = window.__timelines || {}')\n await p.goto(pathToFileURL(page).href, { waitUntil: 'load' })\n await p.evaluate('document.fonts && document.fonts.ready')\n await p.waitForTimeout(300)\n read = await p.evaluate(READ_PAGE)\n fps = read.fps ?? fps\n duration = read.duration ?? duration\n // A composition that reveals its scenes from a script names them there.\n const scripted = scriptScenes(\n read.sceneEls ?? [],\n read.scriptText ?? '',\n duration,\n )\n if (scripted.length > (read.scenes?.length ?? 0)) read.scenes = scripted\n // Lay each scene's words out where they settle, three quarters in.\n for (const s of read.scenes as {\n name: string\n start: number\n duration: number | null\n }[]) {\n const indices = (read.texts as InventoryText[])\n .map((t, i) => (t.scene === s.name ? i : -1))\n .filter((i) => i >= 0)\n const t = s.start + (s.duration ?? 1) * 0.75\n const boxes = (await p.evaluate(\n `${SEEK_AND_READ}(${JSON.stringify({ t, indices, width: read.width, height: read.height })})`,\n )) as Record<string, InventoryText['box']> | null\n if (!boxes)\n break\n // The colour the scene stands on, where its timeline has put it.\n ;(s as { ground?: string | null }).ground = (await p.evaluate(\n READ_GROUND,\n )) as string | null\n for (const [i, box] of Object.entries(boxes)) {\n read.texts[Number(i)].box = box\n settled++\n }\n }\n await ctx.close()\n } finally {\n await browser.close()\n }\n } else if (engine === 'remotion') {\n const r = await readRemotion(dir, opts.log)\n if (r) {\n read = r\n fps = (r.fps as number) ?? fps\n duration = (r.duration as number) ?? duration\n opts.log?.(\n `read the Remotion composition ${String(r.composition)} in its own bundle: ${(r.scenes as unknown[]).length} sequences as scenes, the words where they settle in each`,\n )\n }\n }\n if (settled)\n opts.log?.(\n `${settled} words laid out where they settle in their scene (the piece's own timelines, seeked)`,\n )\n\n const families = new Map<string, InventoryFont>()\n for (const t of read.texts as InventoryText[]) {\n const f = families.get(t.font.family) ?? {\n family: t.font.family,\n weights: [],\n italic: false,\n catalog: catalogFamily(t.font.family),\n }\n if (!f.weights.includes(t.font.weight)) f.weights.push(t.font.weight)\n if (t.font.style === 'italic') f.italic = true\n families.set(t.font.family, f)\n }\n // A page that paints its words names its faces in its script.\n for (const family of scriptFontFamilies(read.scriptText ?? '')) {\n if (!families.has(family))\n families.set(family, {\n family,\n weights: [],\n italic: false,\n catalog: catalogFamily(family),\n })\n }\n\n const stills: Inventory['stills'] = []\n if (render && duration) {\n const has = spawnSync('ffmpeg', ['-version']).status === 0\n if (has) {\n const refDir = join(opts.outDir, 'ref')\n mkdirSync(refDir, { recursive: true })\n const times =\n read.scenes.length >= 3\n ? read.scenes.map(\n (s: { start: number; duration: number | null }) =>\n s.start + (s.duration ?? 1) / 2,\n )\n : Array.from(\n { length: Math.max(1, Math.floor(duration)) },\n (_, i) => i + 0.5,\n )\n for (const t of times.filter((t: number) => t < duration)) {\n const file = join(refDir, `src-${t.toFixed(2)}.png`)\n const ok =\n spawnSync('ffmpeg', [\n '-v',\n 'error',\n '-y',\n '-ss',\n String(t),\n '-i',\n render,\n '-frames:v',\n '1',\n '-vf',\n 'scale=960:-2',\n file,\n ]).status === 0\n if (ok)\n stills.push({\n t: Number(t.toFixed(2)),\n file: relative(opts.outDir, file),\n })\n }\n } else {\n opts.log?.(\n 'no ffmpeg on PATH: no reference stills (install it to get them)',\n )\n }\n }\n\n const scriptStrings = scriptStringsOf(read.scriptText as string)\n return {\n source: relative(process.cwd(), abs) || '.',\n root: abs.endsWith('.html') ? dirname(abs) : abs,\n engine,\n width: read.width,\n height: read.height,\n fps,\n duration,\n scenes: read.scenes,\n texts: read.texts,\n palette: read.palette,\n colors: read.colors,\n fonts: [...families.values()],\n media: read.media,\n canvases: read.canvases,\n gaps: read.gaps,\n variables: read.variables,\n scriptStrings,\n uses:\n (read.uses as string[] | undefined) ?? sourceUses(read.scriptText ?? ''),\n render: render ? relative(process.cwd(), render) : null,\n stills,\n }\n}\n","/**\n * `vos port inventory` for a Remotion project: the project is bundled with\n * its OWN `@remotion/bundler`, mounted in the CLI's Chrome through the window\n * protocol Remotion's renderer drives (`remotion_setBundleMode`,\n * `remotion_setFrame`, `remotion_renderReady`), and read the way a page is:\n * computed faces, sizes and colours, boxes, at a frame inside each scene.\n * Scenes are the composition's `<Sequence>` windows, named by the component\n * they hold; audio is its `<Audio>`; the palette is the colour constants the\n * source names. Without the project's dependencies it reads nothing and says\n * so, and the inventory falls back to the render.\n */\nimport { existsSync, readFileSync, readdirSync, statSync } from 'node:fs'\nimport { createServer } from 'node:http'\nimport type { AddressInfo } from 'node:net'\nimport { createRequire } from 'node:module'\nimport { basename, extname, join } from 'node:path'\nimport { launchBrowser } from '../browser'\nimport { READ_GROUND, READ_PAGE, sourceUses } from './portInventory'\nimport type { InventoryMedia, InventoryText } from './portInventory'\n\nexport interface RemotionSequence {\n from: number\n durationInFrames: number\n /** The component the sequence holds, or its `name` prop. */\n name: string | null\n}\n\nexport interface RemotionScene {\n name: string\n start: number\n duration: number\n ground?: string | null\n}\n\n/** Colour constants a source names (`export const INK = '#0B0B0F'`), pure. */\nexport function themeColors(sources: string[]): Record<string, string> {\n const out: Record<string, string> = {}\n const re =\n /\\bconst\\s+([A-Za-z_$][\\w$]*)\\s*(?::\\s*string\\s*)?=\\s*['\"](#[0-9a-fA-F]{3,8})['\"]/g\n for (const src of sources)\n for (const m of src.matchAll(re)) {\n const key = m[1]\n .toLowerCase()\n .replace(/_([a-z0-9])/g, (_, c: string) => c.toUpperCase())\n if (!(key in out)) out[key] = m[2].toLowerCase()\n }\n return out\n}\n\n/**\n * The scenes, from the composition's sequences (pure): every sequence with a\n * length, named by what it holds, in seconds; a name used twice is numbered.\n */\nexport function remotionScenes(\n seqs: RemotionSequence[],\n fps: number,\n): RemotionScene[] {\n const seen = new Map<string, number>()\n const live = seqs.filter((s) => s.durationInFrames > 0)\n // A sequence lying over a longer one (a wipe, a flash) is a transition\n // between scenes, never a scene of its own.\n const overlaps = (a: RemotionSequence, b: RemotionSequence) =>\n a.from < b.from + b.durationInFrames && b.from < a.from + a.durationInFrames\n return live\n .filter(\n (s) =>\n !live.some(\n (o) =>\n o !== s &&\n o.durationInFrames > s.durationInFrames &&\n overlaps(o, s),\n ),\n )\n .sort((a, b) => a.from - b.from)\n .map((s, i) => {\n const base = s.name ?? `scene${i + 1}`\n const n = (seen.get(base) ?? 0) + 1\n seen.set(base, n)\n return {\n name: n > 1 ? `${base}${n}` : base,\n start: Math.round((s.from / fps) * 1000) / 1000,\n duration: Math.round((s.durationInFrames / fps) * 1000) / 1000,\n }\n })\n}\n\n/**\n * The texts of every scene, merged (pure): a text read at the same place in\n * most scenes (a HUD line, a brand mark) is one global text with no scene;\n * every other text keeps the scene it was read in, once.\n */\nexport function mergeSceneTexts(\n perScene: { scene: string; texts: InventoryText[] }[],\n): InventoryText[] {\n const sig = (t: InventoryText) =>\n `${t.text}|${t.font.family}|${t.font.size}|${t.box ? `${Math.round(t.box.x / 8)},${Math.round(t.box.y / 8)}` : '-'}`\n const counts = new Map<string, number>()\n for (const s of perScene)\n for (const k of new Set(s.texts.map(sig)))\n counts.set(k, (counts.get(k) ?? 0) + 1)\n const global =\n perScene.length >= 3 ? Math.ceil(perScene.length / 2) : Infinity\n const out: InventoryText[] = []\n const placed = new Set<string>()\n const textPlaced = new Set<string>()\n for (const s of perScene)\n for (const t of s.texts) {\n const k = sig(t)\n const shared = (counts.get(k) ?? 0) >= global\n const id = shared ? k : `${s.scene}|${k}`\n if (placed.has(id)) continue\n // A counter (a timecode, a running number) reads differently in every\n // scene: its first reading stands for it.\n const shape = `${t.text.replace(/\\d/g, '0')}|${t.font.family}|${t.box ? Math.round(t.box.y / 8) : '-'}`\n if (/\\d/.test(t.text) && textPlaced.has(shape)) continue\n placed.add(id)\n textPlaced.add(shape)\n out.push({\n ...t,\n // A tag-numbered id stays tag-numbered (the scaffold then names the\n // key after the words); a real id is kept as the source wrote it.\n id: /^[a-z][a-z0-9]*-\\d+$/.test(t.id) ? `${t.tag}-${out.length}` : t.id,\n scene: shared ? null : s.scene,\n })\n }\n return out\n}\n\n/** The project's source files, for the colour constants (bounded). */\nfunction sourceTexts(dir: string): string[] {\n const out: string[] = []\n const walk = (d: string, depth: number) => {\n if (depth > 4 || out.length > 200) return\n for (const name of readdirSync(d)) {\n if (name === 'node_modules' || name.startsWith('.')) continue\n const p = join(d, name)\n if (statSync(p).isDirectory()) walk(p, depth + 1)\n else if (/\\.(tsx?|jsx?|mjs)$/.test(name))\n out.push(readFileSync(p, 'utf8'))\n }\n }\n const src = join(dir, 'src')\n walk(existsSync(src) ? src : dir, 0)\n return out\n}\n\n/** The entry `registerRoot` lives in: Remotion's conventional paths. */\nfunction entryPoint(dir: string): string | null {\n for (const p of [\n 'src/index.ts',\n 'src/index.tsx',\n 'src/index.js',\n 'src/index.jsx',\n 'remotion/index.ts',\n 'remotion/index.tsx',\n ])\n if (existsSync(join(dir, p))) return join(dir, p)\n return null\n}\n\nconst TYPES: Record<string, string> = {\n '.html': 'text/html',\n '.js': 'text/javascript',\n '.css': 'text/css',\n '.json': 'application/json',\n '.woff2': 'font/woff2',\n '.woff': 'font/woff',\n '.ttf': 'font/ttf',\n '.png': 'image/png',\n '.jpg': 'image/jpeg',\n '.svg': 'image/svg+xml',\n '.wav': 'audio/wav',\n '.mp3': 'audio/mpeg',\n '.ogg': 'audio/ogg',\n '.mp4': 'video/mp4',\n '.webm': 'video/webm',\n}\n\n/** The window state Remotion's renderer sets before the bundle loads. */\nconst INIT = `(() => {\n window.remotion_puppeteerTimeout = 30000\n window.remotion_isMainTab = true\n window.remotion_mediaCacheSizeInBytes = 100000000\n window.remotion_initialMemoryAvailable = 1000000000\n window.remotion_sampleRate = 48000\n window.process = window.process || {}\n window.process.env = window.process.env || {}\n window.process.env.NODE_ENV = 'production'\n window.remotion_envVariables = '{}'\n window.remotion_inputProps = '{}'\n window.remotion_initialFrame = 0\n window.remotion_attempt = 1\n window.remotion_audioEnabled = false\n window.remotion_videoEnabled = false\n window.remotion_logLevel = 'error'\n})()`\n\n/** The composition's sequences and audio, from React's fibers. */\nconst READ_TREE = `(() => {\n let fiber = null\n for (const el of document.querySelectorAll('body, body *')) {\n const k = Object.keys(el).find((k) => k.startsWith('__reactFiber$') || k.startsWith('__reactContainer$'))\n if (k) { fiber = el[k]; break }\n }\n while (fiber && fiber.return) fiber = fiber.return\n const nameOf = (t) => t && (t.displayName || t.name || (t.render && (t.render.displayName || t.render.name))) || null\n const internal = /^(Sequence|AbsoluteFill|Freeze|Loop|Series|Fragment)$|Provider|Context|Forwarding|^Inner/\n const seqs = []\n const audio = []\n const walk = (f, offset) => {\n for (let x = f; x; x = x.sibling) {\n const name = nameOf(x.elementType)\n const p = x.memoizedProps || {}\n let next = offset\n if (name === 'Sequence' && typeof p.from === 'number') {\n next = offset + p.from\n if (typeof p.durationInFrames === 'number' && isFinite(p.durationInFrames)) {\n const kids = Array.isArray(p.children) ? p.children : [p.children]\n const held = kids.map((k) => k && nameOf(k.type)).find((n) => n && !internal.test(n))\n seqs.push({ from: next, durationInFrames: p.durationInFrames, name: p.name || held || null })\n }\n }\n if (name && /Audio$/.test(name) && typeof p.src === 'string')\n audio.push({ src: p.src, from: next, volume: typeof p.volume === 'number' ? p.volume : null, startFrom: typeof p.startFrom === 'number' ? p.startFrom : (typeof p.trimBefore === 'number' ? p.trimBefore : null) })\n if (x.child) walk(x.child, next)\n }\n }\n walk(fiber, 0)\n // Nested sequences repeat their parent's window at the same offset: keep the outermost.\n const seen = new Set()\n return { seqs: seqs.filter((s) => { const k = s.from + ':' + s.durationInFrames; if (seen.has(k)) return false; seen.add(k); return true }), audio }\n})()`\n\n/**\n * Read a Remotion project, or null (with the reason logged) when its\n * dependencies are not installed or the bundle does not mount.\n */\nexport async function readRemotion(\n dir: string,\n log?: (l: string) => void,\n): Promise<Record<string, unknown> | null> {\n const entry = entryPoint(dir)\n let bundler: { bundle: (o: Record<string, unknown>) => Promise<string> }\n try {\n bundler = createRequire(join(dir, 'package.json'))('@remotion/bundler')\n } catch {\n log?.(\n 'a Remotion project whose dependencies are not installed: run `npm install` in it so vos can read its compositions (words, scenes, faces); reading only the render',\n )\n return null\n }\n if (!entry) {\n log?.(\n 'a Remotion project with no src/index entry (registerRoot): reading only the render',\n )\n return null\n }\n const out = await bundler.bundle({ entryPoint: entry, onProgress: () => {} })\n const server = createServer((rq, rs) => {\n const path = decodeURIComponent(new URL(rq.url ?? '/', 'http://x').pathname)\n let f = join(out, path)\n if (!f.startsWith(out) || !existsSync(f) || statSync(f).isDirectory())\n f = join(out, 'index.html')\n rs.writeHead(200, {\n 'content-type': TYPES[extname(f)] ?? 'application/octet-stream',\n })\n rs.end(readFileSync(f))\n }).listen(0, '127.0.0.1')\n await new Promise((r) => server.once('listening', r))\n const port = (server.address() as AddressInfo).port\n const browser = await launchBrowser()\n try {\n const ctx = await browser.newContext({\n viewport: { width: 1920, height: 1080 },\n })\n const p = await ctx.newPage()\n await p.addInitScript(INIT)\n await p.goto(`http://127.0.0.1:${port}/index.html`)\n await p.waitForFunction(\n 'typeof window.getStaticCompositions === \"function\"',\n null,\n { timeout: 30000 },\n )\n await p.evaluate(\"window.remotion_setBundleMode({ type: 'evaluation' })\")\n await p.waitForFunction('window.remotion_renderReady === true', null, {\n timeout: 30000,\n })\n const comps = (await p.evaluate('window.getStaticCompositions()')) as {\n id: string\n width: number\n height: number\n fps: number\n durationInFrames: number\n defaultProps?: Record<string, unknown>\n }[]\n if (!comps.length) {\n log?.(\n 'the Remotion project registers no composition: reading only the render',\n )\n return null\n }\n const c = comps[0]\n if (comps.length > 1)\n log?.(`${comps.length} compositions; reading the first, ${c.id}`)\n await p.setViewportSize({ width: c.width, height: c.height })\n await p.evaluate(\n `window.remotion_setBundleMode(${JSON.stringify({\n type: 'composition',\n compositionName: c.id,\n serializedResolvedPropsWithSchema: JSON.stringify(c.defaultProps ?? {}),\n compositionDurationInFrames: c.durationInFrames,\n compositionFps: c.fps,\n compositionHeight: c.height,\n compositionWidth: c.width,\n compositionDefaultCodec: null,\n compositionDefaultOutName: null,\n compositionDefaultVideoImageFormat: null,\n compositionDefaultPixelFormat: null,\n compositionDefaultProResProfile: null,\n compositionDefaultSampleRate: null,\n })})`,\n )\n await p.waitForFunction('window.remotion_renderReady === true', null, {\n timeout: 30000,\n })\n const seek = async (frame: number) => {\n await p.evaluate(\n `window.remotion_setFrame(${frame}, ${JSON.stringify(c.id)}, 1)`,\n )\n await p.waitForFunction('window.remotion_renderReady === true', null, {\n timeout: 30000,\n })\n await p.evaluate('document.fonts && document.fonts.ready')\n }\n await seek(0)\n const tree = (await p.evaluate(READ_TREE)) as {\n seqs: RemotionSequence[]\n audio: {\n src: string\n from: number\n volume: number | null\n startFrom: number | null\n }[]\n }\n let scenes = remotionScenes(tree.seqs, c.fps)\n const total = c.durationInFrames / c.fps\n if (!scenes.length) scenes = [{ name: c.id, start: 0, duration: total }]\n\n // Each scene read nine tenths in, where its words have settled and a scramble has resolved.\n const perScene: { scene: string; texts: InventoryText[] }[] = []\n let first: Record<string, any> | null = null\n const colors = new Set<string>()\n const gaps = new Set<string>()\n for (const s of scenes) {\n const frame = Math.min(\n c.durationInFrames - 1,\n Math.round((s.start + s.duration * 0.9) * c.fps),\n )\n await seek(frame)\n const read = (await p.evaluate(READ_PAGE)) as Record<string, any>\n // A word already leaving at nine tenths has no box: measure it at\n // half way, where it stood.\n const unboxed = (read.texts as InventoryText[]).filter((t) => !t.box)\n if (unboxed.length) {\n await seek(Math.round((s.start + s.duration * 0.5) * c.fps))\n const mid = (await p.evaluate(READ_PAGE)) as { texts: InventoryText[] }\n for (const t of unboxed) {\n const m = mid.texts.find(\n (x) =>\n x.box && x.text === t.text && x.font.family === t.font.family,\n )\n if (m) t.box = m.box\n }\n }\n s.ground = (await p.evaluate(READ_GROUND)) as string | null\n first ??= read\n for (const x of read.colors ?? []) colors.add(x)\n for (const g of read.gaps ?? []) gaps.add(g)\n perScene.push({ scene: s.name, texts: read.texts ?? [] })\n }\n\n const sources = sourceTexts(dir)\n const publicDir = join(dir, 'public')\n const media: InventoryMedia[] = tree.audio.map((a) => {\n const name = basename(a.src.split('?')[0])\n const local = existsSync(join(publicDir, name)) ? `public/${name}` : a.src\n return {\n kind: 'audio',\n src: local,\n start: Math.round((a.from / c.fps) * 1000) / 1000,\n duration: null,\n volume: a.volume,\n mediaStart:\n a.startFrom != null\n ? Math.round((a.startFrom / c.fps) * 1000) / 1000\n : null,\n }\n })\n return {\n width: c.width,\n height: c.height,\n fps: c.fps,\n duration: Math.round(total * 1000) / 1000,\n texts: mergeSceneTexts(perScene),\n palette: themeColors(sources),\n uses: sourceUses(sources.join('\\n')),\n colors: [...colors],\n gaps: [...gaps],\n media,\n canvases: (first?.canvases as unknown[]) ?? [],\n scenes,\n sceneEls: [],\n variables: c.defaultProps ?? {},\n scriptText: '',\n composition: c.id,\n }\n } catch (e) {\n log?.(\n `the Remotion bundle did not mount (${e instanceof Error ? e.message.split('\\n')[0] : String(e)}): reading only the render`,\n )\n return null\n } finally {\n await browser.close()\n server.close()\n }\n}\n","/**\n * `vos port scaffold` — an inventory turned into a program that already\n * keeps the port grammar: every word a data key bound to a text element,\n * every colour a data key, the faces from the catalog, the knobs over them,\n * a label per scene, the score as a document track. What it cannot know is\n * the motion: each scene carries a TODO where the agent translates it, with\n * the vos-port skill's tables open.\n */\nimport { spawnSync } from 'node:child_process'\nimport { copyFileSync, existsSync, mkdirSync, writeFileSync } from 'node:fs'\nimport { basename, dirname, join, resolve } from 'node:path'\nimport { findFontFamily, fontFaceUrl, nearestFontWeight } from '@vosjs/shared'\nimport { PAINTER_LIB } from './painterLib'\nimport type { Inventory, InventoryText } from './portInventory'\n\nconst DESIGN_HEIGHT = 1080\n\n/** `#rrggbb` (or `#rrggbbaa`) for a CSS colour the browser computed (pure). */\nexport function toHex(css: string): string {\n const s = css.trim()\n if (/^#[0-9a-f]{3,8}$/i.test(s)) {\n if (s.length === 4)\n return `#${[...s.slice(1)].map((c) => c + c).join('')}`.toLowerCase()\n return s.toLowerCase()\n }\n const m =\n /^rgba?\\(\\s*([\\d.]+)[,\\s]+([\\d.]+)[,\\s]+([\\d.]+)(?:[,/\\s]+([\\d.]+%?))?\\s*\\)$/i.exec(\n s,\n )\n if (!m) return s\n const hex = (v: number) =>\n Math.round(Math.max(0, Math.min(255, v)))\n .toString(16)\n .padStart(2, '0')\n let a =\n m[4] === undefined\n ? 1\n : m[4].endsWith('%')\n ? Number(m[4].slice(0, -1)) / 100\n : Number(m[4])\n if (!Number.isFinite(a)) a = 1\n return `#${hex(+m[1])}${hex(+m[2])}${hex(+m[3])}${a < 1 ? hex(a * 255) : ''}`\n}\n\n/** A JS identifier from any label (pure), unique against `taken`. */\nexport function keyFor(\n label: string,\n taken: Set<string>,\n prefix = 't',\n): string {\n const words = label\n .replace(/[^A-Za-z0-9]+/g, ' ')\n .trim()\n .split(' ')\n .filter(Boolean)\n .slice(0, 4)\n let base = words\n .map((w, i) =>\n i === 0 ? w.toLowerCase() : w[0].toUpperCase() + w.slice(1).toLowerCase(),\n )\n .join('')\n if (!base || /^[0-9]/.test(base)) base = prefix + (base || '')\n let key = base\n for (let n = 2; taken.has(key); n++) key = `${base}${n}`\n taken.add(key)\n return key\n}\n\n/** A catalog face for a family the catalog lacks, by what its name says (pure). */\nexport function substituteFamily(family: string): string {\n const f = family.toLowerCase()\n if (/mono|code|courier/.test(f)) return 'JetBrains Mono'\n if (/serif/.test(f) && !/sans/.test(f)) return 'Source Serif 4'\n if (/condensed|compressed|black|anton|bebas|oswald/.test(f)) return 'Anton'\n return 'Inter'\n}\n\nexport interface ScaffoldPlan {\n program: string\n doc: Record<string, unknown>\n report: string\n /** Files to copy beside the program: [from, to-basename]. */\n copies: [string, string][]\n}\n\nconst fmtPct = (v: number) => `${Math.round(v * 10000) / 100}%`\n\n/** Plan the scaffold from an inventory (pure but for the score's duration probe). */\nexport function planScaffold(\n inv: Inventory,\n opts: { sourceDir: string; probeDuration?: (file: string) => number | null },\n): ScaffoldPlan {\n const taken = new Set<string>(['scenes', 'bg'])\n const data: Record<string, unknown> = {}\n const report: string[] = []\n const scale = DESIGN_HEIGHT / (inv.height || DESIGN_HEIGHT)\n\n // ── palette: the colours the source names (custom properties, constants) first ──\n const colorKey = new Map<string, string>()\n for (const [name, value] of Object.entries(inv.palette)) {\n const key = keyFor(name, taken, 'color')\n const hex = toHex(value)\n data[key] = hex\n if (!colorKey.has(hex)) colorKey.set(hex, key)\n }\n const colorOf = (css: string): string => {\n const hex = toHex(css)\n const known = colorKey.get(hex)\n if (known) return known\n const key = keyFor(`color ${colorKey.size + 1}`, taken, 'color')\n data[key] = hex\n colorKey.set(hex, key)\n return key\n }\n data.bg = inv.colors.length ? toHex(inv.colors[0]) : '#000000'\n\n // ── words: one key and one bound element each ──\n const faces = new Map<\n string,\n {\n family: string\n weights: Set<number>\n italic: boolean\n from: string | null\n }\n >()\n const faceFor = (t: InventoryText) => {\n const hit = findFontFamily(t.font.family)\n const family = hit?.family ?? substituteFamily(t.font.family)\n const face = faces.get(family) ?? {\n family,\n weights: new Set(),\n italic: false,\n from: hit ? null : t.font.family,\n }\n face.weights.add(t.font.weight)\n if (t.font.style === 'italic') face.italic = true\n faces.set(family, face)\n return family\n }\n const elements: Record<string, unknown>[] = []\n const textKeys: { key: string; size: number; label: string }[] = []\n const sceneNames = new Set(inv.scenes.map((s) => s.name))\n const sceneElements: Record<string, string[]> = {}\n for (const t of inv.texts) {\n const generic = /^(div|span|p|h[1-6]|li|a|b|i|em|strong)-\\d+$/.test(t.id)\n const key = keyFor(generic ? t.text : t.id, taken)\n const words =\n t.font.transform === 'uppercase'\n ? t.text.toUpperCase()\n : t.font.transform === 'lowercase'\n ? t.text.toLowerCase()\n : t.text\n data[key] = words\n const family = faceFor(t)\n elements.push({\n id: key,\n type: 'text',\n content: { $data: key },\n ...(t.split ? { split: { type: t.split } } : {}),\n position: t.box\n ? { x: fmtPct(t.box.x / inv.width), y: fmtPct(t.box.y / inv.height) }\n : 'center',\n font: {\n family,\n size: Math.round(t.font.size * scale),\n weight: t.font.weight,\n ...(t.font.style === 'italic' ? { style: 'italic' } : {}),\n color: { $data: colorOf(t.font.color) },\n ...(t.font.letterSpacing\n ? {\n letterSpacing: Math.round(t.font.letterSpacing * scale * 10) / 10,\n }\n : {}),\n },\n })\n textKeys.push({ key, size: t.font.size, label: words.slice(0, 40) })\n if (t.scene && sceneNames.has(t.scene))\n (sceneElements[t.scene] ??= []).push(key)\n }\n\n // ── faces: catalog URLs, substitutions said ──\n const fonts: Record<string, unknown>[] = []\n for (const face of faces.values()) {\n const entry = findFontFamily(face.family)\n if (!entry) continue\n for (const w of face.weights) {\n const weight = nearestFontWeight(entry, w)\n fonts.push({\n family: entry.family,\n weight,\n url: fontFaceUrl(entry.slug, weight),\n })\n }\n if (face.italic) {\n const italics = (entry as { italics?: number[] }).italics ?? []\n if (italics.length) {\n const weight = italics.includes(400) ? 400 : italics[0]\n fonts.push({\n family: entry.family,\n weight,\n style: 'italic',\n url: fontFaceUrl(entry.slug, weight, 'italic'),\n })\n }\n }\n }\n\n // Faces the source paints with outside a text node (a canvas script's font\n // stacks): declared at every hosted weight, so the painter draws with them.\n const painterFaces: string[] = []\n for (const f of inv.fonts) {\n if (!f.catalog || faces.has(f.catalog)) continue\n const entry = findFontFamily(f.catalog)\n if (!entry) continue\n for (const weight of entry.weights)\n fonts.push({\n family: entry.family,\n weight,\n url: fontFaceUrl(entry.slug, weight),\n })\n for (const weight of (entry as { italics?: number[] }).italics ?? [])\n fonts.push({\n family: entry.family,\n weight,\n style: 'italic',\n url: fontFaceUrl(entry.slug, weight, 'italic'),\n })\n painterFaces.push(entry.family)\n }\n for (const f of inv.fonts) {\n if (\n !f.catalog &&\n !faces.has(substituteFamily(f.family)) &&\n !inv.texts.some((t) => t.font.family === f.family)\n )\n report.push(\n `- **${f.family}** (named in the scripts) is not in the catalog: draw with ${substituteFamily(f.family)} and say so in the push note`,\n )\n }\n if (painterFaces.length)\n report.push(\n `- faces the scripts paint with, declared at every hosted weight for the painter: ${painterFaces.join(', ')}`,\n )\n\n // ── scenes ──\n data.scenes = inv.scenes.map((s) => ({\n name: s.name,\n at: s.start,\n ...(s.ground ? { ground: colorOf(s.ground) } : {}),\n until:\n s.duration == null\n ? null\n : Math.round((s.start + s.duration) * 1000) / 1000,\n }))\n // Which words each scene shows: until the motion is translated, a scene's\n // words are on screen exactly in its window, so the scaffold already plays\n // as the source's sequence.\n data.sceneElements = sceneElements\n\n // ── knobs: the palette, then the largest words, up to 12 ──\n const params: Record<string, unknown>[] = []\n const paletteKeys = [...colorKey.values()].slice(0, 6)\n for (const key of paletteKeys)\n params.push({\n key,\n label: key,\n kind: 'color',\n default: data[key],\n group: 'Colours',\n })\n for (const t of [...textKeys].sort((a, b) => b.size - a.size)) {\n if (params.length >= 12) break\n params.push({\n key: t.key,\n label: t.label,\n kind: 'text',\n default: data[t.key],\n group: 'Words',\n })\n }\n const presets = paletteKeys.length\n ? [\n {\n name: 'Original',\n values: Object.fromEntries(paletteKeys.map((k) => [k, data[k]])),\n },\n ]\n : []\n\n const painter = inv.canvases.length > 0 || inv.gaps.length > 0\n const uses = inv.uses ?? []\n // The starter rides along when a painter needs it or the source's motion\n // reaches for its maths (a spring, noise), so the timeline can use it too.\n const lib = painter || uses.length > 0\n if (uses.includes('spring')) data.fps = inv.fps ?? 30\n const duration = Math.round((inv.duration ?? 5) * 1000) / 1000\n const program = programSource({\n source: inv.source,\n duration,\n data,\n params,\n presets,\n fonts,\n elements,\n scenes: inv.scenes,\n painter,\n lib,\n uses,\n })\n\n // ── the score: a document track, the file beside the program ──\n const audio: Record<string, unknown>[] = []\n const copies: [string, string][] = []\n inv.media\n .filter((m) => m.kind === 'audio' && m.src)\n .forEach((m, i) => {\n const from = resolve(opts.sourceDir, m.src as string)\n const name = basename(from)\n if (!existsSync(from)) {\n report.push(\n `- the audio ${m.src} is not in the source folder; add it to doc.json by hand`,\n )\n return\n }\n copies.push([from, name])\n const fileDuration = opts.probeDuration?.(from) ?? m.duration ?? duration\n audio.push({\n id: `score${i ? i + 1 : ''}`,\n key: name,\n name,\n start: m.start ?? 0,\n in: m.mediaStart ?? 0,\n out: Math.min(\n fileDuration,\n (m.mediaStart ?? 0) + (m.duration ?? fileDuration),\n ),\n duration: fileDuration,\n gain: m.volume ?? 1,\n fadeIn: 0,\n fadeOut: 0,\n })\n })\n const short = Math.min(inv.width, inv.height)\n const doc: Record<string, unknown> = {\n program: {},\n audio,\n export: {\n resolution:\n short >= 2160\n ? '4k'\n : short >= 1440\n ? '2k'\n : short >= 1080\n ? '1080p'\n : '720p',\n fps: (inv.fps ?? 30) >= 50 ? 60 : 30,\n format: 'mp4',\n },\n }\n\n return {\n program,\n doc,\n copies,\n report: reportText(inv, {\n faces: [...faces.values()],\n elements: elements.length,\n params: params.length,\n painter,\n uses,\n scores: audio.map((a) => String(a.key)),\n extra: report,\n }),\n }\n}\n\nfunction programSource(p: {\n source: string\n duration: number\n data: Record<string, unknown>\n params: Record<string, unknown>[]\n presets: Record<string, unknown>[]\n fonts: Record<string, unknown>[]\n elements: Record<string, unknown>[]\n scenes: { name: string; start: number; duration: number | null }[]\n painter: boolean\n lib: boolean\n uses: string[]\n}): string {\n const j = (v: unknown) => JSON.stringify(v, null, 2).replace(/\\n/g, '\\n ')\n const sceneTodos = p.scenes.length\n ? p.scenes\n .map(\n (s) =>\n ` // TODO scene \"${s.name}\" (${s.start}s${s.duration ? ` to ${s.start + s.duration}s` : ''}): translate its motion onto ctx.elements.get(id).props / .segments here`,\n )\n .join('\\n')\n : \" // TODO: translate the source's motion here, one block per scene (tl.addLabel above names them)\"\n const springHint = p.uses.includes('spring')\n ? `\n // The source springs. Put a spring ON THE TIMELINE with the spring ease:\n // tl.to(p, { y: 0, ease: 'spring(200)', duration: content.refs.lib.springSeconds({ damping: 200 }) }, at)\n // moves exactly as Remotion's spring({ config: { damping: 200 } }) (a longer\n // duration stretches it, as durationInFrames does). Never compute a spring in\n // onFrame. lib.spring({ frame, fps, config }) is the value, for a painter.`\n : ''\n const libBlock = p.lib ? `\\n${PAINTER_LIB}` : ''\n const painterContent = p.painter\n ? `\n // THE PAINTER (vos-port rule 6): one canvas, only for what no element can\n // say (the inventory's gaps and canvases). It reads every value from\n // ctx.data. Its plane sits above the elements; move its renderOrder\n // between two of them to paint between (SKILL.md \"Layering\").\n const T = ctx.THREE\n const canvas = document.createElement('canvas')\n canvas.width = ctx.resolution.width\n canvas.height = ctx.resolution.height\n const tex = new T.CanvasTexture(canvas)\n tex.colorSpace = T.SRGBColorSpace\n const plane = new T.Mesh(\n new T.PlaneGeometry(1, 1),\n new T.MeshBasicMaterial({ map: tex, transparent: true, depthTest: false, depthWrite: false }),\n )\n plane.scale.set(ctx.resolution.width, ctx.resolution.height, 1)\n plane.renderOrder = 100.995\n plane.frustumCulled = false\n ctx.overlayScene.add(plane)\n return { objects: [], refs: { canvas, g: canvas.getContext('2d'), tex${p.lib ? ', lib' : ''} } }`\n : `\n return { objects: [], refs: {${p.lib ? ' lib ' : ''}} }`\n const painterFrame = p.painter\n ? `\n // Paint the procedural layer from ctx.time and ctx.data, then upload it.\n const { canvas, g, tex } = content.refs\n g.clearRect(0, 0, canvas.width, canvas.height)\n // TODO: draw what no element can (grain, a blended HUD, noise blobs, masks)\n tex.needsUpdate = true`\n : ''\n return `// Scaffolded by \\`vos port scaffold\\` from ${p.source}.\n// Every word and colour is in \\`data\\`, bound to an element or read by a\n// painter; the knobs sit over them. What is left is the MOTION: translate each\n// scene where it says TODO, with the vos-port skill's tables open. Then:\n// npx vos build program.mjs && npx vos check config.json\n// npx vos compare . --against <the source's render>\nexport default {\n version: 2,\n duration: ${p.duration},\n camera: { preset: 'fullscreen' },\n fonts: ${j(p.fonts)},\n data: ${j(p.data)},\n params: ${j(p.params)},\n presets: ${j(p.presets)},\n elements: ${j(p.elements)},\n\n createContent(ctx) {\n ctx.scene.background = new ctx.THREE.Color(ctx.data.bg)${libBlock}${painterContent}\n },\n\n createTimeline(ctx, content, duration) {\n const tl = ctx.gsap.timeline()\n for (const s of ctx.data.scenes) {\n tl.addLabel(s.name, s.at)\n // Each scene's words show in its window; the motion replaces this.\n for (const id of ctx.data.sceneElements[s.name] || []) {\n // A split word's units carry their own opacity: hide the units.\n const el = ctx.elements.get(id)\n const p = el.segments && el.segments.length ? el.segments : el.props\n if (s.at > 0) {\n tl.set(p, { opacity: 0 }, 0)\n tl.set(p, { opacity: 1 }, s.at)\n }\n if (s.until != null && s.until < duration) tl.set(p, { opacity: 0 }, s.until)\n }\n }\n${sceneTodos}${springHint}\n tl.to({}, { duration }, 0)\n return tl\n },\n\n onFrame(ctx, content) {\n // Each scene's ground, by its palette key; the frame's own colour between them.\n let ground = ctx.data.bg\n for (const s of ctx.data.scenes)\n if (s.ground && ctx.time >= s.at && (s.until == null || ctx.time < s.until))\n ground = ctx.data[s.ground] ?? ground\n ctx.scene.background.set(ground)${painterFrame}\n },\n}\n`\n}\n\nfunction reportText(\n inv: Inventory,\n r: {\n faces: { family: string; from: string | null; italic: boolean }[]\n elements: number\n params: number\n painter: boolean\n uses: string[]\n scores: string[]\n extra: string[]\n },\n): string {\n const lines = [\n `# Port report: ${inv.source === '.' && inv.root ? basename(inv.root) : inv.source}`,\n '',\n `${inv.engine} piece, ${inv.width}×${inv.height}${inv.fps ? ` at ${inv.fps} fps` : ''}, ${inv.duration ?? '?'} s. ` +\n `A program has no size of its own: render it with \\`--width ${inv.width} --height ${inv.height}\\`.`,\n '',\n '## Placed',\n '',\n `- ${r.elements} words as bound text elements, ${Object.keys(inv.palette).length} palette colours the source names (its custom properties or colour constants), ${r.params} knobs.`,\n `- ${inv.scenes.length} scenes as labels${inv.scenes.length ? '' : ' (none declared: name them as you translate)'}.`,\n ...(r.painter || r.uses.length\n ? [\n `- the painter starter as \\`content.refs.lib\\`${r.uses.length ? ` (the source uses ${r.uses.join(', ')})` : ''}: \\`spring\\` (Remotion's, to the frame, \\`durationInFrames\\` included) and \\`springTo\\` (a spring on the timeline, a step per frame), \\`interpolate\\`, \\`bezier\\`, \\`noise2D\\`/\\`noise3D\\` (simplex: \\`@remotion/noise\\`'s character, not its values, so match blobs by eye), \\`random\\`/\\`rng\\`. Use these instead of reading the source engine's code.`,\n ]\n : []),\n ...(r.scores.length\n ? [\n `- the score as a doc.json track (${r.scores.join(', ')}, copied beside the program; vos push uploads it).`,\n ]\n : []),\n '',\n '## Faces',\n '',\n ...r.faces.map((f) =>\n f.from\n ? `- **${f.from}** is not in the catalog: substituted with ${f.family}. Say so in the push note.`\n : `- ${f.family}${f.italic ? ' (italic)' : ''}: from the catalog.`,\n ),\n '',\n '## Needs a painter or an approximation',\n '',\n ...(inv.canvases.length\n ? [\n `- ${inv.canvases.length} canvas${inv.canvases.length === 1 ? '' : 'es'}: the source paints pixels; port those parts as the painter, with their values in data.`,\n ]\n : []),\n ...inv.gaps.map((g) => `- ${g}`),\n ...(r.painter ? [] : ['- nothing: every visible part is an element.']),\n ...(inv.scriptStrings.length && inv.canvases.length\n ? [\n '',\n '## Words the scripts paint',\n '',\n 'The page draws these on its canvas, so no text node holds them. Each one a person reads becomes a data key and a bound element:',\n '',\n ...inv.scriptStrings\n .slice(0, 40)\n .map((s) => `- ${JSON.stringify(s)}`),\n ]\n : []),\n ...(inv.media.some((m) => m.kind === 'image' || m.kind === 'video')\n ? [\n '',\n '## Images and video',\n '',\n 'Not placed: upload each with `vos asset push` and add an image or video element over its hosted URL.',\n '',\n ...inv.media\n .filter((m) => m.kind === 'image' || m.kind === 'video')\n .map((m) => `- ${m.kind} ${m.src ?? '(inline)'}`),\n ]\n : []),\n ...(r.extra.length ? ['', '## Also', '', ...r.extra] : []),\n '',\n '## Reference',\n '',\n inv.render\n ? `The source's render: ${inv.render}. Stills in port/ref/. Check every scene, from where the inventory ran: \\`npx vos compare port/program --against ${inv.render}\\`.`\n : 'No render of the source was found: render it with its own tool and pass it to `vos compare --against`.',\n '',\n ]\n return lines.join('\\n')\n}\n\n/** Write a scaffold to `outDir` (the program, its document, the report, the score). */\nexport function writeScaffold(plan: ScaffoldPlan, outDir: string): void {\n mkdirSync(outDir, { recursive: true })\n writeFileSync(join(outDir, 'program.mjs'), plan.program)\n writeFileSync(\n join(outDir, 'doc.json'),\n JSON.stringify(plan.doc, null, 2) + '\\n',\n )\n writeFileSync(join(dirname(outDir), 'REPORT.md'), plan.report)\n for (const [from, name] of plan.copies) copyFileSync(from, join(outDir, name))\n}\n\nexport function probeAudioDuration(file: string): number | null {\n const res = spawnSync(\n 'ffprobe',\n ['-v', 'error', '-show_entries', 'format=duration', '-of', 'csv=p=0', file],\n { encoding: 'utf8' },\n )\n const d = Number((res.stdout ?? '').trim())\n return Number.isFinite(d) && d > 0 ? Math.round(d * 1000) / 1000 : null\n}\n","/**\n * The painter starter (`vos port scaffold`): the maths every port re-wrote,\n * as one block of plain JavaScript the scaffold writes into a program's\n * `createContent` and returns as `content.refs.lib`, so `createTimeline` and\n * `onFrame` share one definition. Written from the maths, never from another\n * engine's source:\n *\n * - `spring({ frame, fps, config, from, to, delay })`: a damped harmonic\n * oscillator released from rest, solved in closed form (under-, critically\n * and over-damped), with Remotion's signature and defaults (damping 10,\n * mass 1, stiffness 100). Held to Remotion's own values in the tests.\n * - `springTo(tl, target, { key: [from, to] }, at, { fps, config, frames })`:\n * a spring ON THE TIMELINE, as one linear step per frame, exact at every\n * frame, because the tween dialect takes named eases only.\n * - `interpolate(input, inputRange, outputRange, { extrapolateLeft,\n * extrapolateRight, easing })`: any number of stops.\n * - `bezier(x1, y1, x2, y2)`: an easing function (Remotion's `Easing.bezier`).\n * - `noise2D(seed, x, y)`, `noise3D(seed, x, y, z)`: seeded simplex noise in\n * [-1, 1] (Gustavson's construction). The same character as\n * `@remotion/noise`, not its values: a blob is matched by eye, never byte.\n * - `random(seed)` and `rng(seed)`: a seeded value and a seeded generator.\n */\nexport const PAINTER_LIB = ` // THE PAINTER STARTER (vos port): the maths every port re-wrote, in one\n // place: content.refs.lib in createTimeline and onFrame.\n const clamp = (v, lo, hi) => (v < lo ? lo : v > hi ? hi : v)\n const hashSeed = (seed) => {\n if (typeof seed === 'number') return seed | 0\n let h = 2166136261\n for (const ch of String(seed)) h = Math.imul(h ^ ch.charCodeAt(0), 16777619)\n return h | 0\n }\n const rng = (seed) => {\n let s = hashSeed(seed)\n return () => {\n s = (s + 0x6d2b79f5) | 0\n let r = Math.imul(s ^ (s >>> 15), 1 | s)\n r = (r + Math.imul(r ^ (r >>> 7), 61 | r)) ^ r\n return ((r ^ (r >>> 14)) >>> 0) / 4294967296\n }\n }\n const random = (seed) => rng(seed)()\n // interpolate(input, [a, b, ...], [x, y, ...], { extrapolateLeft, extrapolateRight, easing })\n const interpolate = (input, inR, outR, opts = {}) => {\n let i = 1\n while (i < inR.length - 1 && input > inR[i]) i++\n const a = inR[i - 1], b = inR[i]\n let t = b === a ? 0 : (input - a) / (b - a)\n if (t < 0) {\n if (opts.extrapolateLeft === 'clamp') t = 0\n else if (opts.extrapolateLeft === 'identity') return input\n }\n if (t > 1) {\n if (opts.extrapolateRight === 'clamp') t = 1\n else if (opts.extrapolateRight === 'identity') return input\n }\n const e = opts.easing ? opts.easing(t) : t\n return outR[i - 1] + (outR[i] - outR[i - 1]) * e\n }\n // bezier(x1, y1, x2, y2): a CSS cubic-bezier as an easing function.\n const bezier = (x1, y1, x2, y2) => {\n const cx = 3 * x1, bx = 3 * (x2 - x1) - cx, ax = 1 - cx - bx\n const cy = 3 * y1, by = 3 * (y2 - y1) - cy, ay = 1 - cy - by\n const sx = (t) => ((ax * t + bx) * t + cx) * t\n const sy = (t) => ((ay * t + by) * t + cy) * t\n const dx = (t) => (3 * ax * t + 2 * bx) * t + cx\n return (x) => {\n if (x <= 0) return 0\n if (x >= 1) return 1\n let t = x\n for (let k = 0; k < 8; k++) {\n const d = dx(t)\n if (Math.abs(d) < 1e-6) break\n const t2 = t - (sx(t) - x) / d\n if (t2 < 0 || t2 > 1) break\n t = t2\n }\n let lo = 0, hi = 1\n if (Math.abs(sx(t) - x) > 1e-6) {\n t = x\n for (let k = 0; k < 40; k++) {\n if (sx(t) < x) lo = t; else hi = t\n t = (lo + hi) / 2\n }\n }\n return sy(t)\n }\n }\n // spring({ frame, fps, config: { damping, mass, stiffness, overshootClamping }, from, to, delay })\n const springUnit = (t, config = {}) => {\n const m = config.mass ?? 1, k = config.stiffness ?? 100, c = config.damping ?? 10\n const w0 = Math.sqrt(k / m), z = c / (2 * Math.sqrt(k * m))\n if (t <= 0) return 0\n // A damping ratio of 1 or more settles CRITICALLY at the natural\n // frequency, as Remotion's spring does (measured to 1e-16 across\n // overdamped configs; true overdamped motion would crawl, and\n // \\`damping: 200\\` is the smooth spring sources reach for).\n if (z >= 1) return 1 - Math.exp(-w0 * t) * (1 + w0 * t)\n const wd = w0 * Math.sqrt(1 - z * z)\n return 1 - Math.exp(-z * w0 * t) * (Math.cos(wd * t) + ((z * w0) / wd) * Math.sin(wd * t))\n }\n // The frames a spring takes to settle within half a percent and stay there.\n // The spring's continuous settle time in seconds: the duration that makes\n // a tween eased 'spring(damping, stiffness, mass)' (@vosjs/timeline 0.5+)\n // move exactly as Remotion's spring. Same rule and 1 ms step as the ease.\n const springSeconds = (config = {}) => {\n let last = 0\n for (let i = 0; i <= 30000; i++)\n if (Math.abs(springUnit(i * 0.001, config) - 1) >= 0.005) last = i * 0.001\n return last + 0.001\n }\n const springFrames = (fps, config = {}) => {\n let last = 0\n for (let f = 0; f <= fps * 10; f++)\n if (Math.abs(springUnit(f / fps, config) - 1) >= 0.005) last = f\n return last + 1\n }\n // durationInFrames stretches the spring so it settles on that frame, and\n // past it the value IS \\`to\\` (as Remotion's does, measured).\n const spring = ({ frame, fps, config = {}, from = 0, to = 1, delay = 0, durationInFrames }) => {\n const f = Math.max(0, frame - delay)\n if (durationInFrames && f > durationInFrames) return to\n const scale = durationInFrames ? springFrames(fps, config) / durationInFrames : 1\n let x = springUnit((f * scale) / fps, config)\n if (config.overshootClamping && x > 1) x = 1\n return from + (to - from) * x\n }\n // springTo(tl, target, { x: [from, to] }, at, { fps, config, frames }): the\n // spring on the timeline, one linear step per frame; returns its end time.\n const springTo = (tl, target, props, at, opts = {}) => {\n const fps = opts.fps || 30\n const frames = opts.frames ?? springFrames(fps, opts.config)\n const keys = Object.keys(props)\n const start = {}\n for (const k of keys) start[k] = props[k][0]\n tl.set(target, start, at)\n for (let f = 1; f <= frames; f++) {\n const s = f === frames ? 1 : spring({ frame: f, fps, config: opts.config })\n const v = { duration: 1 / fps, ease: 'none' }\n for (const k of keys) v[k] = props[k][0] + (props[k][1] - props[k][0]) * s\n tl.to(target, v, at + (f - 1) / fps)\n }\n return at + frames / fps\n }\n // Seeded simplex noise in [-1, 1] (Gustavson's construction).\n const grad3 = [[1,1,0],[-1,1,0],[1,-1,0],[-1,-1,0],[1,0,1],[-1,0,1],[1,0,-1],[-1,0,-1],[0,1,1],[0,-1,1],[0,1,-1],[0,-1,-1]]\n const perms = new Map()\n const perm = (seed) => {\n const key = String(seed)\n let p = perms.get(key)\n if (!p) {\n const r = rng(seed)\n const base = Array.from({ length: 256 }, (_, i) => i)\n for (let i = 255; i > 0; i--) {\n const j = Math.floor(r() * (i + 1))\n const t = base[i]; base[i] = base[j]; base[j] = t\n }\n p = new Uint8Array(512)\n for (let i = 0; i < 512; i++) p[i] = base[i & 255]\n perms.set(key, p)\n }\n return p\n }\n const noise2D = (seed, x, y) => {\n const p = perm(seed)\n const F2 = 0.5 * (Math.sqrt(3) - 1), G2 = (3 - Math.sqrt(3)) / 6\n const s = (x + y) * F2\n const i = Math.floor(x + s), j = Math.floor(y + s)\n const t = (i + j) * G2\n const x0 = x - (i - t), y0 = y - (j - t)\n const i1 = x0 > y0 ? 1 : 0, j1 = x0 > y0 ? 0 : 1\n const x1 = x0 - i1 + G2, y1 = y0 - j1 + G2\n const x2 = x0 - 1 + 2 * G2, y2 = y0 - 1 + 2 * G2\n const ii = i & 255, jj = j & 255\n const corner = (gi, cx, cy) => {\n const tt = 0.5 - cx * cx - cy * cy\n if (tt < 0) return 0\n const g = grad3[gi % 12]\n return tt * tt * tt * tt * (g[0] * cx + g[1] * cy)\n }\n return 70 * (corner(p[ii + p[jj]], x0, y0) + corner(p[ii + i1 + p[jj + j1]], x1, y1) + corner(p[ii + 1 + p[jj + 1]], x2, y2))\n }\n const noise3D = (seed, x, y, z) => {\n const p = perm(seed)\n const F3 = 1 / 3, G3 = 1 / 6\n const s = (x + y + z) * F3\n const i = Math.floor(x + s), j = Math.floor(y + s), k = Math.floor(z + s)\n const t = (i + j + k) * G3\n const x0 = x - (i - t), y0 = y - (j - t), z0 = z - (k - t)\n let i1, j1, k1, i2, j2, k2\n if (x0 >= y0) {\n if (y0 >= z0) { i1 = 1; j1 = 0; k1 = 0; i2 = 1; j2 = 1; k2 = 0 }\n else if (x0 >= z0) { i1 = 1; j1 = 0; k1 = 0; i2 = 1; j2 = 0; k2 = 1 }\n else { i1 = 0; j1 = 0; k1 = 1; i2 = 1; j2 = 0; k2 = 1 }\n } else {\n if (y0 < z0) { i1 = 0; j1 = 0; k1 = 1; i2 = 0; j2 = 1; k2 = 1 }\n else if (x0 < z0) { i1 = 0; j1 = 1; k1 = 0; i2 = 0; j2 = 1; k2 = 1 }\n else { i1 = 0; j1 = 1; k1 = 0; i2 = 1; j2 = 1; k2 = 0 }\n }\n const ii = i & 255, jj = j & 255, kk = k & 255\n const corner = (gi, cx, cy, cz) => {\n const tt = 0.6 - cx * cx - cy * cy - cz * cz\n if (tt < 0) return 0\n const g = grad3[gi % 12]\n return tt * tt * tt * tt * (g[0] * cx + g[1] * cy + g[2] * cz)\n }\n return 32 * (\n corner(p[ii + p[jj + p[kk]]], x0, y0, z0) +\n corner(p[ii + i1 + p[jj + j1 + p[kk + k1]]], x0 - i1 + G3, y0 - j1 + G3, z0 - k1 + G3) +\n corner(p[ii + i2 + p[jj + j2 + p[kk + k2]]], x0 - i2 + 2 * G3, y0 - j2 + 2 * G3, z0 - k2 + 2 * G3) +\n corner(p[ii + 1 + p[jj + 1 + p[kk + 1]]], x0 - 1 + 3 * G3, y0 - 1 + 3 * G3, z0 - 1 + 3 * G3))\n }\n const lib = { clamp, interpolate, bezier, spring, springFrames, springSeconds, springTo, noise2D, noise3D, random, rng }`\n","/**\n * `vos recipe` — put a recipe document on the shelf. A recipe is a plain\n * markdown ASSET (category `recipe`), the one asset an agent is expected to\n * WRITE: the write-back prompt line and the kept-prior-body history exist\n * for exactly this act, and until now the CLI had no verb for it.\n *\n * vos recipe push <file.md> --folder <folderId|slug> [--json] create\n * vos recipe push <file.md> --asset <assetId> [--json] replace\n *\n * Create goes through the upload door (declared, sent, sealed; filed into the folder you\n * pulled); replace is `PUT /assets/:id/file` (raw markdown, same id and\n * fileUrl, the displaced body kept as the one prior version). ONE verb for\n * both because from the agent's side they are the same act: put this\n * document where the collection reads it. Reading is `vos folder pull`\n * (every recipe, inherited ones included); restore stays a human gesture\n * on the recipe page — a verb that undoes the owner's edit is not one to\n * hand an agent.\n */\nimport { createHash } from 'node:crypto'\nimport { readFileSync } from 'node:fs'\nimport { basename } from 'node:path'\nimport { UsageError, parseArgs, strFlag } from './args'\nimport { listFolders, resolveFolder } from './folder'\nimport { EXIT_OK, createReporter } from './output'\nimport { uploadAsset } from './uploadAsset'\nimport {\n apiError,\n apiJson,\n platformOrigin,\n requireCredential,\n} from './platform'\n\nconst BOOLEAN_FLAGS = new Set(['json', 'help'])\nconst USAGE =\n 'vos recipe push <file.md> (--folder <folderId|slug> | --asset <assetId>)'\n\n/** The server holds recipes to .md; refuse locally so the error names the file. */\nexport function recipeFilename(file: string): string {\n const name = basename(file)\n if (!/\\.md$/i.test(name)) {\n throw new UsageError(`a recipe is a markdown file — ${name} is not .md`)\n }\n return name\n}\n\nasync function cmdPush(argv: string[]): Promise<number> {\n const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS)\n const [file] = positionals\n const folderRef = strFlag(flags, 'folder')\n const assetId = strFlag(flags, 'asset')\n if (!file || (!folderRef && !assetId) || (folderRef && assetId)) {\n throw new UsageError(USAGE)\n }\n const filename = recipeFilename(file)\n const body = readFileSync(file)\n const r = createReporter(flags.json === true)\n const origin = platformOrigin({\n origin: strFlag(flags, 'origin'),\n api: strFlag(flags, 'api'),\n })\n const key = requireCredential(strFlag(flags, 'key'))\n\n if (assetId) {\n const res = await apiJson(origin, `/api/assets/${assetId}/file`, {\n method: 'PUT',\n key,\n raw: new Uint8Array(body),\n headers: { 'content-type': 'text/markdown' },\n })\n if (res.status !== 200) {\n throw new Error(apiError(`replace recipe ${assetId}`, res))\n }\n r.done(\n { id: assetId, filename: res.body.filename, replaced: true },\n `replaced recipe ${assetId} (${String(res.body.filename)}) in place — the prior body is kept, restore it from the recipe page`,\n )\n return EXIT_OK\n }\n\n const folder = resolveFolder(await listFolders(origin, key), folderRef!)\n let put\n try {\n put = await uploadAsset({ origin, key }, new Uint8Array(body), {\n filename,\n contentType: 'text/markdown',\n contentHash: createHash('sha256').update(body).digest('hex'),\n intent: 'library',\n folderId: folder.id,\n })\n } catch (e) {\n throw new Error(\n `push recipe ${filename}: ${e instanceof Error ? e.message : String(e)}`,\n )\n }\n const meta = put.metadata ?? {}\n // The SERVER names the file (a recipe a key files takes the CAPS\n // convention, CUT.md), so report what landed — never the local basename,\n // or the terminal and the shelf describe the same recipe differently.\n const stored = put.filename || filename\n r.done(\n {\n id: put.id,\n filename: stored,\n folder: folder.slug,\n name: meta.name,\n description: meta.description,\n ...(put.notes.length ? { notes: put.notes } : {}),\n },\n `pushed ${stored} into ${folder.slug} (${put.id})${\n typeof meta.name === 'string' ? ` — ${meta.name}` : ''\n }\\nReplace it later with: vos recipe push ${file} --asset ${put.id}`,\n )\n return EXIT_OK\n}\n\nexport async function cmdRecipe(argv: string[]): Promise<number> {\n const sub = argv[0]\n const rest = argv.slice(1)\n switch (sub) {\n case 'push':\n return cmdPush(rest)\n default:\n throw new UsageError(`vos recipe <push> — ${USAGE}`)\n }\n}\n","/**\n * `vos brand <url>` — the brand kit, witnessed. The launch-kit loop must\n * resolve the brand BEFORE any asset is authored (a template's own palette\n * on a deliverable shipped once, and that run is why this verb exists).\n * The kit is a `BRAND.md` recipe: frontmatter carries the roles the poster\n * family binds (`bgA/bgB/bgC`, `ink`, `accent`, `fontDisplay`, `logoUrl`),\n * prose carries where each value came from and what the site says to avoid.\n *\n * Three sources, in order, each read when it exists:\n * 1. `/design.md` — the convention Vercel is teaching companies to\n * publish beside `/llms.txt`: prose for agents, font names, logo\n * assets, a reject list. Colours there are usually CSS variable names,\n * not values, so it never replaces witnessing; it wins on fonts, logos\n * and the avoid list.\n * 2. `/llms.txt` — the product's name and one-line claim.\n * 3. The page itself, in a browser: theme-color, icons, og:image, the\n * computed heading and body faces and inks, the body ground, the\n * surfaces, and the accent (the saturated colour buttons and links\n * agree on).\n *\n * Everything is a pure function over fetched text and one witnessed object,\n * so the composition is testable without a browser.\n */\nimport { catalogFamily } from './fontName'\nimport { writeFile } from 'node:fs/promises'\nimport { resolve } from 'node:path'\nimport { parseFrontmatter } from '@vosjs/shared/frontmatter'\nimport { lookKindForGround } from '@vosjs/studio-core'\nimport { UsageError, parseArgs, strFlag } from './args'\nimport { createReporter } from './output'\nimport { launchBrowser } from '../browser'\nimport type { Browser } from 'playwright'\n\nexport interface BrandKit {\n name: string\n site: string\n witnessed: string\n bgA: string\n bgB: string\n bgC: string\n ink: string\n accent: string\n fontDisplay: string\n fontBody: string\n logoUrl: string | null\n /** The mark for dark grounds (a design.md asset named on-dark or white), when the site publishes one. */\n logoOnDarkUrl: string | null\n iconUrl: string | null\n ogImage: string | null\n wordmark: string\n designMd: string | null\n llmsTxt: string | null\n /**\n * The look the kit's cards and cuts are presented in, decided from the\n * site's own ground: a paper site is a plate, a dark site is dark,\n * anything else takes the gradient (accent → bgC). The maker overrides\n * it by editing the role; `ground` (absent here) overrides the ground.\n */\n look: 'plate' | 'gradient' | 'dark'\n}\n\nexport interface DesignMdFacts {\n name: string | null\n description: string | null\n fonts: string[]\n logos: string[]\n hexes: string[]\n avoid: string[]\n}\n\nexport interface Witness {\n title: string\n siteName: string | null\n themeColor: string | null\n icons: string[]\n ogImage: string | null\n h1: { fontFamily: string; color: string } | null\n body: { fontFamily: string; color: string; backgroundColor: string }\n /** Background colours of sections, headers, cards, in document order. */\n surfaces: string[]\n /** Background colours of buttons and the colours of links. */\n accents: string[]\n}\n\nconst HEX_RE = /#(?:[0-9a-f]{6}|[0-9a-f]{3})\\b/gi\n\n/** Every hex colour in a text, in order, deduped, lowercased. */\nexport function extractHexes(text: string): string[] {\n const out: string[] = []\n for (const m of text.match(HEX_RE) ?? []) {\n const h = normalizeHex(m)\n if (h && !out.includes(h)) out.push(h)\n }\n return out\n}\n\n/** `#abc` → `#aabbcc`; anything else lowercased; null when not a hex. */\nexport function normalizeHex(raw: string): string | null {\n const m = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(raw.trim())\n if (!m) return null\n const h = m[1].toLowerCase()\n return (\n '#' +\n (h.length === 3\n ? h\n .split('')\n .map((c) => c + c)\n .join('')\n : h)\n )\n}\n\n/** `rgb(1, 2, 3)` / `rgba(1,2,3,.5)` → `#010203`, or null (transparent, none). */\nexport function rgbToHex(raw: string): string | null {\n const m =\n /rgba?\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)(?:\\s*,\\s*([\\d.]+))?\\s*\\)/.exec(raw)\n if (!m) return normalizeHex(raw)\n const alpha = m[4] as string | undefined\n if (alpha !== undefined && Number(alpha) === 0) return null\n const hex = (n: string) => Number(n).toString(16).padStart(2, '0')\n return `#${hex(m[1])}${hex(m[2])}${hex(m[3])}`\n}\n\nfunction hsl(hex: string): { h: number; s: number; l: number } {\n const r = parseInt(hex.slice(1, 3), 16) / 255\n const g = parseInt(hex.slice(3, 5), 16) / 255\n const b = parseInt(hex.slice(5, 7), 16) / 255\n const max = Math.max(r, g, b)\n const min = Math.min(r, g, b)\n const l = (max + min) / 2\n const d = max - min\n const s = d === 0 ? 0 : d / (1 - Math.abs(2 * l - 1))\n let h = 0\n if (d !== 0) {\n if (max === r) h = ((g - b) / d) % 6\n else if (max === g) h = (b - r) / d + 2\n else h = (r - g) / d + 4\n h = (h * 60 + 360) % 360\n }\n return { h, s, l }\n}\n\n/** A colour with real chroma: neither a neutral nor near-white/black. */\nexport function isSaturated(hex: string): boolean {\n const { s, l } = hsl(hex)\n return s >= 0.25 && l > 0.12 && l < 0.88\n}\n\nconst isLight = (hex: string) => hsl(hex).l >= 0.5\n\n/** Mix `b` into `a` by `t` (0..1), in sRGB, as hex. */\nexport function mixHex(a: string, b: string, t: number): string {\n const ch = (i: number) =>\n Math.round(\n parseInt(a.slice(i, i + 2), 16) * (1 - t) +\n parseInt(b.slice(i, i + 2), 16) * t,\n )\n .toString(16)\n .padStart(2, '0')\n return `#${ch(1)}${ch(3)}${ch(5)}`\n}\n\n/** The most frequent entry, ties by first appearance. */\nfunction mostCommon(values: string[]): string | null {\n const counts = new Map<string, number>()\n for (const v of values) counts.set(v, (counts.get(v) ?? 0) + 1)\n let best: string | null = null\n let n = 0\n for (const [v, c] of counts)\n if (c > n) {\n best = v\n n = c\n }\n return best\n}\n\n/** The first family of a CSS `font-family` list, unquoted. */\nexport function firstFamily(fontFamily: string): string {\n const first = fontFamily.split(',')[0]?.trim() ?? ''\n return first.replace(/^[\"']|[\"']$/g, '')\n}\n\nconst FONT_HINT_RE =\n /\\b(?:[Uu]se|[Uu]ses|[Ss]et in)\\s+([A-Z][A-Za-z0-9]+(?:\\s+[A-Z][A-Za-z0-9]+){0,3}(?:\\s+(?:Sans|Serif|Mono|Display|Text))?)\\s+(?:for|as|on|everywhere|only)\\b/g\nconst FONT_FAMILY_RE = /font-family\\s*:\\s*[\"']?([^;\"',\\n]+)/gi\nconst LOGO_URL_RE =\n /https?:\\/\\/[^\\s)\"'<>]+?(?:logo|wordmark|mark|brand|icon)[^\\s)\"'<>]*?\\.(?:svg|png|webp)/gi\n\n/**\n * What a `/design.md` says, without pretending it is structured: the\n * frontmatter's name and description, the font families it names (\"Use\n * Geist Sans for prose\"), the logo assets it links, any hex colours it\n * quotes, and the bullets of its reject / avoid / never section verbatim.\n */\nexport function parseDesignMd(text: string): DesignMdFacts {\n const fm = parseFrontmatter(text)\n const fonts: string[] = []\n for (const m of text.matchAll(FONT_HINT_RE)) {\n const f = m[1].trim()\n if (!fonts.includes(f) && !/^(The|This|That|Use|It|A|An)$/.test(f))\n fonts.push(f)\n }\n for (const m of text.matchAll(FONT_FAMILY_RE)) {\n const f = m[1].trim().replace(/^[\"']|[\"']$/g, '')\n if (f && !fonts.includes(f)) fonts.push(f)\n }\n const logos: string[] = []\n for (const m of text.matchAll(LOGO_URL_RE))\n if (!logos.includes(m[0])) logos.push(m[0])\n const avoid: string[] = []\n const lines = text.split('\\n')\n let inAvoid = false\n for (const line of lines) {\n const heading = /^#{1,6}\\s+(.*)$/.exec(line)\n if (heading) {\n inAvoid = /\\b(reject|avoid|never|don'?t|do not|anti-?patterns?)\\b/i.test(\n heading[1],\n )\n continue\n }\n if (!inAvoid) continue\n const bullet = /^\\s*(?:[-*]|\\d+\\.)\\s+(.*)$/.exec(line)\n if (bullet) avoid.push(bullet[1].trim())\n }\n return {\n name: (fm as Record<string, string | undefined>).name ?? null,\n description: (fm as Record<string, string | undefined>).description ?? null,\n fonts,\n logos,\n hexes: extractHexes(text),\n avoid,\n }\n}\n\n/** The product's name and claim from `/llms.txt`: `# name — claim` + `> claim`. */\nexport function parseLlmsTxt(text: string): {\n name: string | null\n claim: string | null\n} {\n const h1 = /^#\\s+(.+)$/m.exec(text)?.[1]?.trim() ?? null\n // The blockquote WRAPS (llms.txt files are written at 80 columns), so\n // join its consecutive `> ` lines and keep the first sentence: the claim\n // is one line by contract, and a recipe heading that stops mid-sentence\n // reads as broken (vos.so's own claim did, on the verb's first run).\n const block = /^>\\s*.+(?:\\n>\\s*.*)*/m.exec(text)?.[0]\n const joined = block\n ? block\n .split('\\n')\n .map((line) => line.replace(/^>\\s*/, '').trim())\n .filter(Boolean)\n .join(' ')\n : ''\n const quote = joined\n ? (/^(.*?[.!?])(?:\\s|$)/.exec(joined)?.[1] ?? joined)\n : null\n let name = h1\n if (h1) {\n const split = /^(.+?)\\s+[—–-]\\s+(.+)$/.exec(h1)\n if (split) name = split[1].trim()\n }\n return { name, claim: quote ?? (h1 && h1 !== name ? h1 : null) }\n}\n\nconst WITNESS_IN_PAGE = `(() => {\n const cs = (el) => el ? getComputedStyle(el) : null\n const meta = (sel) => { const m = document.querySelector(sel); return m ? m.getAttribute('content') : null }\n const abs = (href) => { try { return new URL(href, location.href).toString() } catch { return null } }\n const icons = []\n for (const l of document.querySelectorAll('link[rel~=\"icon\"], link[rel=\"apple-touch-icon\"], link[rel=\"apple-touch-icon-precomposed\"]')) {\n const u = abs(l.getAttribute('href') || ''); if (u && !icons.includes(u)) icons.push(u)\n }\n const h1 = document.querySelector('h1')\n const h1s = cs(h1)\n const bodys = cs(document.body)\n const surfaces = []\n for (const el of document.querySelectorAll('header, nav, main > section, section, footer, article, aside, [class*=\"card\"], [class*=\"Card\"], [class*=\"surface\"], [class*=\"panel\"]')) {\n const bg = cs(el).backgroundColor; if (bg && bg !== 'rgba(0, 0, 0, 0)' && bg !== 'transparent') surfaces.push(bg)\n if (surfaces.length > 60) break\n }\n const accents = []\n for (const el of document.querySelectorAll('button, [role=\"button\"], a[class*=\"btn\"], a[class*=\"button\"], a[class*=\"Button\"], input[type=\"submit\"]')) {\n const bg = cs(el).backgroundColor; if (bg && bg !== 'rgba(0, 0, 0, 0)' && bg !== 'transparent') accents.push(bg)\n if (accents.length > 80) break\n }\n let links = 0\n for (const el of document.querySelectorAll('a[href]')) {\n if (links++ > 80) break\n const c = cs(el).color; if (c) accents.push(c)\n }\n return {\n title: document.title,\n siteName: meta('meta[property=\"og:site_name\"]'),\n themeColor: meta('meta[name=\"theme-color\"]'),\n icons,\n ogImage: abs(meta('meta[property=\"og:image\"]') || '') || null,\n h1: h1s ? { fontFamily: h1s.fontFamily, color: h1s.color } : null,\n body: { fontFamily: bodys.fontFamily, color: bodys.color, backgroundColor: bodys.backgroundColor },\n surfaces,\n accents,\n }\n})()`\n\n/** Read the page's own facts in a browser; the one impure step. */\nexport async function witnessSite(\n browser: Browser,\n url: string,\n): Promise<Witness> {\n const ctx = await browser.newContext({\n viewport: { width: 1440, height: 900 },\n deviceScaleFactor: 1,\n })\n try {\n const page = await ctx.newPage()\n await page\n .goto(url, { waitUntil: 'networkidle', timeout: 45_000 })\n .catch(async () => {\n await page.goto(url, { waitUntil: 'load', timeout: 45_000 })\n })\n await page.waitForTimeout(800)\n return await page.evaluate(WITNESS_IN_PAGE)\n } finally {\n await ctx.close()\n }\n}\n\nexport interface BrandComposition {\n kit: BrandKit\n /** One line per role: where its value came from. */\n provenance: Record<string, string>\n avoid: string[]\n}\n\n/**\n * Compose the kit from what was read, in priority order: the design.md\n * wins on fonts, logos and the avoid list; llms.txt on the name and the\n * claim; the witness on every colour and on whatever the others left out.\n */\nexport function composeBrand(input: {\n url: string\n witness: Witness\n design: DesignMdFacts | null\n designUrl: string | null\n llms: { name: string | null; claim: string | null } | null\n llmsUrl: string | null\n today: string\n}): BrandComposition {\n const { witness: w, design, llms } = input\n const p: Record<string, string> = {}\n\n const bgA = rgbToHex(w.body.backgroundColor) ?? '#ffffff'\n p.bgA = `the body's background`\n const surfaceHexes = w.surfaces\n .map(rgbToHex)\n .filter((h): h is string => h !== null && h !== bgA)\n const neutralSurface = mostCommon(surfaceHexes.filter((h) => !isSaturated(h)))\n const bgB =\n neutralSurface ?? mixHex(bgA, isLight(bgA) ? '#000000' : '#ffffff', 0.04)\n p.bgB = neutralSurface\n ? `the most common section / card ground`\n : `no distinct surface found; bgA stepped 4% toward ${isLight(bgA) ? 'black' : 'white'}`\n\n const accentHexes = w.accents\n .map(rgbToHex)\n .filter((h): h is string => h !== null && isSaturated(h))\n const themeHex = w.themeColor ? rgbToHex(w.themeColor) : null\n let accent = mostCommon(accentHexes)\n if (!accent && themeHex && isSaturated(themeHex)) accent = themeHex\n if (!accent) accent = design?.hexes.find(isSaturated) ?? null\n const inkHex =\n rgbToHex(w.h1?.color ?? w.body.color) ??\n (isLight(bgA) ? '#111111' : '#f5f5f5')\n if (!accent) accent = inkHex\n p.accent = accentHexes.length\n ? `the saturated colour buttons and links agree on`\n : themeHex && isSaturated(themeHex)\n ? `the theme-color meta`\n : design?.hexes.find(isSaturated)\n ? `a hex quoted in design.md`\n : `no saturated colour on the page; the ink stands in`\n\n const bgC = mixHex(bgA, accent, 0.14)\n p.bgC = `bgA tinted 14% toward the accent (a highlight ground)`\n p.ink = w.h1 ? `the h1's colour` : `the body's colour`\n\n // Both faces are written under the catalog's name for them: a page's\n // computed style reports the site's own CSS name (fontName.ts).\n const fontDisplay = catalogFamily(\n design?.fonts[0] ??\n (w.h1 ? firstFamily(w.h1.fontFamily) : firstFamily(w.body.fontFamily)),\n )\n p.fontDisplay = design?.fonts[0]\n ? `named in design.md`\n : w.h1\n ? `the h1's computed face`\n : `the body's computed face (no h1)`\n // design.md's second face is usually the code face (\"Geist Mono only for\n // code\"); a mono family is never the body, so the page's own wins then.\n const designBody = design?.fonts.slice(1).find((f) => !/\\bmono\\b/i.test(f))\n const fontBody = catalogFamily(designBody ?? firstFamily(w.body.fontFamily))\n p.fontBody = designBody ? `named in design.md` : `the body's computed face`\n\n // The mark to PLACE: a design.md asset named mark, logo or wordmark that\n // is not an icon (a favicon or app icon carries a tile) and not the\n // on-dark twin, which is recorded beside it.\n const isIcon = (u: string) => /favicon|apple-touch|icon/i.test(u)\n const onDark = (u: string) => /on-dark|white/i.test(u)\n const logoUrl =\n design?.logos.find(\n (u) => /wordmark|logo|mark/i.test(u) && !isIcon(u) && !onDark(u),\n ) ?? null\n const logoOnDarkUrl =\n design?.logos.find(\n (u) => /wordmark|logo|mark/i.test(u) && !isIcon(u) && onDark(u),\n ) ?? null\n const iconUrl =\n w.icons.find((u) => /apple-touch/i.test(u)) ??\n (w.icons.length ? w.icons[0] : null)\n p.logoUrl = logoUrl\n ? `linked from design.md`\n : `none linked; the icon stands in`\n p.iconUrl = iconUrl ? `the page's icon link` : `no icon link`\n\n const host = new URL(input.url).hostname.replace(/^www\\./, '')\n const wordmark =\n llms?.name ??\n design?.name ??\n w.siteName ??\n (w.title.split(/[|—–-]/)[0].trim() || host)\n p.wordmark = llms?.name\n ? `llms.txt's title`\n : design?.name\n ? `design.md's name`\n : w.siteName\n ? `og:site_name`\n : `the page title`\n\n const kit: BrandKit = {\n name: wordmark,\n site: input.url,\n witnessed: input.today,\n bgA,\n bgB,\n bgC,\n ink: inkHex,\n accent,\n fontDisplay,\n fontBody,\n logoUrl: logoUrl ?? iconUrl,\n logoOnDarkUrl,\n iconUrl,\n ogImage: w.ogImage,\n wordmark,\n designMd: input.designUrl,\n llmsTxt: input.llmsUrl,\n look: lookKindForGround(bgA),\n }\n p.look = `from the body's ground (${bgA}): a paper site is a plate, a dark site is dark, else the gradient`\n return { kit, provenance: p, avoid: design?.avoid ?? [] }\n}\n\n/** The recipe file: frontmatter roles + provenance prose + the avoid list. */\nexport function renderBrandMd(\n c: BrandComposition,\n claim: string | null,\n): string {\n const k = c.kit\n const q = (v: string | null) => (v === null ? 'null' : JSON.stringify(v))\n const fm = [\n '---',\n `name: ${JSON.stringify(k.name)}`,\n `description: ${JSON.stringify(`${k.name}'s brand kit, witnessed from ${new URL(k.site).hostname} on ${k.witnessed}`)}`,\n 'applies: any',\n 'seed: none',\n `site: ${q(k.site)}`,\n `witnessed: ${q(k.witnessed)}`,\n `bgA: ${q(k.bgA)}`,\n `bgB: ${q(k.bgB)}`,\n `bgC: ${q(k.bgC)}`,\n `ink: ${q(k.ink)}`,\n `accent: ${q(k.accent)}`,\n `fontDisplay: ${q(k.fontDisplay)}`,\n `fontBody: ${q(k.fontBody)}`,\n `logoUrl: ${q(k.logoUrl)}`,\n `logoOnDarkUrl: ${q(k.logoOnDarkUrl)}`,\n `iconUrl: ${q(k.iconUrl)}`,\n `ogImage: ${q(k.ogImage)}`,\n `wordmark: ${q(k.wordmark)}`,\n `designMd: ${q(k.designMd)}`,\n `llmsTxt: ${q(k.llmsTxt)}`,\n `look: ${q(k.look)}`,\n '---',\n ].join('\\n')\n const lines = [\n fm,\n '',\n `# ${k.name}`,\n '',\n claim\n ? `${claim}`\n : `The brand of ${k.name}, as witnessed on ${new URL(k.site).hostname}.`,\n '',\n '## Where each value came from',\n '',\n ...Object.entries(c.provenance).map(\n ([role, why]) => `- \\`${role}\\`: ${why}`,\n ),\n '',\n k.designMd\n ? `The site publishes a design.md (${k.designMd}); it wins on fonts, logos and the avoid list below. Colours there are CSS variable names, so every colour above was witnessed on the page.`\n : `The site publishes no design.md; every value above was witnessed on the page, so re-run \\`vos brand\\` after a redesign.`,\n '',\n '## Use',\n '',\n `The poster family binds these roles: \\`bgA/bgB/bgC\\` for the ground, \\`ink\\` for type, \\`fontDisplay\\` for the headline (if it is not in the hosted catalog, \\`vos check\\` warns and the nearest hosted serif or sans stands in), \\`logoUrl\\` for the mark (placed beside the wordmark on the cards and the end card; \\`logoOnDarkUrl\\` stands in on a dark ground). A site that publishes only a favicon or an app icon gets the icon here, tile and all: publish a bare mark and name it in design.md. A take's frame ground is a gradient of \\`accent\\` toward \\`bgC\\` unless the brand is paper, in which case \\`bgB\\` toward \\`bgC\\`.`,\n ]\n if (c.avoid.length) {\n lines.push('', '## Avoid (the site says)', '')\n for (const a of c.avoid) lines.push(`- ${a}`)\n }\n return lines.join('\\n') + '\\n'\n}\n\nasync function fetchText(url: string): Promise<string | null> {\n try {\n const res = await fetch(url, { redirect: 'follow' })\n if (!res.ok) return null\n const type = res.headers.get('content-type') ?? ''\n if (/text\\/html/i.test(type)) return null // a soft 404 page is not a file\n return await res.text()\n } catch {\n return null\n }\n}\n\nexport async function cmdBrand(argv: string[]): Promise<number> {\n const { positionals, flags } = parseArgs(argv, new Set(['json']))\n const raw = positionals[0]\n if (!raw) throw new UsageError('vos brand <url> [--out BRAND.md] [--json]')\n const url = /^https?:\\/\\//i.test(raw) ? raw : `https://${raw}`\n let origin: string\n try {\n origin = new URL(url).origin\n } catch {\n throw new UsageError(`not a URL: ${raw}`)\n }\n const r = createReporter(flags.json === true)\n const out = resolve(strFlag(flags, 'out') ?? 'BRAND.md')\n\n r.log(`reading ${origin}/design.md and /llms.txt…`)\n const [designText, llmsText] = await Promise.all([\n fetchText(`${origin}/design.md`),\n fetchText(`${origin}/llms.txt`),\n ])\n const design = designText ? parseDesignMd(designText) : null\n const llms = llmsText ? parseLlmsTxt(llmsText) : null\n r.event({\n event: 'sources',\n designMd: design !== null,\n llmsTxt: llms !== null,\n })\n\n r.log(`witnessing ${url}…`)\n const browser = await launchBrowser()\n let witness: Witness\n try {\n witness = await witnessSite(browser, url)\n } finally {\n await browser.close()\n }\n\n const composition = composeBrand({\n url,\n witness,\n design,\n designUrl: design ? `${origin}/design.md` : null,\n llms,\n llmsUrl: llms ? `${origin}/llms.txt` : null,\n today: new Date().toISOString().slice(0, 10),\n })\n const md = renderBrandMd(\n composition,\n llms?.claim ?? design?.description ?? null,\n )\n await writeFile(out, md)\n const k = composition.kit\n r.done(\n {\n out,\n kit: k,\n provenance: composition.provenance,\n avoid: composition.avoid,\n },\n `Wrote ${out}\\n ${k.name}: ground ${k.bgA} / ${k.bgB} / ${k.bgC}, ink ${k.ink}, accent ${k.accent}, ${k.fontDisplay} over ${k.fontBody}${k.designMd ? `\\n design.md read (${composition.avoid.length} avoid line(s))` : ''}\\n file it: vos recipe push ${out} --folder <slug>`,\n )\n return 0\n}\n","/**\n * `vos record --hosted`: the take is recorded ON vos.so's fleet, for a\n * machine with no browser (a cloud agent, CI, a chat host). The same\n * actions.json goes up, the platform records, encodes, plans and lands it\n * as a private vos with its doc.json and its digest, and this brings the\n * take home with `vos fetch --media`, so the directory that results is the\n * take directory every other verb reads.\n *\n * What travels: the script, the viewport, `--header` values, and the value\n * of every `{ \"env\": \"NAME\" }` a setup step reads, taken from THIS shell.\n * What never travels: a session (`--session`, `--storage-state`), because\n * none of a person's ever reaches vos.so; a page behind a sign-in fails on\n * the fleet in words naming the local ladder, exit 4.\n */\nimport { setupEnvNames } from '@vosjs/render-core/record'\nimport { apiError, apiJson } from './platform'\nimport type { ActionsFile } from '@vosjs/render-core/record'\n\nexport interface HostedRecordInput {\n origin: string\n key: string | null\n url: string\n actions: ActionsFile\n headers: Record<string, string>\n title?: string\n folderId?: string\n /** The shell the `{ env }` names resolve from. */\n env: Record<string, string | undefined>\n log: (line: string) => void\n /** Wall-clock sleep between polls; tests hand in a fast one. */\n sleep?: (ms: number) => Promise<void>\n /** Give up waiting after this long (the fleet's own cap is far shorter). */\n timeoutMs?: number\n}\n\nexport interface HostedRecordJob {\n id: string\n status: string\n error: string | null\n vosId: string\n versionId: string | null\n telemetry: Record<string, unknown> | null\n}\n\nexport type HostedRecordOutcome =\n | {\n ok: true\n vosId: string\n jobId: string\n job: HostedRecordJob\n studio: string\n }\n | {\n ok: false\n wall: boolean\n error: string\n vosId: string | null\n jobId: string | null\n }\n\nconst POLL_MS = 3000\nconst DEFAULT_TIMEOUT_MS = 20 * 60 * 1000\n\n/** The env the request carries: every name the setup reads, from this shell. */\nexport function hostedEnv(\n actions: ActionsFile,\n shell: Record<string, string | undefined>,\n): { env: Record<string, string>; missing: string[] } {\n const env: Record<string, string> = {}\n const missing: string[] = []\n for (const name of setupEnvNames(actions.setup)) {\n const v = shell[name]\n if (v === undefined || v === '') missing.push(name)\n else env[name] = v\n }\n return { env, missing }\n}\n\n/** A refusal the fleet wrote for a sign-in, told apart from every other failure. */\nexport function isWallError(error: string | null | undefined): boolean {\n // The row's error wears the job's `[kind]` prefix; the sentence is the tell.\n return !!error && /^(\\[\\w+\\] )?The page is behind a sign-in/.test(error)\n}\n\nexport async function recordHosted(\n input: HostedRecordInput,\n): Promise<HostedRecordOutcome> {\n const sleep =\n input.sleep ?? ((ms: number) => new Promise((r) => setTimeout(r, ms)))\n const posted = await apiJson(input.origin, '/api/record/jobs', {\n method: 'POST',\n key: input.key,\n body: {\n url: input.url,\n actions: input.actions,\n viewport: input.actions.viewport,\n ...(Object.keys(input.headers).length ? { headers: input.headers } : {}),\n ...(Object.keys(input.env).length ? { env: input.env } : {}),\n ...(input.title ? { title: input.title } : {}),\n ...(input.folderId ? { folderId: input.folderId } : {}),\n },\n })\n if (posted.status !== 202) {\n return {\n ok: false,\n wall: false,\n error: apiError('record on vos.so', posted),\n vosId: null,\n jobId: null,\n }\n }\n const job = posted.body.job as { id: string; vosId: string }\n const vos = posted.body.vos as { studio?: string } | undefined\n const cap = posted.body.cap as { seconds?: number } | undefined\n input.log(\n `queued on vos.so as job ${job.id.slice(0, 8)} (vos ${job.vosId}${cap?.seconds ? `, cap ${cap.seconds}s` : ''})`,\n )\n\n const deadline = Date.now() + (input.timeoutMs ?? DEFAULT_TIMEOUT_MS)\n let lastStatus = 'queued'\n while (Date.now() < deadline) {\n await sleep(POLL_MS)\n const polled = await apiJson(input.origin, `/api/record/jobs/${job.id}`, {\n key: input.key,\n })\n if (polled.status !== 200) {\n return {\n ok: false,\n wall: false,\n error: apiError(`poll record job ${job.id}`, polled),\n vosId: job.vosId,\n jobId: job.id,\n }\n }\n const state = polled.body.job as HostedRecordJob\n if (state.status !== lastStatus) {\n input.log(`${state.status}…`)\n lastStatus = state.status\n }\n if (state.status === 'completed') {\n return {\n ok: true,\n vosId: state.vosId,\n jobId: state.id,\n job: state,\n studio: vos?.studio ?? `${input.origin}/studio?vos=${state.vosId}`,\n }\n }\n if (state.status === 'failed' || state.status === 'canceled') {\n const error =\n state.error ??\n (state.status === 'canceled'\n ? 'the record job was canceled'\n : 'the record job failed')\n return {\n ok: false,\n wall: isWallError(error),\n error,\n vosId: state.vosId,\n jobId: state.id,\n }\n }\n }\n return {\n ok: false,\n wall: false,\n error: `the record job ${job.id} did not finish within ${Math.round((input.timeoutMs ?? DEFAULT_TIMEOUT_MS) / 60000)} min; poll ${input.origin}/api/record/jobs/${job.id}`,\n vosId: job.vosId,\n jobId: job.id,\n }\n}\n","/**\n * `vos actions from-agent-browser <steps.jsonl>` — the agent that verified\n * the feature already walked the product in agent-browser (Vercel Labs);\n * this turns that walk into an actions.json so `vos record` replays it with\n * a synthesized cursor track, auto-zooms and cuts it. One walk, one take,\n * no second script.\n *\n * What agent-browser leaves behind, measured: no command log (a session\n * persists cookies and state, `trace` is performance events, `record` a\n * raw WebM), and a command's `--json` RESULT does not carry its arguments.\n * `scroll` answers `{scrolled:true}`, `mouse move` `{moved:true}`, `type`\n * echoes the text but not the target, `click @e27` echoes `\"@e27\"`, and a\n * ref is `{role, name}` in the preceding snapshot's `refs` map and nothing\n * else (no selector, no coordinates, no timestamps). So the input is the\n * RECORD agent-browser's own `batch` emits, `{command: [...], result: {…},\n * success, error}`, one per line or the batch array itself, which the\n * skill tells the agent to keep while it verifies (a shell function wraps\n * each call). Refs resolve through the last snapshot line before them.\n *\n * Every mapping is pure and every command that cannot follow is NAMED in\n * the notes, never dropped silently: a recording that skips a step the\n * agent made is a different walk.\n */\nimport { writeFile } from 'node:fs/promises'\nimport { resolve } from 'node:path'\nimport { validateActions } from './actions'\nimport { UsageError, parseArgs, strFlag } from './args'\nimport { EXIT_ERROR, EXIT_OK, createReporter } from './output'\nimport type { ActionStep, ActionsFile } from './actions'\n\n/** One agent-browser command with its result: the `batch` record shape. */\nexport interface AgentBrowserRecord {\n command: string[] | string\n /** Single-command `--json` lines carry `data`; batch records carry `result`. */\n data?: unknown\n result?: unknown\n success?: boolean\n error?: string | null\n}\n\nexport interface ConvertOptions {\n /** Overrides the walk's first `open`. */\n url?: string\n /** Overrides the walk's `set viewport`. */\n viewport?: { width: number; height: number }\n}\n\nexport interface ConvertResult {\n actions: ActionsFile\n /** Every command that became no step, or a different step, with its line. */\n notes: string[]\n /** Commands that produced a step. */\n steps: number\n /** Reads and session verbs: nothing to replay. */\n ignored: number\n /** Actions the recorder cannot follow, or that failed in the walk. */\n skipped: number\n}\n\n/** Parse a steps.jsonl (or a batch array) into records; malformed lines are named. */\nexport function parseAgentBrowserLog(text: string): {\n records: AgentBrowserRecord[]\n problems: string[]\n} {\n const records: AgentBrowserRecord[] = []\n const problems: string[] = []\n const trimmed = text.trim()\n if (!trimmed) return { records, problems: ['the log is empty'] }\n const push = (value: unknown, where: string): void => {\n if (Array.isArray(value)) {\n value.forEach((v, i) => push(v, `${where}[${i}]`))\n return\n }\n if (typeof value !== 'object' || value === null) {\n problems.push(`${where}: not a record`)\n return\n }\n const rec = value as Record<string, unknown>\n if (typeof rec.command !== 'string' && !Array.isArray(rec.command)) {\n problems.push(\n `${where}: no \"command\" — keep each call as {command:[…], …result} (the batch shape); a bare --json result does not say what ran`,\n )\n return\n }\n records.push(rec as unknown as AgentBrowserRecord)\n }\n if (trimmed.startsWith('[')) {\n try {\n push(JSON.parse(trimmed), 'batch')\n } catch (e) {\n problems.push(`not JSON: ${(e as Error).message}`)\n }\n return { records, problems }\n }\n trimmed.split('\\n').forEach((line, i) => {\n const l = line.trim()\n if (!l) return\n try {\n push(JSON.parse(l), `line ${i + 1}`)\n } catch {\n problems.push(`line ${i + 1}: not JSON`)\n }\n })\n return { records, problems }\n}\n\n/** Shell-style split for a `command` kept as one string: quotes group, backslash escapes. */\nexport function splitCommand(command: string): string[] {\n const out: string[] = []\n let cur = ''\n let quote: string | null = null\n let has = false\n for (let i = 0; i < command.length; i++) {\n const c = command[i]\n if (quote) {\n if (c === quote) quote = null\n else if (c === '\\\\' && i + 1 < command.length) cur += command[++i]\n else cur += c\n continue\n }\n if (c === '\"' || c === \"'\") {\n quote = c\n has = true\n continue\n }\n if (c === '\\\\' && i + 1 < command.length) {\n cur += command[++i]\n has = true\n continue\n }\n if (/\\s/.test(c)) {\n if (has) out.push(cur)\n cur = ''\n has = false\n continue\n }\n cur += c\n has = true\n }\n if (has) out.push(cur)\n return out\n}\n\ntype Refs = Record<string, { role?: string; name?: string; href?: string }>\n\nconst READ_VERBS = new Set([\n 'get',\n 'is',\n 'eval',\n 'screenshot',\n 'tab',\n 'session',\n 'close',\n 'doctor',\n 'cookies',\n 'storage',\n 'console',\n 'network',\n 'trace',\n 'record',\n 'pdf',\n 'version',\n 'help',\n])\n\nconst quoteAttr = (s: string): string =>\n `\"${s.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"')}\"`\n\n/**\n * The snapshot's `url=` is the RESOLVED absolute URL, while the DOM's href\n * attribute is usually the relative path the author wrote, and a CSS\n * attribute selector matches the attribute literally. So a link gets both\n * forms, comma-joined (one Playwright locator); a cross-origin href only\n * ever appears absolute.\n */\nexport function hrefSelector(href: string): string {\n try {\n const u = new URL(href)\n const relative = `${u.pathname}${u.search}${u.hash}`\n return `a[href=${quoteAttr(relative)}], a[href=${quoteAttr(href)}]`\n } catch {\n return `a[href=${quoteAttr(href)}]`\n }\n}\n\n/** A ref or CSS target → a Playwright selector the recorder's `page.locator` takes. */\nfunction resolveTarget(\n target: string,\n refs: Refs,\n): { selector: string } | { reason: string } {\n const m = /^@(e\\d+)$/.exec(target)\n if (!m) return { selector: target }\n const ref = Object.hasOwn(refs, m[1]) ? refs[m[1]] : undefined\n if (!ref)\n return {\n reason: `${target} is not in the last snapshot — keep the \\`snapshot -i\\` line that named it before the step`,\n }\n if (ref.role === 'link' && ref.href)\n return { selector: hrefSelector(ref.href) }\n if (ref.role && ref.name)\n return { selector: `role=${ref.role}[name=${quoteAttr(ref.name)}]` }\n if (ref.role) return { selector: `role=${ref.role}` }\n return { reason: `${target} has no role or name in the snapshot` }\n}\n\n/** The `find <kind> <query>` locators → Playwright selectors. */\nfunction findSelector(\n kind: string,\n query: string,\n flags: { name?: string; exact: boolean },\n): { selector: string } | { reason: string } {\n switch (kind) {\n case 'text':\n return {\n selector: flags.exact ? `text=${quoteAttr(query)}` : `text=${query}`,\n }\n case 'role':\n return {\n selector: flags.name\n ? `role=${query}[name=${quoteAttr(flags.name)}]`\n : `role=${query}`,\n }\n case 'label':\n // Playwright's getByLabel form; the public engines have no label=.\n return {\n selector: `internal:label=${quoteAttr(query)}${flags.exact ? 's' : 'i'}`,\n }\n case 'placeholder':\n return { selector: `[placeholder=${quoteAttr(query)}]` }\n case 'alt':\n return { selector: `[alt=${quoteAttr(query)}]` }\n case 'title':\n return { selector: `[title=${quoteAttr(query)}]` }\n case 'testid':\n return { selector: `[data-testid=${quoteAttr(query)}]` }\n case 'first':\n return { selector: query }\n case 'last':\n case 'nth':\n return {\n reason: `find ${kind} is a position, not a stable selector — name the element by role, text or testid`,\n }\n default:\n return { reason: `find ${kind} is not a locator agent-browser documents` }\n }\n}\n\n/** Pull `--flag value` and `--bool` pairs out of a command's tail. */\nfunction takeFlags(\n args: string[],\n valued: ReadonlySet<string>,\n): { positionals: string[]; flags: Record<string, string | true> } {\n const positionals: string[] = []\n const flags: Record<string, string | true> = {}\n for (let i = 0; i < args.length; i++) {\n const a = args[i]\n if (a.startsWith('--')) {\n const name = a.slice(2)\n if (valued.has(name) && i + 1 < args.length) flags[name] = args[++i]\n else flags[name] = true\n continue\n }\n if (a.startsWith('-') && a.length === 2) {\n // agent-browser's short flags: -i (interactive refs), -u (urls), -s <sel>\n if (a === '-s' && i + 1 < args.length) flags.selector = args[++i]\n else flags[a.slice(1)] = true\n continue\n }\n positionals.push(a)\n }\n return { positionals, flags }\n}\n\n/** `[ref=e27, url=https://…]` markers in a snapshot's text tree → href per ref. */\nfunction snapshotHrefs(snapshot: string): Record<string, string> {\n const out: Record<string, string> = {}\n for (const m of snapshot.matchAll(/\\[([^\\]]*?\\bref=(e\\d+)[^\\]]*?)\\]/g)) {\n const url = /\\burl=([^,\\]\\s]+)/.exec(m[1])?.[1]\n if (url) out[m[2]] = url\n }\n return out\n}\n\n/** The walk, as steps the recorder can replay. Pure. */\nexport function convertAgentBrowser(\n records: AgentBrowserRecord[],\n opts: ConvertOptions = {},\n): ConvertResult {\n const steps: ActionStep[] = []\n const notes: string[] = []\n let url: string | undefined\n let viewport: ActionsFile['viewport']\n let refs: Refs = {}\n let lastTarget: string | null = null\n let ignored = 0\n let skipped = 0\n let fillNoted = false\n\n const skip = (n: number, reason: string): void => {\n skipped++\n notes.push(`line ${n}: skipped — ${reason}`)\n }\n const emit = (n: number, step: ActionStep): void => {\n steps.push({ ...step, id: `ab${n}` })\n }\n\n records.forEach((rec, i) => {\n const n = i + 1\n const argv = Array.isArray(rec.command)\n ? rec.command\n : splitCommand(rec.command)\n const [verb, ...args] = argv\n const payload = (rec.data ?? rec.result ?? null) as Record<\n string,\n unknown\n > | null\n if (!verb) {\n skip(n, 'an empty command')\n return\n }\n if (rec.success === false) {\n skip(\n n,\n `\\`${argv.join(' ')}\\` failed in the walk${rec.error ? ` (${rec.error})` : ''}`,\n )\n return\n }\n switch (verb) {\n case 'open': {\n const target = args.find((a) => !a.startsWith('-'))\n if (!target) {\n skip(n, 'open without a URL')\n return\n }\n if (!url) {\n url = target\n ignored++\n return\n }\n skip(\n n,\n `a second open (${target}) — actions.json records ONE page; reach it by clicking, or split the walk`,\n )\n return\n }\n case 'snapshot': {\n const map = (payload?.refs ?? {}) as Record<\n string,\n { role?: string; name?: string }\n >\n const hrefs =\n typeof payload?.snapshot === 'string'\n ? snapshotHrefs(payload.snapshot)\n : {}\n refs = {}\n for (const [id, r] of Object.entries(map))\n refs[id] = { ...r, href: hrefs[id] }\n ignored++\n return\n }\n case 'set': {\n if (args[0] === 'viewport') {\n const w = Number(args[1])\n const h = Number(args[2])\n if (Number.isFinite(w) && Number.isFinite(h)) {\n viewport = { width: w, height: h }\n if (args[3] && Number(args[3]) !== 1)\n notes.push(\n `line ${n}: viewport scale ${args[3]} ignored — the recorder captures at the viewport's CSS size`,\n )\n ignored++\n return\n }\n }\n skip(n, `\\`set ${args.join(' ')}\\` has no recording equivalent`)\n return\n }\n case 'click':\n case 'hover': {\n const target = args.find((a) => !a.startsWith('-'))\n if (!target) {\n skip(n, `${verb} without a target`)\n return\n }\n const r = resolveTarget(target, refs)\n if ('reason' in r) {\n skip(n, r.reason)\n return\n }\n lastTarget = r.selector\n emit(\n n,\n verb === 'click'\n ? { do: 'click', selector: r.selector }\n : { do: 'hover', selector: r.selector },\n )\n return\n }\n case 'fill':\n case 'type': {\n const [target, ...textParts] = args\n if (!target || textParts.length === 0) {\n skip(n, `${verb} needs a target and text`)\n return\n }\n const r = resolveTarget(target, refs)\n if ('reason' in r) {\n skip(n, r.reason)\n return\n }\n if (verb === 'fill' && !fillNoted) {\n fillNoted = true\n notes.push(\n `line ${n}: fill became type — the recorder types into the field as it is; an empty field reads the same, a prefilled one does not`,\n )\n }\n lastTarget = r.selector\n emit(n, { do: 'type', selector: r.selector, text: textParts.join(' ') })\n return\n }\n case 'keyboard': {\n const [mode, ...textParts] = args\n if ((mode === 'type' || mode === 'inserttext') && textParts.length) {\n if (!lastTarget) {\n skip(\n n,\n 'keyboard type before any click or fill — the recorder needs a field to type into',\n )\n return\n }\n emit(n, {\n do: 'type',\n selector: lastTarget,\n text: textParts.join(' '),\n })\n return\n }\n skip(n, `\\`keyboard ${args.join(' ')}\\` has no recording equivalent`)\n return\n }\n case 'press':\n case 'key': {\n const key = args.at(0)\n if (key === 'Enter' && lastTarget) {\n // `focus: false`: agent-browser's press goes to whatever is focused\n // and never clicks, so neither does this. A type step that clicks\n // rings a click effect in the middle of a field the walk had already\n // filled — a bloom on empty space beside the text.\n emit(n, {\n do: 'type',\n selector: lastTarget,\n text: '\\n',\n focus: false,\n })\n notes.push(\n `line ${n}: press Enter became a newline typed into the last field`,\n )\n return\n }\n skip(\n n,\n `press ${key ?? ''} — actions.json has no key verb; a shortcut's effect needs a click on the control that does it`,\n )\n return\n }\n case 'scroll': {\n const { positionals, flags } = takeFlags(args, new Set(['selector']))\n const dir = positionals.at(0) ?? 'down'\n const amountArg = positionals.at(1)\n const amount = amountArg !== undefined ? Number(amountArg) : 300\n if (!Number.isFinite(amount)) {\n skip(n, `scroll amount ${amountArg} is not a number`)\n return\n }\n if (dir === 'left' || dir === 'right') {\n skip(n, 'horizontal scroll has no recording equivalent')\n return\n }\n if (flags.selector)\n notes.push(\n `line ${n}: scroll --selector ${String(flags.selector)} became a page scroll`,\n )\n emit(n, { do: 'scroll', dy: dir === 'up' ? -amount : amount })\n return\n }\n case 'mouse': {\n const [mode, xs, ys] = args\n if (mode === 'move') {\n const x = Number(xs)\n const y = Number(ys)\n if (Number.isFinite(x) && Number.isFinite(y)) {\n emit(n, { do: 'move', x, y })\n return\n }\n }\n skip(\n n,\n `\\`mouse ${args.join(' ')}\\` — only mouse move maps; a click by coordinates needs a selector`,\n )\n return\n }\n case 'wait': {\n const first = args.at(0)\n if (\n first !== undefined &&\n !first.startsWith('-') &&\n /^\\d+$/.test(first)\n ) {\n emit(n, { do: 'wait', ms: Number(first) })\n return\n }\n emit(n, { do: 'wait', ms: 500 })\n notes.push(\n `line ${n}: \\`wait ${args.join(' ')}\\` became 500 ms — the recorder waits for the page itself`,\n )\n return\n }\n case 'find': {\n const { positionals, flags } = takeFlags(args, new Set(['name']))\n const kind = positionals.at(0)\n const query = positionals.at(1)\n const action = positionals.at(2) ?? 'click'\n const rest = positionals.slice(3)\n if (!kind || query === undefined) {\n skip(n, 'find needs a locator and a query')\n return\n }\n const r = findSelector(kind, query, {\n name: typeof flags.name === 'string' ? flags.name : undefined,\n exact: flags.exact === true,\n })\n if ('reason' in r) {\n skip(n, r.reason)\n return\n }\n switch (action) {\n case 'click':\n case 'check':\n lastTarget = r.selector\n emit(n, { do: 'click', selector: r.selector })\n return\n case 'hover':\n lastTarget = r.selector\n emit(n, { do: 'hover', selector: r.selector })\n return\n case 'fill':\n if (!rest.length) {\n skip(n, 'find … fill without text')\n return\n }\n lastTarget = r.selector\n emit(n, { do: 'type', selector: r.selector, text: rest.join(' ') })\n return\n case 'text':\n ignored++\n return\n default:\n skip(n, `find … ${action} has no recording equivalent`)\n return\n }\n }\n case 'drag':\n skip(\n n,\n 'drag needs the end point in px — `get box` the target and write a drag step by hand',\n )\n return\n case 'batch':\n skip(\n n,\n 'a batch line inside the log — keep the batch OUTPUT (its array) instead',\n )\n return\n default:\n if (READ_VERBS.has(verb)) {\n ignored++\n return\n }\n skip(n, `\\`${argv.join(' ')}\\` has no recording equivalent`)\n }\n })\n\n const actions: ActionsFile = {\n ...((opts.url ?? url) ? { url: opts.url ?? url } : {}),\n ...((opts.viewport ?? viewport)\n ? { viewport: opts.viewport ?? viewport }\n : {}),\n steps,\n }\n return { actions, notes, steps: steps.length, ignored, skipped }\n}\n\n/** `vos actions from-agent-browser <steps.jsonl> [--out actions.json] [--url u] [--viewport WxH] [--json]` */\nexport async function cmdActions(argv: string[]): Promise<number> {\n const { positionals, flags } = parseArgs(argv, new Set(['json']))\n const [sub, input] = positionals\n if (sub === 'script' && input) return cmdActionsScript(input, flags)\n if (sub !== 'from-agent-browser' || !input) {\n throw new UsageError(\n 'vos actions from-agent-browser <steps.jsonl> [--out actions.json] [--url <url>] [--viewport WxH] [--json]\\n vos actions script <actions.json> [--json]',\n )\n }\n const r = createReporter(flags.json === true)\n const out = resolve(strFlag(flags, 'out') ?? 'actions.json')\n const viewportFlag = strFlag(flags, 'viewport')\n let viewport: ConvertOptions['viewport']\n if (viewportFlag) {\n const m = /^(\\d+)x(\\d+)$/.exec(viewportFlag)\n if (!m) throw new UsageError('--viewport expects WxH, e.g. 1280x720')\n viewport = { width: Number(m[1]), height: Number(m[2]) }\n }\n const { readFile } = await import('node:fs/promises')\n const text = await readFile(resolve(input), 'utf8')\n const { records, problems } = parseAgentBrowserLog(text)\n for (const p of problems) r.log(` ${p}`)\n const result = convertAgentBrowser(records, {\n url: strFlag(flags, 'url'),\n viewport,\n })\n const errors = validateActions(result.actions)\n if (errors.length) {\n r.done(\n { ok: false, errors, ...summary(result) },\n `${input}: no actions file written\\n ${errors.join('\\n ')}\\n ${result.notes.join('\\n ')}`,\n )\n return EXIT_ERROR\n }\n await writeFile(out, `${JSON.stringify(result.actions, null, 2)}\\n`)\n r.done(\n { ok: true, out, url: result.actions.url ?? null, ...summary(result) },\n `Wrote ${out}: ${result.steps} step${result.steps === 1 ? '' : 's'} from ${records.length} record${records.length === 1 ? '' : 's'} (${result.ignored} read/session, ${result.skipped} skipped)` +\n (result.notes.length ? `\\n ${result.notes.join('\\n ')}` : '') +\n `\\nThen: vos record --actions ${out} --out take --strict`,\n )\n return EXIT_OK\n}\n\nfunction summary(result: ConvertResult): {\n steps: number\n ignored: number\n skipped: number\n notes: string[]\n} {\n return {\n steps: result.steps,\n ignored: result.ignored,\n skipped: result.skipped,\n notes: result.notes,\n }\n}\n\n/**\n * `vos actions script <actions.json>`: the flow as numbered beats in plain\n * words, for the person who will record it by hand (the last rung of the\n * session ladder). The agent hands this over instead of an apology.\n */\nasync function cmdActionsScript(\n input: string,\n flags: ReturnType<typeof parseArgs>['flags'],\n): Promise<number> {\n const r = createReporter(flags.json === true)\n const { readFile } = await import('node:fs/promises')\n const { shotList, formatShotList } = await import('./shotList')\n const raw = JSON.parse(await readFile(resolve(input), 'utf8')) as unknown\n const errors = validateActions(raw)\n if (errors.length) throw new UsageError(`${input}:\\n ${errors.join('\\n ')}`)\n const list = shotList(raw as Parameters<typeof shotList>[0])\n r.done({ ...list, text: formatShotList(list) }, formatShotList(list))\n return EXIT_OK\n}\n","/**\n * `vos ingest <video> [--cursor <trace>] [--out take]` (AN6): a take\n * directory from a recording someone else made. A Cursor cloud agent's PR\n * video, a Playwright run's `video.webm`, a Loom export: the file becomes\n * `recording.<container>` stream-copied into a seekable container\n * (fail-open: an unreadable file is copied as it is), `meta.json` comes\n * from the file's own dimensions and duration, and a trace beside it\n * (`--cursor`: a Playwright `trace.zip`, a `steps.jsonl` of stamped\n * records, or a CSV of `t,x,y,type`) becomes `cursor.json`, so the\n * planner has clicks to zoom on. Without a trace the take has no cursor\n * track and the doc plans nothing, which the done event says: every zoom\n * is then placed by eye.\n *\n * The adapters are `@vosjs/studio-core`'s (pure; the studio's drop zone\n * runs the same ones); this file owns the filesystem, mediabunny and zlib.\n */\nimport { existsSync } from 'node:fs'\nimport { copyFile, mkdir, readFile, stat } from 'node:fs/promises'\nimport { basename, join, resolve } from 'node:path'\nimport { inflateRawSync } from 'node:zlib'\nimport {\n cursorFromPlaywrightTrace,\n cursorFromTrace,\n playwrightTraceEntry,\n traceKindOf,\n zipEntries,\n zipEntryBytes,\n} from '@vosjs/studio-core'\nimport {\n ALL_FORMATS,\n Conversion,\n FilePathSource,\n FilePathTarget,\n Input,\n Mp4OutputFormat,\n Output,\n WebMOutputFormat,\n} from 'mediabunny'\nimport { UsageError, numFlag, parseArgs, strFlag } from './args'\nimport { EXIT_OK, createReporter } from './output'\nimport { planTake } from './plan'\nimport { MULTI_FLAGS, takeBackdrop } from './run'\nimport { ensureTakeDir, prepareReRecord, writeJson } from './take'\nimport type { RecordingMeta, TraceResult } from '@vosjs/studio-core'\n\nconst BOOLEAN_FLAGS = new Set(['json', 'help'])\n\nexport interface ProbedVideo {\n width: number\n height: number\n durationMs: number\n fps: number\n hasAudio: boolean\n /** The container's mime type, as mediabunny read it. */\n mimeType: string\n /** The file extension the container is named by. */\n ext: 'webm' | 'mp4' | 'mov'\n}\n\n/** The file's own facts: dimensions, length, frame rate, audio, container. */\nexport async function probeVideoFile(path: string): Promise<ProbedVideo> {\n const input = new Input({\n source: new FilePathSource(path),\n formats: ALL_FORMATS,\n })\n try {\n const format = await input.getFormat()\n const video = await input.getPrimaryVideoTrack()\n if (!video) throw new UsageError(`${path} has no video track`)\n const [duration, stats, audio] = await Promise.all([\n input.computeDuration(),\n video.computePacketStats(240),\n input.getPrimaryAudioTrack(),\n ])\n const mimeType = format.mimeType\n const ext = mimeType.includes('mp4')\n ? 'mp4'\n : mimeType.includes('quicktime')\n ? 'mov'\n : 'webm'\n return {\n width: video.displayWidth,\n height: video.displayHeight,\n durationMs: Math.round(duration * 1000),\n fps: Math.round(stats.averagePacketRate * 100) / 100,\n hasAudio: !!audio,\n mimeType,\n ext,\n }\n } finally {\n await input.dispose?.()\n }\n}\n\n/**\n * Stream-copy the recording into an indexed container of the same kind\n * (a Playwright or MediaRecorder file has no seek index), or copy it as\n * it is when mediabunny cannot keep every track. Answers whether it remuxed.\n */\nexport async function copyRecording(\n src: string,\n dest: string,\n ext: ProbedVideo['ext'],\n): Promise<boolean> {\n if (ext === 'mov') {\n await copyFile(src, dest)\n return false\n }\n const input = new Input({\n source: new FilePathSource(src),\n formats: ALL_FORMATS,\n })\n const target = new FilePathTarget(dest)\n const output = new Output({\n format:\n ext === 'mp4'\n ? new Mp4OutputFormat({ fastStart: 'in-memory' })\n : new WebMOutputFormat(),\n target,\n })\n try {\n const conversion = await Conversion.init({ input, output })\n if (!conversion.isValid || conversion.discardedTracks.length > 0) {\n await conversion.cancel?.()\n await copyFile(src, dest)\n return false\n }\n await conversion.execute()\n return true\n } catch {\n await copyFile(src, dest)\n return false\n } finally {\n await input.dispose?.()\n }\n}\n\n/** Read a trace file by its name: a zip is opened for its Playwright trace. */\nexport async function readTraceFile(\n path: string,\n offsetMs: number,\n): Promise<TraceResult> {\n const kind = traceKindOf(basename(path))\n if (!kind) {\n throw new UsageError(\n `${path}: not a trace the recorder reads (trace.zip, .trace, .jsonl, .json or .csv)`,\n )\n }\n if (kind === 'zip') {\n const bytes = new Uint8Array(await readFile(path))\n const entry = playwrightTraceEntry(zipEntries(bytes))\n if (!entry) {\n throw new UsageError(\n `${path}: no trace.trace inside; a Playwright trace.zip is what --cursor reads as a zip`,\n )\n }\n const raw = zipEntryBytes(bytes, entry)\n const text = new TextDecoder().decode(\n entry.method === 8 ? new Uint8Array(inflateRawSync(raw)) : raw,\n )\n return cursorFromPlaywrightTrace(text, { offsetMs })\n }\n const text = await readFile(path, 'utf8')\n return cursorFromTrace(basename(path), text, { offsetMs })\n}\n\nfunction parseViewport(\n v: string | undefined,\n): { width: number; height: number } | null {\n if (!v) return null\n const m = /^(\\d+)x(\\d+)$/i.exec(v.trim())\n if (!m) throw new UsageError('--viewport expects WxH, like 1280x720')\n return { width: Number(m[1]), height: Number(m[2]) }\n}\n\nexport async function cmdIngest(argv: string[]): Promise<number> {\n const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS, MULTI_FLAGS)\n const source = positionals[0]\n if (!source)\n throw new UsageError(\n 'vos ingest <video.webm|mp4> [--cursor <trace.zip|steps.jsonl|cursor.csv>] [--as footage|take] [--out take] [--offset <ms>] [--viewport WxH] [--background <slug|url|none>] [--json]',\n )\n const videoPath = resolve(source)\n if (!existsSync(videoPath)) throw new UsageError(`${source}: no such file`)\n const r = createReporter(flags.json === true)\n const outDir = resolve(strFlag(flags, 'out') ?? 'take')\n const offsetMs = numFlag(flags, 'offset', 0)\n const viewportFlag = parseViewport(strFlag(flags, 'viewport'))\n const cursorPath = strFlag(flags, 'cursor')\n // What the file IS decides how it opens. A cursor trace is the one\n // evidence of a screen recording; without it the file is finished footage\n // (a render from another tool, a film) and opens bare, with nothing drawn\n // over it. --as says it outright either way.\n const asFlag = strFlag(flags, 'as')\n if (asFlag !== undefined && asFlag !== 'footage' && asFlag !== 'take')\n throw new UsageError('--as expects footage or take')\n const footage = asFlag ? asFlag === 'footage' : !cursorPath\n if (footage && strFlag(flags, 'background') !== undefined)\n r.log(\n 'note: finished footage opens bare, so --background is not used (pass --as take for the screen-recording card and its ground)',\n )\n const backdrop = footage ? null : await takeBackdrop(flags, r)\n\n r.log(`probing ${basename(videoPath)}…`)\n const probed = await probeVideoFile(videoPath)\n if (!(probed.durationMs > 0)) {\n throw new UsageError(\n `${source}: the file reports no duration; a stream-shaped recording needs its container fixed first (ffmpeg -i in.webm -c copy out.webm)`,\n )\n }\n\n // The trace first, so a bad one costs nothing: no directory is touched.\n let trace: TraceResult | null = null\n if (cursorPath) {\n trace = await readTraceFile(resolve(cursorPath), offsetMs)\n for (const n of trace.notes) r.log(`note: ${n}`)\n }\n\n if (existsSync(join(outDir, 'meta.json'))) {\n const { prevDoc, kept } = await prepareReRecord(outDir)\n r.log(\n `note: re-ingesting into ${outDir}; kept ${kept.length ? kept.join(', ') : 'nothing'}` +\n (prevDoc\n ? `; apply the previous cut with: vos plan ${outDir} --reuse`\n : ''),\n )\n }\n await mkdir(outDir, { recursive: true })\n const paths = await ensureTakeDir(outDir)\n // The recording is named by its container, never by a convention: a take\n // whose file says webm while its bytes are mp4 renders nothing.\n const recording = join(outDir, `recording.${probed.ext}`)\n r.log('copying the recording…')\n const remuxed = await copyRecording(videoPath, recording, probed.ext)\n\n const viewport = viewportFlag ??\n trace?.viewport ?? {\n width: probed.width,\n height: probed.height,\n }\n const events = trace?.events ?? []\n const fileStat = await stat(videoPath)\n const meta: RecordingMeta = {\n dpr: 1,\n zoom: 1,\n t0: trace?.t0 ?? Math.round(fileStat.mtimeMs),\n durationMs: probed.durationMs,\n width: viewport.width,\n height: viewport.height,\n captureWidth: probed.width,\n captureHeight: probed.height,\n fps: probed.fps > 0 ? probed.fps : 30,\n hasAudio: probed.hasAudio,\n producer: 'ingest',\n ...(events.length ? { captureSurface: 'tab' as const } : {}),\n }\n await writeJson(paths.meta, meta, true)\n if (events.length) await writeJson(paths.cursor, events)\n\n const plan = await planTake(outDir, { backdrop, footage })\n const clicks = events.filter((e) => e.type === 'down').length\n const seconds = (probed.durationMs / 1000).toFixed(1)\n const facts = `${seconds}s, ${probed.width}×${probed.height} @ ${meta.fps} fps${probed.hasAudio ? ', audio' : ', no audio'}${remuxed ? '' : ', copied as is'}`\n const cursorLine = trace\n ? `${events.length} cursor events (${clicks} clicks) from ${basename(cursorPath!)}${trace.dropped ? `, ${trace.dropped} not placed` : ''}; ${plan.zoomAuto} zoom${plan.zoomAuto === 1 ? '' : 's'} planned`\n : 'no cursor track, so nothing was planned'\n const opened = footage\n ? `opened as finished footage: no card, no browser bar, no drawn cursor, ${meta.fps > 30 ? 60 : 30} fps export (--as take for a screen recording's card)`\n : `opened as a screen recording: the card, its ground and the drawn cursor (--as footage to open it bare)`\n const next =\n footage && !trace\n ? `Next: vos push ${outDir} --wait — it lands as it is; trim or add to it in the studio`\n : trace\n ? `Next: vos digest ${outDir} — look before you cut; edit doc.json; vos push ${outDir}`\n : `Add --cursor <trace> recorded beside the video (a Playwright trace.zip, stamped JSON records, or a t,x,y,type CSV) to plan zooms from its clicks; else place them by eye: vos frames ${outDir} --times 0,25%,50%,75%,100%, then edit doc.json`\n r.done(\n {\n out: outDir,\n recording: basename(recording),\n durationMs: probed.durationMs,\n width: probed.width,\n height: probed.height,\n viewport,\n fps: meta.fps,\n hasAudio: probed.hasAudio,\n remuxed,\n cursor: trace\n ? {\n file: basename(cursorPath!),\n kind: trace.kind,\n events: events.length,\n clicks,\n placed: trace.placed,\n dropped: trace.dropped,\n notes: trace.notes,\n }\n : null,\n zooms: plan.zoomAuto,\n backdrop: plan.backdrop ?? null,\n as: footage ? 'footage' : 'take',\n },\n `Ingested ${basename(videoPath)} → ${outDir}/${basename(recording)} (${facts})\\n ${opened}\\n ${cursorLine}\\n ${next}`,\n )\n return EXIT_OK\n}\n","/**\n * `vos setup`, `vos doctor`, `vos whoami`, `vos logout` (AN1): the verbs\n * that ready the machine and say what is on it. The facts come from\n * `machine.ts`; this file is the part that spawns, copies and prints.\n *\n * Output: NDJSON when `--json` is given OR stdout is not a TTY (an agent\n * reads these verbs far more often than a person does), always ending in a\n * `done` event that carries `next_step`. No verb here ever prints a\n * credential; `whoami` answers a key's NAME and the account's handle.\n */\nimport { spawnSync } from 'node:child_process'\nimport {\n cpSync,\n existsSync,\n mkdirSync,\n readFileSync,\n rmSync,\n writeFileSync,\n} from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\nimport { chromium } from 'playwright'\nimport { UsageError, parseArgs, strFlag } from './args'\nimport {\n agentsFromFlag,\n applyRulesBlock,\n bundledSkillsDir,\n detectAgents,\n doctorReport,\n fallbackSkillsHome,\n installedSkills,\n probeBrowser,\n rulesFileFor,\n skillsDirFor,\n} from './machine'\nimport type { AgentHome, BrowserProbe, DoctorFacts } from './machine'\nimport { EXIT_ERROR, EXIT_NO_BROWSER, EXIT_OK, createReporter } from './output'\nimport {\n CREDENTIALS_PATH,\n apiError,\n apiJson,\n platformOrigin,\n resolveCredential,\n} from './platform'\nimport type { Reporter } from './output'\n\nconst BOOLEAN_FLAGS = new Set([\n 'json',\n 'help',\n 'global',\n 'no-skills',\n 'no-rules',\n 'no-browser',\n])\n\n/** The skills catalog on skills.sh, the first rung of the install. */\nexport const SKILLS_SOURCE = 'vosjs/skills'\n\nfunction reporterFor(flags: Record<string, string | true>): Reporter {\n return createReporter(flags.json === true || process.stdout.isTTY !== true)\n}\n\nfunction npx(): string {\n return process.platform === 'win32' ? 'npx.cmd' : 'npx'\n}\n\n/** Playwright's bundled Chromium, when it has been installed. */\nfunction bundledChromium(): string | null {\n try {\n const p = chromium.executablePath()\n return p && existsSync(p) ? p : null\n } catch {\n return null\n }\n}\n\nfunction probe(): BrowserProbe {\n return probeBrowser({\n platform: process.platform,\n env: process.env,\n exists: existsSync,\n bundled: bundledChromium,\n })\n}\n\nfunction ffmpegVersion(): string | null {\n const res = spawnSync('ffmpeg', ['-version'], { encoding: 'utf8' })\n if (res.status !== 0 || !res.stdout) return null\n const m = /ffmpeg version (\\S+)/.exec(res.stdout)\n return m ? m[1] : 'present'\n}\n\nasync function devServerFact(url: string): Promise<DoctorFacts['devServer']> {\n try {\n const res = await fetch(url, {\n signal: AbortSignal.timeout(2000),\n redirect: 'manual',\n })\n return { url, ok: res.status < 500, status: res.status }\n } catch (e) {\n return {\n url,\n ok: false,\n status: null,\n error: e instanceof Error ? e.message.split('\\n')[0] : String(e),\n }\n }\n}\n\n/** The vos skills, by name: what the bundled catalog carries. */\nfunction catalogNames(): string[] | null {\n const bundled = bundledSkillsDir(import.meta.url.replace('file://', ''))\n return bundled ? installedSkills(bundled) : null\n}\n\n/**\n * Every home's installed VOS skills, project and (under --global) home. A\n * home directory holds every skill a person ever installed; doctor answers\n * for ours, so the list is filtered to the catalog's names when the\n * bundled copy is there to say what they are.\n */\nfunction skillsFacts(homes: AgentHome[]): DoctorFacts['skills'] {\n const ours = catalogNames()\n return homes.map((h) => ({\n agent: h.agent,\n scope: h.scope,\n names: installedSkills(skillsDirFor(h)).filter(\n (n) => !ours || ours.includes(n),\n ),\n }))\n}\n\nasync function doctorFacts(opts: {\n homes: AgentHome[]\n url?: string\n}): Promise<DoctorFacts> {\n return {\n node: process.versions.node,\n browser: probe(),\n ffmpeg: ffmpegVersion(),\n skills: skillsFacts(opts.homes),\n credential: resolveCredential() !== null,\n ...(opts.url ? { devServer: await devServerFact(opts.url) } : {}),\n }\n}\n\n/**\n * `vos setup`: the skills into the agents' directories (skills.sh when\n * `npx` answers, else the copy this package ships), a browser found or\n * installed, one idempotent block in the rules file, then doctor.\n */\nexport async function cmdSetup(argv: string[]): Promise<number> {\n const { flags } = parseArgs(argv, BOOLEAN_FLAGS)\n const r = reporterFor(flags)\n const root = process.cwd()\n const global = flags.global === true\n const url = strFlag(flags, 'url')\n // Every flag is read up front: the flag tracker records READS, and a\n // --no-browser consulted only when no browser exists would count as\n // ignored on the machine that has one.\n const noSkills = flags['no-skills'] === true\n const noRules = flags['no-rules'] === true\n const noBrowser = flags['no-browser'] === true\n\n // 1. Which agents.\n const wanted = strFlag(flags, 'agent')\n let homes: AgentHome[]\n if (wanted) {\n const v = agentsFromFlag(wanted, root)\n if ('error' in v) throw new UsageError(v.error)\n homes = v.homes\n } else {\n homes = detectAgents(root, { home: homedir(), global })\n }\n const agents = [...new Set(homes.map((h) => h.agent))]\n r.event({ event: 'agents', agents, global })\n r.log(\n agents.length\n ? `agents: ${agents.join(', ')}`\n : 'agents: none detected here (the skills land in .agents/skills, which every agent reads)',\n )\n\n // 2. The skills.\n let skillsVia: 'skills.sh' | 'bundled' | 'skipped' = 'skipped'\n let skillNames: string[] = []\n if (!noSkills) {\n const args = [\n 'skills',\n 'add',\n SKILLS_SOURCE,\n '-y',\n ...(global ? ['-g'] : []),\n ]\n r.log(`installing the vos skills: npx ${args.join(' ')}`)\n const res = spawnSync(npx(), args, {\n cwd: root,\n encoding: 'utf8',\n stdio: ['ignore', 'pipe', 'pipe'],\n shell: process.platform === 'win32',\n timeout: 120_000,\n })\n if (res.status === 0) {\n skillsVia = 'skills.sh'\n } else {\n // The catalog CLI did not answer (no network, no npx, an older npm):\n // the copy this package ships is the same files at its release.\n const bundled = bundledSkillsDir(import.meta.url.replace('file://', ''))\n if (!bundled)\n throw new Error(\n `could not install the skills: npx skills add ${SKILLS_SOURCE} failed (${(res.stderr ?? '').trim().split('\\n').at(-1) ?? res.error?.message ?? 'no output'}) and this build carries no bundled copy`,\n )\n const targets = homes.length ? homes : [fallbackSkillsHome(root)]\n for (const home of targets) {\n const dest = skillsDirFor(home)\n mkdirSync(dest, { recursive: true })\n for (const name of installedSkills(bundled)) {\n cpSync(join(bundled, name), join(dest, name), { recursive: true })\n }\n }\n skillsVia = 'bundled'\n r.log(\n `skills.sh did not answer; copied the bundled skills into ${targets.map((t) => skillsDirFor(t)).join(', ')}`,\n )\n }\n skillNames = [\n ...new Set(\n (homes.length ? homes : [fallbackSkillsHome(root)]).flatMap((h) =>\n installedSkills(skillsDirFor(h)),\n ),\n ),\n ].sort()\n }\n r.event({ event: 'skills', via: skillsVia, names: skillNames })\n\n // 3. The browser.\n let browser = probe()\n if (browser.kind === 'none' && !noBrowser) {\n r.log(\n 'no browser found; installing Chromium: npx playwright install chromium',\n )\n spawnSync(npx(), ['playwright', 'install', 'chromium'], {\n cwd: root,\n stdio: ['ignore', 'ignore', 'inherit'],\n shell: process.platform === 'win32',\n timeout: 600_000,\n })\n browser = probe()\n }\n r.event({ event: 'browser', kind: browser.kind, path: browser.path })\n r.log(`browser: ${browser.line}`)\n\n // 4. The rules block.\n let rules: { file: string; changed: boolean } | null = null\n if (!noRules) {\n const file = rulesFileFor(root)\n const existing = existsSync(file) ? readFileSync(file, 'utf8') : null\n const { text, changed } = applyRulesBlock(existing)\n if (changed) writeFileSync(file, text)\n rules = { file, changed }\n r.log(\n changed\n ? `rules: wrote the vosso block into ${file}`\n : `rules: ${file} already carries the block`,\n )\n }\n r.event({ event: 'rules', ...(rules ?? { file: null, changed: false }) })\n\n // 5. Doctor.\n const report = doctorReport(\n await doctorFacts({\n homes: homes.length ? homes : [fallbackSkillsHome(root)],\n url,\n }),\n )\n r.done(\n {\n agents,\n skills: { via: skillsVia, names: skillNames },\n browser: { kind: browser.kind, path: browser.path },\n rules,\n doctor: { ok: report.ok, ...report.facts },\n next_step: report.next_step,\n },\n `${report.lines.join('\\n')}\\n\\nNext: ${report.next_step}`,\n )\n return report.ok ? EXIT_OK : EXIT_NO_BROWSER\n}\n\n/** `vos doctor`: what is ready, in words; exit 3 when no browser. */\nexport async function cmdDoctor(argv: string[]): Promise<number> {\n const { flags } = parseArgs(argv, BOOLEAN_FLAGS)\n const r = reporterFor(flags)\n const root = process.cwd()\n const homes = detectAgents(root, { home: homedir(), global: true })\n const report = doctorReport(\n await doctorFacts({\n homes: homes.length ? homes : [fallbackSkillsHome(root)],\n url: strFlag(flags, 'url'),\n }),\n )\n r.done(\n { ok: report.ok, ...report.facts, next_step: report.next_step },\n `${report.lines.join('\\n')}\\n\\nNext: ${report.next_step}`,\n )\n return report.ok ? EXIT_OK : EXIT_NO_BROWSER\n}\n\n/**\n * `vos whoami`: the key's name and the account it belongs to, from\n * `GET /user/whoami` (key- or session-readable on vos.so). Never the key.\n */\nexport async function cmdWhoami(argv: string[]): Promise<number> {\n const { flags } = parseArgs(argv, BOOLEAN_FLAGS)\n const r = reporterFor(flags)\n const origin = platformOrigin({\n origin: strFlag(flags, 'origin'),\n api: strFlag(flags, 'api'),\n })\n const key = resolveCredential(strFlag(flags, 'key'))\n if (!key) {\n r.done(\n {\n signedIn: false,\n origin,\n next_step:\n 'vos login (only needed for hosting, sharing or cloud rendering)',\n },\n `Not signed in to ${origin}. Recording and rendering need no account; vos login when you want a link.`,\n )\n return EXIT_ERROR\n }\n const res = await apiJson(origin, '/api/user/whoami', { key })\n if (res.status === 404) {\n // An origin from before the route: the credential exists, that is all\n // this CLI can say about it without printing it.\n r.done(\n {\n signedIn: true,\n origin,\n user: null,\n key: null,\n next_step: 'vos push when you want the work hosted',\n },\n `A credential is present for ${origin} (this origin cannot say whose).`,\n )\n return EXIT_OK\n }\n if (res.status === 401 || res.status === 403) {\n r.done(\n {\n signedIn: false,\n origin,\n error: apiError('whoami', res),\n next_step: 'vos login',\n },\n `The stored credential is refused by ${origin}: ${apiError('whoami', res)}. Run vos login.`,\n )\n return EXIT_ERROR\n }\n if (res.status !== 200) throw new Error(apiError('whoami', res))\n const user = res.body.user as {\n name?: string | null\n username?: string | null\n } | null\n const k = res.body.key as {\n name?: string\n prefix?: string\n scopes?: string[]\n createdAt?: string\n } | null\n const who = user?.username\n ? `@${user.username}`\n : (user?.name ?? 'an account')\n const keyLine = k\n ? `key \"${k.name ?? ''}\" (${k.prefix ?? '…'}, ${(k.scopes ?? []).join(', ') || 'no scopes'})`\n : 'a session, not a key'\n r.done(\n {\n signedIn: true,\n origin,\n user,\n key: k,\n next_step: 'vos push when you want the work hosted',\n },\n `Signed in to ${origin} as ${who}, with ${keyLine}.`,\n )\n return EXIT_OK\n}\n\n/** `vos logout`: remove the credentials file. Idempotent. */\nexport function cmdLogout(argv: string[]): number {\n const { flags } = parseArgs(argv, BOOLEAN_FLAGS)\n const r = reporterFor(flags)\n const had = existsSync(CREDENTIALS_PATH)\n rmSync(CREDENTIALS_PATH, { force: true })\n const envKey = Boolean(process.env.VOS_API_KEY?.trim())\n r.done(\n {\n path: CREDENTIALS_PATH,\n removed: had,\n envCredential: envKey,\n next_step: envKey\n ? 'unset VOS_API_KEY as well; it still resolves'\n : 'vos login when you next need hosting',\n },\n (had\n ? `Removed ${CREDENTIALS_PATH}.`\n : `Nothing stored at ${CREDENTIALS_PATH}.`) +\n (envKey\n ? ' VOS_API_KEY is still set in this shell and still resolves.'\n : ''),\n )\n return EXIT_OK\n}\n","/**\n * The machine (AN1): what `vos setup` and `vos doctor` know about the\n * computer they run on, as pure functions over injected facts. Agent\n * detection by directory, the rules block with its begin/end markers (so a\n * second run replaces its own text and never a person's), the browser\n * probe in the order the recorder itself resolves one, and the doctor\n * report in words. Nothing here spawns a process or prints; `machineCmd.ts`\n * does that and hands the answers in.\n *\n * Not `setup.ts`: that module is the SI `setup` steps of actions.json.\n */\nimport { existsSync, readFileSync, readdirSync, statSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\n\nexport type AgentName = 'claude' | 'cursor' | 'codex' | 'copilot'\n\nexport const AGENT_NAMES: readonly AgentName[] = [\n 'claude',\n 'cursor',\n 'codex',\n 'copilot',\n]\n\n/** One place an agent keeps its files: a project directory or a home one. */\nexport interface AgentHome {\n agent: AgentName\n /** The directory, absolute. Skills go under `<dir>/skills/`. */\n dir: string\n scope: 'project' | 'global'\n}\n\n/**\n * Where each agent keeps its project files. Codex reads `.codex/` and the\n * cross-agent `.agents/`; Copilot keeps its instructions under `.github/`.\n */\nconst PROJECT_DIRS: Record<AgentName, string[]> = {\n claude: ['.claude'],\n cursor: ['.cursor'],\n codex: ['.codex', '.agents'],\n copilot: ['.github/copilot'],\n}\n\n/** The home-directory forms, read under --global. */\nconst HOME_DIRS: Record<AgentName, string[]> = {\n claude: ['.claude'],\n cursor: ['.cursor'],\n codex: ['.codex', '.agents'],\n copilot: ['.copilot'],\n}\n\nexport interface DetectOptions {\n /** The person's home directory; read only when `global` is set. */\n home?: string\n global?: boolean\n /** Injected for tests. */\n exists?: (path: string) => boolean\n}\n\n/**\n * The agents present, by the directories they leave behind. A project\n * directory counts on its own; a home directory counts under --global.\n * Order is AGENT_NAMES order, project before global, so output is stable.\n */\nexport function detectAgents(\n root: string,\n opts: DetectOptions = {},\n): AgentHome[] {\n const exists = opts.exists ?? existsSync\n const out: AgentHome[] = []\n for (const agent of AGENT_NAMES) {\n for (const rel of PROJECT_DIRS[agent]) {\n const dir = join(root, rel)\n if (exists(dir)) out.push({ agent, dir, scope: 'project' })\n }\n // Copilot's project presence is often a single file, not a directory.\n if (\n agent === 'copilot' &&\n !out.some((h) => h.agent === 'copilot') &&\n exists(join(root, '.github', 'copilot-instructions.md'))\n ) {\n out.push({\n agent,\n dir: join(root, '.github', 'copilot'),\n scope: 'project',\n })\n }\n }\n if (opts.global && opts.home) {\n for (const agent of AGENT_NAMES) {\n for (const rel of HOME_DIRS[agent]) {\n const dir = join(opts.home, rel)\n if (exists(dir)) out.push({ agent, dir, scope: 'global' })\n }\n }\n }\n return out\n}\n\n/**\n * `--agent claude,cursor` or `--agent all`, validated. The homes it names\n * are the project directories whether or not they exist yet, so a person\n * can ready an agent they are about to install.\n */\nexport function agentsFromFlag(\n value: string,\n root: string,\n): { homes: AgentHome[] } | { error: string } {\n const wanted =\n value.trim() === 'all'\n ? [...AGENT_NAMES]\n : value\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean)\n const bad = wanted.filter((w) => !AGENT_NAMES.includes(w as AgentName))\n if (bad.length)\n return {\n error: `--agent takes ${AGENT_NAMES.join(', ')} or all, not \"${bad.join(', ')}\"`,\n }\n if (!wanted.length) return { error: '--agent expects a name' }\n return {\n homes: wanted.map((agent) => ({\n agent: agent as AgentName,\n dir: join(root, PROJECT_DIRS[agent as AgentName][0]),\n scope: 'project',\n })),\n }\n}\n\n/** Where skills live for one home; the layout the skills CLI writes. */\nexport function skillsDirFor(home: AgentHome): string {\n return join(home.dir, 'skills')\n}\n\n/** The cross-agent home the bundled copy lands in when no agent is found. */\nexport function fallbackSkillsHome(root: string): AgentHome {\n return { agent: 'codex', dir: join(root, '.agents'), scope: 'project' }\n}\n\n/** The skills installed under one skills directory: every `<name>/SKILL.md`. */\nexport function installedSkills(\n dir: string,\n exists: (p: string) => boolean = existsSync,\n list: (p: string) => string[] = (p) => {\n try {\n return readdirSync(p)\n } catch {\n return []\n }\n },\n): string[] {\n if (!exists(dir)) return []\n return list(dir)\n .filter((name) => exists(join(dir, name, 'SKILL.md')))\n .sort()\n}\n\n// ---------------------------------------------------------------------------\n// The rules block\n// ---------------------------------------------------------------------------\n\nexport const RULES_BEGIN =\n '<!-- vos:begin (written by vos setup; the block is replaced on the next run) -->'\nexport const RULES_END = '<!-- vos:end -->'\n\n/**\n * The block `vos setup` writes into AGENTS.md (or CLAUDE.md). Four things\n * an agent needs every session and nothing more: the skill, the hand-back,\n * local by default, where a credential comes from. The full contract is\n * the reference it names, never a wall inside a rules file.\n */\nexport const RULES_BODY = `## Product videos (vosso)\n- Skill: product-video (npx skills add vosjs/skills) records the real product from actions.json\n- Look before you cut: vos frames take --at-zooms; edit take/doc.json and re-render, never re-record\n- Hand back: vos open take serves the take into the studio at vos.so, doc.json intact\n- Local by default: vos push only when asked for a link, the shelf or a cloud render\n- Deleting: vos delete moves a vos to Trash and vos restore brings it back; if you deleted by mistake, restore it and say so. Only the person can delete forever, at vos.so/app/trash\n- Credentials: VOS_API_KEY, then ~/.config/vos/credentials, then vos login; never print one\n- Reference: https://vos.so/llms-full.txt`\n\nexport const RULES_BLOCK = `${RULES_BEGIN}\\n${RULES_BODY}\\n${RULES_END}`\n\n/**\n * The file with the block in it, idempotently: a file already carrying the\n * markers gets the text between them replaced (an older block, or one a\n * person edited, gives way to the current one); any other file gets the\n * block appended after one blank line. `changed` is false when the file\n * already reads exactly this.\n */\nexport function applyRulesBlock(existing: string | null): {\n text: string\n changed: boolean\n} {\n const current = existing ?? ''\n const begin = current.indexOf(RULES_BEGIN)\n const end = current.indexOf(RULES_END)\n let text: string\n if (begin !== -1 && end !== -1 && end > begin) {\n text =\n current.slice(0, begin) +\n RULES_BLOCK +\n current.slice(end + RULES_END.length)\n } else if (current.trim() === '') {\n text = `${RULES_BLOCK}\\n`\n } else {\n text = `${current.replace(/\\s*$/, '')}\\n\\n${RULES_BLOCK}\\n`\n }\n return { text, changed: text !== current }\n}\n\n/**\n * AGENTS.md when it exists, else CLAUDE.md when it exists, else AGENTS.md\n * (the cross-agent name, created). A file the project already keeps wins,\n * because the block belongs where the agent already reads.\n */\nexport function rulesFileFor(\n root: string,\n exists: (p: string) => boolean = existsSync,\n): string {\n const agents = join(root, 'AGENTS.md')\n if (exists(agents)) return agents\n const claude = join(root, 'CLAUDE.md')\n if (exists(claude)) return claude\n return agents\n}\n\n// ---------------------------------------------------------------------------\n// The browser\n// ---------------------------------------------------------------------------\n\nexport interface BrowserProbe {\n kind: 'env' | 'chrome' | 'chromium' | 'none'\n path: string | null\n /** The one line doctor prints for it. */\n line: string\n}\n\n/** The system Chrome's install locations, the ones `channel: 'chrome'` reads. */\nexport function chromeCandidates(\n platform: NodeJS.Platform,\n env: Record<string, string | undefined>,\n): string[] {\n if (platform === 'darwin')\n return ['/Applications/Google Chrome.app/Contents/MacOS/Google Chrome']\n if (platform === 'win32')\n return [\n join(\n env['PROGRAMFILES'] ?? 'C:\\\\Program Files',\n 'Google',\n 'Chrome',\n 'Application',\n 'chrome.exe',\n ),\n join(\n env['LOCALAPPDATA'] ?? '',\n 'Google',\n 'Chrome',\n 'Application',\n 'chrome.exe',\n ),\n ]\n return [\n '/usr/bin/google-chrome',\n '/usr/bin/google-chrome-stable',\n '/opt/google/chrome/chrome',\n ]\n}\n\n/**\n * The browser the recorder will use, in the recorder's own order:\n * VOS_BROWSER_PATH, then the system Chrome, then Playwright's bundled\n * Chromium (`bundled` answers its path when it is installed).\n */\nexport function probeBrowser(opts: {\n platform: NodeJS.Platform\n env: Record<string, string | undefined>\n exists: (p: string) => boolean\n bundled: () => string | null\n}): BrowserProbe {\n const explicit = opts.env.VOS_BROWSER_PATH?.trim()\n if (explicit) {\n return opts.exists(explicit)\n ? { kind: 'env', path: explicit, line: `${explicit} (VOS_BROWSER_PATH)` }\n : {\n kind: 'none',\n path: null,\n line: `VOS_BROWSER_PATH points at ${explicit}, which does not exist`,\n }\n }\n const chrome = chromeCandidates(opts.platform, opts.env).find(opts.exists)\n if (chrome) return { kind: 'chrome', path: chrome, line: 'Chrome (system)' }\n const chromium = opts.bundled()\n if (chromium)\n return { kind: 'chromium', path: chromium, line: 'Chromium (Playwright)' }\n return {\n kind: 'none',\n path: null,\n line: 'none: install Google Chrome, or run npx playwright install chromium',\n }\n}\n\n// ---------------------------------------------------------------------------\n// The doctor\n// ---------------------------------------------------------------------------\n\nexport const NODE_MIN_MAJOR = 18\n\nexport interface DoctorFacts {\n node: string\n browser: BrowserProbe\n /** The first line of `ffmpeg -version`, or null when absent. */\n ffmpeg: string | null\n skills: { agent: AgentName; scope: AgentHome['scope']; names: string[] }[]\n /** A credential resolves (flag, env or file). Never the value. */\n credential: boolean\n devServer?: {\n url: string\n ok: boolean\n status: number | null\n error?: string\n }\n}\n\nexport interface DoctorReport {\n /** Ready to record: a browser and a new-enough node. */\n ok: boolean\n lines: string[]\n next_step: string\n facts: DoctorFacts\n}\n\nfunction major(version: string): number {\n return parseInt(version.split('.')[0] ?? '0', 10)\n}\n\n/** The report in words; the JSON is `facts` plus `ok` and `next_step`. */\nexport function doctorReport(facts: DoctorFacts): DoctorReport {\n const lines: string[] = []\n const nodeOk = major(facts.node) >= NODE_MIN_MAJOR\n lines.push(\n `node ${facts.node} ${nodeOk ? '✓' : `✗ ${NODE_MIN_MAJOR} or newer is needed`}`,\n )\n const browserOk = facts.browser.kind !== 'none'\n lines.push(`browser ${facts.browser.line} ${browserOk ? '✓' : '✗'}`)\n lines.push(\n `ffmpeg ${facts.ffmpeg ? `${facts.ffmpeg} ✓` : 'absent (optional)'}`,\n )\n const withSkills = facts.skills.filter((s) => s.names.length)\n if (withSkills.length) {\n const names = [...new Set(withSkills.flatMap((s) => s.names))].sort()\n const agents = [\n ...new Set(\n withSkills.map((s) =>\n s.scope === 'global' ? `${s.agent} (global)` : s.agent,\n ),\n ),\n ]\n lines.push(`skills ${names.join(', ')} (${agents.join(', ')}) ✓`)\n } else {\n lines.push('skills none ✗ run: npx vos setup')\n }\n lines.push(\n `credential ${facts.credential ? 'present ✓' : 'absent (vos login when you need hosting)'}`,\n )\n if (facts.devServer) {\n const d = facts.devServer\n lines.push(\n `dev server ${d.url} ${\n d.ok\n ? 'answers ✓'\n : `does not answer ✗${d.error ? ` (${d.error})` : d.status ? ` (HTTP ${d.status})` : ''}`\n }`,\n )\n }\n\n let next_step: string\n if (!nodeOk)\n next_step = `Install Node ${NODE_MIN_MAJOR} or newer, then run npx vos doctor again`\n else if (!browserOk)\n next_step = 'Install Google Chrome, or run: npx playwright install chromium'\n else if (facts.devServer && !facts.devServer.ok)\n next_step = `Start the dev server so ${facts.devServer.url} answers, then record`\n else if (!withSkills.length) next_step = 'Run: npx vos setup'\n else\n next_step =\n 'Record: npx vos record --actions actions.json --out take --strict (the product-video skill writes actions.json)'\n return { ok: nodeOk && browserOk, lines, next_step, facts }\n}\n\n// ---------------------------------------------------------------------------\n// The bundled skills\n// ---------------------------------------------------------------------------\n\n/**\n * The copy of vosjs/skills this package ships (`packages/cli/skills`,\n * synced by `scripts/sync-skills.mjs`), found by walking up from the\n * calling module to the package root, so it resolves from `dist/` and from\n * `src/` alike. Null when the package carries none.\n */\nexport function bundledSkillsDir(from: string): string | null {\n let dir = dirname(from)\n for (let i = 0; i < 6; i++) {\n const pkg = join(dir, 'package.json')\n if (existsSync(pkg)) {\n try {\n const name = (\n JSON.parse(readFileSync(pkg, 'utf8')) as { name?: string }\n ).name\n if (name === '@vosjs/cli') {\n const skills = join(dir, 'skills')\n return existsSync(skills) && statSync(skills).isDirectory()\n ? skills\n : null\n }\n } catch {\n // not ours; keep walking\n }\n }\n const up = dirname(dir)\n if (up === dir) break\n dir = up\n }\n return null\n}\n"],"mappings":"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A;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAA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","names":["mkdir","readFile","rm","existsSync","join","resolve","END_CARD_FROM","docOutputDuration","migrateHostedDoc","words","overlaps","isObj","mkdir","readFile","rename","writeFile","existsSync","join","resolve","momentsFromDoc","planForDigest","ratedSegments","spanOutputExtent","resolve","pct","context","chunk","readFile","writeFile","existsSync","join","DIGEST_CROP_MAX","DIGEST_FULL_MAX","DIGEST_VERSION","join","existsSync","context","f","writeFile","readFile","out","ratedSegments","spanOutputExtent","resolve","join","mkdir","context","rename","existsSync","readFile","momentsFromDoc","planForDigest","parseTimes","writeFile","mkdir","rename","rm","writeFile","join","resolve","existsSync","readFile","docOutputDuration","writeFile","compileVosConfig","lowerToComposition","resolveExportSize","VIDEO_TOKEN","resolveExportSize","lowerToComposition","compileVosConfig","writeFile","ratedSegments","spanOutputExtent","off","ratedSegments","spanOutputExtent","relative","median","ratedSegments","spanOutputExtent","ratedSegments","spanOutputExtent","words","at","kept","hex","existsSync","readFile","join","resolve","docStillTime","existsSync","join","resolve","readFile","at","docStillTime","join","existsSync","readFile","probe","rm","docOutputDuration","resolve","mkdir","rename","writeFile","mkdir","readFile","writeFile","existsSync","isAbsolute","join","resolve","existsSync","mkdir","readFile","writeFile","isAbsolute","join","resolve","DESTINATIONS","DESTINATIONS","o","readFile","resolve","join","mkdir","existsSync","isAbsolute","writeFile","findFontFamily","existsSync","readFile","join","cameraModel","docCardLayout","docZoomTrack","pinBox","ratedSegments","resolvePins","spanOutputExtent","docCardLayout","docZoomTrack","ratedSegments","spanOutputExtent","at","window","cameraModel","resolvePins","pinBox","framesTake","join","existsSync","readFile","readFile","DUPLICATE_BITS","hexToRgb","at","ffmpeg","readFile","existsSync","readFile","stat","dirname","isAbsolute","join","DESTINATIONS","PNG_SIG","readFile","DESTINATIONS","dirname","isAbsolute","existsSync","join","stat","join","join","existsSync","statSync","join","resolve","existsSync","readFile","join","migrateMotion","resolveAnchor","at","join","existsSync","readFile","words","migrateMotion","existsSync","readFileSync","readdirSync","readFile","join","lowerToComposition","migrateHostedDoc","mkdir","writeFile","join","migrateHostedDoc","mkdir","join","writeFile","migrateHostedDoc","summary","readdirSync","readFileSync","join","existsSync","readFile","lowerToComposition","media","migrateHostedDoc","existsSync","mkdir","readFile","writeFile","createInterface","basename","dirname","join","migrateHostedDoc","BOOLEAN_FLAGS","join","existsSync","mkdir","writeFile","migrateHostedDoc","readFile","dirname","basename","title","created","watchUrl","studioUrl","landed","createInterface","probe","createHash","readFileSync","basename","BOOLEAN_FLAGS","basename","readFileSync","createHash","existsSync","rmSync","statSync","join","createInterface","BOOLEAN_FLAGS","at","entries","BOOLEAN_FLAGS","existsSync","statSync","createInterface","rmSync","join","readFileSync","writeFileSync","basename","dirname","join","resolve","at","BOOLEAN_FLAGS","resolve","readFileSync","basename","join","dirname","writeFileSync","existsSync","mkdirSync","statSync","writeFileSync","dirname","join","resolve","BOOLEAN_FLAGS","resolve","existsSync","statSync","dirname","mkdirSync","join","writeFileSync","existsSync","mkdirSync","readFileSync","writeFileSync","dirname","join","resolve","pathToFileURL","spawnSync","existsSync","mkdirSync","readFileSync","readdirSync","statSync","dirname","join","relative","resolve","pathToFileURL","findFontFamily","existsSync","readFileSync","readdirSync","statSync","createServer","basename","extname","join","overlaps","readdirSync","join","statSync","readFileSync","existsSync","createServer","extname","basename","existsSync","join","readFileSync","statSync","readdirSync","catalogFamily","findFontFamily","spawnSync","resolve","dirname","pathToFileURL","t","mkdirSync","relative","spawnSync","existsSync","mkdirSync","writeFileSync","basename","dirname","join","resolve","findFontFamily","hex","words","findFontFamily","resolve","basename","existsSync","mkdirSync","writeFileSync","join","dirname","spawnSync","BOOLEAN_FLAGS","resolve","mkdirSync","join","writeFileSync","existsSync","readFileSync","dirname","pathToFileURL","createHash","readFileSync","basename","BOOLEAN_FLAGS","basename","cmdPush","readFileSync","createHash","writeFile","resolve","parseFrontmatter","hex","parseFrontmatter","resolve","writeFile","setupEnvNames","setupEnvNames","writeFile","resolve","relative","resolve","readFile","summary","writeFile","existsSync","mkdir","readFile","stat","basename","join","resolve","BOOLEAN_FLAGS","basename","readFile","text","MULTI_FLAGS","resolve","existsSync","join","mkdir","stat","spawnSync","existsSync","mkdirSync","readFileSync","rmSync","writeFileSync","homedir","join","chromium","existsSync","readFileSync","readdirSync","statSync","dirname","join","chromium","BOOLEAN_FLAGS","chromium","existsSync","probe","spawnSync","homedir","mkdirSync","join","readFileSync","writeFileSync","rmSync","BOOLEAN_FLAGS","MULTI_FLAGS","readFile","resolve","existsSync","browser","context","join","mkdir","cmdCreate","rm","words","off","at","END_CARD_FROM","docOutputDuration","parseTimes","migrateHostedDoc","window","problems","warnings","probe","cmdPush","cmdPull","summary"]}