@vosjs/cli 0.83.1 → 0.83.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +0,0 @@
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/motionPlan.ts","../src/plugin/captionFit.ts","../src/plugin/moments.ts","../src/plugin/login.ts","../src/plugin/markAsset.ts","../src/plugin/officialTemplates.ts","../src/plugin/music.ts","../src/plugin/fontName.ts","../src/plugin/callout.ts","../src/plugin/picture.ts","../src/plugin/kitPicture.ts","../src/plugin/validateKit.ts","../src/plugin/recorder.ts","../src/plugin/session.ts","../src/plugin/sessionWindow.ts","../src/plugin/wall.ts","../src/plugin/exposure.ts","../src/plugin/setup.ts","../src/plugin/sessionExec.ts","../src/plugin/recordingCap.ts","../src/plugin/encode.ts","../src/plugin/plan.ts","../src/plugin/reuse.ts","../src/plugin/sync.ts","../src/plugin/takeScript.ts","../src/plugin/folder.ts","../src/plugin/platformEngine.ts","../src/plugin/program.ts","../src/plugin/programFiles.ts","../src/plugin/asset.ts","../src/plugin/assetWords.ts","../src/plugin/netAddress.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/traceInflate.ts","../src/plugin/checkVideo.ts","../src/plugin/videoChecks.ts","../src/plugin/join.ts","../src/plugin/score.ts","../src/plugin/stepCaptions.ts","../src/plugin/scriptStep.ts","../src/plugin/beats.ts","../src/plugin/rejoin.ts","../src/plugin/timeline.ts","../src/plugin/audio.ts","../src/plugin/look.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, bearerFor } 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: bearerFor(opts.key, origin) },\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 { dirname, 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 { jsSyntaxProblems, validateActions } from './actions'\nimport { lintDoc } from './validateDoc'\nimport { containerMismatch } from './container'\nimport { docAudioRefs, readMediaHead, takeRelativeFile } from './media'\nimport { localFile } from '../programAssets'\nimport {\n collectConfigMediaUrls,\n collectDocMediaUrls,\n mediaProbeLints,\n probeMediaUrls,\n} from './mediaProbe'\nimport {\n framesTake,\n parseTimes,\n unrenderedZoomLine,\n writeIndexJson,\n} from './framesTake'\nimport {\n deliverTake,\n readLaunchBesideTake,\n resolveChannels,\n resolveLook,\n readBrandBesideTake,\n} from './deliver'\nimport { launchDefaultBrowser } from './login'\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 {\n composeCallout,\n footageFrames,\n groundCheckTimes,\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 promptHint,\n readSyncState,\n requireCredential,\n resolveCredential,\n mintAt,\n} from './platform'\nimport { startTakeServer } from './server'\nimport {\n PREV_DOC_NAME,\n dropScreencastFrames,\n ensureTakeDir,\n loadTake,\n notePlannedDoc,\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, scriptForHost } from './recorder'\nimport { PasteFileRefusal } from './pasteFiles'\nimport type { RecordResult, SkippedStep } from './recorder'\nimport {\n RecordRefusedError,\n guardVerdict,\n guardedSteps,\n hostedRefusals,\n readyProblem,\n overrunLine,\n sayValue,\n} from '@vosjs/render-core/record'\nimport type { ReadyMode, ReadyReport } from '@vosjs/render-core/record'\nimport { WallError, wallVerdict } from './wall'\nimport {\n EXPOSURE_ADVICE,\n exposureLine,\n noticeAdvice,\n noticeLine,\n} from './exposure'\nimport { SetupEnvError, SetupError, parseHeaders, teardownLine } from './setup'\nimport {\n listSessions,\n openSession,\n removeSession,\n sessionVerdict,\n sessionDir,\n sessionNameVerdict,\n summarizeSession,\n summaryLine,\n withSession,\n verdictLine,\n} from './session'\nimport type { SessionVerdict } from './session'\nimport { ExecScriptError, execInProfile, loadExecScript } from './sessionExec'\nimport type { ExecScript } from './sessionExec'\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 type { PlanSummary } from './plan'\nimport { openingBackdrop } from './backdrops'\nimport { renderTake } from './renderTake'\nimport {\n PushRefusedError,\n pullTake,\n pushTake,\n pushTakeClaimable,\n takePushRefusal,\n} 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 {\n announceEnvNames,\n envReaders,\n hostedEnv,\n recordHosted,\n} from './hostedRecord'\nimport { urlSchemeProblem } from '@vosjs/render-core/record'\nimport { cmdActions } from './agentBrowser'\nimport { cmdIngest } from './ingest'\nimport { cmdCheckVideo } from './checkVideo'\nimport { cmdJoin } from './join'\nimport { cmdTakeInfo } from './timeline'\nimport { scriptDrift, scriptDriftLine } from './scriptStep'\nimport {\n applyZoomMarks,\n oneZoomPerBeat,\n perBeatLine,\n zoomMarkLine,\n zoomModeOf,\n} from './beats'\nimport type { PerBeatReport } from './beats'\nimport { cmdScore } from './score'\nimport { cmdAudio } from './audio'\nimport { PlatformBehindError } from './platformEngine'\nimport { bareCaptionsFlag, landStepCaptions } from './stepCaptions'\nimport type { StepCaptionReport } from './stepCaptions'\nimport { cmdLook } from './look'\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 'check',\n 'motion',\n 'leader',\n 'keep-frames',\n 'dry-run',\n 'allow-wall',\n 'hosted',\n 'claimable',\n 'share',\n 'verbose',\n 'bake',\n])\n/** Repeatable value flags (accumulate): --set path=value on render/frames, --override id on push, --browser-arg=<switch> and --confirm <id> on record/create. */\nexport const MULTI_FLAGS = new Set([\n 'set',\n 'override',\n 'browser-arg',\n 'header',\n 'confirm',\n])\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] [--reuse] [out.webm] [--strict] [--allow-wall] [--keep-frames] [--max-duration <s>] [--ready dom|networkidle] [--storage-state <file>|--session <name>] [--header name=value]... [--confirm <id>]... [--browser-arg=<switch>]... [--background <slug|url|none>] [render flags] [--json]\n vos record --actions actions.json [--url <url>] [--out take] [--reuse] [--strict] [--dry-run] [--allow-wall] [--keep-frames] [--max-duration <s>] [--ready dom|networkidle] [--storage-state <file>|--session <name>] [--header name=value]... [--confirm <id>]... [--browser-arg=<switch>]... [--background <slug|url|none>] [--verbose] [--json]\n --reuse, recording again into a take that has a cut: the cut (kept as doc.prev.json) goes onto the new footage as vos plan --reuse does; without it the take is planned fresh and its last line says where the cut is\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|--captions none] [--clicks none] [--still <t>] [--release v2.1] [--zooms per-beat] [--json]\n --zooms per-beat keeps at most one zoom per beat: the beats are the captioned steps of actions.json (each runs until the next one starts, plus the opening before the first); a step marked \"zoom\": true in actions.json is its beat's payoff, and the beat keeps the proposal that overlaps it most (one per marked step, never two overlapping), promoted to manual; a beat with no marked step keeps no zoom; when no step of the take is marked, each beat's last click, drag, type or paste stands in (the opening keeps none) and the done line says so; a step marked \"zoom\": false is never zoomed on; the rest go into doc.rejected like a person deleting them, and a beat with a manual zoom keeps only its manual ones. A media with no captioned step keeps its zooms as planned, and the done line says so\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>]... [--strict] [--json]\n --at-zooms stills every zoom span's apex on every media of the take and renders it again with the zooms off: a zoom whose frame matches its zoom-off twin did not render, and says so (exit 2 under --strict)\n vos check-video <file.mp4|webm> [--out dir] [--strict] [--json]\n the rendered file itself, no ffmpeg: duration, size, codecs, resolution, frame rate; full-frame scene changes (a warning when a 5 s window holds more than one); loudness (short-term every 3 s, integrated, sample peak; a warning below -23 or above -9 LUFS); the first and last frames as PNGs (a warning when either is near-uniform). Exit 2 on any warning under --strict\n vos deliver <take> --to youtube,x,shorts,github (or all) [--look plate|gradient|dark|none] [--brand BRAND.md] [--set path=value] [--release v2.1] [--out dir] [--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 info <take> [--json]\n the take's two clocks, read-only: per media, every step with its id, what it did, its source seconds (meta.json tStart..tEnd), its caption and where it plays; then the output timeline after trims, speed and freezes: each segment, speed span, freeze, zoom and tilt span (or \"(cut)\"), every layer with its anchor resolved, each sound clip, the still and the film's end\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 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 join <take> <take|file.mp4>... --out <dir> [--keep-edits|--force] [--captions] [--zooms per-beat] [--mute <file>]... [--json]\n several takes (and plain video files) as ONE take, cut in argument order: the first is the primary (its frame, cursor, export and sound), each next one a media m1, m2, … with its footage copied, its spans tagged and renamed, its layers moved to where it now starts; a file opens full-bleed and its own sound plays as an audio clip (--mute <file> leaves it out). --captions lands every step's caption anchored to its step, starting as the step begins (anchor.at \"start\"), each ending with its clip. --zooms per-beat keeps a beat's zoom on its steps marked \"zoom\": true (as vos plan --zooms per-beat). The result must pass vos validate before anything is written\n --keep-edits joins again over an edited joined take and keeps its edits: inputs are matched to their media by source file (join.json records each input's path and footage hash), a kept input keeps its id and everything on it (segments in their edited order, spans, rejections, anchored layers, its sound), the frame, export, styles and still stay, a new input is joined fresh under a new id (and only it is captioned or re-planned), a re-recorded input (changed footage at its path, or the same script at a new one) keeps its edits re-timed by its steps as vos plan --reuse does, and an input that is gone takes its edits with it, each named. A new input's segments go before the next kept input's; reordering the kept inputs regroups the segments in argument order. The first input must stay the primary. --force replaces the take instead\n vos score <take> --track <slug|file> [--at <step id|output seconds>] [--gain 0..1] [--normalize <lufs|off>] [--fade-in <s>] [--fade-out <s>] [--dry-run] [--json]\n the film's music as one audio clip (id score): reads the track's loudness, finds its strongest swell and offsets the track so the swell lands at --at (a step, resolved through the cut, or output seconds); without --at it starts where the track first rises above its median level. The clip carries its measured loudness and a target, --normalize (default -16 LUFS), with --gain (default 0.5) a trim on it; --normalize off plays it at --gain alone\n vos audio measure <take> [--json]\n every audio clip's loudness (BS.1770 integrated LUFS and sample peak, the meter check-video reads a render with), written beside it in doc.json as loudness { lufs, peakDb, at, src }; a clip's normalize (a target in LUFS, -30..-6) plays it at the gain that reaches it, past 1 if need be, capped so its peak stays under -1 dBFS, and only once it is measured for its own key\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 look <url> [--session <name>|--storage-state <file>] [--viewport WxH] [--headed] [--click <selector>]... [--type <selector>=<text>]... [--wait <ms>] [--header name=value]... [--browser-arg=<switch>]... [--out look] [--json]\n see a page before scripting it, signed in the way vos record would be: <out>/look.png and every control in view with ONE proposed selector (test id, aria-label, role + name, then words in its dialog or landmark), UNIQUE or AMBIGUOUS as the recorder's own engine counts it, plus what the frame exposes. --click/--type run first, in order; a click on a spend or delete word is refused. Exit 4 at a sign-in wall\n vos session open <url> --name <app> a plain Chrome window on a vos-owned profile; sign in, set the account up, close the window (or Enter)\n vos session check <name> [--url <url>] [--strict] headless, against a stranger: does the page open as you? exit 0/4\n vos session exec <name> <script.mjs> [--url <url>] [--headed] [--viewport WxH] [--json]\n run your own Playwright code inside the session: the module's default export gets { context, page, url, name } and what it returns is printed (result under --json). The ONLY safe way to script a session: a profile opened by any other browser (Playwright's bundled one, a mock keychain) cannot read its cookies and is signed out\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] [--skills-from-catalog] [--no-rules] [--no-browser] [--url <dev server>] [--json]\n ready this computer for the loop: the vos skills into your\n agent's directories (the copy bundled in this package, or with\n --skills-from-catalog the same tag through skills.sh), a\n browser found or installed, one idempotent block in AGENTS.md\n (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, its\n actions.json and every file that script pastes, beside it\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>] [--bake]\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 (NO\n credential): creates a 72h claim link instead — hand it to the\n user and nowhere else; unclaimed work is deleted after 72h. On a\n take it is for a REMIX of a public take fetched with --media: it\n uploads nothing, so every file must be one the fetch brought home,\n unchanged, and it credits the take it came from.\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, and so does every file a take's\n actions.json pastes (a picture through the upload door, a text\n file inside the document; one outside the take is refused). --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 A take push first reads which studio-core the platform renders\n with (GET /api/engine) and refuses (exit 2) a take using a field\n newer than it, which its studio would draw wrong and save that\n way; --bake sends a copy any renderer plays, every such field\n resolved (an anchored caption at the start it plays at, a\n loudness target as its gain) whatever the platform answered,\n doc.json untouched. Without --bake an unreadable answer warns\n and pushes.\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; the same bytes twice\n are the same file. Prints, per file, what was read, its\n asset:<id>, the url a doc.json key takes, and the line that\n declares it in a program's \"assets\"\n vos asset import <url> [--name <file>] [--folder <slug>]\n [--license <text>] [--attribution <text>]\n fetch a file from an address and add it, with where it came\n from kept beside it. Say the license: it is what lets the\n next person use the file\n vos assets ls [--kind <kind>] [--folder <slug>|none] [--q <text>]\n [--sort recent|size|name] [--limit <n>]\n what is in your library: id, kind, size, whether a program\n uses it, and whether it is a library file or attached to a\n document\n vos assets usage\n storage held, of how much, and the part in Trash; uploads in\n the last 24 hours per kind against each daily rate\n vos assets why <assetId>\n every program that uses a file, and how (in what plays now,\n in history, in a draft): why it is kept\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 human span follows the step it was made on (its window, or\nthe gesture just before it), keeping its offset exactly, or an explicit\nanchor {step, at, offset}; a span between steps maps piecewise through\nmatched step edges; a span whose step vanished is dropped and named with\nwhat it framed; autos re-plan; a layer pinned to a step follows its new\noutput time, every other layer and audio keep OUTPUT times, and a layer\nover a step that moved is named with the pin to write. The done event's\nreuse block NAMES whatever could not follow — fix by exception, never\nre-cut from scratch. Give steps ids in actions.json so re-timing survives\nscript edits.\n\nrecord --strict exits 2 when any selector was skipped, an expect never\nheld, a click landed on a disabled control, an await timed out, or the\ntake hit --max-duration (the done event lists skipped[], disabled[] and\ncapped either way). Step 1 runs once the first page has stopped changing\n(after load, 800 ms with no DOM change, at most 8 s); --ready networkidle\n(or \"ready\" in actions.json) waits for network idle instead, at most 45 s,\nwhich a page holding a socket open never reaches. The done event's ready\n{ mode, ms, capped } says how it settled; navTimeout is true only when\nnetworkidle was asked for and never came; neither is a strict failure. --max-duration defaults to\nthe hosted recording cap, read live from GET /api/limits (30 min when the\norigin is unreachable): the capture stops there and says so in one line.\nThree steps beyond the gestures: expect checks the page on camera\n(selector, text or gone; enabled; or js, an expression evaluated in the\npage, truthy or with equals a value, for state an app keeps in script,\nsaid with the value it got and kept on meta.steps[].value; timeout 5 s);\nawait waits OFF camera (until {selector|text|gone|js}, timeout 600 s,\npoll 2 s, reload, onTimeout fail|continue), so the footage has no gap and the cut lands in\nmeta.skips[] and becomes a segment boundary; download keeps a file the page\nmakes in the take's outputs/ (selector: the download a click starts; src:\nthe currentSrc of a video, audio or img; as: the file name), listed in\nmeta.outputs[]. Sound the page plays (a video or audio element heard,\nnot muted) lands in meta.media[] with the footage stretches it was heard;\nits file is fetched into page-sound/ and the plan places it as audio\nclips with source \"page\", which a re-plan replaces. The scan after each\nstep reports exposures (an email, a key, a card: kind and place) and,\napart, notices: the signed-in account's own name (its places, never the\nname) and a list of its recent items, with the mask that hides it;\nnotices are information, never a --strict failure. A click, press or type with \"guard\": \"spend\" costs\nsomething real: --dry-run hovers it and never presses, and record presses\nit only with --confirm <id> (repeatable), refusing before any capture\notherwise. --hosted refuses guarded, download, paste and js steps.\npeers in actions.json add other people OFF camera: each its own browser\ncontext (storageState, by a path from the actions file) on the same url,\nits steps started with a take step or after one (by id); only the take's\npage is filmed and only its steps make the cursor track, so a peer's work\nreaches the footage through the app's own sync. A peer takes wait, move,\nhover, click, type, press, scroll, drag and expect; its misses are skips\n(--strict fails on them); meta.peers[] places its steps; --hosted refuses it.\nEvery step is bounded: a call into a page that stopped answering gives up\nat the step's own timeout (an expect's or an await's, or a gesture's plan\nplus 30 s), the step is a skip with the real time it took, and --strict\nstops the take there. --json reports { event: \"step\", phase, i, id, do,\nms } as each step starts and ends.\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 (--size WxH for an exact size). 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 video destinations in one pass —\nthe channel specs (schema/channel-specs.json, verified sizes for a YouTube\ndemo, an X feed cut, a 9:16 cut for Shorts and LinkedIn, a GitHub README\nloop) drive each cut at exact pixels, every artifact is VERIFIED against\nits spec (px, bytes, duration; misses land in skipped[] with the reason),\nand kit.json beside the assets is the manifest. --range cuts every\ndestination. A channel with no video destination is refused in words.\nThe LOOK presents the card: every cut sits on a ground (a cream plate,\nthe house gradient, a dark plate with a light streak) at ~84% of the width\nwith headroom, a soft ambient shadow plus a tight contact shadow, and a\nhairline when card and ground are both light; a wide frame runs the card\noff the bottom. --look picks a house look (or none for the doc's own\nframe); with no flag the BRAND.md beside the take (or --brand <file>)\ndecides from its look role or its own ground, and with no brand the house\ngradient.\nplan --style <doc.json|vosId> copies a signed-off take's layout onto this\none (its card placement, its stage clips with the release's words patched\nin from LAUNCH.md's headline and kicker roles or --headline and --kicker,\nits rest lean, its freeze), or edit doc.json by hand.\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. --set\npath=value overrides the doc in memory for every render here (the user's\nsets apply last). Uploads stay manual: hand the human the kit\ndirectory, then vos validate <kit.json> re-measures every cut from its\nbytes against the channel specs; --picture adds what each cut LOOKS like:\nits first and last frames, read through ffmpeg, must not be blank or bled\non all four sides. Every finding carries a code, a severity and a fix\nhint; an error fails the verdict beside the spec problems.\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 brand's roles (bgA/bgB/bgC, ink, accent,\nfontDisplay, 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) errors.push(...jsSyntaxProblems(raw as ActionsFile))\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 disabled?: unknown[]\n capped: boolean\n masks?: { selector: string; hits: number }[]\n meta?: { steps?: { do: string; timedOut?: boolean }[] }\n}): string {\n const parts = [`${rec.skipped.length} skipped step(s)`]\n if (rec.disabled?.length)\n parts.push(`${rec.disabled.length} click(s) on a disabled control`)\n const timedOut = timedOutAwaits(rec)\n if (timedOut) parts.push(`${timedOut} await(s) that timed out`)\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/** How many awaits gave up and let the take go on (`onTimeout: \"continue\"`). */\nfunction timedOutAwaits(rec: {\n meta?: { steps?: { do: string; timedOut?: boolean }[] }\n}): number {\n return (rec.meta?.steps ?? []).filter((s) => s.do === 'await' && s.timedOut)\n .length\n}\n\n/**\n * What `--strict` fails a take on: a skipped step (a selector that never\n * appeared, an expect that never held, a download that never came), a\n * click on a disabled control, an await that timed out, the cap, a mask\n * that hid nothing. Never a first load that missed networkidle: plenty of\n * real apps hold a socket open for good and never go network-idle, so that\n * is a warning (`navTimeout` in the done event), or every take of them\n * would fail.\n */\nexport function strictFails(rec: RecordResult): boolean {\n return (\n rec.skipped.length > 0 ||\n rec.disabled.length > 0 ||\n timedOutAwaits(rec) > 0 ||\n rec.capped ||\n maskMisses(rec).length > 0\n )\n}\n\n/**\n * `--ready dom|networkidle`: when the first page counts as ready, over\n * the script's own `ready`. Folded into the actions, so the take's\n * actions.json says how it was recorded and a hosted take carries it.\n */\nfunction withReady(\n actions: ActionsFile,\n flags: ParsedArgs['flags'],\n): ActionsFile {\n const asked = strFlag(flags, 'ready')\n if (asked === undefined) return actions\n const problem = readyProblem(asked)\n if (problem) throw new UsageError(`--${problem}`)\n return { ...actions, ready: asked as ReadyMode }\n}\n\n/**\n * The note a take or rehearsal prints when the first load gave up waiting:\n * network idle never came (asked for with `ready: \"networkidle\"`), or the\n * page never stopped changing within the settle's cap.\n */\nfunction navTimeoutNote(rec: {\n navTimeout: boolean\n ready?: ReadyReport\n}): string {\n if (rec.navTimeout)\n return '\\n note: the first load never reached networkidle (a page holding a socket open never does); recorded anyway. The default, ready \"dom\", waits for the page to stop changing instead'\n if (rec.ready?.mode === 'dom' && rec.ready.capped)\n return `\\n note: the first page was still changing after ${(rec.ready.ms / 1000).toFixed(1)} s (an animation, a ticker); the take started anyway. Give step 1 a wait if the page needs longer`\n return ''\n}\n\n/** `vos validate`'s notices section: information about the footage, after the warnings. */\nfunction noticeLines(notices: string[]): string {\n return notices.length ? `\\n noticed:\\n ${notices.join('\\n ')}` : ''\n}\n\n/** A value as a shell word: bare when it is plain, else single-quoted. */\nfunction shellWord(v: string): string {\n return /^[\\w@%+=:,./-]+$/.test(v) ? v : `'${v.replace(/'/g, `'\\\\''`)}'`\n}\n\n/** The sound the page played, as the take-ready line says it. */\nfunction pageSoundNote(rec: Pick<RecordResult, 'media'>): string {\n const heard = rec.media.filter((m) => m.intervals.length)\n if (!heard.length) return ''\n const kept = heard.filter((m) => m.file)\n const lost = heard.filter((m) => !m.file)\n return `\\n page sound: ${heard.length} source(s) heard; ${kept.length} kept in page-sound/ and placed as audio clips (source \"page\")${lost.length ? `; not kept: ${lost.map((m) => `${m.src || 'a media element'} (${m.fetchError ?? 'no file'})`).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 recorder noticed (the account's name, its recent items), in words: information, never a failure. */\nfunction noticeNote(rec: {\n notices: Parameters<typeof noticeLine>[0][]\n}): string {\n if (!rec.notices.length) return ''\n return `\\n NOTICED in the frame (${rec.notices.length}):\\n${rec.notices\n .map((n) => ` - ${noticeLine(n)}`)\n .join('\\n')}\\n ${noticeAdvice(rec.notices)}`\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 * What the script's teardown did after the take, for the end of a record or\n * a rehearsal: how many steps ran, or where it stopped and what may be left\n * behind. Never part of whether the take passed.\n */\nfunction teardownNote(rec: Pick<RecordResult, 'teardown'>): string {\n return rec.teardown ? `\\n ${teardownLine(rec.teardown)}` : ''\n}\n\n/** The teardown's report on a done event, when the script has one. */\nfunction teardownField(rec: Pick<RecordResult, 'teardown'>): {\n teardown?: NonNullable<RecordResult['teardown']>\n} {\n return rec.teardown ? { teardown: rec.teardown } : {}\n}\n\n/**\n * `--confirm <id>`, repeatable: the guarded steps a recording may press.\n * Checked against the script BEFORE a browser opens, so a step that\n * spends is refused (or a typo in an id is caught) at no cost; a\n * rehearsal presses no guarded step, so it takes the flag and checks\n * nothing.\n */\nfunction takeConfirm(\n multi: ParsedArgs['multi'],\n actions: ActionsFile,\n opts: { dryRun: boolean; r: Reporter },\n): string[] {\n const given = ((multi.confirm as string[] | undefined) ?? []).filter(Boolean)\n if (opts.dryRun) return given\n const verdict = guardVerdict(actions, given)\n if (!verdict.ok) {\n // Under --json the refusal is an event too, one per step or name it is\n // about, beside the sentence on stderr.\n const guarded = guardedSteps(actions)\n for (const id of verdict.unconfirmed)\n opts.r.event({\n event: 'refused',\n reason: verdict.message,\n step: guarded.find((g) => g.id === id)?.step ?? null,\n id,\n })\n for (const id of verdict.unknown)\n opts.r.event({\n event: 'refused',\n reason: verdict.message,\n step: null,\n id,\n })\n throw new UsageError(verdict.message)\n }\n return given\n}\n\n/** What the new steps reported, in lines for the end of a record or a rehearsal. */\nfunction stepReportNote(\n rec: Pick<\n RecordResult,\n 'disabled' | 'skips' | 'outputs' | 'confirmed' | 'stopped'\n > &\n Partial<Pick<RecordResult, 'overruns'>>,\n): string {\n const lines: string[] = []\n const overrun = overrunLine(rec.overruns ?? [])\n if (overrun) lines.push(`OVERRUN: ${overrun}`)\n if (rec.disabled.length)\n lines.push(\n `DISABLED when clicked: ${rec.disabled.map((d) => `#${d.step}${d.id ? ` ${d.id}` : ''} ${d.selector}`).join(', ')} (the press likely did nothing; an expect with enabled: true before it waits for the control)`,\n )\n if (rec.skips.length)\n lines.push(\n `off camera: ${rec.skips.map((s) => `#${s.step}${s.id ? ` ${s.id}` : ''} ${(s.ms / 1000).toFixed(1)} s, cut at ${s.at.toFixed(2)}s${s.timedOut ? ' (timed out)' : ''}`).join(', ')}`,\n )\n if (rec.outputs.length)\n lines.push(\n `outputs/: ${rec.outputs.map((o) => `${o.name} (${o.bytes} bytes)`).join(', ')}`,\n )\n if (rec.confirmed.length)\n lines.push(`pressed, as --confirm said: ${rec.confirmed.join(', ')}`)\n if (rec.stopped) lines.push(`STOPPED: ${rec.stopped.reason}`)\n return lines.map((l) => `\\n ${l}`).join('')\n}\n\n/** A skipped step in words: the reason when it has one, else the selector that never appeared. */\nfunction skippedLine(s: SkippedStep): string {\n return `${s.peer ? `peer ${s.peer} ` : ''}#${s.step}${s.id ? ` ${s.id}` : ''} ${s.do}${s.reason ? `: ${s.reason}` : ` ${s.selector}`}`\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\n/**\n * A re-record replaces the FOOTAGE, never the cut. Run by the wall gate,\n * once the recorder has landed where it was asked: 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 *\n * `--reuse` applies that cut to the new footage in the same command (what\n * `vos plan --reuse` does); without it, the take's last line and its done\n * event say where the cut is and how to apply it, because a note logged\n * before the take is gone by the time anyone reads the result.\n */\nexport function reRecord(\n outDir: string,\n flags: ParsedArgs['flags'],\n r: { log: (line: string) => void },\n): {\n prepare: () => Promise<void>\n plan: (backdrop: Backdrop | null) => Promise<PlanSummary>\n previousCut: () => string | null\n} {\n const wantsReuse = flags.reuse === true\n if (wantsReuse && !existsSync(join(outDir, 'doc.json')))\n throw new UsageError(\n `--reuse: ${outDir} has no cut to keep (no doc.json); record without --reuse`,\n )\n let previousCut: string | null = null\n return {\n prepare: async () => {\n if (existsSync(join(outDir, 'meta.json'))) {\n const { prevDoc, kept } = await prepareReRecord(outDir)\n if (prevDoc) previousCut = join(outDir, PREV_DOC_NAME)\n r.log(\n `note: re-recording ${outDir} — kept ${kept.length ? kept.join(', ') : 'nothing'}` +\n (prevDoc\n ? wantsReuse\n ? '; the previous cut goes onto the new footage when it is recorded (--reuse)'\n : `; the previous cut is ${PREV_DOC_NAME}`\n : ''),\n )\n }\n await mkdir(outDir, { recursive: true })\n await ensureTakeDir(outDir)\n },\n plan: async (backdrop) => {\n const from = wantsReuse ? previousCut : null\n const plan = await planTake(outDir, {\n backdrop,\n ...(from\n ? {\n reuse: {\n from,\n doc: JSON.parse(await readFile(from, 'utf8')) as ProjectDoc,\n },\n }\n : {}),\n })\n // A fresh plan is noted, so the next re-record knows it was never\n // edited and keeps the cut in doc.prev.json; a reused cut IS the cut.\n if (!from) await notePlannedDoc(outDir)\n return plan\n },\n previousCut: () => previousCut,\n }\n}\n\n/** What a re-record says after its take about the cut it kept: lines and done-event fields. */\nexport function previousCutReport(\n outDir: string,\n previousCut: string | null,\n plan: Pick<PlanSummary, 'reuse'> | null,\n): { line: string; next: string | null; fields: Record<string, unknown> } {\n if (plan?.reuse) {\n const s = plan.reuse\n return {\n line:\n `\\n reused ${s.from}: ${s.anchored} anchored + ${s.mapped} mapped span(s)` +\n (s.flagged.length\n ? `\\n flagged:\\n ${s.flagged.join('\\n ')}`\n : ''),\n next: null,\n fields: { previousCut: s.from, reuse: s },\n }\n }\n if (!previousCut) return { line: '', next: null, fields: {} }\n const next = `vos plan ${outDir} --reuse`\n return {\n line: `\\n YOUR PREVIOUS CUT is kept in ${previousCut}, not on this footage. Apply it: ${next} (or record with --reuse next time)`,\n next,\n fields: { previousCut, next_step: next },\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 = withReady(await loadActions(actionsPath), flags)\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 scheme = urlSchemeProblem(url)\n if (scheme) throw new UsageError(scheme)\n // What the script reads from this shell, by name, before any value is.\n announceEnvNames(actions, r)\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 // A guarded step the command did not name is refused here, before a\n // browser opens; on the fleet there is no way to name one at all.\n const confirm =\n flags.hosted === true\n ? []\n : takeConfirm(multi, actions, {\n dryRun: flags['dry-run'] === true,\n r,\n })\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 // Nobody can confirm a step that spends on the fleet, and a download\n // has no take directory to land in there.\n // The script travels alone: a path a file holds goes up inline.\n const hostedActions = await scriptForHost(\n actions,\n dirname(resolve(actionsPath)),\n ).catch((e: unknown) => {\n throw new UsageError(e instanceof Error ? e.message : String(e))\n })\n const refusals = hostedRefusals(hostedActions)\n if (refusals.length)\n throw new UsageError(\n `a hosted take cannot run this script: ${refusals.join('; ')}`,\n )\n if ((multi.confirm as string[] | undefined)?.length)\n throw new UsageError(\n '--confirm presses a guarded step on this machine; a hosted take runs no guarded step, so drop --hosted to record it here',\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 ${origin} needs a credential: vos login, or VOS_API_KEY (mint a key at ${mintAt(origin)})`,\n )\n const { env, missing } = hostedEnv(actions, process.env)\n if (missing.length)\n throw new UsageError(\n `${envReaders(actions)} ${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: { ...hostedActions, 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 const cut = reRecord(outDir, flags, r)\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 // --reuse acts on the take, which a rehearsal never touches.\n void flags.strict\n void flags['keep-frames']\n void flags.reuse\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 actionsDir: dirname(resolve(actionsPath)),\n storageState,\n headers,\n context,\n dryRun: true,\n // A rehearsal is always strict: a page that stops answering stops it.\n stopOnHang: true,\n verbose: flags.verbose === true,\n onEvent: (e) => r.event(e),\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 const out = rec.outputs.find((o) => o.step === s.step)\n const notes = [\n ...(rec.disabled.some((d) => d.step === s.step)\n ? ['DISABLED, pressed anyway']\n : []),\n ...(s.guard && !s.skipped\n ? [`guarded (${s.guard}), hovered, not pressed`]\n : []),\n ...(s.followsGuard !== undefined\n ? [\n `not waited: it follows #${s.followsGuard} (guarded, not pressed)`,\n ]\n : []),\n ...(s.offCameraMs !== undefined\n ? [\n `${s.timedOut ? 'timed out after' : 'held after'} ${(s.offCameraMs / 1000).toFixed(1)} s off camera`,\n ]\n : []),\n ...(out\n ? [`→ ${out.name} (${out.bytes} bytes, not kept in a rehearsal)`]\n : []),\n ...(s.value !== undefined && !s.skipped\n ? [`= ${sayValue(s.value)}`]\n : []),\n ].map((n) => ` ${n}`)\n return ` ${s.skipped ? '✗' : '✓'} #${s.step}${s.id ? ` (${s.id})` : ''} ${s.do}${what}${s.skipped ? ` ${s.reason ?? 'NOT FOUND'}` : rect}${s.navigated ? ' → navigated' : ''}${notes.join('')}`\n })\n // A step that never ran (the take stopped, or hit the cap) is listed\n // too, so the count is out of the whole script.\n for (const [i, step] of actions.steps.entries())\n if (!steps.some((s) => s.step === i))\n lines.push(\n ` – #${i}${step.id ? ` (${step.id})` : ''} ${step.do} not run`,\n )\n // Each peer's steps, off camera: what ran, what missed, what never did.\n for (const pr of rec.peers) {\n const peer = actions.peers?.find((p) => p.id === pr.id)\n lines.push(` peer ${pr.id} (off camera):`)\n for (const ps of pr.steps)\n lines.push(\n ` ${ps.skipped ? '✗' : '✓'} #${ps.step}${ps.id ? ` (${ps.id})` : ''} ${ps.do}${ps.selector ? ` ${ps.selector}` : ''}${ps.with ? ` with ${ps.with}` : ps.after ? ` after ${ps.after}` : ''}${ps.skipped ? ` ${ps.reason ?? 'NOT FOUND'}` : ''}${ps.late ? ' (late)' : ''}`,\n )\n for (const i of pr.notRun)\n lines.push(` – #${i} ${peer?.steps[i]?.do ?? 'step'} not run`)\n }\n const resolved = steps.filter((s) => !s.skipped).length\n // A rehearsal is always strict; a first load that never went\n // network-idle is a note, as in a take.\n const failed = strictFails(rec) || rec.stopped !== null\n const unconfirmed = guardVerdict(actions, confirm)\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 // Every flag that shapes the take, as given, so the next command\n // records what was rehearsed.\n ...(['url', 'ready', 'max-duration', 'background'] as const).flatMap(\n (k) =>\n strFlag(flags, k)\n ? [`--${k} ${shellWord(strFlag(flags, k)!)}`]\n : [],\n ),\n ...(flags['keep-frames'] === true ? ['--keep-frames'] : []),\n ...(strFlag(flags, 'storage-state')\n ? [`--storage-state ${strFlag(flags, 'storage-state')}`]\n : []),\n ...browserArgs.map((a) => `--browser-arg=${a}`),\n // A header value is a bypass token more often than not: named, never\n // printed.\n ...Object.keys(headers).map((k) => `--header ${k}=…`),\n ...(sessionName ? [`--session ${sessionName}`] : []),\n ...(flags['allow-wall'] === true ? ['--allow-wall'] : []),\n ...confirm.map((c) => `--confirm ${c}`),\n // A take that already has a cut keeps it on the new footage.\n ...(existsSync(join(outDir, 'doc.json')) ? ['--reuse'] : []),\n ].join(' ')\n const nextOut = strFlag(flags, 'out') ?? 'take'\n // A guarded step the next command does not name would refuse it: the\n // hint says so rather than adding the confirmation for the person.\n const guardNote = !unconfirmed.ok\n ? unconfirmed.unconfirmed.length\n ? ` (it refuses until you add ${unconfirmed.unconfirmed.map((id) => `--confirm ${id}`).join(' ')}: ${unconfirmed.unconfirmed.length === 1 ? 'that step spends' : 'those steps spend'} something real)`\n : ` (${unconfirmed.unknown.map((c) => `--confirm ${c}`).join(', ')} names no guarded step)`\n : ''\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 disabled: rec.disabled,\n skips: rec.skips,\n outputs: rec.outputs,\n pageErrors: rec.pageErrors,\n ...(rec.stopped ? { stopped: rec.stopped } : {}),\n navTimeout: rec.navTimeout,\n ready: rec.ready,\n exposures: rec.exposures,\n notices: rec.notices,\n masks: rec.masks,\n ...(rec.peers.length ? { peers: rec.peers } : {}),\n ...teardownField(rec),\n },\n `${failed ? 'REHEARSAL FAILED' : 'Rehearsal passed'}: ${resolved}/${actions.steps.length} steps resolved in ${((Date.now() - started) / 1000).toFixed(1)}s${rec.navTimeout ? ' (the first load never reached networkidle)' : rec.ready.capped ? ' (the first page never stopped changing)' : ''}\\n${lines.join('\\n')}\\n ${maskMisses(rec).length ? `MASK hid nothing: ${maskMisses(rec).join(', ')} (the selector reached no element). ` : ''}${rec.stopped ? `STOPPED: ${rec.stopped.reason}. ` : ''}${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${guardNote}`}${exposureNote(rec)}${noticeNote(rec)}${teardownNote(rec)}`,\n )\n // An await that gave up stops the take, in a rehearsal as in a record.\n return rec.stopped ? EXIT_ERROR : failed ? EXIT_USAGE : EXIT_OK\n } finally {\n await browser.close()\n }\n }\n\n const paths = takePaths(outDir)\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 actionsDir: dirname(resolve(actionsPath)),\n maxDurationSeconds: maxDurationSeconds,\n storageState: storageState,\n headers,\n context,\n confirm,\n stopOnHang: flags.strict === true,\n verbose: flags.verbose === true,\n onEvent: (e) => r.event(e),\n onArrival: wallGate(flags, r, {\n strict: flags.strict === true,\n prepare: cut.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 cut.plan(backdrop)\n const kept = previousCutReport(outDir, cut.previousCut(), plan)\n const clicks = rec.events.filter((e) => e.type === 'down').length\n const strict = flags.strict === true\n const strictFail = strict && strictFails(rec)\n const skippedNote = rec.skipped.length\n ? `\\n SKIPPED ${rec.skipped.length} step(s): ${rec.skipped.map(skippedLine).join(', ')}`\n : ''\n const stepNote = stepReportNote(rec)\n // An await that gave up stopped the take: the directory holds the\n // footage up to it, whole, and the command fails in words.\n if (rec.stopped) {\n r.done(\n {\n take: outDir,\n ok: false,\n stopped: rec.stopped,\n durationMs: rec.meta.durationMs,\n skipped: rec.skipped,\n disabled: rec.disabled,\n confirmed: rec.confirmed,\n skips: rec.skips,\n outputs: rec.outputs,\n pageErrors: rec.pageErrors,\n ...kept.fields,\n ...teardownField(rec),\n },\n `FAILED: ${rec.stopped.reason}.\\n The footage up to it is in ${outDir}.${skippedNote}${stepNote}${navTimeoutNote(rec)}${kept.line}${teardownNote(rec)}`,\n )\n return EXIT_ERROR\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 ready: rec.ready,\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 notices: rec.notices,\n ...(rec.masks.length ? { masks: rec.masks } : {}),\n disabled: rec.disabled,\n confirmed: rec.confirmed,\n skips: rec.skips,\n outputs: rec.outputs,\n ...(rec.media.length ? { media: rec.media } : {}),\n overruns: rec.overruns,\n pageErrors: rec.pageErrors,\n ...(rec.peers.length ? { peers: rec.peers } : {}),\n ...teardownField(rec),\n ...(strictFail ? { strictFailed: true } : {}),\n ...kept.fields,\n },\n strictFail\n ? `STRICT: take recorded but incomplete — ${strictReason(rec)}; fix the flow and re-record.${skippedNote}${stepNote}${navTimeoutNote(rec)}${kept.line}${exposureNote(rec)}${noticeNote(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}${stepNote}${navTimeoutNote(rec)}${pageSoundNote(rec)}${kept.line}\\n Next: ${kept.next ? `${kept.next}, then` : `edit ${join(outDir, 'doc.json')} (optional), then:`} vos render ${outDir}${exposureNote(rec)}${noticeNote(rec)}${teardownNote(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 (a skipped step, a disabled click, a\n * timed-out await, the cap); a missed networkidle is only a warning.\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 = withReady(await loadActions(actionsPath), flags)\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 scheme = urlSchemeProblem(url)\n if (scheme) throw new UsageError(scheme)\n announceEnvNames(actions, r)\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 const confirm = takeConfirm(multi, actions, { dryRun: false, r })\n\n const paths = takePaths(outDir)\n const cut = reRecord(outDir, flags, r)\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 actionsDir: dirname(resolve(actionsPath)),\n maxDurationSeconds: maxDurationSeconds,\n storageState: storageState,\n headers,\n context,\n confirm,\n stopOnHang: flags.strict === true,\n verbose: flags.verbose === true,\n onEvent: (e) => r.event(e),\n onArrival: wallGate(flags, r, {\n strict: flags.strict === true,\n prepare: cut.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 const plan = await cut.plan(backdrop)\n const kept = previousCutReport(outDir, cut.previousCut(), plan)\n\n // An await that gave up stopped the take: nothing is rendered.\n if (rec.stopped) {\n r.done(\n {\n take: outDir,\n ok: false,\n stopped: rec.stopped,\n skipped: rec.skipped,\n rendered: false,\n ...kept.fields,\n ...teardownField(rec),\n },\n `FAILED: ${rec.stopped.reason}. NOT rendering; the footage up to it is in ${outDir}.${kept.line}${teardownNote(rec)}`,\n )\n return EXIT_ERROR\n }\n\n if (flags.strict === true && strictFails(rec)) {\n r.done(\n {\n take: outDir,\n skipped: rec.skipped,\n disabled: rec.disabled,\n navTimeout: rec.navTimeout,\n ready: rec.ready,\n capped: rec.capped,\n strictFailed: true,\n rendered: false,\n ...kept.fields,\n ...teardownField(rec),\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}${kept.line}${teardownNote(rec)}`,\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 ready: rec.ready,\n freezes: rec.freezes,\n freezePct: rec.freezePct,\n dead: rec.dead,\n exposures: rec.exposures,\n notices: rec.notices,\n ...(rec.masks.length ? { masks: rec.masks } : {}),\n disabled: rec.disabled,\n confirmed: rec.confirmed,\n skips: rec.skips,\n outputs: rec.outputs,\n ...(rec.media.length ? { media: rec.media } : {}),\n overruns: rec.overruns,\n pageErrors: rec.pageErrors,\n ...teardownField(rec),\n ...(flags.draft === true ? { draft: true } : {}),\n ...kept.fields,\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}${stepReportNote(rec)}${navTimeoutNote(rec)}${kept.line}${exposureNote(rec)}${noticeNote(rec)}${teardownNote(rec)}`,\n )\n return EXIT_OK\n } finally {\n await browser.close()\n }\n}\n\nasync function cmdPlan(argvIn: string[]): Promise<number> {\n // A bare `--captions` lands every step's caption anchored to its step.\n const argv = bareCaptionsFlag(argvIn)\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] [--zooms per-beat]',\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 stepCaptions = strFlag(flags, 'captions') === 'steps'\n const zoomMode = zoomModeOf(strFlag(flags, 'zooms'))\n if (zoomMode && typeof zoomMode === 'object')\n throw new UsageError(zoomMode.error)\n // Step captions are anchored to their steps; the plan's fixed-time beat\n // captions would say the same words twice.\n if (stepCaptions) release.launchRoles.captions = 'none'\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 let captions: StepCaptionReport | null = null\n if (stepCaptions) {\n const take = await loadTake(dir)\n captions = landStepCaptions(s.doc, new Map([['', take.actions]]))\n await writeJson(take.paths.doc, s.doc, true)\n }\n // The script's zoom marks: a step marked `zoom: false` loses the\n // planner's proposal on it, a step marked `zoom: true` with none is said.\n // Read from actions.json now, so a mark added after recording counts.\n const marksTake = await loadTake(dir)\n // A script edited since the take was recorded is read step by step\n // against what was recorded: said, never refused.\n const drift = scriptDrift(\n marksTake.meta.steps ?? [],\n marksTake.actions?.steps,\n )\n if (drift) r.warn(scriptDriftLine(drift))\n const marks = applyZoomMarks(s.doc, new Map([['', marksTake.actions]]))\n if (marks.rejected.length) await writeJson(marksTake.paths.doc, s.doc, true)\n const marksLine = zoomMarkLine(marks)\n // One zoom per beat: the captioned steps are the beats, the marked steps\n // their payoffs, and every other proposal inside one is rejected the way\n // a person deletes it.\n let perBeat: PerBeatReport | null = null\n if (zoomMode === 'per-beat') {\n const take = await loadTake(dir)\n perBeat = oneZoomPerBeat(s.doc, new Map([['', take.actions]]))\n await writeJson(take.paths.doc, s.doc, true)\n }\n const zoomAuto = s.doc.zoom.filter((z) => z.source !== 'manual').length\n const zoomManual = s.doc.zoom.length - zoomAuto\n const captionLines = captions\n ? `\\n ${captions.landed.length} step caption${captions.landed.length === 1 ? '' : 's'} anchored to their steps` +\n (captions.skipped.length\n ? `\\n not landed: ${captions.skipped.join('; ')}`\n : '') +\n (captions.held.length ? `\\n ${captions.held.join('\\n ')}` : '') +\n (captions.uncaptioned.length\n ? `\\n no step in ${captions.uncaptioned.length === 1 && captions.uncaptioned[0] === '' ? 'this take' : captions.uncaptioned.map((m) => (m ? `media ${m}` : 'the primary')).join(', ')} carries a caption`\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 (s.motion.held.length ? `\\n ${s.motion.held.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,\n 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 ...(captions ? { captions } : {}),\n ...(perBeat ? { perBeat } : {}),\n },\n `${s.reuse ? 'Reused' : s.fresh ? 'Planned' : 'Refreshed'} ${join(dir, 'doc.json')}: ${zoomAuto} auto + ${zoomManual} manual zoom spans${s.cursorKept ? '' : ' (cursor track dropped)'}${layoutLines}${motionLines}${reuseLines}${captionLines}${marksLine ? `\\n ${marksLine}` : ''}${perBeat ? `\\n ${perBeatLine(perBeat)}` : ''}`,\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 const strict = flags.strict === 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 for (const z of result.skippedZooms ?? [])\n r.warn(\n `zoom ${z.id}${z.media ? ` (media ${z.media})` : ''} has no apex to still: ${z.reason}`,\n )\n const unrendered = result.frames.filter((f) => f.rendered === false)\n for (const f of unrendered) r.warn(unrenderedZoomLine(f))\n const zoomTag = (f: (typeof result.frames)[number]) =>\n `${f.zoomId ? ` ${f.zoomId}` : ''}${f.media ? ` on ${f.media}` : ''}${f.rendered === false ? ', DID NOT RENDER' : ''}`\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 ...(result.skippedZooms ? { skippedZooms: result.skippedZooms } : {}),\n ...(atZooms ? { unrenderedZooms: unrendered.length } : {}),\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${zoomTag(f)}]` : f.kind === 'moment' ? ` [${f.momentId}]` : ''} → ${f.file}`).join('\\n ')}`,\n )\n return unrendered.length && strict ? EXIT_USAGE : 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 youtube,x,shorts,github (or all) [--release v2.1] [--out dir] [--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 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 const browser = await launchBrowser()\n try {\n const result = await deliverTake(browser, dir, {\n look: lookPick.look,\n channels,\n outDir: strFlag(flags, 'out'),\n release: strFlag(flags, 'release'),\n range,\n parallel,\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.toFixed(1)}s)`,\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 `\\nUploads 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.\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 await launchDefaultBrowser(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 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 const notes: 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 // Information, never a warning: whose account the footage shows.\n const notices = (take.meta.notices ?? []).map(\n (n) => `the recording shows ${noticeLine(n)}`,\n )\n if (notices.length) notices.push(noticeAdvice(take.meta.notices ?? []))\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 notes.push(...(lint.notes ?? []).map((n) => `doc.json: ${n}`))\n const probe = mediaProbeLints(\n await probeMediaUrls(collectDocMediaUrls(take.doc)),\n )\n problems.push(...probe.problems)\n warnings.push(...probe.warnings)\n // A sound the document names in the take must be there: a render that\n // cannot read it plays the film without it, and says so only in a log.\n for (const ref of docAudioRefs(take.doc)) {\n const rel = takeRelativeFile(ref.key)\n const found = localFile(rel, target)\n if (!('refused' in found)) continue\n problems.push(\n existsSync(resolve(target, rel))\n ? `doc.json: ${ref.where}: ${ref.key} ${found.refused}`\n : `doc.json: ${ref.where}: ${ref.key} is not a file in the take, so a render plays the film without it (put the file there, or fix the key)`,\n )\n }\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 = groundCheckTimes(doc)\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 {\n valid: false,\n target,\n problems,\n warnings,\n ...(notes.length ? { notes } : {}),\n ...(notices.length ? { notices } : {}),\n },\n `${target}:\\n ${problems.join('\\n ')}${warnings.length ? `\\n warnings:\\n ${warnings.join('\\n ')}` : ''}${notes.length ? `\\n notes:\\n ${notes.join('\\n ')}` : ''}${noticeLines(notices)}`,\n )\n return EXIT_ERROR\n }\n const noteLines = notes.length ? `\\n notes:\\n ${notes.join('\\n ')}` : ''\n r.done(\n {\n valid: true,\n target,\n warnings,\n ...(notes.length ? { notes } : {}),\n ...(notices.length ? { notices } : {}),\n },\n `${target}: take is complete and renderable${warnings.length ? `\\n warnings:\\n ${warnings.join('\\n ')}` : ''}${noteLines}${noticeLines(notices)}`,\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|--prompt|--folder|--override|--yes|--key|--api|--bake|--claimable [--share]]',\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 if (flags.claimable === true) {\n // A claimable take creates a NEW vos and uploads nothing: the flags\n // that iterate or file one have nothing to act on.\n const iterating = ['vos', 'folder', 'override', 'base'].filter((name) =>\n hasFlag(flags, name),\n )\n if (iterating.length)\n throw new UsageError(\n `--claimable creates a NEW claimable vos; ${iterating.map((f) => `--${f}`).join(', ')} ${iterating.length > 1 ? 'apply' : 'applies'} to a keyed push`,\n )\n const claim = await pushTakeClaimable(\n resolve(dir),\n {\n api: strFlag(flags, 'api'),\n origin: strFlag(flags, 'origin'),\n title: strFlag(flags, 'title'),\n prompt: strFlag(flags, 'prompt'),\n share: flags.share === true,\n bake: flags.bake === true,\n },\n r,\n )\n r.done(\n { ...claim },\n `Claimable push created (${claim.title})\\n` +\n ` claim: ${claim.claimUrl}\\n` +\n ` expires: ${claim.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.`,\n )\n return 0\n }\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 prompt: strFlag(flags, 'prompt'),\n bake: flags.bake === true,\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 // A new vos shows the prompt that made it by default: say how, when none\n // was given, because an agent acts on what a push prints.\n const prompt = strFlag(flags, 'prompt')\n const hint =\n result.versionNumber === 1 && !prompt ? promptHint(dir, result.vosId) : null\n r.done(\n {\n ...result,\n ...(hint ? { promptHint: hint } : {}),\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 (hint\n ? `\\n prompt: none shown; show the one that made it: ${hint}`\n : '') +\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>`). 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 '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 // A claimable take push is cmdPush's to judge (a remix of a fetched\n // public take, which uploads nothing), never refused here.\n const target = rest.find((a) => !a.startsWith('-'))\n if (target && isTakeDir(target)) return await cmdPush(rest)\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 case 'assets':\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 case 'check-video':\n return await cmdCheckVideo(rest)\n case 'join':\n return await cmdJoin(rest)\n case 'info':\n return await cmdTakeInfo(rest)\n case 'score':\n return await cmdScore(rest)\n case 'audio':\n return await cmdAudio(rest)\n case 'look':\n return await cmdLook(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 (\n e instanceof SetupError ||\n e instanceof SetupEnvError ||\n e instanceof RecordRefusedError ||\n e instanceof PlatformBehindError ||\n e instanceof PushRefusedError ||\n e instanceof PasteFileRefusal\n ) {\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 * A session check's exit: 0 signed in, 4 not signed in, and a URL that\n * cannot tell is a warning (0), or 4 under --strict. No verdict at all (no\n * cookies) is `none`.\n */\nfunction verdictExit(\n v: SessionVerdict | null,\n strict: boolean,\n none: number,\n): number {\n if (!v) return none\n if (v.state === 'signed-in') return EXIT_OK\n if (v.state === 'not-signed-in') return EXIT_WALL\n return strict ? EXIT_WALL : EXIT_OK\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(\n argv,\n new Set([...BOOLEAN_FLAGS, 'headed']),\n )\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>] | exec <name> <script.mjs> [--url <url>] [--headed] [--viewport WxH] | 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 const opened = await openSession(name!, url.href, { log: r.log })\n const summary = await summarizeSession(name!)\n // Cookies prove nothing (analytics land on a stranger's visit too):\n // the session passed only if the page it was opened on opens as the\n // person, the same check `vos session check --url` runs.\n const verdict = summary.origins.length\n ? await sessionVerdict(name!, url.href)\n : null\n const signedIn = verdict?.state === 'signed-in'\n const again = `Try again: vos session open ${url.href} --name ${name}, sign in, and close the window once the app shows you signed in`\n r.done(\n {\n name: summary.name,\n finish: opened.finish,\n signedIn,\n ...(verdict ? { verdict } : {}),\n origins: summary.origins,\n newestExpires: summary.newestExpires,\n sessionOnly: summary.sessionOnly,\n },\n verdict\n ? `${verdictLine(verdict, url.href, name!)}. ${summaryLine(summary)}${signedIn ? `\\n Record on it: vos record --actions actions.json --out take --session ${name} --strict` : verdict.state === 'not-signed-in' ? `\\n ${again}` : ''}`\n : `${summaryLine(summary)}\\n ${opened.finish === 'quit' ? `Chrome exited${opened.code ? ` (code ${opened.code})` : ''} before anything was saved. If you did not quit it (⌘Q), it exited on its own: the likely cause is a HOME with no login keychain to keep the cookies' key in (a sandbox, a fresh user, a CI runner), or a profile another Chrome already holds. ` : ''}Nothing was saved. ${again}`,\n )\n return verdictExit(verdict, flags.strict === true, 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 sessionVerdict(arg, url)\n r.done(\n {\n name: arg,\n ok: verdict.state === 'signed-in',\n verdict,\n origins: summary.origins,\n newestExpires: summary.newestExpires,\n },\n `session \"${arg}\": ${verdictLine(verdict, url, arg)}${verdict.state === 'not-signed-in' ? `. It expired, the sign-in never landed, or the profile was opened by a browser that cannot read its cookies (a script launching it itself signs it out; run scripts with vos session exec). Sign in again: vos session open ${url} --name ${arg}` : `. ${summaryLine(summary)}`}`,\n )\n return verdictExit(verdict, flags.strict === true, EXIT_WALL)\n }\n case 'exec': {\n const scriptPath = positionals[2]\n if (!arg || !scriptPath) 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 url = strFlag(flags, 'url')\n if (url && !/^https?:\\/\\//.test(url))\n throw new UsageError('--url wants an http(s) URL')\n const viewport = strFlag(flags, 'viewport')\n const size = viewport ? /^(\\d+)x(\\d+)$/.exec(viewport) : null\n if (viewport && !size)\n throw new UsageError('--viewport wants WxH, e.g. 1280x720')\n let script: ExecScript\n try {\n script = await loadExecScript(scriptPath)\n } catch (e) {\n if (e instanceof ExecScriptError) throw new UsageError(e.message)\n throw new UsageError(\n `${scriptPath} could not be loaded: ${e instanceof Error ? e.message.split('\\n')[0] : String(e)}`,\n )\n }\n let result: unknown\n try {\n result = await execInProfile(sessionDir(arg), script, {\n name: arg,\n ...(url ? { url } : {}),\n headless: flags.headed !== true,\n ...(size ? { viewport: { width: +size[1], height: +size[2] } } : {}),\n })\n } catch (e) {\n r.done(\n {\n name: arg,\n ok: false,\n error: e instanceof Error ? e.message.split('\\n')[0] : String(e),\n },\n `the script failed in session \"${arg}\": ${e instanceof Error ? e.message.split('\\n')[0] : String(e)} (the session was closed cleanly)`,\n )\n return EXIT_ERROR\n }\n r.done(\n { name: arg, ok: true, ...(result !== undefined ? { result } : {}) },\n result === undefined\n ? `ran ${scriptPath} in session \"${arg}\"`\n : typeof result === 'string'\n ? result\n : JSON.stringify(result, null, 2),\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 /**\n * Something the person must hear about. Under --json it is a `warning`\n * event, because a log line is silent there and an agent driving the CLI\n * reads only events: a dropped file said only on stderr was never said.\n */\n warn: (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 warn: (msg) => {\n if (json) {\n process.stdout.write(\n `${JSON.stringify({ event: 'warning', message: msg })}\\n`,\n )\n } else process.stderr.write(`warning ${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 */\nimport type { ActionsFile } from '@vosjs/render-core/record'\n\nexport { validateActions } from '@vosjs/render-core/record'\nexport type { ActionStep, ActionsFile } from '@vosjs/render-core/record'\n\n/**\n * A `js` check that cannot parse, said before a browser opens: the\n * structural check is host-free (a fleet isolate compiles no code), so the\n * parse is the CLI's. The expression is compiled, never run, as the body\n * the recorder evaluates it in (an async function, so `await` reads).\n */\nexport function jsSyntaxProblems(\n actions: Pick<ActionsFile, 'steps'>,\n): string[] {\n const out: string[] = []\n const AsyncFunction = Object.getPrototypeOf(async function () {})\n .constructor as new (body: string) => unknown\n actions.steps.forEach((s, i) => {\n const js =\n s.do === 'expect' ? s.js : s.do === 'await' ? s.until.js : undefined\n if (typeof js !== 'string') return\n try {\n new AsyncFunction(`return await (${js}\\n)`)\n } catch (e) {\n out.push(\n `steps[${i}]: ${s.do === 'await' ? 'await until.js' : 'expect js'} does not parse as an expression (${e instanceof Error ? e.message : String(e)})`,\n )\n }\n })\n return out\n}\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 NORMALIZE_MAX_LUFS,\n NORMALIZE_MIN_LUFS,\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 formatElapsed,\n hasElapsed,\n outputEnd,\n layerStart,\n resolveAnchor,\n resolveOverlayAnchors,\n pinBox,\n pinCandidates,\n pinRectOnScreen,\n pinReferent,\n marksEmphasis,\n migrateTextClip,\n plainText,\n resolveOverlayStyle,\n snapRunWeight,\n RUN_STYLE_KEYS,\n ratedSegments,\n replayedSeconds,\n cameraSpanExtents,\n spanOutputExtents,\n clipGain,\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 { AudioClip, RichText, TextOverlayClip } from '@vosjs/studio-core'\nimport type {\n CardLayout,\n ExportResolution,\n ProjectDoc,\n StudioDoc,\n OverlayAnchor,\n OverlayClip,\n OverlayPin,\n ReplayedSpan,\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' || Array.isArray(o.text)\n ? plainText(o.text as RichText)\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 /** What the document does that a reader may not expect, said once. Absent when there is nothing to say. */\n notes?: 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/**\n * What an HTML layer's own face may be named by, or null when it is fine:\n * a URL, a hosted file (`/api/assets/<id>/file`), or a `.woff2` beside the\n * document, which `vos push` uploads and a local render serves. The page\n * embeds every face as woff2, so another format would be drawn in a\n * fallback face without a word; and a path stays inside the document's\n * directory, like every file a program names.\n */\nexport function htmlFontUrlProblem(url: string): string | null {\n // A face is fetched by the page and inlined, like the images a layer\n // names, so it is held to the same host: the hosted catalog, or a file\n // on vos.so. Any other host is refused in words.\n if (/^https:\\/\\/assets\\.vos\\.so\\//.test(url)) return null\n if (/^\\/api\\/assets\\/[^/]+\\/file$/.test(url)) return null\n if (/^https?:\\/\\//i.test(url)) {\n return `names ${url}: a face is fetched from https://assets.vos.so (the host a layer's images are held to), a hosted file (/api/assets/<id>/file) or a .woff2 beside the document, never another host`\n }\n if (/^(data:|blob:)/.test(url) || url.startsWith('/')) {\n return `must be an https://assets.vos.so URL, a hosted file (/api/assets/<id>/file) or a .woff2 beside the document (got ${url})`\n }\n if (url.split(/[\\\\/]/).includes('..')) {\n return `names ${url}, outside the document's directory: copy the font beside doc.json`\n }\n if (!/\\.woff2$/i.test(url)) {\n return `names ${url}: an HTML layer embeds its faces as woff2, so convert it (for example: pyftsubset or woff2_compress) and name the .woff2`\n }\n return null\n}\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\n/**\n * A loudness target and the measurement it is computed from. The target\n * is the author's; the measurement is tooling's, so a missing or stale one\n * is a warning with the verb that writes it: the clip still plays, at its\n * gain alone.\n */\nfunction lintLoudness(\n a: Json,\n name: string,\n problems: string[],\n warnings: string[],\n): void {\n if (a.normalize !== undefined) {\n if (\n !isNum(a.normalize) ||\n a.normalize < NORMALIZE_MIN_LUFS ||\n a.normalize > NORMALIZE_MAX_LUFS\n )\n problems.push(\n `${name}: normalize is a target loudness in LUFS, ${NORMALIZE_MIN_LUFS}..${NORMALIZE_MAX_LUFS} (e.g. -16; got ${String(a.normalize)})`,\n )\n }\n const l = a.loudness\n if (l !== undefined) {\n if (\n !isObj(l) ||\n !isNum(l.lufs) ||\n (l.peakDb !== null && !isNum(l.peakDb)) ||\n typeof l.at !== 'string' ||\n typeof l.src !== 'string'\n ) {\n problems.push(\n `${name}: loudness is a measurement { lufs, peakDb, at, src } written by vos audio measure, never by hand; delete it and measure again`,\n )\n return\n }\n }\n if (!isNum(a.normalize)) return\n const g = clipGain(a as unknown as AudioClip)\n if (g.basis === 'unmeasured' || g.basis === 'stale')\n warnings.push(\n `${name}: normalize ${a.normalize} is ignored until the clip is measured${g.basis === 'stale' ? ` (its loudness was measured for ${String((l as Json).src)}, not ${String(a.key)})` : ''}, so it plays at its gain alone; measure it: vos audio measure <take>`,\n )\n else if (g.capped === 'peak')\n warnings.push(\n `${name}: normalize ${a.normalize} asks for gain ${g.asked?.toFixed(2)}, held at ${g.gain.toFixed(2)} so the file's peak stays under -1 dBFS; it plays ${(20 * Math.log10((g.asked ?? g.gain) / g.gain)).toFixed(1)} dB under its target`,\n )\n else if (g.capped === 'lift')\n warnings.push(\n `${name}: normalize ${a.normalize} asks for more than +24 dB, the most a target lifts; it plays under its target`,\n )\n}\n\nfunction checkSpanList(\n list: Json[],\n label: string,\n duration: number,\n problems: string[],\n opts: { overlap?: boolean } = {},\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 // Footage clips may play the same seconds more than once (a cold open,\n // a replay); every other span list is one span per second.\n if (opts.overlap) return\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 const notes: 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 = (\n list: Json[],\n label: string,\n opts: { overlap?: boolean } = {},\n ): 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 opts,\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 // The layers where they play: an anchored one at its step.\n const end = outputEnd(\n resolveOverlayAnchors(doc as unknown as ProjectDoc, rated),\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 // --- cursor-off ranges: OUTPUT seconds, an absent out runs to the end;\n // overlapping ranges read as their union, so overlap is no finding ---\n const cursorStyle = isObj(doc.cursor) ? doc.cursor : {}\n if (recording && cursorStyle.off !== undefined) {\n const off = cursorStyle.off\n if (!Array.isArray(off)) {\n problems.push(\n 'cursor.off must be an array of { in, out?, from? } ranges (OUTPUT seconds)',\n )\n } else {\n let end: number | null = null\n const filmEnd = (): number => {\n if (end === null) {\n const rated = ratedSegments(doc as unknown as ProjectDoc)\n end = outputEnd(\n resolveOverlayAnchors(doc as unknown as ProjectDoc, rated),\n rated.reduce((a, s) => a + (s.out - s.in) / (s.rate ?? 1), 0),\n )\n }\n return end\n }\n for (const [i, raw] of (off as unknown[]).entries()) {\n const name = `cursor.off[${i}]`\n if (!isObj(raw)) {\n problems.push(\n `${name} must be an object { in, out?, from? } (OUTPUT seconds)`,\n )\n continue\n }\n for (const k of Object.keys(raw))\n if (k !== 'in' && k !== 'out' && k !== 'from')\n problems.push(`${name}.${k}: not a range field (in, out, from)`)\n lintFrom(name, raw.from, problems)\n if (!isNum(raw.in) || raw.in < 0) {\n problems.push(\n `${name}.in=${String(raw.in)} must be a number ≥ 0 (OUTPUT seconds)`,\n )\n continue\n }\n if (raw.out !== undefined && (!isNum(raw.out) || raw.out <= raw.in)) {\n problems.push(\n `${name}.out=${String(raw.out)} must be a number past in (${raw.in}s); leave it out to hide the cursor to the end of the film`,\n )\n continue\n }\n if (raw.in > filmEnd() + 1e-6)\n warnings.push(\n `${name} starts at ${raw.in}s, past the film's end (${filmEnd().toFixed(2)}s): it hides nothing`,\n )\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', { overlap: true })\n // A segment that plays seconds an earlier one already played is a\n // replay: said once, because every source-anchored span over those\n // seconds (a zoom, a tilt, a click, a freeze, a speed span) plays in\n // each occurrence.\n {\n // Only the seconds a segment plays AGAIN: a cold open followed by\n // the trimmed recording replays the cold open's seconds once, in the\n // one segment that holds them, never every trim after it.\n const index: number[] = []\n const pieces: { in: number; out: number; media?: string }[] = []\n for (const [i, seg] of entries(doc.segments).entries()) {\n if (!isNum(seg.in) || !isNum(seg.out)) continue\n index.push(i)\n pieces.push({\n in: seg.in,\n out: seg.out,\n ...(typeof seg.media === 'string' ? { media: seg.media } : {}),\n })\n }\n const bySegment = new Map<number, ReplayedSpan[]>()\n for (const r of replayedSeconds(pieces)) {\n const list = bySegment.get(r.piece) ?? []\n list.push(r)\n bySegment.set(r.piece, list)\n }\n for (const [p, spans] of bySegment) {\n const m = spans[0].media\n const which = spans\n .map((r) => `${r.in.toFixed(2)}–${r.out.toFixed(2)}s`)\n .join(', ')\n const segs = entries(doc.segments)\n const rests = segs[index[p]]?.camera === 'rest'\n // The earlier passes over the same seconds that rest the camera: a\n // cold open at rest, replayed by the trimmed recording after it.\n const restedBefore = pieces\n .map((q, k) => ({ q, k }))\n .filter(\n ({ q, k }) =>\n k < p &&\n (q.media ?? '') === m &&\n segs[index[k]]?.camera === 'rest' &&\n spans.some((r) => Math.min(q.out, r.out) > Math.max(q.in, r.in)),\n )\n .map(({ k }) => `segments[${index[k]}]`)\n const what = `segments[${index[p]}] replays ${which} of ${m ? `media \"${m}\"` : 'the recording'}`\n notes.push(\n rests\n ? `${what} with its camera at rest: clicks, freezes and speed spans over those seconds play again, zooms, tilts and cam moves do not`\n : restedBefore.length\n ? `${what}, which ${restedBefore.join(' and ')} played with the camera at rest: clicks, freezes and speed spans over those seconds play in every occurrence, zooms, tilts and cam moves only in segments[${index[p]}]`\n : `${what}: zooms, tilts, clicks, freezes and speed spans over those seconds play in every occurrence`,\n )\n }\n }\n // A clip may keep the camera at rest through its pass, and a camera\n // span that plays only in such passes moves nothing.\n const segList = entries(doc.segments)\n segList.forEach((seg, i) => {\n if (seg.camera !== undefined && seg.camera !== 'rest')\n problems.push(\n `segments[${i}].camera must be \"rest\" (the camera rests through this clip's pass); absent = the camera plays here`,\n )\n })\n if (segList.some((s) => s.camera === 'rest')) {\n const rated = ratedSegments(doc as unknown as ProjectDoc)\n for (const [label, list] of [\n ['zoom', zoom],\n ['tilt', entries(doc.tilt)],\n ['camMotion', entries(doc.camMotion)],\n ] as const) {\n for (const s of list) {\n if (!isNum(s.in) || !isNum(s.out)) continue\n const media = typeof s.media === 'string' ? s.media : undefined\n if (\n spanOutputExtents(rated, s.in, s.out, media).length &&\n !cameraSpanExtents(rated, s.in, s.out, media).length\n )\n warnings.push(\n `${spanName(label, s)}: it plays only in segments whose camera rests (segments[].camera: \"rest\"), so it never moves the camera`,\n )\n }\n }\n }\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(\n `${name}: gain must be 0..1 (to lift a quiet file, give it a loudness target: normalize, in LUFS)`,\n )\n }\n lintLoudness(a, name, problems, warnings)\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 // The rated pieces an anchored layer's step is mapped through, once.\n let anchorPieces: ReturnType<typeof ratedSegments> | null = null\n if (recording) {\n try {\n anchorPieces = ratedSegments(doc as unknown as ProjectDoc)\n } catch {\n anchorPieces = null\n }\n }\n // Captions as they play (an anchor resolved), for the overlap check.\n const captionTimes: { name: string; start: number; end: number }[] = []\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 const playsAt = checkOverlayAnchor(\n o,\n name,\n docIn,\n recording,\n anchorPieces,\n problems,\n warnings,\n notes,\n )\n if (\n o.kind === 'text' &&\n o.preset === 'caption' &&\n o.pin === undefined &&\n isNum(playsAt) &&\n isNum(o.duration) &&\n o.duration > 0\n ) {\n const label = typeof o.id === 'string' ? `${name} (${o.id})` : name\n captionTimes.push({\n name: label,\n start: playsAt,\n end: playsAt + o.duration,\n })\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 // An anchored layer is placed by its step; its start, when it has one,\n // is only the fallback (checkOverlayAnchor refuses one that resolves\n // nowhere and has none).\n if (o.anchor === undefined || o.start !== undefined) {\n if (!isNum(o.start) || o.start < 0)\n problems.push(`${name}.start must be ≥ 0 (OUTPUT seconds)`)\n }\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(playsAt) &&\n isNum(o.duration)\n ) {\n const over = playsAt + 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 playsAt >= footageEnd\n ? `${name} starts at ${playsAt.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 // The words: a string, or runs (a piece of text and how it departs\n // from the layer's style). An unknown run field is an ERROR that\n // names it: a typo there paints nothing and says nothing.\n if (Array.isArray(o.text)) {\n const HINTS: Record<string, string> = {\n bold: 'weight: 700',\n fontWeight: 'weight',\n strikethrough: 'strike: true',\n background: 'highlight',\n colour: 'color',\n }\n o.text.forEach((run: unknown, ri: number) => {\n const at = `${name}.text[${ri}]`\n if (!run || typeof run !== 'object' || Array.isArray(run)) {\n problems.push(\n `${at} must be a run: { text, weight?, italic?, color?, underline?, strike?, highlight? }`,\n )\n return\n }\n const r = run as Record<string, unknown>\n if (typeof r.text !== 'string')\n problems.push(`${at}.text must be a string`)\n else if (!r.text)\n warnings.push(`${at} has no text and paints nothing; drop it`)\n for (const k of Object.keys(r)) {\n if (\n k === 'text' ||\n (RUN_STYLE_KEYS as readonly string[]).includes(k)\n )\n continue\n problems.push(\n `${at}.${k} is not a run field (${RUN_STYLE_KEYS.join(', ')})${HINTS[k] ? `: write ${HINTS[k]}` : ''}`,\n )\n }\n if (\n r.weight !== undefined &&\n (!isNum(r.weight) || r.weight < 100 || r.weight > 900)\n )\n problems.push(`${at}.weight must be 100..900`)\n for (const k of ['italic', 'underline', 'strike'] as const) {\n if (r[k] !== undefined && typeof r[k] !== 'boolean')\n problems.push(`${at}.${k} must be true or false`)\n }\n for (const k of ['color', 'highlight'] as const) {\n if (r[k] !== undefined && typeof r[k] !== 'string')\n problems.push(\n isObj(r[k]) && '$data' in r[k]\n ? `${at}.${k} must be a CSS colour: a layer has no data to read, { \"$data\" } binds a program's own text element`\n : `${at}.${k} must be a CSS colour`,\n )\n }\n // A weight the family cannot offer paints as the layer's own.\n if (isNum(r.weight) && r.weight >= 100 && r.weight <= 900) {\n const layer = o as unknown as TextOverlayClip\n const own = resolveOverlayStyle({ ...layer, text: '' }).weight\n if (r.weight !== own && snapRunWeight(layer, r.weight) === own)\n warnings.push(\n `${at}.weight ${r.weight} paints no differently: the layer's family hosts no weight nearer to it than the layer's own ${own}`,\n )\n }\n })\n } else if (typeof o.text !== 'string') {\n problems.push(\n `${name}.text must be a string, or a list of runs ([{ text, weight?, italic?, color?, underline?, strike?, highlight? }])`,\n )\n }\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` and its *markers* are RETIRED. A layer that still carries\n // the field is read into runs on its way to a render, so it paints as\n // it did; say what to write instead, in full. Without the field,\n // asterisks are text as typed, and a pair of them is usually someone\n // reaching for bold.\n if (o.emphasis !== undefined && typeof o.text === 'string') {\n const runs = migrateTextClip(o as unknown as TextOverlayClip).text\n warnings.push(\n `${name}.emphasis is retired (styled words are runs now, with no markers in the text). It is still read, but write it as: \"text\": ${JSON.stringify(runs)} and drop \"emphasis\"`,\n )\n } else if (typeof o.text === 'string' && marksEmphasis(o.text)) {\n const runs = migrateTextClip({\n ...(o as unknown as TextOverlayClip),\n emphasis: {},\n } as unknown as TextOverlayClip).text\n warnings.push(\n `${name}.text has words between asterisks, which show as typed. To set them bold write runs: \"text\": ${JSON.stringify(runs)}`,\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 !f.url\n ) {\n problems.push(\n `${name}.fonts[${fi}] must be { family, url, weight?, style? }: a face the catalog does not host. A hosted family needs no entry; name it in the CSS`,\n )\n return\n }\n const problem = htmlFontUrlProblem(f.url)\n if (problem) problems.push(`${name}.fonts[${fi}].url ${problem}`)\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 // Two captions on screen at once read as one jumble in the margin they\n // share: said by name, once the anchors have placed them.\n captionTimes.sort((a, b) => a.start - b.start || a.end - b.end)\n for (let i = 0; i < captionTimes.length; i++) {\n for (let j = i + 1; j < captionTimes.length; j++) {\n const a = captionTimes[i]\n const b = captionTimes[j]\n if (b.start >= a.end - EPS) break\n warnings.push(\n `${a.name} (${a.start.toFixed(2)}–${a.end.toFixed(2)}s) and ${b.name} (${b.start.toFixed(2)}–${b.end.toFixed(2)}s) are captions on screen at the same time; shorten the first, move one (an anchor's offset), or drop one`,\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, ...(notes.length ? { notes } : {}) }\n}\n\n/**\n * Where a layer anchored to a step of one media starts over ANOTHER\n * media's footage: the segment it lands in and where its own media's\n * footage ended just before, or null when it starts over its own media\n * (or past the footage, an ending on the ground). A step-anchored caption\n * lands after its gesture; trim the footage after that step and the\n * caption runs into the next scene with nothing saying so.\n */\nfunction otherSceneAt(\n doc: ProjectDoc,\n start: number,\n anchorMedia: unknown,\n): { index: number; media: string; ownEnd: number | null } | null {\n const segs = Array.isArray(doc.segments) ? doc.segments : []\n if (!segs.length) return null\n const own = typeof anchorMedia === 'string' ? anchorMedia : ''\n const mediaOf = (i: number): string =>\n (segs[i] as { media?: unknown })?.media === undefined\n ? ''\n : String((segs[i] as { media?: unknown }).media)\n const ext = segmentOutputExtents(doc)\n const EPS = 1e-3\n const at = (i: number) =>\n start >= ext[i].start - EPS && start < ext[i].end - EPS\n if (ext.some((_, i) => mediaOf(i) === own && at(i))) return null\n const index = ext.findIndex((_, i) => mediaOf(i) !== own && at(i))\n if (index < 0) return null\n const before = ext\n .filter((e, i) => mediaOf(i) === own && e.end <= start + EPS)\n .map((e) => e.end)\n return {\n index,\n media: mediaOf(index),\n ownEnd: before.length ? Math.max(...before) : null,\n }\n}\n\n/**\n * A layer's `anchor`: when it starts, as a recorder step. Checked for its\n * shape, then resolved against the steps and the cut the way the lowering\n * resolves it; one that cannot resolve plays at its `start`, which is said.\n * Answers the OUTPUT second the layer plays at (its `start` when it has no\n * anchor or the anchor cannot resolve), null when neither is a number.\n */\nfunction checkOverlayAnchor(\n o: Json,\n name: string,\n docIn: StudioDoc,\n recording: boolean,\n pieces: ReturnType<typeof ratedSegments> | null,\n problems: string[],\n warnings: string[],\n notes: string[],\n): number | null {\n const fallback = isNum(o.start) ? o.start : null\n const words = o.kind === 'text' ? (o.text as RichText | undefined) : undefined\n const elapsed = o.kind === 'text' && hasElapsed(words)\n if (o.anchor === undefined) {\n if (elapsed)\n warnings.push(\n `${name}: its words carry {elapsed}, which fills only from an anchored step's off-camera wait; anchor it (anchor: { step }) or write the duration`,\n )\n return fallback\n }\n const a = o.anchor\n if (!isObj(a)) {\n problems.push(`${name}.anchor must be { step, media?, at?, offset? }`)\n return fallback\n }\n let shaped = true\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 its index (integer ≥ 0)`,\n )\n shaped = false\n }\n if (a.media !== undefined && typeof a.media !== 'string') {\n problems.push(`${name}.anchor.media must be a media[].id (string)`)\n shaped = false\n }\n if (a.at !== undefined && a.at !== 'start' && a.at !== 'end') {\n problems.push(`${name}.anchor.at must be \"start\" or \"end\"`)\n shaped = false\n }\n if (a.offset !== undefined && !isNum(a.offset)) {\n problems.push(`${name}.anchor.offset must be a number (OUTPUT seconds)`)\n shaped = false\n }\n if (!shaped) return fallback\n if (!recording || !pieces) {\n if (fallback === null)\n problems.push(\n recording\n ? `${name}.anchor: the cut could not be read to place step ${JSON.stringify(a.step)}, and the layer has no start to fall back to`\n : `${name}.anchor: names step ${JSON.stringify(a.step)}, but a program document has no recorder steps, and the layer has no start to fall back to; give it a start`,\n )\n return fallback\n }\n const r = resolveAnchor(\n docIn as ProjectDoc,\n a as unknown as OverlayAnchor,\n pieces,\n )\n const step = `step ${JSON.stringify(a.step)}${typeof a.media === 'string' ? ` of media ${a.media}` : ''}`\n const at = fallback === null ? 'nowhere' : `${fallback.toFixed(2)}s`\n if (r.start === null) {\n const why =\n r.miss === 'media'\n ? `media \"${String(a.media)}\" is not one of media[].id`\n : r.miss === 'step'\n ? `${step} is not in its meta.steps`\n : r.miss === 'skipped'\n ? `${step} was skipped by the recorder`\n : `the cut leaves ${step} out`\n if (fallback === null)\n problems.push(\n `${name}.anchor: ${why}, and the layer has no start to fall back to, so it would play nowhere; re-anchor it, keep the footage that step plays in, or give it a start`,\n )\n else\n warnings.push(\n `${name}.anchor: ${why}, so it plays at its fallback start (${at}); re-anchor it, or keep the footage that step plays in`,\n )\n }\n if (r.start !== null) {\n const over = otherSceneAt(docIn as ProjectDoc, r.start, a.media)\n if (over)\n warnings.push(\n `${name}${typeof o.id === 'string' ? ` (${o.id})` : ''}: anchored to ${step}, it starts at ${r.start.toFixed(2)}s, ${over.ownEnd === null ? 'where' : `after that media's footage there ends (${over.ownEnd.toFixed(2)}s), where`} segments[${over.index}] plays ${over.media ? `media \"${over.media}\"` : 'the recording'}: it speaks over another scene. Anchor it to the step's start (anchor.at: \"start\"), lower anchor.offset, or keep more of the footage it is about`,\n )\n }\n if (elapsed && r.elapsedFrom && r.elapsedMs !== undefined)\n notes.push(\n `${name}: {elapsed} reads the off-camera wait of step ${JSON.stringify(r.elapsedFrom.id ?? r.elapsedFrom.step)} (${formatElapsed(r.elapsedMs)}), the nearest one before ${step}, which waited for nothing itself`,\n )\n if (\n elapsed &&\n r.elapsedMs === undefined &&\n r.miss !== 'media' &&\n r.miss !== 'step'\n )\n warnings.push(\n `${name}: {elapsed} stays as written, because neither ${step} nor any step before it recorded an off-camera wait (no meta.skips entry names one, and none has an offCameraMs)`,\n )\n return r.start ?? fallback\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 // Every media's own evidence: a span's seconds are its media's, and so\n // are the clicks and the capture space they are measured in. A span on\n // a second media judged against the primary's clicks points \"beside\"\n // something that media never showed.\n const evidence = new Map<\n string,\n { w: number; h: number; clicks: DownEvent[]; layout: CardLayout }\n >()\n const others = Array.isArray(doc.media) ? doc.media : []\n for (const [key, src] of [\n ['', doc.source],\n ...others.map((m) => [isObj(m) ? m.id : undefined, m] as const),\n ] as const) {\n if (typeof key !== 'string' || !isObj(src)) continue\n const meta = isObj(src.meta) ? src.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)) continue\n const clicks = clicksWithRects(src)\n if (!clicks.length) continue\n let layout: CardLayout\n try {\n layout = docCardLayout(docIn, key || null)\n } catch {\n continue\n }\n evidence.set(key, { w, h, clicks, layout })\n }\n if (!evidence.size) return\n const layout = docCardLayout(docIn)\n\n for (const z of zoom) {\n const ev = evidence.get(typeof z.media === 'string' ? z.media : '')\n if (!ev) continue\n const { w, h, clicks } = ev\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 ev.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.duration)) return\n // Where the layer PLAYS: an anchored one at its step (its `start` is\n // only the fallback, stale after a trim, or absent), else its start.\n const start = o.anchor\n ? layerStart(o as unknown as OverlayClip, docIn, rated)\n : isNum(o.start)\n ? o.start\n : null\n if (start === null) 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,\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 const presses = [...evidence.entries()].flatMap(([key, ev]) =>\n ev.clicks.map((c) => ({ c, key, ev })),\n )\n for (const { c, key, ev } of presses) {\n const out = spanOutputExtent(rated, c.t, c.t + 0.001, key || undefined)\n if (!out || out.start < start || out.start > start + o.duration)\n continue\n const target = pinRectOnScreen(\n {\n x: c.rect.x / ev.w,\n y: c.rect.y / ev.h,\n w: c.rect.w / ev.w,\n h: c.rect.h / ev.h,\n },\n out.start,\n ev.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 on a cut. 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 — on every media of the take, and renders each apex a second time\n * with the zooms off: a zoom whose frame matches its zoom-off twin did not\n * render, and the still alone would never say so.\n */\nimport { mkdir, readFile, rename, rm, 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 cameraSpanExtents,\n spanOutputExtents,\n} from '@vosjs/studio-core'\nimport { loadTake } from './take'\nimport { startTakeServer, waitForPageDone } from './server'\nimport { renderPageHtml } from './renderAnimation'\nimport {\n applyAndValidate,\n applyDocOverrides,\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, BrowserContext } from 'playwright'\n\nconst VIDEO_TOKEN = '__VOS_CLI_VIDEO__'\n\n/**\n * The supersample factor a still renders at: a small --size (a 440\n * px frame, a 240 px one) renders at two or three times its\n * pixels and downscales once with the 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 variant built in memory). 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 /** A zoom apex: the span it stills. */\n zoomId?: string\n /** A zoom apex on another media of the take: that media's id. */\n media?: string\n /**\n * A zoom apex: whether the zoom shows in the frame, judged against the\n * same output time rendered with the zooms off.\n */\n rendered?: boolean\n /** Mean absolute difference from the zoom-off twin (0..1 of full range). */\n difference?: number\n /** The zoom-off twin's still, written only when the zoom did not render. */\n twin?: string\n}\n\n/** A zoom span with no apex to still, and why. */\nexport interface SkippedZoom {\n id: string\n media?: string\n /** The span's SOURCE extent, seconds of its media. */\n in: number\n out: number\n reason: string\n}\n\nexport interface FramesTakeResult {\n frames: CapturedFrame[]\n width: number\n height: number\n duration: number\n outDir: string\n /** Zoom spans `atZooms` could not still (outside the cut, an unknown media). */\n skippedZooms?: SkippedZoom[]\n}\n\n/** A zoom span's apex: the midpoint of its OUTPUT window. */\nexport interface ZoomApex {\n id: string\n media?: string\n time: number\n start: number\n end: number\n}\n\n/**\n * Every zoom span's apex, on every media of the take: each span's source\n * extent mapped through the rated segments onto the output, the mapping the\n * lowering builds the camera track from. A span of another media is read\n * in that media's seconds; a span the cut keeps nothing of is skipped and\n * said, never stilled at a time it does not play.\n */\nexport function zoomApexes(doc: ProjectDoc): {\n apexes: ZoomApex[]\n skipped: SkippedZoom[]\n} {\n const rated = ratedSegments(doc)\n const media = new Set((doc.media ?? []).map((m) => m.id))\n const apexes: ZoomApex[] = []\n const skipped: SkippedZoom[] = []\n for (const z of doc.zoom) {\n const of = z.media ? { media: z.media } : {}\n if (z.media && !media.has(z.media)) {\n skipped.push({\n id: z.id,\n ...of,\n in: z.in,\n out: z.out,\n reason: `names media \"${z.media}\", which the take does not carry`,\n })\n continue\n }\n const exts = cameraSpanExtents(rated, z.in, z.out, z.media)\n if (!exts.length) {\n skipped.push({\n id: z.id,\n ...of,\n in: z.in,\n out: z.out,\n reason: spanOutputExtents(rated, z.in, z.out, z.media).length\n ? 'every pass of it plays in a segment whose camera rests'\n : 'the cut keeps none of it, so it never plays',\n })\n continue\n }\n // A cut that replays the span's seconds plays its zoom each time the\n // camera plays them: one apex per occurrence, none in a resting pass.\n for (const ext of exts)\n apexes.push({\n id: z.id,\n ...of,\n time: (ext.start + ext.end) / 2,\n start: ext.start,\n end: ext.end,\n })\n }\n return { apexes, skipped }\n}\n\n/**\n * Below this mean absolute difference (0..1 of full range, over a small\n * grayscale of the frame) a zoomed apex is the zoom-off frame: the zoom did\n * not render. Two renders of the same frame agree to well under a level in\n * 255; a zoom of the smallest level the planner proposes moves every edge\n * of the picture and lands far above it.\n */\nexport const ZOOM_UNRENDERED_BELOW = 0.004\n\n/** The long side of the grayscale a frame is compared at, in pixels. */\nconst SIGNATURE_LONG_SIDE = 96\n\n/** Mean absolute difference of two equal-length grayscale signatures, 0..1. */\nexport function signatureDifference(\n a: ArrayLike<number>,\n b: ArrayLike<number>,\n): number {\n if (a.length !== b.length || a.length === 0) return 1\n let sum = 0\n for (let i = 0; i < a.length; i++) sum += Math.abs(a[i] - b[i])\n return sum / a.length / 255\n}\n\n/** The warning a zoom that did not render prints. */\nexport function unrenderedZoomLine(f: CapturedFrame): string {\n return `zoom ${f.zoomId ?? '?'} at ${f.time.toFixed(2)}s did not render (its frame matches the zoom-off frame${f.twin ? `: ${f.twin}` : ''})`\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 /** Shots whose small grayscale is handed back, for a comparison. */\n sigNames: string[]\n sigW: number\n sigH: number\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 // An import spelled as text: a transform that rewrites `import()` in\n // this function (a test runner's) would break it in the page.\n const load = new Function('u', 'return import(u)') as (\n u: string,\n ) => Promise<any>\n const mod = await load(\n URL.createObjectURL(new Blob([code], { type: 'text/javascript' })),\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 // The frame as a small grayscale, for a comparison in node.\n const sigCanvas = document.createElement('canvas')\n sigCanvas.width = opts.sigW\n sigCanvas.height = opts.sigH\n const signature = (): number[] => {\n const g = sigCanvas.getContext('2d', { willReadFrequently: true })!\n g.imageSmoothingEnabled = true\n g.imageSmoothingQuality = 'high'\n g.clearRect(0, 0, opts.sigW, opts.sigH)\n g.drawImage(canvas, 0, 0, opts.sigW, opts.sigH)\n const px = g.getImageData(0, 0, opts.sigW, opts.sigH).data\n const out: number[] = new Array(opts.sigW * opts.sigH)\n for (let p = 0, q = 0; p < px.length; p += 4, q++)\n out[q] = Math.round(\n 0.299 * px[p] + 0.587 * px[p + 1] + 0.114 * px[p + 2],\n )\n return out\n }\n const sigWanted = new Set(opts.sigNames)\n const sigs: Record<string, number[]> = {}\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 if (sigWanted.has(shot.name)) sigs[shot.name] = signature()\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, sigs }\n } catch (e) {\n w.__error = String((e instanceof Error && e.stack) || e)\n }\n}\n\n/** Seek and capture `shots` in one fresh page; the signatures asked for come back. */\nasync function captureShots(\n context: BrowserContext,\n base: string,\n opts: {\n animationCode: string\n videoUrl: string\n width: number\n height: number\n ss: number\n shots: { time: number; name: string }[]\n sigNames: string[]\n },\n): Promise<Record<string, number[]>> {\n const long = Math.max(opts.width, opts.height)\n const side = (n: number) =>\n Math.max(1, Math.round((n / long) * SIGNATURE_LONG_SIDE))\n const page = await context.newPage()\n try {\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(`${base}/render.html`)\n await page.waitForFunction('window.__pageReady__ === true')\n void page\n .evaluate(stillsInPage, {\n animationCode: opts.animationCode,\n token: VIDEO_TOKEN,\n videoUrl: opts.videoUrl,\n W: opts.width,\n H: opts.height,\n ss: opts.ss,\n shots: opts.shots,\n sigNames: opts.sigNames,\n sigW: side(opts.width),\n sigH: side(opts.height),\n })\n .catch(() => {})\n const done = await waitForPageDone(\n page,\n 'stills',\n () => {},\n 120_000 + opts.shots.length * 4_000,\n )\n return (done.sigs as Record<string, number[]> | undefined) ?? {}\n } finally {\n await page.close()\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 zoomId?: string\n media?: string\n }[] = opts.times.map((t) => ({\n time: clamp(t),\n kind: 'time',\n }))\n let skippedZooms: SkippedZoom[] | undefined\n if (opts.atZooms) {\n const { apexes, skipped } = zoomApexes(doc)\n for (const a of apexes)\n shots.push({\n time: clamp(a.time),\n kind: 'zoom',\n zoomId: a.id,\n ...(a.media ? { media: a.media } : {}),\n })\n skippedZooms = skipped\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 && !skippedZooms?.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 stamp = (i: number, t: number) =>\n `${String(i).padStart(2, '0')}-${t.toFixed(2)}s.png`\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'}-${stamp(i, s.time)}`,\n twinName: s.kind === 'zoom' ? `zoomoff-${stamp(i, s.time)}` : undefined,\n }))\n const zoomShots = named.filter((n) => n.kind === 'zoom')\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 const videoUrl = `/${take.paths.recordingName}`\n try {\n const sigs = named.length\n ? await captureShots(context, server.base, {\n animationCode,\n videoUrl,\n width,\n height,\n ss,\n shots: named.map(({ time, name }) => ({ time, name })),\n sigNames: zoomShots.map((n) => n.name),\n })\n : {}\n\n // The zoom-off twin of every apex: the same document with no zoom\n // spans (what `--set zoom=[]` makes), at the same times.\n let twinSigs: Record<string, number[]> = {}\n if (zoomShots.length) {\n const twinDoc = structuredClone(doc)\n applyDocOverrides(twinDoc, { set: ['zoom=[]'] })\n const twinLowered = lowerToComposition(twinDoc)\n twinSigs = await captureShots(context, server.base, {\n animationCode: compileVosConfig(twinLowered.config as never, {\n tweenEngine: 'vos',\n }),\n videoUrl,\n width,\n height,\n ss,\n shots: zoomShots.map((n) => ({ time: n.time, name: n.twinName! })),\n sigNames: zoomShots.map((n) => n.twinName!),\n })\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 const frame: CapturedFrame = {\n file: to,\n time: n.time,\n kind: n.kind,\n ...(n.momentId ? { momentId: n.momentId } : {}),\n ...(n.zoomId ? { zoomId: n.zoomId } : {}),\n ...(n.media ? { media: n.media } : {}),\n }\n if (n.twinName) {\n const a = sigs[n.name]\n const b = twinSigs[n.twinName]\n const twinFrom = join(dir, n.twinName)\n if (a && b) {\n const difference = signatureDifference(a, b)\n frame.rendered = difference >= ZOOM_UNRENDERED_BELOW\n frame.difference = Math.round(difference * 1e5) / 1e5\n // The twin is kept only beside a zoom that did not render: it is\n // the evidence, and every other one would only crowd the folder.\n if (!frame.rendered) {\n const twinTo = join(outDir, n.twinName)\n if (twinFrom !== twinTo) await rename(twinFrom, twinTo)\n frame.twin = twinTo\n }\n }\n if (!frame.twin) await rm(twinFrom, { force: true })\n }\n frames.push(frame)\n }\n return {\n frames,\n width,\n height,\n duration,\n outDir,\n ...(skippedZooms ? { skippedZooms } : {}),\n }\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 ...(result.skippedZooms?.length\n ? { skippedZooms: result.skippedZooms }\n : {}),\n },\n null,\n 2,\n ),\n )\n return index\n}\n","import { createServer } from 'node:http'\nimport { randomBytes } from 'node:crypto'\nimport { existsSync, readFileSync, realpathSync, statSync } from 'node:fs'\nimport { writeFile } from 'node:fs/promises'\nimport { extname, join, resolve, sep } 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 * A `/save` name is a file the CLI's own pages write: a render, a frame,\n * the encoded recording, a digest picture. Never a path, a dotfile, or one\n * of the take's own records, which no page has a reason to replace.\n */\nconst SAVE_NAME = /^[A-Za-z0-9][A-Za-z0-9._-]*$/\nconst SAVE_NEVER = new Set([\n 'doc.json',\n 'actions.json',\n 'vos.json',\n 'meta.json',\n 'cursor.json',\n])\nexport function saveNameOk(name: string): boolean {\n return SAVE_NAME.test(name) && !name.includes('..') && !SAVE_NEVER.has(name)\n}\n\n/**\n * The file a request path names inside the take directory, or null when it\n * names nothing there: the resolved real path must stay under the real\n * root, so an encoded `..` or a symlink out of the directory answers 404.\n */\nexport function fileInRoot(rootDir: string, pathname: string): string | null {\n let decoded: string\n try {\n decoded = decodeURIComponent(pathname)\n } catch {\n return null\n }\n const file = resolve(rootDir, `.${decoded}`)\n if (!existsSync(file) || !statSync(file).isFile()) return null\n const root = realpathSync(rootDir)\n const real = realpathSync(file)\n return real.startsWith(root + sep) ? real : null\n}\n\n/**\n * Who may read a bare path (one without the token prefix): the server's own\n * pages, which fetch as same-origin, and a person at the address bar. A\n * page on any other origin reads only through the tokened base the studio\n * was handed, so a stray page on the machine cannot list the take.\n */\nfunction ownReader(req: { headers: Record<string, unknown> }): boolean {\n const site = req.headers['sec-fetch-site']\n return site === undefined || site === 'same-origin' || site === 'none'\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 // The base the studio is handed carries a per-start token in its path,\n // and a cross-site read must carry it back; the server's own pages keep\n // their bare absolute paths (`/save`, `/recording.webm`).\n const token = randomBytes(16).toString('hex')\n const prefix = `/t/${token}`\n const server = createServer((req, res) => {\n const raw = new URL(req.url ?? '/', 'http://x')\n const tokened =\n raw.pathname === prefix || raw.pathname.startsWith(`${prefix}/`)\n if (!tokened && req.method !== 'OPTIONS' && !ownReader(req)) {\n res.writeHead(404).end()\n return\n }\n const url = tokened\n ? new URL(raw.pathname.slice(prefix.length) || '/', 'http://x')\n : raw\n url.search = raw.search\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'\n // Only the server's own pages write, and only a file name.\n if (tokened || !ownReader(req) || !saveNameOk(name)) {\n res.writeHead(404).end()\n return\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 = fileInRoot(rootDir, url.pathname)\n if (file) {\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 // Loopback only: a take is this machine's, never the LAN's.\n return new Promise((done) =>\n server.listen(0, '127.0.0.1', () => {\n const addr = server.address()\n const port = typeof addr === 'object' && addr ? addr.port : 0\n done({\n base: `http://127.0.0.1:${port}${prefix}`,\n close: () => server.close(),\n })\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 { esmShModules } from '@vosjs/core/addons'\nimport { startTakeServer, waitForPageDone } from './server'\nimport type { RenderChunk } from '@vosjs/render-core'\nimport type { Browser } from 'playwright'\n\n// The engine's pinned dependencies, from esm.sh (the engine's own default\n// source), so this page and the engine's templates can never drift apart.\nconst MODULES = esmShModules()\nconst MEDIABUNNY_URL = MODULES.mediabunny\nconst THREE_URL = MODULES.three\nconst THREE_ADDONS = MODULES.threeAddons\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 // program may draw element text and images over its ground, and without\n // 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.VOS_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 headline\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 CHANGE_GRID,\n CHANGE_LEAD,\n CHANGE_OFFSETS,\n DIGEST_CROP_MAX,\n DIGEST_FULL_MAX,\n DIGEST_VERSION,\n MOTION_DELTA,\n ambientDrift,\n buildDigest,\n changedRegion,\n cropBox,\n frameGeometry,\n momentsFromDoc,\n outputDurationOf,\n pickChange,\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 /** The clicks and typing runs: luma grids at each seed and a few beats after. */\n seeds: { id: string; t: number }[]\n grid: { w: number; h: number }\n offsets: number[]\n lead: 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 // The consequences: at each seed and a few beats after it, the frame\n // as a luma grid, coarse enough that a cursor is one cell. Node finds\n // what changed; the page only looks.\n const g = document.createElement('canvas')\n g.width = opts.grid.w\n g.height = opts.grid.h\n const gctx = g.getContext('2d', { willReadFrequently: true })!\n const gridAt = async (t: number): Promise<number[]> => {\n const el = await getFrame(Math.max(0, Math.min(opts.durationS, t)))\n gctx.drawImage(el, 0, 0, opts.grid.w, opts.grid.h)\n const d = gctx.getImageData(0, 0, opts.grid.w, opts.grid.h).data\n const out = new Array<number>(opts.grid.w * opts.grid.h)\n for (let p = 0; p < out.length; p++) {\n const o = p * 4\n out[p] = (d[o] * 299 + d[o + 1] * 587 + d[o + 2] * 114) / 1000\n }\n return out\n }\n const changes: { id: string; samples: { dt: number; luma: number[] }[] }[] =\n []\n for (const seed of opts.seeds) {\n const samples: { dt: number; luma: number[] }[] = []\n // A beat before the seed: what moves on its own is masked out.\n if (seed.t - opts.lead >= 0)\n samples.push({ dt: -opts.lead, luma: await gridAt(seed.t - opts.lead) })\n samples.push({ dt: 0, luma: await gridAt(seed.t) })\n for (const dt of opts.offsets) {\n if (seed.t + dt > opts.durationS) break\n samples.push({ dt, luma: await gridAt(seed.t + dt) })\n }\n changes.push({ id: seed.id, samples })\n }\n w.__done = {\n ok: true,\n bins,\n width: size.width,\n height: size.height,\n changes,\n }\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, and the frames around every click and typing run,\n // so the digest can say what each did to the page.\n const seeds = momentsFromDoc(doc, plan, {})\n .filter(\n (m) => m.at !== null && (m.kind === 'click' || m.kind === 'typing'),\n )\n .map((m) => ({\n id: m.id,\n t: m.kind === 'click' ? (m.at as number) : m.source.out,\n }))\n void page\n .evaluate(binsInPage, {\n source,\n durationS: durS,\n delta: MOTION_DELTA,\n seeds,\n grid: { ...CHANGE_GRID },\n offsets: [...CHANGE_OFFSETS],\n lead: CHANGE_LEAD,\n })\n .catch(() => {})\n const b = await waitForPageDone(\n page,\n 'digest bins',\n () => {},\n 60_000 + durS * 400 + seeds.length * 2_000,\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 const sampled = (b.changes ?? []) as {\n id: string\n samples: { dt: number; luma: number[] }[]\n }[]\n const changes = seeds.flatMap((seed) => {\n const row = sampled.find((c) => c.id === seed.id)\n const at = row?.samples.find((smp) => smp.dt === 0)\n const earlier = row?.samples.find((smp) => smp.dt < 0)\n const after = row?.samples.filter((smp) => smp.dt > 0) ?? []\n if (!row || !at || !after.length) return []\n const before = { ...CHANGE_GRID, luma: at.luma }\n const rate = earlier\n ? ambientDrift(\n { ...CHANGE_GRID, luma: earlier.luma },\n before,\n -earlier.dt,\n )\n : null\n const w = pickChange(\n { id: seed.id, at: seed.t },\n after.map((smp) => ({\n dt: smp.dt,\n region: changedRegion(\n before,\n { ...CHANGE_GRID, luma: smp.luma },\n MOTION_DELTA,\n 1,\n rate ? { rate, dt: smp.dt } : null,\n ),\n })),\n )\n return w ? [w] : []\n })\n\n moments = momentsFromDoc(doc, plan, {\n bins,\n scenes: sceneChanges(bins),\n transcript,\n changes,\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 video destinations and write the\n * kit manifest. Loops the DESTINATIONS table (studio-core, generated from\n * schema/channel-specs.json): each cut through renderTake at its spec's\n * exact pixels, then VERIFIES every artifact against its spec (px, bytes,\n * duration) and writes kit.json beside the assets.\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. Uploads stay\n * manual — the verb hands the human a kit directory, it never posts to a\n * channel.\n */\nimport { mkdir, writeFile } from 'node:fs/promises'\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 { renderTake } from './renderTake'\nimport { LOOP_DESTINATIONS, destinationMechanics } from './motionPlan'\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 yt: 'youtube',\n gh: 'github',\n shorts: 'shorts-linkedin',\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 /** 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 * The card's presentation, resolved before the run (`resolveLook`): a\n * house look, the maker's BRAND.md, or null for the cut as the doc\n * frames it. Every destination rides it.\n */\n look?: Look | null\n onPhase?: (phase: string) => void\n onProgress?: (fraction: number) => void\n}\n\n/** One produced cut, the kit.json entry shape. */\nexport interface KitAsset {\n channel: string\n asset: string\n /** The destination id (`x-feed-cut`) the entry was rendered for. */\n destination: string\n path: string\n w: number\n h: number\n bytes: number\n seconds: number\n}\n\nexport interface KitManifest {\n release: string | null\n /** The look the 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 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}\" — deliver renders video cuts for: ${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 cuts in, in precedence: `--look none` (the\n * doc's own frame), `--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. The document's camera and bar kind\n * stay. 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: { 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 return set\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\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 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 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 for (const d of destinations) {\n const label = `${d.channel} ${d.asset}`\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(10_000_000, Math.floor(((d.maxBytes * 8) / seconds) * 0.85))\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 })\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 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 = '__VOS_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 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 hasReplay,\n migrateMotion,\n momentOutputs,\n ratedSegments,\n resolveAnchor as resolveLayerAnchor,\n sameMedia,\n spanOutputExtent,\n} from '@vosjs/studio-core'\nimport { fitCaptions, heldLine } from './captionFit'\nimport { STEP_SETTLE_SECONDS, stepOutputTime } from './moments'\nimport type {\n Anim,\n AnimKind,\n Destination,\n EndCard,\n Look,\n ProjectDoc,\n TemplateAnchor,\n TextOverlayClip,\n} from '@vosjs/studio-core'\n\n/** The release's words a plan writes into the cut's titles and end card. */\nexport interface ReleaseWords {\n headline?: string | null\n kicker?: string | null\n brand?: string | null\n release?: string | null\n}\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/** The longest a beat's caption stays, seconds. */\nconst CAPTION_BEAT_MAX = 3.5\n\n/** The house caption: a lower-third in a dark box, rising in and fading out. */\nexport function houseCaption(\n id: string,\n text: string,\n start: number,\n duration: number,\n): TextOverlayClip {\n return {\n id,\n kind: 'text',\n text,\n preset: 'caption',\n start,\n duration,\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\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 /** Captions kept past their step to be read, in words, with the room they need. */\n held: 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 // A press plays each time the cut plays its seconds, as its ring does.\n const replayed = hasReplay(rated)\n const at: number[] = []\n for (const e of doc.source.cursor) {\n if (e.type !== 'down') continue\n const src = e.t / 1000\n if (replayed) {\n at.push(...momentOutputs(rated, src))\n continue\n }\n const ext = spanOutputExtent(rated, src, src + 0.001)\n if (ext) at.push(ext.start)\n }\n if (replayed) at.sort((a, b) => a - b)\n const out: number[] = []\n for (const t of at) {\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/**\n * The end card's cursor-off range: the drawn cursor leaves where the card\n * begins and stays off to the end of the film, so it never sits under the\n * card's words. Stamped `from: 'endcard'`, it replaces an earlier one and\n * goes wherever the end card goes; a person's own ranges are kept.\n */\nfunction withEndCardCursorOff(doc: ProjectDoc, start: number): ProjectDoc {\n const own = (doc.cursor.off ?? []).filter((r) => r.from !== END_CARD_FROM)\n return {\n ...doc,\n cursor: {\n ...doc.cursor,\n off: [\n ...own,\n { in: +Math.max(0, start).toFixed(3), from: END_CARD_FROM },\n ],\n },\n }\n}\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 held: 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 before = outputLength(doc)\n const applied = applyTemplate(t.doc, doc, {\n at,\n from: t.from,\n words: tWords,\n keys,\n })\n doc = applied.doc\n if (t.from === END_CARD_FROM) {\n // The cursor leaves where the moving footage ends, as under the\n // house card, or where the card's first clip begins if that is\n // sooner.\n const starts = (doc.overlays ?? [])\n .filter((o) => o.from === END_CARD_FROM && o.start !== undefined)\n .map((o) => o.start as number)\n doc = withEndCardCursorOff(doc, Math.min(before, ...starts))\n }\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 doc = withEndCardCursorOff(doc, endStart)\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 is a lower-third that lands as the\n // step BEGINS, so its words name the beat while it plays, and leaves when\n // the step ends (landing after the step put its words over the next one).\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 const beats: {\n caption: (typeof opts.captions)[number]\n t: number\n until?: number\n }[] = []\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 ref = step.id ?? step.step\n const t = resolveLayerAnchor(doc, { step: ref, at: 'start' }, rated).start\n if (t === null || t < 0 || t >= footage) continue\n const until = resolveLayerAnchor(\n doc,\n { step: ref, at: 'end' },\n rated,\n ).start\n beats.push({\n caption: c,\n t: +t.toFixed(3),\n ...(until !== null ? { until } : {}),\n })\n }\n // Each leaves with its step (or once its words are read), gives way to\n // the next and leaves before the footage ends, so a caption never sits\n // beside another one, over the next beat, or into the end card.\n const fit = fitCaptions(\n beats,\n (b) => ({\n start: b.t,\n end: footage,\n ...(b.until !== undefined ? { until: b.until } : {}),\n text: b.caption.caption,\n }),\n { max: CAPTION_BEAT_MAX },\n )\n for (const { item, why } of fit.dropped)\n skipped.push(`caption for step ${item.caption.step}: ${why}`)\n for (const k of fit.kept)\n if (k.held)\n held.push(\n heldLine(`the caption for step ${k.item.caption.step}`, k.held),\n )\n for (const { item, duration } of fit.kept)\n captionClips.push(\n houseCaption(\n `${CAPTION_ID_PREFIX}${item.caption.step}`,\n item.caption.caption,\n item.t,\n duration,\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, held }\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' | 'px' | 'text'>,\n doc: Pick<ProjectDoc, 'overlays' | 'freeze'> & {\n cursor?: Pick<ProjectDoc['cursor'], 'off'>\n },\n): { set: string[]; unset: string[]; notes: string[] } {\n const set: string[] = []\n const unset: string[] = []\n const notes: string[] = []\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 // and so does the cursor-off range it placed (it would blink the\n // cursor out at the wrap).\n const keptFreezes = (doc.freeze ?? []).filter((f) => !f.from)\n if (keptFreezes.length !== (doc.freeze ?? []).length)\n set.push(`freeze=${JSON.stringify(keptFreezes)}`)\n const off = doc.cursor?.off ?? []\n const keptOff = off.filter((r) => !r.from)\n if (keptOff.length !== off.length)\n set.push(`cursor.off=${JSON.stringify(keptOff)}`)\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 * How long each caption stays on screen, so that no two are up at once.\n *\n * Captions land where their steps play, and steps can play close together\n * (a click, then the field it opened a second later). A caption is about its\n * step, so it leaves when the step ends, unless its words need longer to be\n * read; it never lingers over the steps after it. It gives way to the next\n * caption with a small gap and never outlives the clip it starts in. When a\n * caption cannot stay up long enough to be read before the next one (or\n * before its clip ends), it is DROPPED and said, never squeezed into an\n * overlap: two captions on screen at once read as neither.\n *\n * Walked from the last caption back, so each one gives way to the next\n * caption that is actually kept. Pure: the input is never mutated.\n */\n\n/** The longest a caption stays up, seconds. */\nexport const CAPTION_MAX = 3\n/** The shortest a caption can be read in, seconds. */\nexport const CAPTION_MIN = 1.2\n/** The gap between one caption leaving and the next arriving, seconds. */\nexport const CAPTION_GAP = 0.1\n\n/** Reading speed: the subtitle standard of 17 characters a second, spaces included. */\nconst READ_CHARS_PER_SECOND = 17\n\n/** How long `text` takes to read, seconds (`CAPTION_MIN` to `CAPTION_MAX`). */\nexport function readingSeconds(text: string): number {\n const chars = text.trim().replace(/\\s+/g, ' ').length\n return Math.min(\n CAPTION_MAX,\n Math.max(CAPTION_MIN, chars / READ_CHARS_PER_SECOND),\n )\n}\n\nexport interface CaptionSlot {\n start: number\n /** Where the clip it starts in ends (the end of the film for the last). */\n end: number\n /**\n * Where its step ends (output seconds): the caption leaves there, or once\n * its words are read when that is later. Absent: it stays as long as the\n * room allows.\n */\n until?: number\n /** Its words, for the reading time. */\n text?: string\n}\n\nexport interface CaptionFit<T> {\n /**\n * The kept captions in playing order, each with its duration, and `held`:\n * the seconds it stays past its step's end because its words take longer\n * to read than the step lasts (absent when it leaves with its step).\n */\n kept: { item: T; duration: number; held?: number }[]\n /** The captions that could not be read in time, and why, in words. */\n dropped: { item: T; why: string }[]\n}\n\nexport function fitCaptions<T>(\n items: T[],\n slotOf: (item: T) => CaptionSlot,\n opts: { max?: number; min?: number; gap?: number } = {},\n): CaptionFit<T> {\n const max = opts.max ?? CAPTION_MAX\n const min = opts.min ?? CAPTION_MIN\n const gap = opts.gap ?? CAPTION_GAP\n const ordered = items\n .map((item) => ({ item, slot: slotOf(item) }))\n .sort((a, b) => a.slot.start - b.slot.start)\n const kept: { item: T; duration: number; held?: number }[] = []\n const dropped: { item: T; why: string }[] = []\n let nextStart = Infinity\n for (let i = ordered.length - 1; i >= 0; i--) {\n const { item, slot } = ordered[i]\n const clipRoom = slot.end - slot.start\n const nextRoom = nextStart - gap - slot.start\n const ownRoom =\n slot.until === undefined\n ? Infinity\n : Math.max(\n slot.until - slot.start,\n slot.text === undefined ? min : readingSeconds(slot.text),\n )\n const duration = Math.min(max, clipRoom, nextRoom, ownRoom)\n if (duration < min - 1e-9) {\n dropped.unshift({\n item,\n why:\n nextRoom < clipRoom\n ? `the next caption starts ${(nextStart - slot.start).toFixed(2)}s after it, too soon to read it (more time on its step, its ms, gives it room)`\n : `it plays in the last ${Math.max(0, clipRoom).toFixed(2)}s of its clip, too short to read it (a wait after its step gives it room)`,\n })\n continue\n }\n const held =\n slot.until === undefined ? 0 : duration - (slot.until - slot.start)\n kept.unshift({\n item,\n duration: +duration.toFixed(3),\n ...(held > 0.05 ? { held: +held.toFixed(2) } : {}),\n })\n nextStart = slot.start\n }\n return { kept, dropped }\n}\n\n/**\n * A kept caption that stays past its step, in words, with both ways to let\n * it leave with the step: fewer words (an edit to the caption, no take) or\n * more time on the step (a re-record). Never a shorter duration: that only\n * takes the time its words need to be read.\n */\nexport function heldLine(label: string, held: number): string {\n return `${label} stays ${held.toFixed(2)}s past its step to be read; to let it leave with the step, shorten its words (17 characters read in a second) or give its step more time (its ms, then record again). Do not cut its duration: the words need that time`\n}\n","/**\n * Where a step of the take's step timeline lands in the cut: a gesture's\n * end plus a settle (so the frame shows the response, not the travel),\n * mapped through the cut into OUTPUT seconds. The captions a plan writes\n * sit there. Pure.\n */\nimport {\n hasReplay,\n longestOutputExtent,\n momentOutputs,\n ratedSegments,\n spanOutputExtent,\n} from '@vosjs/studio-core'\nimport type { 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/**\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 if (!hasReplay(rated)) return ext.start\n // A step the cut replays settles in the pass it plays longest.\n const pass = longestOutputExtent(rated, step.tStart, step.tEnd)\n const after = pass\n ? momentOutputs(rated, src).find((o) => o >= pass.start - 1e-6)\n : undefined\n return after ?? ext.start\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, mintAt, 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, origin: string) => string\n}\n\n/**\n * Best-effort OS launch — the printed URL stays the contract (vos open).\n * The URL is an ARGUMENT, never part of a shell line: a server answer is\n * not a thing to hand a shell.\n */\nexport async function launchDefaultBrowser(url: string): Promise<void> {\n const { spawn } = await import('node:child_process')\n const [cmd, args] =\n process.platform === 'darwin'\n ? ['open', [url]]\n : process.platform === 'win32'\n ? ['cmd', ['/c', 'start', '', url]]\n : ['xdg-open', [url]]\n try {\n const child = spawn(cmd, args, { detached: true, stdio: 'ignore' })\n child.on('error', () => {})\n child.unref()\n } catch {\n // The printed URL is the contract.\n }\n}\n\n/** The address a sign-in may open: a page on the origin the CLI asked. */\nexport function verifyUrlOk(verifyUrl: string, origin: string): boolean {\n try {\n return new URL(verifyUrl).origin === new URL(origin).origin\n } catch {\n return false\n }\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 && verifyUrlOk(verifyUrl, origin))\n 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)(\n res.body.key as string,\n origin,\n )\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 ${mintAt(origin)} 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, origin: 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)(\n res.body.key as string,\n parsed.origin,\n )\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 * 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","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 layerStart,\n parseCssColour,\n pinBox,\n ratedSegments,\n resolvePins,\n longestOutputExtent,\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 // A step the cut replays is read in the pass it plays longest.\n const ext = longestOutputExtent(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 = longestOutputExtent(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/** The output second a card's ground is read at: its start (where its anchor places it) plus its entrance. */\nfunction groundTime(start: number, duration: number): number {\n return +(start + Math.min(0.35, duration / 2)).toFixed(3)\n}\n\n/** Every output second `groundFindings` reads a frame at, once each. */\nexport function groundCheckTimes(doc: ProjectDoc): number[] {\n const rated = ratedSegments(doc)\n const times = new Set<number>()\n for (const o of doc.overlays ?? []) {\n if (o.kind !== 'html') continue\n const start = layerStart(o, doc, rated)\n if (start !== null) times.add(groundTime(start, o.duration))\n }\n return [...times]\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 const rated = ratedSegments(doc)\n for (let i = 0; i < overlays.length; i++) {\n const o = overlays[i]\n if (o.kind !== 'html') continue\n // Where the layer plays (an anchor places it); nowhere is not checked.\n const start = layerStart(o, doc, rated)\n if (start === null) 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 = groundTime(start, o.duration)\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 - 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 * 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 * `vos validate <kit.json> --picture`: what each cut LOOKS like, read from\n * its bytes the way the spec pass reads its size. Every finding carries a\n * code, a severity, a message written from the failure it was built on and\n * a fix hint, so an agent can self-check by name and a reader can find the\n * spot.\n *\n * firstlast a video whose first or last frame is blank (a cold open on\n * nothing, a clip that ends on nothing) or bled on all four\n * sides (no ground, no room)\n *\n * The frames come through ffmpeg when it is on PATH and are skipped, said,\n * when it is not. Pure over decoded pixels otherwise.\n */\nimport { execFile } from 'node:child_process'\nimport { promisify } from 'node:util'\nimport { decodePng, inkCoverage, measureStill } from './picture'\nimport type { Rect, Rgba, StillMeasure } from './picture'\n\nconst execFileP = promisify(execFile)\n\nexport type PictureCode = 'firstlast'\n\nexport interface PictureFinding {\n code: PictureCode\n severity: 'error' | 'warning' | 'info'\n /** The asset's destination id. */\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\nexport interface PictureAsset {\n destination: string\n path: string\n file: string\n seconds?: number | null\n}\n\n/** Ink coverage under which a frame's subject is blank. */\nexport const BLANK_INK = 0.12\n\nconst pct = (v: number) => `${Math.round(v * 100)}%`\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/** The checks on one frame of a cut; pure. */\nexport function frameFindings(\n asset: string,\n name: 'first' | 'last',\n img: Rgba,\n m: StillMeasure,\n): PictureFinding[] {\n const out: PictureFinding[] = []\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 out.push({\n code: 'firstlast',\n severity: 'error',\n asset,\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',\n })\n }\n if (m.bleed.length === 4) {\n out.push({\n code: 'firstlast',\n severity: 'warning',\n asset,\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 return out\n}\n\n/**\n * Run the picture checks over a kit's cuts: each video's first and last\n * frame through ffmpeg. Returns the findings and, per asset, what was\n * measured on its first frame.\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 let ffmpeg: boolean | null = null\n\n for (const a of assets) {\n if (!/\\.(mp4|webm|mov)$/i.test(a.file)) continue\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(a.file, Math.max(0, seconds - 0.1), 'ffmpeg')\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 findings.push(...frameFindings(a.destination, name, img, m))\n }\n }\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 cut in the manifest must exist,\n * measure what the manifest claims, and meet its destination's spec (px,\n * bytes, duration). Reads dims and durations from the FILES, never from\n * intent, so a manifest that lies is caught. Pure over a directory: no\n * 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 } 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 source?: 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\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 */\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 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 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 (/\\.(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(`${label}: ${a.path} is not a video the kit verifies`)\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 seconds,\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 }\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, plus `outputs/<name>` for every\n * file a `download` step kept and `page-sound/<name>` for every sound the\n * page was heard playing.\n */\nimport { writeFileSync } from 'node:fs'\nimport { lstat, mkdir, readFile, realpath } from 'node:fs/promises'\nimport { join, resolve, sep } from 'node:path'\nimport {\n fileNameProblem,\n inlineScript,\n loadScriptFiles,\n recordTake as recordTakeCore,\n} from '@vosjs/render-core/record'\nimport type {\n OutputSink,\n RecordOpts as CoreRecordOpts,\n SoundSink,\n ScriptFiles,\n} from '@vosjs/render-core/record'\nimport type { Browser, BrowserContext } from 'playwright'\nimport { writeJson } from './take'\nimport { looksLikeStorageState } from './session'\nimport { refuseSymlink, writeFileSafe } from './safeWrite'\nimport type { ActionsFile } from './actions'\nimport type { TakePaths } from './take'\n\nexport type {\n DisabledClick,\n FrameRec,\n FreezeSpan,\n RecordResult,\n SkippedStep,\n StoppedTake,\n} from '@vosjs/render-core/record'\n\n/** The take's `outputs/`: where a `download` step's file lands, and nowhere else. */\nexport function outputsSink(dir: string): OutputSink {\n const outDir = join(dir, 'outputs')\n return {\n save: async (name, bytes) => {\n // The recorder names the file; a name that is not plain never\n // reaches the disk, whoever chose it.\n const problem = fileNameProblem(name)\n if (problem) throw new Error(`outputs/${name}: ${problem}`)\n await refuseSymlink(outDir)\n await mkdir(outDir, { recursive: true })\n await writeFileSafe(join(outDir, name), bytes)\n },\n }\n}\n\n/** The take's `page-sound/`: the sound the page played, keyed take-relative for the plan's clips. */\nexport const PAGE_SOUND_DIR = 'page-sound'\n\nexport function pageSoundSink(dir: string): SoundSink {\n const soundDir = join(dir, PAGE_SOUND_DIR)\n return {\n save: async (name, bytes) => {\n const problem = fileNameProblem(name)\n if (problem) throw new Error(`${PAGE_SOUND_DIR}/${name}: ${problem}`)\n await refuseSymlink(soundDir)\n await mkdir(soundDir, { recursive: true })\n await writeFileSafe(join(soundDir, name), bytes)\n return `${PAGE_SOUND_DIR}/${name}`\n },\n }\n}\n\n/**\n * The files a script names beside itself (a drag's path, a paste's file):\n * a plain name in the actions file's own directory, never a link, never a\n * path that resolves outside it, whoever wrote the name.\n */\nexport function actionsDirFiles(dir: string): ScriptFiles {\n return {\n read: async (name) => {\n const problem = fileNameProblem(name)\n if (problem) throw new Error(problem)\n const file = join(dir, name)\n if ((await lstat(file)).isSymbolicLink())\n throw new Error(\n `${name} is a symbolic link, which a script never follows`,\n )\n const [real, root] = await Promise.all([realpath(file), realpath(dir)])\n if (!real.startsWith(root + sep))\n throw new Error(`${name} resolves outside the actions file's directory`)\n return new Uint8Array(await readFile(real))\n },\n }\n}\n\n/**\n * Where a peer's `storageState` is read from: a path from the actions\n * file's directory (or an absolute one), to a regular file shaped like a\n * Playwright storage state. The file is opened by the browser and nothing\n * else: never copied into a take, never uploaded, never printed.\n */\nexport function peerStateFrom(dir: string): (name: string) => Promise<string> {\n return async (name) => {\n const file = resolve(dir, name)\n let raw: string\n try {\n raw = await readFile(file, 'utf8')\n } catch {\n throw new Error(\n `there is no file at ${file}; a storage state is never copied into a take, so name it by a path from the actions file (or an absolute one, such as one saved under ~/.config/vos)`,\n )\n }\n let parsed: unknown\n try {\n parsed = JSON.parse(raw)\n } catch {\n parsed = null\n }\n if (!looksLikeStorageState(parsed))\n throw new Error(\n `${file} is not a Playwright storage state ({ cookies, origins }); save one with context.storageState({ path })`,\n )\n return file\n }\n}\n\n/** The name a pasted file is kept under in the take: `paste-<name>`, once. */\nexport const pasteCopyName = (name: string): string =>\n name.startsWith('paste-') ? name : `paste-${name}`\n\n/**\n * Copy every file a `paste` step names into the take, under\n * `paste-<name>`, and point the script at the copy: the take's own\n * actions.json then re-records on this machine with the original gone. A\n * paste's bytes never travel inside the script itself (a push embeds the\n * script, not the file).\n */\nexport async function keepPasteFiles(\n actions: ActionsFile,\n actionsDir: string,\n takeDir: string,\n): Promise<ActionsFile> {\n if (!actions.steps.some((s) => s.do === 'paste' && s.file)) return actions\n const files = actionsDirFiles(actionsDir)\n const steps = await Promise.all(\n actions.steps.map(async (s) => {\n if (s.do !== 'paste' || !s.file) return s\n const name = pasteCopyName(s.file)\n const same = resolve(actionsDir) === resolve(takeDir) && name === s.file\n if (!same)\n await writeFileSafe(join(takeDir, name), await files.read(s.file))\n return { ...s, file: name }\n }),\n )\n return { ...actions, steps }\n}\n\n/**\n * The script a hosted recorder runs: every path a file held written\n * inline, since the script travels alone. A paste is left as it is for the\n * hosted refusal to name.\n */\nexport async function scriptForHost(\n actions: ActionsFile,\n actionsDir: string,\n): Promise<ActionsFile> {\n const pathsOnly = {\n steps: actions.steps.map((s) =>\n s.do === 'paste' ? ({ do: 'wait', ms: 0 } as const) : s,\n ),\n }\n const files = await loadScriptFiles(pathsOnly, actionsDirFiles(actionsDir))\n if ('problem' in files) throw new Error(files.problem)\n return inlineScript(actions, files)\n}\n\nexport type RecordOpts = Omit<\n CoreRecordOpts,\n 'context' | 'env' | 'platform' | 'outputs' | 'sounds' | 'files'\n> & {\n /**\n * The actions file's directory: where a drag's path file and a paste's\n * file are read from. Absent, a script that names one is refused.\n */\n actionsDir?: string\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 outputs: outputsSink(paths.dir),\n sounds: pageSoundSink(paths.dir),\n ...(opts.actionsDir\n ? {\n files: actionsDirFiles(opts.actionsDir),\n peerStorageState: peerStateFrom(opts.actionsDir),\n }\n : {}),\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 // The script as it ran, self-contained: paths are inline (the\n // recorder's), and a pasted file is kept beside it under its own name.\n if (opts.actionsDir)\n result.actions = await keepPasteFiles(\n result.actions,\n opts.actionsDir,\n paths.dir,\n )\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 * `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 {\n existsSync,\n mkdirSync,\n mkdtempSync,\n readdirSync,\n rmSync,\n statSync,\n} from 'node:fs'\nimport { homedir, tmpdir } from 'node:os'\nimport { join } from 'node:path'\nimport { chromium } from 'playwright'\nimport type { BrowserContext } from 'playwright'\nimport { BROWSER_SWITCHES } from '../browser'\nimport {\n cookieWatch,\n enterPressed,\n helpersGone,\n readChromeTree,\n runSessionWindow,\n} from './sessionWindow'\nimport type { SessionFinish } from './sessionWindow'\nimport { WALL_PROBE, isIdpHost, isSignInPath, wallVerdict } from './wall'\nimport type { WallVerdict } from './wall'\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 the\n * person to FINISH, however they finish (sessionWindow.ts): the last window\n * closed, Chrome quit, or Enter in the terminal. A child process with no\n * debugging endpoint and no automation switch, so a sign-in that refuses\n * automated browsers goes through, and the person signs in however the app\n * demands. The cookie store is written when Chrome quits, so a finish that\n * leaves Chrome running (a closed window on a Mac, Enter) quits THIS\n * Chrome, by its PID, and only then is the session read.\n */\nexport async function openSession(\n name: string,\n url: string,\n opts: { log: (line: string) => void } = { log: () => {} },\n): Promise<SessionOpened> {\n const dir = sessionDir(name)\n mkdirSync(dir, { recursive: true, mode: 0o700 })\n return openSessionWindow({\n dir,\n url,\n label: `session \"${name}\"`,\n log: opts.log,\n })\n}\n\nexport interface SessionOpened {\n finish: SessionFinish\n /** Chrome had to be stopped after the grace: the last cookies may be missing */\n forced: boolean\n /** Chrome's exit code; 0 on a clean quit */\n code: number | null\n}\n\n/**\n * The window itself, on any profile directory. `extraArgs` exists for the\n * test of this, which closes the page through a debugging endpoint the\n * person's window never has.\n */\nexport async function openSessionWindow(opts: {\n dir: string\n url: string\n label: string\n log: (line: string) => void\n extraArgs?: string[]\n pollMs?: number\n /** listen for Enter (default: when stdin is a terminal) */\n stdin?: boolean\n}): Promise<SessionOpened> {\n const exe = systemChromePath()\n const args = [\n `--user-data-dir=${opts.dir}`,\n '--no-first-run',\n '--no-default-browser-check',\n '--window-size=1100,800',\n ...(opts.extraArgs ?? []),\n opts.url,\n ]\n const { host, hostname } = new URL(opts.url)\n const tty = opts.stdin !== false && process.stdin.isTTY === true\n const enter = tty\n ? enterPressed()\n : { pressed: new Promise<void>(() => {}), close: () => {} }\n opts.log(\n `a Chrome window opened on ${opts.label}: sign in to ${host}, and set the account up the way the takes should find it (a workspace, demo data). When you are done, close the window${tty ? ' or press Enter here' : ''}; the session saves either way`,\n )\n const child = spawn(exe, args, { stdio: 'ignore' })\n let failed: Error | null = null\n let code: number | null = null\n const exited = new Promise<void>((resolve) => {\n child.once('exit', (c) => {\n code = c\n resolve()\n })\n child.once('error', (e) => {\n failed = e\n resolve()\n })\n })\n try {\n const pid = child.pid\n if (pid === undefined) {\n await exited\n throw failed ?? new Error(`could not start ${exe}`)\n }\n // The last helper PIDs seen: the cookie store is written by one of them.\n let helpers: number[] = []\n const { finish, forced } = await runSessionWindow({\n pid,\n watch: {\n pages: async () => {\n const tree = await readChromeTree(pid)\n if (tree) helpers = tree.pids\n return tree ? tree.pages : null\n },\n exited,\n enter: enter.pressed,\n onTick: cookieWatch(opts.dir, hostname, opts.log),\n ...(opts.pollMs !== undefined ? { pollMs: opts.pollMs } : {}),\n },\n kill: (p, signal) => process.kill(p, signal),\n afterExit: () => helpersGone(helpers),\n save: async () => undefined,\n log: opts.log,\n })\n if (failed) throw failed\n return { finish, forced, code }\n } finally {\n enter.close()\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 return withProfile(dir, fn, opts)\n}\n\n/** `withSession` on any profile directory (the test of the wall check makes its own). */\nexport async function withProfile<T>(\n dir: string,\n fn: (ctx: BrowserContext) => Promise<T>,\n opts: {\n headless?: boolean\n viewport?: { width: number; height: number }\n } = {},\n): Promise<T> {\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 args: [...BROWSER_SWITCHES],\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\n/**\n * Does this profile open `url` as the person who signed in? The wall\n * check's own verdict, headless, on the saved profile: null when the page\n * opens where it was asked, else where a stranger is sent and why. Cookies\n * prove nothing on their own (a site sets analytics cookies on every\n * visit), so this is the one test of a sign-in that `open` and `check`\n * both say.\n */\nexport async function profileWall(\n dir: string,\n url: string,\n): Promise<WallVerdict | null> {\n return withProfile(dir, (ctx) => arrivalWall(ctx, url))\n}\n\n/** Open `url` in this context and give the wall check's verdict on where it landed. */\nasync function arrivalWall(\n ctx: BrowserContext,\n url: string,\n): Promise<WallVerdict | null> {\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\n/**\n * What a session's check found, against a STRANGER: a page that opens the\n * same for someone with no session cannot tell a sign-in from none, and a\n * sign-in page opens for everyone.\n */\nexport type SessionVerdict =\n | { state: 'signed-in'; stranger: WallVerdict }\n | { state: 'not-signed-in'; wall: WallVerdict }\n | { state: 'cant-tell'; reason: 'sign-in-page' | 'same-for-stranger' }\n\n/** Is this URL a sign-in page by the wall's own rules (a sign-in path, an identity provider)? */\nexport function isSignInUrl(url: string): boolean {\n try {\n const u = new URL(url)\n return isSignInPath(u.pathname) || isIdpHost(u.hostname)\n } catch {\n return false\n }\n}\n\n/**\n * The verdict from the two arrivals: the saved profile's and a stranger's\n * (a fresh, empty context). Pure. Walled with the profile is not signed\n * in; open with the profile and walled for the stranger is signed in;\n * open for both is a URL that cannot tell.\n */\nexport function sessionVerdictOf(\n profile: WallVerdict | null,\n stranger: WallVerdict | null,\n): SessionVerdict {\n if (profile) return { state: 'not-signed-in', wall: profile }\n if (stranger) return { state: 'signed-in', stranger }\n return { state: 'cant-tell', reason: 'same-for-stranger' }\n}\n\n/**\n * Check a saved profile against a stranger on `url`. A sign-in URL is not\n * opened at all: a stranger reaches it too, so it proves nothing.\n */\nexport async function profileVerdict(\n dir: string,\n url: string,\n): Promise<SessionVerdict> {\n if (isSignInUrl(url)) return { state: 'cant-tell', reason: 'sign-in-page' }\n const profile = await profileWall(dir, url)\n if (profile) return sessionVerdictOf(profile, null)\n const stranger = await strangerWall(url)\n return sessionVerdictOf(null, stranger)\n}\n\n/** The wall check for someone with no session: a fresh, empty context on the same Chrome. */\nasync function strangerWall(url: string): Promise<WallVerdict | null> {\n const dir = mkdtempSync(join(tmpdir(), 'vos-stranger-'))\n try {\n return await withProfile(dir, (ctx) => arrivalWall(ctx, url))\n } finally {\n rmSync(dir, { recursive: true, force: true })\n }\n}\n\n/** The check on a named session. */\nexport function sessionVerdict(\n name: string,\n url: string,\n): Promise<SessionVerdict> {\n return profileVerdict(sessionDir(name), url)\n}\n\n/** The sentence for a verdict, said the same way by `open` and `check`. */\nexport function verdictLine(\n v: SessionVerdict,\n url: string,\n name: string,\n): string {\n switch (v.state) {\n case 'signed-in':\n return `signed in: ${url} opens as you (a stranger is sent to ${landedWords(v.stranger)})`\n case 'not-signed-in':\n return `NOT signed in: ${url} sends a stranger to ${landedWords(v.wall)}, and this session along with them; nothing a take needs was saved`\n case 'cant-tell':\n return v.reason === 'sign-in-page'\n ? `can't tell: ${url} is a sign-in page, which a stranger opens too; check with the app's own page: vos session check ${name} --url <a page only a signed-in person sees, such as its dashboard>`\n : `can't tell: ${url} opens the same for a stranger; check with --url <a page only a signed-in person sees>: vos session check ${name} --url <that page>`\n }\n}\n\n/** Where a verdict says a stranger lands, as the person reads it: the path on the same host, else the URL. */\nexport function landedWords(v: WallVerdict): string {\n try {\n const asked = new URL(v.asked)\n const landed = new URL(v.landed)\n return landed.host === asked.host ? landed.pathname : v.landed\n } catch {\n return v.landed\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 * How `vos session open` knows the person is done with the window, without\n * making the window look automated.\n *\n * A debugging endpoint is out: with `--remote-debugging-port` or\n * `--remote-debugging-pipe` on, Chrome reports `navigator.webdriver ===\n * true` to every page (measured, Chrome 155), which is exactly what a\n * sign-in that refuses automated browsers reads. So the window is watched\n * from OUTSIDE the browser, through what any process can see:\n *\n * - the process table: a Chrome window that draws a page has a renderer\n * for it, and when the last window closes every renderer that is not an\n * extension's exits while the browser process stays up (a Mac keeps\n * Chrome running with no window; measured). A minimized window, or one on\n * another desktop, keeps its renderer, so neither reads as closed;\n * - the profile's cookie store, a SQLite file Chrome commits about every\n * thirty seconds: hosts, names and expiry dates are plain columns, the\n * values are encrypted and never read here.\n *\n * The CLI never quits on a sign-in it detects. The person often is not\n * done: a second factor or a single sign-on hop finishes later, and they\n * pick a workspace and stage the account in that window, which every take\n * on the session inherits. Only the person's own act finishes it: the last\n * window closed, Chrome quit, or Enter in the terminal.\n */\nimport { execFile } from 'node:child_process'\nimport { existsSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { createInterface } from 'node:readline'\n\n/** How the person finished: closed the last window, quit Chrome, or pressed Enter. */\nexport type SessionFinish = 'window-closed' | 'quit' | 'enter'\n\nexport interface ProcessRow {\n pid: number\n ppid: number\n command: string\n}\n\n/** `ps -A -o pid= -o ppid= -o command=`, read into rows. */\nexport function parseProcessTable(out: string): ProcessRow[] {\n const rows: ProcessRow[] = []\n for (const line of out.split('\\n')) {\n const m = /^\\s*(\\d+)\\s+(\\d+)\\s+(.*)$/.exec(line)\n if (m) rows.push({ pid: Number(m[1]), ppid: Number(m[2]), command: m[3] })\n }\n return rows\n}\n\n/** A renderer that draws a page (a tab, a popup, a sign-in window), not an extension's. */\nexport function isPageRenderer(command: string): boolean {\n return (\n /\\s--type=renderer(\\s|$)/.test(command) &&\n !/\\s--extension-process(\\s|$)/.test(command)\n )\n}\n\n/** What one Chrome's process tree holds: its page renderers, and every helper's PID. */\nexport interface ChromeTree {\n pages: number\n pids: number[]\n}\n\n/**\n * The tree of the Chrome at `pid`, over every descendant: on Linux\n * renderers hang off a zygote, not the browser.\n */\nexport function chromeTree(rows: ProcessRow[], pid: number): ChromeTree {\n const kids = new Map<number, ProcessRow[]>()\n for (const r of rows) {\n const list = kids.get(r.ppid)\n if (list) list.push(r)\n else kids.set(r.ppid, [r])\n }\n let pages = 0\n const pids: number[] = []\n const stack = [...(kids.get(pid) ?? [])]\n const seen = new Set<number>()\n while (stack.length) {\n const r = stack.pop()!\n if (seen.has(r.pid)) continue\n seen.add(r.pid)\n pids.push(r.pid)\n if (isPageRenderer(r.command)) pages++\n stack.push(...(kids.get(r.pid) ?? []))\n }\n return { pages, pids }\n}\n\n/** The live tree off this machine's process table; null where there is no `ps`. */\nexport function readChromeTree(pid: number): Promise<ChromeTree | null> {\n if (process.platform === 'win32') return Promise.resolve(null)\n return new Promise((resolve) => {\n execFile(\n 'ps',\n ['-A', '-o', 'pid=', '-o', 'ppid=', '-o', 'command='],\n { maxBuffer: 16 * 1024 * 1024, timeout: 5000 },\n (err, stdout) => {\n if (err) resolve(null)\n else resolve(chromeTree(parseProcessTable(stdout), pid))\n },\n )\n })\n}\n\n/**\n * Wait until every one of these processes is gone. The browser process\n * exits before its helpers do, and the network service, which owns the\n * cookie store, is still writing it for a moment after (measured: a read\n * straight after the exit found no store, under load). Bounded: a helper\n * that lingers past `ms` is not waited for.\n */\nexport async function helpersGone(\n pids: number[],\n ms = 10000,\n sleep: (ms: number) => Promise<void> = realSleep,\n): Promise<void> {\n const alive = (p: number) => {\n try {\n process.kill(p, 0)\n return true\n } catch (e) {\n return (e as NodeJS.ErrnoException).code === 'EPERM'\n }\n }\n const until = Date.now() + ms\n while (pids.some(alive) && Date.now() < until) await sleep(100)\n}\n\n/** What the watch needs, every part injectable so the logic is tested without a browser. */\nexport interface SessionWatch {\n /** page renderers now; null when this platform cannot tell (then only quit and Enter finish) */\n pages: () => Promise<number | null>\n /** settles when the browser process exits */\n exited: Promise<unknown>\n /** settles when the person presses Enter; never, without a terminal */\n enter: Promise<unknown>\n /** once per poll: the cookie report */\n onTick?: () => Promise<void>\n sleep?: (ms: number) => Promise<void>\n pollMs?: number\n /**\n * Polls in a row with no page before the window counts as closed. One is\n * a navigation swapping its renderer; two is a window that is gone.\n */\n emptyPolls?: number\n /**\n * How long the browser must stay up once its pages are gone before the\n * window counts as closed. Chrome that is EXITING (quit, or gone on its\n * own) drops its renderers first and its own process a moment later;\n * that is a quit, never a window the person closed.\n */\n confirmMs?: number\n}\n\nconst realSleep = (ms: number) => new Promise<void>((r) => setTimeout(r, ms))\n\n/**\n * Wait until the person finishes. A window counts as closed only after a\n * page was seen at least once (Chrome starts with none for a moment), and\n * only once it stays closed for `emptyPolls` polls.\n */\nexport async function waitForFinish(w: SessionWatch): Promise<SessionFinish> {\n const sleep = w.sleep ?? realSleep\n const pollMs = w.pollMs ?? 1000\n const needEmpty = w.emptyPolls ?? 2\n let done: SessionFinish | null = null\n void w.exited.then(() => {\n done ??= 'quit'\n })\n void w.enter.then(() => {\n done ??= 'enter'\n })\n let seen = false\n let empty = 0\n while (done === null) {\n await Promise.race([sleep(pollMs), w.exited, w.enter])\n if (done !== null) break\n const n = await w.pages().catch(() => null)\n if (done !== null) break\n if (n !== null) {\n if (n > 0) {\n seen = true\n empty = 0\n } else if (seen && ++empty >= needEmpty) {\n const exiting = await Promise.race([\n w.exited.then(() => true),\n sleep(w.confirmMs ?? 1500).then(() => false),\n ])\n if (exiting) break\n done = 'window-closed'\n break\n }\n }\n await w.onTick?.().catch(() => {})\n }\n // Set by the exit's own callback, which runs before this one resumes.\n return done ?? 'quit'\n}\n\n/**\n * Quit the session's own Chrome, by its PID. SIGTERM is a clean shutdown to\n * Chromium on Mac and Linux (it writes the cookie store and marks the\n * profile's exit normal), and a PID names this Chrome and no other: the\n * person's everyday Chrome is the same app, so never by name and never\n * through AppleScript. A Chrome that does not go in `graceMs` is killed,\n * and the caller says the last cookies may be missing.\n */\nexport async function quitOwnChrome(d: {\n pid: number\n exited: Promise<unknown>\n kill: (pid: number, signal: NodeJS.Signals) => void\n graceMs?: number\n sleep?: (ms: number) => Promise<void>\n}): Promise<{ forced: boolean }> {\n const sleep = d.sleep ?? realSleep\n try {\n d.kill(d.pid, 'SIGTERM')\n } catch {\n // already gone\n }\n const quit = await Promise.race([\n d.exited.then(() => true),\n sleep(d.graceMs ?? 20000).then(() => false),\n ])\n if (quit) return { forced: false }\n try {\n d.kill(d.pid, 'SIGKILL')\n } catch {\n // gone in between\n }\n await d.exited\n return { forced: true }\n}\n\n/**\n * The whole finish: wait for the person, quit this Chrome when the person\n * left it running (a closed window, Enter), then save, which is reading the\n * profile Chrome wrote on the way out. Every finish saves.\n */\nexport async function runSessionWindow<T>(d: {\n pid: number\n watch: SessionWatch\n kill: (pid: number, signal: NodeJS.Signals) => void\n save: () => Promise<T>\n /** after Chrome exits, before the save: wait for its helpers (helpersGone) */\n afterExit?: () => Promise<void>\n log: (line: string) => void\n graceMs?: number\n sleep?: (ms: number) => Promise<void>\n}): Promise<{ finish: SessionFinish; forced: boolean; saved: T }> {\n const finish = await waitForFinish(d.watch)\n let forced = false\n if (finish !== 'quit') {\n d.log(\n finish === 'enter'\n ? 'Enter: saving the session and quitting its Chrome'\n : 'the window closed: saving the session and quitting its Chrome',\n )\n ;({ forced } = await quitOwnChrome({\n pid: d.pid,\n exited: d.watch.exited,\n kill: d.kill,\n ...(d.graceMs !== undefined ? { graceMs: d.graceMs } : {}),\n ...(d.sleep ? { sleep: d.sleep } : {}),\n }))\n if (forced)\n d.log(\n 'Chrome did not quit in time and was stopped: cookies set in the last half minute may not be saved',\n )\n }\n // The browser is gone; its helpers finish writing the profile.\n await d.afterExit?.()\n return { finish, forced, saved: await d.save() }\n}\n\n/** Enter in the terminal, when there is one. `close` lets go of stdin. */\nexport function enterPressed(): { pressed: Promise<void>; close: () => void } {\n if (!process.stdin.isTTY)\n return { pressed: new Promise<void>(() => {}), close: () => {} }\n const rl = createInterface({ input: process.stdin })\n const pressed = new Promise<void>((resolve) =>\n rl.once('line', () => resolve()),\n )\n return { pressed, close: () => rl.close() }\n}\n\n/**\n * Cookie names that are measurement, never a sign-in: a site sets them on\n * a stranger's first visit, so counting them reads as progress that is\n * not there. Matched by the whole name, or by prefix where a vendor\n * numbers or suffixes its cookies: Google Analytics and Ads (`_ga`,\n * `_ga_*`, `_gid`, `_gat*`, `_gcl_*`), Google sign-in's one-tap state\n * (`g_state`, which holds no session), PostHog (`ph_*`, `*_posthog`),\n * Segment (`ajs_*`), Meta (`_fbp`, `_fbc`), Hotjar (`_hj*`), Stripe's\n * fraud signals (`__stripe_*`), Microsoft Clarity and Ads (`_clck`,\n * `_clsk`, `_uet*`), Mixpanel (`mp_*`), Amplitude (`amp_*`), HubSpot\n * (`__hs*`, `hubspotutk`) and Cloudflare's bot checks (`__cf_bm`,\n * `cf_clearance`, `_cfuvid`).\n */\nconst ANALYTICS_COOKIE =\n /^(?:_ga|_ga_.*|_gid|_gat.*|_gcl_.*|g_state|ph_.*|.*_posthog|ajs_.*|_fbp|_fbc|_hj.*|__stripe_.*|_clck|_clsk|_uet.*|mp_.*|amp_.*|__hs.*|hubspotutk|__cf_bm|cf_clearance|_cfuvid)$/\n\n/** Is this cookie measurement rather than anything a sign-in could have set? */\nexport function isAnalyticsCookie(name: string): boolean {\n return ANALYTICS_COOKIE.test(name)\n}\n\n/** One cookie row as the store keeps it, minus the value, which is never read. */\nexport interface CookieRow {\n host: string\n name: string\n /**\n * Chrome's own expiry, as text: microseconds since 1601, which for any\n * cookie that lasts is past the largest integer a JavaScript number holds\n * exactly, and some Nodes' SQLite refuses to hand it back as one.\n */\n expires: string\n}\n\n/** Does a cookie stored for `cookieHost` go with requests to `host`? */\nexport function cookieAppliesTo(cookieHost: string, host: string): boolean {\n const d = cookieHost.replace(/^\\./, '').toLowerCase()\n // A cookie belongs to a host NAME, never a port: localhost:5301's cookies\n // are stored for localhost.\n const h = host.toLowerCase().replace(/:\\d+$/, '')\n return h === d || h.endsWith(`.${d}`)\n}\n\n/**\n * What to say about the target host's cookies this poll: a line when they\n * changed since the last line, null otherwise. The first read is the\n * baseline (the page's own first-visit cookies), so the first line is the\n * first CHANGE. Counts only.\n */\nexport function cookieReport(\n state: { last: string | null; said: boolean },\n rows: CookieRow[],\n host: string,\n): string | null {\n const mine = rows.filter(\n (r) => cookieAppliesTo(r.host, host) && !isAnalyticsCookie(r.name),\n )\n const sig = mine\n .map((r) => `${r.host}\\t${r.name}\\t${r.expires}`)\n .sort()\n .join('\\n')\n if (state.last === null) {\n state.last = sig\n return null\n }\n if (sig === state.last) return null\n state.last = sig\n if (!mine.length) return `${host} holds none now (analytics not counted)`\n const n = `${mine.length} cookie${mine.length === 1 ? '' : 's'}`\n if (state.said) return `${host}: ${n} now`\n state.said = true\n return `${host} set ${n} (analytics not counted). When you are done in the window, close it: the session is then checked by opening ${host} again`\n}\n\n/** The profile's cookie store: `Default/Network/Cookies` on newer builds, `Default/Cookies` before. */\nexport function cookieStore(profileDir: string): string | null {\n for (const p of [\n join(profileDir, 'Default', 'Network', 'Cookies'),\n join(profileDir, 'Default', 'Cookies'),\n ])\n if (existsSync(p)) return p\n return null\n}\n\ntype Sqlite = {\n DatabaseSync: new (\n path: string,\n opts?: { readOnly?: boolean },\n ) => {\n prepare(sql: string): { all(): unknown[] }\n close(): void\n }\n}\nlet sqlite: Promise<Sqlite | null> | null = null\n\n/** `node:sqlite`, where this Node has it (22.5 and up); null otherwise, and the report stays quiet. */\nfunction loadSqlite(): Promise<Sqlite | null> {\n sqlite ??= (async () => {\n // Older Nodes print an experimental-feature warning on import: this is\n // a read of a local file, and the warning would only confuse the person.\n const emit = process.emitWarning\n process.emitWarning = ((w: unknown, ...rest: unknown[]) => {\n if (String(w).includes('SQLite')) return\n ;(emit as (...a: unknown[]) => void).call(process, w, ...rest)\n }) as typeof process.emitWarning\n try {\n // Asked of Node itself, never a bundler or a test runner's resolver,\n // neither of which knows this module on every version.\n const builtin = (\n process as { getBuiltinModule?: (id: string) => unknown }\n ).getBuiltinModule\n return (builtin?.('node:sqlite') as Sqlite | undefined) ?? null\n } catch {\n return null\n } finally {\n process.emitWarning = emit\n }\n })()\n return sqlite\n}\n\n/** Hosts, names and expiry of every saved cookie; null when the store cannot be read this moment. */\nexport async function readCookieRows(\n profileDir: string,\n): Promise<CookieRow[] | null> {\n const file = cookieStore(profileDir)\n if (!file) return []\n const mod = await loadSqlite()\n if (!mod) return null\n try {\n const db = new mod.DatabaseSync(file, { readOnly: true })\n try {\n return (\n db\n .prepare(\n 'SELECT host_key, name, CAST(expires_utc AS TEXT) AS expires FROM cookies',\n )\n .all() as { host_key: string; name: string; expires: string | null }[]\n ).map((r) => ({\n host: r.host_key,\n name: r.name,\n expires: r.expires ?? '0',\n }))\n } finally {\n db.close()\n }\n } catch {\n return null\n }\n}\n\n/** The per-poll cookie report for `host`, said through `log`. */\nexport function cookieWatch(\n profileDir: string,\n host: string,\n log: (line: string) => void,\n): () => Promise<void> {\n const state = { last: null as string | null, said: false }\n return async () => {\n const rows = await readCookieRows(profileDir)\n if (!rows) return\n const line = cookieReport(state, rows, host)\n if (line) log(line)\n }\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 NoticeLog,\n exposureLine,\n maskInitScript,\n noticeAdvice,\n noticeLine,\n} from '@vosjs/render-core/record'\nexport type {\n Exposure,\n ExposureKind,\n MaskReport,\n MaskRule,\n Notice,\n} from '@vosjs/render-core/record'\n","/**\n * `setup` and `teardown` 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 TEARDOWN_BOUND_MS,\n parseHeaders,\n resolveSetupText,\n runSetup,\n scriptEnvNames,\n setupEnvNames,\n teardownEnvProblem,\n teardownLine,\n validateSetup,\n} from '@vosjs/render-core/record'\nexport type {\n SetupResult,\n SetupStep,\n SetupText,\n StepPhase,\n TeardownReport,\n} from '@vosjs/render-core/record'\n","/**\n * Run your own browser code inside a saved session.\n *\n * Some work a take needs is not a step: looking at a state that exists only\n * after a click that creates something, listing what an account holds,\n * cleaning up after a flow. The tempting way is to open the session's\n * profile with your own browser, and that is the one way to lose it: the\n * cookies a plain Chrome saved are encrypted with a key in the login\n * keychain, Playwright's bundled browser and any mock keychain cannot read\n * them, and a browser that cannot read them starts the profile over,\n * signed out. `vos session exec` opens the profile the way every vos verb\n * does (the system Chrome, the real keychain) and hands the script the\n * context and a page; the profile is closed cleanly whatever the script\n * does.\n *\n * The script is an ES module whose default export is a function:\n *\n * export default async ({ context, page, url, name }) => {\n * await page.goto(url)\n * return await page.title()\n * }\n *\n * What it returns (JSON-serializable) is the command's result.\n */\nimport { existsSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport { pathToFileURL } from 'node:url'\nimport { withProfile } from './session'\nimport type { BrowserContext, Page } from 'playwright'\n\nexport interface ExecArgs {\n context: BrowserContext\n page: Page\n /** The `--url` given, when one was (the page is already on it). */\n url?: string\n /** The session's name. */\n name: string\n}\n\nexport type ExecScript = (args: ExecArgs) => unknown\n\n/** A script that could not run, said in words (exit 2). */\nexport class ExecScriptError extends Error {}\n\n/** Load the module and find its default function, in words when it has none. */\nexport async function loadExecScript(path: string): Promise<ExecScript> {\n const file = resolve(path)\n if (!existsSync(file)) throw new ExecScriptError(`no script at ${file}`)\n if (!/\\.(m?js|cjs)$/.test(file))\n throw new ExecScriptError(\n `${path}: a script is a .mjs or .js module (compile TypeScript first)`,\n )\n const mod = (await import(pathToFileURL(file).href)) as {\n default?: unknown\n }\n if (typeof mod.default !== 'function')\n throw new ExecScriptError(\n `${path} has no default export function: export default async ({ context, page, url }) => { … }`,\n )\n return mod.default as ExecScript\n}\n\n/**\n * Open the profile in `dir` as every vos verb does, run the script in it,\n * and close the profile, whatever the script does. The script's own error\n * is rethrown after the close.\n */\nexport async function execInProfile(\n dir: string,\n script: ExecScript,\n opts: {\n name: string\n url?: string\n headless?: boolean\n viewport?: { width: number; height: number }\n },\n): Promise<unknown> {\n return withProfile(\n dir,\n async (context) => {\n const page = context.pages()[0] ?? (await context.newPage())\n if (opts.url)\n await page.goto(opts.url, { waitUntil: 'load', timeout: 30000 })\n return await script({\n context,\n page,\n name: opts.name,\n ...(opts.url ? { url: opts.url } : {}),\n })\n },\n {\n headless: opts.headless ?? true,\n ...(opts.viewport ? { viewport: opts.viewport } : {}),\n },\n )\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 */\nimport { bearerFor } from './platform'\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 headers: bearerFor(key, origin),\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 {\n splitSegmentsAtSkips,\n withFittingExport,\n withPageSound,\n} from '@vosjs/render-core/record'\nimport { loadTake, writeJson } from './take'\nimport { footageOutputEnd, retimeCut, retimeOverlays } from './reuse'\nimport { proposeMotion } from './motionPlan'\nimport type { MotionProposalInput, ReleaseWords } from './motionPlan'\nimport type { ReuseReport } from './reuse'\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[]; held: 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 steps: m.meta.steps,\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 steps: m.meta.steps,\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 // Every cut an `await` made in the NEW footage is a segment boundary.\n doc.segments = splitSegmentsAtSkips(rt.segments, meta.skips)\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 steps: doc.source.meta.steps,\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 steps: doc.source.meta.steps,\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). A\n // layer pinned to a step is about that step and follows its new\n // output time, now that the cut's rate is final; an unpinned layer\n // over a step that moved is named in the report.\n if (prev.overlays?.length) {\n doc.overlays = retimeOverlays(prev, doc, rt.report)\n }\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 page's own sound is the NEW recording's: the previous take's\n // page clips go, the ones this take heard are placed.\n withPageSound(doc, meta.media)\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 // So are the ranges the cursor is off: they carry at their output\n // times, like an unpinned layer (a style copy never carries them), and\n // one that began after the footage (the end card's) keeps its distance\n // from the footage's end, which moves with the new recording's length.\n if (prev.cursor?.off?.length) {\n const oldEnd = footageOutputEnd(prev)\n const shift = footageOutputEnd(doc) - oldEnd\n doc.cursor = {\n ...doc.cursor,\n off: prev.cursor.off.map((r) =>\n r.in >= oldEnd - 1e-6 && Math.abs(shift) > 1e-6\n ? {\n ...r,\n in: +Math.max(0, r.in + shift).toFixed(3),\n ...(r.out !== undefined\n ? { out: +Math.max(0, r.out + shift).toFixed(3) }\n : {}),\n }\n : { ...r },\n ),\n }\n }\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 steps: doc.source.meta.steps,\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 steps: doc.source.meta.steps,\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 // An `await` waited off camera: the footage runs straight across the\n // wait, and the cut is a real segment boundary.\n doc.segments = splitSegmentsAtSkips(doc.segments, meta.skips)\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 steps: doc.source.meta.steps,\n })\n doc.speed = planAutoSpeed(doc.source.cursor, {\n durationMs: doc.source.meta.durationMs,\n params: doc.speedParams,\n activity,\n steps: doc.source.meta.steps,\n })\n // The footage decides the export a fresh doc opens on; a --style\n // reference's export is the series' choice and stays.\n if (!opts.style) withFittingExport(doc)\n fresh = true\n }\n\n // The sound the page played, placed under the footage it was heard over;\n // a re-plan replaces only those clips.\n withPageSound(doc, meta.media)\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 = {\n notes: proposed.notes,\n skipped: proposed.skipped,\n held: proposed.held,\n }\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. A span is re-timed against the STEP it was made\n * on whenever one can be found: an explicit `anchor` first, else the step\n * whose window held the span's start (or ended just before it), keeping\n * the span's offset from that step exactly. Only a span between steps\n * goes through the map.\n *\n * Report, never guess: every span that could not re-anchor cleanly is\n * NAMED in `flagged` with the reason in words — a vanished step (the span\n * that sat on it is dropped, with what it framed, never re-timed to a\n * place with nothing under it), a skipped selector, a span clamped or\n * dropped at the new take's edge. The agent fixes actions.json and\n * re-runs; the verb never silently invents a cut.\n *\n * Output-anchored layers keep their output second by contract (a title at\n * 1 s stays a title at 1 s). A layer PINNED to a step is about that step,\n * so it follows the step's new output time instead (`retimeOverlays`);\n * an unpinned layer that sat over a step which moved is named, with the\n * step's new time, so the person pins it or moves it.\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 {\n docFreezes,\n ratedSegments,\n resolveAnchor as resolveLayerAnchor,\n} from '@vosjs/studio-core'\nimport type {\n FreezeSpan,\n OverlayClip,\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/** A span starting this long after a step's end still belongs to it. */\nconst AFTER_STEP = 1\n/** A layer is about the press before it for longer: a callout lands a beat after. */\nconst LAYER_AFTER_STEP = 5\n/** Slack around a step's window, seconds. */\nconst WINDOW_SLACK = 0.05\n/** An unpinned layer whose step moved less than this is left unnamed. */\nconst LAYER_DRIFT = 0.5\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 * An unnamed old step by its place beside the NEAREST named one: the step\n * two after `zoomOut` is still two after `zoomOut` when a step was added\n * before it. Looked for from the named step before and the one after; the\n * verb and the selector must agree, and two answers that disagree are no\n * answer.\n */\nfunction matchByNeighbour(\n old: StepSpan,\n newSteps: readonly StepSpan[],\n oldSteps: readonly StepSpan[],\n): StepSpan | null {\n const named = oldSteps.filter(\n (s) => s.id && newSteps.some((n) => n.id === s.id && !n.skipped),\n )\n const before = named\n .filter((s) => s.step < old.step)\n .sort((a, b) => b.step - a.step)[0]\n const after = named\n .filter((s) => s.step > old.step)\n .sort((a, b) => a.step - b.step)[0]\n const found = [before, after].flatMap((anchor) => {\n if (!anchor) return []\n const now = newSteps.find((n) => n.id === anchor.id)!\n const hit = newSteps.find(\n (n) => n.step === now.step + old.step - anchor.step,\n )\n return hit &&\n !hit.skipped &&\n !hit.id &&\n hit.do === old.do &&\n hit.selector === old.selector\n ? [hit]\n : []\n })\n return found.length && found.every((h) => h === found[0]) ? found[0] : null\n}\n\n/**\n * Match an old step to a new one: by `id` when both carry one; else, for\n * an unnamed step, by its place beside the nearest named step; 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(\n old: StepSpan,\n newSteps: StepSpan[],\n oldSteps: readonly StepSpan[] = [],\n): 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 near = matchByNeighbour(old, newSteps, oldSteps)\n if (near) return near\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\n/** A step by the reference an anchor or a pin carries: an id, else an index. */\nfunction stepByRef(\n steps: readonly StepSpan[],\n ref: string | number,\n): StepSpan | undefined {\n return typeof ref === 'string'\n ? steps.find((s) => s.id === ref)\n : steps.find((s) => s.step === ref)\n}\n\nconst stepName = (s: StepSpan): string => String(s.id ?? s.step)\n\n/**\n * The step a SOURCE moment was made on: the gesture whose window holds it\n * (a wait is no gesture), else the gesture that ended within a second\n * before it. Null between steps.\n */\nexport function stepUnder(\n t: number,\n steps: readonly StepSpan[],\n after = AFTER_STEP,\n): StepSpan | null {\n const gestures = steps.filter((s) => s.do !== 'wait' && !s.skipped)\n const holding = gestures.find(\n (s) => s.tStart - WINDOW_SLACK <= t && t <= s.tEnd + WINDOW_SLACK,\n )\n if (holding) return holding\n const before = gestures\n .filter((s) => s.tEnd <= t && t - s.tEnd <= after)\n .sort((a, b) => b.tEnd - a.tEnd)\n return before[0] ?? 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, oldSteps)\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 = stepByRef(newSteps, 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 against a step: an explicit anchor, or the step they sat on. */\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\n/** What a span framed, for the words that name a dropped one. */\nfunction framed(span: object): string {\n const s = span as Partial<ZoomSpan & SpeedSpan & TiltSpan & FreezeSpan>\n if (typeof s.level === 'number' && typeof s.cx === 'number') {\n return ` (it framed ${s.cx.toFixed(2)}, ${(s.cy ?? 0).toFixed(2)} at ${s.level.toFixed(1)}×)`\n }\n if (typeof s.rate === 'number') return ` (${s.rate}× speed)`\n if (typeof s.rx === 'number' || typeof s.ry === 'number') {\n return ` (lean ${s.rx ?? 0}°, ${s.ry ?? 0}°)`\n }\n if (typeof s.seconds === 'number') return ` (a ${s.seconds} s hold)`\n return ''\n}\n\n/**\n * Where a SOURCE moment lands in the new recording, and how: through its\n * explicit anchor, through the step it sat on (offset kept exactly), else\n * through the map. Null means the step it was made on is gone from the\n * new recording — the moment is dropped and named by the caller.\n */\nfunction placeMoment(\n t: number,\n anchor: StepAnchor | undefined,\n ctx: {\n oldSteps: readonly StepSpan[]\n newSteps: StepSpan[]\n stepMap: StepMap\n report: ReuseReport\n },\n):\n | { at: number; via: 'anchor' | 'step' | 'map' }\n | { gone: StepSpan | string } {\n if (anchor) {\n const at = resolveAnchor(anchor, ctx.newSteps)\n if (at === null) return { gone: String(anchor.step) }\n ctx.report.anchored++\n return { at, via: 'anchor' }\n }\n const under = stepUnder(t, ctx.oldSteps)\n if (under) {\n const hit = matchStep(under, ctx.newSteps, ctx.oldSteps)\n if (!hit) return { gone: under }\n ctx.report.anchored++\n return { at: hit.tStart + (t - under.tStart), via: 'step' }\n }\n ctx.report.mapped++\n return { at: ctx.stepMap.map(t), via: 'map' }\n}\n\nconst goneWords = (gone: StepSpan | string): string =>\n typeof gone === 'string'\n ? `its anchored step (${gone}) is missing or skipped in the new recording`\n : `it sat on step ${stepName(gone)} (${gone.do}${gone.selector ? ` ${gone.selector}` : ''}), which is missing or skipped in the new recording`\n\nfunction retimeSpans<T extends SourceSpan>(\n kind: string,\n spans: T[],\n ctx: {\n oldSteps: readonly StepSpan[]\n newSteps: StepSpan[]\n stepMap: StepMap\n newDuration: number\n report: ReuseReport\n },\n opts: { overlap: 'trim' | 'keep' } = { overlap: 'trim' },\n): T[] {\n const out: T[] = []\n for (const span of spans) {\n const length = span.out - span.in\n const placed = placeMoment(span.in, span.anchor, ctx)\n if ('gone' in placed) {\n ctx.report.flagged.push(\n `${kind} ${span.id}: ${goneWords(placed.gone)} — dropped; re-aim it on the new footage${framed(span)}`,\n )\n continue\n }\n const nextIn = placed.at\n const nextOut = Math.min(nextIn + length, ctx.newDuration)\n const clampedIn = Math.max(0, Math.min(nextIn, ctx.newDuration))\n if (nextOut - clampedIn < MIN_SPAN) {\n ctx.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 out.sort((a, b) => a.in - b.in)\n // A deletion is a record of what was removed; two may cover the same\n // seconds, and trimming one away would let a deleted proposal return.\n if (opts.overlap === 'keep') return out\n // Playing spans must not overlap: trim a later span's head to its\n // neighbour's tail (a shifted step can squeeze two spans together).\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 ctx.report.flagged.push(\n `${kind} ${span.id}: fully overlapped ${prev.id} after re-timing — dropped`,\n )\n continue\n }\n ctx.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: see `retimeOverlays`, which runs\n * once the new cut's rate is final.\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 ${stepName(miss)} (${miss.do}${miss.selector ? ` ${miss.selector}` : ''}) has no match in the new recording — times near it interpolate`,\n )\n }\n const ctx = { oldSteps, newSteps, stepMap, newDuration, report }\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 ctx,\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 ctx,\n )\n const tilt = retimeSpans(\n 'tilt',\n (prev.tilt ?? []).filter((t) => t.source !== 'auto'),\n ctx,\n )\n // A freeze is a source MOMENT: its anchor or its step 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 const placed = placeMoment(f.at, f.anchor, ctx)\n if ('gone' in placed) {\n report.flagged.push(\n `freeze ${f.id}: ${goneWords(placed.gone)} — dropped; re-place it on the new footage${framed(f)}`,\n )\n continue\n }\n if (placed.at < 0 || placed.at > newDuration) {\n report.flagged.push(\n `freeze ${f.id}: lands outside the new recording (${placed.at.toFixed(2)}s) — dropped`,\n )\n continue\n }\n freeze.push({ ...f, at: +placed.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 // and two deletions may legitimately cover 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 ctx,\n { overlap: 'keep' },\n ),\n )\n }\n\n return { segments, zoom, speed, freeze, tilt, rejected, report }\n}\n\n/** OUTPUT seconds of a SOURCE moment through a rated piece list; a moment in cut footage snaps to the next kept piece. */\nfunction sourceToOutput(\n pieces: readonly { in: number; out: number; rate?: number }[],\n s: number,\n): number {\n let acc = 0\n for (const p of pieces) {\n const rate = p.rate && p.rate > 0 ? p.rate : 1\n const len = Math.max(0, p.out - p.in) / rate\n if (s < p.in) return acc\n if (s <= p.out) return acc + (s - p.in) / rate\n acc += len\n }\n return acc\n}\n\n/** SOURCE seconds of an OUTPUT moment through a rated piece list. */\nfunction outputToSource(\n pieces: readonly { in: number; out: number; rate?: number }[],\n t: number,\n): number {\n let acc = 0\n for (const p of pieces) {\n const rate = p.rate && p.rate > 0 ? p.rate : 1\n const len = Math.max(0, p.out - p.in) / rate\n if (acc + len >= t) return p.in + Math.max(0, t - acc) * rate\n acc += len\n }\n return pieces.at(-1)?.out ?? t\n}\n\n/**\n * The previous cut's layers onto the new cut, once its rate is final. A\n * layer pinned to a step keeps its offset from the step's OUTPUT time, so\n * a callout about a press plays when the press plays; a layer pinned to a\n * press (a source second) has the press re-timed and follows it the same\n * way; a layer pinned to a rect, or to nothing, keeps its output second,\n * and when the step under it moved by more than half a second the layer\n * is named with the step's new time, so the person pins it or moves it.\n */\n/**\n * Where the FOOTAGE ends in output seconds: the cut's length without the\n * freezes a template laid (an end card's, stamped `from`), which play\n * after the footage and carry the card's clips.\n */\nexport function footageOutputEnd(doc: ProjectDoc): number {\n const own: ProjectDoc = {\n ...doc,\n freeze: (doc.freeze ?? []).filter((f) => !f.from),\n }\n return ratedSegments(own).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\nexport function retimeOverlays(\n prev: ProjectDoc,\n next: ProjectDoc,\n report: ReuseReport,\n): OverlayClip[] {\n const overlays = prev.overlays ?? []\n if (!overlays.length) return []\n // A layer that played after the footage (an end card's words, a closing\n // line) stays after it: it keeps its distance from the footage's end,\n // which moves with the new recording's length.\n const oldEnd = footageOutputEnd(prev)\n const endShift = footageOutputEnd(next) - oldEnd\n const oldSteps = prev.source.meta.steps ?? []\n const newSteps = next.source.meta.steps ?? []\n const oldPieces = ratedSegments(prev)\n const newPieces = ratedSegments(next)\n const oldDuration = prev.source.meta.durationMs / 1000\n const newDuration = next.source.meta.durationMs / 1000\n const stepMap = buildStepMap(oldSteps, newSteps, oldDuration, newDuration)\n const ctx = { oldSteps, newSteps, stepMap, report }\n const follow = (\n o: OverlayClip,\n from: number,\n oldRef: number,\n newRef: number,\n ): OverlayClip & { start: number } => {\n const offset = from - sourceToOutput(oldPieces, oldRef)\n const start = Math.max(0, sourceToOutput(newPieces, newRef) + offset)\n return { ...o, start: +start.toFixed(3) }\n }\n return overlays.map((o) => {\n // Anchored to a step: the lowering re-reads it against the new steps;\n // its fallback `start` follows too, so the document says where it plays.\n // A layer with no fallback stays without one: its anchor is its time.\n if (o.anchor && typeof o.anchor === 'object') {\n const r = resolveLayerAnchor(next, o.anchor, newPieces)\n if (r.start === null) {\n report.flagged.push(\n o.start === undefined\n ? `overlay ${o.id}: anchored to step ${String(o.anchor.step)}, which is missing, skipped or cut in the new recording — it has no start to fall back to, so it plays nowhere; re-anchor it or give it a start`\n : `overlay ${o.id}: anchored to step ${String(o.anchor.step)}, which is missing, skipped or cut in the new recording — it plays at its fallback ${o.start.toFixed(2)}s; re-anchor or re-place it`,\n )\n return o\n }\n report.anchored++\n return o.start === undefined ? o : { ...o, start: r.start }\n }\n // Every layer without an anchor carries its start (validate refuses\n // one that does not).\n const at = o.start\n if (at === undefined) return o\n const pin = o.pin\n if (pin?.step !== undefined) {\n const was = stepByRef(oldSteps, pin.step)\n const now = was\n ? matchStep(was, newSteps, oldSteps)\n : stepByRef(newSteps, pin.step)\n if (!now || now.skipped) {\n report.flagged.push(\n `overlay ${o.id}: pinned to step ${String(pin.step)}, which is missing or skipped in the new recording — kept at ${at.toFixed(2)}s; re-pin or re-place it`,\n )\n return o\n }\n report.anchored++\n return follow(o, at, was?.tStart ?? now.tStart, now.tStart)\n }\n if (typeof pin?.press === 'number') {\n const placed = placeMoment(pin.press, undefined, ctx)\n if ('gone' in placed) {\n report.flagged.push(\n `overlay ${o.id}: pinned to a press at ${pin.press.toFixed(2)}s, and ${goneWords(placed.gone)} — kept at ${at.toFixed(2)}s; re-pin or re-place it`,\n )\n return o\n }\n const moved = follow(o, at, pin.press, placed.at)\n return { ...moved, pin: { ...pin, press: +placed.at.toFixed(3) } }\n }\n if (at >= oldEnd - 1e-6) {\n if (Math.abs(endShift) < 1e-6) return o\n return { ...o, start: +Math.max(0, at + endShift).toFixed(3) }\n }\n // Unpinned (or pinned to a rect): the output-time contract holds, and\n // a layer that sat over a step which moved is named.\n const under = stepUnder(\n outputToSource(oldPieces, at),\n oldSteps,\n LAYER_AFTER_STEP,\n )\n if (!under) return o\n const now = matchStep(under, newSteps, oldSteps)\n if (!now) {\n report.flagged.push(\n `overlay ${o.id} (${at.toFixed(2)}s): it sat over step ${stepName(under)}, which is missing or skipped in the new recording — kept at its output time; re-place it`,\n )\n return o\n }\n const expected = follow(o, at, under.tStart, now.tStart).start\n if (Math.abs(expected - at) > LAYER_DRIFT) {\n report.flagged.push(\n `overlay ${o.id} (${at.toFixed(2)}s): it sat over step ${stepName(under)}, which now plays at ${expected.toFixed(2)}s in the cut — kept at ${at.toFixed(2)}s by the output-time contract; pin it to follow (pin: { step: ${JSON.stringify(under.id ?? under.step)} }) or move it`,\n )\n }\n return o\n })\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 { embedScript, readScript, writeScriptBeside } from './takeScript'\nimport {\n claimablePasteFiles,\n readPasteFiles,\n sendPasteFiles,\n} from './pasteFiles'\nimport {\n docMediaRefs,\n fileSha256,\n isTakeRelativeKey,\n pullMedia,\n sourceSidecarRefs,\n takeRelativeFile,\n uploadDocRefs,\n} from './media'\nimport { MEDIA_HEAD_BYTES, nameForType, resolveMediaType } from './container'\nimport { resolvePushFolder } from './folder'\nimport { uploadAsset } from './uploadAsset'\nimport { looksLikeStorageState } from './session'\nimport { checkPlatformPlays } from './platformEngine'\nimport {\n apiJson,\n clientId,\n platformOrigin,\n readSyncState,\n requireCredential,\n serverWarnings,\n writeSyncState,\n detailLine,\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, platformOrigin(flags)),\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/** 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 /** The prompt that made it, shown on its watch page (the person's words). */\n prompt?: string\n /** Send fields the platform cannot play yet as what it reads (a copy). */\n bake?: boolean\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 // The files its script pastes travel with the take: read (and a file\n // from outside the take refused) before anything is asked or sent.\n const pasteFiles = await readPasteFiles(\n (await readScript(dir)) ?? take.doc.source.script,\n dir,\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, and\n // before anything is asked of the platform or done to the document.\n const firstPush = tracked === null\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 // Before anything uploads: can the platform play every field this take\n // uses? A refusal costs nothing; a platform that cannot say is warned of.\n const plays = await checkPlatformPlays(take.doc, {\n origin: ctx.origin,\n bake: flags.bake,\n })\n for (const line of plays.lines) r.log(line)\n const sendDoc = plays.doc as ProjectDoc\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 // A project address asks the server where it lands (continue or\n // start from); a bare slug or id is the caller's own shelf.\n const target = await resolvePushFolder(ctx.origin, ctx.key, flags.folder)\n folderId = target.id\n if (target.note) r.log(target.note)\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 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 // Said once the platform asks for the bytes: a re-push of a hosted\n // take sends none, and says only that it reused them.\n onSending: () => {\n if (filename !== take.paths.recordingName)\n r.log(\n ` ${take.paths.recordingName} holds ${contentType} — uploading it as ${filename}`,\n )\n r.log(`uploading recording (${Math.round(bytes.length / 1024)} kB)…`)\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(sendDoc)\n docForPush.source.videoKey = assetUrl\n embedScript(docForPush, dir)\n await sendPasteFiles(docForPush, pasteFiles, ctx, (l) => r.log(l))\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 ...(flags.prompt ? { prompt: flags.prompt } : {}),\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 if (flags.prompt) {\n const set = await api(ctx, `/vos/${state.vosId}`, {\n method: 'PATCH',\n body: { prompt: flags.prompt },\n })\n if (set.status !== 200)\n r.warn(\n `could not set the prompt (${set.status}): ${String(set.json.error ?? '')}${detailLine(set.json)}`,\n )\n }\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, and the\n // script that recorded it is written back, so it can be recorded again.\n const media = flags.media ? await pullMedia(ctx, dir, doc, r.log) : undefined\n if (flags.media && (await writeScriptBeside(dir, doc))) {\n r.log(' actions.json written from the document')\n }\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/**\n * A push refused for something the person can change (the command or the\n * take): exit 2, like every other refusal of that kind, in words that say\n * what to do instead.\n */\nexport class PushRefusedError extends Error {}\n\n/**\n * `vos push <take> --claimable`: a REMIX of a public take, pushed with no\n * account. The claim never takes footage, so every file the document names\n * must already be on vos.so: a file `vos fetch --media` brought home is\n * named by the address it came from (vos.json `hostedMedia`), and only\n * while its bytes are unchanged. Anything new is refused in words; the\n * platform checks the same rule again. The lineage is the vos the\n * directory was fetched from.\n */\nexport async function pushTakeClaimable(\n dir: string,\n flags: {\n api?: string\n origin?: string\n title?: string\n prompt?: string\n share?: boolean\n bake?: boolean\n },\n r: Reporter,\n): Promise<{\n id: string | null\n title: string\n claimUrl: string\n expiresAt: string\n}> {\n const stateFile = storageStateInDir(dir)\n if (stateFile)\n throw new PushRefusedError(\n `${stateFile} looks like a Playwright storage state (cookies + origins): a live session in the take directory would be sent with it. Move it out of the take and push again`,\n )\n const take = await loadTake(dir)\n if (!take.doc) {\n throw new PushRefusedError(\n 'no doc.json in this take — run `vos plan` first',\n )\n }\n const lint = lintDoc(take.doc)\n if (lint.problems.length) {\n throw new PushRefusedError(\n `doc.json fails lint:\\n ${lint.problems.join('\\n ')}`,\n )\n }\n const pasteFiles = await readPasteFiles(\n (await readScript(dir)) ?? take.doc.source.script,\n dir,\n )\n const state = readSyncState(dir)\n const hosted = state?.hostedMedia ?? {}\n // A claimable take is a remix of a public take brought home with its\n // media, which is the only footage a claim can name: a take recorded\n // here (or fetched without --media) has nothing it may carry. Refused\n // before anything is asked of the platform.\n if (!Object.keys(hosted).length)\n throw new PushRefusedError(\n `${dir} was not fetched from a public take with its media (its vos.json records no hosted files), and a claimable push never uploads footage. Push it with an account (vos login, then vos push ${dir}), or remix a public take: vos fetch <url> --media, edit, then vos push <dir> --claimable`,\n )\n // Every file the claim names is checked here, on this machine, before\n // anything is asked of the platform: each must be a file the take\n // fetched, unchanged since.\n const claimRefs = (doc: ProjectDoc) => [\n ...(isTakeRelativeKey(doc.source.videoKey)\n ? [\n {\n where: 'the recording',\n key: doc.source.videoKey,\n set: (next: string) => {\n doc.source.videoKey = next\n },\n },\n ]\n : []),\n ...sourceSidecarRefs(doc),\n ...docMediaRefs(doc),\n ]\n for (const ref of claimRefs(take.doc)) {\n const file = takeRelativeFile(ref.key)\n const origin = hosted[file]\n if (!origin) {\n throw new PushRefusedError(\n `${ref.where} (${file}) is not a file this take fetched from vos.so, and a claimable push never uploads footage. Push the take with an account (vos login, then vos push ${dir}), or remix a public take fetched with \\`vos fetch <url> --media\\``,\n )\n }\n const path = join(dir, file)\n const now = existsSync(path) ? await fileSha256(path) : null\n if (now !== origin.sha256) {\n throw new PushRefusedError(\n `${ref.where} (${file}) changed since it was fetched, so it is no longer the hosted file. A claimable push names only the original; push with an account to upload the new one`,\n )\n }\n }\n const plays = await checkPlatformPlays(take.doc, {\n origin: platformOrigin(flags),\n bake: flags.bake,\n })\n for (const line of plays.lines) r.log(line)\n const docForPush: ProjectDoc = structuredClone(plays.doc as ProjectDoc)\n embedScript(docForPush, dir)\n await claimablePasteFiles(docForPush, pasteFiles, hosted, (l) => r.log(l))\n // The document pushed names the hosted originals, checked above.\n for (const ref of claimRefs(docForPush)) {\n const origin = hosted[takeRelativeFile(ref.key)]\n if (!origin)\n throw new PushRefusedError(\n `${ref.where} (${takeRelativeFile(ref.key)}) is not a file this take fetched from vos.so, and a claimable push never uploads footage`,\n )\n ref.set(origin.ref)\n }\n\n const lowered = lowerToComposition(docForPush)\n const config = { ...lowered.config, data: lowered.data }\n const title = (\n flags.title ?? (state?.title ? `${state.title} remix` : basename(dir))\n ).slice(0, 200)\n const body: Record<string, unknown> = { title, config, doc: docForPush }\n if (state?.vosId) body.remixOfId = state.vosId\n if (flags.prompt) body.prompt = flags.prompt\n if (flags.share) body.share = true\n const origin = platformOrigin(flags)\n r.log(`creating a claimable push of ${title}…`)\n const res = await apiJson(origin, '/api/claim', { method: 'POST', body })\n if (res.status !== 201) {\n throw new Error(\n `claimable push failed (${res.status}): ${String(res.body.error ?? '')}${res.body.hint ? ` (${String(res.body.hint)})` : ''}`,\n )\n }\n serverWarnings(res.body, (l) => r.log(l))\n const created = (res.body.vos ?? {}) as { id?: string }\n return {\n id: created.id ?? null,\n title,\n claimUrl: String(res.body.claimUrl ?? ''),\n expiresAt: String(res.body.expiresAt ?? ''),\n }\n}\n","/**\n * The script travels with the take. `actions.json` is what makes a take\n * re-recordable, and a take fetched from vos.so used to come home without\n * it, so nobody but the directory's owner could ever record it again.\n * `vos push` embeds the script in the document (`source.script`) and\n * `vos fetch --media` / `vos pull --media` write it back beside the\n * recording — never over a script already on disk, which is the person's\n * working copy.\n *\n * The pure halves (`scriptFromText`, `scriptToWrite`) are unit-tested; the\n * two I/O wrappers are a read and a write.\n */\nimport { existsSync } from 'node:fs'\nimport { readFile, writeFile } from 'node:fs/promises'\nimport { readFileSync } from 'node:fs'\nimport { basename, join } from 'node:path'\nimport type { ProjectDoc } from '@vosjs/studio-core'\n\n/** The script as an object, or null for anything that is not one. */\nexport function scriptFromText(text: string): Record<string, unknown> | null {\n try {\n const v = JSON.parse(text) as unknown\n return v && typeof v === 'object' && !Array.isArray(v)\n ? (v as Record<string, unknown>)\n : null\n } catch {\n return null\n }\n}\n\n/**\n * The bytes to write as actions.json beside a fetched take, or null: the\n * document carries no script, or one is already on disk.\n */\nexport function scriptToWrite(\n doc: Pick<ProjectDoc, 'source'>,\n hasLocal: boolean,\n): string | null {\n const script = doc.source.script\n if (hasLocal || !script || typeof script !== 'object') return null\n return `${JSON.stringify(script, null, 2)}\\n`\n}\n\n/**\n * The script as it may travel: every setup and teardown value a person\n * typed replaced by a word, and every setup and teardown address stripped\n * to its origin and path. A setup exists to pass a sign-in and a teardown\n * to undo what a take created, so their literals are the one place a secret\n * is typed and their addresses the one place a magic link is pasted; a\n * pushed document is read by the fleet, by grants and, once public, by\n * anyone. An `{ env }` reference keeps its NAME, which is what a re-record\n * needs.\n */\nexport function publicScript(\n script: Record<string, unknown>,\n): Record<string, unknown> {\n const peers = publicPeers(script.peers)\n if (peers) script = { ...script, peers }\n for (const key of ['setup', 'teardown'] as const) {\n const steps = script[key]\n if (Array.isArray(steps))\n script = { ...script, [key]: steps.map(publicStep) }\n }\n return script\n}\n\n/** One off-camera step as it may travel: no typed literal, no query or hash. */\nfunction publicStep(step: unknown): unknown {\n if (!step || typeof step !== 'object') return step\n const s = step as Record<string, unknown>\n if (s.do === 'type' && typeof s.text === 'string')\n return { ...s, text: '[typed value not stored]' }\n if (s.do === 'goto' && typeof s.url === 'string') {\n try {\n const u = new URL(s.url)\n return { ...s, url: `${u.origin}${u.pathname}` }\n } catch {\n return s\n }\n }\n return s\n}\n\n/**\n * A peer's storage state named by its file name only: the path is this\n * machine's (a home directory, a user name in it), and a re-record\n * elsewhere names its own.\n */\nfunction publicPeers(peers: unknown): unknown[] | null {\n if (!Array.isArray(peers)) return null\n return peers.map((p: unknown) => {\n if (!p || typeof p !== 'object') return p\n const peer = p as Record<string, unknown>\n if (typeof peer.storageState !== 'string') return peer\n return { ...peer, storageState: basename(peer.storageState) }\n })\n}\n\n/** Embed the take directory's actions.json into the document about to be pushed. */\nexport function embedScript(doc: ProjectDoc, dir: string): void {\n const path = join(dir, 'actions.json')\n if (!existsSync(path)) return\n const script = scriptFromText(readFileSync(path, 'utf8'))\n if (script) doc.source.script = publicScript(script)\n}\n\n/** Write the document's script beside the take when none is there; true when written. */\nexport async function writeScriptBeside(\n dir: string,\n doc: Pick<ProjectDoc, 'source'>,\n): Promise<boolean> {\n const path = join(dir, 'actions.json')\n const text = scriptToWrite(doc, existsSync(path))\n if (text === null) return false\n await writeFile(path, text, 'utf8')\n return true\n}\n\n/** Read a take's script, or null when there is none. */\nexport async function readScript(\n dir: string,\n): Promise<Record<string, unknown> | null> {\n const path = join(dir, 'actions.json')\n if (!existsSync(path)) return null\n return scriptFromText(await readFile(path, 'utf8'))\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 } from 'node:fs/promises'\nimport { safePathName } from './pathName'\nimport { writeFileSafe } from './safeWrite'\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\n/**\n * A project ADDRESS, `<handle>/<slug>` (an `@` before the handle is\n * allowed): anyone's project, as its page on vos.so names it. Null for a\n * bare id or slug, which names a project on the caller's own shelf.\n */\nexport function projectAddress(\n ref: string,\n): { handle: string; slug: string } | null {\n const m = /^@?([A-Za-z0-9_]{1,30})\\/([A-Za-z0-9][\\w-]{0,99})$/.exec(\n ref.trim(),\n )\n return m ? { handle: m[1], slug: m[2].toLowerCase() } : null\n}\n\nexport interface PushFolder {\n id: string\n /** What the push will do there, in words for the person; null on your own shelf. */\n note: string | null\n}\n\n/**\n * Where a CREATED vos is filed. A bare id or slug names a project on the\n * caller's own shelf, as it always has. A project address asks the server\n * where a push meant for that project lands, because the answer depends on\n * the credential: its owner CONTINUES the project; anyone else STARTS FROM\n * it, in a private project of their own made once, named after it, with its\n * recipes copied in. The CLI never decides which.\n */\nexport async function resolvePushFolder(\n origin: string,\n key: string,\n ref: string,\n): Promise<PushFolder> {\n const at = projectAddress(ref)\n if (!at) {\n return {\n id: resolveFolder(await listFolders(origin, key), ref).id,\n note: null,\n }\n }\n const r = await apiJson(\n origin,\n `/api/folders/public/${encodeURIComponent(at.handle)}/${encodeURIComponent(at.slug)}/push-target`,\n { method: 'POST', key },\n )\n if (r.status !== 200 && r.status !== 201) {\n throw new Error(apiError(`find the project ${at.handle}/${at.slug}`, r))\n }\n const body = r.body as {\n target?: string\n created?: boolean\n recipes?: number\n folder?: { id: string; slug: string; name: string }\n source?: { name: string }\n }\n if (!body.folder) {\n throw new Error(\n `find the project ${at.handle}/${at.slug}: no project in the answer`,\n )\n }\n const source = body.source?.name ?? `${at.handle}/${at.slug}`\n const note =\n body.target === 'continue'\n ? `continuing ${source}`\n : body.created\n ? `starting your own ${source} (${body.folder.slug}), its ${body.recipes ?? 0} recipe${body.recipes === 1 ? '' : 's'} copied in`\n : `adding to your own ${source} (${body.folder.slug})`\n return { id: body.folder.id, note }\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\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 // Every name the server chose becomes a path here, so each is held to a\n // plain lowercase segment, with the row's id standing in for an empty one.\n const safeName = (v: string | undefined, id: string) =>\n safePathName((v ?? '').toLowerCase(), id)\n const out = strFlag(flags, 'out') ?? safeName(folder.slug, folder.id)\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, rec.id))\n await writeFileSafe(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', '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, rec.id),\n )\n await writeFileSafe(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 writeFileSafe(\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 writeFileSafe(\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 * Can the platform play what this take uses?\n *\n * A CLI release can teach the document a field (a caption anchored to a\n * step, a loudness target on a clip) days before the hosting platform runs\n * the `@vosjs/studio-core` release that reads it. A push lowers the take\n * HERE, so the program the platform plays from the push is right; but the\n * platform keeps the document too, and its studio lowers that document\n * again with its own release when the take is opened, and every version\n * saved from the studio (a person's save, an autosave checkpoint) stores\n * that lowering. An older release skips a field it does not know, without\n * a word, so the take is right until somebody opens it there.\n *\n * So a push reads the platform's release (`GET <origin>/api/engine`, public,\n * `{ studioCore, core }`) and refuses, in words, a take that uses a feature\n * newer than it (studio-core's feature table), unless `--bake` says those\n * features in what the older release reads, on the copy that is sent. An\n * unreadable answer (no such endpoint, a refusal, a timeout) never blocks a\n * push: it warns and goes ahead.\n */\nimport { bakeDocFeatures, featuresNewerThan } from '@vosjs/studio-core'\nimport type { StudioDoc, UsedFeature } from '@vosjs/studio-core'\n\n/** The platform's renderer, as `GET /api/engine` answers it. */\nexport interface PlatformEngine {\n studioCore: string\n core?: string\n}\n\n/** How long a push waits for the answer, ms. */\nexport const ENGINE_TIMEOUT_MS = 2000\n\nconst VERSION = /^\\d+\\.\\d+\\.\\d+([-+].*)?$/\n\n/** Read the platform's releases; a reason in words when they cannot be read. */\nexport async function readPlatformEngine(\n origin: string,\n fetchImpl: typeof fetch = fetch,\n timeoutMs = ENGINE_TIMEOUT_MS,\n): Promise<{ engine: PlatformEngine } | { unknown: string }> {\n const url = `${origin.replace(/\\/+$/, '')}/api/engine`\n const ctl = new AbortController()\n const timer = setTimeout(() => ctl.abort(), timeoutMs)\n try {\n const res = await fetchImpl(url, {\n signal: ctl.signal,\n headers: { accept: 'application/json' },\n })\n if (!res.ok) return { unknown: `GET ${url} answered ${res.status}` }\n const body = (await res.json()) as Record<string, unknown>\n const v = body?.studioCore\n if (typeof v !== 'string' || !VERSION.test(v.trim()))\n return { unknown: `GET ${url} named no studio-core release` }\n return {\n engine: {\n studioCore: v.trim(),\n ...(typeof body.core === 'string' ? { core: body.core } : {}),\n },\n }\n } catch (e) {\n return {\n unknown: ctl.signal.aborted\n ? `GET ${url} did not answer within ${timeoutMs / 1000} s`\n : `GET ${url} failed (${e instanceof Error ? e.message : String(e)})`,\n }\n } finally {\n clearTimeout(timer)\n }\n}\n\n/** A take that uses what the platform cannot play yet: exit 2, in words. */\nexport class PlatformBehindError extends Error {}\n\nconst listOf = (words: string[]): string =>\n words.length <= 1\n ? (words[0] ?? '')\n : `${words.slice(0, -1).join(', ')} and ${words[words.length - 1]}`\n\n/** The refusal, in words. */\nexport function behindMessage(\n used: readonly UsedFeature[],\n platform: string,\n host: string,\n bake: boolean,\n): string {\n const named = (u: UsedFeature) =>\n `${u.feature.name} (studio-core ${u.feature.since})`\n const head =\n used.length === 1\n ? `this take uses ${named(used[0])}; ${host} renders with ${platform}, and its studio ${used[0].feature.before}, as would every version saved there.`\n : `this take uses fields ${host} cannot play yet; it renders with ${platform}, and its studio, and every version saved there, would get them wrong: ${used.map((u) => `${named(u)} ${u.feature.before}`).join('; ')}.`\n const cannot = used.filter((u) => !u.feature.bake).map((u) => u.feature.name)\n if (bake)\n return `${head} --bake cannot say ${listOf(cannot)} in what ${platform} reads; push again when ${host} updates`\n if (!cannot.length)\n return `${head} Push again when ${host} updates, or bake them: vos push --bake`\n return `${head} Push again when ${host} updates (${listOf(cannot)} cannot be baked).`\n}\n\nexport interface PushCheck {\n /** The document to send: the take's own, or its baked copy. */\n doc: StudioDoc\n /** Said on the way (a platform that could not be read, what a bake changed). */\n lines: string[]\n /** The features baked into the copy. */\n baked: string[]\n}\n\n/**\n * The check a take push makes before anything is sent. Throws\n * PlatformBehindError on a take the platform cannot play yet (unless\n * `bake` can say every such feature); never on a network failure.\n *\n * `bake` is the person's choice to send a copy ANY renderer plays, so it\n * bakes every feature the take uses that can be baked, whatever the check\n * found: a platform behind, current, or one that could not say.\n */\nexport async function checkPlatformPlays(\n doc: StudioDoc,\n opts: { origin: string; bake?: boolean; fetchImpl?: typeof fetch },\n): Promise<PushCheck> {\n const host = hostOf(opts.origin)\n const read = await readPlatformEngine(opts.origin, opts.fetchImpl)\n const platform = 'engine' in read ? read.engine.studioCore : null\n const newer = platform ? featuresNewerThan(doc, platform) : []\n if (\n platform &&\n newer.length &&\n (!opts.bake || newer.some((u) => !u.feature.bake))\n )\n throw new PlatformBehindError(\n behindMessage(newer, platform, host, !!opts.bake),\n )\n const unread =\n 'unknown' in read\n ? `could not read which studio-core ${host} renders with (${read.unknown}); `\n : ''\n if (!opts.bake)\n return {\n doc,\n lines: unread\n ? [\n `${unread}pushing without checking that it plays every field this take uses`,\n ]\n : [],\n baked: [],\n }\n // Every bakeable feature, against the oldest release there is.\n const r = bakeDocFeatures(doc, '0.0.0')\n const against = platform\n ? `${host} renders with ${platform}`\n : `${host} could not say what it renders with`\n return {\n doc: r.doc,\n lines: [\n ...(unread ? [`${unread}baking every field --bake can say`] : []),\n r.baked.length\n ? `baked: ${listOf(r.baked.map((f) => f.name))} (${against}; the copy sent, doc.json untouched)`\n : `baked: nothing, this take uses no field --bake says (${against})`,\n ...r.notes.map((n) => ` ${n}`),\n ],\n baked: r.baked.map((f) => f.id),\n }\n}\n\nfunction hostOf(origin: string): string {\n try {\n return new URL(origin).host\n } catch {\n return origin\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 } from 'node:fs/promises'\nimport { safePathName } from './pathName'\nimport { writeFileSafe } from './safeWrite'\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 promptHint,\n readSyncState,\n requireCredential,\n resolveCredential,\n mintAt,\n serverWarnings,\n writeCredential,\n writeSyncState,\n} from './platform'\nimport { programPushTarget } from './sync'\nimport { hostedAssetId, manifestRefs } from '../programAssets'\nimport { resolvePushFolder } from './folder'\nimport {\n docLayerRefs,\n pullMedia,\n recordHostedMedia,\n uploadDocRefs,\n} from './media'\nimport { codeFileWarnings, liftNamedFiles, localDataRefs } from './programFiles'\nimport {\n hostedLiteralWarnings,\n localManifestRefs,\n pullManifest,\n uploadManifest,\n} from './assetManifest'\nimport { lintDoc } from './validateDoc'\nimport { writeScriptBeside } from './takeScript'\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'\nimport type { UploadTarget } from './uploadAsset'\n\nconst BOOLEAN_FLAGS = new Set([\n 'json',\n 'help',\n 'media',\n 'check',\n 'yes',\n 'claimable',\n 'share',\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 // The slug is the server's word; as a directory name it is held to a\n // plain path segment, and the id stands in when nothing of it is left.\n const out = strFlag(flags, 'out') ?? safePathName(slug, vosId)\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 writeFileSafe(\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 writeFileSafe(\n join(out, 'config.json'),\n JSON.stringify(own, null, 2),\n )\n }\n } else if (doc.status === 200) {\n take = true\n const hosted = migrateHostedDoc(doc.body) as unknown as ProjectDoc\n await writeFileSafe(\n join(out, 'doc.json'),\n JSON.stringify(hosted, null, 2),\n )\n if (flags.media === true) {\n const media = await pullMedia({ origin, key }, out, hosted, r.log)\n await recordHostedMedia(out, vosId, media)\n // The script that recorded the take comes home with its footage,\n // so the take can be recorded again from this directory.\n if (await writeScriptBeside(out, hosted)) {\n r.log(' actions.json written from the document')\n }\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 writeFileSafe(\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 /** The prompt that made it, shown on its watch page (the person's words). */\n prompt?: string\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.prompt) body.prompt = opts.prompt\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|handle/slug>] [--remix-of id] [--note n] [--label l] [--base versionId] [--override id]... [--prompt \"<the prompt that made it>\"] [--claimable [--share]]',\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 // The prompt that made it, shown on the watch page: only what the person\n // said may be shown, so it is never filled in for them.\n const prompt = strFlag(flags, 'prompt')\n if (flags.share === true && flags.claimable !== true) {\n throw new UsageError(\n '--share asks a claimable push to lead its claim page with \"Claim and share\". A key can never publish: open the watch page and set it to Unlisted or Public there',\n )\n }\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.warn(w)\n for (const w of codeFileWarnings(config, dir)) r.warn(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.warn(`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, and every file the program names rides with it: the\n // claim's own upload session carries them through the same door a key\n // uses, under the claim's caps (12 files, 50 MB). The session token is\n // the bearer and the claim spends it.\n const files = await collectFiles(config, programDoc, dir, r)\n let uploadToken: string | undefined\n if (files.count > 0) {\n const opened = await apiJson(origin, '/api/claim/uploads', {\n method: 'POST',\n })\n if (opened.status !== 201) {\n throw new Error(apiError('open a claim upload session', opened))\n }\n uploadToken = String(opened.body.uploadToken)\n r.log(\n `uploading ${files.count} file${files.count === 1 ? '' : 's'} with the claim`,\n )\n await files.upload({\n origin,\n key: uploadToken,\n door: '/api/claim/uploads/files',\n })\n }\n const body: Record<string, unknown> = {\n title,\n config: storedProgramConfig(config, programDoc),\n }\n if (uploadToken) body.uploadToken = uploadToken\n if (prompt) body.prompt = prompt\n if (flags.share === true) body.share = true\n // Lineage: --remix-of, else the vos this directory was fetched from, so\n // a fetch -> edit -> claimable push credits its source with no flag. The\n // server keeps it only while that source is public or unlisted.\n const remixOf = strFlag(flags, 'remix-of')\n const remixOfId = remixOf ? parseVosId(remixOf) : state?.vosId\n if (remixOfId) body.remixOfId = remixOfId\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, say(r))\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 {\n id: created.id ?? null,\n title,\n claimUrl,\n expiresAt,\n ...(uploadToken ? { files: files.count } : {}),\n },\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 // Every file the program names, still local: the document's layers\n // (picture and video overlays, 3D props, sound), the manifest, and what\n // elements, fonts and data name, lifted or rewritten so one upload\n // carries them. The config object and the document leave with hosted\n // refs; the files on disk keep their paths.\n const files = await collectFiles(config, programDoc, dir, r)\n await files.upload({ origin, key })\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, say(r))\n if (prompt) {\n const set = await apiJson(origin, `/api/vos/${vosId}`, {\n method: 'PATCH',\n key,\n body: { prompt },\n })\n if (set.status !== 200) r.warn(apiError('set the prompt', set))\n }\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: say(r),\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 // A project address asks the server where it lands (continue or start\n // from); a bare slug or id is the caller's own shelf.\n const pushFolder = folderRef\n ? await resolvePushFolder(origin, key, folderRef)\n : undefined\n const folderId = pushFolder?.id\n if (pushFolder?.note) r.log(pushFolder.note)\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 prompt,\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: say(r),\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 ...(pushFolder?.note ? { folderNote: pushFolder.note } : {}),\n remixOfId: remixOfId ?? null,\n currentVersionId: created.currentVersionId,\n watchUrl,\n studioUrl,\n prompt: prompt ?? null,\n ...(prompt ? {} : { promptHint: promptHint(source, created.id) }),\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}${pushFolder?.note ? ` (${pushFolder.note})` : ''}` : `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 (prompt\n ? ` prompt: shown on the watch page\\n`\n : ` prompt: none shown; show the one that made it: ${promptHint(source, created.id)}\\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 // Read up front: an up-to-date pull returns before the check branch, and a\n // flag read nowhere on that path is reported as ignored.\n const check = flags.check === true\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 (check) {\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 writeFileSafe(\n join(dir, 'config.backup.json'),\n await readFile(configPath),\n )\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 writeFileSafe(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 ${mintAt(origin)}`,\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, origin)\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 reporter's log, with the lines that are warnings sent as warnings. */\nfunction say(r: Reporter): (line: string) => void {\n return (line) => {\n const m = /^\\s*warning\\s+(.*)$/s.exec(line)\n if (m) r.warn(m[1])\n else r.log(line)\n }\n}\n\n/**\n * Every local file a program names, ready to upload through one target:\n * the document's layers, the manifest (with what elements and fonts name\n * lifted into it), and the paths in `data`. `count` is how many files\n * will cross; `upload` sends them and rewrites the refs in place.\n */\nasync function collectFiles(\n config: Record<string, unknown>,\n programDoc: Record<string, unknown> | null,\n dir: string,\n r: Reporter,\n): Promise<{ count: number; upload: (target: UploadTarget) => Promise<void> }> {\n for (const line of liftNamedFiles(config, dir)) r.log(` ${line}`)\n const docRefs = programDoc ? docLayerRefs(layersOf(programDoc)) : []\n const dataRefs = localDataRefs(config, dir)\n const count =\n docRefs.length + localManifestRefs(config).length + dataRefs.length\n return {\n count,\n upload: async (target) => {\n await uploadDocRefs(docRefs, dir, target, say(r))\n await uploadManifest(config, dir, target, say(r))\n await uploadDocRefs(dataRefs, dir, target, say(r))\n },\n }\n}\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 writeFileSafe(\n docPath,\n JSON.stringify({ ...doc, still: t }, null, 2) + '\\n',\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 writeFileSafe(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 * The files a program names OUTSIDE its manifest, made to cross too.\n *\n * A push used to carry two kinds of local file: the ones `config.assets`\n * declares and the ones a program document's layers key. A picture an\n * element names as `src`, a face in `config.fonts`, a path in `config.data`\n * went up as written, so every hosted page resolved it against its own\n * address and loaded that page instead of the file, with no word said.\n *\n * Now each is carried. An element's file and a font's file are LIFTED into\n * the manifest (the element then names `\"$assets.<name>\"`), so the one\n * manifest upload carries them and every surface resolves them the way it\n * resolves any declared file. A path in `data` is uploaded and rewritten to\n * the hosted file's path, which the platform already resolves per surface.\n * A path typed inside a function cannot be rewritten; it is said, with the\n * fix. Only the in-memory config changes; the files on disk keep their\n * paths.\n */\nimport { basename, extname, relative } from 'node:path'\nimport { existsSync, realpathSync } from 'node:fs'\nimport { localFile } from '../programAssets'\nimport type { DocMediaRef } from './media'\n\n/**\n * A file on this machine, rather than something a hosted page loads as\n * written (a URL, a hosted file, a binding resolved later). A path that\n * starts with `/` is an app path on a hosted page, unless it names a file\n * on this disk, which is what an agent writing an absolute path meant.\n * Inline SVG markup is the picture itself, never a name.\n */\nfunction isLocalName(value: string): boolean {\n if (/^(https?:|data:|blob:|asset:|media:)/.test(value)) return false\n if (value.startsWith('$')) return false\n if (value.startsWith('<svg') || value.startsWith('<?xml')) return false\n if (value.startsWith('/')) return existsSync(value)\n return true\n}\n\n/** The kinds of file a program draws with, by extension. */\nconst FILE_EXT =\n /\\.(png|jpe?g|webp|gif|avif|svg|mp4|webm|mov|mp3|m4a|ogg|wav|flac|aac|glb|gltf|woff2?|ttf|otf|hdr|exr)$/i\n\ntype Manifest = Record<string, { ref: string | string[]; kind?: string }>\n\n/** A manifest name from a file name: an identifier, unique in the manifest. */\nfunction manifestName(file: string, taken: Set<string>): string {\n const stem =\n basename(file, extname(file))\n .replace(/[^A-Za-z0-9_]/g, '_')\n .replace(/^(?=[0-9])/, '_') || 'file'\n let name = stem\n for (let n = 2; taken.has(name); n++) name = `${stem}_${n}`\n taken.add(name)\n return name\n}\n\n/**\n * Lift the local files an element (`src`) or a font (`url`) names into the\n * manifest, and point them at it. Returns where each came from. A path that\n * leaves the program's directory is refused the way the manifest refuses\n * it; a path naming no file is left as is (the platform says so).\n */\nexport function liftNamedFiles(\n config: Record<string, unknown>,\n dir: string,\n): string[] {\n const manifest = (config.assets ?? {}) as Manifest\n const taken = new Set(Object.keys(manifest))\n const lifted: string[] = []\n const lift = (where: string, value: unknown, kind?: string) => {\n if (typeof value !== 'string' || !value || !isLocalName(value)) return null\n const found = localFile(value, dir)\n if ('refused' in found) {\n if (found.refused.startsWith('which is outside')) {\n throw new Error(`${where} names ${value}, ${found.refused}`)\n }\n return null\n }\n const name = manifestName(value, taken)\n manifest[name] = kind ? { ref: value, kind } : { ref: value }\n lifted.push(`${where} → assets.${name}`)\n return `$assets.${name}`\n }\n const elements = Array.isArray(config.elements) ? config.elements : []\n elements.forEach((el, i) => {\n const e = el as Record<string, unknown>\n if (!e || e.type === 'text') return\n const next = lift(`elements[${i}].src`, e.src)\n if (next) e.src = next\n })\n const fonts = Array.isArray(config.fonts) ? config.fonts : []\n fonts.forEach((f, i) => {\n const font = f as Record<string, unknown>\n const next = lift(`fonts[${i}].url`, font?.url, 'font')\n if (next) font.url = next\n })\n if (lifted.length) config.assets = manifest\n return lifted\n}\n\n/**\n * The local files `config.data` names, as refs an uploader rewrites to the\n * hosted file's path. Only a string that IS a file beside the config with a\n * media extension: a word in `data` is text, not a path.\n */\nexport function localDataRefs(\n config: Record<string, unknown>,\n dir: string,\n): DocMediaRef[] {\n const refs: DocMediaRef[] = []\n const root = realpathSync(dir)\n const walk = (value: unknown, where: string, set: (v: string) => void) => {\n if (typeof value === 'string') {\n if (!isLocalName(value) || !FILE_EXT.test(value)) return\n const found = localFile(value, dir)\n if ('refused' in found) return\n refs.push({ where, key: relative(root, found.file), set })\n return\n }\n if (Array.isArray(value)) {\n value.forEach((v, i) =>\n walk(v, `${where}[${i}]`, (next) => {\n value[i] = next\n }),\n )\n return\n }\n if (value && typeof value === 'object') {\n const obj = value as Record<string, unknown>\n for (const k of Object.keys(obj)) {\n walk(obj[k], `${where}.${k}`, (next) => {\n obj[k] = next\n })\n }\n }\n }\n walk(config.data, 'data', () => {})\n return refs\n}\n\nconst FUNCTION_FIELDS = ['setup', 'createContent', 'createTimeline', 'onFrame']\nconst QUOTED = /(['\"`])([^'\"`\\n]{1,200}?)\\1/g\n\n/**\n * A local file typed inside a function. Nothing can rewrite a string in\n * code, so no push carries it: one line per file, with the fix.\n */\nexport function codeFileWarnings(\n config: Record<string, unknown>,\n dir: string,\n): string[] {\n const out: string[] = []\n const seen = new Set<string>()\n const scan = (label: string, src: unknown) => {\n if (typeof src !== 'string') return\n for (const m of src.matchAll(QUOTED)) {\n const value = m[2]\n if (seen.has(value) || !isLocalName(value) || !FILE_EXT.test(value)) {\n continue\n }\n if ('refused' in localFile(value, dir)) continue\n seen.add(value)\n out.push(\n `${label} names ${value} in code, which no push can carry. Declare it: \"assets\": { \"name\": { \"ref\": \"${value}\" } }, and read ctx.assets.name`,\n )\n }\n }\n for (const field of FUNCTION_FIELDS) scan(field, config[field])\n return out\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 * vos asset import <url> [--name <file>] [--folder <slug>]\n * [--license <text>] [--attribution <text>] [--json]\n * vos assets ls [--kind <kind>] [--folder <slug>] [--q <text>]\n * [--sort recent|size|name] [--limit <n>] [--json]\n * vos assets usage [--json]\n * vos assets why <assetId> [--json]\n *\n * `vos assets` and `vos asset` are one verb: the plural reads better for\n * the three that look at the collection.\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 {\n alignRows,\n bytesWords,\n listRow,\n manifestLine,\n nameFromUrl,\n probeLine,\n} from './assetWords'\nimport { hostedFile } from './assetWords'\nimport type { HostedFile } from './assetWords'\nimport { fetchPublic, fetchRefusal } from './netAddress'\nimport { uploadAsset } from './uploadAsset'\nimport { UsageError, numFlag, 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 ref: string\n size: number\n duration?: number\n metadata?: Record<string, unknown>\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 ref: put.ref,\n size: put.size,\n ...(put.duration ? { duration: put.duration } : {}),\n ...(put.metadata ? { metadata: put.metadata } : {}),\n ...(put.reused ? { reused: true as const } : {}),\n ...(put.notes.length ? { notes: put.notes } : {}),\n })\n const hosted = {\n id: put.id,\n kind: put.kind,\n filename: stored,\n size: put.size,\n duration: put.duration,\n metadata: put.metadata,\n }\n r.log(\n `uploaded ${stored}${put.reused ? ' — already yours, nothing sent' : ''}`,\n )\n // What the platform read, the two ways to name the file, and the line\n // that declares it in a program's \"assets\".\n r.log(` ${probeLine(hosted)}, ${bytesWords(put.size)}`)\n r.log(` ${put.ref} ${put.url}`)\n r.log(` ${manifestLine(hosted)}`)\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\n/** A bytes cap for one imported file: it is held in memory to be sent. */\nconst IMPORT_MAX_BYTES = 512 * 1024 * 1024\n\n/**\n * Bring a file in from an address, with where it came from kept beside it.\n * The CLI fetches it (so it is this machine's network, never the\n * platform's, that reaches the address) and sends it through the upload\n * door like any other file.\n */\nasync function cmdImport(argv: string[]): Promise<number> {\n const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS)\n const [url] = positionals\n if (!url || !/^https?:\\/\\//i.test(url)) {\n throw new UsageError(\n 'vos asset import <http(s) url> [--name <file>] [--folder <slug>] [--license <text>] [--attribution <text>]',\n )\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 // An address on this machine's own network is refused before anything\n // is fetched, and so is a redirect landing on one.\n const refused = fetchRefusal(url)\n if (refused) throw new UsageError(`import: ${refused}`)\n r.log(`fetching ${url}`)\n const res = await fetchPublic(url)\n if (!res.ok)\n throw new Error(`import ${url}: the address answered ${res.status}`)\n const declared = Number(res.headers.get('content-length') ?? 0)\n if (declared > IMPORT_MAX_BYTES) {\n throw new Error(\n `import ${url}: ${bytesWords(declared)} is over the ${bytesWords(IMPORT_MAX_BYTES)} an import carries. Download it and use vos asset push`,\n )\n }\n const body = new Uint8Array(await res.arrayBuffer())\n if (body.length > IMPORT_MAX_BYTES) {\n throw new Error(\n `import ${url}: ${bytesWords(body.length)} is over the ${bytesWords(IMPORT_MAX_BYTES)} an import carries. Download it and use vos asset push`,\n )\n }\n const name = strFlag(flags, 'name') ?? nameFromUrl(res.url || url)\n const license = strFlag(flags, 'license')\n const attribution = strFlag(flags, 'attribution')\n let put\n try {\n put = await uploadAsset({ origin, key }, body, {\n filename: name,\n contentHash: createHash('sha256').update(body).digest('hex'),\n intent: 'library',\n ...(folder ? { folderId: folder.id } : {}),\n provenance: {\n sourceUrl: res.url || url,\n ...(license ? { license } : {}),\n ...(attribution ? { attribution } : {}),\n },\n })\n } catch (e) {\n throw new Error(\n `import ${name}: ${e instanceof Error ? e.message : String(e)}`,\n )\n }\n const hosted = {\n id: put.id,\n kind: put.kind,\n filename: put.filename || name,\n size: put.size,\n duration: put.duration,\n metadata: put.metadata,\n }\n if (!license) {\n r.log(\n 'note: no --license was given. Say what lets you use this file, so the next person can tell',\n )\n }\n r.done(\n {\n id: put.id,\n filename: hosted.filename,\n kind: put.kind,\n url: put.url,\n ref: put.ref,\n size: put.size,\n sourceUrl: res.url || url,\n ...(license ? { license } : {}),\n ...(attribution ? { attribution } : {}),\n ...(put.reused ? { reused: true } : {}),\n ...(put.notes.length ? { notes: put.notes } : {}),\n folder: folder?.slug ?? null,\n },\n `imported ${hosted.filename}${put.reused ? ' — already yours, nothing sent' : ''}\\n ${probeLine(hosted)}, ${bytesWords(put.size)}\\n ${put.ref} ${put.url}\\n ${manifestLine(hosted)}`,\n )\n return EXIT_OK\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 params = new URLSearchParams({\n limit: String(Math.min(200, Math.max(1, numFlag(flags, 'limit', 50)))),\n })\n for (const name of ['kind', 'q', 'sort', 'scope']) {\n const value = strFlag(flags, name)\n if (value) params.set(name, value)\n }\n const folderRef = strFlag(flags, 'folder')\n if (folderRef) {\n params.set(\n 'folder',\n folderRef === 'none'\n ? 'none'\n : resolveFolder(await listFolders(origin, key), folderRef).id,\n )\n }\n const res = await apiJson(origin, `/api/assets?${params}`, { key })\n if (res.status !== 200) throw new Error(apiError('list assets', res))\n const assets = ((res.body.assets ?? []) as unknown[]).map(hostedFile)\n const total =\n typeof res.body.total === 'number' ? res.body.total : assets.length\n r.done(\n { assets, total, kinds: res.body.kinds ?? {} },\n assets.length === 0\n ? 'no files'\n : `${alignRows(assets.map(listRow)).join('\\n')}\\n${assets.length} of ${total} file${total === 1 ? '' : 's'}${\n total > assets.length ? ' (--limit for more, --q to search)' : ''\n }`,\n )\n return EXIT_OK\n}\n\nasync function cmdUsage(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 res = await apiJson(origin, '/api/user/usage', { key })\n if (res.status !== 200) throw new Error(apiError('read usage', res))\n const usage = (res.body.usage ?? {}) as Record<string, unknown>\n const limits = (res.body.limits ?? {}) as Record<string, unknown>\n const held = Number(usage.assetBytes ?? 0)\n const trash = Number(usage.trashBytes ?? 0)\n const limit = Number(limits.storageBytes ?? 0)\n const today = (usage.uploadsToday ?? {}) as Record<string, number>\n const perKind = (limits.uploadKinds ?? {}) as Record<\n string,\n { perDay?: number }\n >\n const rates = Object.entries(today)\n .filter(([kind]) => perKind[kind]?.perDay)\n .map(([kind, n]) => `${kind} ${n} of ${perKind[kind].perDay}`)\n r.done(\n { plan: res.body.plan, usage, limits },\n `${bytesWords(held)} of ${bytesWords(limit)} used` +\n (trash > 0\n ? `, ${bytesWords(trash)} of it in Trash (a person empties Trash at vos.so/app/trash; deleting more frees nothing)`\n : '') +\n (rates.length ? `\\nuploaded in the last 24 h: ${rates.join(', ')}` : ''),\n )\n return EXIT_OK\n}\n\nasync function cmdWhy(argv: string[]): Promise<number> {\n const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS)\n const [assetId] = positionals\n if (!assetId) throw new UsageError('vos assets why <assetId>')\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 res = await apiJson(origin, `/api/assets/${assetId}`, { key })\n if (res.status !== 200) throw new Error(apiError(`read ${assetId}`, res))\n const asset = hostedFile(res.body.asset) as HostedFile & {\n removedAt?: string\n removedReason?: string\n }\n const usedIn = (res.body.usedIn ?? []) as {\n vosId: string\n title: string\n head?: boolean\n versions?: number\n draft?: boolean\n trashed?: boolean\n }[]\n const how = (u: (typeof usedIn)[number]) =>\n [\n u.head ? 'in what plays now' : '',\n u.versions ? `${u.versions} version${u.versions === 1 ? '' : 's'}` : '',\n u.draft ? 'an unsaved draft' : '',\n u.trashed ? 'in Trash' : '',\n ]\n .filter(Boolean)\n .join(', ')\n const lines = [\n `${asset.filename} ${probeLine(asset)}, ${bytesWords(asset.size)}`,\n asset.removedAt\n ? `removed from vos.so: ${asset.removedReason ?? 'no reason given'}`\n : usedIn.length === 0\n ? asset.intent === 'attached'\n ? 'nothing uses it: an attached file that stays unused is collected after 7 days'\n : 'nothing uses it: it stays because it is in your library'\n : `used by ${usedIn.length}:`,\n ...usedIn.map((u) => ` ${u.vosId} ${u.title || 'Untitled'} (${how(u)})`),\n ]\n r.done({ asset, usedIn }, lines.join('\\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 case 'import':\n return cmdImport(rest)\n case 'ls':\n case 'list':\n return cmdList(rest)\n case 'usage':\n return cmdUsage(rest)\n case 'why':\n return cmdWhy(rest)\n default:\n throw new UsageError(\n 'vos asset <push|import|rename> | vos assets <ls|usage|why> — add files to your library, or see what is in it (vos asset push <file...> [--folder <slug>])',\n )\n }\n}\n","/**\n * How a hosted file is put into words on a terminal: what the platform\n * read it to be, and the line that names it in a program. Pure.\n */\n\nexport interface HostedFile {\n id: string\n kind: string\n filename: string\n size: number\n duration?: number | null\n metadata?: Record<string, unknown> | null\n uses?: number\n intent?: string\n folderId?: string | null\n}\n\n/**\n * A file as the platform lists it, read defensively: the list has called a\n * file's kind `category` for longer than it has called it `kind`, and a\n * row missing a field must print as a gap, never throw.\n */\nexport function hostedFile(raw: unknown): HostedFile {\n const row = (raw && typeof raw === 'object' ? raw : {}) as Record<\n string,\n unknown\n >\n const text = (value: unknown, fallback = ''): string =>\n typeof value === 'string' ? value : fallback\n return {\n ...row,\n id: text(row.id),\n kind: text(row.kind) || text(row.category, 'file'),\n filename: text(row.filename, 'unnamed'),\n size: typeof row.size === 'number' ? row.size : 0,\n } as HostedFile\n}\n\nexport function bytesWords(bytes: number): string {\n if (!Number.isFinite(bytes) || bytes < 0) return '0 B'\n if (bytes < 1024) return `${Math.round(bytes)} B`\n const units = ['KB', 'MB', 'GB', 'TB']\n let value = bytes / 1024\n let unit = 0\n while (value >= 1024 && unit < units.length - 1) {\n value /= 1024\n unit++\n }\n return `${value >= 100 ? Math.round(value) : value.toFixed(1)} ${units[unit]}`\n}\n\nconst num = (value: unknown): number | null =>\n typeof value === 'number' && Number.isFinite(value) ? value : null\n\n/**\n * What the platform measured, in one line: `video 1920×1080 h264 34.2 s,\n * audio`. Only what it actually read is said; a kind with nothing measured\n * is just its kind.\n */\nexport function probeLine(file: HostedFile): string {\n const meta = file.metadata ?? {}\n const parts: string[] = [file.kind]\n const width = num(meta.width)\n const height = num(meta.height)\n if (width && height) parts.push(`${width}×${height}`)\n if (typeof meta.videoCodec === 'string') parts.push(meta.videoCodec)\n else if (typeof meta.audioCodec === 'string' && file.kind === 'audio') {\n parts.push(meta.audioCodec)\n }\n const seconds = num(file.duration)\n if (seconds && seconds > 0) {\n parts.push(`${seconds >= 10 ? seconds.toFixed(1) : seconds.toFixed(2)} s`)\n }\n let line = parts.join(' ')\n if (file.kind === 'video' && meta.hasAudio === true) line += ', audio'\n if (file.kind === 'model') {\n const meshes = num(meta.meshCount)\n if (meshes !== null) line += ` ${meshes} mesh${meshes === 1 ? '' : 'es'}`\n }\n return line\n}\n\n/** A manifest name from a file name: an identifier, as `ctx.assets.<name>` needs. */\nexport function manifestName(filename: string): string {\n const stem = filename.replace(/\\.[^.]+$/, '')\n const name = stem\n .replace(/[^A-Za-z0-9_]+/g, '_')\n .replace(/^_+|_+$/g, '')\n .replace(/^(\\d)/, '_$1')\n return name || 'file'\n}\n\n/** The kinds a manifest's `kind` hint knows. */\nconst MANIFEST_KINDS = new Set([\n 'image',\n 'video',\n 'audio',\n 'model',\n 'font',\n 'hdr',\n])\n\n/** The line that declares the file in a program's `assets`. */\nexport function manifestLine(file: HostedFile): string {\n const kind = file.kind === 'vector' ? 'image' : file.kind\n const hint = MANIFEST_KINDS.has(kind) ? `, \"kind\": \"${kind}\"` : ''\n return `\"${manifestName(file.filename)}\": { \"ref\": \"asset:${file.id}\"${hint} }`\n}\n\n/** One row of `vos assets ls`: aligned by the caller, facts in a fixed order. */\nexport function listRow(file: HostedFile): string[] {\n return [\n file.id,\n file.kind,\n bytesWords(file.size),\n file.kind === 'recipe'\n ? ''\n : file.uses\n ? `used in ${file.uses}`\n : 'not used',\n file.intent === 'attached' ? 'attached' : 'library',\n file.filename,\n ]\n}\n\n/** Columns padded to the widest cell; the last column is left ragged. */\nexport function alignRows(rows: string[][]): string[] {\n if (rows.length === 0) return []\n const widths = rows[0].map((_, col) =>\n Math.max(...rows.map((row) => (row[col] ?? '').length)),\n )\n return rows.map((row) =>\n row\n .map((cell, col) =>\n col === row.length - 1 ? cell : cell.padEnd(widths[col]),\n )\n .join(' ')\n .trimEnd(),\n )\n}\n\n/** A file name for bytes fetched from an address: its last path segment. */\nexport function nameFromUrl(url: string): string {\n try {\n const last = decodeURIComponent(\n new URL(url).pathname.split('/').filter(Boolean).pop() ?? '',\n )\n const clean = last.replace(/[^\\w.\\- ]+/g, '_').slice(0, 120)\n return clean || 'download'\n } catch {\n return 'download'\n }\n}\n","/**\n * Where a URL the person typed may be fetched from. `vos asset import` and\n * `vos brand` follow an address from this machine, so an address on this\n * machine's own network (loopback, a private range, link-local, the cloud\n * metadata range) is refused before anything is fetched, and so is a\n * redirect that lands on one. Only a LITERAL address is judged here: a\n * name resolves at fetch time, where this check cannot see it.\n */\n\ntype Octets = [number, number, number, number]\n\n/** Why a hostname is not fetched, or null when it may be. */\nexport function privateHostReason(hostname: string): string | null {\n const host = hostname.replace(/^\\[|\\]$/g, '').toLowerCase()\n if (host === 'localhost' || host.endsWith('.localhost'))\n return 'is this machine'\n const v4 = parseIPv4(host)\n if (v4) return privateIPv4Reason(v4)\n const v6 = expandIPv6(host)\n if (!v6) return null\n // An IPv4 address carried in IPv6 is judged as the IPv4 it carries.\n const carried = carriedIPv4(v6)\n if (carried) return privateIPv4Reason(carried)\n if (v6.every((w) => w === 0)) return 'is an unspecified address'\n if (v6.slice(0, 7).every((w) => w === 0) && v6[7] === 1)\n return 'is this machine'\n if ((v6[0] & 0xfe00) === 0xfc00) return 'is a private network address'\n if ((v6[0] & 0xffc0) === 0xfe80) return 'is a link-local address'\n return null\n}\n\nfunction privateIPv4Reason([a, b]: Octets): string | null {\n if (a === 0) return 'is an unspecified address'\n if (a === 127) return 'is this machine'\n if (a === 10) return 'is a private network address'\n if (a === 172 && b >= 16 && b <= 31) return 'is a private network address'\n if (a === 192 && b === 168) return 'is a private network address'\n if (a === 100 && b >= 64 && b <= 127) return 'is a private network address'\n if (a === 169 && b === 254) return 'is a link-local address'\n return null\n}\n\n/**\n * The four octets of an IPv4 literal in any spelling a resolver takes\n * (dotted decimal, hex, octal, fewer than four parts), or null.\n */\nexport function parseIPv4(host: string): Octets | null {\n if (!/^[0-9a-fx.]+$/i.test(host)) return null\n const parts = host.split('.')\n if (parts.length > 4 || parts.some((p) => p === '')) return null\n const nums: number[] = []\n for (const p of parts) {\n let n: number\n if (/^0x[0-9a-f]+$/i.test(p)) n = parseInt(p.slice(2), 16)\n else if (/^0[0-7]+$/.test(p)) n = parseInt(p, 8)\n else if (/^[0-9]+$/.test(p)) n = parseInt(p, 10)\n else return null\n nums.push(n)\n }\n // The last part fills the remaining octets, the way inet_aton reads it.\n const last = nums[nums.length - 1]\n const lead = nums.slice(0, -1)\n if (lead.some((n) => n > 255)) return null\n const fill = 4 - lead.length\n if (last >= 256 ** fill) return null\n const tail: number[] = []\n let rest = last\n for (let i = 0; i < fill; i++) {\n tail.unshift(rest % 256)\n rest = Math.floor(rest / 256)\n }\n return [...lead, ...tail] as Octets\n}\n\n/** The eight 16-bit words of an IPv6 literal, or null when it is not one. */\nexport function expandIPv6(host: string): number[] | null {\n if (!host.includes(':')) return null\n const zone = host.indexOf('%')\n const addr = zone >= 0 ? host.slice(0, zone) : host\n if (!/^[0-9a-f:.]+$/i.test(addr)) return null\n const halves = addr.split('::')\n if (halves.length > 2) return null\n const words = (part: string): number[] | null => {\n if (part === '') return []\n const out: number[] = []\n const groups = part.split(':')\n for (let i = 0; i < groups.length; i++) {\n const g = groups[i]\n if (g.includes('.')) {\n // A dotted IPv4 tail takes the last two words.\n if (i !== groups.length - 1) return null\n const v4 = parseIPv4(g)\n if (!v4) return null\n out.push((v4[0] << 8) | v4[1], (v4[2] << 8) | v4[3])\n continue\n }\n if (!/^[0-9a-f]{1,4}$/i.test(g)) return null\n out.push(parseInt(g, 16))\n }\n return out\n }\n const head = words(halves[0])\n const tail = halves.length === 2 ? words(halves[1]) : []\n if (!head || !tail) return null\n if (halves.length === 1) return head.length === 8 ? head : null\n const gap = 8 - head.length - tail.length\n if (gap < 1) return null\n return [...head, ...new Array<number>(gap).fill(0), ...tail]\n}\n\n/** The IPv4 an IPv6 address carries (mapped, compatible or NAT64), if any. */\nfunction carriedIPv4(v6: number[]): Octets | null {\n const zeroLead = v6.slice(0, 5).every((w) => w === 0)\n const mapped = zeroLead && v6[5] === 0xffff\n // ::a.b.c.d (compatible), but never :: or ::1 themselves.\n const compatible = zeroLead && v6[5] === 0 && (v6[6] !== 0 || v6[7] > 1)\n const nat64 = v6[0] === 0x0064 && v6[1] === 0xff9b\n if (!mapped && !compatible && !nat64) return null\n return [v6[6] >> 8, v6[6] & 0xff, v6[7] >> 8, v6[7] & 0xff]\n}\n\n/** Why a URL is not fetched from this machine, or null when it may be. */\nexport function fetchRefusal(url: string): string | null {\n let u: URL\n try {\n u = new URL(url)\n } catch {\n return `${url} is not a URL`\n }\n if (u.protocol !== 'http:' && u.protocol !== 'https:')\n return `${url} is not an http(s) address, and the CLI fetches nothing else`\n const reason = privateHostReason(u.hostname)\n if (reason)\n return `${u.hostname} ${reason}, and the CLI fetches only from the public internet`\n return null\n}\n\nconst MAX_HOPS = 5\n\n/**\n * Fetch a public address, following at most five redirects and holding\n * every hop to the same rule as the first. The answer is the last hop's.\n */\nexport async function fetchPublic(\n url: string,\n init: RequestInit = {},\n fetchImpl: typeof fetch = fetch,\n): Promise<Response> {\n let at = url\n for (let hop = 0; ; hop++) {\n const refused = fetchRefusal(at)\n if (refused) throw new Error(refused)\n const res = await fetchImpl(at, { ...init, redirect: 'manual' })\n const location = res.headers.get('location')\n if (res.status < 300 || res.status > 399 || !location) return res\n if (hop >= MAX_HOPS)\n throw new Error(`${url} redirected more than ${MAX_HOPS} times`)\n at = new URL(location, at).href\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: the one named, or, for a\n * delete by id or URL, the working directory when its vos.json tracks it.\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 const tracking = dir ?? trackingCwd(vosId)\n let unlinked = false\n if (tracking) {\n rmSync(join(tracking, 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\n ? `; ${dir ?? 'this directory'} no longer tracks it`\n : ''\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/** The working directory, when its own vos.json tracks `vosId`. */\nfunction trackingCwd(vosId: string): string | null {\n const cwd = process.cwd()\n if (!existsSync(join(cwd, SYNC_STATE_NAME))) return null\n return readSyncState(cwd)?.vosId === vosId ? cwd : null\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 // A scene's name comes off the page (an element id, a label) and lands in\n // a module the port then imports: it is written as a JSON string on one\n // line, and its times as numbers or nothing.\n const word = (v: unknown) =>\n JSON.stringify(\n Array.from(String(v), (ch) => {\n const code = ch.charCodeAt(0)\n return code < 0x20 || code === 0x2028 || code === 0x2029 ? ' ' : ch\n }).join(''),\n )\n const secs = (v: unknown): number | null =>\n typeof v === 'number' && Number.isFinite(v) ? v : null\n const sceneTodos = p.scenes.length\n ? p.scenes\n .map((s) => {\n const start = secs(s.start) ?? 0\n const duration = secs(s.duration)\n return ` // TODO scene ${word(s.name)} (${start}s${duration ? ` to ${start + 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. A release must resolve the\n * brand BEFORE any cut is authored (a template's own palette on a\n * deliverable shipped once, and that run is why this verb exists).\n * The kit is a `BRAND.md` recipe: frontmatter carries the roles the look,\n * the titles and the end card bind (`bgA/bgB/bgC`, `ink`, `accent`,\n * `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 { fetchPublic, fetchRefusal } from './netAddress'\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 look, the titles and the end card bind 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 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 // Each redirect hop is held to the public internet, like the first.\n const res = await fetchPublic(url)\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 // A brand is witnessed on the public internet, never on this machine's\n // own network: the address is judged before a page or a file is asked.\n const refused = fetchRefusal(url)\n if (refused) throw new UsageError(refused)\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 or teardown step reads, taken from\n * 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 { scriptEnvNames, 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 and teardown read, 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 scriptEnvNames(actions)) {\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/**\n * Who reads the env, as a sentence's subject and verb: `the setup reads`,\n * `the teardown reads`, or `the setup and teardown read`.\n */\nexport function envReaders(\n actions: Pick<ActionsFile, 'setup' | 'teardown'>,\n): string {\n const setup = setupEnvNames(actions.setup).length > 0\n const teardown = setupEnvNames(actions.teardown).length > 0\n if (setup && teardown) return 'the setup and teardown read'\n return teardown ? 'the teardown reads' : 'the setup reads'\n}\n\n/**\n * The env NAMES a script's setup and teardown read, said before any value\n * is resolved, so a person running a script they did not write sees what\n * it is about to read from their shell. Names only: a value is never\n * printed. Null when the script reads nothing.\n */\nexport function envNamesNotice(\n actions: Pick<ActionsFile, 'setup' | 'teardown'>,\n): { names: string[]; line: string } | null {\n const names = scriptEnvNames(actions)\n if (names.length === 0) return null\n return {\n names,\n line: `${envReaders(actions)} ${names.length === 1 ? 'this environment variable' : 'these environment variables'} from this shell: ${names.join(', ')} (names only; a value is never printed or stored)`,\n }\n}\n\n/** Say the names, as a line for a person or an `env` event for a machine. */\nexport function announceEnvNames(\n actions: Pick<ActionsFile, 'setup' | 'teardown'>,\n r: {\n log: (line: string) => void\n event: (obj: Record<string, unknown>) => void\n },\n): void {\n const notice = envNamesNotice(actions)\n if (!notice) return\n r.log(notice.line)\n r.event({ event: 'env', names: notice.names })\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 { inflateEntry, traceBudget } from './traceInflate'\nimport {\n cursorFromPlaywrightTrace,\n cursorFromTrace,\n playwrightTraceEntry,\n traceKindOf,\n zipEntries,\n zipEntryBytes,\n} from '@vosjs/studio-core'\nimport {\n ALL_FORMATS,\n BufferTarget,\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 format = () =>\n ext === 'mp4'\n ? new Mp4OutputFormat({ fastStart: 'in-memory' })\n : new WebMOutputFormat()\n try {\n // A track it cannot keep is said by the caller, never as a raw dump.\n // Asked against a buffer first: a file target opens the destination\n // when it is made and closes it only once its output has started, so\n // one made for a conversion that is then abandoned leaves the handle\n // to the garbage collector.\n const probe = await Conversion.init({\n input,\n output: new Output({ format: format(), target: new BufferTarget() }),\n showWarnings: false,\n })\n const keepsAll = probe.isValid && probe.discardedTracks.length === 0\n await probe.cancel?.()\n if (!keepsAll) {\n await copyFile(src, dest)\n return false\n }\n const conversion = await Conversion.init({\n input,\n output: new Output({\n format: format(),\n target: new FilePathTarget(dest),\n }),\n showWarnings: 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 // Inflated under a budget: the zip's declared sizes are its own word.\n const raw = zipEntryBytes(bytes, entry)\n const text = new TextDecoder().decode(\n inflateEntry(raw, entry, traceBudget()),\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","import { inflateRawSync } from 'node:zlib'\nimport type { ZipEntry } from '@vosjs/studio-core'\n\n/**\n * A trace zip's entry inflated under a budget. A zip declares each entry's\n * size, but the declaration is the file's word: a small archive can inflate\n * to anything, and a trace read with no ceiling would take the machine's\n * memory with it. So an entry is held to a cap, the archive to a total,\n * and the inflater itself stops at the ceiling rather than trusting the\n * declared size.\n */\nexport const TRACE_ENTRY_MAX_BYTES = 64 * 1024 * 1024\nexport const TRACE_TOTAL_MAX_BYTES = 256 * 1024 * 1024\n\nexport interface InflateBudget {\n /** The most one entry may inflate to. */\n entry: number\n /** The most every entry together may inflate to. */\n total: number\n /** What the entries read so far took; advanced by each read. */\n used: number\n}\n\nexport function traceBudget(\n caps: Partial<Pick<InflateBudget, 'entry' | 'total'>> = {},\n): InflateBudget {\n return {\n entry: caps.entry ?? TRACE_ENTRY_MAX_BYTES,\n total: caps.total ?? TRACE_TOTAL_MAX_BYTES,\n used: 0,\n }\n}\n\nconst mib = (n: number) =>\n `${(n / (1024 * 1024)).toFixed(n < 10 * 1024 * 1024 ? 1 : 0)} MiB`\n\n/** The entry's bytes, stored or inflated, within the budget. */\nexport function inflateEntry(\n raw: Uint8Array,\n entry: Pick<ZipEntry, 'name' | 'method' | 'size'>,\n budget: InflateBudget,\n): Uint8Array {\n const room = Math.min(budget.entry, budget.total - budget.used)\n const over = (bytes: string) =>\n new Error(\n `${entry.name} inflates to ${bytes}, past the ${mib(budget.entry)} an entry may take (${mib(budget.total)} for the whole trace); this is not a trace the recorder reads`,\n )\n if (entry.size > room) throw over(mib(entry.size))\n let out: Uint8Array\n if (entry.method === 8) {\n try {\n out = new Uint8Array(inflateRawSync(raw, { maxOutputLength: room + 1 }))\n } catch (e) {\n if ((e as { code?: string }).code === 'ERR_BUFFER_TOO_LARGE')\n throw over(`more than ${mib(room)}`)\n throw e\n }\n } else {\n out = raw\n }\n if (out.length > room) throw over(mib(out.length))\n budget.used += out.length\n return out\n}\n","/**\n * `vos check-video <file>`: the rendered FILE checked as a viewer meets it,\n * with no ffmpeg. The container's facts come from mediabunny in node; the\n * pictures and the sound are decoded in the browser the CLI already drives\n * (mediabunny over WebCodecs, the copy this package installs), which hands\n * back small measurements: each sampled frame's change from the one before\n * (the mean absolute difference of its colours, drawn 160 px on the long side),\n * the K-weighted energy of the sound in 100 ms pieces, the first and last\n * frames as PNGs. What they mean is decided in videoChecks.ts.\n */\nimport { createRequire } from 'node:module'\nimport { existsSync } from 'node:fs'\nimport { mkdir, readFile, stat, writeFile } from 'node:fs/promises'\nimport { basename, dirname, extname, join, resolve } from 'node:path'\nimport { ALL_FORMATS, FilePathSource, Input } from 'mediabunny'\nimport { UsageError, parseArgs, strFlag } from './args'\nimport { EXIT_OK, EXIT_USAGE, createReporter } from './output'\nimport { startTakeServer, waitForPageDone } from './server'\nimport { launchBrowser } from '../browser'\nimport {\n SCENE_CHANGE_AT,\n CELL_CHANGED_AT,\n CELL_STRONG_AT,\n ISOLATED_CHANGE_AT,\n SCENE_WINDOW,\n SUB_BLOCK_SECONDS,\n createLoudnessMeter,\n loudnessFromEnergies,\n loudnessWarnings,\n posterWarning,\n sceneChanges,\n sceneWarnings,\n windowCounts,\n} from './videoChecks'\nimport type { LoudnessReport, SceneChange, SceneScatter } from './videoChecks'\nimport type { Browser } from 'playwright'\n\nconst BOOLEAN_FLAGS = new Set(['json', 'help', 'strict'])\n\n/**\n * The long side frames are drawn at to be compared, in pixels. Large\n * enough that a thin line still reads as a change where it vanishes: at\n * 64 px a board of outlined boxes on white averages into the white.\n */\nconst THUMB_LONG_SIDE = 160\n\n/** The cells a frame's change is counted in: this many across its long side. */\nconst CELLS_LONG_SIDE = 16\n\nexport interface VideoFacts {\n file: string\n bytes: number\n /** Seconds. */\n duration: number\n width: number\n height: number\n /** Frames per second, from the packets' own timing. */\n fps: number\n container: string\n video: { codec: string | null; codecString: string | null }\n audio: {\n codec: string | null\n codecString: string | null\n sampleRate: number\n channels: number\n } | null\n}\n\n/** The file's own facts, read from its container in node. */\nexport async function probeVideoFacts(file: string): Promise<VideoFacts> {\n const input = new Input({\n source: new FilePathSource(file),\n formats: ALL_FORMATS,\n })\n try {\n const video = await input.getPrimaryVideoTrack()\n if (!video) throw new UsageError(`${file} has no video track`)\n const [format, duration, stats, audio, bytes] = await Promise.all([\n input.getFormat(),\n input.computeDuration(),\n video.computePacketStats(240),\n input.getPrimaryAudioTrack(),\n stat(file).then((s) => s.size),\n ])\n return {\n file,\n bytes,\n duration: Math.round(duration * 1000) / 1000,\n width: video.displayWidth,\n height: video.displayHeight,\n fps: Math.round(stats.averagePacketRate * 100) / 100,\n container: format.mimeType,\n video: {\n codec: video.codec,\n codecString: await video.getCodecParameterString(),\n },\n audio: audio\n ? {\n codec: audio.codec,\n codecString: await audio.getCodecParameterString(),\n sampleRate: audio.sampleRate,\n channels: audio.numberOfChannels,\n }\n : null,\n }\n } finally {\n input.dispose()\n }\n}\n\n/** The browser bundle of the mediabunny this package installs. */\nasync function mediabunnyBundle(): Promise<string> {\n const entry = createRequire(import.meta.url).resolve('mediabunny')\n const bundle = join(dirname(entry), 'mediabunny.min.mjs')\n if (existsSync(bundle)) return readFile(bundle, 'utf8')\n // A layout where `require` resolves into dist/modules: the bundles sit beside it.\n return readFile(\n join(entry.split('/dist/')[0], 'dist/bundles/mediabunny.min.mjs'),\n 'utf8',\n )\n}\n\ninterface DecodeDone {\n times: number[]\n changes: number[]\n coverage: number[]\n scatter: SceneScatter[]\n firstDeviation: number\n lastDeviation: number\n firstTime: number\n lastTime: number\n firstPng: string\n lastPng: string\n audio: {\n sampleRate: number\n channels: number\n energies: number[][]\n peak: number\n samples: number\n } | null\n}\n\n/** Runs inside the decode page (serialized by Playwright). */\nasync function decodeInPage(opts: {\n mbCode: string\n meterSrc: string\n videoUrl: string\n sampleFps: number\n thumbW: number\n thumbH: number\n cellPx: number\n subBlock: number\n cellChanged: number\n cellStrong: number\n}) {\n const w = window as unknown as Record<string, any>\n try {\n // An import spelled as text: a bundler or a test transform that\n // rewrites `import()` in this function would break it in the page.\n const load = new Function('u', 'return import(u)') as (\n u: string,\n ) => Promise<any>\n const MB = await load(\n URL.createObjectURL(new Blob([opts.mbCode], { type: 'text/javascript' })),\n )\n const input = new MB.Input({\n source: new MB.UrlSource(opts.videoUrl),\n formats: MB.ALL_FORMATS,\n })\n const track = await input.getPrimaryVideoTrack()\n if (!track) throw new Error('no video track')\n if (!(await track.canDecode()))\n throw new Error(`this browser cannot decode ${String(track.codec)}`)\n\n // A frame as its colour values, R, G and B in turn: a cut between two\n // pictures of the same brightness and a different hue is still a cut.\n const pixels = (canvas: HTMLCanvasElement | OffscreenCanvas): number[] => {\n const g = canvas.getContext('2d', {\n willReadFrequently: true,\n }) as CanvasRenderingContext2D\n const px = g.getImageData(0, 0, canvas.width, canvas.height).data\n const out: number[] = new Array((px.length / 4) * 3)\n for (let p = 0, q = 0; p < px.length; p += 4, q += 3) {\n out[q] = px[p]\n out[q + 1] = px[p + 1]\n out[q + 2] = px[p + 2]\n }\n return out\n }\n // How far a frame is from one flat colour: the spread of each channel,\n // averaged over the three.\n const deviation = (a: number[]) => {\n let total = 0\n for (let c = 0; c < 3; c++) {\n let s = 0\n let n = 0\n for (let i = c; i < a.length; i += 3) {\n s += a[i]\n n++\n }\n const m = s / Math.max(1, n)\n let q = 0\n for (let i = c; i < a.length; i += 3) q += (a[i] - m) * (a[i] - m)\n total += Math.sqrt(q / Math.max(1, n))\n }\n return total / 3\n }\n const difference = (a: number[], b: number[]) => {\n let s = 0\n for (let i = 0; i < a.length; i++) s += Math.abs(a[i] - b[i])\n return s / Math.max(1, a.length) / 255\n }\n // How much of the frame changed: the share of cells whose own mean\n // difference reaches `opts.cellChanged`; and how the cells that changed\n // by a lot (`opts.cellStrong`) lie: their share, and the box around\n // them as a share of the frame.\n const coverageOf = (\n a: number[],\n b: number[],\n ): { share: number; scatter: { share: number; box: number } } => {\n const W = opts.thumbW\n const H = opts.thumbH\n const C = opts.cellPx\n let cells = 0\n let changed = 0\n let strong = 0\n let x0 = W\n let x1 = 0\n let y0 = H\n let y1 = 0\n for (let cy = 0; cy < H; cy += C)\n for (let cx = 0; cx < W; cx += C) {\n let s = 0\n let n = 0\n for (let y = cy; y < Math.min(H, cy + C); y++)\n for (let x = cx; x < Math.min(W, cx + C); x++) {\n const k = (y * W + x) * 3\n s +=\n Math.abs(a[k] - b[k]) +\n Math.abs(a[k + 1] - b[k + 1]) +\n Math.abs(a[k + 2] - b[k + 2])\n n += 3\n }\n cells++\n const m = s / Math.max(1, n) / 255\n if (m >= opts.cellChanged) changed++\n if (m >= opts.cellStrong) {\n strong++\n x0 = Math.min(x0, cx)\n x1 = Math.max(x1, Math.min(W, cx + C))\n y0 = Math.min(y0, cy)\n y1 = Math.max(y1, Math.min(H, cy + C))\n }\n }\n const n = Math.max(1, cells)\n return {\n share: changed / n,\n scatter: {\n share: strong / n,\n box: strong ? ((x1 - x0) * (y1 - y0)) / Math.max(1, W * H) : 0,\n },\n }\n }\n\n // Every frame is decoded in order (never a seek per sample, which\n // re-decodes from the keyframe each time) and drawn small with the\n // high-quality resampler, which averages the picture instead of picking\n // a few of its pixels; one frame is kept per sample step.\n const small = document.createElement('canvas')\n small.width = opts.thumbW\n small.height = opts.thumbH\n const sctx = small.getContext('2d', { willReadFrequently: true })!\n sctx.imageSmoothingEnabled = true\n sctx.imageSmoothingQuality = 'high'\n const samples = new MB.VideoSampleSink(track)\n const step = 1 / opts.sampleFps\n const times: number[] = []\n const changes: number[] = []\n const coverage: number[] = []\n const scatter: { share: number; box: number }[] = []\n const none = { share: 0, scatter: { share: 0, box: 0 } }\n let next = -Infinity\n let prev: number[] | null = null\n let first: number[] | null = null\n let firstTime = 0\n let lastTime = 0\n let lastKept = -1\n let lastGray: number[] | null = null\n let tail: number[] | null = null\n const duration = await input.computeDuration()\n for await (const sample of samples.samples()) {\n const t = sample.timestamp as number\n sctx.clearRect(0, 0, opts.thumbW, opts.thumbH)\n sample.draw(sctx, 0, 0, opts.thumbW, opts.thumbH)\n sample.close()\n lastTime = t\n // Half a step of slack: a container rounds timestamps (WebM to the\n // millisecond), and a frame a hair early is still the one wanted.\n if (t + step / 2 < next) {\n tail = pixels(small)\n continue\n }\n tail = null\n const g = pixels(small)\n if (!first) {\n first = g\n firstTime = t\n }\n times.push(t)\n changes.push(prev ? difference(prev, g) : 0)\n const cov = prev ? coverageOf(prev, g) : none\n coverage.push(cov.share)\n scatter.push(cov.scatter)\n prev = g\n lastKept = t\n lastGray = g\n next = next === -Infinity ? t + step : next + step\n if (next <= t) next = t + step\n w.__progress = duration > 0 ? Math.min(0.9, (t / duration) * 0.9) : 0\n }\n if (!first || !lastGray) throw new Error('no video frame decoded')\n // The very last frame, when the sampling stepped past it.\n if (tail && lastTime > lastKept) {\n times.push(lastTime)\n changes.push(prev ? difference(prev, tail) : 0)\n const cov = prev ? coverageOf(prev, tail) : none\n coverage.push(cov.share)\n scatter.push(cov.scatter)\n lastGray = tail\n }\n\n const toBase64 = (bytes: Uint8Array) => {\n let s = ''\n for (let i = 0; i < bytes.length; i += 0x8000)\n s += String.fromCharCode(...bytes.subarray(i, i + 0x8000))\n return btoa(s)\n }\n const full = new MB.CanvasSink(track)\n const png = async (t: number) => {\n const wc = await full.getCanvas(t)\n if (!wc) return ''\n const c = wc.canvas as HTMLCanvasElement | OffscreenCanvas\n const blob: Blob =\n 'convertToBlob' in c\n ? await c.convertToBlob({ type: 'image/png' })\n : await new Promise<Blob>((res, rej) =>\n c.toBlob(\n (b) => (b ? res(b) : rej(new Error('toBlob failed'))),\n 'image/png',\n ),\n )\n return toBase64(new Uint8Array(await blob.arrayBuffer()))\n }\n const firstPng = await png(firstTime)\n const lastPng = await png(lastTime)\n\n let audio = null\n const at = await input.getPrimaryAudioTrack()\n if (at && (await at.canDecode())) {\n const make = new Function(`return (${opts.meterSrc})`)() as (\n rate: number,\n channels: number,\n sub: number,\n ) => {\n push: (c: Float32Array[]) => void\n finish: () => { energies: number[][]; peak: number; samples: number }\n }\n const meter = make(at.sampleRate, at.numberOfChannels, opts.subBlock)\n const sink = new MB.AudioBufferSink(at)\n for await (const wb of sink.buffers()) {\n const b = wb.buffer as AudioBuffer\n const chans: Float32Array[] = []\n for (let c = 0; c < at.numberOfChannels; c++)\n chans.push(\n c < b.numberOfChannels ? b.getChannelData(c) : new Float32Array(0),\n )\n meter.push(chans)\n }\n audio = {\n sampleRate: at.sampleRate,\n channels: at.numberOfChannels,\n ...meter.finish(),\n }\n }\n input.dispose()\n w.__done = {\n times,\n changes,\n coverage,\n scatter,\n firstDeviation: deviation(first),\n lastDeviation: deviation(lastGray),\n firstTime,\n lastTime,\n firstPng,\n lastPng,\n audio,\n }\n } catch (e) {\n w.__error = String((e instanceof Error && e.stack) || e)\n }\n}\n\nexport interface CheckVideoResult extends VideoFacts {\n scenes: {\n /** Frames per second the change was measured at. */\n sampleFps: number\n threshold: number\n /** The smaller change that still counts when it stands alone. */\n isolatedThreshold: number\n window: number\n changes: SceneChange[]\n perWindow: { start: number; count: number }[]\n }\n loudness: LoudnessReport | null\n posters: {\n first: { file: string; time: number; deviation: number; uniform: boolean }\n last: { file: string; time: number; deviation: number; uniform: boolean }\n }\n warnings: string[]\n outDir: string\n}\n\n/** Check a rendered video file; writes the posters and check.json into `outDir`. */\nexport async function checkVideo(\n browser: Browser,\n file: string,\n outDir: string,\n): Promise<CheckVideoResult> {\n const facts = await probeVideoFacts(file)\n // The file's own rate, within reason: never under 10 a second unless the\n // file has fewer, never over 30, and 10 for a long file.\n const ceiling = facts.duration > 120 ? 10 : 30\n const sampleFps = Math.max(\n Math.min(10, facts.fps || 10),\n Math.min(facts.fps || 30, ceiling),\n )\n const long = Math.max(facts.width, facts.height, 1)\n const side = (n: number) =>\n Math.max(1, Math.round((n / long) * THUMB_LONG_SIDE))\n\n const server = await startTakeServer(dirname(resolve(file)), {\n '/check.html':\n '<!doctype html><html><head><meta charset=\"utf-8\"><link rel=\"icon\" href=\"data:,\"></head><body></body></html>',\n })\n const page = await browser.newPage()\n let done: DecodeDone\n try {\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}/check.html`)\n void page\n .evaluate(decodeInPage, {\n mbCode: await mediabunnyBundle(),\n meterSrc: String(createLoudnessMeter),\n videoUrl: `/${encodeURIComponent(basename(file))}`,\n sampleFps,\n thumbW: side(facts.width),\n thumbH: side(facts.height),\n cellPx: Math.max(1, Math.round(THUMB_LONG_SIDE / CELLS_LONG_SIDE)),\n subBlock: SUB_BLOCK_SECONDS,\n cellChanged: CELL_CHANGED_AT,\n cellStrong: CELL_STRONG_AT,\n })\n .catch(() => {})\n done = (await waitForPageDone(\n page,\n 'check-video',\n () => {},\n 120_000 + facts.duration * 4_000,\n )) as unknown as DecodeDone\n } finally {\n await page.close()\n server.close()\n }\n\n await mkdir(outDir, { recursive: true })\n const firstFile = join(outDir, 'first.png')\n const lastFile = join(outDir, 'last.png')\n await writeFile(firstFile, Buffer.from(done.firstPng, 'base64'))\n await writeFile(lastFile, Buffer.from(done.lastPng, 'base64'))\n\n const changes = sceneChanges(\n done.times,\n done.changes,\n done.coverage,\n done.scatter,\n )\n const loudness = done.audio\n ? loudnessFromEnergies(done.audio.energies, done.audio.peak)\n : null\n const round2 = (n: number) => Math.round(n * 100) / 100\n const posters = {\n first: {\n file: firstFile,\n time: round2(done.firstTime),\n deviation: round2(done.firstDeviation),\n uniform: posterWarning('first', done.firstDeviation) !== null,\n },\n last: {\n file: lastFile,\n time: round2(done.lastTime),\n deviation: round2(done.lastDeviation),\n uniform: posterWarning('last', done.lastDeviation) !== null,\n },\n }\n const warnings = [\n ...sceneWarnings(changes),\n ...(loudness ? loudnessWarnings(loudness) : []),\n ...[\n posterWarning('first', done.firstDeviation),\n posterWarning('last', done.lastDeviation),\n ].filter((w): w is string => w !== null),\n ]\n const result: CheckVideoResult = {\n ...facts,\n scenes: {\n sampleFps: round2(sampleFps),\n threshold: SCENE_CHANGE_AT,\n isolatedThreshold: ISOLATED_CHANGE_AT,\n window: SCENE_WINDOW,\n changes: changes.map((c) => ({ ...c, time: round2(c.time) })),\n perWindow: windowCounts(changes, facts.duration),\n },\n loudness,\n posters,\n warnings,\n outDir,\n }\n await writeFile(\n join(outDir, 'check.json'),\n `${JSON.stringify(result, null, 2)}\\n`,\n )\n return result\n}\n\nconst mb = (n: number) =>\n n >= 1024 * 1024\n ? `${(n / 1024 / 1024).toFixed(1)} MB`\n : `${Math.max(1, Math.round(n / 1024))} KB`\n\n/** The human summary of a check, one fact per line. */\nexport function checkVideoLines(r: CheckVideoResult): string {\n const codecs = [\n r.video.codecString ?? r.video.codec ?? 'unknown',\n ...(r.audio ? [r.audio.codecString ?? r.audio.codec ?? 'unknown'] : []),\n ].join(' + ')\n const cuts = r.scenes.changes\n const l = r.loudness\n const st = l?.shortTerm.map((s) =>\n s.loudness === null ? '-' : String(s.loudness),\n )\n return [\n `Checked ${r.file}: ${r.duration.toFixed(2)}s, ${r.width}x${r.height} @ ${r.fps} fps, ${mb(r.bytes)}, ${codecs}`,\n ` scene changes: ${cuts.length}${cuts.length ? ` (${cuts.map((c) => `${c.time.toFixed(2)}s`).join(', ')})` : ''}; per ${r.scenes.window} s: ${r.scenes.perWindow.map((w) => w.count).join(', ')}`,\n r.audio\n ? ` loudness: ${l?.integrated ?? 'silent'}${l?.integrated !== null ? ' LUFS' : ''} integrated; short-term every 3 s: ${st?.join(', ')}; sample peak ${l?.samplePeakDb ?? '-inf'} dBFS`\n : ' loudness: no audio track',\n ` posters: ${r.posters.first.file} (deviation ${r.posters.first.deviation}), ${r.posters.last.file} (deviation ${r.posters.last.deviation})`,\n ` ${r.warnings.length ? `${r.warnings.length} warning${r.warnings.length === 1 ? '' : 's'}` : 'no warnings'}; ${join(r.outDir, 'check.json')}`,\n ].join('\\n')\n}\n\nexport async function cmdCheckVideo(argv: string[]): Promise<number> {\n const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS)\n const file = positionals[0]\n if (!file)\n throw new UsageError(\n 'vos check-video <file.mp4|webm> [--out dir] [--strict] [--json]',\n )\n if (!existsSync(file)) throw new UsageError(`${file} does not exist`)\n const r = createReporter(flags.json === true)\n const strict = flags.strict === true\n const outDir = resolve(\n strFlag(flags, 'out') ??\n join(dirname(file), `${basename(file, extname(file))}-check`),\n )\n const browser = await launchBrowser()\n try {\n r.event({ event: 'phase', phase: 'check-video' })\n const result = await checkVideo(browser, file, outDir)\n for (const w of result.warnings) r.warn(w)\n r.done({ ...result }, checkVideoLines(result))\n return result.warnings.length && strict ? EXIT_USAGE : EXIT_OK\n } finally {\n await browser.close()\n }\n}\n","/**\n * What `vos check-video` concludes from a rendered file, as pure functions\n * over what the decode page measured: the frame-to-frame change of a small\n * picture, the K-weighted energy of the sound in 100 ms pieces, and how\n * flat the first and last frames are. The page decodes; this decides.\n *\n * Loudness follows ITU-R BS.1770-4: the K-weighting pre-filter (a high\n * shelf, then the RLB high-pass) designed for the file's own sample rate,\n * 400 ms blocks every 100 ms, the absolute gate at -70 LUFS and the\n * relative gate 10 LU under the absolutely gated mean. Short-term loudness\n * is the same measure over 3 s. The peak is the SAMPLE peak: no\n * oversampling, so a true peak can sit a little above it.\n */\n\n/** A full-frame change: the mean absolute difference (0..1) at or above this. */\nexport const SCENE_CHANGE_AT = 0.12\n\n/** A cell of the small frame has changed when its own mean difference reaches this. */\nexport const CELL_CHANGED_AT = 0.03\n\n/** A cell has changed by a lot when its own mean difference reaches this. */\nexport const CELL_STRONG_AT = 0.06\n\n/** The window a cut is counted in, seconds. */\nexport const SCENE_WINDOW = 5\n\n/** A frame whose colours deviate less than this (0..255, per channel) is near-uniform. */\nexport const UNIFORM_BELOW = 2\n\n/** Integrated loudness below this is too quiet for a social feed. */\nexport const QUIET_BELOW_LUFS = -23\n\n/** Integrated loudness above this is too loud: it will be turned down and may clip. */\nexport const LOUD_ABOVE_LUFS = -9\n\n/** The piece of sound the page sums energy over, seconds. */\nexport const SUB_BLOCK_SECONDS = 0.1\n\n/** Short-term loudness is reported every this many seconds, over as many. */\nexport const SHORT_TERM_SECONDS = 3\n\n/**\n * A cut stands out from the frames around it: at least this many times the\n * median change of its two neighbours on either side. Motion (a zoom, a\n * pan, a scroll) changes every frame of its stretch by about as much, so it\n * never stands out, however much of the picture it moves.\n */\nexport const SCENE_SPIKE = 2.5\n\n/**\n * A smaller change is still a cut when it stands ALONE: the picture held\n * still on both sides of it (each of the two frames either side changed by\n * under 1/ISOLATED_SPIKE of it) and it reached ISOLATED_CHANGE_AT over at\n * least ISOLATED_COVERAGE of the frame. Two views of one dark or sparse\n * picture differ by little on average, and a camera that jumps between\n * them in one frame is a cut all the same. A fade's first step has the\n * fade's next steps beside it, so it never stands alone.\n */\nexport const ISOLATED_CHANGE_AT = 0.03\nexport const ISOLATED_SPIKE = 8\nexport const ISOLATED_COVERAGE = 0.25\n\n/**\n * A change that stands alone is a cut too when what changed by a lot is\n * SCATTERED over the frame: its cells (CELL_STRONG_AT) are at least\n * SCATTER_SHARE of the frame and the box around them at least SCATTER_BOX.\n * A light, sparse picture (outlined boxes and notes on white) cut to\n * another view changes little on average, and over less than a quarter of\n * the frame, since most of both frames is the same ground; an app's own\n * change in one frame (a panel opening, an embed appearing, a selection\n * tint) is one block, or a change too faint to count.\n */\nexport const SCATTER_SHARE = 0.1\nexport const SCATTER_BOX = 0.22\n\n/** How the cells that changed by a lot lie: their share of the frame, and the box around them. */\nexport interface SceneScatter {\n share: number\n box: number\n}\n\nexport interface SceneChange {\n /** Output seconds of the first frame after the change. */\n time: number\n /** Mean absolute difference from the frame before, 0..1. */\n change: number\n /** The share of the frame that changed, 0..1, when it was measured. */\n coverage?: number\n}\n\n/**\n * The full-frame changes in a series of sampled frames, from each frame's\n * change from the one before (and, when measured, the share of the frame\n * that changed). A frame is a cut when it is the peak of its run, so a cut\n * that spreads over two decoded frames counts once, and either a large\n * change that stands out from its neighbours (SCENE_CHANGE_AT,\n * SCENE_SPIKE), or a smaller one that stands alone (ISOLATED_*) over a\n * quarter of the frame or scattered across it (SCATTER_*). A camera move\n * is neither.\n */\nexport function sceneChanges(\n times: readonly number[],\n changes: readonly number[],\n coverage?: readonly number[],\n scatter?: readonly SceneScatter[],\n): SceneChange[] {\n const out: SceneChange[] = []\n for (let i = 1; i < changes.length; i++) {\n const c = changes[i]\n if (c < Math.min(SCENE_CHANGE_AT, ISOLATED_CHANGE_AT)) continue\n if (i > 1 && changes[i - 1] > c) continue\n if (i + 1 < changes.length && changes[i + 1] >= c) continue\n const around = [i - 2, i - 1, i + 1, i + 2]\n .filter((k) => k >= 1 && k < changes.length)\n .map((k) => changes[k])\n .sort((a, b) => a - b)\n const mid = around.length\n ? around.length % 2\n ? around[(around.length - 1) / 2]\n : (around[around.length / 2 - 1] + around[around.length / 2]) / 2\n : 0\n const most = around.length ? around[around.length - 1] : 0\n const share = coverage ? coverage[i] : 1\n const standsOut = c >= SCENE_CHANGE_AT && c >= SCENE_SPIKE * mid\n const spread = scatter?.[i]\n const scattered =\n !!spread && spread.share >= SCATTER_SHARE && spread.box >= SCATTER_BOX\n const standsAlone =\n c >= ISOLATED_CHANGE_AT &&\n (share >= ISOLATED_COVERAGE || scattered) &&\n c >= ISOLATED_SPIKE * most\n if (!standsOut && !standsAlone) continue\n out.push({\n time: times[i],\n change: Math.round(c * 1e4) / 1e4,\n ...(coverage ? { coverage: Math.round(share * 1000) / 1000 } : {}),\n })\n }\n return out\n}\n\n/** How many changes fall in each consecutive window from 0. */\nexport function windowCounts(\n cuts: readonly SceneChange[],\n duration: number,\n window = SCENE_WINDOW,\n): { start: number; count: number }[] {\n const n = Math.max(1, Math.ceil(duration / window - 1e-9))\n const out = Array.from({ length: n }, (_, k) => ({\n start: k * window,\n count: 0,\n }))\n for (const c of cuts) {\n const k = Math.min(n - 1, Math.max(0, Math.floor(c.time / window)))\n out[k].count++\n }\n return out\n}\n\n/**\n * Runs of changes that any one window of `window` seconds holds more than\n * one of: two cuts closer than the window, wherever the window starts.\n */\nexport function crowdedRuns(\n cuts: readonly SceneChange[],\n window = SCENE_WINDOW,\n): SceneChange[][] {\n const runs: SceneChange[][] = []\n let run: SceneChange[] = []\n for (const c of cuts) {\n if (run.length && c.time - run[run.length - 1].time < window) run.push(c)\n else {\n if (run.length > 1) runs.push(run)\n run = [c]\n }\n }\n if (run.length > 1) runs.push(run)\n return runs\n}\n\n/**\n * A streaming K-weighted energy meter, SELF-CONTAINED on purpose: the decode\n * page runs it from its source text (`String(createLoudnessMeter)`), so it\n * references nothing outside its own body. `push` takes each decoded\n * buffer's channels in order; `finish` hands back, per channel, the mean\n * square of the K-weighted signal over every `subBlockSeconds` piece, and\n * the sample peak.\n */\nexport function createLoudnessMeter(\n sampleRate: number,\n channelCount: number,\n subBlockSeconds: number,\n): {\n push: (channels: Float32Array[]) => void\n finish: () => { energies: number[][]; peak: number; samples: number }\n} {\n // BS.1770's two biquads, designed for this rate (the design libebur128\n // uses; at 48 kHz it lands on the standard's own coefficients).\n const shelf = (() => {\n const f0 = 1681.974450955533\n const G = 3.999843853973347\n const Q = 0.7071752369554196\n const K = Math.tan((Math.PI * f0) / sampleRate)\n const Vh = Math.pow(10, G / 20)\n const Vb = Math.pow(Vh, 0.4996667741545416)\n const a0 = 1 + K / Q + K * K\n return {\n b0: (Vh + (Vb * K) / Q + K * K) / a0,\n b1: (2 * (K * K - Vh)) / a0,\n b2: (Vh - (Vb * K) / Q + K * K) / a0,\n a1: (2 * (K * K - 1)) / a0,\n a2: (1 - K / Q + K * K) / a0,\n }\n })()\n const highpass = (() => {\n const f0 = 38.13547087602444\n const Q = 0.5003270373238773\n const K = Math.tan((Math.PI * f0) / sampleRate)\n const a0 = 1 + K / Q + K * K\n return {\n b0: 1,\n b1: -2,\n b2: 1,\n a1: (2 * (K * K - 1)) / a0,\n a2: (1 - K / Q + K * K) / a0,\n }\n })()\n const per = Math.max(1, Math.round(sampleRate * subBlockSeconds))\n const state = Array.from({ length: channelCount }, () => ({\n // Direct form I history for each stage.\n x1: 0,\n x2: 0,\n y1: 0,\n y2: 0,\n u1: 0,\n u2: 0,\n w1: 0,\n w2: 0,\n sum: 0,\n count: 0,\n energies: [] as number[],\n }))\n let peak = 0\n let samples = 0\n return {\n push(channels) {\n for (let c = 0; c < channelCount; c++) {\n const data = channels[c]\n const s = state[c]\n if (!data) continue\n for (let i = 0; i < data.length; i++) {\n const x = data[i]\n const ax = x < 0 ? -x : x\n if (ax > peak) peak = ax\n const y =\n shelf.b0 * x +\n shelf.b1 * s.x1 +\n shelf.b2 * s.x2 -\n shelf.a1 * s.y1 -\n shelf.a2 * s.y2\n s.x2 = s.x1\n s.x1 = x\n s.y2 = s.y1\n s.y1 = y\n const w =\n highpass.b0 * y +\n highpass.b1 * s.u1 +\n highpass.b2 * s.u2 -\n highpass.a1 * s.w1 -\n highpass.a2 * s.w2\n s.u2 = s.u1\n s.u1 = y\n s.w2 = s.w1\n s.w1 = w\n s.sum += w * w\n s.count++\n if (s.count === per) {\n s.energies.push(s.sum / per)\n s.sum = 0\n s.count = 0\n }\n }\n if (c === 0) samples += data.length\n }\n },\n finish() {\n return {\n energies: state.map((s) =>\n s.count > 0 ? [...s.energies, s.sum / s.count] : s.energies,\n ),\n peak,\n samples,\n }\n },\n }\n}\n\n/** BS.1770's channel weights: 1 for left, right and centre, 0 for the LFE of 5.1, 1.41 for the surrounds. */\nexport function channelWeights(count: number): number[] {\n if (count === 6) return [1, 1, 1, 0, 1.41, 1.41]\n return Array.from({ length: count }, (_, i) => (i < 3 ? 1 : 1.41))\n}\n\nconst LOUDNESS_OFFSET = -0.691\nconst toLufs = (power: number): number | null =>\n power > 0 ? LOUDNESS_OFFSET + 10 * Math.log10(power) : null\n\n/** The weighted power of `count` sub-blocks from `from`, averaged. */\nfunction windowPower(\n energies: readonly (readonly number[])[],\n weights: readonly number[],\n from: number,\n count: number,\n): number {\n let total = 0\n for (let c = 0; c < energies.length; c++) {\n const e = energies[c]\n let sum = 0\n let n = 0\n for (let k = from; k < from + count && k < e.length; k++) {\n sum += e[k]\n n++\n }\n if (n) total += (weights[c] ?? 1) * (sum / n)\n }\n return total\n}\n\nexport interface LoudnessReport {\n unit: 'LUFS'\n /** Integrated loudness; null when no block passes the absolute gate (silence). */\n integrated: number | null\n /** Short-term loudness of each 3 s from 0; null for a silent stretch. */\n shortTerm: { time: number; loudness: number | null }[]\n /** The loudest short-term value. */\n maxShortTerm: number | null\n /** Sample peak in dBFS (not oversampled); null for digital silence. */\n samplePeakDb: number | null\n}\n\nconst round1 = (n: number | null) =>\n n === null ? null : Math.round(n * 10) / 10\n\n/**\n * BS.1770 integrated and short-term loudness from per-channel K-weighted\n * energies in `subBlock`-second pieces (what `createLoudnessMeter` hands\n * back), plus the sample peak.\n */\nexport function loudnessFromEnergies(\n energies: readonly (readonly number[])[],\n peak: number,\n subBlock = SUB_BLOCK_SECONDS,\n): LoudnessReport {\n const weights = channelWeights(energies.length)\n const pieces = Math.max(0, ...energies.map((e) => e.length))\n const blockLen = Math.max(1, Math.round(0.4 / subBlock))\n const blocks: number[] = []\n for (let k = 0; k + blockLen <= pieces; k++)\n blocks.push(windowPower(energies, weights, k, blockLen))\n // A file shorter than one block is measured as the one block it has.\n if (!blocks.length && pieces > 0)\n blocks.push(windowPower(energies, weights, 0, pieces))\n const mean = (xs: number[]) =>\n xs.length ? xs.reduce((a, b) => a + b, 0) / xs.length : 0\n const loud = (p: number) => toLufs(p) ?? -Infinity\n const absolute = blocks.filter((p) => loud(p) > -70)\n let integrated: number | null = null\n if (absolute.length) {\n const gate = loud(mean(absolute)) - 10\n const relative = absolute.filter((p) => loud(p) > gate)\n integrated = toLufs(mean(relative))\n }\n const stLen = Math.max(1, Math.round(SHORT_TERM_SECONDS / subBlock))\n const shortTerm: LoudnessReport['shortTerm'] = []\n for (let k = 0; k < pieces; k += stLen) {\n // A last stretch under one block says nothing a listener would hear.\n if (pieces - k < blockLen && k > 0) break\n shortTerm.push({\n time: Math.round(k * subBlock * 100) / 100,\n loudness: round1(toLufs(windowPower(energies, weights, k, stLen))),\n })\n }\n const st = shortTerm\n .map((s) => s.loudness)\n .filter((l): l is number => l !== null)\n return {\n unit: 'LUFS',\n integrated: round1(integrated),\n shortTerm,\n maxShortTerm: st.length ? Math.max(...st) : null,\n samplePeakDb: peak > 0 ? round1(20 * Math.log10(peak)) : null,\n }\n}\n\n/** The loudness warnings, in words. */\nexport function loudnessWarnings(l: LoudnessReport): string[] {\n if (l.integrated === null)\n return [\n 'the sound is silent: no 400 ms block reaches -70 LUFS, the floor loudness is measured from',\n ]\n if (l.integrated < QUIET_BELOW_LUFS)\n return [\n `integrated loudness ${l.integrated} LUFS is below ${QUIET_BELOW_LUFS}: too quiet for a social feed, where a viewer turns sound up once and keeps it`,\n ]\n if (l.integrated > LOUD_ABOVE_LUFS)\n return [\n `integrated loudness ${l.integrated} LUFS is above ${LOUD_ABOVE_LUFS}: too loud, a platform turns it down and a peak may clip`,\n ]\n return []\n}\n\n/** The scene warnings, in words. */\nexport function sceneWarnings(cuts: readonly SceneChange[]): string[] {\n return crowdedRuns(cuts).map(\n (run) =>\n `${run.length} full-frame changes within ${SCENE_WINDOW} s (at ${run.map((c) => `${c.time.toFixed(2)}s`).join(', ')}): more than one cut in ${SCENE_WINDOW} s is hard to follow`,\n )\n}\n\n/** The poster warning for the first or last frame, in words, or null. */\nexport function posterWarning(\n which: 'first' | 'last',\n deviation: number,\n): string | null {\n if (deviation >= UNIFORM_BELOW) return null\n return which === 'first'\n ? `the first frame is near-uniform (deviation ${deviation.toFixed(2)} of 255): the video opens on an empty or faded frame, which is what a feed shows before it plays`\n : `the last frame is near-uniform (deviation ${deviation.toFixed(2)} of 255): the video ends on an empty or faded frame, which is what a player rests on`\n}\n","/**\n * `vos join <take> <take|file.mp4>… --out <dir> [--keep-edits|--force]\n * [--captions] [--zooms per-beat]`:\n * several takes (and plain video files) as ONE film, cut in argument\n * order, editable as one document.\n *\n * The first input is the PRIMARY: its frame, cursor style, export, audio\n * and its own cut come along as they are. Each next input becomes a media\n * of the document (`m1`, `m2`, …): its footage is copied under `<id>/` in\n * the new take, its segments are appended in order (so the output plays\n * the inputs one after the other), every source-anchored span it carries\n * is tagged with its media and renamed `<id>-…`, and its layers move to\n * where its footage now starts (a layer about one of its steps is anchored\n * to that step instead, so it keeps its moment whatever the cut does).\n * Only the last input keeps its ENDING (the layers that start after its\n * footage); anyone else's would land over the next clip, so it is dropped\n * and named. A\n * plain video file becomes a media with no cursor, a probed meta, a\n * full-bleed card of its own and one segment over its whole length.\n *\n * The document is assembled in memory (`joinDocs`, pure) and must pass\n * `vos validate` before anything is written; `--out` is refused when it\n * exists, unless `--force` names a take directory to replace or\n * `--keep-edits` joins again over it and keeps the edits made since\n * (rejoin.ts). Every join writes `join.json`, the record a re-join matches\n * its inputs against.\n */\nimport { existsSync, readdirSync, statSync } from 'node:fs'\nimport { copyFile, mkdir, readFile, rm } from 'node:fs/promises'\nimport {\n basename,\n dirname,\n isAbsolute,\n join,\n relative,\n resolve,\n sep,\n} from 'node:path'\nimport {\n mediaKey,\n mediaRefId,\n migrateMotion,\n projectFromArtifact,\n ratedSegments,\n layerStart,\n resolveAnchor,\n segmentOutputExtents,\n} from '@vosjs/studio-core'\nimport { totalDuration } from '@vosjs/timeline'\nimport { localFile } from '../programAssets'\nimport { UsageError, parseArgs, strFlag } from './args'\nimport { copyRecording, probeVideoFile } from './ingest'\nimport {\n docMediaRefs,\n docObjectRefs,\n docOverlayRefs,\n isTakeRelativeKey,\n sourceSidecarRefs,\n takeRelativeFile,\n} from './media'\nimport { EXIT_ERROR, EXIT_OK, createReporter } from './output'\nimport { loudnessFact, measureTrack } from './score'\nimport { landStepCaptions } from './stepCaptions'\nimport { publicScript } from './takeScript'\nimport { scriptDrift, scriptDriftLine } from './scriptStep'\nimport { oneZoomPerBeat, perBeatLine, zoomModeOf } from './beats'\nimport {\n JOIN_RECORD_NAME,\n joinRecordOf,\n partFootage,\n readJoinRecord,\n recordFromFootage,\n rejoinDocs,\n rejoinLines,\n} from './rejoin'\nimport type { PerBeatReport } from './beats'\nimport type { RejoinInput } from './rejoin'\nimport { loadTake, writeJson } from './take'\nimport { lintDoc } from './validateDoc'\nimport type {\n OverlayClip,\n Media,\n MediaFrame,\n ProjectDoc,\n RecordingMeta,\n} from '@vosjs/studio-core'\nimport type { ActionsFile } from './actions'\nimport type { ProbedVideo } from './ingest'\nimport type { DocMediaRef } from './media'\nimport type { StepCaptionReport } from './stepCaptions'\n\n/** The card a plain video file wears: the whole frame, no corners, no shadow. */\nexport const FULL_BLEED_FRAME: MediaFrame = {\n inset: { top: 0, right: 0, bottom: 0, left: 0 },\n radius: 0,\n shadow: 0,\n shadowContact: 0,\n border: 0,\n fit: 'cover',\n}\n\n/** One input to a join, read. */\nexport interface JoinPart {\n /** How the input was named, for messages. */\n label: string\n kind: 'take' | 'file'\n /** The input's document (a take's doc.json, or one built for the file). */\n doc: ProjectDoc\n /** Where the document's take-relative keys resolve (a take's directory). */\n dir: string\n /** The actions.json that recorded it, when there is one. */\n actions: ActionsFile | null\n /** A plain file: the video itself, its container, and whether it carries sound. */\n file?: { path: string; ext: ProbedVideo['ext']; hasAudio?: boolean }\n /** Leave a plain file's own sound out (`--mute`). */\n mute?: boolean\n /**\n * The media id this input keeps (a re-join that keeps the edits); absent\n * = the next free one. Never set on the first input, which is the primary.\n */\n id?: string\n /** Its own media's ids in the joined take, by their id in its document (a re-join). */\n subIds?: Record<string, string>\n}\n\n/** A file the joined take needs: its source on disk and its key in the new take. */\nexport interface JoinCopy {\n from: string\n to: string\n /** A plain video file, stream-copied into an indexed container. */\n remux?: ProbedVideo['ext']\n /** The input directory `from` must sit in (a document names files beside it). */\n base?: string\n}\n\nexport interface JoinPlan {\n doc: ProjectDoc\n copies: JoinCopy[]\n /** Each input after the first, and the media id it became. */\n media: { label: string; id: string }[]\n /** actions.json per media key (`''` = the primary), for step captions. */\n actions: Map<string, ActionsFile | null>\n notes: string[]\n /** Each input in argument order: its media id (`''` = the primary) and its own media's. */\n ids: { id: string; sub: Record<string, string> }[]\n /** The layers, props and sound clips placed for a later input, by their id: that input's media id. */\n owners: Map<string, string>\n}\n\nconst round3 = (v: number): number => Math.round(v * 1000) / 1000\n\n/** The fade at each end of a plain file's own sound, seconds. */\nexport const FILE_SOUND_FADE = 0.15\n\n/** The take-relative key a later input's file lands under. */\nconst prefixed = (id: string, key: string): string =>\n `${id}/${takeRelativeFile(key)}`\n\n/** A document for a plain video file: its footage, bare, one segment. */\nexport function fileDoc(\n key: string,\n probed: Pick<\n ProbedVideo,\n 'width' | 'height' | 'durationMs' | 'fps' | 'hasAudio'\n >,\n t0 = 0,\n): ProjectDoc {\n const meta: RecordingMeta = {\n dpr: 1,\n zoom: 1,\n t0,\n durationMs: probed.durationMs,\n width: probed.width,\n height: probed.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 }\n const doc = projectFromArtifact({ videoKey: key, cursor: [], meta }, key, {\n footage: true,\n }).doc\n doc.segments = [{ in: 0, out: round3(probed.durationMs / 1000) }]\n return doc\n}\n\n/**\n * The layers of one input that START after its footage ends: an ending\n * (an end card's words, a closing title) that plays over the held frame or\n * the ground once the footage is over. In a join only the last input's\n * ending is still an ending; anyone else's would land over the next clip.\n * An anchored layer is judged where its anchor places it.\n */\nexport function endingLayers(doc: ProjectDoc): OverlayClip[] {\n const pieces = ratedSegments(doc)\n const end = totalDuration(pieces)\n if (!(end > 0)) return []\n return (doc.overlays ?? []).filter((o) => {\n // A layer placed nowhere (an anchor that resolves to no step, and no\n // start) plays nowhere, so it ends nothing.\n const start = layerStart(o, doc, pieces)\n return start !== null && start >= end - 1e-3\n })\n}\n\n/** Drop an input's ending, saying what went. In place. */\nfunction dropEnding(d: ProjectDoc, label: string, notes: string[]): void {\n const ending = endingLayers(d)\n const legacy = d.endCard !== undefined\n if (!ending.length && !legacy) return\n const gone = new Set(ending)\n d.overlays = (d.overlays ?? []).filter((o) => !gone.has(o))\n if (!d.overlays.length) delete d.overlays\n if (legacy) delete d.endCard\n const named = [\n ...ending.map((o) => o.id),\n ...(legacy ? ['its endCard'] : []),\n ].join(', ')\n notes.push(\n `${label}: dropped ${named}, which played after its footage and would land over the next input (only the last input's ending stays, at the end of the film)`,\n )\n}\n\n/** An input's first clip (its cut, or its whole length). */\nfunction segs0(d: ProjectDoc): { in: number; out: number } | undefined {\n return d.segments.length\n ? d.segments[0]\n : { in: 0, out: round3(d.source.meta.durationMs / 1000) }\n}\n\n/**\n * Assemble the joined document. Pure: no file is read or written; the\n * plan names every file to copy.\n */\nexport function joinDocs(\n parts: readonly JoinPart[],\n opts: { reserved?: Iterable<string> } = {},\n): JoinPlan {\n if (parts.length < 2)\n throw new UsageError('vos join needs two inputs or more')\n const [first, ...rest] = parts\n const doc = structuredClone(first.doc)\n const notes: string[] = []\n // Every input but the last loses its ending before anything is copied.\n dropEnding(doc, first.label, notes)\n const copies = new Map<string, JoinCopy>()\n const copy = (c: JoinCopy) => {\n if (!copies.has(c.to)) copies.set(c.to, c)\n }\n const actions = new Map<string, ActionsFile | null>([['', first.actions]])\n\n // The primary's files keep their keys.\n if (first.file) {\n copy({\n from: first.file.path,\n to: takeRelativeFile(doc.source.videoKey),\n remux: first.file.ext,\n })\n } else {\n const refs: DocMediaRef[] = [\n ...(isTakeRelativeKey(doc.source.videoKey)\n ? [{ where: 'recording', key: doc.source.videoKey, set: () => {} }]\n : []),\n ...sourceSidecarRefs(doc),\n ...docMediaRefs(doc),\n ]\n for (const ref of refs)\n copy({\n from: join(first.dir, takeRelativeFile(ref.key)),\n to: takeRelativeFile(ref.key),\n base: first.dir,\n })\n }\n // An empty list means \"untrimmed\"; once other footage follows, the\n // primary's whole length has to be said.\n if (!doc.segments.length)\n doc.segments = [{ in: 0, out: round3(doc.source.meta.durationMs / 1000) }]\n\n // A fresh id never lands on one a kept input holds, or on one a re-join\n // retired (an id names one media for the life of the take).\n const taken = new Set([\n ...(doc.media ?? []).map((m) => m.id),\n ...(opts.reserved ?? []),\n ...rest.flatMap((p) => [\n ...(p.id ? [p.id] : []),\n ...Object.values(p.subIds ?? {}),\n ]),\n ])\n const ids: JoinPlan['ids'] = [\n {\n id: '',\n sub: Object.fromEntries((doc.media ?? []).map((m) => [m.id, m.id])),\n },\n ]\n const owners = new Map<string, string>()\n const allocate = (): string => {\n let n = 1\n while (taken.has(`m${n}`)) n++\n taken.add(`m${n}`)\n return `m${n}`\n }\n const media: Media[] = [...(doc.media ?? [])]\n const joined: JoinPlan['media'] = []\n /** Each later input's first segment index and its own document, for the layers. */\n const placed: {\n part: JoinPart\n d: ProjectDoc\n pid: string\n firstSegment: number\n mapMedia: (k: string | undefined) => string\n }[] = []\n\n for (const part of rest) {\n // One vocabulary first: a legacy end card is clips, a hold a freeze.\n const d = structuredClone(migrateMotion(part.doc))\n if (part !== rest[rest.length - 1]) dropEnding(d, part.label, notes)\n const pid = part.id ?? allocate()\n const idMap = new Map<string, string>([['', pid]])\n for (const m of d.media ?? [])\n idMap.set(m.id, part.subIds?.[m.id] ?? allocate())\n ids.push({\n id: pid,\n sub: Object.fromEntries(\n (d.media ?? []).map((m) => [m.id, idMap.get(m.id)!]),\n ),\n })\n const mapMedia = (k: string | undefined): string =>\n idMap.get(mediaKey(k)) ?? pid\n joined.push({ label: part.label, id: pid })\n actions.set(pid, part.actions)\n\n // Its files, under `<id>/`: the footage and its sidecars, its other\n // media, and the files its layers and props name. Its frame and its\n // sound are the primary's business and are not brought.\n if (part.file) {\n const to = `${pid}/recording.${part.file.ext}`\n copy({ from: part.file.path, to, remux: part.file.ext })\n d.source.videoKey = to\n } else {\n const refs: DocMediaRef[] = [\n ...(isTakeRelativeKey(d.source.videoKey)\n ? [\n {\n where: 'recording',\n key: d.source.videoKey,\n set: (next: string) => {\n d.source.videoKey = next\n },\n },\n ]\n : []),\n ...sourceSidecarRefs(d),\n ...(d.media ?? []).flatMap((m) =>\n [\n ['videoKey', m.videoKey],\n ['micKey', m.micKey],\n ['camKey', m.camKey],\n ]\n .filter(([, k]) => isTakeRelativeKey(k))\n .map(([field, k]) => ({\n where: `media ${m.id}`,\n key: k as string,\n set: (next: string) => {\n ;(m as unknown as Record<string, string>)[field as string] =\n next\n },\n })),\n ),\n ...docOverlayRefs(d),\n ...docObjectRefs(d),\n ]\n for (const ref of refs) {\n const to = prefixed(pid, ref.key)\n copy({\n from: join(part.dir, takeRelativeFile(ref.key)),\n to,\n base: part.dir,\n })\n ref.set(to)\n }\n }\n\n // Its script rides its media, as a pushed take's rides its source, so\n // its step captions (and the beats they mark) are read from the joined\n // take alone.\n const script =\n !d.source.script && part.actions\n ? publicScript(part.actions as unknown as Record<string, unknown>)\n : undefined\n media.push({\n ...d.source,\n id: pid,\n ...(script ? { script } : {}),\n ...(part.kind === 'file' ? { frame: { ...FULL_BLEED_FRAME } } : {}),\n } as Media)\n for (const m of d.media ?? []) media.push({ ...m, id: idMap.get(m.id)! })\n\n // Its cut, appended: output order is argument order.\n const segs = d.segments.length\n ? d.segments\n : [{ in: 0, out: round3(d.source.meta.durationMs / 1000) }]\n const at = doc.segments.length\n doc.segments.push(...segs.map((s) => ({ ...s, media: mapMedia(s.media) })))\n\n // Its source-anchored spans, tagged with their media and renamed.\n const ns = (id: string) => `${pid}-${id}`\n const tag = <T extends { id: string; media?: string }>(s: T): T => ({\n ...s,\n id: ns(s.id),\n media: mapMedia(s.media),\n })\n doc.zoom = [...doc.zoom, ...d.zoom.map(tag)]\n if (d.speed?.length) doc.speed = [...(doc.speed ?? []), ...d.speed.map(tag)]\n if (d.tilt?.length) doc.tilt = [...(doc.tilt ?? []), ...d.tilt.map(tag)]\n if (d.camMotion?.length)\n doc.camMotion = [...(doc.camMotion ?? []), ...d.camMotion.map(tag)]\n if (d.freeze?.length)\n doc.freeze = [...(doc.freeze ?? []), ...d.freeze.map(tag)]\n if (d.rejected?.length)\n doc.rejected = [...(doc.rejected ?? []), ...d.rejected.map(tag)]\n if (d.audio.length)\n notes.push(\n `${part.label}: its ${d.audio.length} sound clip${d.audio.length === 1 ? '' : 's'} stay behind (the film's sound is the first input's; add a score with vos score)`,\n )\n placed.push({ part, d, pid, firstSegment: at, mapMedia })\n }\n if (media.length) doc.media = media\n\n // The layers: each later input's move to where its footage now starts,\n // or keep their step through an anchor.\n const extents = segmentOutputExtents(doc)\n for (const { part, d, pid, firstSegment, mapMedia } of placed) {\n const offset = extents[firstSegment]?.start ?? 0\n const ownPieces = ratedSegments(d)\n const ns = (id: string) => `${pid}-${id}`\n let dropped = 0\n for (const o of d.overlays ?? []) {\n const next = { ...o, id: ns(o.id) }\n if (next.kind !== 'text' && next.kind !== 'html') {\n const ref = mediaRefId(next.key)\n if (ref !== null) next.key = `media:${mapMedia(ref)}`\n }\n if (o.anchor) {\n next.anchor = { ...o.anchor, media: mapMedia(o.anchor.media) }\n } else if (o.start === undefined) {\n // Neither a time nor a step: validate refuses the joined take.\n } else if (o.pin?.step !== undefined) {\n // A pin reads the PRIMARY's steps and card, so on another media it\n // would point at the wrong thing; its time survives as an anchor.\n const r = resolveAnchor(d, { step: o.pin.step }, ownPieces)\n if (r.start !== null) {\n next.anchor = {\n step: o.pin.step,\n media: pid,\n offset: round3(o.start - r.start),\n }\n } else {\n next.start = round3(o.start + offset)\n }\n delete next.pin\n dropped++\n } else {\n if (o.pin) {\n delete next.pin\n dropped++\n }\n next.start = round3(o.start + offset)\n }\n ;(doc.overlays ??= []).push(next)\n owners.set(next.id, pid)\n }\n if (dropped)\n notes.push(\n `${part.label}: ${dropped} pinned layer${dropped === 1 ? '' : 's'} kept ${dropped === 1 ? 'its' : 'their'} time and lost the pin (a pin places a layer on the first input's footage only)`,\n )\n // A plain file's own sound is part of what it is: a media plays its\n // picture only, so the sound rides the take's audio, keyed to the copied\n // file, starting where the file now plays, trimmed to its clip, with a\n // short fade at each end. A take's added sound is its own choice and\n // stays behind (above).\n if (part.file?.hasAudio) {\n const seg = segs0(d)\n const at = extents[firstSegment]\n if (part.mute) {\n notes.push(`${part.label}: its own sound is left out (--mute)`)\n } else if (seg && at) {\n const len = Math.max(0, seg.out - seg.in)\n const fade = round3(Math.min(FILE_SOUND_FADE, len / 4))\n const id = `${pid}-sound`\n owners.set(id, pid)\n doc.audio = [\n ...doc.audio,\n {\n id,\n key: d.source.videoKey,\n name: basename(part.file.path),\n start: round3(at.start),\n in: round3(seg.in),\n out: round3(seg.out),\n duration: round3(d.source.meta.durationMs / 1000),\n gain: 1,\n fadeIn: fade,\n fadeOut: fade,\n },\n ]\n notes.push(\n `${part.label}: its own sound plays as audio clip ${id}, ${at.start.toFixed(2)}..${(at.start + len).toFixed(2)}s (--mute ${part.label} to leave it out)`,\n )\n }\n }\n for (const ob of d.objects ?? []) {\n owners.set(ns(ob.id), pid)\n ;(doc.objects ??= []).push({\n ...ob,\n id: ns(ob.id),\n ...(ob.span\n ? { span: { ...ob.span, start: round3(ob.span.start + offset) } }\n : {}),\n })\n }\n }\n for (const part of rest)\n if (part.mute && !part.file?.hasAudio)\n notes.push(\n `${part.label}: --mute leaves nothing out (${part.file ? 'the file carries no sound' : \"a take's own footage sound is its recording's; its added sound stays behind anyway\"})`,\n )\n if (first.mute)\n notes.push(\n `${first.label}: --mute leaves nothing out (the first input's sound is the film's own)`,\n )\n // Every anchored layer's fallback start is where it plays now; a layer\n // that carries none keeps none, its anchor is its time.\n const pieces = ratedSegments(doc)\n for (const o of doc.overlays ?? []) {\n if (!o.anchor || o.start === undefined) continue\n const r = resolveAnchor(doc, o.anchor, pieces)\n if (r.start !== null) o.start = r.start\n }\n return {\n doc,\n copies: [...copies.values()],\n media: joined,\n actions,\n notes,\n ids,\n owners,\n }\n}\n\nconst BOOLEAN_FLAGS = new Set([\n 'json',\n 'help',\n 'force',\n 'keep-edits',\n 'captions',\n])\nconst MULTI = new Set(['mute'])\n\nconst USAGE =\n 'vos join <take> <take|file.mp4>… --out <dir> [--keep-edits|--force] [--captions] [--zooms per-beat] [--mute <file>]... [--json]'\n\n/** Is `inner` the same path as `outer`, or inside it? */\nconst within = (inner: string, outer: string): boolean => {\n const rel = relative(outer, inner)\n return (\n rel === '' ||\n (!rel.startsWith(`..${sep}`) && rel !== '..' && !isAbsolute(rel))\n )\n}\n\n/** Read one input: a take directory, or a plain video file. */\nasync function readPart(arg: string): Promise<JoinPart> {\n const path = resolve(arg)\n if (!existsSync(path)) throw new UsageError(`${arg}: no such take or file`)\n if (statSync(path).isDirectory()) {\n if (!existsSync(join(path, 'meta.json')))\n throw new UsageError(\n `${arg}: not a take directory (no meta.json); a video file is joined by its path`,\n )\n const take = await loadTake(path)\n const doc =\n take.doc ??\n projectFromArtifact(\n {\n videoKey: take.paths.recordingName,\n cursor: take.cursor,\n meta: take.meta,\n },\n take.paths.recordingName,\n ).doc\n return { label: arg, kind: 'take', doc, dir: path, actions: take.actions }\n }\n const probed = await probeVideoFile(path)\n if (!(probed.durationMs > 0))\n throw new UsageError(`${arg}: the file reports no duration`)\n const doc = fileDoc(\n `recording.${probed.ext}`,\n probed,\n Math.round(statSync(path).mtimeMs),\n )\n return {\n label: arg,\n kind: 'file',\n doc,\n dir: dirname(path),\n actions: null,\n file: { path, ext: probed.ext, hasAudio: probed.hasAudio },\n }\n}\n\nexport async function cmdJoin(argv: string[]): Promise<number> {\n const { positionals, flags, multi } = parseArgs(argv, BOOLEAN_FLAGS, MULTI)\n const r = createReporter(flags.json === true)\n const outArg = strFlag(flags, 'out')\n const force = flags.force === true\n const keepEdits = flags['keep-edits'] === true\n const withCaptions = flags.captions === true\n const zoomMode = zoomModeOf(strFlag(flags, 'zooms'))\n if (zoomMode && typeof zoomMode === 'object')\n throw new UsageError(zoomMode.error)\n if (positionals.length < 2 || !outArg) throw new UsageError(USAGE)\n if (force && keepEdits)\n throw new UsageError(\n '--force replaces the joined take and --keep-edits keeps its edits; pass one',\n )\n const out = resolve(outArg)\n const inputs = positionals.map((p) => resolve(p))\n const muted = new Set<number>()\n for (const m of multi.mute ?? []) {\n const i = inputs.indexOf(resolve(m))\n if (i < 0)\n throw new UsageError(\n `--mute ${m}: not one of the inputs; name a file as it is given to vos join`,\n )\n muted.add(i)\n }\n for (const [i, input] of inputs.entries()) {\n if (within(out, input) || within(input, out))\n throw new UsageError(\n `--out ${outArg} overlaps the input ${positionals[i]}; write the joined take somewhere of its own`,\n )\n }\n // --keep-edits over a joined take: its edited doc.json is the base.\n let rejoin = false\n if (existsSync(out)) {\n if (!force && !keepEdits)\n throw new UsageError(\n `--out ${outArg} exists; pass --keep-edits to join again and keep every edit made since (its trims, spans, layers, frame, sound), --force to replace it, or name a new directory`,\n )\n if (keepEdits) {\n if (!existsSync(join(out, 'doc.json')))\n throw new UsageError(\n `--keep-edits: ${outArg} holds no doc.json, so there are no edits to keep; name a new directory, or --force to replace it`,\n )\n rejoin = true\n } else {\n const isTake =\n existsSync(join(out, 'doc.json')) || existsSync(join(out, 'meta.json'))\n if (!isTake && readdirSync(out).length > 0)\n throw new UsageError(\n `--force replaces a take directory, and ${outArg} holds other files; name a new directory`,\n )\n }\n if (within(process.cwd(), out))\n throw new UsageError(\n `--out ${outArg} is the working directory or above it; name a new directory`,\n )\n }\n\n const parts: JoinPart[] = []\n const read: RejoinInput[] = []\n for (const [i, p] of positionals.entries()) {\n r.log(`reading ${p}…`)\n const part: JoinPart = {\n ...(await readPart(p)),\n ...(muted.has(i) ? { mute: true } : {}),\n }\n parts.push(part)\n // An input's script edited since it was recorded: said, never refused.\n const drift =\n part.kind === 'take'\n ? scriptDrift(part.doc.source.meta.steps ?? [], part.actions?.steps)\n : null\n if (drift) r.warn(`${p}: ${scriptDriftLine(drift)}`)\n read.push({\n part,\n path: relative(out, inputs[i]) || '.',\n footage: await partFootage(part),\n })\n }\n if (keepEdits && !rejoin)\n r.log(\n `note: --keep-edits: ${outArg} does not exist yet, so this is a fresh join`,\n )\n\n let plan: JoinPlan\n let rejoined: ReturnType<typeof rejoinDocs> | null = null\n if (rejoin) {\n const prev = JSON.parse(\n await readFile(join(out, 'doc.json'), 'utf8'),\n ) as ProjectDoc\n let record = await readJoinRecord(out)\n if (!record) {\n record = await recordFromFootage(out, prev)\n r.log(\n `note: ${outArg} carries no ${JOIN_RECORD_NAME} (joined by an older vos), so its inputs are matched by the footage it holds; a video file joined then was re-encoded on the way in and reads as new`,\n )\n }\n // The record's paths are relative to the take; the done line says them\n // from where the command runs.\n rejoined = rejoinDocs(migrateMotion(prev), record, read, {\n where: (p) => relative(process.cwd(), resolve(out, p)) || '.',\n })\n plan = rejoined.plan\n } else plan = joinDocs(parts)\n // A re-join captions and re-plans only the media it added.\n const only = rejoined ? rejoined.newIds : undefined\n const labelOf = new Map<string, string>([\n ['', positionals[0]],\n ...plan.media.map((m) => [m.id, m.label] as [string, string]),\n ])\n let captions: StepCaptionReport | null = null\n if (withCaptions) {\n captions = landStepCaptions(plan.doc, plan.actions, { only })\n for (const line of captions.held) plan.notes.push(line)\n for (const k of captions.uncaptioned)\n plan.notes.push(\n `no step in ${labelOf.get(k) ?? `media ${k}`} carries a caption`,\n )\n }\n let perBeat: PerBeatReport | null = null\n if (zoomMode === 'per-beat')\n perBeat = oneZoomPerBeat(plan.doc, plan.actions, { only })\n\n // The result must validate before a byte is written.\n const lint = lintDoc(plan.doc)\n if (lint.problems.length) {\n r.log(\n `the joined document does not validate:\\n ${lint.problems.join('\\n ')}`,\n )\n return EXIT_ERROR\n }\n // Every file a document names sits in its own take directory or below\n // (a fetched document is not trusted with the disk), and is there.\n for (const c of plan.copies) {\n if (!c.base) continue\n const found = localFile(relative(c.base, c.from), c.base)\n if ('refused' in found)\n throw new Error(\n `${relative(process.cwd(), c.from) || c.from}, which an input's doc.json names, ${found.refused}; bring its media home first (vos fetch --media) or fix the key`,\n )\n c.from = found.file\n }\n\n if (rejoined) {\n // In place: everything else in the take (its vos.json, a score's\n // track, renders) stays; a media that went takes its directory.\n for (const k of rejoined.dropped) {\n if (!/^[A-Za-z0-9_-]+$/.test(k)) continue\n const dir = join(out, k)\n if (existsSync(dir) && statSync(dir).isDirectory())\n await rm(dir, { recursive: true, force: true })\n }\n } else {\n if (existsSync(out)) await rm(out, { recursive: true, force: true })\n await mkdir(out, { recursive: true })\n }\n for (const c of plan.copies) {\n const to = join(out, c.to)\n await mkdir(dirname(to), { recursive: true })\n if (c.remux) {\n const remuxed = await copyRecording(c.from, to, c.remux)\n // Node decodes no compressed audio, so a file whose sound it cannot\n // read is copied as it is; the render reads it in the browser.\n if (!remuxed && c.remux !== 'mov')\n plan.notes.push(\n `could not read ${basename(c.from)}'s audio in Node, so it was copied as it is; its length comes from the container`,\n )\n } else await copyFile(c.from, to)\n }\n const doc = plan.doc\n // The sound the join added carries what its file measures, so a target\n // can be set on it later without decoding it again. A file that cannot\n // be measured here is copied all the same, and said.\n const added = new Set(\n plan.media\n .filter((m) => !only || only.has(m.id))\n .map((m) => `${m.id}-sound`),\n )\n for (const clip of doc.audio) {\n if (!added.has(clip.id) || !isTakeRelativeKey(clip.key)) continue\n try {\n const m = await measureTrack(join(out, takeRelativeFile(clip.key)))\n if (m.lufs !== null)\n clip.loudness = loudnessFact(\n { lufs: m.lufs, peakDb: m.peakDb },\n clip.key,\n )\n } catch (e) {\n plan.notes.push(\n `could not measure audio clip ${clip.id}'s loudness (${(e instanceof Error ? e.message : String(e)).split('\\n')[0]}); vos audio measure ${outArg} tries again`,\n )\n }\n }\n await writeJson(join(out, 'meta.json'), doc.source.meta, true)\n if (doc.source.cursor.length)\n await writeJson(join(out, 'cursor.json'), doc.source.cursor)\n if (parts[0].actions)\n await writeJson(join(out, 'actions.json'), parts[0].actions, true)\n await writeJson(join(out, 'doc.json'), doc, true)\n await writeJson(\n join(out, JOIN_RECORD_NAME),\n joinRecordOf(read, plan.ids),\n true,\n )\n\n const extents = segmentOutputExtents(doc)\n const length = extents.length ? extents[extents.length - 1].end : 0\n for (const n of plan.notes) r.log(`note: ${n}`)\n for (const w of lint.warnings) r.log(`warning: ${w}`)\n // A re-join captions and re-plans its new inputs alone: say which, or\n // that there were none, never a count over inputs it did not look at.\n // A re-join captions and re-plans its new inputs alone: say which, or\n // that there were none, never a count over inputs it did not look at;\n // and an input with no recorded steps (a video file) is said as such.\n const stepCount = (id: string): number =>\n (doc.media ?? []).find((m) => m.id === id)?.meta.steps?.length ?? 0\n const newMedia = only ? plan.media.filter((m) => only.has(m.id)) : []\n const stepped = newMedia.filter((m) => stepCount(m.id) > 0)\n const bare = newMedia.filter((m) => stepCount(m.id) === 0)\n const bareWords = bare.length\n ? `${bare.map((m) => m.label).join(', ')} ${bare.length === 1 ? 'has' : 'have'} no recorded steps`\n : ''\n const onNew = only ? ` on ${stepped.map((m) => m.label).join(', ')}` : ''\n const captionLine = !captions\n ? ''\n : only && !newMedia.length\n ? '\\n --captions: no new input to caption (a re-join captions only the inputs it adds; the kept ones keep their captions as edited)'\n : only && !stepped.length\n ? `\\n --captions: ${bareWords}, so there is nothing to caption`\n : `\\n ${captions.landed.length} step caption${captions.landed.length === 1 ? '' : 's'} landed${onNew}` +\n (captions.skipped.length\n ? `; not landed: ${captions.skipped.join('; ')}`\n : '') +\n (bareWords ? `; ${bareWords}` : '')\n const beatLine = !perBeat\n ? ''\n : only && !newMedia.length\n ? '\\n --zooms per-beat: no new input to re-plan (a re-join re-plans only the inputs it adds; the kept ones keep their zooms as edited)'\n : only && !stepped.length\n ? `\\n --zooms per-beat: ${bareWords}, so there are no beats to plan`\n : `\\n ${only ? `${stepped.map((m) => m.label).join(', ')}: ` : ''}${perBeatLine(perBeat, (k) => labelOf.get(k) ?? `media ${k}`)}${bareWords ? `; ${bareWords}` : ''}`\n const rejoinText = rejoined\n ? rejoinLines(rejoined.report)\n .map((l) => `\\n ${l}`)\n .join('')\n : ''\n r.done(\n {\n out,\n primary: positionals[0],\n media: plan.media,\n segments: doc.segments.length,\n seconds: round3(length),\n files: plan.copies.map((c) => c.to),\n notes: plan.notes,\n warnings: lint.warnings,\n ...(captions ? { captions } : {}),\n ...(perBeat ? { perBeat } : {}),\n ...(rejoined ? { keptEdits: rejoined.report } : {}),\n },\n `${rejoined ? 'Joined again, keeping the edits:' : 'Joined'} ${parts.length} inputs → ${out} (${length.toFixed(1)}s, ${doc.segments.length} segments)\\n ${positionals[0]} is the primary; ${plan.media.map((m) => `${m.label} → ${m.id}`).join(', ')}${rejoinText}${captionLine}${beatLine}\\n Next: vos info ${outArg}; vos frames ${outArg} --times 0,25%,50%,75%,100%; vos render ${outArg}`,\n )\n return EXIT_OK\n}\n","/**\n * `vos score <take> --track <slug|file> [--at <step|seconds>] [--gain 0..1]\n * [--fade-out <s>] [--dry-run]`: the film's music, timed to the film.\n *\n * A track has a shape: a quiet bar, a build, a SWELL where it opens up. A\n * score lands that swell on the film's payoff. So the track is decoded and\n * measured (a short-term loudness curve: K-weighted LUFS per BS.1770 where\n * the audio allows it, plain RMS dBFS otherwise, labelled either way), its\n * strongest swell is found (the largest sustained rise to a peak), and the\n * audio clip's `in` is set so the swell plays at `--at`: a step, resolved\n * through the cut exactly as an anchored caption is, or output seconds.\n * Without `--at` the track starts where it first rises above its median\n * level, past any near-silent count-in. The clip covers the film (`out` =\n * `in` + the film's length, clamped to the track, said when it cannot).\n *\n * The clip is ONE audio clip with id `score`, written or replaced in\n * doc.json; `--dry-run` prints the plan and the envelope instead.\n *\n * Decoding: mediabunny in Node, which reads PCM (WAV) by itself; a\n * compressed track (the catalog's MP3s) is decoded in the CLI's headless\n * browser, which has the codecs Node lacks, and measured here.\n */\nimport { existsSync } from 'node:fs'\nimport {\n copyFile,\n mkdir,\n mkdtemp,\n readFile,\n rm,\n writeFile,\n} from 'node:fs/promises'\nimport { tmpdir } from 'node:os'\nimport { basename, isAbsolute, join, relative, resolve, sep } from 'node:path'\nimport {\n NORMALIZE_MAX_LUFS,\n NORMALIZE_MIN_LUFS,\n clipGain,\n docMediaList,\n docOutputDuration,\n findStep,\n ratedSegments,\n resolveAnchor,\n} from '@vosjs/studio-core'\nimport { launchBrowser } from '../browser'\nimport { UsageError, numFlag, parseArgs, strFlag } from './args'\nimport { fetchMusicCatalog } from './music'\nimport { EXIT_OK, createReporter } from './output'\nimport { platformOrigin } from './platform'\nimport {\n SUB_BLOCK_SECONDS,\n createLoudnessMeter,\n loudnessFromEnergies,\n} from './videoChecks'\nimport { loadTake, writeJson } from './take'\nimport type { AudioClip, AudioLoudness, ProjectDoc } from '@vosjs/studio-core'\n\n/** The clip a score writes, and replaces on the next run. */\nexport const SCORE_ID = 'score'\n\n/**\n * The loudness a score plays at, LUFS, unless `--normalize` says: the level\n * the hosted catalog masters its tracks to, so a catalog score at the\n * default `--gain 0.5` plays as it did before it had a target, and a file\n * of your own lands at the same level.\n */\nexport const SCORE_NORMALIZE_LUFS = -16\n\n/** The fade a track entered mid-song opens on (seconds), unless `--fade-in` says. */\nexport const MID_SONG_FADE_IN = 0.8\n\n/** Seconds per measured block, the BS.1770 gating block's step. */\nexport const BLOCK_SECONDS = 0.1\n/** The short-term window a level point averages, and the step between points. */\nexport const WINDOW_SECONDS = 1\nexport const HOP_SECONDS = 0.5\n/** A level below this reads as silence (and the curve's floor). */\nconst FLOOR_DB = -70\n\nexport type LoudnessUnit = 'LUFS' | 'dBFS'\n\n// --- K-weighting (BS.1770: a high shelf, then a high pass) ---\n\ninterface Biquad {\n b0: number\n b1: number\n b2: number\n a1: number\n a2: number\n}\n\n/** The two K-weighting stages at a sample rate (the published analog design, bilinear). */\nexport function kWeighting(sampleRate: number): [Biquad, Biquad] {\n const shelf = (() => {\n const f0 = 1681.974450955533\n const G = 3.999843853973347\n const Q = 0.7071752369554196\n const K = Math.tan((Math.PI * f0) / sampleRate)\n const Vh = Math.pow(10, G / 20)\n const Vb = Math.pow(Vh, 0.4996667741545416)\n const a0 = 1 + K / Q + K * K\n return {\n b0: (Vh + (Vb * K) / Q + K * K) / a0,\n b1: (2 * (K * K - Vh)) / a0,\n b2: (Vh - (Vb * K) / Q + K * K) / a0,\n a1: (2 * (K * K - 1)) / a0,\n a2: (1 - K / Q + K * K) / a0,\n }\n })()\n const highPass = (() => {\n const f0 = 38.13547087602444\n const Q = 0.5003270373238773\n const K = Math.tan((Math.PI * f0) / sampleRate)\n const a0 = 1 + K / Q + K * K\n return {\n b0: 1,\n b1: -2,\n b2: 1,\n a1: (2 * (K * K - 1)) / a0,\n a2: (1 - K / Q + K * K) / a0,\n }\n })()\n return [shelf, highPass]\n}\n\n/**\n * Mean-square power per block, summed over channels, fed in chunks of\n * planar samples. K-weighted (LUFS) when the audio is mono or stereo at a\n * rate the filter is defined for; plain (dBFS) otherwise.\n */\nexport class LoudnessMeter {\n readonly unit: LoudnessUnit\n private readonly blockLen: number\n private readonly filters: [Biquad, Biquad] | null\n /** Per channel, per stage: [x1, x2, y1, y2]. */\n private readonly state: number[][][]\n private readonly acc: number[]\n private filled = 0\n readonly blocks: number[] = []\n\n constructor(\n readonly sampleRate: number,\n readonly channels: number,\n ) {\n this.blockLen = Math.max(1, Math.round(sampleRate * BLOCK_SECONDS))\n const weighted = channels >= 1 && channels <= 2 && sampleRate >= 8000\n this.unit = weighted ? 'LUFS' : 'dBFS'\n this.filters = weighted ? kWeighting(sampleRate) : null\n this.state = Array.from({ length: channels }, () => [\n [0, 0, 0, 0],\n [0, 0, 0, 0],\n ])\n this.acc = new Array<number>(channels).fill(0)\n }\n\n /** One chunk: a Float32Array per channel, all the same length. */\n push(planes: readonly Float32Array[]): void {\n const n = planes[0]?.length ?? 0\n for (let i = 0; i < n; i++) {\n for (let c = 0; c < this.channels; c++) {\n let v = planes[c]?.[i] ?? 0\n if (this.filters) {\n for (let k = 0; k < 2; k++) {\n const f = this.filters[k]\n const s = this.state[c][k]\n const y =\n f.b0 * v + f.b1 * s[0] + f.b2 * s[1] - f.a1 * s[2] - f.a2 * s[3]\n s[1] = s[0]\n s[0] = v\n s[3] = s[2]\n s[2] = y\n v = y\n }\n }\n this.acc[c] += v * v\n }\n if (++this.filled === this.blockLen) this.flush()\n }\n }\n\n private flush(): void {\n let power = 0\n for (let c = 0; c < this.channels; c++) {\n // dBFS reads the mean over channels; LUFS sums them (weight 1 each).\n power += this.acc[c] / this.filled\n this.acc[c] = 0\n }\n if (this.unit === 'dBFS') power /= Math.max(1, this.channels)\n this.blocks.push(power)\n this.filled = 0\n }\n\n /** The blocks, the last partial one included. */\n finish(): number[] {\n if (this.filled > this.blockLen / 2) this.flush()\n return this.blocks\n }\n}\n\nexport interface LevelPoint {\n /** The window's centre, track seconds. */\n t: number\n /** Short-term level, in the curve's unit (floored at -70). */\n level: number\n}\n\n/** The short-term level curve from block powers: a 1 s window every 0.5 s. */\nexport function levelCurve(\n blocks: readonly number[],\n unit: LoudnessUnit,\n): LevelPoint[] {\n const per = Math.round(WINDOW_SECONDS / BLOCK_SECONDS)\n const hop = Math.round(HOP_SECONDS / BLOCK_SECONDS)\n const out: LevelPoint[] = []\n for (let i = 0; i + per <= blocks.length; i += hop) {\n let sum = 0\n for (let j = i; j < i + per; j++) sum += blocks[j]\n const mean = sum / per\n const db =\n mean > 0\n ? (unit === 'LUFS' ? -0.691 : 0) + 10 * Math.log10(mean)\n : -Infinity\n out.push({\n t: +((i + per / 2) * BLOCK_SECONDS).toFixed(3),\n level: +Math.max(FLOOR_DB, db).toFixed(2),\n })\n }\n return out\n}\n\nexport interface Swell {\n /** Where the swell ARRIVES (first reaches within 1 dB of its peak), track seconds. */\n at: number\n /** The quiet it rises from, and the peak it reaches. */\n from: number\n peak: number\n /** The rise, in dB (LU for LUFS). */\n rise: number\n peakLevel: number\n}\n\n/** How far back a swell's quiet may lie, seconds. */\nconst SWELL_LOOKBACK = 15\n/** A peak must hold (within 3 dB) this long to count: a swell, not a hit. */\nconst SWELL_SUSTAIN = 1.5\nconst SWELL_HOLD_DB = 3\n/** Arrival: the first point within this of the peak. */\nconst SWELL_ARRIVE_DB = 1\n/** A rise smaller than this is no swell. */\nconst SWELL_MIN_RISE = 3\n/**\n * A level this far under the track's median is the track not yet playing\n * (a fade in from silence): a rise is measured from no lower than it.\n */\nconst SWELL_FLOOR_DB = 12\n/** Seconds after the track first reaches that level before a rise may start. */\nconst SWELL_SETTLE = 5\n\n/**\n * The track's strongest swell: the largest sustained rise to a peak, once\n * the track has established its level. A track that fades in from silence\n * rises tens of dB in its first seconds, and that is the track starting,\n * never a swell: a rise starts no earlier than SWELL_SETTLE after the\n * first moment within SWELL_FLOOR_DB of the median level, and is measured\n * from no lower than that floor.\n */\nexport function findSwell(curve: readonly LevelPoint[]): Swell | null {\n const step = HOP_SECONDS\n const back = Math.round(SWELL_LOOKBACK / step)\n const hold = Math.round(SWELL_SUSTAIN / step)\n const floor = median(curve.map((p) => p.level)) - SWELL_FLOOR_DB\n const begun = curve.findIndex((p) => p.level >= floor)\n if (begun < 0) return null\n const settled = begun + Math.round(SWELL_SETTLE / step)\n const levelAt = (j: number) => Math.max(curve[j].level, floor)\n let best: Swell | null = null\n for (let i = settled + 1; i < curve.length; i++) {\n const p = curve[i]\n // Sustained: the level holds near the peak for a while after it.\n let held = true\n for (let k = i + 1; k <= i + hold; k++) {\n if (k >= curve.length || curve[k].level < p.level - SWELL_HOLD_DB) {\n held = false\n break\n }\n }\n if (!held) continue\n // The quiet it rose from: the lowest point in the lookback, never\n // before the track settled, never lower than the floor.\n let lo = i\n for (let j = Math.max(settled, i - back); j < i; j++)\n if (levelAt(j) < levelAt(lo)) lo = j\n const rise = p.level - levelAt(lo)\n if (rise < SWELL_MIN_RISE) continue\n // Only the summit of a climb is a candidate (a better peak follows it).\n if (i + 1 < curve.length && curve[i + 1].level > p.level) continue\n if (best && rise <= best.rise + 1e-9) continue\n let arrive = i\n for (let k = lo; k <= i; k++) {\n if (curve[k].level >= p.level - SWELL_ARRIVE_DB) {\n arrive = k\n break\n }\n }\n best = {\n at: curve[arrive].t,\n from: curve[lo].t,\n peak: p.t,\n rise: +rise.toFixed(2),\n peakLevel: p.level,\n }\n }\n return best\n}\n\nconst median = (xs: readonly number[]): number => {\n if (!xs.length) return FLOOR_DB\n const s = [...xs].sort((a, b) => a - b)\n const m = Math.floor(s.length / 2)\n return s.length % 2 ? s[m] : (s[m - 1] + s[m]) / 2\n}\n\n/** The first moment the track rises above its median level (its window's start). */\nexport function firstAboveMedian(curve: readonly LevelPoint[]): number {\n const m = median(curve.map((p) => p.level))\n const hit = curve.find((p) => p.level > m)\n return hit ? Math.max(0, +(hit.t - WINDOW_SECONDS / 2).toFixed(3)) : 0\n}\n\nexport interface ScorePlanInput {\n trackDuration: number\n film: number\n curve: readonly LevelPoint[]\n swell: Swell | null\n /** Output seconds the swell should land at; null = start at the first rise. */\n at: number | null\n}\n\nexport interface ScorePlan {\n in: number\n out: number\n /** Output seconds the swell plays at in the planned clip, when there is one. */\n swellAt: number | null\n notes: string[]\n}\n\nconst r3 = (v: number) => Math.round(v * 1000) / 1000\n\n/** Where the clip starts in the track, and what could not be had. */\nexport function planScore(input: ScorePlanInput): ScorePlan {\n const { trackDuration, film, swell } = input\n const notes: string[] = []\n let start: number\n if (input.at !== null) {\n if (!swell) {\n notes.push(\n 'the track has no swell (no sustained rise of 3 dB or more); it starts at its first rise instead',\n )\n start = firstAboveMedian(input.curve)\n } else {\n start = swell.at - input.at\n if (start < 0) {\n notes.push(\n `the swell (${swell.at.toFixed(1)}s into the track) comes before ${input.at.toFixed(1)}s of film can play ahead of it; the track starts at its top and the swell lands at ${swell.at.toFixed(1)}s`,\n )\n start = 0\n }\n }\n } else {\n start = firstAboveMedian(input.curve)\n }\n if (trackDuration < film) {\n notes.push(\n `the track (${trackDuration.toFixed(1)}s) is shorter than the film (${film.toFixed(1)}s); it cannot cover it, so it starts at its top and ends early`,\n )\n start = 0\n } else if (start + film > trackDuration) {\n const fit = Math.max(0, trackDuration - film)\n notes.push(\n `from ${start.toFixed(1)}s the track ends before the film does; it starts at ${fit.toFixed(1)}s instead, so the film is covered${swell && input.at !== null ? ` and the swell lands at ${(swell.at - fit).toFixed(1)}s` : ''}`,\n )\n start = fit\n }\n const out = Math.min(trackDuration, start + film)\n const swellAt =\n swell && swell.at >= start && swell.at <= out ? r3(swell.at - start) : null\n return { in: r3(start), out: r3(out), swellAt, notes }\n}\n\n/** A curve as one line of blocks, a glyph per point (at most `width` of them). */\nexport function sparkline(curve: readonly LevelPoint[], width = 64): string {\n if (!curve.length) return ''\n const glyphs = '▁▂▃▄▅▆▇█'\n const step = Math.max(1, Math.ceil(curve.length / width))\n const pts: number[] = []\n for (let i = 0; i < curve.length; i += step) {\n let m = -Infinity\n for (let j = i; j < Math.min(curve.length, i + step); j++)\n m = Math.max(m, curve[j].level)\n pts.push(m)\n }\n // The top 24 dB is the shape; a fade to silence would flatten the rest.\n const hi = Math.max(...pts)\n const lo = Math.max(Math.min(...pts), hi - 24)\n return pts\n .map(\n (v) =>\n glyphs[\n hi > lo\n ? Math.max(\n 0,\n Math.min(\n glyphs.length - 1,\n Math.floor(((v - lo) / (hi - lo)) * glyphs.length),\n ),\n )\n : 0\n ],\n )\n .join('')\n}\n\n// --- decoding ---\n\nexport interface Measured {\n sampleRate: number\n channels: number\n duration: number\n unit: LoudnessUnit\n blocks: number[]\n /**\n * BS.1770 integrated loudness of the whole file (K-weighted, gated), by\n * the meter `vos check-video` reads a render with; null for silence.\n */\n lufs: number | null\n /** Sample peak, dBFS; null for digital silence. */\n peakDb: number | null\n /**\n * The gated meter's per-channel K-weighted energies, one per\n * `SUB_BLOCK_SECONDS`: what a stretch of the file measures is read from\n * them (`spanLoudness`) without decoding it again.\n */\n energies: number[][]\n /** Which decoder read it. */\n via: 'node' | 'browser'\n}\n\n/** Both meters over one decode: the level curve's and the integrated one. */\nfunction meters(sampleRate: number, channels: number) {\n const curve = new LoudnessMeter(sampleRate, channels)\n const gated = createLoudnessMeter(sampleRate, channels, SUB_BLOCK_SECONDS)\n return {\n push(planes: Float32Array[]) {\n curve.push(planes)\n gated.push(planes)\n },\n finish() {\n const g = gated.finish()\n const l = loudnessFromEnergies(g.energies, g.peak)\n return {\n unit: curve.unit,\n blocks: curve.finish(),\n lufs: l.integrated,\n peakDb: l.samplePeakDb,\n energies: g.energies,\n }\n },\n }\n}\n\n/** Decode in Node with mediabunny (PCM needs no codec); null when it cannot. */\nasync function measureInNode(path: string): Promise<Measured | null> {\n const MB = await import('mediabunny')\n const input = new MB.Input({\n formats: MB.ALL_FORMATS,\n source: new MB.FilePathSource(path),\n })\n try {\n const track = await input.getPrimaryAudioTrack()\n if (!track) throw new UsageError(`${path} has no audio track`)\n if (!(await track.canDecode())) return null\n const meter = meters(track.sampleRate, track.numberOfChannels)\n const sink = new MB.AudioSampleSink(track)\n let frames = 0\n for await (const sample of sink.samples()) {\n const planes: Float32Array[] = []\n for (let c = 0; c < track.numberOfChannels; c++) {\n const a = new Float32Array(sample.numberOfFrames)\n sample.copyTo(a, { planeIndex: c, format: 'f32-planar' })\n planes.push(a)\n }\n frames += sample.numberOfFrames\n sample.close()\n meter.push(planes)\n }\n return {\n sampleRate: track.sampleRate,\n channels: track.numberOfChannels,\n duration: frames / track.sampleRate,\n ...meter.finish(),\n via: 'node',\n }\n } finally {\n await input.dispose?.()\n }\n}\n\n/** Seconds of samples per round trip out of the page. */\nconst PAGE_CHUNK_SECONDS = 10\n\n/** The largest file handed to the page whole, bytes. */\nexport const BROWSER_DECODE_MAX_BYTES = 200 * 1024 * 1024\n\n/** Decode in the headless browser (its codecs), measure here. */\nasync function measureInBrowser(path: string): Promise<Measured> {\n const bytes = await readFile(path)\n if (bytes.length > BROWSER_DECODE_MAX_BYTES)\n throw new Error(\n `${basename(path)} is ${Math.round(bytes.length / 1048576)} MB, past the ${BROWSER_DECODE_MAX_BYTES / 1048576} MB the browser decode takes whole`,\n )\n const browser = await launchBrowser()\n try {\n const page = await browser.newPage()\n // Strings, not functions: nothing a bundler adds to a function body\n // reaches the page.\n const info = (await page.evaluate(`(async () => {\n const b64 = ${JSON.stringify(bytes.toString('base64'))}\n const bin = atob(b64)\n const u8 = new Uint8Array(bin.length)\n for (let i = 0; i < bin.length; i++) u8[i] = bin.charCodeAt(i)\n const ctx = new OfflineAudioContext(1, 1, 48000)\n const buf = await ctx.decodeAudioData(u8.buffer)\n window.__vosScore = buf\n return { sampleRate: buf.sampleRate, channels: buf.numberOfChannels, length: buf.length }\n })()`)) as { sampleRate: number; channels: number; length: number }\n const meter = meters(info.sampleRate, info.channels)\n const chunk = Math.round(info.sampleRate * PAGE_CHUNK_SECONDS)\n for (let from = 0; from < info.length; from += chunk) {\n const parts = (await page.evaluate(`(() => {\n const buf = window.__vosScore\n const out = []\n for (let c = 0; c < buf.numberOfChannels; c++) {\n const a = buf.getChannelData(c).subarray(${from}, ${from + chunk})\n const u8 = new Uint8Array(a.buffer, a.byteOffset, a.byteLength)\n let s = ''\n for (let i = 0; i < u8.length; i += 0x8000)\n s += String.fromCharCode.apply(null, u8.subarray(i, i + 0x8000))\n out.push(btoa(s))\n }\n return out\n })()`)) as string[]\n meter.push(\n parts.map((p) => {\n const b = Buffer.from(p, 'base64')\n return new Float32Array(b.buffer, b.byteOffset, b.byteLength / 4)\n }),\n )\n }\n return {\n sampleRate: info.sampleRate,\n channels: info.channels,\n duration: info.length / info.sampleRate,\n ...meter.finish(),\n via: 'browser',\n }\n } finally {\n await browser.close()\n }\n}\n\n/** Decode and measure a track file. */\nexport async function measureTrack(path: string): Promise<Measured> {\n return (await measureInNode(path)) ?? (await measureInBrowser(path))\n}\n\n/**\n * The integrated loudness of the stretch `[from, to)` of a measured file,\n * seconds: what a clip that plays only that stretch sounds like. Null for\n * silence.\n */\nexport function spanLoudness(\n m: Pick<Measured, 'energies'>,\n from: number,\n to: number,\n): number | null {\n const a = Math.max(0, Math.floor(from / SUB_BLOCK_SECONDS))\n const b = Math.max(a + 1, Math.ceil(to / SUB_BLOCK_SECONDS))\n return loudnessFromEnergies(\n m.energies.map((e) => e.slice(a, b)),\n 0,\n ).integrated\n}\n\n/** What a measurement stores beside the clip it was taken for. */\nexport function loudnessFact(\n m: { lufs: number; peakDb: number | null },\n key: string,\n): AudioLoudness {\n return {\n lufs: m.lufs,\n peakDb: m.peakDb,\n at: new Date().toISOString(),\n src: key,\n }\n}\n\n// --- the verb ---\n\n/**\n * `--at`: output seconds, or a step (its id, or `step:<index>`;\n * `<media>:<step>` for another media's), resolved through the cut like an\n * anchor.\n */\nexport function resolveAt(\n doc: ProjectDoc,\n raw: string,\n): { at: number; via: string } {\n const trimmed = raw.trim()\n // A bare number is seconds; `step:<n>` names a step by its index.\n if (/^\\d+(\\.\\d+)?s?$/.test(trimmed)) {\n const at = parseFloat(trimmed)\n return { at, via: `${at}s` }\n }\n const v = trimmed.startsWith('step:') ? trimmed.slice(5) : trimmed\n const pieces = ratedSegments(doc)\n const colon = v.indexOf(':')\n const named =\n colon > 0 ? { media: v.slice(0, colon), step: v.slice(colon + 1) } : null\n const candidates = named\n ? [named]\n : docMediaList(doc)\n .filter(({ source }) => findStep(source.meta.steps ?? [], v))\n .map(({ id }) => ({ media: id, step: v }))\n if (!candidates.length)\n throw new UsageError(\n `--at ${raw}: no step by that id or index in this take (and not a number of seconds)`,\n )\n if (candidates.length > 1)\n throw new UsageError(\n `--at ${raw}: steps of several media carry it; say which, as <media>:<step> (${candidates.map((c) => `${c.media || 'primary'}`).join(', ')})`,\n )\n const c = candidates[0]\n const r = resolveAnchor(\n doc,\n { step: c.step, ...(c.media ? { media: c.media } : {}) },\n pieces,\n )\n if (r.start === null)\n throw new UsageError(\n `--at ${raw}: that step ${r.miss === 'cut' ? 'is cut out of the film' : r.miss === 'skipped' ? 'was skipped by the recorder' : 'is not in the take'}`,\n )\n return { at: r.start, via: `step ${v} (${r.start.toFixed(2)}s)` }\n}\n\n/** The track a `--track` names: a file here, or a catalog slug. */\nasync function resolveTrack(\n dir: string,\n ref: string,\n flags: Record<string, string | true>,\n dryRun: boolean,\n): Promise<{\n path: string\n key: string\n name: string\n cleanup?: () => Promise<void>\n}> {\n const local = resolve(ref)\n if (existsSync(local)) {\n const rel = relative(resolve(dir), local)\n // A file beside the take is named where it is; one from elsewhere is\n // copied into the take's music/ (the document names files beside it).\n const inside =\n !!rel && !rel.startsWith(`..${sep}`) && rel !== '..' && !isAbsolute(rel)\n const key = inside ? rel.split(sep).join('/') : `music/${basename(local)}`\n if (!inside && !dryRun) {\n await mkdir(join(dir, 'music'), { recursive: true })\n await copyFile(local, join(dir, key))\n }\n return { path: local, key, name: basename(local) }\n }\n const origin = platformOrigin({\n origin: strFlag(flags, 'origin'),\n api: strFlag(flags, 'api'),\n })\n const catalog = await fetchMusicCatalog(origin)\n const track = catalog.tracks.find((t) => t.slug === ref)\n if (!track)\n throw new UsageError(\n `--track ${ref}: no such file, and no catalog track by that slug (some: ${catalog.tracks\n .slice(0, 6)\n .map((t) => t.slug)\n .join(', ')}; the list is GET ${origin}/api/music)`,\n )\n const res = await fetch(track.url)\n if (!res.ok) throw new Error(`GET ${track.url} answered ${res.status}`)\n const tmp = await mkdtemp(join(tmpdir(), 'vos-score-'))\n const path = join(tmp, basename(new URL(track.url).pathname) || 'track')\n await writeFile(path, new Uint8Array(await res.arrayBuffer()))\n return {\n path,\n key: track.url,\n name: track.title,\n cleanup: () => rm(tmp, { recursive: true, force: true }),\n }\n}\n\nconst BOOLEAN_FLAGS = new Set(['json', 'help', 'dry-run'])\n\nconst USAGE =\n 'vos score <take> --track <slug|file> [--at <step id|output seconds>] [--gain 0..1] [--normalize <lufs|off>] [--fade-in <s>] [--fade-out <s>] [--dry-run] [--json]'\n\nexport async function cmdScore(argv: string[]): Promise<number> {\n const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS)\n const dir = positionals[0]\n const trackRef = strFlag(flags, 'track')\n if (!dir || !trackRef) throw new UsageError(USAGE)\n const r = createReporter(flags.json === true)\n const dryRun = flags['dry-run'] === true\n const gain = numFlag(flags, 'gain', 0.5)\n if (!(gain >= 0 && gain <= 1))\n throw new UsageError('--gain expects a number from 0 to 1')\n const fadeOut = numFlag(flags, 'fade-out', 1.5)\n if (!(fadeOut >= 0)) throw new UsageError('--fade-out expects seconds ≥ 0')\n const normalizeFlag = strFlag(flags, 'normalize')\n const normalize =\n normalizeFlag === 'off'\n ? null\n : numFlag(flags, 'normalize', SCORE_NORMALIZE_LUFS)\n if (\n normalize !== null &&\n !(normalize >= NORMALIZE_MIN_LUFS && normalize <= NORMALIZE_MAX_LUFS)\n )\n throw new UsageError(\n `--normalize expects LUFS from ${NORMALIZE_MIN_LUFS} to ${NORMALIZE_MAX_LUFS}, or off`,\n )\n const fadeInFlag = strFlag(flags, 'fade-in')\n const fadeInAsked = numFlag(flags, 'fade-in', MID_SONG_FADE_IN)\n if (!(fadeInAsked >= 0)) throw new UsageError('--fade-in expects seconds ≥ 0')\n const take = await loadTake(dir)\n if (!take.doc)\n throw new UsageError(`${dir} has no doc.json; run vos plan first`)\n const doc = take.doc\n const atRaw = strFlag(flags, 'at')\n const at = atRaw !== undefined ? resolveAt(doc, atRaw) : null\n\n const track = await resolveTrack(dir, trackRef, flags, dryRun)\n let measured: Measured\n try {\n r.log(`measuring ${track.name}…`)\n measured = await measureTrack(track.path)\n } finally {\n await track.cleanup?.()\n }\n const curve = levelCurve(measured.blocks, measured.unit)\n const swell = findSwell(curve)\n const film = docOutputDuration(doc)\n const plan = planScore({\n trackDuration: measured.duration,\n film,\n curve,\n swell,\n at: at ? at.at : null,\n })\n const clip: AudioClip = {\n id: SCORE_ID,\n key: track.key,\n name: track.name,\n start: 0,\n in: plan.in,\n out: plan.out,\n duration: r3(measured.duration),\n gain,\n // A track entered mid-song opens on a fade, never a cut into the bar;\n // one that starts at its own top needs none unless asked.\n fadeIn: Math.min(\n fadeInFlag !== undefined || plan.in > 0 ? fadeInAsked : 0,\n Math.max(0, plan.out - plan.in),\n ),\n fadeOut: Math.min(fadeOut, Math.max(0, plan.out - plan.in)),\n ...(doc.source.micKey ? { duck: true } : {}),\n // The level is a target over what the file measures: the gain above\n // is a trim on top of it.\n ...(measured.lufs !== null\n ? {\n ...(normalize !== null ? { normalize } : {}),\n loudness: loudnessFact(\n { lufs: measured.lufs, peakDb: measured.peakDb },\n track.key,\n ),\n }\n : {}),\n }\n if (normalize !== null && measured.lufs === null)\n plan.notes.push(\n 'the track measured as silence, so it carries no loudness target',\n )\n const levels = curve.map((p) => p.level)\n const envelope = {\n unit: measured.unit,\n weighted: measured.unit === 'LUFS',\n decoder: measured.via,\n sampleRate: measured.sampleRate,\n channels: measured.channels,\n min: levels.length ? Math.min(...levels) : null,\n median: levels.length ? median(levels) : null,\n max: levels.length ? Math.max(...levels) : null,\n points: curve,\n }\n const others = doc.audio.filter((a) => a.id !== SCORE_ID && a.start < 0.05)\n if (others.length)\n plan.notes.push(\n `${others.map((a) => a.id).join(', ')} also play${others.length === 1 ? 's' : ''} from the top; two tracks under one film rarely mean to`,\n )\n if (!dryRun) {\n doc.audio = [...doc.audio.filter((a) => a.id !== SCORE_ID), clip]\n await writeJson(take.paths.doc, doc, true)\n }\n const label = measured.unit === 'LUFS' ? 'LUFS, K-weighted' : 'dBFS RMS'\n const played = clipGain(clip)\n // What the film hears is the stretch it plays, not the whole file.\n const heard = spanLoudness(measured, plan.in, plan.out)\n /** The loudness the film hears, LUFS: the stretch at the gain it plays at. */\n const playsAt =\n heard !== null && played.gain > 0\n ? Math.round((heard + 20 * Math.log10(played.gain)) * 10) / 10\n : null\n const levelWords =\n played.basis === 'normalize' && measured.lufs !== null\n ? `at about ${(playsAt ?? measured.lufs + 20 * Math.log10(played.gain)).toFixed(1)} LUFS over the stretch it plays (target ${normalize}, --gain ${gain} as a trim on it; the whole track measures ${measured.lufs.toFixed(1)} LUFS${heard !== null ? `, that stretch ${heard.toFixed(1)}` : ''}, so gain ${played.gain.toFixed(2)}${played.capped === 'peak' ? ', held there so its peak stays under -1 dBFS' : played.capped ? ', the most a target lifts' : ''})`\n : `at gain ${gain}`\n const swellLine = swell\n ? `swell: +${swell.rise.toFixed(1)} dB from ${swell.from.toFixed(1)}s, arriving ${swell.at.toFixed(1)}s into the track (peak ${swell.peakLevel.toFixed(1)} ${measured.unit} at ${swell.peak.toFixed(1)}s)`\n : 'swell: none (no sustained rise of 3 dB or more)'\n const placeLine =\n at && plan.swellAt !== null\n ? `the track starts at ${plan.in.toFixed(2)}s, so the swell lands at ${plan.swellAt.toFixed(2)}s of film (asked: ${at.via})`\n : `the track starts at ${plan.in.toFixed(2)}s${at ? ` (asked: ${at.via})` : ', its first rise above its median level'}`\n r.done(\n {\n take: resolve(dir),\n dryRun,\n track: { key: track.key, name: track.name, duration: clip.duration },\n film: r3(film),\n swell,\n at: at?.at ?? null,\n clip,\n playsAt,\n notes: plan.notes,\n envelope,\n },\n `${dryRun ? 'Would score' : 'Scored'} ${dir} with ${track.name} (${measured.duration.toFixed(1)}s, ${label})\\n ${sparkline(curve)}\\n ${swellLine}\\n ${placeLine}; it plays ${plan.in.toFixed(2)}..${plan.out.toFixed(2)} under the ${film.toFixed(1)}s film ${levelWords}${plan.notes.length ? `\\n note: ${plan.notes.join('\\n note: ')}` : ''}${dryRun ? '\\n (dry run: doc.json untouched)' : `\\n audio clip \"${SCORE_ID}\" ${doc.audio.length > 1 ? 'written beside the others' : 'written'} in doc.json`}`,\n )\n return EXIT_OK\n}\n","/**\n * Step captions: every recorder step that carries a `caption` (two to eight\n * words in actions.json) becomes a text layer ANCHORED to that step, in the\n * house caption style. The anchor is what keeps it honest: the lowering\n * places it where the step plays in the cut, so a trim or a speed change\n * moves it with no edit, and `start` is written too, as the fallback and as\n * what a reader of the document sees.\n *\n * The captions it lands are stamped `from: 'steps'`, so a second run\n * replaces exactly those and nothing a person wrote; a step that already\n * has a caption anchored to it (or the plan's own caption for it) is left\n * alone. Pure: the caller hands in each media's actions.json.\n */\nimport {\n docMediaList,\n findStep,\n mediaKey,\n overlayPlainText,\n ratedSegments,\n resolveAnchor,\n segmentOutputExtents,\n} from '@vosjs/studio-core'\nimport { totalDuration } from '@vosjs/timeline'\nimport { CAPTION_MAX, CAPTION_MIN, fitCaptions, heldLine } from './captionFit'\nimport { CAPTION_ID_PREFIX, houseCaption } from './motionPlan'\nimport { scriptStepOf } from './scriptStep'\nimport type {\n OverlayAnchor,\n OverlayClip,\n ProjectDoc,\n StepSpan,\n} from '@vosjs/studio-core'\nimport type { ActionsFile } from './actions'\n\n/** The provenance a landed step caption carries. */\nexport const STEP_CAPTIONS_FROM = 'steps'\n\n/**\n * Where a step caption lands: as its step BEGINS (`at: \"start\"`, no\n * offset), so the words name the beat while it plays. Landing after the\n * gesture ended ran a caption over the next beat's payoff.\n */\nexport const STEP_CAPTION_AT = 'start' as const\n\nexport interface StepCaptionReport {\n /** Captions landed (each `media` absent = the primary). */\n landed: { id: string; step: string | number; media?: string; start: number }[]\n /** Steps with a caption that did not land, in words. */\n skipped: string[]\n /** Landed captions kept past their step to be read, in words. */\n held: string[]\n /** The media (`''` = the primary) that have steps and not one caption among them. */\n uncaptioned: string[]\n}\n\n/**\n * A step's caption: on the step itself, else its actions.json step, else\n * the document's embedded script. `recorded` is the media's recorded steps,\n * which find the script step a recorded one was made from when the script\n * was edited after recording (`scriptStepOf`).\n */\nexport function captionOf(\n step: StepSpan,\n actions: ActionsFile | null | undefined,\n script: Record<string, unknown> | undefined,\n recorded: readonly StepSpan[] = [],\n): string | null {\n const own = (step as { caption?: unknown }).caption\n if (typeof own === 'string' && own.trim()) return own.trim()\n for (const list of [\n actions?.steps,\n Array.isArray(script?.steps) ? (script.steps as unknown[]) : undefined,\n ]) {\n const raw = scriptStepOf(step, list, recorded)\n if (typeof raw?.caption === 'string' && raw.caption.trim())\n return raw.caption.trim()\n }\n return null\n}\n\nconst safeId = (v: string | number): string =>\n String(v)\n .replace(/[^A-Za-z0-9_-]+/g, '-')\n .replace(/^-+|-+$/g, '') || 'step'\n\n/**\n * Land every step's caption on `doc` as a step-anchored layer. `actions`\n * maps a media key (`''` = the primary, else a `media[].id`) to the\n * actions.json that recorded it. Mutates `doc`; answers what it did.\n */\nexport function landStepCaptions(\n doc: ProjectDoc,\n actions: ReadonlyMap<string, ActionsFile | null>,\n opts: { only?: ReadonlySet<string> } = {},\n): StepCaptionReport {\n const report: StepCaptionReport = {\n landed: [],\n skipped: [],\n held: [],\n uncaptioned: [],\n }\n // `only` (a re-join): land the captions of these media alone, and keep\n // every other media's step captions as they were edited.\n const mine = (o: OverlayClip) =>\n !opts.only || opts.only.has(mediaKey(o.anchor?.media))\n const kept = (doc.overlays ?? []).filter(\n (o) => o.from !== STEP_CAPTIONS_FROM || !mine(o),\n )\n const rated = ratedSegments(doc)\n const footageEnd = totalDuration(rated)\n // Where each clip of the cut ends, and whose it is: a caption is about\n // its media and never outlives the clip it starts in (after a join, the\n // next clip is someone else's footage).\n const docSegments = (\n doc.segments.length\n ? doc.segments\n : [{ in: 0, out: doc.source.meta.durationMs / 1000 }]\n ) as { media?: string }[]\n const extents = segmentOutputExtents(doc)\n const clipEnd = (start: number, media: string): number => {\n for (let i = 0; i < extents.length; i++) {\n const e = extents[i]\n if (\n mediaKey(docSegments[i]?.media) === media &&\n start >= e.start - 1e-6 &&\n start < e.end - 1e-6\n )\n return e.end\n }\n return footageEnd\n }\n const ends = new Map<OverlayClip, number>()\n const labels = new Map<OverlayClip, string>()\n const untils = new Map<OverlayClip, number>()\n /** Does a caption the run keeps already speak for this step? */\n const spoken = (media: string, step: StepSpan, steps: StepSpan[]) =>\n kept.some((o) => {\n if (o.kind !== 'text' || o.preset !== 'caption') return false\n if (o.anchor && mediaKey(o.anchor.media) === media)\n return findStep(steps, o.anchor.step) === step\n // The plan's own beat caption (`vos plan` on the primary).\n return media === '' && o.id === `${CAPTION_ID_PREFIX}${step.step}`\n })\n const fresh: (OverlayClip & { start: number })[] = []\n const taken = new Set(kept.map((o) => o.id))\n for (const { id: media, source } of docMediaList(doc)) {\n if (opts.only && !opts.only.has(media)) continue\n const steps = source.meta.steps ?? []\n let captioned = 0\n for (const step of steps) {\n const caption = captionOf(step, actions.get(media), source.script, steps)\n if (!caption) continue\n captioned++\n const ref = step.id ?? step.step\n const label = `step ${JSON.stringify(ref)}${media ? ` of ${media}` : ''}`\n if (step.skipped) {\n report.skipped.push(`${label}: the recorder skipped it`)\n continue\n }\n if (spoken(media, step, steps)) {\n report.skipped.push(`${label}: a caption is already anchored to it`)\n continue\n }\n const anchor: OverlayAnchor = {\n step: ref,\n ...(media ? { media } : {}),\n at: STEP_CAPTION_AT,\n }\n const placed = resolveAnchor(doc, anchor, rated)\n if (placed.start === null) {\n report.skipped.push(`${label}: the cut leaves it out`)\n continue\n }\n const end = clipEnd(placed.start, media)\n if (placed.start >= end - CAPTION_MIN) {\n report.skipped.push(`${label}: it plays in the last second of its clip`)\n continue\n }\n const base = `step-${media ? `${media}-` : ''}${safeId(ref)}`\n let id = base\n for (let n = 2; taken.has(id); n++) id = `${base}-${n}`\n taken.add(id)\n const clip: OverlayClip & { start: number } = {\n ...houseCaption(id, caption, placed.start, CAPTION_MAX),\n start: placed.start,\n anchor,\n from: STEP_CAPTIONS_FROM,\n }\n ends.set(clip, end)\n // Where the step ends in the cut: the caption leaves with it.\n const stepEnd = resolveAnchor(doc, { ...anchor, at: 'end' }, rated)\n if (stepEnd.start !== null) untils.set(clip, stepEnd.start)\n labels.set(clip, label)\n fresh.push(clip)\n report.landed.push({\n id,\n step: ref,\n ...(media ? { media } : {}),\n start: placed.start,\n })\n }\n if (steps.length && !captioned) report.uncaptioned.push(media)\n }\n // In playing order, each caption leaves when its step ends (or once its\n // words are read), gives way to the next one and ends with the clip it\n // starts in; one that cannot be read before the next is dropped and said,\n // never left on screen beside it.\n const fit = fitCaptions(fresh, (c) => ({\n start: c.start,\n end: ends.get(c) ?? footageEnd,\n ...(untils.has(c) ? { until: untils.get(c) } : {}),\n ...(c.kind === 'text' ? { text: overlayPlainText(c) } : {}),\n }))\n for (const { item, why } of fit.dropped) {\n report.skipped.push(`${labels.get(item) ?? item.id}: ${why}`)\n report.landed = report.landed.filter((l) => l.id !== item.id)\n }\n for (const k of fit.kept)\n if (k.held)\n report.held.push(heldLine(labels.get(k.item) ?? k.item.id, k.held))\n const landedClips = fit.kept.map(({ item, duration }) => {\n item.duration = duration\n return item\n })\n const overlays = [...kept, ...landedClips]\n if (overlays.length) doc.overlays = overlays\n else delete doc.overlays\n return report\n}\n\n/**\n * `vos plan`'s argv with a bare `--captions` (no value after it) read as\n * `--captions=steps`: land the step captions. `--captions none` keeps its\n * meaning (the plan proposes no captions).\n */\nexport function bareCaptionsFlag(argv: readonly string[]): string[] {\n return argv.map((a, i) =>\n a === '--captions' && (i + 1 >= argv.length || argv[i + 1].startsWith('--'))\n ? '--captions=steps'\n : a,\n )\n}\n","/**\n * The script step a RECORDED step was made from, in a script that may have\n * been edited since the take was recorded (a mark, an id, a check added).\n *\n * A recorded step (`meta.steps[]`) keeps the index it had in the script it\n * ran, so `list[step.step]` is that step only while nothing was inserted\n * before it. An agent edits `actions.json` after recording (that is the\n * point of a mark that works on the next plan), and one `expect` added\n * early would hand every later unnamed step its neighbour's caption or\n * mark. So: a named step is found by its id; an unnamed one by its place\n * beside the nearest recorded named step before it and after it (the way\n * `vos plan --reuse` re-finds a step), else at its own index; in every case\n * the verb must agree (and the selector, when both say one), a script step\n * that carries the id of ANOTHER recorded step is never this one, and two\n * places that disagree are no answer. Pure.\n */\nimport type { StepSpan } from '@vosjs/studio-core'\n\ntype Raw = Record<string, unknown>\n\nconst asRaw = (v: unknown): Raw | undefined =>\n typeof v === 'object' && v !== null && !Array.isArray(v)\n ? (v as Raw)\n : undefined\n\nexport function scriptStepOf(\n step: StepSpan,\n list: unknown,\n recorded: readonly StepSpan[] = [],\n): Raw | undefined {\n if (!Array.isArray(list)) return undefined\n const steps = list.map(asRaw)\n const indexOfId = (id: string): number => steps.findIndex((s) => s?.id === id)\n if (step.id !== undefined) {\n const at = indexOfId(String(step.id))\n if (at >= 0) return steps[at]\n }\n const recordedIds = new Set(\n recorded\n .filter((r) => r !== step && r.id !== undefined)\n .map((r) => String(r.id)),\n )\n const fits = (s: Raw | undefined): s is Raw =>\n !!s &&\n s.do === step.do &&\n !(typeof s.id === 'string' && recordedIds.has(s.id)) &&\n !(\n typeof s.selector === 'string' &&\n typeof step.selector === 'string' &&\n s.selector !== step.selector\n )\n const named = recorded.filter(\n (r) => r !== step && r.id !== undefined && indexOfId(String(r.id)) >= 0,\n )\n const before = named\n .filter((r) => r.step < step.step)\n .sort((a, b) => b.step - a.step)[0]\n const after = named\n .filter((r) => r.step > step.step)\n .sort((a, b) => a.step - b.step)[0]\n const found = new Set<Raw>()\n for (const anchor of [before, after]) {\n if (!anchor) continue\n const hit = steps[indexOfId(String(anchor.id)) + step.step - anchor.step]\n if (fits(hit)) found.add(hit)\n }\n if (found.size === 1) return [...found][0]\n if (found.size > 1) return undefined\n const own = steps[step.step]\n return fits(own) ? own : undefined\n}\n\n/** How a script differs from what was recorded from it. */\nexport interface ScriptDrift {\n /** Steps the take recorded (`meta.steps`). */\n recorded: number\n /** Steps in the script now. */\n inScript: number\n /** Recorded steps the script no longer has as they were: another verb or selector, or not found. */\n changed: { step: number; id?: string; was: string; now: string | null }[]\n}\n\n/**\n * The script against the steps recorded from it, or null when they still\n * agree: as many steps, each recorded step found (`scriptStepOf`) with its\n * verb and its selector. Pure.\n */\nexport function scriptDrift(\n recorded: readonly StepSpan[],\n list: unknown,\n): ScriptDrift | null {\n if (!Array.isArray(list) || !recorded.length) return null\n const changed: ScriptDrift['changed'] = []\n for (const step of recorded) {\n const raw = scriptStepOf(step, list, recorded)\n const id = step.id !== undefined ? { id: String(step.id) } : {}\n if (!raw) {\n changed.push({ step: step.step, ...id, was: step.do, now: null })\n continue\n }\n const selectorMoved =\n typeof raw.selector === 'string' &&\n typeof step.selector === 'string' &&\n raw.selector !== step.selector\n if (raw.do !== step.do || selectorMoved)\n changed.push({\n step: step.step,\n ...id,\n was: step.selector ? `${step.do} ${step.selector}` : step.do,\n now:\n typeof raw.selector === 'string'\n ? `${String(raw.do)} ${raw.selector}`\n : String(raw.do),\n })\n }\n if (list.length === recorded.length && !changed.length) return null\n return { recorded: recorded.length, inScript: list.length, changed }\n}\n\n/** The drift in one line: what differs, and how captions and marks are matched despite it. */\nexport function scriptDriftLine(d: ScriptDrift, file = 'actions.json'): string {\n const counts =\n d.inScript === d.recorded\n ? `${file} no longer matches what was recorded`\n : `${file} has ${d.inScript} step${d.inScript === 1 ? '' : 's'} and the take recorded ${d.recorded} (meta.steps)`\n const shown = d.changed\n .slice(0, 3)\n .map(\n (c) =>\n `#${c.step}${c.id ? ` ${c.id}` : ''} was ${c.was}, ${c.now === null ? 'not found in the file' : `now ${c.now}`}`,\n )\n const changed = d.changed.length\n ? `; ${d.changed.length} recorded step${d.changed.length === 1 ? '' : 's'} changed (${shown.join('; ')}${d.changed.length > 3 ? '; …' : ''})`\n : ''\n return `${counts}${changed}: captions and zoom marks are matched to the recorded steps by id, then by place beside a named step, then by index (vos info shows where each lands; record again to bring them back in step)`\n}\n","/**\n * One zoom per beat (`vos plan --zooms per-beat`, `vos join --zooms\n * per-beat`), and the script's `zoom` marks (`applyZoomMarks`).\n *\n * The zoom planner proposes a span per gesture, which is right for a form\n * and far too busy for a canvas, where every drag, label and copy is a\n * gesture. The script already says where the beats are: a step that\n * carries a `caption` (the words `--captions` lands) starts one. A beat\n * runs from its captioned step's start until the next captioned step of\n * the same media starts, the last one to the media's end; what plays\n * before the first captioned step is one more beat, the opening.\n *\n * Which zoom a beat keeps is the SCRIPT's to say, because no rule read off\n * the steps finds the payoff a person picks (it is sometimes the first\n * gesture, sometimes the last, sometimes the typing between): a step\n * marked `\"zoom\": true` is a beat's payoff. A beat keeps, for each marked\n * step, the proposal that overlaps it most (ties: the one the cut plays\n * longest, then the longer, then the higher level, then the earlier),\n * never two that overlap; a beat with no marked step keeps NO zoom. When\n * no step of the take is marked at all, each beat's LAST gesture (a\n * click, a drag, typing or a paste; never a key press, which closes a beat\n * more often than it pays it off) stands in for the mark, the opening\n * keeps none, and the report says so. A step marked `\"zoom\": false` is\n * never zoomed on, in either case. A mark never invents a zoom: a marked\n * step the planner proposed nothing for is named.\n *\n * A span belongs to the beat its midpoint falls in. The others are\n * deleted the way a person deletes a proposal: each becomes a\n * `doc.rejected` entry, so no re-plan proposes it again. The one kept is\n * promoted to `manual`, because a rejected extent can overlap it by half\n * and would otherwise take it too on the next re-plan. A beat that already\n * holds a manual zoom keeps every manual one and loses its proposals. A\n * media none of whose steps carries a caption has no beats: its zooms stay\n * as the planner proposed them, and the report names it.\n *\n * A mark is read from the take's actions.json first (edited after the\n * recording, it takes effect on the next plan, no re-record), then from\n * the step the recorder kept (`meta.steps[].zoom`), then from the script a\n * pushed or joined take carries (`script`). Pure; mutates the document it\n * is handed.\n */\nimport { docMediaList, mediaKey, rejectSpan } from '@vosjs/studio-core'\nimport { scriptStepOf } from './scriptStep'\nimport { captionOf } from './stepCaptions'\nimport type { ProjectDoc, StepSpan, ZoomSpan } from '@vosjs/studio-core'\nimport type { ActionsFile } from './actions'\n\n/** The note a per-beat rejection carries. */\nexport const PER_BEAT_NOTE = 'one zoom per beat'\n\n/** The note a rejection carries when the script says never to zoom on a step. */\nexport const ZOOM_FALSE_NOTE = 'zoom: false in the script'\n\n/** The values `--zooms` takes. */\nexport const ZOOM_MODES = ['per-beat'] as const\nexport type ZoomMode = (typeof ZOOM_MODES)[number]\n\n/** `--zooms <mode>`, read: null when absent, a usage message when unknown. */\nexport function zoomModeOf(\n raw: string | undefined,\n): ZoomMode | null | { error: string } {\n if (raw === undefined) return null\n if ((ZOOM_MODES as readonly string[]).includes(raw)) return raw as ZoomMode\n return {\n error: `--zooms expects ${ZOOM_MODES.join(' or ')}, got \"${raw}\"`,\n }\n}\n\n/** The gestures a beat's last one is read from when the script marks none: no key press. */\nexport const LAST_GESTURE_VERBS: readonly string[] = [\n 'click',\n 'drag',\n 'type',\n 'paste',\n]\n\n/** A step of one media as a beat names it: its index, id, verb and own span. */\nexport interface BeatStep {\n step: number\n id?: string\n do: string\n in: number\n out: number\n}\n\n/** One beat of one media, in that media's SOURCE seconds. */\nexport interface Beat {\n /** The media key (`''` = the primary). */\n media: string\n /** The captioned step that starts it (its id, else its index); null for the opening. */\n step: string | number | null\n caption: string | null\n in: number\n out: number\n /** Its steps marked `\"zoom\": true`, in order. */\n marked: BeatStep[]\n /** Its last click, drag, typing or paste not marked `\"zoom\": false`: the stand-in when the take marks nothing. */\n lastGesture?: BeatStep\n}\n\n/** The script's `zoom` mark on a recorded step: actions.json, then the step, then the carried script. */\nexport function zoomMarkOf(\n step: StepSpan,\n actions: ActionsFile | null | undefined,\n script: Record<string, unknown> | undefined,\n recorded: readonly StepSpan[] = [],\n): boolean | undefined {\n const inList = (list: unknown): boolean | undefined => {\n const raw = scriptStepOf(step, list, recorded)\n return typeof raw?.zoom === 'boolean' ? raw.zoom : undefined\n }\n return (\n inList(actions?.steps) ??\n (typeof step.zoom === 'boolean' ? step.zoom : undefined) ??\n inList(script?.steps)\n )\n}\n\nconst beatStep = (s: StepSpan): BeatStep => ({\n step: s.step,\n ...(s.id ? { id: s.id } : {}),\n do: s.do,\n in: s.tStart,\n out: Math.max(s.tStart, s.tEnd),\n})\n\n/** A media's steps that ran, in time order, each with its `zoom` mark. */\nfunction markedSteps(\n source: ProjectDoc['source'],\n actions: ActionsFile | null | undefined,\n): { s: StepSpan; mark: boolean | undefined }[] {\n return [...(source.meta.steps ?? [])]\n .filter((s) => typeof s.tStart === 'number' && !s.skipped)\n .sort((a, b) => a.tStart - b.tStart || a.step - b.step)\n .map((s) => ({\n s,\n mark: zoomMarkOf(s, actions, source.script, source.meta.steps ?? []),\n }))\n}\n\n/**\n * A media's beats: one per captioned step, plus the opening before the\n * first. Empty when no step carries a caption.\n */\nexport function mediaBeats(\n media: string,\n source: ProjectDoc['source'],\n actions: ActionsFile | null | undefined,\n): Beat[] {\n const end = (source.meta.durationMs || 0) / 1000\n const starts: { step: StepSpan; caption: string }[] = []\n for (const step of source.meta.steps ?? []) {\n if (typeof step.tStart !== 'number') continue\n const caption = captionOf(\n step,\n actions,\n source.script,\n source.meta.steps ?? [],\n )\n if (caption) starts.push({ step, caption })\n }\n if (!starts.length) return []\n starts.sort((a, b) => a.step.tStart - b.step.tStart)\n const steps = markedSteps(source, actions)\n const beat = (\n step: string | number | null,\n caption: string | null,\n from: number,\n to: number,\n last: boolean,\n ): Beat => {\n const mine = steps.filter(\n (x) => x.s.tStart >= from && (x.s.tStart < to || last),\n )\n const gesture = mine\n .filter((x) => LAST_GESTURE_VERBS.includes(x.s.do) && x.mark !== false)\n .at(-1)\n return {\n media,\n step,\n caption,\n in: from,\n out: to,\n marked: mine.filter((x) => x.mark === true).map((x) => beatStep(x.s)),\n ...(gesture ? { lastGesture: beatStep(gesture.s) } : {}),\n }\n }\n const beats: Beat[] = []\n if (starts[0].step.tStart > 0)\n beats.push(beat(null, null, 0, starts[0].step.tStart, false))\n starts.forEach(({ step, caption }, i) => {\n const next = starts[i + 1]\n beats.push(\n beat(\n step.id ?? step.step,\n caption,\n step.tStart,\n next ? next.step.tStart : Math.max(end, step.tStart),\n !next,\n ),\n )\n })\n return beats\n}\n\n/** The source seconds of a span that the cut keeps, on its own media. */\nexport function playedSeconds(doc: ProjectDoc, z: ZoomSpan): number {\n const key = mediaKey(z.media)\n const segments = doc.segments.length\n ? doc.segments\n : [{ in: 0, out: doc.source.meta.durationMs / 1000 }]\n let played = 0\n for (const s of segments) {\n if (mediaKey((s as { media?: string }).media) !== key) continue\n played += Math.max(0, Math.min(s.out, z.out) - Math.max(s.in, z.in))\n }\n return played\n}\n\n/** Milliseconds, so two spans of one length never part on float noise. */\nconst ms = (v: number): number => Math.round(v * 1000)\n\n/**\n * How much of a step a span covers, seconds; an instant step (an\n * `expect`) inside the span counts as covered, by a hair.\n */\nexport function stepOverlap(\n z: { in: number; out: number },\n step: { in: number; out: number } | undefined,\n): number {\n if (!step) return 0\n const shared = Math.min(z.out, step.out) - Math.max(z.in, step.in)\n if (shared > 0) return shared\n return step.out - step.in < 1e-3 && z.in <= step.in && step.in <= z.out\n ? 1e-6\n : 0\n}\n\n/** A span is ON a step when they share more than half of the shorter of the two. */\nexport function onStep(\n z: { in: number; out: number },\n step: { in: number; out: number },\n): boolean {\n const shorter = Math.min(z.out - z.in, step.out - step.in)\n return shorter > 0\n ? stepOverlap(z, step) > shorter / 2\n : stepOverlap(z, step) > 0\n}\n\n/** Among the proposals on a step: played longest, then longest, then higher, then earlier. */\nfunction stronger(doc: ProjectDoc) {\n return (a: ZoomSpan, b: ZoomSpan): number =>\n ms(playedSeconds(doc, b)) - ms(playedSeconds(doc, a)) ||\n ms(b.out - b.in) - ms(a.out - a.in) ||\n b.level - a.level ||\n a.in - b.in\n}\n\nconst overlaps = (a: ZoomSpan, b: ZoomSpan) => a.in < b.out && b.in < a.out\n\n/** A beat as the report names it: its caption. */\nexport interface BeatWords {\n media: string\n step: string | number | null\n caption: string | null\n}\n\n/** A step a beat zoomed on, or meant to: its index and verb. */\nexport interface BeatTarget {\n step: number\n do: string\n}\n\nexport interface PerBeatReport {\n /** No step of the take carries `\"zoom\": true`: each beat's last gesture stood in. */\n fallback: boolean\n /** One per kept zoom: the beat, the step it is on, the span. */\n kept: (BeatWords & { action: BeatTarget; id: string })[]\n /**\n * Beats, or marked steps, that kept nothing: no proposal in the beat at\n * all (`empty`; a captioned beat only, never the opening), no step marked\n * (`unmarked`), the opening under the fallback (`opening`), no gesture to\n * stand in (`no-gesture`), or a marked step with no proposal on it\n * (`no-proposal`).\n */\n none: (BeatWords & {\n why: 'empty' | 'unmarked' | 'opening' | 'no-gesture' | 'no-proposal'\n action?: BeatTarget\n /** On an `empty` beat: the steps it marks, which had nothing to keep. */\n marked?: BeatTarget[]\n ids: string[]\n })[]\n /** Beats that hold a manual zoom already; their proposals were rejected. */\n manual: { media: string; step: string | number | null; ids: string[] }[]\n /** How many proposals went into `doc.rejected`. */\n rejected: number\n /** Media keys whose steps carry no caption: their zooms are untouched. */\n uncaptioned: string[]\n /** How many beats held a zoom, over every media looked at. */\n beats: number\n}\n\n/** Whether any step of the document's media carries `\"zoom\": true`. */\nexport function takeMarksZoom(\n doc: ProjectDoc,\n actions: ReadonlyMap<string, ActionsFile | null>,\n): boolean {\n return docMediaList(doc).some(({ id, source }) =>\n markedSteps(source, actions.get(id)).some((x) => x.mark === true),\n )\n}\n\n/** Reject a set of zooms into `doc.rejected` with a note; returns how many. */\nfunction rejectAll(doc: ProjectDoc, drop: Set<ZoomSpan>, note: string): number {\n if (!drop.size) return 0\n const rejected = [...(doc.rejected ?? [])]\n for (const z of doc.zoom) {\n if (!drop.has(z)) continue\n const entry = rejectSpan(rejected, 'zoom', z, note)\n if (z.media) entry.media = z.media\n rejected.push(entry)\n }\n doc.rejected = rejected\n doc.zoom = doc.zoom.filter((z) => !drop.has(z))\n return drop.size\n}\n\n/**\n * Keep at most one zoom per marked step of each beat on every media (or\n * only on `only`, the media keys a join just added). `actions` maps a\n * media key to the actions.json that recorded it; a media's embedded\n * script is read when it has none.\n */\nexport function oneZoomPerBeat(\n doc: ProjectDoc,\n actions: ReadonlyMap<string, ActionsFile | null>,\n opts: { only?: ReadonlySet<string> } = {},\n): PerBeatReport {\n const fallback = !takeMarksZoom(doc, actions)\n const report: PerBeatReport = {\n fallback,\n kept: [],\n none: [],\n manual: [],\n rejected: 0,\n uncaptioned: [],\n beats: 0,\n }\n const drop = new Set<ZoomSpan>()\n const refused = new Set<ZoomSpan>()\n const order = stronger(doc)\n for (const { id: media, source } of docMediaList(doc)) {\n if (opts.only && !opts.only.has(media)) continue\n const beats = mediaBeats(media, source, actions.get(media))\n const spans = doc.zoom.filter((z) => mediaKey(z.media) === media)\n if (!beats.length) {\n if (spans.length) report.uncaptioned.push(media)\n continue\n }\n // Never zoom on a step marked so.\n const never = markedSteps(source, actions.get(media))\n .filter((x) => x.mark === false)\n .map((x) => beatStep(x.s))\n for (const z of spans) if (never.some((s) => onStep(z, s))) refused.add(z)\n for (const beat of beats) {\n const inBeat = spans.filter((z) => {\n const mid = (z.in + z.out) / 2\n return mid >= beat.in && mid < beat.out\n })\n if (inBeat.length) report.beats++\n const manual = inBeat.filter((z) => z.source === 'manual')\n const auto = inBeat.filter((z) => z.source !== 'manual')\n if (manual.length) {\n for (const z of auto) drop.add(z)\n if (auto.length)\n report.manual.push({\n media,\n step: beat.step,\n ids: manual.map((z) => z.id),\n })\n continue\n }\n const words: BeatWords = {\n media,\n step: beat.step,\n caption: beat.caption,\n }\n // A captioned beat the planner proposed nothing in is said too.\n if (!inBeat.length) {\n if (beat.step !== null)\n report.none.push({\n ...words,\n why: 'empty',\n ids: [],\n ...(beat.marked.length\n ? {\n marked: beat.marked.map((m) => ({ step: m.step, do: m.do })),\n }\n : {}),\n })\n continue\n }\n const targets = fallback\n ? beat.step === null || !beat.lastGesture\n ? []\n : [beat.lastGesture]\n : beat.marked\n if (!targets.length) {\n for (const z of auto) drop.add(z)\n if (auto.length)\n report.none.push({\n ...words,\n why: !fallback\n ? 'unmarked'\n : beat.step === null\n ? 'opening'\n : 'no-gesture',\n ids: auto.map((z) => z.id),\n })\n continue\n }\n const candidates = auto.filter((z) => !never.some((s) => onStep(z, s)))\n const chosen: ZoomSpan[] = []\n for (const target of targets) {\n const action = { step: target.step, do: target.do }\n const [best] = candidates\n .filter(\n (z) =>\n stepOverlap(z, target) > 0 &&\n !chosen.some((c) => c === z || overlaps(c, z)),\n )\n .sort(\n (a, b) =>\n ms(stepOverlap(b, target)) - ms(stepOverlap(a, target)) ||\n order(a, b),\n )\n if (!best) {\n report.none.push({ ...words, why: 'no-proposal', action, ids: [] })\n continue\n }\n chosen.push(best)\n report.kept.push({ ...words, action, id: best.id })\n }\n for (const z of chosen) z.source = 'manual'\n for (const z of auto) if (!chosen.includes(z)) drop.add(z)\n }\n }\n // A proposal on a step the script says never to zoom on is rejected for\n // that reason, whichever beat it sat in.\n const onNever = new Set([...drop].filter((z) => refused.has(z)))\n for (const z of onNever) drop.delete(z)\n report.rejected =\n rejectAll(doc, onNever, ZOOM_FALSE_NOTE) +\n rejectAll(doc, drop, PER_BEAT_NOTE)\n return report\n}\n\n/** What the script's `zoom` marks did to a plan. */\nexport interface ZoomMarkReport {\n /** Proposals rejected because they sat on a step marked `\"zoom\": false`. */\n rejected: { media: string; step: number; ids: string[] }[]\n /** Steps marked `\"zoom\": true` the planner proposed no zoom on: none is invented. */\n unproposed: { media: string; step: number; id?: string; do: string }[]\n}\n\n/**\n * The marks on a plain plan: every proposal ON a step marked\n * `\"zoom\": false` is rejected like a person's delete (so no re-plan\n * proposes it again), and every step marked `\"zoom\": true` with no zoom\n * on it is named. A manual zoom is the person's and is never touched.\n */\nexport function applyZoomMarks(\n doc: ProjectDoc,\n actions: ReadonlyMap<string, ActionsFile | null>,\n): ZoomMarkReport {\n const report: ZoomMarkReport = { rejected: [], unproposed: [] }\n const drop = new Set<ZoomSpan>()\n for (const { id: media, source } of docMediaList(doc)) {\n const spans = doc.zoom.filter((z) => mediaKey(z.media) === media)\n for (const { s, mark } of markedSteps(source, actions.get(media))) {\n const step = beatStep(s)\n if (mark === false) {\n const on = spans.filter(\n (z) => z.source !== 'manual' && !drop.has(z) && onStep(z, step),\n )\n for (const z of on) drop.add(z)\n if (on.length)\n report.rejected.push({\n media,\n step: s.step,\n ids: on.map((z) => z.id),\n })\n } else if (\n mark === true &&\n !spans.some((z) => !drop.has(z) && stepOverlap(z, step) > 0)\n ) {\n report.unproposed.push({\n media,\n step: s.step,\n ...(s.id ? { id: s.id } : {}),\n do: s.do,\n })\n }\n }\n }\n rejectAll(doc, drop, ZOOM_FALSE_NOTE)\n return report\n}\n\n/** The marks' report in words, or null when they did nothing. */\nexport function zoomMarkLine(\n r: ZoomMarkReport,\n name: (media: string) => string = (m) => (m ? `media ${m}` : 'the primary'),\n): string | null {\n const at = (x: { media: string; step: number }) =>\n `#${x.step}${x.media ? ` of ${name(x.media)}` : ''}`\n const parts: string[] = []\n if (r.rejected.length)\n parts.push(\n `zoom: false rejected ${r.rejected.map((x) => `${x.ids.join(', ')} on step ${at(x)}`).join('; ')}`,\n )\n if (r.unproposed.length)\n parts.push(\n `zoom: true on ${r.unproposed.map((x) => `step ${at(x)} ${x.id ? `${x.id} ` : ''}${x.do}`).join(', ')}, but the planner proposed no zoom there (none is invented)`,\n )\n return parts.length ? parts.join('; ') : null\n}\n\n/** The report in words, one line, for a done line. */\nexport function perBeatLine(\n r: PerBeatReport,\n name: (media: string) => string = (m) => (m ? `media ${m}` : 'the primary'),\n): string {\n const parts = [\n `one zoom per beat: ${r.beats} beat${r.beats === 1 ? '' : 's'} held zooms, ${r.kept.length} kept (now manual), ${r.rejected} rejected into doc.rejected (no re-plan brings them back)`,\n ]\n if (r.fallback)\n parts.push(\n 'no step is marked \"zoom\": falling back to each beat\\'s last gesture',\n )\n const beatName = (b: BeatWords) =>\n b.step === null\n ? `the opening${b.media ? ` of ${name(b.media)}` : ''}`\n : `beat ${b.caption ? JSON.stringify(b.caption) : String(b.step)}${b.media ? ` (${name(b.media)})` : ''}`\n const target = (a: BeatTarget) =>\n `${r.fallback ? 'last gesture' : 'marked'} #${a.step} ${a.do}`\n // The beats that kept a zoom first, then the rest.\n for (const b of r.kept)\n parts.push(`${beatName(b)}: ${target(b.action)}, kept ${b.id}`)\n for (const b of r.none)\n parts.push(\n `${beatName(b)}: ${\n b.why === 'empty'\n ? `no proposal in this beat${b.marked?.length ? ` (marked ${b.marked.map((m) => `#${m.step} ${m.do}`).join(', ')})` : ''}`\n : b.why === 'no-proposal' && b.action\n ? `${target(b.action)}, but no proposal on it`\n : b.why === 'unmarked'\n ? 'no step marked \"zoom\", no zoom'\n : b.why === 'no-gesture'\n ? 'no gesture to stand in, no zoom'\n : 'no zoom'\n }`,\n )\n if (r.manual.length)\n parts.push(\n `${r.manual.length} beat${r.manual.length === 1 ? '' : 's'} kept ${r.manual.length === 1 ? 'its' : 'their'} manual zoom${r.manual.some((m) => m.ids.length > 1) ? 's' : ''}`,\n )\n if (r.uncaptioned.length)\n parts.push(\n `no captioned step in ${r.uncaptioned.map(name).join(', ')}, so ${r.uncaptioned.length === 1 ? 'its' : 'their'} zooms stay as planned`,\n )\n return parts.join('; ')\n}\n","/**\n * `vos join … --out <take> --keep-edits`: join again over a joined take\n * that has been edited since, and keep the edits.\n *\n * A joined take is cut after the join: segments trimmed and reordered,\n * speed spans, zooms kept or rejected, captions written and anchored, the\n * frame, the sound, the still, the export. Joining again to add an input\n * (a cold open, a scene recorded later) or to reorder them used to rebuild\n * the document from the inputs and lose all of it. With `--keep-edits` the\n * edited document is the base, and the inputs only say what is new and\n * what is gone:\n *\n * - Inputs are matched to the media they became by their SOURCE FILE,\n * never by position: the joined take keeps a `join.json` naming each\n * input's path and the sha256 of its footage. The same footage at the\n * same path is the same media (the same footage at a new path too: a\n * moved directory). A take joined before `join.json` existed is matched\n * by the footage it holds (a take's footage is copied byte for byte),\n * and a video file joined then reads as new, since the join re-encoded\n * its container.\n * - A RE-RECORDED input keeps its edits, re-timed by its steps the way\n * `vos plan --reuse` re-times a cut onto a new recording of the same\n * script (`retimeCut`, one mapping): a take whose footage changed at the\n * same path, or a take at a new path that recorded the same script (most\n * of the old take's named steps are in the new one, and the url agrees).\n * It comes in under a new media id; its segments take the old ones'\n * place in the cut, re-timed; its manual spans and rejections follow the\n * steps they sat on; the planner's fresh proposals for it fill in where\n * no kept span or rejection stands; a layer anchored to one of its steps\n * stays on that step when the new take has it; a layer placed by output\n * second over its footage keeps its place in the scene. What cannot be\n * placed (a span on a step the new take lacks, a layer anchored to one)\n * is dropped and named. A plain video file has no steps to re-time by,\n * so a changed file is still a removal plus an addition.\n * - A kept input keeps its media id, its media entry, and everything on it\n * as edited: segments, every source-anchored span (zoom, speed, tilt,\n * cam moves, freezes, rejections), its sound clip, and every layer\n * anchored to one of its steps. The film-wide fields (frame, cursor,\n * cam, export, styles) are the edited document's.\n * - A new input is joined the way a fresh join would join it, under an id\n * no media ever held, and only its own media are re-planned (`--zooms\n * per-beat`) or captioned (`--captions`).\n * - An input that is gone takes its edits with it, named: its segments,\n * its spans, the layers anchored to it or placed over its footage, its\n * sound clip.\n * - Order: while the kept inputs keep their relative order, the edited\n * segment list stands as it is (a cold open moved to the front stays\n * there) and a new input's segments go just before the first segment of\n * the next kept input in argument order, or at the end. When the kept\n * inputs' order changes, the segments are regrouped in argument order,\n * each input's own segments keeping their edited order, and the report\n * says so.\n * - A layer, prop, sound clip or still placed at an output second (no\n * anchor) follows the segment it played in, so a new input before it\n * does not slide it onto other footage; one past the footage (an ending)\n * stays past the new end. A film-wide sound clip (a score) keeps its\n * seconds, and the report names a changed length.\n * - The first input must be the take's primary, unchanged: the primary\n * carries the cut's frame and camera, and a different one is a\n * different film (join it afresh with --force).\n *\n * Pure (`rejoinDocs`); the I/O halves read and write `join.json` and hash\n * footage.\n */\nimport { createHash } from 'node:crypto'\nimport { createReadStream, existsSync } from 'node:fs'\nimport { readFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport {\n isRejected,\n layerStart,\n mediaKey,\n mediaRefId,\n ratedSegments,\n resolveAnchor,\n segmentOutputExtents,\n} from '@vosjs/studio-core'\nimport { totalDuration } from '@vosjs/timeline'\nimport { splitSegmentsAtSkips } from '@vosjs/render-core/record'\nimport { UsageError } from './args'\nimport { joinDocs } from './join'\nimport { isTakeRelativeKey, takeRelativeFile } from './media'\nimport { retimeCut } from './reuse'\nimport type {\n DocSegment,\n Media,\n OverlayClip,\n ProjectDoc,\n RejectedSpan,\n} from '@vosjs/studio-core'\nimport type { JoinPart, JoinPlan } from './join'\nimport type { ReusedCut } from './reuse'\n\n/** The record a joined take keeps of what it was joined from. */\nexport const JOIN_RECORD_NAME = 'join.json'\n\nexport interface JoinedInput {\n /** The input as given, relative to the joined take; '' when unknown. */\n path: string\n kind: 'take' | 'file'\n /** sha256 of the input's footage as the join read it. */\n footage: string\n /** The media id it became (`''` = the primary). */\n media: string\n /** Its own media's ids in the joined take, by their id in its document. */\n sub?: Record<string, string>\n}\n\nexport interface JoinRecord {\n version: 1\n inputs: JoinedInput[]\n}\n\n/** One input of the new join, read: the part, its path relative to the take, its footage hash. */\nexport interface RejoinInput {\n part: JoinPart\n path: string\n footage: string\n}\n\nexport interface RejoinReport {\n kept: { label: string; id: string; moved?: string }[]\n added: { label: string; id: string }[]\n dropped: {\n input: string\n id: string\n why: 'removed' | 'changed'\n segments: number\n spans: number\n layers: string[]\n sound: string[]\n }[]\n /**\n * Inputs recorded again since the join: their edits re-timed onto the\n * new footage by its steps, under a new media id; what could not be\n * placed is named in `flagged`.\n */\n rerecorded: {\n label: string\n /** The old media id and the new one. */\n from: string\n id: string\n /** The prior input's path, when it was found at another one. */\n was?: string\n segments: number\n spans: number\n layers: string[]\n /** What needs a look, in words: what was dropped, trimmed or interpolated, and why. */\n flagged: string[]\n }[]\n /** The kept inputs changed order, so the segments play in argument order again. */\n regrouped: boolean\n /** Layers, props, sound clips and the still that moved with their footage. */\n shifted: string[]\n notes: string[]\n}\n\nconst round3 = (v: number): number => Math.round(v * 1000) / 1000\n\n/** sha256 of a file, streamed. */\nexport function fileHash(file: string): Promise<string> {\n return new Promise((done, fail) => {\n const h = createHash('sha256')\n createReadStream(file)\n .on('data', (c) => h.update(c))\n .on('error', fail)\n .on('end', () => done(h.digest('hex')))\n })\n}\n\n/** The fingerprint of an input's footage: its file's bytes, or a hosted key itself. */\nexport async function partFootage(part: JoinPart): Promise<string> {\n if (part.file) return fileHash(part.file.path)\n const key = part.doc.source.videoKey\n if (!isTakeRelativeKey(key))\n return `key:${createHash('sha256').update(key).digest('hex')}`\n const file = join(part.dir, takeRelativeFile(key))\n return existsSync(file)\n ? fileHash(file)\n : `key:${createHash('sha256').update(key).digest('hex')}`\n}\n\n/** The take's `join.json`, or null when it has none (or one this CLI cannot read). */\nexport async function readJoinRecord(dir: string): Promise<JoinRecord | null> {\n const file = join(dir, JOIN_RECORD_NAME)\n if (!existsSync(file)) return null\n try {\n const v = JSON.parse(await readFile(file, 'utf8')) as JoinRecord\n return v && v.version === 1 && Array.isArray(v.inputs) ? v : null\n } catch {\n return null\n }\n}\n\n/**\n * A record for a take joined before `join.json`: each media's footage as\n * the take holds it, in the document's order (the primary first). A\n * take's footage was copied byte for byte, so it matches its input.\n */\nexport async function recordFromFootage(\n dir: string,\n doc: ProjectDoc,\n): Promise<JoinRecord> {\n const hash = async (key: string) => {\n if (!isTakeRelativeKey(key))\n return `key:${createHash('sha256').update(key).digest('hex')}`\n const file = join(dir, takeRelativeFile(key))\n return existsSync(file) ? fileHash(file) : `missing:${key}`\n }\n const inputs: JoinedInput[] = [\n {\n path: '',\n kind: 'take',\n footage: await hash(doc.source.videoKey),\n media: '',\n },\n ]\n for (const m of doc.media ?? [])\n inputs.push({\n path: '',\n kind: 'take',\n footage: await hash(m.videoKey),\n media: m.id,\n })\n return { version: 1, inputs }\n}\n\n/** The record a join writes beside its document. */\nexport function joinRecordOf(\n inputs: readonly { path: string; footage: string; part: JoinPart }[],\n ids: JoinPlan['ids'],\n): JoinRecord {\n return {\n version: 1,\n inputs: inputs.map((x, i) => {\n const sub = ids[i]?.sub ?? {}\n return {\n path: x.path,\n kind: x.part.kind,\n footage: x.footage,\n media: ids[i]?.id ?? '',\n ...(Object.keys(sub).length ? { sub } : {}),\n }\n }),\n }\n}\n\n/**\n * Which new input is which old one. Two passes so a duplicate input (the\n * same take twice) pairs in order: the same footage at the same path,\n * then the same footage anywhere. A prior input whose path comes back\n * with other footage CHANGED; one that does not come back is REMOVED.\n */\nexport function matchInputs(\n prev: readonly JoinedInput[],\n next: readonly { path: string; footage: string }[],\n): {\n match: (number | null)[]\n changed: number[]\n removed: number[]\n} {\n const match: (number | null)[] = next.map(() => null)\n const claimed = new Set<number>()\n const pass = (same: (p: JoinedInput, n: { path: string }) => boolean) => {\n next.forEach((n, i) => {\n if (match[i] !== null) return\n const j = prev.findIndex(\n (p, k) => !claimed.has(k) && p.footage === n.footage && same(p, n),\n )\n if (j >= 0) {\n match[i] = j\n claimed.add(j)\n }\n })\n }\n pass((p, n) => p.path !== '' && p.path === n.path)\n pass(() => true)\n const changed: number[] = []\n const removed: number[] = []\n prev.forEach((p, j) => {\n if (claimed.has(j)) return\n const back =\n p.path !== '' &&\n next.some((n, i) => match[i] === null && n.path === p.path)\n ;(back ? changed : removed).push(j)\n })\n return { match, changed, removed }\n}\n\n/** A prior input's media keys: its own and its media's. */\nconst keysOf = (x: JoinedInput): string[] => [\n x.media,\n ...Object.values(x.sub ?? {}),\n]\n\n/** A media's recorded script url, when its document carries one. */\nconst scriptUrl = (m: { script?: unknown } | undefined): string | undefined => {\n const s = m?.script as { url?: unknown } | undefined\n return typeof s?.url === 'string' ? s.url : undefined\n}\n\n/** More than half of these named steps must be in the new take for a new path to be the same scene. */\nconst SAME_SCRIPT = 0.5\n\n/**\n * Which inputs were RECORDED AGAIN: a prior take input that did not come\n * back paired with a new take input. A changed input (its path came back\n * with other footage) is paired with the input at that path; a removed\n * one with the new input that recorded the same script, read from the\n * steps (more than half of its named steps, the url agreeing when both\n * say one; the best match, and a tie is no match). Both sides must be\n * takes with steps and no media of their own: a plain file has nothing to\n * re-time by. Returns new input index → prior input index.\n */\nexport function rerecordedInputs(\n prev: ProjectDoc,\n record: JoinRecord,\n inputs: readonly RejoinInput[],\n m: Pick<ReturnType<typeof matchInputs>, 'match' | 'changed' | 'removed'>,\n): Map<number, number> {\n const pairs = new Map<number, number>()\n const mediaOf = (k: string) => (prev.media ?? []).find((x) => x.id === k)\n const fit = (j: number) => {\n const x = record.inputs[j]\n if (x.kind !== 'take' || x.media === '' || Object.keys(x.sub ?? {}).length)\n return null\n const media = mediaOf(x.media)\n const steps = media?.meta.steps ?? []\n return media && steps.length ? { media, steps } : null\n }\n const open = (i: number) =>\n i > 0 &&\n m.match[i] === null &&\n !pairs.has(i) &&\n inputs[i].part.kind === 'take' &&\n !(inputs[i].part.doc.media ?? []).length &&\n !!inputs[i].part.doc.source.meta.steps?.length\n for (const j of m.changed) {\n if (!fit(j)) continue\n const i = inputs.findIndex(\n (n, at) => open(at) && n.path === record.inputs[j].path,\n )\n if (i >= 0) pairs.set(i, j)\n }\n for (const j of m.removed) {\n const old = fit(j)\n if (!old) continue\n const ids = [\n ...new Set(old.steps.map((s) => s.id).filter((v): v is string => !!v)),\n ]\n if (!ids.length) continue\n const url = scriptUrl(old.media)\n let best = -1\n let bestScore = SAME_SCRIPT\n let tie = false\n inputs.forEach((n, i) => {\n if (!open(i)) return\n const there = scriptUrl(n.part.doc.source) ?? n.part.actions?.url\n if (url && there && url !== there) return\n const now = new Set((n.part.doc.source.meta.steps ?? []).map((s) => s.id))\n const score = ids.filter((id) => now.has(id)).length / ids.length\n if (score > bestScore) {\n best = i\n bestScore = score\n tie = false\n } else if (score === bestScore && best >= 0) tie = true\n })\n if (best >= 0 && !tie) pairs.set(best, j)\n }\n return pairs\n}\n\n/** One media of a joined document, seen as a take of its own: its source and the edits on it. */\nfunction mediaView(\n doc: ProjectDoc,\n media: Media,\n segments: DocSegment[],\n): ProjectDoc {\n const own = <T extends { media?: string }>(\n xs: readonly T[] | undefined,\n ): T[] =>\n (xs ?? [])\n .filter((x) => mediaKey(x.media) === media.id)\n .map((x) => {\n const { media: _, ...rest } = x\n return rest as T\n })\n return {\n ...doc,\n source: {\n videoKey: media.videoKey,\n cursor: media.cursor,\n meta: media.meta,\n },\n segments: own(segments),\n zoom: own(doc.zoom),\n speed: own(doc.speed),\n tilt: own(doc.tilt),\n freeze: own(doc.freeze),\n rejected: own(doc.rejected),\n media: undefined,\n }\n}\n\n/**\n * Join `inputs` over `prev`, the joined take's edited document, keeping\n * its edits (see the module comment). Throws a UsageError when the first\n * input is not the take's primary. `where` says a recorded input path\n * (relative to the joined take) in the report's words.\n */\nexport function rejoinDocs(\n prev: ProjectDoc,\n record: JoinRecord,\n inputs: readonly RejoinInput[],\n opts: { where?: (recordPath: string) => string } = {},\n): {\n plan: JoinPlan\n report: RejoinReport\n newIds: Set<string>\n dropped: Set<string>\n} {\n const where = opts.where ?? ((p: string) => p)\n const { match, changed, removed } = matchInputs(record.inputs, inputs)\n const first = match[0] === null ? null : record.inputs[match[0]]\n if (!first || first.media !== '')\n throw new UsageError(\n `--keep-edits: ${inputs[0].part.label} is not the primary this take was joined from (its first input, footage unchanged). The primary carries the cut's frame and camera; keep it first, or join afresh with --force`,\n )\n // Inputs recorded again: new input index → prior input index.\n const redo = rerecordedInputs(prev, record, inputs, {\n match,\n changed,\n removed,\n })\n const redoneFrom = new Set(redo.values())\n /** A new input: no prior input, and not a prior input recorded again. */\n const isNew = (i: number) => match[i] === null && !redo.has(i)\n\n // The kept inputs keep their ids; every id the take ever named stays\n // retired, so a new input never inherits an old media's edits.\n const parts: JoinPart[] = inputs.map((x, i) => {\n const j = match[i]\n if (i === 0 || j === null) return x.part\n const was = record.inputs[j]\n return { ...x.part, id: was.media, ...(was.sub ? { subIds: was.sub } : {}) }\n })\n const reserved = new Set<string>([\n ...record.inputs.flatMap(keysOf),\n ...(prev.media ?? []).map((m) => m.id),\n ])\n const fresh = joinDocs(parts, { reserved })\n\n // Which media keys stay, which are new, which go; and each key's input.\n const argOf = new Map<string, number>()\n const newIds = new Set<string>()\n const kept = new Set<string>()\n fresh.ids.forEach((ids, i) => {\n for (const k of [ids.id, ...Object.values(ids.sub)]) {\n argOf.set(k, i)\n if (isNew(i)) newIds.add(k)\n }\n })\n match.forEach((j, i) => {\n if (j === null) return\n for (const k of keysOf(record.inputs[j])) kept.add(k)\n // A kept input's media the record never named (a sub-media the take\n // grew since) stays with it.\n for (const k of [fresh.ids[i].id, ...Object.values(fresh.ids[i].sub)])\n kept.add(k)\n })\n kept.add('')\n const dropped = new Set<string>()\n for (const k of [\n ...record.inputs.flatMap(keysOf),\n ...(prev.media ?? []).map((m) => m.id),\n ])\n if (!kept.has(k)) dropped.add(k)\n\n const report: RejoinReport = {\n kept: [],\n added: [],\n dropped: [],\n rerecorded: [],\n regrouped: false,\n shifted: [],\n notes: [],\n }\n inputs.forEach((x, i) => {\n const j = match[i]\n if (j === null) {\n if (isNew(i))\n report.added.push({ label: x.part.label, id: fresh.ids[i].id })\n return\n }\n const was = record.inputs[j]\n report.kept.push({\n label: x.part.label,\n id: was.media,\n ...(was.path && was.path !== x.path ? { moved: where(was.path) } : {}),\n })\n })\n\n const doc = structuredClone(prev)\n const keyOf = (s: { media?: string }) => mediaKey(s.media)\n\n // ── segments ──\n const prevSegments = prev.segments.length\n ? prev.segments\n : [{ in: 0, out: round3(prev.source.meta.durationMs / 1000) }]\n const prevExt = segmentOutputExtents(prev)\n const prevFootage = totalDuration(ratedSegments(prev))\n\n // A re-recorded input's cut, re-timed onto its new footage by its steps\n // (the same mapping `vos plan --reuse` makes), under its new media id.\n interface Redo {\n i: number\n from: string\n to: string\n rt: ReusedCut\n segments: DocSegment[]\n placed: boolean\n entry: RejoinReport['rerecorded'][number]\n }\n const redoByOld = new Map<string, Redo>()\n for (const [i, j] of redo) {\n const from = record.inputs[j].media\n const to = fresh.ids[i].id\n const was = (prev.media ?? []).find((m) => m.id === from)!\n const view = mediaView(prev, was, prevSegments)\n const meta = inputs[i].part.doc.source.meta\n const rt = retimeCut(view, meta.steps ?? [], meta.durationMs)\n const cut = view.segments.length\n ? splitSegmentsAtSkips(rt.segments, meta.skips)\n : []\n const x = inputs[i]\n redoByOld.set(from, {\n i,\n from,\n to,\n rt,\n segments: cut.map((sg) => ({ ...sg, media: to })),\n placed: false,\n entry: {\n label: x.part.label,\n from,\n id: to,\n ...(record.inputs[j].path && record.inputs[j].path !== x.path\n ? { was: where(record.inputs[j].path) }\n : {}),\n segments: cut.length,\n spans: 0,\n layers: [],\n flagged: [...rt.report.flagged],\n },\n })\n }\n const redoTo = new Set([...redoByOld.values()].map((r) => r.to))\n\n let segments: DocSegment[] = prevSegments.flatMap((sg) => {\n const r = redoByOld.get(keyOf(sg))\n if (r) {\n // The new recording's cut takes the place of the old one's first clip.\n if (r.placed) return []\n r.placed = true\n return r.segments\n }\n return kept.has(keyOf(sg)) ? [sg] : []\n })\n // The kept inputs' order now against their order in the record.\n const keptOrder = match.filter((j): j is number => j !== null)\n const inOrder = keptOrder.every((j, k) => k === 0 || keptOrder[k - 1] < j)\n if (!inOrder) {\n report.regrouped = true\n segments = segments\n .map((s, at) => ({ s, at, arg: argOf.get(keyOf(s)) ?? 0 }))\n .sort((a, b) => a.arg - b.arg || a.at - b.at)\n .map((x) => x.s)\n }\n // Each new input's segments, as the fresh join cut them, go before the\n // next kept input's first segment in argument order, or at the end.\n const freshSegs = fresh.doc.segments\n const freshExt = segmentOutputExtents(fresh.doc)\n const firstFresh = new Map<number, number>()\n inputs.forEach((_, i) => {\n if (!isNew(i)) return\n const mine = freshSegs\n .map((s, at) => ({ s, at }))\n .filter((x) => argOf.get(keyOf(x.s)) === i)\n if (!mine.length) return\n firstFresh.set(i, mine[0].at)\n let at = segments.length\n for (let n = i + 1; n < inputs.length; n++) {\n if (isNew(n)) continue\n const k = segments.findIndex((s) => argOf.get(keyOf(s)) === n)\n if (k >= 0) {\n at = k\n break\n }\n }\n segments.splice(at, 0, ...mine.map((x) => x.s))\n })\n doc.segments = segments\n\n // ── media ──\n const freshMedia = new Map((fresh.doc.media ?? []).map((m) => [m.id, m]))\n const media = [\n ...(prev.media ?? [])\n .filter((m) => kept.has(m.id))\n .map((m) => {\n // A take joined before media carried their script gains it now.\n const f = freshMedia.get(m.id)\n return !m.script && f?.script ? { ...m, script: f.script } : m\n }),\n ...(fresh.doc.media ?? []).filter(\n (m) => newIds.has(m.id) || redoTo.has(m.id),\n ),\n ]\n .map((m, at) => ({ m, at, arg: argOf.get(m.id) ?? 0 }))\n .sort((a, b) => a.arg - b.arg || a.at - b.at)\n .map((x) => x.m)\n if (media.length) doc.media = media\n else delete doc.media\n\n // ── source-anchored spans ──\n const spanLanes = [\n 'zoom',\n 'speed',\n 'tilt',\n 'camMotion',\n 'freeze',\n 'rejected',\n ] as const\n const dropCount = new Map<string, { segments: number; spans: number }>()\n const tally = (k: string, what: 'segments' | 'spans') => {\n const c = dropCount.get(k) ?? { segments: 0, spans: 0 }\n c[what]++\n dropCount.set(k, c)\n }\n for (const s of prevSegments)\n if (dropped.has(keyOf(s)) && !redoByOld.has(keyOf(s)))\n tally(keyOf(s), 'segments')\n type Span = { id: string; media?: string; in?: number; out?: number }\n /** A re-recorded input's spans on one lane: its cut's, re-timed, then the planner's fresh proposals where nothing stands. */\n const redoSpans = (lane: (typeof spanLanes)[number]): Span[] => {\n const out: Span[] = []\n for (const r of redoByOld.values()) {\n const tag = (x: object): Span => ({ ...(x as Span), media: r.to })\n let mine: Span[]\n if (lane === 'camMotion') {\n // A cam move is not re-timed by a re-record (as with plan --reuse).\n mine = ((prev.camMotion ?? []) as Span[])\n .filter((x) => keyOf(x) === r.from)\n .map(tag)\n } else {\n mine = (r.rt[lane] as object[]).map(tag)\n if (lane === 'zoom' || lane === 'speed' || lane === 'tilt') {\n const rejected = r.rt.rejected as RejectedSpan[]\n const proposed = ((fresh.doc[lane] ?? []) as Span[]).filter(\n (x) =>\n keyOf(x) === r.to &&\n (x as { source?: string }).source === 'auto' &&\n !mine.some((m) => x.in! < m.out! && m.in! < x.out!) &&\n !isRejected(lane, x as { in: number; out: number }, rejected),\n )\n r.entry.spans += mine.length\n mine = [...mine, ...proposed]\n } else if (lane === 'rejected') {\n const fromTake = (\n (fresh.doc.rejected ?? []) as RejectedSpan[]\n ).filter(\n (x) =>\n keyOf(x) === r.to &&\n !isRejected(x.lane, x, r.rt.rejected as RejectedSpan[]),\n )\n r.entry.spans += mine.length\n mine = [...mine, ...(fromTake as Span[])]\n } else r.entry.spans += mine.length\n }\n if (lane === 'camMotion') r.entry.spans += mine.length\n out.push(...mine)\n }\n return out\n }\n for (const lane of spanLanes) {\n const before = (prev[lane] ?? []) as { media?: string }[]\n for (const s of before)\n if (dropped.has(keyOf(s)) && !redoByOld.has(keyOf(s)))\n tally(keyOf(s), 'spans')\n const next = [\n ...before.filter((s) => kept.has(keyOf(s))),\n ...redoSpans(lane),\n ...((fresh.doc[lane] ?? []) as { media?: string }[]).filter((s) =>\n newIds.has(keyOf(s)),\n ),\n ]\n if (next.length) (doc as unknown as Record<string, unknown>)[lane] = next\n else delete (doc as unknown as Record<string, unknown>)[lane]\n }\n\n // ── output-time placement ──\n const newExt = segmentOutputExtents(doc)\n const newFootage = totalDuration(ratedSegments(doc))\n const placeOf = new Map<DocSegment, number>()\n segments.forEach((s, i) => placeOf.set(s, i))\n /** Where an output second of the old cut plays now; null = over footage that is gone. */\n const follow = (t: number): number | null => {\n for (let i = 0; i < prevExt.length; i++) {\n const e = prevExt[i]\n if (t >= e.start - 1e-6 && t < e.end - 1e-6) {\n const at = placeOf.get(prevSegments[i])\n if (at === undefined) return null\n const moved = newExt[at].start + (t - e.start)\n return Math.abs(moved - t) < 1e-9 ? t : round3(moved)\n }\n }\n if (t >= prevFootage - 1e-6) {\n const moved = newFootage + (t - prevFootage)\n return Math.abs(moved - t) < 1e-9 ? t : round3(moved)\n }\n return t\n }\n /** A new input's own placements, from where the fresh join cut it to where it plays now. */\n const deltaOf = (k: string): number => {\n const i = argOf.get(k)\n if (i === undefined) return 0\n const at = firstFresh.get(i)\n if (at === undefined) return 0\n const now = placeOf.get(freshSegs[at])\n return now === undefined ? 0 : newExt[now].start - freshExt[at].start\n }\n const droppedItems = new Map<string, { layers: string[]; sound: string[] }>()\n const lose = (k: string, what: 'layers' | 'sound', id: string) => {\n const c = droppedItems.get(k) ?? { layers: [], sound: [] }\n c[what].push(id)\n droppedItems.set(k, c)\n }\n /** Which input's footage an output second of the old cut played over. */\n const footageAt = (t: number): string | null => {\n for (let i = 0; i < prevExt.length; i++) {\n const e = prevExt[i]\n if (t >= e.start - 1e-6 && t < e.end - 1e-6) return keyOf(prevSegments[i])\n }\n return null\n }\n /** Where a media's clips play, first to last, in a cut. */\n const blockOf = (\n segs: readonly DocSegment[],\n ext: readonly { start: number; end: number }[],\n k: string,\n ): { start: number; end: number } | null => {\n const at = segs.flatMap((sg, i) => (keyOf(sg) === k ? [ext[i]] : []))\n return at.length ? { start: at[0].start, end: at[at.length - 1].end } : null\n }\n /**\n * `follow`, and over a re-recorded input's footage the same place in its\n * scene: the offset from where the scene starts, kept while it still\n * falls inside the scene's new length.\n */\n const place = (t: number): number | null => {\n const k = footageAt(t)\n const r = k === null ? undefined : redoByOld.get(k)\n if (!r) return follow(t)\n const was = blockOf(prevSegments, prevExt, r.from)\n const now = blockOf(segments, newExt, r.to)\n if (!was || !now) return null\n const moved = now.start + (t - was.start)\n if (moved >= now.end - 1e-6) return null\n return Math.abs(moved - t) < 1e-9 ? t : round3(moved)\n }\n /** A thing over a re-recorded input's footage that has no place in its new recording. */\n const loseOver = (t: number, what: string): boolean => {\n const r = redoByOld.get(footageAt(t) ?? '\\u0000')\n if (!r) return false\n r.entry.flagged.push(\n `${what} (${t.toFixed(2)} s): it played over this input's footage past where its new recording ends; dropped`,\n )\n return true\n }\n\n // Layers: the edited ones, then a new input's.\n const overlays: OverlayClip[] = []\n /** A re-recorded input's layers, by id: the input they now follow. */\n const redoLayers = new Map<string, Redo>()\n for (const prevLayer of prev.overlays ?? []) {\n let o = prevLayer\n const refMedia =\n o.kind !== 'text' && o.kind !== 'html' ? mediaRefId(o.key) : null\n const owner = o.anchor ? mediaKey(o.anchor.media) : null\n const goes = (k: string | null): k is string =>\n k !== null && dropped.has(k) && !redoByOld.has(k)\n const gone = (goes(owner) && owner) || (goes(refMedia) && refMedia) || null\n if (gone) {\n lose(gone, 'layers', o.id)\n continue\n }\n // A re-recorded input's layer names its new media.\n const byOwner = owner === null ? undefined : redoByOld.get(owner)\n if (byOwner && o.anchor) {\n o = { ...o, anchor: { ...o.anchor, media: byOwner.to } }\n redoLayers.set(o.id, byOwner)\n }\n const byRef = refMedia === null ? undefined : redoByOld.get(refMedia)\n if (byRef && o.kind !== 'text' && o.kind !== 'html') {\n o = { ...o, key: `media:${byRef.to}` }\n redoLayers.set(o.id, byRef)\n }\n if (o.anchor || o.start === undefined) {\n // An anchored layer follows its step; one with neither a step nor a\n // time plays nowhere and is kept as it is (validate refuses it).\n overlays.push(o)\n continue\n }\n const t = place(o.start)\n if (t === null) {\n if (!loseOver(o.start, `layer ${o.id}`))\n lose(footageAt(o.start) ?? '', 'layers', o.id)\n continue\n }\n const over = redoByOld.get(footageAt(o.start) ?? '\\u0000')\n if (over) redoLayers.set(o.id, over)\n if (t !== o.start) report.shifted.push(o.id)\n overlays.push(t === o.start ? o : { ...o, start: t })\n }\n for (const o of fresh.doc.overlays ?? []) {\n const k = fresh.owners.get(o.id)\n if (k === undefined || !newIds.has(k)) continue\n const d = o.anchor ? 0 : deltaOf(k)\n overlays.push(\n d && o.start !== undefined ? { ...o, start: round3(o.start + d) } : o,\n )\n }\n if (overlays.length) doc.overlays = overlays\n else delete doc.overlays\n\n // 3D props, the same way.\n const objects: NonNullable<ProjectDoc['objects']> = []\n for (const ob of prev.objects ?? []) {\n if (!ob.span) {\n objects.push(ob)\n continue\n }\n const t = place(ob.span.start)\n if (t === null) {\n if (!loseOver(ob.span.start, `prop ${ob.id}`))\n lose(footageAt(ob.span.start) ?? '', 'layers', ob.id)\n continue\n }\n if (t !== ob.span.start) report.shifted.push(ob.id)\n objects.push(\n t === ob.span.start ? ob : { ...ob, span: { ...ob.span, start: t } },\n )\n }\n for (const ob of fresh.doc.objects ?? []) {\n const k = fresh.owners.get(ob.id)\n if (k === undefined || !newIds.has(k)) continue\n const d = deltaOf(k)\n objects.push(\n d && ob.span\n ? { ...ob, span: { ...ob.span, start: round3(ob.span.start + d) } }\n : ob,\n )\n }\n if (objects.length) doc.objects = objects\n else delete doc.objects\n\n // Sound: a media's own clip follows its media; a film-wide one keeps its seconds.\n const allPrev = new Set([...dropped, ...kept])\n const audio: ProjectDoc['audio'] = []\n for (const a of prev.audio) {\n const m = /^(.*)-sound$/.exec(a.id)\n const k = m && allPrev.has(m[1]) ? m[1] : null\n if (k === null) {\n audio.push(a)\n continue\n }\n const r = redoByOld.get(k)\n if (r) {\n r.entry.flagged.push(\n `sound ${a.id}: it was the old recording's own sound; dropped`,\n )\n continue\n }\n if (dropped.has(k)) {\n lose(k, 'sound', a.id)\n continue\n }\n const t = follow(a.start)\n if (t === null) {\n lose(k, 'sound', a.id)\n continue\n }\n if (t !== a.start) report.shifted.push(a.id)\n audio.push(t === a.start ? a : { ...a, start: t })\n }\n for (const a of fresh.doc.audio) {\n const k = fresh.owners.get(a.id)\n if (k === undefined || !newIds.has(k)) continue\n const d = deltaOf(k)\n audio.push(d ? { ...a, start: round3(a.start + d) } : a)\n }\n doc.audio = audio\n\n // The cover moment, an output second the author chose.\n if (typeof prev.still === 'number') {\n const t = place(prev.still)\n if (t === null) {\n delete doc.still\n report.notes.push(\n `the still (${prev.still.toFixed(2)} s) played over footage that is gone; the cover falls back to its default (vos push --still sets one)`,\n )\n } else if (t !== prev.still) {\n doc.still = t\n report.shifted.push('still')\n }\n }\n\n // Every anchored layer's fallback start is where it plays now; a layer\n // that carries none keeps none, its anchor is its time. A layer anchored\n // to a step a re-recorded input no longer plays has no place.\n const pieces = ratedSegments(doc)\n if (doc.overlays) {\n doc.overlays = doc.overlays.flatMap((o) => {\n const r = o.anchor ? resolveAnchor(doc, o.anchor, pieces) : null\n const redone = redoLayers.get(o.id)\n if (o.anchor && r && r.start === null && redone) {\n redone.entry.flagged.push(\n `layer ${o.id}: anchored to step ${String(o.anchor.step)}, which the new recording does not have, skipped, or the cut leaves out; dropped`,\n )\n return []\n }\n if (redone) redone.entry.layers.push(o.id)\n return r &&\n r.start !== null &&\n o.start !== undefined &&\n r.start !== o.start\n ? [{ ...o, start: r.start }]\n : [o]\n })\n if (!doc.overlays.length) delete doc.overlays\n }\n // An ending anchored to a step (an end card on the last input's last\n // step) stays on its step, which may no longer be the end: say so.\n const prevPieces = ratedSegments(prev)\n const wasEnding = new Set(\n (prev.overlays ?? [])\n .filter((o) => {\n if (!o.anchor) return false\n const r = resolveAnchor(prev, o.anchor, prevPieces)\n return r.start !== null && r.start >= prevFootage - 1e-3\n })\n .map((o) => o.id),\n )\n const overrun = (doc.overlays ?? [])\n .filter((o) => {\n if (!wasEnding.has(o.id)) return false\n const start = layerStart(o, doc, pieces)\n return start !== null && start < newFootage - 1e-3\n })\n .map((o) => o.id)\n if (overrun.length)\n report.notes.push(\n `${overrun.join(', ')} played after the footage and, anchored to ${overrun.length === 1 ? 'its' : 'their'} step, now ${overrun.length === 1 ? 'lands' : 'land'} over the footage that follows; anchor ${overrun.length === 1 ? 'it' : 'them'} to the last input's end, or move ${overrun.length === 1 ? 'it' : 'them'}`,\n )\n\n // What went, per input.\n const labelOf = (k: string): string => {\n const x = record.inputs.find((r) => keysOf(r).includes(k))\n return x?.path ? where(x.path) : k ? `media ${k}` : 'the primary'\n }\n for (const j of [...changed, ...removed]) {\n if (redoneFrom.has(j)) continue\n const x = record.inputs[j]\n for (const k of keysOf(x)) {\n const c = dropCount.get(k) ?? { segments: 0, spans: 0 }\n const items = droppedItems.get(k) ?? { layers: [], sound: [] }\n report.dropped.push({\n input: labelOf(k),\n id: k,\n why: changed.includes(j) ? 'changed' : 'removed',\n segments: c.segments,\n spans: c.spans,\n layers: items.layers,\n sound: items.sound,\n })\n }\n }\n // A media in the document the record never named (and so no input).\n for (const k of dropped) {\n if (report.dropped.some((d) => d.id === k) || redoByOld.has(k)) continue\n const c = dropCount.get(k) ?? { segments: 0, spans: 0 }\n const items = droppedItems.get(k) ?? { layers: [], sound: [] }\n report.dropped.push({\n input: `media ${k}`,\n id: k,\n why: 'removed',\n segments: c.segments,\n spans: c.spans,\n layers: items.layers,\n sound: items.sound,\n })\n }\n if (Math.abs(newFootage - prevFootage) > 1e-3) {\n const film = doc.audio.filter((a) => !/-sound$/.test(a.id))\n if (film.length)\n report.notes.push(\n `the footage now runs ${newFootage.toFixed(2)} s (was ${prevFootage.toFixed(2)} s); ${film.map((a) => a.id).join(', ')} kept ${film.length === 1 ? 'its' : 'their'} seconds (vos score places a score again)`,\n )\n }\n\n // A new input's notes only: the kept ones' were said at their join.\n report.rerecorded = [...redoByOld.values()].map((r) => r.entry)\n const newLabels = inputs.filter((_, i) => isNew(i)).map((x) => x.part.label)\n const notes = fresh.notes.filter((n) =>\n newLabels.some((l) => n.startsWith(`${l}:`)),\n )\n const copies = fresh.copies.filter((c) =>\n [...newIds, ...redoTo].some((k) => k !== '' && c.to.startsWith(`${k}/`)),\n )\n return {\n plan: {\n doc,\n copies,\n media: fresh.media,\n actions: fresh.actions,\n notes,\n ids: fresh.ids,\n owners: fresh.owners,\n },\n report,\n newIds,\n dropped,\n }\n}\n\n/** The report in words, for the done line. */\nexport function rejoinLines(r: RejoinReport): string[] {\n const lines: string[] = []\n const n = (v: number, one: string, many = `${one}s`) =>\n `${v} ${v === 1 ? one : many}`\n if (r.kept.length)\n lines.push(\n `kept the edits of ${r.kept.map((k) => `${k.label} (${k.id || 'primary'}${k.moved ? `, found at its new path; was ${k.moved}` : ''})`).join(', ')}`,\n )\n if (r.added.length)\n lines.push(`added ${r.added.map((a) => `${a.label} → ${a.id}`).join(', ')}`)\n for (const x of r.rerecorded) {\n lines.push(\n `re-recorded ${x.label}${x.was ? ` (was ${x.was})` : ''}: ${x.from} → ${x.id}; its edits re-timed by its steps: ${[\n n(x.segments, 'segment'),\n n(x.spans, 'span'),\n x.layers.length ? `layers ${x.layers.join(', ')}` : '0 layers',\n ].join(', ')}`,\n )\n for (const f of x.flagged) lines.push(` ${f}`)\n }\n for (const d of r.dropped) {\n const what = [\n n(d.segments, 'segment'),\n n(d.spans, 'span'),\n ...(d.layers.length ? [`layers ${d.layers.join(', ')}`] : []),\n ...(d.sound.length ? [`sound ${d.sound.join(', ')}`] : []),\n ].join(', ')\n lines.push(\n `dropped ${d.input} (${d.id || 'primary'}): ${d.why === 'changed' ? 'its footage changed since the join' : 'no longer an input'}; ${what} went with it`,\n )\n }\n if (r.regrouped)\n lines.push(\n 'the inputs changed order, so the segments play in argument order again (each input’s own segments in their edited order)',\n )\n if (r.shifted.length)\n lines.push(\n `${r.shifted.join(', ')} moved with the footage ${r.shifted.length === 1 ? 'it plays' : 'they play'} over`,\n )\n lines.push(...r.notes)\n return lines\n}\n","/**\n * `vos info <take> [--json]`: where everything in a take is, in both\n * clocks. `vos info` inspects a program config; given a take directory it\n * reads the take instead, the way every engine verb takes a take.\n *\n * Per media, every recorder step with its id, its SOURCE seconds\n * (`meta.steps[].tStart`/`tEnd`), its caption and where it plays in the\n * cut. Then the OUTPUT timeline as the lowering resolves it, read through\n * studio-core's own functions (`ratedSegments`, `segmentOutputExtents`,\n * `spanOutputExtents`, `longestOutputExtent`, `cameraSpanExtents`,\n * `resolveOverlayAnchors`, `docOutputDuration`): every\n * segment, speed span, freeze, zoom and tilt with its output extent (or\n * cut, when the trims leave it out), every layer with its anchor resolved,\n * every sound clip, the still and the end. Read-only.\n */\nimport { join, resolve } from 'node:path'\nimport {\n docFreezes,\n docMediaList,\n docOutputDuration,\n cameraSpanExtents,\n docStillTime,\n freezeOutputExtents,\n mediaKey,\n migrateMotion,\n overlayPlainText,\n longestOutputExtent,\n ratedSegments,\n resolveOverlayAnchors,\n segmentOutputExtents,\n spanOutputExtents,\n} from '@vosjs/studio-core'\nimport { totalDuration } from '@vosjs/timeline'\nimport { UsageError, parseArgs } from './args'\nimport { EXIT_OK, createReporter } from './output'\nimport { captionOf } from './stepCaptions'\nimport { loadTake } from './take'\nimport { scriptDrift, scriptDriftLine } from './scriptStep'\nimport type {\n OverlayAnchor,\n OverlayClip,\n ProjectDoc,\n Segment,\n} from '@vosjs/studio-core'\nimport type { ActionsFile } from './actions'\n\ntype Extent = { start: number; end: number } | null\n\nconst r3 = (v: number): number => Math.round(v * 1000) / 1000\nconst ext = (e: Extent): Extent =>\n e ? { start: r3(e.start), end: r3(e.end) } : null\n/**\n * Every other place a source span plays, beside `output`: a cut that\n * replays seconds (a cold open) plays the span in each pass. For a step,\n * `output` is the pass an anchor on it lands in (its longest); for a\n * camera span, the passes where it moves the camera.\n */\ntype Also = { start: number; end: number }[]\n\nexport interface TimelineStep {\n step: number\n id?: string\n do: string\n /** SOURCE seconds. */\n in: number\n out: number\n caption?: string\n skipped?: boolean\n /** Where the step plays in the cut; null when the trims leave it out. */\n output: Extent\n also?: Also\n}\n\nexport interface TimelineMedia {\n /** `''` = the primary. */\n id: string\n file: string\n /** Source seconds. */\n duration: number\n steps: TimelineStep[]\n}\n\nexport interface TakeTimeline {\n media: TimelineMedia[]\n segments: {\n index: number\n media: string\n in: number\n out: number\n start: number\n end: number\n }[]\n speed: {\n id: string\n media: string\n in: number\n out: number\n rate: number\n source?: string\n output: Extent\n also?: Also\n }[]\n freeze: {\n id: string\n media: string\n at: number\n seconds: number\n output: Extent\n }[]\n zoom: {\n id: string\n media: string\n in: number\n out: number\n level: number\n source?: string\n output: Extent\n also?: Also\n /** Where it plays in a clip that rests the camera, so moves nothing. */\n rests?: Also\n }[]\n tilt: {\n id: string\n media: string\n in: number\n out: number\n output: Extent\n also?: Also\n rests?: Also\n }[]\n overlays: {\n id: string\n kind: string\n text?: string\n start: number\n end: number\n anchor?: OverlayAnchor\n from?: string\n }[]\n objects: { id: string; start: number; end: number | null }[]\n audio: {\n id: string\n name?: string\n start: number\n end: number\n in: number\n out: number\n }[]\n /** The kept footage's output length (speed and freezes applied). */\n footage: number\n /** The film's output length: the footage, or the last layer past it. */\n end: number\n /** The cover moment, output seconds. */\n still: number\n}\n\n/** The rated pieces without freezes: what a freeze is placed into. */\nfunction ratedWithoutFreezes(doc: ProjectDoc): Segment[] {\n return ratedSegments({\n ...doc,\n freeze: undefined,\n segments: doc.segments.map((s) => {\n const { hold: _hold, ...rest } = s as typeof s & { hold?: unknown }\n void _hold\n return rest\n }),\n })\n}\n\n/**\n * The take's two clocks, resolved. `actions` maps a media key (`''` = the\n * primary) to the actions.json that recorded it, for the step captions; a\n * media's embedded script is read when it has none.\n */\nexport function takeTimeline(\n rawDoc: ProjectDoc,\n actions: ReadonlyMap<string, ActionsFile | null> = new Map(),\n): TakeTimeline {\n const doc = migrateMotion(rawDoc)\n const rated = ratedSegments(doc)\n // Where a source span plays: its first place and, on a cut that replays\n // it, every other place.\n const round = (e: { start: number; end: number }) => ({\n start: r3(e.start),\n end: r3(e.end),\n })\n const span = (\n sIn: number,\n sOut: number,\n media?: string,\n ): { output: Extent; also?: Also } => {\n const all = spanOutputExtents(rated, sIn, sOut, media).map(round)\n return {\n output: all[0] ?? null,\n ...(all.length > 1 ? { also: all.slice(1) } : {}),\n }\n }\n // A step plays where an anchor on it lands, the pass it plays longest\n // (`resolveAnchor`), and is seen in the others too.\n const stepSpan = (\n sIn: number,\n sOut: number,\n media?: string,\n ): { output: Extent; also?: Also } => {\n const all = spanOutputExtents(rated, sIn, sOut, media).map(round)\n const longest = longestOutputExtent(rated, sIn, sOut, media)\n const main = longest\n ? all.find(\n (e) =>\n Math.abs(e.start - r3(longest.start)) < 1e-6 &&\n Math.abs(e.end - r3(longest.end)) < 1e-6,\n )\n : undefined\n const others = all.filter((e) => e !== main)\n return {\n output: main ?? null,\n ...(others.length ? { also: others } : {}),\n }\n }\n // A camera span moves the camera only in the passes whose clip does not\n // rest it (`segments[].camera: \"rest\"`); where it rests is said apart.\n const cameraSpan = (\n sIn: number,\n sOut: number,\n media?: string,\n ): { output: Extent; also?: Also; rests?: Also } => {\n const moves = cameraSpanExtents(rated, sIn, sOut, media).map(round)\n const rests = spanOutputExtents(rated, sIn, sOut, media)\n .map(round)\n .filter(\n (e) =>\n !moves.some(\n (m) => m.start >= e.start - 1e-6 && m.end <= e.end + 1e-6,\n ),\n )\n return {\n output: moves[0] ?? null,\n ...(moves.length > 1 ? { also: moves.slice(1) } : {}),\n ...(rests.length ? { rests } : {}),\n }\n }\n\n const media: TimelineMedia[] = docMediaList(doc).map(({ id, source }) => ({\n id,\n file: source.videoKey,\n duration: r3((source.meta.durationMs || 0) / 1000),\n steps: (source.meta.steps ?? []).map((s) => {\n const caption = captionOf(\n s,\n actions.get(id),\n source.script,\n source.meta.steps ?? [],\n )\n // A step is an instant as often as a stretch (a press, a key): it\n // plays where its first moment does.\n const out = Math.max(s.tEnd, s.tStart + 1e-3)\n return {\n step: s.step,\n ...(s.id !== undefined ? { id: s.id } : {}),\n do: s.do,\n in: r3(s.tStart),\n out: r3(s.tEnd),\n ...(caption ? { caption } : {}),\n ...(s.skipped ? { skipped: true } : {}),\n ...stepSpan(s.tStart, out, id || undefined),\n }\n }),\n }))\n\n const docSegments = doc.segments.length\n ? doc.segments\n : [{ in: 0, out: doc.source.meta.durationMs / 1000 }]\n const extents = segmentOutputExtents(doc)\n const segments = docSegments.map((s, index) => ({\n index,\n media: mediaKey((s as { media?: string }).media),\n in: r3(s.in),\n out: r3(s.out),\n start: r3(extents[index]?.start ?? 0),\n end: r3(extents[index]?.end ?? 0),\n }))\n\n const freezeMarks = freezeOutputExtents(\n ratedWithoutFreezes(doc),\n docFreezes(doc),\n )\n const freeze = docFreezes(doc).map((f) => {\n const m = freezeMarks.get(f.id)\n return {\n id: f.id,\n media: mediaKey(f.media),\n at: r3(f.at),\n seconds: r3(f.seconds),\n output: m ? ext({ start: m.t, end: m.t + m.duration }) : null,\n }\n })\n\n // Resolved layers come back without the ones placed nowhere (an anchor\n // that resolves to no step, and no start), so the raw layer is found by\n // id, never by index.\n const resolved = resolveOverlayAnchors(doc, rated)\n const rawById = new Map((doc.overlays ?? []).map((o) => [o.id, o]))\n const overlays = (resolved.overlays ?? []).flatMap((o: OverlayClip) => {\n const start = o.start\n if (start === undefined) return []\n const raw = rawById.get(o.id)\n const text =\n o.kind === 'text'\n ? overlayPlainText(o)\n : o.kind === 'html'\n ? undefined\n : (o as { key?: string }).key\n return [\n {\n id: o.id,\n kind: o.kind ?? 'text',\n ...(text !== undefined ? { text } : {}),\n start: r3(start),\n end: r3(start + o.duration),\n ...(raw?.anchor ? { anchor: raw.anchor } : {}),\n ...(o.from ? { from: o.from } : {}),\n },\n ]\n })\n\n const footage = totalDuration(rated)\n return {\n media,\n segments,\n speed: (doc.speed ?? []).map((s) => ({\n id: s.id,\n media: mediaKey(s.media),\n in: r3(s.in),\n out: r3(s.out),\n rate: s.rate,\n ...(s.source ? { source: s.source } : {}),\n ...span(s.in, s.out, s.media),\n })),\n freeze,\n zoom: doc.zoom.map((z) => ({\n id: z.id,\n media: mediaKey(z.media),\n in: r3(z.in),\n out: r3(z.out),\n level: z.level,\n ...(z.source ? { source: z.source } : {}),\n ...cameraSpan(z.in, z.out, z.media),\n })),\n tilt: (doc.tilt ?? []).map((t) => ({\n id: t.id,\n media: mediaKey(t.media),\n in: r3(t.in),\n out: r3(t.out),\n ...cameraSpan(t.in, t.out, t.media),\n })),\n overlays,\n objects: (doc.objects ?? []).map((ob) => ({\n id: ob.id,\n start: r3(ob.span?.start ?? 0),\n end: ob.span ? r3(ob.span.start + ob.span.duration) : null,\n })),\n audio: doc.audio.map((a) => {\n const len = a.loop && a.loopLen ? a.loopLen : a.out - a.in\n return {\n id: a.id,\n ...(a.name ? { name: a.name } : {}),\n start: r3(a.start),\n end: r3(a.start + len),\n in: r3(a.in),\n out: r3(a.out),\n }\n }),\n footage: r3(footage),\n end: r3(docOutputDuration(doc)),\n still: docStillTime(doc),\n }\n}\n\nconst f2 = (v: number): string => v.toFixed(2)\nconst range = (a: number, b: number): string => `${f2(a)}–${f2(b)}`\nconst ranges = (list: Also): string =>\n list.map((a) => range(a.start, a.end)).join(', ')\nconst outText = (e: Extent, also?: Also, rests?: Also): string =>\n `${e ? range(e.start, e.end) : rests?.length ? '(camera at rest)' : '(cut)'}${also?.length ? `, also ${ranges(also)}` : ''}${rests?.length ? `${e ? ',' : ''} at rest in ${ranges(rests)}` : ''}`\nconst mediaName = (m: string): string => m || 'primary'\n\n/** The timeline in words, one thing a line. */\nexport function formatTimeline(t: TakeTimeline, label: string): string {\n const lines: string[] = []\n const pad = (s: string, n: number) => s.padEnd(n)\n lines.push(\n `${label}: output ${f2(t.end)} s (footage ${f2(t.footage)} s), ${t.media.length} media`,\n )\n for (const m of t.media) {\n lines.push('')\n lines.push(\n `${mediaName(m.id)} ${m.file} ${f2(m.duration)} s source, ${m.steps.length} step${m.steps.length === 1 ? '' : 's'}`,\n )\n if (m.steps.length)\n lines.push(\n ` ${pad('step', 5)} ${pad('id', 16)} ${pad('do', 8)} ${pad('source', 14)} ${pad('output', 14)} caption`,\n )\n for (const s of m.steps)\n lines.push(\n ` ${pad(String(s.step), 5)} ${pad(s.id ?? '-', 16)} ${pad(s.do, 8)} ${pad(range(s.in, s.out), 14)} ${pad(s.skipped ? '(skipped)' : outText(s.output), 14)} ${s.caption ? JSON.stringify(s.caption) : ''}${s.also?.length && !s.skipped ? ` (also ${ranges(s.also)})` : ''}`.trimEnd(),\n )\n }\n lines.push('')\n lines.push('output timeline (source → output seconds)')\n lines.push(' segments')\n for (const s of t.segments)\n lines.push(\n ` #${pad(String(s.index), 4)} ${pad(mediaName(s.media), 8)} ${pad(range(s.in, s.out), 14)} → ${range(s.start, s.end)}`,\n )\n if (t.speed.length) {\n lines.push(' speed')\n for (const s of t.speed)\n lines.push(\n ` ${pad(s.id, 12)} ${pad(mediaName(s.media), 8)} ${pad(range(s.in, s.out), 14)} ×${pad(String(s.rate), 5)} ${pad(s.source ?? '', 6)} → ${outText(s.output, s.also)}`,\n )\n }\n if (t.freeze.length) {\n lines.push(' freeze')\n for (const f of t.freeze)\n lines.push(\n ` ${pad(f.id, 12)} ${pad(mediaName(f.media), 8)} at ${pad(f2(f.at), 11)} ${f2(f.seconds)} s → ${outText(f.output)}`,\n )\n }\n if (t.zoom.length) {\n lines.push(' zoom')\n for (const z of t.zoom)\n lines.push(\n ` ${pad(z.id, 12)} ${pad(mediaName(z.media), 8)} ${pad(range(z.in, z.out), 14)} L${pad(String(z.level), 5)} ${pad(z.source ?? '', 6)} → ${outText(z.output, z.also, z.rests)}`,\n )\n }\n if (t.tilt.length) {\n lines.push(' tilt')\n for (const z of t.tilt)\n lines.push(\n ` ${pad(z.id, 12)} ${pad(mediaName(z.media), 8)} ${pad(range(z.in, z.out), 14)} → ${outText(z.output, z.also, z.rests)}`,\n )\n }\n if (t.overlays.length) {\n lines.push(' layers')\n for (const o of t.overlays) {\n const anchor = o.anchor\n ? ` anchor ${o.anchor.media ? `${o.anchor.media}:` : ''}${String(o.anchor.step)}${o.anchor.at === 'end' ? ' end' : ''}${o.anchor.offset ? ` ${o.anchor.offset > 0 ? '+' : ''}${o.anchor.offset}` : ''}`\n : ''\n const words = o.text !== undefined ? ` ${JSON.stringify(o.text)}` : ''\n lines.push(\n ` ${pad(o.id, 12)} ${pad(o.kind, 6)} ${range(o.start, o.end)}${anchor}${o.from ? ` (from ${o.from})` : ''}${words}`,\n )\n }\n }\n if (t.objects.length) {\n lines.push(' 3D')\n for (const o of t.objects)\n lines.push(\n ` ${pad(o.id, 12)} ${o.end === null ? 'always' : range(o.start, o.end)}`,\n )\n }\n if (t.audio.length) {\n lines.push(' sound')\n for (const a of t.audio)\n lines.push(\n ` ${pad(a.id, 12)} ${range(a.start, a.end)} (its file ${range(a.in, a.out)})${a.name ? ` ${a.name}` : ''}`,\n )\n }\n lines.push(` still ${f2(t.still)}`)\n lines.push(` end ${f2(t.end)}`)\n return lines.join('\\n')\n}\n\n/** `vos info <take> [--json]`. */\nexport async function cmdTakeInfo(argv: string[]): Promise<number> {\n const { positionals, flags } = parseArgs(argv, new Set(['json', 'help']))\n const dir = positionals[0]\n if (!dir) throw new UsageError('vos info <take> [--json]')\n const r = createReporter(flags.json === true)\n const take = await loadTake(dir)\n if (!take.doc)\n throw new UsageError(\n `${dir} has no doc.json yet; vos plan ${dir} writes one`,\n )\n // A script edited since the take was recorded: said, never refused.\n const drift = scriptDrift(take.meta.steps ?? [], take.actions?.steps)\n if (drift) r.warn(scriptDriftLine(drift))\n const timeline = takeTimeline(take.doc, new Map([['', take.actions]]))\n r.done(\n { take: resolve(dir), doc: join(resolve(dir), 'doc.json'), ...timeline },\n formatTimeline(timeline, dir),\n )\n return EXIT_OK\n}\n","/**\n * `vos audio measure <take> [--json]`: what every sound in the document\n * measures, written beside it.\n *\n * A clip's `normalize` is a target loudness; the gain it plays at is\n * computed at lowering from what the clip's file MEASURES. That fact lives\n * in the document as `loudness: { lufs, peakDb, at, src }`, written here and\n * never by hand: each clip's file is decoded (mediabunny in Node, the\n * headless browser for what Node cannot read, as `vos score` does) and read\n * by the BS.1770 meter `vos check-video` reads a render with, integrated\n * (K-weighted, gated) over the whole file, plus its sample peak. `src` is\n * the key it was measured for, so a clip pointed at another file stops\n * matching and its target is ignored until it is measured again.\n *\n * A key on this disk is read in the take directory or below, never outside\n * it; an absolute URL (a catalog track) is downloaded for the measure and\n * not kept; a hosted asset key is not on this disk, and is said.\n */\nimport { mkdtemp, rm, writeFile } from 'node:fs/promises'\nimport { tmpdir } from 'node:os'\nimport { basename, join } from 'node:path'\nimport { clipGain } from '@vosjs/studio-core'\nimport { localFile } from '../programAssets'\nimport { UsageError, parseArgs } from './args'\nimport { isTakeRelativeKey, takeRelativeFile } from './media'\nimport { EXIT_ERROR, EXIT_OK, createReporter } from './output'\nimport { loudnessFact, measureTrack } from './score'\nimport { loadTake, writeJson } from './take'\nimport type { AudioClip, AudioLoudness } from '@vosjs/studio-core'\nimport type { Measured } from './score'\n\nconst USAGE = 'vos audio measure <take> [--json]'\n\nexport interface MeasuredClip {\n id: string\n key: string\n loudness: AudioLoudness | null\n normalize: number | null\n /** The gain the clip plays at now, and why. */\n plays: ReturnType<typeof clipGain>\n /** Why it was not measured, in words. */\n skipped?: string\n}\n\n/** Where a key's bytes are, for a measure: a file here, or downloaded. */\nasync function fileFor(\n dir: string,\n key: string,\n fetchImpl: typeof fetch,\n): Promise<\n { path: string; cleanup?: () => Promise<void> } | { skipped: string }\n> {\n if (isTakeRelativeKey(key)) {\n const found = localFile(takeRelativeFile(key), dir)\n if ('refused' in found) return { skipped: `${key} ${found.refused}` }\n return { path: found.file }\n }\n if (/^https?:\\/\\//.test(key)) {\n const res = await fetchImpl(key)\n if (!res.ok) return { skipped: `GET ${key} answered ${res.status}` }\n const tmp = await mkdtemp(join(tmpdir(), 'vos-audio-'))\n const path = join(tmp, basename(new URL(key).pathname) || 'audio')\n await writeFile(path, new Uint8Array(await res.arrayBuffer()))\n return { path, cleanup: () => rm(tmp, { recursive: true, force: true }) }\n }\n return {\n skipped: `${key} is not on this disk (a hosted file comes home with vos pull --media)`,\n }\n}\n\n/**\n * Measure every audio clip of a document in place. Pure of the disk but\n * for the reads: the caller writes the document.\n */\nexport async function measureDocAudio(\n dir: string,\n audio: AudioClip[],\n opts: {\n measure?: (path: string) => Promise<Pick<Measured, 'lufs' | 'peakDb'>>\n fetchImpl?: typeof fetch\n } = {},\n): Promise<{ clips: MeasuredClip[]; failed: string[] }> {\n const measure = opts.measure ?? measureTrack\n const fetchImpl = opts.fetchImpl ?? fetch\n const byKey = new Map<string, AudioLoudness | { skipped: string }>()\n const failed: string[] = []\n const clips: MeasuredClip[] = []\n for (const clip of audio) {\n let got = byKey.get(clip.key)\n if (!got) {\n try {\n const file = await fileFor(dir, clip.key, fetchImpl)\n if ('skipped' in file) got = file\n else {\n try {\n const m = await measure(file.path)\n got =\n m.lufs === null\n ? { skipped: 'it measures as silence' }\n : loudnessFact({ lufs: m.lufs, peakDb: m.peakDb }, clip.key)\n } finally {\n await file.cleanup?.()\n }\n }\n } catch (e) {\n const why = (e instanceof Error ? e.message : String(e)).split('\\n')[0]\n failed.push(`audio ${clip.id}: could not measure ${clip.key} (${why})`)\n got = { skipped: why }\n }\n byKey.set(clip.key, got)\n }\n if (!('skipped' in got)) clip.loudness = { ...got }\n clips.push({\n id: clip.id,\n key: clip.key,\n loudness: 'skipped' in got ? null : clip.loudness!,\n normalize: typeof clip.normalize === 'number' ? clip.normalize : null,\n plays: clipGain(clip),\n ...('skipped' in got ? { skipped: got.skipped } : {}),\n })\n }\n return { clips, failed }\n}\n\nfunction clipLine(c: MeasuredClip): string {\n if (!c.loudness) return `audio ${c.id}: not measured (${c.skipped})`\n const peak =\n c.loudness.peakDb === null\n ? ''\n : `, peak ${c.loudness.peakDb.toFixed(1)} dBFS`\n const level =\n c.plays.basis === 'normalize'\n ? `; normalize ${c.normalize} plays it at gain ${c.plays.gain.toFixed(2)}${c.plays.capped === 'peak' ? ` (asked ${c.plays.asked?.toFixed(2)}, held so its peak stays under -1 dBFS)` : c.plays.capped === 'lift' ? ' (the most a target lifts, +24 dB)' : ''}`\n : `; plays at gain ${c.plays.gain.toFixed(2)} (no normalize target)`\n return `audio ${c.id}: ${c.loudness.lufs.toFixed(1)} LUFS${peak}${level}`\n}\n\nexport async function cmdAudio(argv: string[]): Promise<number> {\n const { positionals, flags } = parseArgs(argv, new Set(['json', 'help']))\n const [sub, dir] = positionals\n if (sub !== 'measure' || !dir) throw new UsageError(USAGE)\n const r = createReporter(flags.json === true)\n const take = await loadTake(dir)\n if (!take.doc)\n throw new UsageError(`${dir} has no doc.json; run vos plan first`)\n const doc = take.doc\n if (!doc.audio?.length) {\n r.done({ take: dir, clips: [] }, `${dir}: no audio clips to measure`)\n return EXIT_OK\n }\n r.log(\n `measuring ${doc.audio.length} audio clip${doc.audio.length === 1 ? '' : 's'}…`,\n )\n const { clips, failed } = await measureDocAudio(dir, doc.audio)\n const wrote = clips.some((c) => c.loudness)\n if (wrote) await writeJson(take.paths.doc, doc, true)\n for (const f of failed) r.warn(f)\n r.done(\n { take: dir, clips, failed },\n `${clips.map(clipLine).join('\\n')}${wrote ? '\\n loudness written in doc.json' : ''}`,\n )\n return failed.length ? EXIT_ERROR : EXIT_OK\n}\n","/**\n * `vos look <url>`: the agent's eyes before it writes a flow. A screenshot\n * and the controls on screen, each with ONE proposed selector, on the same\n * browser and the same session `vos record` would use, so a page behind a\n * login can be seen without recording it.\n *\n * Looking never spends and never destroys: a `--click` whose target reads\n * as a spend or a delete (Generate, Publish, Delete, Pay…) is refused in\n * words before it is pressed, and `--type` fills a field without pressing\n * Enter.\n *\n * A proposal is checked against the page, not guessed: every candidate is\n * counted with the selector engine the recorder itself resolves steps with\n * (`page.locator`), and it is only UNIQUE when it reaches this element and\n * no other. The ranking, the scopes and the refusal words are pure and\n * tested; the page probes are strings, because a function serialized out of\n * a bundle picks up the bundler's `__name` helper and dies in the page.\n */\nimport { mkdir } from 'node:fs/promises'\nimport { existsSync } from 'node:fs'\nimport { join, resolve } from 'node:path'\nimport { headersFor, urlSchemeProblem } from '@vosjs/render-core/record'\nimport type { BrowserContext, Page } from 'playwright'\nimport { UsageError, parseArgs, strFlag } from './args'\nimport { EXIT_OK, EXIT_USAGE, EXIT_WALL, createReporter } from './output'\nimport {\n EXPOSURE_ADVICE,\n EXPOSURE_MATCHERS_SRC,\n EXPOSURE_PROBE,\n} from './exposure'\nimport { exposureLine } from './exposure'\nimport { WALL_PROBE, wallVerdict } from './wall'\nimport { parseHeaders } from './setup'\nimport { sessionDir, sessionNameVerdict, withSession } from './session'\nimport { launchBrowser } from '../browser'\nimport type { Exposure } from './exposure'\nimport type { WallVerdict } from './wall'\n\n// ---------------------------------------------------------------------------\n// What the page reports, and what look says about it\n// ---------------------------------------------------------------------------\n\n/** A scope an element sits in: the open dialog, or the landmark around it. */\nexport interface ScopeFacts {\n tag: string\n /** the explicit `role` attribute's first token, '' when none */\n role: string\n /** `aria-label`, when it has one */\n label: string | null\n testId: { attr: string; value: string } | null\n}\n\n/** One control as the page probe reads it, before a selector is chosen. */\nexport interface RawControl {\n /** its index in the probe's list, stamped on the element while looking */\n index: number\n tag: string\n /** explicit role, else the implicit one ('' for none) */\n role: string\n /** the accessible name, as near as the page can compute it */\n name: string\n /** visible text, whitespace collapsed */\n text: string\n ariaLabel: string | null\n testId: { attr: string; value: string } | null\n id: string | null\n /** a form control's `name` attribute */\n nameAttr: string | null\n placeholder: string | null\n /** a link's path and query (origin too when it leaves the page's), never its hash */\n href: string | null\n /** a link's `href` attribute as the page wrote it, for the selector */\n hrefAttr: string | null\n rect: { x: number; y: number; w: number; h: number }\n disabled: boolean\n /** something else is on top of its centre (an overlay, a modal's backdrop) */\n covered: boolean\n dialog: ScopeFacts | null\n landmark: ScopeFacts | null\n /** kinds of sensitive text its words held; those words are withheld */\n redacted?: string[]\n}\n\nexport type SelectorBasis =\n | 'testid'\n | 'aria-label'\n | 'href'\n | 'role'\n | 'form'\n | 'id'\n | 'text'\n\nexport interface Candidate {\n selector: string\n basis: SelectorBasis\n}\n\n/** UNIQUE: reaches this element and no other. AMBIGUOUS: this and others. */\nexport type SelectorMatch = 'unique' | 'ambiguous' | 'none'\n\nexport interface LookControl {\n tag: string\n role: string\n /** the accessible name or text, trimmed to 60 characters */\n name: string\n testId: string | null\n href: string | null\n rect: { x: number; y: number; w: number; h: number }\n disabled: boolean\n inDialog: boolean\n covered: boolean\n selector: string | null\n basis: SelectorBasis | null\n match: SelectorMatch\n /** how many elements the proposed selector reaches */\n matches: number\n redacted?: string[]\n}\n\n// ---------------------------------------------------------------------------\n// Pure: quoting, scopes, candidates, the choice, the refusal words\n// ---------------------------------------------------------------------------\n\n/** A double-quoted string, as both CSS and Playwright's engines read one. */\nexport function quote(value: string): string {\n return `\"${value.replace(/\\s+/g, ' ').replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"')}\"`\n}\n\n/** The longest name or text a selector is built from: past it, it is prose. */\nconst NAME_MAX = 80\n\n/**\n * The CSS that reaches a dialog or a landmark: its test id, else its role or\n * tag, narrowed by its `aria-label` when it has one.\n */\nexport function scopeSelector(\n s: ScopeFacts,\n kind: 'dialog' | 'landmark',\n): string {\n if (s.testId) return `[${s.testId.attr}=${quote(s.testId.value)}]`\n let base: string\n if (s.role) base = `[role=${quote(s.role)}]`\n else if (kind === 'dialog' && s.tag === 'dialog') base = 'dialog[open]'\n else if (kind === 'dialog') base = '[aria-modal=\"true\"]'\n else base = s.tag\n return s.label ? `${base}[aria-label=${quote(s.label)}]` : base\n}\n\n/** An id a person wrote, not one a framework minted (`:r3:`, `radix-…`, `mui-12`). */\nexport function stableId(id: string | null): boolean {\n if (!id || !/^[A-Za-z][\\w-]*$/.test(id)) return false\n if (/^(radix|headlessui|mui|react|ember|ext|rc|el|v)-/i.test(id)) return false\n return !/\\d{2,}/.test(id)\n}\n\n/**\n * Every selector worth trying for a control, most stable first: the test\n * id; the `aria-label` (inside the open dialog it sits in); a link's own\n * `href`, query included (two tiles to `?vos=a` and `?vos=b` are two\n * links), which holds where a computed name does not; role + name; a\n * form control's own attributes; a written id; its words inside the dialog\n * or landmark around it. Never a position in the tree: a `:nth-child` chain\n * breaks the first time the page changes.\n */\nexport function selectorCandidates(c: RawControl): Candidate[] {\n const out: Candidate[] = []\n const add = (selector: string, basis: SelectorBasis) => {\n if (!out.some((x) => x.selector === selector)) out.push({ selector, basis })\n }\n const dialog = c.dialog ? scopeSelector(c.dialog, 'dialog') : null\n const landmark = c.landmark ? scopeSelector(c.landmark, 'landmark') : null\n const css = (sel: string) => (dialog ? `${dialog} ${sel}` : sel)\n const chain = (sel: string) => (dialog ? `${dialog} >> ${sel}` : sel)\n\n if (c.testId) {\n const sel = `[${c.testId.attr}=${quote(c.testId.value)}]`\n add(sel, 'testid')\n if (dialog) add(`${dialog} ${sel}`, 'testid')\n }\n if (c.ariaLabel && c.ariaLabel.length <= NAME_MAX)\n add(css(`[aria-label=${quote(c.ariaLabel)}]`), 'aria-label')\n if (\n c.tag === 'a' &&\n c.hrefAttr &&\n c.hrefAttr.length <= 200 &&\n !/^\\s*javascript:/i.test(c.hrefAttr) &&\n c.hrefAttr.trim() !== '#'\n )\n add(css(`a[href=${quote(c.hrefAttr)}]`), 'href')\n if (c.role && c.name && c.name.length <= NAME_MAX) {\n const sel = `role=${c.role}[name=${quote(c.name)}]`\n add(chain(sel), 'role')\n if (!dialog && landmark) add(`${landmark} >> ${sel}`, 'role')\n }\n const form = /^(input|textarea|select)$/.test(c.tag)\n if (form && c.nameAttr)\n add(css(`${c.tag}[name=${quote(c.nameAttr)}]`), 'form')\n if (form && c.placeholder && c.placeholder.length <= NAME_MAX)\n add(css(`${c.tag}[placeholder=${quote(c.placeholder)}]`), 'form')\n if (stableId(c.id)) add(`#${c.id}`, 'id')\n if (!form && c.text && c.text.length <= 60) {\n const sel = `text=${quote(c.text)}`\n if (dialog) add(`${dialog} >> ${sel}`, 'text')\n else if (landmark) add(`${landmark} >> ${sel}`, 'text')\n else add(sel, 'text')\n }\n return out\n}\n\n/**\n * What a candidate reaches, judged for ONE element: the stamps of the\n * elements it matched, in page order. A selector that misses this element\n * is no proposal for it, however few it matches.\n */\nexport function judgeMatch(\n index: number,\n reached: (string | null)[],\n): SelectorMatch | 'miss' {\n if (!reached.includes(String(index))) return 'miss'\n return reached.length === 1 ? 'unique' : 'ambiguous'\n}\n\n/**\n * The proposal: the most stable candidate that reaches this element and no\n * other; failing that, the most stable that reaches it among others (said\n * AMBIGUOUS, with the count); failing that, none.\n */\nexport function chooseProposal(\n index: number,\n candidates: Candidate[],\n reached: (string | null)[][],\n): {\n selector: string | null\n basis: SelectorBasis | null\n match: SelectorMatch\n matches: number\n} {\n let fallback: { c: Candidate; n: number } | null = null\n for (let i = 0; i < candidates.length; i++) {\n const verdict = judgeMatch(index, reached[i] ?? [])\n if (verdict === 'unique')\n return {\n selector: candidates[i].selector,\n basis: candidates[i].basis,\n match: 'unique',\n matches: 1,\n }\n if (verdict === 'ambiguous' && !fallback)\n fallback = { c: candidates[i], n: reached[i].length }\n }\n if (fallback)\n return {\n selector: fallback.c.selector,\n basis: fallback.c.basis,\n match: 'ambiguous',\n matches: fallback.n,\n }\n return { selector: null, basis: null, match: 'none', matches: 0 }\n}\n\n/**\n * Words that spend, send or destroy. A look presses nothing that says one:\n * the screenshot is not worth a generation, an email or a deleted row.\n * Matched as word STEMS at a word's start, so `Deleting`, `Revoked` and\n * `Unsubscribe` are caught with `Delete`, and a near miss like `Payments`\n * is refused too: a look can afford to be wrong in that direction.\n *\n * It cannot know every spend. `Make a video` or `Create` on a primary\n * button may start paid work, and refusing every Make and Create would\n * refuse half of every app, so they pass. A recorded flow fences a step\n * like that with `guard: \"spend\"` in actions.json; this list is a floor\n * under the look, never the fence.\n */\nexport const SPEND_STEMS = [\n 'delet',\n 'remov',\n 'revok',\n 'eras',\n 'discard',\n 'publish',\n 'deploy',\n 'purchas',\n 'subscri',\n 'unsubscri',\n 'pay',\n 'buy',\n 'generat',\n 'submit',\n 'send',\n 'transfer',\n 'upgrad',\n 'confirm',\n 'leav',\n 'destroy',\n] as const\n\n/** Phrases whose words are harmless alone. */\nexport const SPEND_PHRASES = [\n 'move to trash',\n 'empty trash',\n 'cancel subscription',\n 'cancel plan',\n 'close account',\n] as const\n\nconst SPEND = new RegExp(\n `\\\\b(?:${SPEND_PHRASES.map((p) => p.replace(/ /g, '\\\\s+')).join('|')}|(?:${SPEND_STEMS.join('|')})[a-z]*)`,\n 'i',\n)\n\n/** The spend or delete word a control's words hold, or null. */\nexport function spendWord(words: (string | null | undefined)[]): string | null {\n for (const w of words) {\n const m = w ? SPEND.exec(w.replace(/\\s+/g, ' ')) : null\n if (m) return m[0].toLowerCase()\n }\n return null\n}\n\nexport function refusalLine(\n selector: string,\n label: string,\n word: string,\n): string {\n return `refused: --click ${selector} reaches \"${label}\": \"${word}\" spends, sends or destroys, and vos look never presses one. Look at the page before it; a flow that needs the press has it as a step in actions.json, for vos record`\n}\n\n/** A look step, in the order the flags were given. */\nexport type LookStep =\n | { do: 'click'; selector: string }\n | { do: 'type'; selector: string; text: string }\n\n/** Selector engines whose name ends in `=` (`role=…`, `text=…`, `nth=0`). */\nconst ENGINES =\n /^(css|xpath|text|role|id|nth|visible|data-testid|data-test-id|data-test|internal:[a-z-]+)$/\n\n/**\n * `--type <selector>=<text>`: the `=` that splits is the first one outside\n * brackets and quotes that is not an engine's own (`role=`, `text=`, `nth=`\n * at the start of the selector or after a `>>`).\n */\nexport function splitTypeFlag(value: string): {\n selector: string\n text: string\n} {\n let depth = 0\n let inQuote: string | null = null\n let segment = 0\n for (let i = 0; i < value.length; i++) {\n const ch = value[i]\n if (inQuote) {\n if (ch === '\\\\') i++\n else if (ch === inQuote) inQuote = null\n continue\n }\n if (ch === '\"' || ch === \"'\") inQuote = ch\n else if (ch === '[' || ch === '(') depth++\n else if ((ch === ']' || ch === ')') && depth > 0) depth--\n else if (ch === '>' && value[i + 1] === '>') {\n segment = i + 2\n i++\n } else if (ch === '=' && depth === 0) {\n if (ENGINES.test(value.slice(segment, i).trim())) continue\n const selector = value.slice(0, i).trim()\n if (!selector) break\n return { selector, text: value.slice(i + 1) }\n }\n }\n throw new UsageError(\n `--type expects <selector>=<text>, got \"${value}\" (the text follows the first = outside the selector's brackets and quotes)`,\n )\n}\n\n/** The `--click` and `--type` flags in the order they were given. */\nexport function lookSteps(argv: string[]): LookStep[] {\n const steps: LookStep[] = []\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i]\n if (arg === '--') break\n const m = /^--(click|type)(?:=(.*))?$/s.exec(arg)\n if (!m) continue\n let value = m[2]\n if (value === undefined) {\n value = argv[i + 1]\n if (value === undefined || value.startsWith('--'))\n throw new UsageError(`--${m[1]} expects a value`)\n i++\n }\n if (m[1] === 'click') {\n if (!value.trim()) throw new UsageError('--click expects a selector')\n steps.push({ do: 'click', selector: value })\n } else steps.push({ do: 'type', ...splitTypeFlag(value) })\n }\n return steps\n}\n\nexport function parseViewport(value: string | undefined): {\n width: number\n height: number\n} {\n if (!value) return { width: 1280, height: 720 }\n const m = /^(\\d+)x(\\d+)$/i.exec(value)\n if (!m) throw new UsageError('--viewport expects WxH, like 1280x720')\n const width = Number(m[1])\n const height = Number(m[2])\n if (width < 200 || height < 200 || width > 3840 || height > 2160)\n throw new UsageError('--viewport wants a size from 200x200 to 3840x2160')\n return { width, height }\n}\n\n/** The words a control is listed by: its name, else its text, ≤60 chars. */\nexport function displayName(\n c: Pick<RawControl, 'name' | 'text' | 'placeholder'>,\n): string {\n const words = c.name || c.text || c.placeholder || ''\n return words.length > 60 ? `${words.slice(0, 59).trimEnd()}…` : words\n}\n\nexport function controlLine(c: LookControl): string {\n const what = c.role && c.role !== c.tag ? `${c.tag} (${c.role})` : c.tag\n const name = c.redacted?.length\n ? ` [${c.redacted.join(', ')} withheld]`\n : c.name\n ? ` ${JSON.stringify(c.name)}`\n : ''\n const flags = [\n c.inDialog ? 'in dialog' : '',\n c.disabled ? 'disabled' : '',\n c.covered ? 'covered' : '',\n ].filter(Boolean)\n const proposal = c.selector\n ? `${c.selector} ${c.match === 'unique' ? 'UNIQUE' : `AMBIGUOUS (${c.matches})`}`\n : 'no stable selector (use its rect)'\n const r = c.rect\n return ` ${what}${name}${flags.length ? ` [${flags.join(', ')}]` : ''}\\n ${proposal} @ ${r.x},${r.y} ${r.w}×${r.h}`\n}\n\n// ---------------------------------------------------------------------------\n// The page probes (strings: see the header)\n// ---------------------------------------------------------------------------\n\n/** The most controls one look lists; the count of the rest is said. */\nconst CONTROL_LIMIT = 150\n\n/**\n * The visible controls, in document order, each stamped\n * `data-vos-look=\"<index>\"` so a candidate can be judged by WHICH elements\n * it reaches. The stamps are taken off again once the proposals are made.\n */\nexport const LOOK_PROBE = `(() => {\n const { kindsIn } = ${EXPOSURE_MATCHERS_SRC}\n const vw = innerWidth, vh = innerHeight\n const CONTROLS = 'button, a, [role=button], [role=tab], [role=menuitem], [role=menuitemcheckbox], [role=menuitemradio], [role=checkbox], [role=switch], [role=option], [role=radio], [role=link], input, textarea, select, [contenteditable], [data-testid], [data-test-id], [data-test], [data-cy]'\n const TEST_IDS = ['data-testid', 'data-test-id', 'data-test', 'data-cy']\n const DIALOGS = 'dialog[open], [role=dialog], [role=alertdialog], [aria-modal=true]'\n const LANDMARKS = 'nav, header, main, aside, footer, [role=navigation], [role=banner], [role=main], [role=complementary], [role=contentinfo], [role=search]'\n const squash = (s) => (s || '').replace(/\\\\s+/g, ' ').trim()\n const textOf = (el) => squash(typeof el.innerText === 'string' ? el.innerText : el.textContent)\n const shown = (el) => {\n const r = el.getBoundingClientRect()\n if (r.width < 2 || r.height < 2) return null\n if (el.checkVisibility && !el.checkVisibility({ opacityProperty: true, visibilityProperty: true })) return null\n const s = getComputedStyle(el)\n if (s.visibility === 'hidden' || s.display === 'none' || +s.opacity === 0) return null\n return r\n }\n const testIdOf = (el) => {\n for (const attr of TEST_IDS) { const value = el.getAttribute(attr); if (value) return { attr, value } }\n return null\n }\n const implicitRole = (el) => {\n const t = el.tagName\n if (t === 'BUTTON') return 'button'\n if (t === 'A') return el.hasAttribute('href') ? 'link' : ''\n if (t === 'TEXTAREA') return 'textbox'\n if (t === 'SELECT') return el.multiple || el.size > 1 ? 'listbox' : 'combobox'\n if (t === 'INPUT') {\n const type = (el.getAttribute('type') || 'text').toLowerCase()\n if (type === 'checkbox' || type === 'radio') return type\n if (type === 'range') return 'slider'\n if (type === 'number') return 'spinbutton'\n if (/^(button|submit|reset|image)$/.test(type)) return 'button'\n if (/^(text|email|tel|url|search)$/.test(type)) return el.hasAttribute('list') ? 'combobox' : type === 'search' ? 'searchbox' : 'textbox'\n return ''\n }\n if (el.isContentEditable && el.hasAttribute('contenteditable')) return 'textbox'\n return ''\n }\n const roleOf = (el) => (el.getAttribute('role') || '').trim().split(/\\\\s+/)[0] || implicitRole(el)\n const nameOf = (el) => {\n const aria = squash(el.getAttribute('aria-label'))\n if (aria) return aria\n const by = el.getAttribute('aria-labelledby')\n if (by) {\n const t = squash(by.split(/\\\\s+/).map((id) => document.getElementById(id)).filter(Boolean).map(textOf).join(' '))\n if (t) return t\n }\n if (/^(INPUT|TEXTAREA|SELECT)$/.test(el.tagName)) {\n const type = (el.getAttribute('type') || '').toLowerCase()\n if (/^(button|submit|reset)$/.test(type)) return squash(el.value) || (type === 'submit' ? 'Submit' : type === 'reset' ? 'Reset' : '')\n if (type === 'image') return squash(el.getAttribute('alt'))\n const label = el.labels ? squash([...el.labels].map(textOf).join(' ')) : ''\n return label || squash(el.getAttribute('title')) || squash(el.getAttribute('placeholder'))\n }\n const text = textOf(el)\n if (text) return text\n const img = el.querySelector('img[alt]')\n return squash(img && img.getAttribute('alt')) || squash(el.getAttribute('title'))\n }\n const scopeOf = (el) => el ? {\n tag: el.tagName.toLowerCase(),\n role: (el.getAttribute('role') || '').trim().split(/\\\\s+/)[0] || '',\n label: squash(el.getAttribute('aria-label')) || null,\n testId: testIdOf(el),\n } : null\n const hrefOf = (el) => {\n if (el.tagName !== 'A' || !el.hasAttribute('href')) return null\n try { const u = new URL(el.href, location.href); const at = u.pathname + u.search; return u.origin === location.origin ? at : u.origin + at } catch { return null }\n }\n const out = []\n let offscreen = 0, more = 0\n for (const el of document.querySelectorAll(CONTROLS)) {\n if (el.tagName === 'INPUT' && (el.getAttribute('type') || '').toLowerCase() === 'hidden') continue\n if (el.getAttribute('contenteditable') === 'false') continue\n if (el.tagName === 'A' && !el.hasAttribute('href') && !el.getAttribute('role') && !testIdOf(el)) continue\n const r = shown(el)\n if (!r) continue\n if (r.bottom <= 0 || r.right <= 0 || r.top >= vh || r.left >= vw) { offscreen++; continue }\n if (out.length >= ${CONTROL_LIMIT}) { more++; continue }\n const dlg = el.closest(DIALOGS)\n const lm = el.closest(LANDMARKS)\n let name = nameOf(el), text = /^(INPUT|TEXTAREA|SELECT)$/.test(el.tagName) ? '' : textOf(el)\n let ariaLabel = squash(el.getAttribute('aria-label')) || null\n let placeholder = squash(el.getAttribute('placeholder')) || null\n let hrefAttr = el.tagName === 'A' ? el.getAttribute('href') : null, href = hrefOf(el)\n const kinds = [...new Set([...kindsIn(name), ...kindsIn(text), ...kindsIn(ariaLabel || ''), ...kindsIn(placeholder || ''), ...kindsIn(hrefAttr || '')])]\n if (kinds.length) { name = ''; text = ''; ariaLabel = null; placeholder = null; hrefAttr = null; href = null }\n const cx = Math.min(vw - 1, Math.max(0, r.left + r.width / 2)), cy = Math.min(vh - 1, Math.max(0, r.top + r.height / 2))\n const hit = document.elementFromPoint(cx, cy)\n const covered = !!hit && !(hit === el || el.contains(hit) || (el.labels && [...el.labels].some((l) => l.contains(hit))))\n const index = out.length\n out.push({\n index,\n tag: el.tagName.toLowerCase(),\n role: roleOf(el),\n name,\n text,\n ariaLabel,\n testId: testIdOf(el),\n id: el.id || null,\n nameAttr: /^(INPUT|TEXTAREA|SELECT)$/.test(el.tagName) ? el.getAttribute('name') || null : null,\n placeholder,\n href,\n hrefAttr,\n rect: { x: Math.round(r.left), y: Math.round(r.top), w: Math.round(r.width), h: Math.round(r.height) },\n disabled: el.matches(':disabled') || el.getAttribute('aria-disabled') === 'true',\n covered,\n dialog: dlg && shown(dlg) ? scopeOf(dlg) : null,\n landmark: lm ? scopeOf(lm) : null,\n ...(kinds.length ? { redacted: kinds } : {}),\n })\n el.setAttribute('data-vos-look', String(index))\n }\n return { controls: out, offscreen, more }\n})()`\n\nconst UNSTAMP = `(() => { for (const el of document.querySelectorAll('[data-vos-look]')) el.removeAttribute('data-vos-look') })()`\n\n/**\n * Resolves once the DOM has held still for `quietMs`, or at `capMs`. Many\n * apps never reach network idle (a socket, a poll, analytics), so the page's\n * own stillness is the signal.\n */\nexport function settleScript(quietMs: number, capMs: number): string {\n return `new Promise((resolve) => {\n let last = performance.now()\n const start = last\n const mo = new MutationObserver(() => { last = performance.now() })\n mo.observe(document, { subtree: true, childList: true, attributes: true, characterData: true })\n const tick = () => {\n const now = performance.now()\n if (now - last >= ${quietMs} || now - start >= ${capMs}) {\n mo.disconnect()\n resolve(now - last >= ${quietMs})\n } else setTimeout(tick, 50)\n }\n tick()\n})`\n}\n\nconst QUIET_MS = 800\nconst SETTLE_CAP_MS = 6000\nconst STEP_TIMEOUT_MS = 8000\n\n/** Load, then the DOM holding still. A navigation mid-wait starts it again. */\nasync function settle(page: Page): Promise<boolean> {\n const started = Date.now()\n for (let tries = 0; tries < 3; tries++) {\n await page.waitForLoadState('load', { timeout: 15000 }).catch(() => {})\n const left = Math.max(QUIET_MS, SETTLE_CAP_MS - (Date.now() - started))\n try {\n return (await page.evaluate(settleScript(QUIET_MS, left))) as boolean\n } catch {\n // The context went away under the wait: a navigation. Wait for it.\n }\n }\n return false\n}\n\n// ---------------------------------------------------------------------------\n// Looking\n// ---------------------------------------------------------------------------\n\nexport class LookRefusal extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'LookRefusal'\n }\n}\n\nexport interface LookResult {\n url: string\n landed: string\n screenshot: string\n viewport: { width: number; height: number }\n controls: LookControl[]\n /** visible controls outside the viewport (scroll to see them) */\n offscreen: number\n /** controls past the listing's limit */\n more: number\n exposures: Exposure[]\n wall: WallVerdict | null\n /** steps that ran before the look; none when a hard wall stopped them */\n steps: { do: LookStep['do']; selector: string; note?: string }[]\n /** false when the page never held still and was looked at anyway */\n settled: boolean\n}\n\nexport interface LookOpts {\n steps?: LookStep[]\n /** extra ms after the last settle, for a page that animates in */\n waitMs?: number\n /** where look.png goes */\n outDir: string\n log?: (line: string) => void\n}\n\n/** Where a page landed: origin and path (a redirect's query can carry a code). */\nconst place = (u: string): string => {\n try {\n const x = new URL(u)\n return `${x.origin}${x.pathname}`\n } catch {\n return u\n }\n}\n\n/** The URL as it was given, query and all, without a `user:password@`. */\nexport function shownUrl(u: string): string {\n try {\n const x = new URL(u)\n if (!x.username && !x.password) return u\n x.username = ''\n x.password = ''\n return x.href\n } catch {\n return u\n }\n}\n\n/**\n * Open `url` in `page`, judge the wall, run the steps, and look: the\n * screenshot, the exposure scan, the inventory and a proposal per control.\n * A hard wall stops the steps but not the look, since the sign-in page is\n * what the agent must script past next.\n */\nexport async function lookAt(\n page: Page,\n url: string,\n opts: LookOpts,\n): Promise<LookResult> {\n const log = opts.log ?? (() => {})\n log(`goto ${shownUrl(url)}`)\n const response = await page\n .goto(url, { waitUntil: 'load', timeout: 45000 })\n .catch((e: unknown) => {\n // A load that never fired still left a page to look at; a refused\n // connection did not.\n if (e instanceof Error && /net::ERR_/.test(e.message))\n throw new Error(\n `could not open ${shownUrl(url)}: ${(e.message.split('\\n')[0] ?? '').split(url).join(shownUrl(url))}`,\n )\n log(' (the load event never fired; looking anyway)')\n return null\n })\n let settled = await settle(page)\n\n const seen = (await page.evaluate(WALL_PROBE).catch(() => null)) as {\n passwordFields: number\n newPasswordField: boolean\n oneTimeCodeField: boolean\n } | null\n const wall = 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 const ran: LookResult['steps'] = []\n if (!wall || wall.level === 'soft') {\n for (const step of opts.steps ?? []) {\n const all = page.locator(step.selector)\n const target = all.first()\n try {\n await target.waitFor({ state: 'visible', timeout: STEP_TIMEOUT_MS })\n } catch {\n throw new UsageError(\n `--${step.do} ${step.selector}: no visible element matches it after ${STEP_TIMEOUT_MS / 1000} s. Look without the step and take a selector from the list`,\n )\n }\n const count = await all.count()\n const note = count > 1 ? `the first of ${count} matches` : undefined\n if (step.do === 'click') {\n // The words it is known by, read before anything is pressed. An\n // inline arrow with no named helper inside, so no \\`__name\\` rides in.\n const words = await target\n .evaluate((el) =>\n [\n el.getAttribute('aria-label'),\n (el as HTMLElement).innerText || el.textContent,\n (el as HTMLInputElement).value,\n el.getAttribute('title'),\n el.getAttribute('alt'),\n ].map((s) =>\n typeof s === 'string' ? s.replace(/\\s+/g, ' ').trim() : '',\n ),\n )\n .catch(() => [] as string[])\n const word = spendWord(words)\n if (word) {\n const label = words.find((w) => spendWord([w])) ?? word\n throw new LookRefusal(\n refusalLine(step.selector, label.slice(0, 60), word),\n )\n }\n log(`click ${step.selector}${note ? ` (${note})` : ''}`)\n await target.click({ timeout: STEP_TIMEOUT_MS })\n } else {\n // The text is never logged: it may be a password.\n log(\n `type ${step.text.length} chars into ${step.selector}${note ? ` (${note})` : ''}`,\n )\n await target.fill(step.text, { timeout: STEP_TIMEOUT_MS })\n }\n ran.push({\n do: step.do,\n selector: step.selector,\n ...(note ? { note } : {}),\n })\n settled = await settle(page)\n }\n }\n if (opts.waitMs && opts.waitMs > 0) await page.waitForTimeout(opts.waitMs)\n\n await mkdir(opts.outDir, { recursive: true })\n const screenshot = join(opts.outDir, 'look.png')\n await page.screenshot({ path: screenshot })\n\n const scan = (await page.evaluate(EXPOSURE_PROBE).catch(() => null)) as {\n exposures?: Omit<Exposure, 'step' | 'seen'>[]\n } | null\n const step = ran.length ? ran.length - 1 : -1\n const exposures: Exposure[] = (scan?.exposures ?? []).map((e) => ({\n step,\n ...e,\n seen: 1,\n }))\n\n const probe = (await page.evaluate(LOOK_PROBE)) as {\n controls: RawControl[]\n offscreen: number\n more: number\n }\n const controls: LookControl[] = []\n try {\n for (const raw of probe.controls) {\n const candidates = selectorCandidates(raw)\n const reached: (string | null)[][] = []\n for (const c of candidates) {\n const stamps = (await page\n .locator(c.selector)\n .evaluateAll((els) =>\n els.map((el) => el.getAttribute('data-vos-look')),\n )\n .catch(() => [])) as (string | null)[]\n reached.push(stamps)\n // The first unique one is the answer; the rest need not be counted.\n if (judgeMatch(raw.index, stamps) === 'unique') break\n }\n const proposal = chooseProposal(raw.index, candidates, reached)\n controls.push({\n tag: raw.tag,\n role: raw.role,\n name: displayName(raw),\n testId: raw.testId?.value ?? null,\n href: raw.href,\n rect: raw.rect,\n disabled: raw.disabled,\n inDialog: raw.dialog !== null,\n covered: raw.covered,\n ...proposal,\n ...(raw.redacted ? { redacted: raw.redacted } : {}),\n })\n }\n } finally {\n await page.evaluate(UNSTAMP).catch(() => {})\n }\n return {\n url: shownUrl(url),\n landed: place(page.url()),\n screenshot,\n viewport: page.viewportSize() ?? { width: 0, height: 0 },\n controls,\n offscreen: probe.offscreen,\n more: probe.more,\n exposures,\n wall,\n steps: ran,\n settled,\n }\n}\n\n// ---------------------------------------------------------------------------\n// The verb\n// ---------------------------------------------------------------------------\n\nconst USAGE =\n 'vos look <url> [--session <name> | --storage-state <file>] [--viewport WxH] [--headed] [--click <selector>]... [--type <selector>=<text>]... [--wait <ms>] [--out <dir>] [--json]'\n\n/** The human report: the picture, the controls, what the frame exposes. */\nexport function lookReport(r: LookResult): string {\n const inDialog = r.controls.filter((c) => c.inDialog).length\n const head = `Looked at ${r.landed} (${r.viewport.width}×${r.viewport.height}): ${r.screenshot}${r.settled ? '' : '\\n note: the page never held still for 0.8 s; looked at it as it was'}`\n const steps = r.steps.length\n ? `\\n after ${r.steps.map((s) => `${s.do} ${s.selector}${s.note ? ` (${s.note})` : ''}`).join(', then ')}`\n : ''\n const wall = r.wall\n ? `\\n ${r.wall.level === 'hard' ? 'WALL' : 'WARNING'}: ${r.wall.message}${r.wall.level === 'hard' ? '\\n The steps did not run; this is the page in front of the one asked for.' : ''}`\n : ''\n const count = `\\n ${r.controls.length} control${r.controls.length === 1 ? '' : 's'} in view${inDialog ? ` (${inDialog} in an open dialog)` : ''}${r.offscreen ? `, ${r.offscreen} more outside it (scroll, or a taller --viewport)` : ''}${r.more ? `, ${r.more} past the listing's limit` : ''}:`\n const list = r.controls.map(controlLine).join('\\n')\n const exposed = r.exposures.length\n ? `\\n EXPOSED in the frame (${r.exposures.length}):\\n${r.exposures.map((e) => ` - ${exposureLine(e)}`).join('\\n')}\\n ${EXPOSURE_ADVICE}`\n : ''\n const next = `\\n Take a UNIQUE selector into actions.json as it is; an AMBIGUOUS one reaches several and the recorder takes the first. Then rehearse: vos record --actions actions.json --dry-run`\n return `${head}${steps}${wall}${count}\\n${list}${exposed}${next}`\n}\n\nexport async function cmdLook(argv: string[]): Promise<number> {\n const steps = lookSteps(argv)\n const { positionals, flags, multi } = parseArgs(\n argv,\n new Set(['json', 'headed']),\n new Set(['click', 'type', 'header', 'browser-arg']),\n )\n // Read here so the flag check knows they were used; the order is lookSteps'.\n void multi.click\n void multi.type\n const url = positionals[0]\n if (!url) throw new UsageError(USAGE)\n const scheme = urlSchemeProblem(url)\n if (scheme) throw new UsageError(scheme)\n const r = createReporter(flags.json === true)\n const viewport = parseViewport(strFlag(flags, 'viewport'))\n const outDir = resolve(strFlag(flags, 'out') ?? 'look')\n const headed = flags.headed === true\n const waitRaw = strFlag(flags, 'wait')\n const waitMs = waitRaw === undefined ? 0 : Number(waitRaw)\n if (!Number.isFinite(waitMs) || waitMs < 0 || waitMs > 60000)\n throw new UsageError('--wait expects milliseconds, 0 to 60000')\n\n const storageRaw = strFlag(flags, 'storage-state')\n const storageState = storageRaw ? resolve(storageRaw) : undefined\n if (storageState && !existsSync(storageState))\n throw new UsageError(`--storage-state: no such file: ${storageState}`)\n const sessionName = strFlag(flags, 'session')\n if (sessionName) {\n const bad = sessionNameVerdict(sessionName)\n if (bad) throw new UsageError(bad)\n if (storageState)\n throw new UsageError(\n '--session and --storage-state are two doors to one page: a persistent profile cannot take a storage state. Pass one',\n )\n if (!existsSync(sessionDir(sessionName)))\n throw new UsageError(\n `no session \"${sessionName}\". Make one: vos session open <url> --name ${sessionName} (a Chrome window opens; sign in and close it)`,\n )\n }\n let headers: Record<string, string>\n try {\n headers = parseHeaders(multi.header as string[] | undefined)\n } catch (e) {\n throw new UsageError(e instanceof Error ? e.message : String(e))\n }\n const browserArgs = (\n (multi['browser-arg'] as string[] | undefined) ?? []\n ).filter(Boolean)\n\n const inContext = async (ctx: BrowserContext): Promise<LookResult> => {\n if (Object.keys(headers).length)\n await ctx.route('**/*', async (route) => {\n const req = route.request()\n const scoped = headersFor(req.url(), url, headers)\n await route.continue(\n scoped ? { headers: { ...req.headers(), ...scoped } } : undefined,\n )\n })\n const page = ctx.pages()[0] ?? (await ctx.newPage())\n await page.setViewportSize(viewport)\n return lookAt(page, url, { steps, waitMs, outDir, log: r.log })\n }\n\n let result: LookResult\n try {\n if (sessionName) {\n result = await withSession(sessionName, inContext, {\n headless: !headed,\n viewport,\n })\n } else {\n const browser = await launchBrowser(browserArgs, { headless: !headed })\n try {\n const ctx = await browser.newContext({\n viewport,\n deviceScaleFactor: 1,\n ...(storageState ? { storageState } : {}),\n })\n result = await inContext(ctx)\n } finally {\n await browser.close()\n }\n }\n } catch (e) {\n if (e instanceof LookRefusal) {\n r.done({ ok: false, refused: true, error: e.message }, e.message)\n return EXIT_USAGE\n }\n throw e\n }\n\n r.done(\n { ok: !result.wall || result.wall.level === 'soft', ...result },\n lookReport(result),\n )\n return result.wall?.level === 'hard' ? EXIT_WALL : 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 bundledSkillsVersion,\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 'skills-from-catalog',\n 'no-rules',\n 'no-browser',\n])\n\n/** The skills catalog's repository, for the opt-in install through skills.sh. */\nexport const SKILLS_SOURCE = 'vosjs/skills'\n/**\n * The catalog CLI (`npx skills`) the opt-in runs, pinned: `npx skills` with\n * no version runs whatever its owner published last, with this machine's\n * permissions. Moved on purpose, with the bundled skills (`pnpm sync-skills`).\n */\nexport const SKILLS_CLI_VERSION = '1.7.2'\n/** The catalog at ONE tag, the one the bundled copy was synced from. */\nexport function skillsCatalogAt(version: string): string {\n return `https://github.com/${SKILLS_SOURCE}/tree/v${version}`\n}\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 fromCatalog = flags['skills-from-catalog'] === 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. The copy this package ships is the default: it is the\n // catalog at the tag this release was cut from (skills/VERSION), reviewed\n // and tested with it, and it needs no network. `--skills-from-catalog`\n // asks skills.sh for that SAME tag through a pinned catalog CLI, so what\n // lands is what this release was tested with either way; the bundled copy\n // stays the fallback when skills.sh cannot be reached. An unpinned\n // `npx skills add vosjs/skills` ran whatever both repositories held that\n // minute, with this machine's permissions.\n let skillsVia: 'skills.sh' | 'bundled' | 'skipped' = 'skipped'\n let skillNames: string[] = []\n if (!noSkills) {\n const bundled = bundledSkillsDir(import.meta.url.replace('file://', ''))\n const version = bundled ? bundledSkillsVersion(bundled) : null\n const targets = homes.length ? homes : [fallbackSkillsHome(root)]\n const copyBundled = (dir: string) => {\n for (const home of targets) {\n const dest = skillsDirFor(home)\n mkdirSync(dest, { recursive: true })\n for (const name of installedSkills(dir)) {\n cpSync(join(dir, name), join(dest, name), { recursive: true })\n }\n }\n }\n if (fromCatalog) {\n const source = version ? skillsCatalogAt(version) : SKILLS_SOURCE\n const args = [\n `skills@${SKILLS_CLI_VERSION}`,\n 'add',\n 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 tag.\n if (!bundled)\n throw new Error(\n `could not install the skills: npx ${args.join(' ')} failed (${(res.stderr ?? '').trim().split('\\n').at(-1) ?? res.error?.message ?? 'no output'}) and this build carries no bundled copy`,\n )\n copyBundled(bundled)\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 } else {\n if (!bundled)\n throw new Error(\n 'this build carries no bundled skills; run with --skills-from-catalog',\n )\n copyBundled(bundled)\n skillsVia = 'bundled'\n r.log(\n `installed the bundled vos skills${version ? ` (catalog ${version})` : ''} into ${targets.map((t) => skillsDirFor(t)).join(', ')}`,\n )\n }\n skillNames = [\n ...new Set(targets.flatMap((h) => installedSkills(skillsDirFor(h)))),\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 */\n/**\n * The catalog tag the bundled copy was synced from (`skills/VERSION`, written\n * by `scripts/sync-skills.mjs`), or null when the file is absent.\n */\nexport function bundledSkillsVersion(dir: string): string | null {\n try {\n const v = readFileSync(join(dir, 'VERSION'), 'utf8').trim()\n return /^\\d+\\.\\d+\\.\\d+$/.test(v) ? v : null\n } catch {\n return null\n }\n}\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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AA;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;AA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","names":["ms","mkdir","readFile","rm","existsSync","dirname","join","resolve","END_CARD_FROM","docOutputDuration","migrateHostedDoc","ms","off","segs","run","at","ext","EPS","words","layout","overlaps","isObj","mkdir","readFile","rename","rm","writeFile","existsSync","join","resolve","momentsFromDoc","planForDigest","ratedSegments","cameraSpanExtents","spanOutputExtents","range","pct","context","num","readFile","writeFile","existsSync","join","resolve","DIGEST_CROP_MAX","DIGEST_FULL_MAX","DIGEST_VERSION","resolve","join","existsSync","context","f","at","writeFile","readFile","ratedSegments","cameraSpanExtents","spanOutputExtents","ext","out","context","resolve","join","mkdir","rename","rm","existsSync","readFile","momentsFromDoc","planForDigest","parseTimes","writeFile","mkdir","writeFile","join","resolve","existsSync","readFile","docOutputDuration","writeFile","compileVosConfig","lowerToComposition","resolveExportSize","VIDEO_TOKEN","resolveExportSize","lowerToComposition","compileVosConfig","writeFile","hasReplay","momentOutputs","ratedSegments","spanOutputExtent","spanOutputExtent","settle","ext","range","ratedSegments","hasReplay","at","momentOutputs","ext","spanOutputExtent","words","resolveAnchor","kept","off","hex","join","existsSync","readFile","docOutputDuration","resolve","mkdir","range","writeFile","spawn","ms","mkdir","readFile","writeFile","existsSync","join","resolve","ext","findFontFamily","existsSync","readFile","join","cameraModel","docCardLayout","docZoomTrack","layerStart","pinBox","ratedSegments","resolvePins","longestOutputExtent","off","docCardLayout","docZoomTrack","ratedSegments","ext","longestOutputExtent","at","window","layerStart","cameraModel","resolvePins","pinBox","framesTake","join","existsSync","readFile","at","ffmpeg","existsSync","readFile","isAbsolute","join","DESTINATIONS","readFile","DESTINATIONS","isAbsolute","existsSync","join","mkdir","readFile","join","resolve","sep","existsSync","statSync","join","execFile","existsSync","join","resolve","ms","join","existsSync","hostname","resolve","statSync","join","mkdir","sep","readFile","resolve","existsSync","resolve","resolve","existsSync","context","existsSync","readFile","join","migrateMotion","ratedSegments","resolveLayerAnchor","near","resolveAnchor","at","now","join","existsSync","readFile","words","migrateMotion","existsSync","readFileSync","readdirSync","readFile","createInterface","basename","join","lowerToComposition","migrateHostedDoc","existsSync","readFile","writeFile","readFileSync","join","mkdir","join","at","mkdir","join","summary","words","readdirSync","readFileSync","join","existsSync","createInterface","readFile","lowerToComposition","basename","media","migrateHostedDoc","origin","existsSync","mkdir","readFile","createInterface","basename","dirname","join","migrateHostedDoc","basename","extname","relative","existsSync","realpathSync","existsSync","basename","extname","realpathSync","relative","BOOLEAN_FLAGS","join","existsSync","mkdir","migrateHostedDoc","readFile","dirname","basename","title","files","remixOfId","created","watchUrl","studioUrl","landed","createInterface","probe","createHash","readFileSync","basename","manifestName","hostname","words","at","BOOLEAN_FLAGS","basename","readFileSync","createHash","cmdList","existsSync","rmSync","statSync","join","createInterface","BOOLEAN_FLAGS","at","entries","BOOLEAN_FLAGS","existsSync","statSync","createInterface","rmSync","join","readFileSync","writeFileSync","basename","dirname","join","resolve","pathToFileURL","at","BOOLEAN_FLAGS","resolve","readFileSync","pathToFileURL","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","quote","resolve","writeFile","scriptEnvNames","setupEnvNames","scriptEnvNames","setupEnvNames","ms","urlSchemeProblem","writeFile","resolve","quote","relative","resolve","readFile","summary","writeFile","existsSync","mkdir","readFile","stat","basename","join","resolve","BOOLEAN_FLAGS","ext","probe","basename","readFile","text","MULTI_FLAGS","resolve","existsSync","join","mkdir","stat","createRequire","existsSync","mkdir","readFile","stat","writeFile","basename","dirname","extname","join","resolve","ALL_FORMATS","FilePathSource","Input","sceneChanges","window","run","absolute","relative","BOOLEAN_FLAGS","Input","FilePathSource","ALL_FORMATS","stat","createRequire","join","dirname","existsSync","readFile","n","sample","at","resolve","basename","mkdir","writeFile","sceneChanges","extname","existsSync","readdirSync","statSync","copyFile","mkdir","readFile","rm","basename","dirname","isAbsolute","join","relative","resolve","sep","mediaKey","mediaRefId","migrateMotion","projectFromArtifact","ratedSegments","layerStart","resolveAnchor","segmentOutputExtents","totalDuration","existsSync","copyFile","mkdir","readFile","rm","writeFile","tmpdir","basename","isAbsolute","join","relative","resolve","sep","NORMALIZE_MAX_LUFS","NORMALIZE_MIN_LUFS","clipGain","docOutputDuration","findStep","ratedSegments","resolveAnchor","median","sample","readFile","basename","at","ratedSegments","findStep","c","resolveAnchor","resolve","existsSync","relative","sep","isAbsolute","mkdir","join","copyFile","tmpdir","writeFile","rm","BOOLEAN_FLAGS","USAGE","NORMALIZE_MIN_LUFS","NORMALIZE_MAX_LUFS","docOutputDuration","clipGain","docMediaList","findStep","ratedSegments","resolveAnchor","segmentOutputExtents","at","ratedSegments","segmentOutputExtents","findStep","docMediaList","resolveAnchor","docMediaList","mediaKey","mediaKey","overlaps","docMediaList","words","at","createHash","existsSync","readFile","join","isRejected","layerStart","mediaKey","ratedSegments","resolveAnchor","segmentOutputExtents","totalDuration","splitSegmentsAtSkips","round3","createHash","join","existsSync","readFile","at","mediaKey","segmentOutputExtents","totalDuration","ratedSegments","splitSegmentsAtSkips","isRejected","ext","place","resolveAnchor","layerStart","round3","projectFromArtifact","ratedSegments","totalDuration","layerStart","join","migrateMotion","mediaKey","at","segmentOutputExtents","mediaRefId","resolveAnchor","basename","BOOLEAN_FLAGS","USAGE","relative","sep","isAbsolute","resolve","existsSync","statSync","doc","dirname","readdirSync","readFile","rm","mkdir","copyFile","join","resolve","docFreezes","docMediaList","docOutputDuration","cameraSpanExtents","docStillTime","mediaKey","migrateMotion","overlayPlainText","longestOutputExtent","ratedSegments","resolveOverlayAnchors","segmentOutputExtents","spanOutputExtents","totalDuration","r3","ratedSegments","migrateMotion","media","spanOutputExtents","longestOutputExtent","cameraSpanExtents","docMediaList","segmentOutputExtents","mediaKey","docFreezes","resolveOverlayAnchors","overlayPlainText","totalDuration","docOutputDuration","docStillTime","words","resolve","join","mkdtemp","rm","writeFile","tmpdir","basename","join","clipGain","USAGE","mkdtemp","join","tmpdir","basename","writeFile","rm","clipGain","mkdir","existsSync","join","resolve","words","parseViewport","step","mkdir","join","probe","USAGE","resolve","existsSync","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","join","mkdir","urlSchemeProblem","dirname","browser","context","cmdCreate","rm","words","off","at","END_CARD_FROM","range","docOutputDuration","parseTimes","migrateHostedDoc","window","problems","warnings","probe","cmdPush","cmdPull","summary"]}